diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 93c4b27b4..000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: processing -custom: https://processingfoundation.org/ diff --git a/.gitignore b/.gitignore index 0dae35b4d..87f2a6943 100644 --- a/.gitignore +++ b/.gitignore @@ -1,30 +1,2 @@ -mode/processing-core.zip -mode/mode/AndroidMode.jar -mode/mode/gradle-tooling-api* -mode/mode/slf4j* - -mode/mode/percent.jar -mode/mode/recyclerview-v7.jar -mode/mode/support-* -mode/mode/wearable.jar - -mode/libraries/vr/library -mode/libraries/ar/library -mode/tools/SDKUpdater/tool -mode/tools/SDKUpdater/lib - -debug/.gradle -debug/.idea - -**/examples/**/AndroidManifest.xml - -**/*.iml **/.DS_Store -**/build -**/bin -**/dist - -**/local.properties -.gradle -.java-version diff --git a/README.md b/README.md index 743c8422c..749f4baa6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,30 @@ -Processing for Android -====================== +# Processing Android Maven Repository -This is the main repository for Processing for Android. It includes the core library inside the core folder, and the mode itself in the root. See the [wiki](https://github.com/processing/processing-android/wiki) for build instructions. +This is the Maven repository with the processing-core library. +To import into your project add https://raw.github.com/processing/processing-android/repository/ as a maven repository in the ```settings.gradle``` file of the project, under the dependencyResolutionManagement block: +``` +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven { + url "https://raw.github.com/processing/processing-android/repository/" + } + } +} +``` + +Then you should able to incorporate processing-core as a dependency in the build.gradle file: + +``` +dependencies { + implementation 'org.processing.android:processing-core:4.6.0' +} +``` + +More information below about declaring respositories in Gradle: + +https://docs.gradle.org/current/userguide/declaring_repositories.html \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index a957961c0..000000000 --- a/build.gradle +++ /dev/null @@ -1,173 +0,0 @@ -import java.nio.file.Files -import org.zeroturnaround.zip.ZipUtil -import org.apache.commons.io.FileUtils -import java.util.regex.Pattern -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; - -buildscript { - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:4.1.3' - classpath group: 'commons-io', name: 'commons-io', version: '2.8.0' - classpath group: 'org.zeroturnaround', name: 'zt-zip', version: '1.14' - } -} - -plugins { - id 'java' - id('io.github.gradle-nexus.publish-plugin') version '1.1.0' -} - -apply from: "${rootDir}/scripts/publish-root.gradle" - -allprojects { - apply plugin: 'java' - apply plugin: 'java-library' - - Properties versions = new Properties() - versions.load(project.rootProject.file("mode/version.properties").newDataInputStream()) - ext.targetSdkVersion = versions.getProperty("android-platform") - ext.appcompatVersion = versions.getProperty("androidx.appcompat%appcompat") - ext.v4legacyVersion = versions.getProperty("androidx.legacy%legacy-support-v4") - ext.wearVersion = versions.getProperty("com.google.android.support%wearable") - ext.gvrVersion = versions.getProperty("com.google.vr") - ext.garVersion = versions.getProperty("com.google.ar") - ext.processingVersion = versions.getProperty("org.processing") - ext.toolingVersion = versions.getProperty("org.gradle%gradle-tooling-api") - ext.slf4jVersion = versions.getProperty("org.slf4j") - ext.gradlewVersion = versions.getProperty("gradle-wrapper") - ext.toolsLibVersion = versions.getProperty("android-toolslib") - ext.jdtVersion = versions.getProperty("org.eclipse.jdt") - - Properties modeProperties = new Properties() - modeProperties.load(project.rootProject.file("mode/mode.properties").newDataInputStream()) - ext.modeVersion = modeProperties.getProperty("prettyVersion") - - Properties vrProperties = new Properties() - vrProperties.load(project.rootProject.file("mode/libraries/vr/library.properties").newDataInputStream()) - ext.vrLibVersion = vrProperties.getProperty("prettyVersion") - - Properties arProperties = new Properties() - arProperties.load(project.rootProject.file("mode/libraries/ar/library.properties").newDataInputStream()) - ext.arLibVersion = arProperties.getProperty("prettyVersion") - - - def fn = project.rootProject.file("local.properties") - if (!fn.exists()) { - if (System.env["ANDROID_SDK"] != null) { - def syspath = System.env["ANDROID_SDK"] - def parts = syspath.split(Pattern.quote(File.separator)) - def path = String.join("/", parts) - fn.withWriterAppend { w -> - w << "sdk.dir=${path}\n" - } - } else { - throw new GradleException( - "The file local.properties does not exist, and there is no ANDROID_SDK environmental variable defined in the system.\n" + - "Define ANDROID_SDK so it points to the location of the Android SDK, or create the local.properties file manually\n" + - "and add the following line to it:\n" + - "sdk.dir=") - } - } - - - Properties localProperties = new Properties() - localProperties.load(project.rootProject.file("local.properties").newDataInputStream()) - def sdkDir = localProperties.getProperty("sdk.dir") - ext.androidPlatformPath = "${sdkDir}/platforms/android-${targetSdkVersion}" - ext.coreZipPath = "${rootDir}/mode/processing-core.zip" - - repositories { - google() - mavenCentral() - maven { url "https://maven.google.com" } - maven { url "https://jitpack.io" } - maven { url 'https://repo.gradle.org/gradle/libs-releases' } - flatDir dirs: androidPlatformPath - flatDir dirs: "${rootDir}/core/build/libs" - } - - compileJava { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - - // Uncomment this option when building with Java 11+ - // https://github.com/processing/processing-android/issues/625 - // options.release = 8 - } -} - -clean.doFirst { - delete "dist" -} - -task dist { - dependsOn subprojects.build - doLast { - def root = "${buildDir}/zip/AndroidMode" - - // Copy assets to build dir - FileUtils.copyDirectory(file("mode/templates"), file("${root}/templates")) - FileUtils.copyDirectory(file("mode/examples"), file("${root}/examples")) - FileUtils.copyDirectory(file("mode/icons"), file("${root}/icons")) - FileUtils.copyDirectory(file("mode/theme"), file("${root}/theme")) - FileUtils.copyDirectory(file("mode/mode"), file("${root}/mode")) - delete "${root}/mode/core.jar" - delete "${root}/mode/pde.jar" - delete "${root}/mode/JavaMode.jar" - // delete "${root}/mode/jdi.jar" - // delete "${root}/mode/jdimodel.jar" - - Files.copy(file("mode/processing-core.zip").toPath(), - file("${root}/processing-core.zip").toPath(), REPLACE_EXISTING) - - Files.copy(file("mode/keywords.txt").toPath(), - file("${root}/keywords.txt").toPath(), REPLACE_EXISTING) - - Files.copy(file("mode/version.properties").toPath(), - file("${root}/version.properties").toPath(), REPLACE_EXISTING) - - Files.copy(file("mode/mode.properties").toPath(), - file("${root}/mode.properties").toPath(), REPLACE_EXISTING) - - FileUtils.copyDirectory(file("mode/languages"), - file("${root}/languages")) - - FileUtils.copyDirectory(file("mode/resources"), - file("${root}/resources")) - - FileUtils.copyDirectory(file("mode/tools/SDKUpdater/tool"), - file("${root}/tools/SDKUpdater/tool")) - FileUtils.copyDirectory(file("mode/tools/SDKUpdater/lib"), - file("${root}/tools/SDKUpdater/lib")) - FileUtils.copyDirectory(file("mode/tools/SDKUpdater/src"), - file("${root}/tools/SDKUpdater/src")) - - FileUtils.copyDirectory(file("mode/libraries/vr/examples"), - file("${root}/libraries/vr/examples")) - FileUtils.copyDirectory(file("mode/libraries/vr/library"), - file("${root}/libraries/vr/library")) - FileUtils.copyDirectory(file("mode/libraries/vr/src"), - file("${root}/libraries/vr/src")) - Files.copy(file("mode/libraries/vr/library.properties").toPath(), - file("${root}/libraries/vr/library.properties").toPath(), REPLACE_EXISTING) - - FileUtils.copyDirectory(file("mode/libraries/ar/examples"), - file("${root}/libraries/ar/examples")) - FileUtils.copyDirectory(file("mode/libraries/ar/library"), - file("${root}/libraries/ar/library")) - FileUtils.copyDirectory(file("mode/libraries/ar/src"), - file("${root}/libraries/ar/src")) - Files.copy(file("mode/libraries/ar/library.properties").toPath(), - file("${root}/libraries/ar/library.properties").toPath(), REPLACE_EXISTING) - - File distFolder = file("dist") - distFolder.mkdirs() - ZipUtil.pack(file("${buildDir}/zip"), new File("dist/AndroidMode.zip")) - Files.copy(file("mode/mode.properties").toPath(), - file("dist/AndroidMode.txt").toPath(), REPLACE_EXISTING) - } -} diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle deleted file mode 100644 index a95a3cb68..000000000 --- a/buildSrc/build.gradle +++ /dev/null @@ -1,15 +0,0 @@ -// apply plugin: 'groovy' -plugins { - id 'groovy' -} - -repositories { - google() - mavenCentral() -} - -dependencies { - implementation gradleApi() - implementation localGroovy() - implementation 'com.android.tools.build:gradle:4.1.1' -} \ No newline at end of file diff --git a/buildSrc/src/main/groovy/processing/android/ImportAar.groovy b/buildSrc/src/main/groovy/processing/android/ImportAar.groovy deleted file mode 100644 index 8880ff931..000000000 --- a/buildSrc/src/main/groovy/processing/android/ImportAar.groovy +++ /dev/null @@ -1,125 +0,0 @@ -package processing.android - -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.plugins.PluginManager -import org.gradle.api.plugins.ExtensionContainer -import org.gradle.plugins.ide.idea.IdeaPlugin -import org.gradle.plugins.ide.idea.model.IdeaModel -import org.gradle.plugins.ide.idea.model.IdeaModule -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.transform.ArtifactTransform - -import static org.gradle.api.internal.artifacts.ArtifactAttributes.ARTIFACT_FORMAT -import com.android.build.gradle.internal.dependency.AarTransform -import com.android.build.gradle.internal.dependency.ExtractAarTransform -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import com.android.builder.aar.AarExtractor -import com.google.common.collect.ImmutableList -import java.util.regex.Pattern -import static com.android.SdkConstants.FD_JARS -import static com.android.SdkConstants.FN_CLASSES_JAR - -import java.io.File -import java.nio.file.Files -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING - -/** - * Build Gradle plgin needed to use aar files as dependencies in a pure java library project. - * Adapted from the following plugin by nekocode - * https://github.com/nekocode/Gradle-Import-Aar - * Ported to Groovy, and made specific to the needs of the Android mode build process (i.e.: this plugin - * is not meant to be used with other projects). - */ -class ImportAar implements Plugin { - - final String CONFIG_NAME_POSTFIX = "Aar" - - void apply(Project project) { - def aar = AndroidArtifacts.TYPE_AAR - def jar = AndroidArtifacts.TYPE_JAR - def exp = AndroidArtifacts.TYPE_EXPLODED_AAR - - // // Create aar configurations - Collection allConfigs = project.getConfigurations().toList() - for (Configuration config: allConfigs) { - Configuration aarConfig = project.configurations.maybeCreate(config.name + CONFIG_NAME_POSTFIX) - - // Add extracted jars to original configuration after project evaluating - aarConfig.getAttributes().attribute(ARTIFACT_FORMAT, jar) - project.afterEvaluate { - for (File jarFile: aarConfig) { - // print "================================================> FILE " - // println jarFile - // println jarFile.getName() - // for (String s: project.sourceSets.main.compileClasspath) { - // println s - // } - // project.getDependencies().add(config.name, project.files(jarFile)) - - // Add jar file to classpath - project.sourceSets.main.compileClasspath += project.files(jarFile) - - File libraryFolder = new File(System.getProperty("user.dir"), "build/libs") - libraryFolder.mkdirs() - - // Strip version number when copying - String name = jarFile.getName() - int p = name.lastIndexOf("-") - String libName = name.substring(0, p) + ".jar" - File libraryJar = new File(libraryFolder, libName) - Files.copy(jarFile.toPath(), libraryJar.toPath(), REPLACE_EXISTING) - } - - } - - // Tell Idea about our aar configuration - PluginManager pluginManager = project.getPluginManager() - pluginManager.apply(IdeaPlugin.class) - ExtensionContainer extensions = project.getExtensions() - // IdeaModel model = extensions.getByType​(IdeaModel.class) - IdeaModel model = extensions.getByName("idea") - IdeaModule module = model.getModule() - module.scopes.PROVIDED.plus += [aarConfig] - } - - // Register aar transform - project.dependencies { - registerTransform { - from.attribute(ARTIFACT_FORMAT, aar) - to.attribute(ARTIFACT_FORMAT, jar) - artifactTransform(AarJarArtifactTransform.class) - } - } - } - - static class AarJarArtifactTransform extends ArtifactTransform { - @Override - List transform(File file) { - // println "Transforming---------------------------------" - // println outputDirectory - // println file - File explodedDir = new File(getOutputDirectory(), "exploded") - // println explodedDir - - AarExtractor aarExtractor = new AarExtractor() - aarExtractor.extract(file, explodedDir) - File classesJar = new File(new File(explodedDir, FD_JARS), FN_CLASSES_JAR) - // println classesJar - - // String[] names = file.getPath().split(Pattern.quote(File.separator)) - // print "NAMES " - // println names - // print "NAME " - // println file.getName() - // String aarName = names[names.length - 4].replace(".aar", "") - String aarName = file.getName().replace(".aar", "") - // print "AAR NAME " - // println aarName - File renamedJar = new File(getOutputDirectory(), aarName + ".jar") - renamedJar << classesJar.bytes - - return ImmutableList.of(renamedJar) - } - } -} \ No newline at end of file diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/aar.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/aar.properties deleted file mode 100644 index 42d81af01..000000000 --- a/buildSrc/src/main/resources/META-INF/gradle-plugins/aar.properties +++ /dev/null @@ -1 +0,0 @@ -implementation-class=processing.android.ImportAar \ No newline at end of file diff --git a/core/build.gradle b/core/build.gradle deleted file mode 100644 index 4aadfdd44..000000000 --- a/core/build.gradle +++ /dev/null @@ -1,96 +0,0 @@ -import org.apache.tools.ant.Project -import java.nio.file.Files -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; - -plugins { - id 'aar' -} - -dependencies { - implementation name: "android" - implementationAar "androidx.legacy:legacy-support-v4:${v4legacyVersion}" - implementationAar "com.google.android.support:wearable:${wearVersion}" -} - -sourceSets { - main { - java { - srcDirs = ["src/"] - } - resources { - srcDirs = ["src/"] - } - } -} - -task sourceJar(type: Jar, dependsOn: classes) { - duplicatesStrategy = DuplicatesStrategy.INCLUDE - classifier = "sources" - from sourceSets.main.allSource -} - -// Does not work because of Processing-specific tags in source code, such as @webref -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = "javadoc" - from javadoc.destinationDir -} - -artifacts { -// archives javadocJar - archives sourceJar -} - -jar.doLast { task -> - ant.checksum file: task.archivePath -} - -clean.doFirst { - delete "dist" - delete "${coreZipPath}" -} - -compileJava.doFirst { - String[] deps = ["wearable.jar"] - for (String fn : deps) { - Files.copy(file("${rootDir}/build/libs/" + fn).toPath(), - file("${rootDir}/mode/mode/" + fn).toPath(), REPLACE_EXISTING) - } -} - -build.doLast { - - // Need to check the existance of the files before using as the files - // will get generated only if Task :core:jar is not being skipped - // Task :core:jar will be skipped if source files are unchanged or jar task is UP-TO-DATE - - if (file("${buildDir}/libs/core.jar").exists()) { - // Copying core jar as zip inside the mode folder - Files.copy(file("${buildDir}/libs/core.jar").toPath(), - file("${coreZipPath}").toPath(), REPLACE_EXISTING) - } - // Renaming artifacts for maven publishing - if (file("${buildDir}/libs/core.jar").exists()) { - Files.move(file("${buildDir}/libs/core.jar").toPath(), - file("$buildDir/libs/processing-core-${modeVersion}.jar").toPath(), REPLACE_EXISTING); - } - if (file("${buildDir}/libs/core-sources.jar").exists()) { - Files.move(file("${buildDir}/libs/core-sources.jar").toPath(), - file("$buildDir/libs/processing-core-${modeVersion}-sources.jar").toPath(), REPLACE_EXISTING); - } - if (file("${buildDir}/libs/core.jar.MD5").exists()) { - Files.move(file("${buildDir}/libs/core.jar.MD5").toPath(), - file("$buildDir/libs/processing-core-${modeVersion}.jar.md5").toPath(), REPLACE_EXISTING); - } -} - -ext { - libName = 'processing-core' - libVersion = modeVersion - libJar = "${buildDir}/libs/${libName}-${libVersion}.jar" - libSrc = "${buildDir}/libs/${libName}-${libVersion}-sources.jar" - libMd5 = "${buildDir}/libs/${libName}-${libVersion}-sources.jar.md5" - libDependencies = [[name: 'legacy-support-v4', group: 'androidx.legacy', version: v4legacyVersion], - [name: 'wearable', group: 'com.google.android.support', version: wearVersion], - [name: 'android']] -} -apply from: "${rootProject.projectDir}/scripts/publish-module.gradle" diff --git a/core/src/assets/shaders/ColorFrag.glsl b/core/src/assets/shaders/ColorFrag.glsl deleted file mode 100644 index 5f86d92b4..000000000 --- a/core/src/assets/shaders/ColorFrag.glsl +++ /dev/null @@ -1,32 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -varying vec4 vertColor; - -void main() { - gl_FragColor = vertColor; -} \ No newline at end of file diff --git a/core/src/assets/shaders/ColorVert.glsl b/core/src/assets/shaders/ColorVert.glsl deleted file mode 100644 index 65fd55716..000000000 --- a/core/src/assets/shaders/ColorVert.glsl +++ /dev/null @@ -1,34 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -uniform mat4 transformMatrix; - -attribute vec4 position; -attribute vec4 color; - -varying vec4 vertColor; - -void main() { - gl_Position = transformMatrix * position; - - vertColor = color; -} \ No newline at end of file diff --git a/core/src/assets/shaders/LightFrag.glsl b/core/src/assets/shaders/LightFrag.glsl deleted file mode 100644 index 6b60d4039..000000000 --- a/core/src/assets/shaders/LightFrag.glsl +++ /dev/null @@ -1,33 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -varying vec4 vertColor; -varying vec4 backVertColor; - -void main() { - gl_FragColor = gl_FrontFacing ? vertColor : backVertColor; -} \ No newline at end of file diff --git a/core/src/assets/shaders/LightVert.glsl b/core/src/assets/shaders/LightVert.glsl deleted file mode 100644 index adc4bf9ad..000000000 --- a/core/src/assets/shaders/LightVert.glsl +++ /dev/null @@ -1,151 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -uniform mat4 modelviewMatrix; -uniform mat4 transformMatrix; -uniform mat3 normalMatrix; - -uniform int lightCount; -uniform vec4 lightPosition[8]; -uniform vec3 lightNormal[8]; -uniform vec3 lightAmbient[8]; -uniform vec3 lightDiffuse[8]; -uniform vec3 lightSpecular[8]; -uniform vec3 lightFalloff[8]; -uniform vec2 lightSpot[8]; - -attribute vec4 position; -attribute vec4 color; -attribute vec3 normal; - -attribute vec4 ambient; -attribute vec4 specular; -attribute vec4 emissive; -attribute float shininess; - -varying vec4 vertColor; -varying vec4 backVertColor; - -const float zero_float = 0.0; -const float one_float = 1.0; -const vec3 zero_vec3 = vec3(0); - -float falloffFactor(vec3 lightPos, vec3 vertPos, vec3 coeff) { - vec3 lpv = lightPos - vertPos; - vec3 dist = vec3(one_float); - dist.z = dot(lpv, lpv); - dist.y = sqrt(dist.z); - return one_float / dot(dist, coeff); -} - -float spotFactor(vec3 lightPos, vec3 vertPos, vec3 lightNorm, float minCos, float spotExp) { - vec3 lpv = normalize(lightPos - vertPos); - vec3 nln = -one_float * lightNorm; - float spotCos = dot(nln, lpv); - return spotCos <= minCos ? zero_float : pow(spotCos, spotExp); -} - -float lambertFactor(vec3 lightDir, vec3 vecNormal) { - return max(zero_float, dot(lightDir, vecNormal)); -} - -float blinnPhongFactor(vec3 lightDir, vec3 vertPos, vec3 vecNormal, float shine) { - vec3 np = normalize(vertPos); - vec3 ldp = normalize(lightDir - np); - return pow(max(zero_float, dot(ldp, vecNormal)), shine); -} - -void main() { - // Vertex in clip coordinates - gl_Position = transformMatrix * position; - - // Vertex in eye coordinates - vec3 ecVertex = vec3(modelviewMatrix * position); - - // Normal vector in eye coordinates - vec3 ecNormal = normalize(normalMatrix * normal); - vec3 ecNormalInv = ecNormal * -one_float; - - // Light calculations - vec3 totalAmbient = vec3(0, 0, 0); - - vec3 totalFrontDiffuse = vec3(0, 0, 0); - vec3 totalFrontSpecular = vec3(0, 0, 0); - - vec3 totalBackDiffuse = vec3(0, 0, 0); - vec3 totalBackSpecular = vec3(0, 0, 0); - - for (int i = 0; i < 8; i++) { - if (lightCount == i) break; - - vec3 lightPos = lightPosition[i].xyz; - bool isDir = lightPosition[i].w < one_float; - float spotCos = lightSpot[i].x; - float spotExp = lightSpot[i].y; - - vec3 lightDir; - float falloff; - float spotf; - - if (isDir) { - falloff = one_float; - lightDir = -one_float * lightNormal[i]; - } else { - falloff = falloffFactor(lightPos, ecVertex, lightFalloff[i]); - lightDir = normalize(lightPos - ecVertex); - } - - spotf = spotExp > zero_float ? spotFactor(lightPos, ecVertex, lightNormal[i], - spotCos, spotExp) - : one_float; - - if (any(greaterThan(lightAmbient[i], zero_vec3))) { - totalAmbient += lightAmbient[i] * falloff; - } - - if (any(greaterThan(lightDiffuse[i], zero_vec3))) { - totalFrontDiffuse += lightDiffuse[i] * falloff * spotf * - lambertFactor(lightDir, ecNormal); - totalBackDiffuse += lightDiffuse[i] * falloff * spotf * - lambertFactor(lightDir, ecNormalInv); - } - - if (any(greaterThan(lightSpecular[i], zero_vec3))) { - totalFrontSpecular += lightSpecular[i] * falloff * spotf * - blinnPhongFactor(lightDir, ecVertex, ecNormal, shininess); - totalBackSpecular += lightSpecular[i] * falloff * spotf * - blinnPhongFactor(lightDir, ecVertex, ecNormalInv, shininess); - } - } - - // Calculating final color as result of all lights (plus emissive term). - // Transparency is determined exclusively by the diffuse component. - vertColor = vec4(totalAmbient, 0) * ambient + - vec4(totalFrontDiffuse, 1) * color + - vec4(totalFrontSpecular, 0) * specular + - vec4(emissive.rgb, 0); - - backVertColor = vec4(totalAmbient, 0) * ambient + - vec4(totalBackDiffuse, 1) * color + - vec4(totalBackSpecular, 0) * specular + - vec4(emissive.rgb, 0); -} \ No newline at end of file diff --git a/core/src/assets/shaders/LineFrag.glsl b/core/src/assets/shaders/LineFrag.glsl deleted file mode 100644 index 9046e17e9..000000000 --- a/core/src/assets/shaders/LineFrag.glsl +++ /dev/null @@ -1,32 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -varying vec4 vertColor; - -void main() { - gl_FragColor = vertColor; -} \ No newline at end of file diff --git a/core/src/assets/shaders/LineVert.glsl b/core/src/assets/shaders/LineVert.glsl deleted file mode 100644 index 15e7bf951..000000000 --- a/core/src/assets/shaders/LineVert.glsl +++ /dev/null @@ -1,99 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-17 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -#define PROCESSING_LINE_SHADER - -uniform mat4 modelviewMatrix; -uniform mat4 projectionMatrix; - -uniform vec4 viewport; -uniform int perspective; -uniform vec3 scale; - -attribute vec4 position; -attribute vec4 color; -attribute vec4 direction; - -varying vec4 vertColor; - -void main() { - vec4 posp = modelviewMatrix * position; - vec4 posq = modelviewMatrix * (position + vec4(direction.xyz, 0)); - - // Moving vertices slightly toward the camera - // to avoid depth-fighting with the fill triangles. - // Discussed here: - // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=252848 - posp.xyz = posp.xyz * scale; - posq.xyz = posq.xyz * scale; - - vec4 p = projectionMatrix * posp; - vec4 q = projectionMatrix * posq; - - // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height]) - // screen_p = (p.xy/p.w + <1,1>) * 0.5 * viewport.zw - - // prevent division by W by transforming the tangent formula (div by 0 causes - // the line to disappear, see https://github.com/processing/processing/issues/5183) - // t = screen_q - screen_p - // - // tangent is normalized and we don't care which direction it points to (+-) - // t = +- normalize( screen_q - screen_p ) - // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*viewport.zw - (p.xy/p.w+<1,1>)*0.5*viewport.zw ) - // - // extract common factor, <1,1> - <1,1> cancels out - // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * viewport.zw ) - // - // convert to common divisor - // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * viewport.zw ) - // - // remove the common scalar divisor/factor, not needed due to normalize and +- - // (keep viewport - can't remove because it has different components for x and y - // and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181) - // t = +- normalize( (q.xy*p.w - p.xy*q.w) * viewport.zw ) - - vec2 tangent = (q.xy*p.w - p.xy*q.w) * viewport.zw; - // don't normalize zero vector (line join triangles and lines perpendicular to the eye plane) - tangent = length(tangent) == 0.0 ? vec2(0.0, 0.0) : normalize(tangent); - - // flip tangent to normal (it's already normalized) - vec2 normal = vec2(-tangent.y, tangent.x); - - float thickness = direction.w; - vec2 offset = normal * thickness; - - // Perspective --- - // convert from world to clip by multiplying with projection scaling factor - // to get the right thickness (see https://github.com/processing/processing/issues/5182) - // invert Y, projections in Processing invert Y - vec2 perspScale = (projectionMatrix * vec4(1, -1, 0, 0)).xy; - - // No Perspective --- - // multiply by W (to cancel out division by W later in the pipeline) and - // convert from screen to clip (derived from clip to screen above) - vec2 noPerspScale = p.w / (0.5 * viewport.zw); - - gl_Position.xy = p.xy + offset.xy * mix(noPerspScale, perspScale, float(perspective > 0)); - gl_Position.zw = p.zw; - - vertColor = color; -} diff --git a/core/src/assets/shaders/MaskFrag.glsl b/core/src/assets/shaders/MaskFrag.glsl deleted file mode 100644 index 3d7e7dbf1..000000000 --- a/core/src/assets/shaders/MaskFrag.glsl +++ /dev/null @@ -1,40 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -#define PROCESSING_TEXTURE_SHADER - -uniform sampler2D texture; -uniform sampler2D mask; - -varying vec4 vertTexCoord; - -void main() { - vec3 texColor = texture2D(texture, vertTexCoord.st).rgb; - vec3 maskColor = texture2D(mask, vertTexCoord.st).rgb; - float luminance = dot(maskColor, vec3(0.2126, 0.7152, 0.0722)); - gl_FragColor = vec4(texColor, luminance); -} \ No newline at end of file diff --git a/core/src/assets/shaders/P2DFrag.glsl b/core/src/assets/shaders/P2DFrag.glsl deleted file mode 100644 index ce3a3fb27..000000000 --- a/core/src/assets/shaders/P2DFrag.glsl +++ /dev/null @@ -1,14 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -varying vec4 vertColor; -varying vec2 vertTexCoord; -varying float vertTexFactor; - -uniform sampler2D texture; - -void main() { - gl_FragColor = mix(vertColor, vertColor * texture2D(texture, vertTexCoord), vertTexFactor); -} diff --git a/core/src/assets/shaders/P2DVert.glsl b/core/src/assets/shaders/P2DVert.glsl deleted file mode 100644 index 4e9a1f7e1..000000000 --- a/core/src/assets/shaders/P2DVert.glsl +++ /dev/null @@ -1,23 +0,0 @@ -attribute vec3 position; -attribute vec4 color; -attribute vec2 texCoord; -attribute float texFactor; - -varying vec4 vertColor; -varying vec2 vertTexCoord; -varying float vertTexFactor; - -uniform mat4 transform; -uniform vec2 texScale; - -void main() { - gl_Position = transform * vec4(position, 1); - - //we avoid affecting the Z component by the transform - //because it would mess up our depth testing - gl_Position.z = position.z; - - vertColor = color.zyxw; - vertTexCoord = texCoord * texScale; - vertTexFactor = texFactor; -} diff --git a/core/src/assets/shaders/PointFrag.glsl b/core/src/assets/shaders/PointFrag.glsl deleted file mode 100644 index 5f86d92b4..000000000 --- a/core/src/assets/shaders/PointFrag.glsl +++ /dev/null @@ -1,32 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -varying vec4 vertColor; - -void main() { - gl_FragColor = vertColor; -} \ No newline at end of file diff --git a/core/src/assets/shaders/PointVert.glsl b/core/src/assets/shaders/PointVert.glsl deleted file mode 100644 index 292674615..000000000 --- a/core/src/assets/shaders/PointVert.glsl +++ /dev/null @@ -1,56 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-17 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -uniform mat4 projectionMatrix; -uniform mat4 modelviewMatrix; - -uniform vec4 viewport; -uniform int perspective; - -attribute vec4 position; -attribute vec4 color; -attribute vec2 offset; - -varying vec4 vertColor; - -void main() { - vec4 pos = modelviewMatrix * position; - vec4 clip = projectionMatrix * pos; - - // Perspective --- - // convert from world to clip by multiplying with projection scaling factor - // invert Y, projections in Processing invert Y - vec2 perspScale = (projectionMatrix * vec4(1, -1, 0, 0)).xy; - - // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height]) - // screen_p = (p.xy/p.w + <1,1>) * 0.5 * viewport.zw - - // No Perspective --- - // multiply by W (to cancel out division by W later in the pipeline) and - // convert from screen to clip (derived from clip to screen above) - vec2 noPerspScale = clip.w / (0.5 * viewport.zw); - - gl_Position.xy = clip.xy + offset.xy * mix(noPerspScale, perspScale, float(perspective > 0)); - gl_Position.zw = clip.zw; - - vertColor = color; -} \ No newline at end of file diff --git a/core/src/assets/shaders/TexFrag.glsl b/core/src/assets/shaders/TexFrag.glsl deleted file mode 100644 index c8e183d49..000000000 --- a/core/src/assets/shaders/TexFrag.glsl +++ /dev/null @@ -1,37 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D texture; - -uniform vec2 texOffset; - -varying vec4 vertColor; -varying vec4 vertTexCoord; - -void main() { - gl_FragColor = texture2D(texture, vertTexCoord.st) * vertColor; -} \ No newline at end of file diff --git a/core/src/assets/shaders/TexLightFrag.glsl b/core/src/assets/shaders/TexLightFrag.glsl deleted file mode 100644 index fd9b61576..000000000 --- a/core/src/assets/shaders/TexLightFrag.glsl +++ /dev/null @@ -1,37 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D texture; - -uniform vec2 texOffset; - -varying vec4 vertColor; -varying vec4 backVertColor; -varying vec4 vertTexCoord; - -void main() { - gl_FragColor = texture2D(texture, vertTexCoord.st) * (gl_FrontFacing ? vertColor : backVertColor); -} \ No newline at end of file diff --git a/core/src/assets/shaders/TexLightVert.glsl b/core/src/assets/shaders/TexLightVert.glsl deleted file mode 100644 index 57551edce..000000000 --- a/core/src/assets/shaders/TexLightVert.glsl +++ /dev/null @@ -1,157 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -uniform mat4 modelviewMatrix; -uniform mat4 transformMatrix; -uniform mat3 normalMatrix; -uniform mat4 texMatrix; - -uniform int lightCount; -uniform vec4 lightPosition[8]; -uniform vec3 lightNormal[8]; -uniform vec3 lightAmbient[8]; -uniform vec3 lightDiffuse[8]; -uniform vec3 lightSpecular[8]; -uniform vec3 lightFalloff[8]; -uniform vec2 lightSpot[8]; - -attribute vec4 position; -attribute vec4 color; -attribute vec3 normal; -attribute vec2 texCoord; - -attribute vec4 ambient; -attribute vec4 specular; -attribute vec4 emissive; -attribute float shininess; - -varying vec4 vertColor; -varying vec4 backVertColor; -varying vec4 vertTexCoord; - -const float zero_float = 0.0; -const float one_float = 1.0; -const vec3 zero_vec3 = vec3(0); - -float falloffFactor(vec3 lightPos, vec3 vertPos, vec3 coeff) { - vec3 lpv = lightPos - vertPos; - vec3 dist = vec3(one_float); - dist.z = dot(lpv, lpv); - dist.y = sqrt(dist.z); - return one_float / dot(dist, coeff); -} - -float spotFactor(vec3 lightPos, vec3 vertPos, vec3 lightNorm, float minCos, float spotExp) { - vec3 lpv = normalize(lightPos - vertPos); - vec3 nln = -one_float * lightNorm; - float spotCos = dot(nln, lpv); - return spotCos <= minCos ? zero_float : pow(spotCos, spotExp); -} - -float lambertFactor(vec3 lightDir, vec3 vecNormal) { - return max(zero_float, dot(lightDir, vecNormal)); -} - -float blinnPhongFactor(vec3 lightDir, vec3 vertPos, vec3 vecNormal, float shine) { - vec3 np = normalize(vertPos); - vec3 ldp = normalize(lightDir - np); - return pow(max(zero_float, dot(ldp, vecNormal)), shine); -} - -void main() { - // Vertex in clip coordinates - gl_Position = transformMatrix * position; - - // Vertex in eye coordinates - vec3 ecVertex = vec3(modelviewMatrix * position); - - // Normal vector in eye coordinates - vec3 ecNormal = normalize(normalMatrix * normal); - vec3 ecNormalInv = ecNormal * -one_float; - - // Light calculations - vec3 totalAmbient = vec3(0, 0, 0); - - vec3 totalFrontDiffuse = vec3(0, 0, 0); - vec3 totalFrontSpecular = vec3(0, 0, 0); - - vec3 totalBackDiffuse = vec3(0, 0, 0); - vec3 totalBackSpecular = vec3(0, 0, 0); - - for (int i = 0; i < 8; i++) { - if (lightCount == i) break; - - vec3 lightPos = lightPosition[i].xyz; - bool isDir = lightPosition[i].w < one_float; - float spotCos = lightSpot[i].x; - float spotExp = lightSpot[i].y; - - vec3 lightDir; - float falloff; - float spotf; - - if (isDir) { - falloff = one_float; - lightDir = -one_float * lightNormal[i]; - } else { - falloff = falloffFactor(lightPos, ecVertex, lightFalloff[i]); - lightDir = normalize(lightPos - ecVertex); - } - - spotf = spotExp > zero_float ? spotFactor(lightPos, ecVertex, lightNormal[i], - spotCos, spotExp) - : one_float; - - if (any(greaterThan(lightAmbient[i], zero_vec3))) { - totalAmbient += lightAmbient[i] * falloff; - } - - if (any(greaterThan(lightDiffuse[i], zero_vec3))) { - totalFrontDiffuse += lightDiffuse[i] * falloff * spotf * - lambertFactor(lightDir, ecNormal); - totalBackDiffuse += lightDiffuse[i] * falloff * spotf * - lambertFactor(lightDir, ecNormalInv); - } - - if (any(greaterThan(lightSpecular[i], zero_vec3))) { - totalFrontSpecular += lightSpecular[i] * falloff * spotf * - blinnPhongFactor(lightDir, ecVertex, ecNormal, shininess); - totalBackSpecular += lightSpecular[i] * falloff * spotf * - blinnPhongFactor(lightDir, ecVertex, ecNormalInv, shininess); - } - } - - // Calculating final color as result of all lights (plus emissive term). - // Transparency is determined exclusively by the diffuse component. - vertColor = vec4(totalAmbient, 0) * ambient + - vec4(totalFrontDiffuse, 1) * color + - vec4(totalFrontSpecular, 0) * specular + - vec4(emissive.rgb, 0); - - backVertColor = vec4(totalAmbient, 0) * ambient + - vec4(totalBackDiffuse, 1) * color + - vec4(totalBackSpecular, 0) * specular + - vec4(emissive.rgb, 0); - - // Calculating texture coordinates, with r and q set both to one - vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); -} diff --git a/core/src/assets/shaders/TexVert.glsl b/core/src/assets/shaders/TexVert.glsl deleted file mode 100644 index c07dc30d7..000000000 --- a/core/src/assets/shaders/TexVert.glsl +++ /dev/null @@ -1,38 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -uniform mat4 transformMatrix; -uniform mat4 texMatrix; - -attribute vec4 position; -attribute vec4 color; -attribute vec2 texCoord; - -varying vec4 vertColor; -varying vec4 vertTexCoord; - -void main() { - gl_Position = transformMatrix * position; - - vertColor = color; - vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); -} \ No newline at end of file diff --git a/core/src/processing/a2d/PGraphicsAndroid2D.java b/core/src/processing/a2d/PGraphicsAndroid2D.java deleted file mode 100644 index b82ced644..000000000 --- a/core/src/processing/a2d/PGraphicsAndroid2D.java +++ /dev/null @@ -1,2390 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2005-12 Ben Fry and Casey Reas - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.a2d; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.app.ActivityManager; -import android.app.ActivityManager.MemoryInfo; -import android.content.Context; -import android.graphics.*; -import android.graphics.Bitmap.Config; -import android.graphics.Paint.Style; -import android.os.Build; -import android.os.Environment; -import android.view.SurfaceHolder; -import static android.os.Environment.isExternalStorageRemovable; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.nio.ByteBuffer; -import java.io.InputStream; -import java.util.zip.GZIPInputStream; - -import processing.android.AppComponent; -import processing.core.PApplet; -import processing.core.PFont; -import processing.core.PGraphics; -import processing.core.PImage; -import processing.core.PMatrix; -import processing.core.PMatrix2D; -import processing.core.PMatrix3D; -import processing.core.PShape; -import processing.core.PShapeSVG; -import processing.core.PSurface; -import processing.data.XML; - -/** - * Subclass for PGraphics that implements the graphics API using - * the Android 2D graphics model. Similar tradeoffs to JAVA2D mode - * with the original (desktop) version of Processing. - */ -public class PGraphicsAndroid2D extends PGraphics { - static public boolean useBitmap = true; - - public Canvas canvas; // like g2 for PGraphicsJava2D - - /// break the shape at the next vertex (next vertex() call is a moveto()) - boolean breakShape; - - /// coordinates for internal curve calculation - float[] curveCoordX; - float[] curveCoordY; - float[] curveDrawX; - float[] curveDrawY; - - static protected final int MATRIX_STACK_DEPTH = 32; - protected float[][] transformStack; - public PMatrix2D transform; - protected Matrix transformMatrix; - protected float[] transformArray; - int transformCount; - -// Line2D.Float line = new Line2D.Float(); -// Ellipse2D.Float ellipse = new Ellipse2D.Float(); -// Rectangle2D.Float rect = new Rectangle2D.Float(); -// Arc2D.Float arc = new Arc2D.Float(); - /** - * The temporary path object that does most of the drawing work. If there are - * any points in the path (meaning that moveto has been called), then - * vertexCount will be 1 (or more). In the POLYGON case, vertexCount is only - * set to 1 after the first point is drawn (to indicate a moveto) and not - * incremented after, since the variable isn't used for POLYGON paths. - */ - Path path; - - /** Temporary rectangle object. */ - RectF rect; - -// protected Color tintColorObject; - -// protected Color fillColorObject; -// public boolean fillGradient; -// public Paint fillGradientObject; - -// protected Color strokeColorObject; -// public boolean strokeGradient; -// public Paint strokeGradientObject; - - Paint fillPaint; - Paint strokePaint; - Paint tintPaint; - - - /** - * Marks when changes to the size have occurred, so that the backing bitmap - * can be recreated. - */ - protected boolean sized; - - /** - * Marks when some changes have occurred, to the surface view. - */ - protected boolean changed; - - ////////////////////////////////////////////////////////////// - - // INTERNAL - - - public PGraphicsAndroid2D() { - transformStack = new float[MATRIX_STACK_DEPTH][6]; - transform = new PMatrix2D(); - transformMatrix = new Matrix(); - transformArray = new float[9]; - - path = new Path(); - rect = new RectF(); - - fillPaint = new Paint(); - fillPaint.setStyle(Style.FILL); - strokePaint = new Paint(); - strokePaint.setStyle(Style.STROKE); - tintPaint = new Paint(Paint.FILTER_BITMAP_FLAG); - } - - - //public void setParent(PApplet parent) - - - //public void setPrimary(boolean primary) - - - //public void setPath(String path) - - @Override - public void surfaceChanged() { - changed = true; - } - - - @Override - public void setSize(int iwidth, int iheight) { - sized = iwidth != width || iheight != height; - super.setSize(iwidth, iheight); - } - - - @Override - public void dispose() { - if (bitmap != null) bitmap.recycle(); - } - - - @Override - public PSurface createSurface(AppComponent component, SurfaceHolder holder, boolean reset) { // ignore - return new PSurfaceAndroid2D(this, component, holder); - } - - - ////////////////////////////////////////////////////////////// - - // FRAME - - @SuppressLint("NewApi") - protected Canvas checkCanvas() { - if ((canvas == null || sized) && (useBitmap || !primaryGraphics)) { - if (bitmap == null || bitmap.getWidth() * bitmap.getHeight() < width * height || - Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { - if (bitmap != null) bitmap.recycle(); - bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); - } else { - // reconfigure is only available in API level 19 or higher. - bitmap.reconfigure(width, height, bitmap.getConfig()); - } - canvas = new Canvas(bitmap); - sized = false; - } - restoreSurface(); - return canvas; - } - - - @Override - public void beginDraw() { - canvas = checkCanvas(); - - checkSettings(); - - resetMatrix(); // reset model matrix - - // reset vertices - vertexCount = 0; - } - - - @Override - public void endDraw() { - if (bitmap == null) return; - - if (primaryGraphics) { - SurfaceHolder holder = parent.getSurface().getSurfaceHolder(); - if (holder != null) { - Canvas screen = null; - try { - screen = holder.lockCanvas(null); - if (screen != null) { - screen.drawBitmap(bitmap, new Matrix(), null); - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (screen != null) { - try { - holder.unlockCanvasAndPost(screen); - } catch (IllegalStateException ex) { - } catch (IllegalArgumentException ex) { - } - } - } - } - } else { - // TODO this is probably overkill for most tasks... - loadPixels(); - } - - // Marking as modified, and then calling updatePixels() in - // the super class, which just sets the mx1, my1, mx2, my2 - // coordinates of the modified area. This avoids doing the - // full copy of the pixels to the surface in this.updatePixels(). - setModified(); - super.updatePixels(); - } - - - - ////////////////////////////////////////////////////////////// - - // SETTINGS - - - //protected void checkSettings() - - - //protected void defaultSettings() - - - //protected void reapplySettings() - - - - ////////////////////////////////////////////////////////////// - - // HINT - - - //public void hint(int which) - - - - ////////////////////////////////////////////////////////////// - - // SHAPES - - - //public void beginShape(int kind) - - - @Override - public void beginShape(int kind) { - //super.beginShape(kind); - shape = kind; - vertexCount = 0; - curveVertexCount = 0; - - // reset the path, because when mixing curves and straight - // lines, vertexCount will be set back to zero, so vertexCount == 1 - // is no longer a good indicator of whether the shape is new. - // this way, just check to see if gpath is null, and if it isn't - // then just use it to continue the shape. - //path = null; -// path.reset(); -// pathReset = true; - } - - - //public boolean edge(boolean e) - - - //public void normal(float nx, float ny, float nz) { - - - //public void textureMode(int mode) - - - @Override - public void texture(PImage image) { - showMethodWarning("texture"); - } - - - @Override - public void vertex(float x, float y) { - // POLYGON and POINTS are broken out for efficiency - if (shape == POLYGON) { -// if (path == null) { -// path = new Path(); -// path.moveTo(x, y); - //if (pathReset) { - if (vertexCount == 0) { - path.reset(); - path.moveTo(x, y); - vertexCount = 1; -// pathReset = false; - } else if (breakShape) { - path.moveTo(x, y); - breakShape = false; - } else { - path.lineTo(x, y); - } - - // this is way too slow, otherwise what's the point of using beginShape() -// } else if (shape == POINTS) { -// point(x, y); - - } else { - curveVertexCount = 0; - - if (vertexCount == vertices.length) { - float temp[][] = new float[vertexCount<<1][VERTEX_FIELD_COUNT]; - System.arraycopy(vertices, 0, temp, 0, vertexCount); - vertices = temp; - } - // not everyone needs this, but just easier to store rather - // than adding another moving part to the code... - vertices[vertexCount][X] = x; - vertices[vertexCount][Y] = y; - vertexCount++; - - switch (shape) { - - case POINTS: - // store them for later - break; - - case LINES: - if ((vertexCount % 2) == 0) { - line(vertices[vertexCount-2][X], - vertices[vertexCount-2][Y], x, y); - vertexCount = 0; - } - break; - - case LINE_STRIP: - case LINE_LOOP: - if (vertexCount >= 2) { - line(vertices[vertexCount-2][X], - vertices[vertexCount-2][Y], x, y); - } - break; - - case TRIANGLES: - if ((vertexCount % 3) == 0) { - triangle(vertices[vertexCount - 3][X], - vertices[vertexCount - 3][Y], - vertices[vertexCount - 2][X], - vertices[vertexCount - 2][Y], - x, y); - vertexCount = 0; - } - break; - - case TRIANGLE_STRIP: - if (vertexCount >= 3) { - triangle(vertices[vertexCount - 2][X], - vertices[vertexCount - 2][Y], - x, //vertices[vertexCount - 1][X], - y, //vertices[vertexCount - 1][Y], - vertices[vertexCount - 3][X], - vertices[vertexCount - 3][Y]); - } - break; - - case TRIANGLE_FAN: - if (vertexCount >= 3) { - triangle(vertices[0][X], - vertices[0][Y], - vertices[vertexCount - 2][X], - vertices[vertexCount - 2][Y], - x, y); - } - break; - - case QUAD: - case QUADS: - if ((vertexCount % 4) == 0) { - quad(vertices[vertexCount - 4][X], - vertices[vertexCount - 4][Y], - vertices[vertexCount - 3][X], - vertices[vertexCount - 3][Y], - vertices[vertexCount - 2][X], - vertices[vertexCount - 2][Y], - x, y); - vertexCount = 0; - } - break; - - case QUAD_STRIP: - // 0---2---4 - // | | | - // 1---3---5 - if ((vertexCount >= 4) && ((vertexCount % 2) == 0)) { - quad(vertices[vertexCount - 4][X], - vertices[vertexCount - 4][Y], - vertices[vertexCount - 2][X], - vertices[vertexCount - 2][Y], - x, y, - vertices[vertexCount - 3][X], - vertices[vertexCount - 3][Y]); - } - break; - } - } - } - - - @Override - public void vertex(float x, float y, float z) { - showDepthWarningXYZ("vertex"); - } - - - @Override - public void vertex(float[] v) { - vertex(v[X], v[Y]); - } - - - @Override - public void vertex(float x, float y, float u, float v) { - showVariationWarning("vertex(x, y, u, v)"); - } - - - @Override - public void vertex(float x, float y, float z, float u, float v) { - showDepthWarningXYZ("vertex"); - } - - - @Override - public void breakShape() { - breakShape = true; - } - - - @Override - public void endShape(int mode) { - if (shape == POINTS && stroke && vertexCount > 0) { - Matrix m = getMatrixImp(); - if (strokeWeight == 1 && m.isIdentity()) { - if (screenPoint == null) { - screenPoint = new float[2]; - } - for (int i = 0; i < vertexCount; i++) { - screenPoint[0] = vertices[i][X]; - screenPoint[1] = vertices[i][Y]; - m.mapPoints(screenPoint); - set(PApplet.round(screenPoint[0]), PApplet.round(screenPoint[1]), strokeColor); - float x = vertices[i][X]; - float y = vertices[i][Y]; - set(PApplet.round(screenX(x, y)), PApplet.round(screenY(x, y)), strokeColor); - } - } else { - float sw = strokeWeight / 2; - // temporarily use the stroke Paint as a fill - strokePaint.setStyle(Style.FILL); - for (int i = 0; i < vertexCount; i++) { - float x = vertices[i][X]; - float y = vertices[i][Y]; - rect.set(x - sw, y - sw, x + sw, y + sw); - canvas.drawOval(rect, strokePaint); - } - strokePaint.setStyle(Style.STROKE); - } - } else if (shape == POLYGON) { - if (!path.isEmpty()) { - if (mode == CLOSE) { - path.close(); - } - drawPath(); - } - } else if (shape == LINE_LOOP && vertexCount >= 2) { - line(vertices[vertexCount-1][X], - vertices[vertexCount-1][Y], - vertices[0][X], - vertices[0][Y]); - } - shape = 0; - } - - - ////////////////////////////////////////////////////////////// - - // CLIPPING - - - @Override - protected void clipImpl(float x1, float y1, float x2, float y2) { - canvas.clipRect(x1, y1, x2, y2); - } - - - @Override - public void noClip() { - canvas.clipRect(0, 0, width, height, Region.Op.REPLACE); - } - - - ////////////////////////////////////////////////////////////// - - // BEZIER VERTICES - - - @Override - public void bezierVertex(float x1, float y1, - float x2, float y2, - float x3, float y3) { - // will check to make sure that vertexCount > 0 - bezierVertexCheck(); - path.cubicTo(x1, y1, x2, y2, x3, y3); - } - - - @Override - public void bezierVertex(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - showDepthWarningXYZ("bezierVertex"); - } - - - - ////////////////////////////////////////////////////////////// - - // QUADRATIC BEZIER VERTICES - - - @Override - public void quadraticVertex(float ctrlX, float ctrlY, - float endX, float endY) { - bezierVertexCheck(); - path.quadTo(ctrlX, ctrlY, endX, endY); - } - - - @Override - public void quadraticVertex(float x2, float y2, float z2, - float x4, float y4, float z4) { - showDepthWarningXYZ("quadVertex"); - } - - - - ////////////////////////////////////////////////////////////// - - // CURVE VERTICES - - - @Override - protected void curveVertexCheck() { - super.curveVertexCheck(); - - if (curveCoordX == null) { - curveCoordX = new float[4]; - curveCoordY = new float[4]; - curveDrawX = new float[4]; - curveDrawY = new float[4]; - } - } - - - @Override - protected void curveVertexSegment(float x1, float y1, - float x2, float y2, - float x3, float y3, - float x4, float y4) { - curveCoordX[0] = x1; - curveCoordY[0] = y1; - - curveCoordX[1] = x2; - curveCoordY[1] = y2; - - curveCoordX[2] = x3; - curveCoordY[2] = y3; - - curveCoordX[3] = x4; - curveCoordY[3] = y4; - - curveToBezierMatrix.mult(curveCoordX, curveDrawX); - curveToBezierMatrix.mult(curveCoordY, curveDrawY); - - // since the paths are continuous, - // only the first point needs the actual moveto - if (vertexCount == 0) { -// if (path == null) { -// path = new Path(); - path.moveTo(curveDrawX[0], curveDrawY[0]); - vertexCount = 1; - } - - path.cubicTo(curveDrawX[1], curveDrawY[1], - curveDrawX[2], curveDrawY[2], - curveDrawX[3], curveDrawY[3]); - } - - - @Override - public void curveVertex(float x, float y, float z) { - showDepthWarningXYZ("curveVertex"); - } - - - - ////////////////////////////////////////////////////////////// - - // RENDERER - - - //public void flush() - - - - ////////////////////////////////////////////////////////////// - - // POINT, LINE, TRIANGLE, QUAD - - - @Override - public void point(float x, float y) { - // this is a slow function to call on its own anyway. - // most people will use set(). - beginShape(POINTS); - vertex(x, y); - endShape(); -// if (strokeWeight > 1) { -// //line(x, y, x + EPSILON, y + EPSILON); -// float sw = strokeWeight / 2; -// rect.set(x - sw, y - sw, x + sw, y + sw); -// strokePaint.setStyle(Style.FILL); -// canvas.drawOval(rect, strokePaint); -// strokePaint.setStyle(Style.STROKE); -// } else { -// // TODO this isn't accurate, really we need to -// set(PApplet.round(screenX(x, y)), PApplet.round(screenY(x, y)), strokeColor); -// } - } - - - @Override - public void line(float x1, float y1, float x2, float y2) { -// line.setLine(x1, y1, x2, y2); -// strokeShape(line); - if (stroke) { - canvas.drawLine(x1, y1, x2, y2, strokePaint); - } - } - - - @Override - public void triangle(float x1, float y1, float x2, float y2, - float x3, float y3) { - path.reset(); - path.moveTo(x1, y1); - path.lineTo(x2, y2); - path.lineTo(x3, y3); - path.close(); - drawPath(); - } - - - @Override - public void quad(float x1, float y1, float x2, float y2, - float x3, float y3, float x4, float y4) { - path.reset(); - path.moveTo(x1, y1); - path.lineTo(x2, y2); - path.lineTo(x3, y3); - path.lineTo(x4, y4); - path.close(); - drawPath(); - } - - - - ////////////////////////////////////////////////////////////// - - // RECT - - - //public void rectMode(int mode) - - - //public void rect(float a, float b, float c, float d) - - - @Override - protected void rectImpl(float x1, float y1, float x2, float y2) { -// rect.setFrame(x1, y1, x2-x1, y2-y1); -// drawShape(rect); - //rect.set(x1, y1, x2, y2); - if (fill) { - canvas.drawRect(x1, y1, x2, y2, fillPaint); - } - if (stroke) { - canvas.drawRect(x1, y1, x2, y2, strokePaint); - } - } - - - - ////////////////////////////////////////////////////////////// - - // ELLIPSE - - - //public void ellipseMode(int mode) - - - //public void ellipse(float a, float b, float c, float d) - - - @Override - protected void ellipseImpl(float x, float y, float w, float h) { -// ellipse.setFrame(x, y, w, h); -// drawShape(ellipse); - rect.set(x, y, x+w, y+h); - if (fill) { - canvas.drawOval(rect, fillPaint); - } - if (stroke) { - canvas.drawOval(rect, strokePaint); - } - } - - - - ////////////////////////////////////////////////////////////// - - // ARC - - - //public void arc(float a, float b, float c, float d, - // float start, float stop) - - - @Override - protected void arcImpl(float x, float y, float w, float h, - float start, float stop, int mode) { - // 0 to 90 in java would be 0 to -90 for p5 renderer - // but that won't work, so -90 to 0? - - if (stop - start >= TWO_PI) { - ellipseImpl(x, y, w, h); - - } else { - // Android agrees with us, so don't set start/stop negative like Java 2D - start = start * RAD_TO_DEG; - stop = stop * RAD_TO_DEG; - - // ok to do this because already checked for NaN - while (start < 0) { - start += 360; - stop += 360; - } - if (start > stop) { - float temp = start; - start = stop; - stop = temp; - } - - float sweep = stop - start; - rect.set(x, y, x+w, y+h); - - if (mode == 0) { - if (fill) { - canvas.drawArc(rect, start, sweep, true, fillPaint); - } - if (stroke) { - canvas.drawArc(rect, start, sweep, false, strokePaint); - } - } else if (mode == OPEN) { - if (fill) { - // Android does not support stroke and fill with different color - // after drawing the arc,draw the arc with Paint.Style.Stroke style - // again - canvas.drawArc(rect, start, sweep, false, fillPaint); - canvas.drawArc(rect, start, sweep, false, strokePaint); - } - if (stroke) { - canvas.drawArc(rect, start, sweep, false, strokePaint); - } - } else if (mode == CHORD) { - // Draw an extra line between start angle point and end point to - // achieve the chord - float endAngle = start + sweep; - float halfRectWidth = rect.width()/2; - float halfRectHeight = rect.height()/2; - float centerX = rect.centerX(); - float centerY = rect.centerY(); - - float startX = (float) (halfRectWidth* Math.cos(Math.toRadians(start))) + centerX; - float startY = (float) (halfRectHeight * Math.sin(Math.toRadians(start))) + centerY; - float endX = (float) (halfRectWidth * Math.cos(Math.toRadians(endAngle))) + centerX; - float endY = (float) (halfRectHeight * Math.sin(Math.toRadians(endAngle))) + centerY; - - if (fill) { - // draw the fill arc - canvas.drawArc(rect,start,sweep,false,fillPaint); - // draw the arc round border - canvas.drawArc(rect,start,sweep,false,strokePaint); - // draw the straight border - canvas.drawLine(startX,startY,endX,endY,strokePaint); - } - if (stroke) { - // draw the arc - canvas.drawArc(rect,start,sweep,false,strokePaint); - // draw the straight border - canvas.drawLine(startX,startY,endX,endY,strokePaint); - } - } else if (mode == PIE) { - if (fill) { - canvas.drawArc(rect, start, sweep, true, fillPaint); - } - if (stroke) { - canvas.drawArc(rect, start, sweep, true, strokePaint); - } - } - } - } - - - - ////////////////////////////////////////////////////////////// - - // JAVA2D SHAPE/PATH HANDLING - - -// protected void fillShape(Shape s) { -// if (fillGradient) { -// canvas.setPaint(fillGradientObject); -// canvas.fill(s); -// } else if (fill) { -// canvas.setColor(fillColorObject); -// canvas.fill(s); -// } -// } - - -// protected void strokeShape(Shape s) { -// if (strokeGradient) { -// canvas.setPaint(strokeGradientObject); -// canvas.draw(s); -// } else if (stroke) { -// canvas.setColor(strokeColorObject); -// canvas.draw(s); -// } -// } - - -// protected void drawShape(Shape s) { -// if (fillGradient) { -// canvas.setPaint(fillGradientObject); -// canvas.fill(s); -// } else if (fill) { -// canvas.setColor(fillColorObject); -// canvas.fill(s); -// } -// if (strokeGradient) { -// canvas.setPaint(strokeGradientObject); -// canvas.draw(s); -// } else if (stroke) { -// canvas.setColor(strokeColorObject); -// canvas.draw(s); -// } -// } - - - protected void drawPath() { - if (fill) { - canvas.drawPath(path, fillPaint); - } - if (stroke) { - canvas.drawPath(path, strokePaint); - } - } - - - - ////////////////////////////////////////////////////////////// - - // BOX - - - //public void box(float size) - - - @Override - public void box(float w, float h, float d) { - showMethodWarning("box"); - } - - - - ////////////////////////////////////////////////////////////// - - // SPHERE - - - //public void sphereDetail(int res) - - - //public void sphereDetail(int ures, int vres) - - - @Override - public void sphere(float r) { - showMethodWarning("sphere"); - } - - - - ////////////////////////////////////////////////////////////// - - // BEZIER - - - //public float bezierPoint(float a, float b, float c, float d, float t) - - - //public float bezierTangent(float a, float b, float c, float d, float t) - - - //protected void bezierInitCheck() - - - //protected void bezierInit() - - - /** Ignored (not needed) in Java 2D. */ - @Override - public void bezierDetail(int detail) { - } - - - //public void bezier(float x1, float y1, - // float x2, float y2, - // float x3, float y3, - // float x4, float y4) - - - //public void bezier(float x1, float y1, float z1, - // float x2, float y2, float z2, - // float x3, float y3, float z3, - // float x4, float y4, float z4) - - - - ////////////////////////////////////////////////////////////// - - // CURVE - - - //public float curvePoint(float a, float b, float c, float d, float t) - - - //public float curveTangent(float a, float b, float c, float d, float t) - - - /** Ignored (not needed) in Java 2D. */ - @Override - public void curveDetail(int detail) { - } - - //public void curveTightness(float tightness) - - - //protected void curveInitCheck() - - - //protected void curveInit() - - - //public void curve(float x1, float y1, - // float x2, float y2, - // float x3, float y3, - // float x4, float y4) - - - //public void curve(float x1, float y1, float z1, - // float x2, float y2, float z2, - // float x3, float y3, float z3, - // float x4, float y4, float z4) - - - - ////////////////////////////////////////////////////////////// - - // SMOOTH - - - @Override - public void smooth(int quality) { // ignore - super.smooth(quality); -// smooth = true; -// canvas.setRenderingHint(RenderingHints.KEY_ANTIALIASING, -// RenderingHints.VALUE_ANTIALIAS_ON); -// canvas.setRenderingHint(RenderingHints.KEY_INTERPOLATION, -// RenderingHints.VALUE_INTERPOLATION_BICUBIC); - strokePaint.setAntiAlias(true); - fillPaint.setAntiAlias(true); - } - - - @Override - public void noSmooth() { - super.noSmooth(); -// smooth = false; -// canvas.setRenderingHint(RenderingHints.KEY_ANTIALIASING, -// RenderingHints.VALUE_ANTIALIAS_OFF); -// canvas.setRenderingHint(RenderingHints.KEY_INTERPOLATION, -// RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); - strokePaint.setAntiAlias(false); - fillPaint.setAntiAlias(false); - } - - - - ////////////////////////////////////////////////////////////// - - // IMAGE - - - //public void imageMode(int mode) - - - //public void image(PImage image, float x, float y) - - - //public void image(PImage image, float x, float y, float c, float d) - - - //public void image(PImage image, - // float a, float b, float c, float d, - // int u1, int v1, int u2, int v2) - - - Rect imageImplSrcRect; - RectF imageImplDstRect; - //android.widget.ImageView imv; - - /** - * Handle renderer-specific image drawing. - */ - @Override - protected void imageImpl(PImage src, - float x1, float y1, float x2, float y2, - int u1, int v1, int u2, int v2) { - Bitmap bitmap = (Bitmap)src.getNative(); - - if (bitmap != null && bitmap.isRecycled()) { - // Let's make sure it is recreated - bitmap = null; - } - - if (bitmap == null && src.format == ALPHA) { - // create an alpha bitmap for this feller - bitmap = Bitmap.createBitmap(src.width, src.height, Config.ARGB_8888); - int[] px = new int[src.pixels.length]; - for (int i = 0; i < px.length; i++) { - px[i] = src.pixels[i] << 24 | 0xFFFFFF; - } - bitmap.setPixels(px, 0, src.width, 0, 0, src.width, src.height); - modified = false; - src.setNative(bitmap); - } - - // this version's not usable because it doesn't allow you to set output w/h -// if (src.bitmap == null) { // format is ARGB or RGB -// int offset = v1*src.width + u1; -// canvas.drawBitmap(src.pixels, offset, src.width, -// x1, y1, u2-u1, v2-v1, -// src.format == ARGB, tint ? tintPaint : null); -// } else { - - if (bitmap == null || - src.width != bitmap.getWidth() || - src.height != bitmap.getHeight()) { - if (bitmap != null) bitmap.recycle(); - bitmap = Bitmap.createBitmap(src.width, src.height, Config.ARGB_8888); - modified = true; - src.setNative(bitmap); - } - - if (src.isModified()) { - //System.out.println("mutable, recycled = " + who.bitmap.isMutable() + ", " + who.bitmap.isRecycled()); - if (!bitmap.isMutable()) { - bitmap.recycle(); - bitmap = Bitmap.createBitmap(src.width, src.height, Config.ARGB_8888); - src.setNative(bitmap); - } - if (src.pixels != null) { - bitmap.setPixels(src.pixels, 0, src.width, 0, 0, src.width, src.height); - } - src.setModified(false); - } - - if (imageImplSrcRect == null) { - imageImplSrcRect = new Rect(u1, v1, u2, v2); - imageImplDstRect = new RectF(x1, y1, x2, y2); - } else { - imageImplSrcRect.set(u1, v1, u2, v2); - imageImplDstRect.set(x1, y1, x2, y2); - } - //canvas.drawBitmap(who.bitmap, imageImplSrcRect, imageImplDstRect, tint ? tintPaint : null); - //System.out.println(PApplet.hex(fillPaint.getColor())); - //canvas.drawBitmap(who.bitmap, imageImplSrcRect, imageImplDstRect, fillPaint); - // System.out.println("drawing lower, tint = " + tint + " " + PApplet.hex(tintPaint.getColor())); - canvas.drawBitmap(bitmap, imageImplSrcRect, imageImplDstRect, tint ? tintPaint : null); - - // If the OS things the memory is low, then recycles bitmaps automatically... - // but I don't think it is particularly efficient, as the bitmaps are stored - // in native heap for Android 10 and older. - MemoryInfo mi = new MemoryInfo(); - Activity activity = parent.getSurface().getActivity(); - if (activity == null) return; - ActivityManager activityManager = (ActivityManager) activity.getSystemService(android.content.Context.ACTIVITY_SERVICE); - activityManager.getMemoryInfo(mi); - if (mi.lowMemory) { - bitmap.recycle(); - src.setNative(null); - } - } - - - - ////////////////////////////////////////////////////////////// - - // SHAPE - - - //public void shapeMode(int mode) - - - //public void shape(PShape shape) - - - //public void shape(PShape shape, float x, float y) - - - //public void shape(PShape shape, float x, float y, float c, float d) - - - ////////////////////////////////////////////////////////////// - - // SHAPE I/O - - - @Override - public PShape loadShape(String filename) { - String extension = PApplet.getExtension(filename); - - PShapeSVG svg = null; - - if (extension.equals("svg")) { - svg = new PShapeSVG(parent.loadXML(filename)); - - } else if (extension.equals("svgz")) { - try { - InputStream input = new GZIPInputStream(parent.createInput(filename)); - XML xml = new XML(input); - svg = new PShapeSVG(xml); - } catch (Exception e) { - e.printStackTrace(); - } - } else { - PGraphics.showWarning("Unsupported format"); - } - - return svg; - } - - - ////////////////////////////////////////////////////////////// - - // TEXT ATTRIBTUES - - - //public void textAlign(int align) - - - //public void textAlign(int alignX, int alignY) - - -// public float textAscent() { -// if (textFont == null) { -// defaultFontOrDeath("textAscent"); -// } -//// Font font = textFont.getFont(); -// Typeface font = textFont.getTypeface(); -// if (font == null) { -// return super.textAscent(); -// } -// return fillPaint.ascent(); -// } - - -// public float textDescent() { -// if (textFont == null) { -// defaultFontOrDeath("textDescent"); -// } -//// Font font = textFont.getFont(); -// Typeface font = textFont.getTypeface(); -// if (font == null) { -// return super.textDescent(); -// } -// return fillPaint.descent(); -// } - - - @Override - public void textFont(PFont which) { - super.textFont(which); - fillPaint.setTypeface((Typeface) which.getNative()); - fillPaint.setTextSize(which.getDefaultSize()); - } - - - @Override - public void textFont(PFont which, float size) { - super.textFont(which, size); - fillPaint.setTypeface((Typeface) which.getNative()); - fillPaint.setTextSize(size); - } - - - //public void textLeading(float leading) - - - //public void textMode(int mode) - - - @Override - protected boolean textModeCheck(int mode) { - return mode == MODEL; - } - - - /** - * Same as parent, but override for native version of the font. - *

- * Also gets called by textFont, so the metrics - * will get recorded properly. - */ - @Override - public void textSize(float size) { - if (textFont == null) { - defaultFontOrDeath("textSize", size); - } - - Typeface font = (Typeface) textFont.getNative(); - if (font != null) { - fillPaint.setTextSize(size); - } - - handleTextSize(size); - } - - - protected void beginTextScreenMode() { - loadPixels(); - } - - protected void endTextScreenMode() { - updatePixels(); - } - - //public float textWidth(char c) - - - //public float textWidth(String str) - - - @Override - protected float textWidthImpl(char buffer[], int start, int stop) { -// Font font = textFont.getFont(); - Typeface font = (Typeface) textFont.getNative(); - if (font == null) { - return super.textWidthImpl(buffer, start, stop); - } - // maybe should use one of the newer/fancier functions for this? - int length = stop - start; -// FontMetrics metrics = canvas.getFontMetrics(font); -// return metrics.charsWidth(buffer, start, length); - return fillPaint.measureText(buffer, start, length); - } - - - - ////////////////////////////////////////////////////////////// - - // TEXT - - // None of the variations of text() are overridden from PGraphics. - - - - ////////////////////////////////////////////////////////////// - - // TEXT IMPL - - - //protected void textLineAlignImpl(char buffer[], int start, int stop, - // float x, float y) - - - @Override - protected void textLineImpl(char buffer[], int start, int stop, - float x, float y) { - Typeface font = (Typeface) textFont.getNative(); - if (font == null) { - showWarning("Inefficient font rendering: use createFont() with a TTF/OTF instead of loadFont()."); - //new Exception().printStackTrace(System.out); - super.textLineImpl(buffer, start, stop, x, y); - return; - } - - /* - // save the current setting for text smoothing. note that this is - // different from the smooth() function, because the font smoothing - // is controlled when the font is created, not now as it's drawn. - // fixed a bug in 0116 that handled this incorrectly. - Object textAntialias = - g2.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - - // override the current text smoothing setting based on the font - // (don't change the global smoothing settings) - g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, - textFont.smooth ? - RenderingHints.VALUE_ANTIALIAS_ON : - RenderingHints.VALUE_ANTIALIAS_OFF); - */ - -// Object antialias = -// canvas.getRenderingHint(RenderingHints.KEY_ANTIALIASING); -// if (antialias == null) { -// // if smooth() and noSmooth() not called, this will be null (0120) -// antialias = RenderingHints.VALUE_ANTIALIAS_DEFAULT; -// } - - // override the current smoothing setting based on the font - // also changes global setting for antialiasing, but this is because it's - // not possible to enable/disable them independently in some situations. -// canvas.setRenderingHint(RenderingHints.KEY_ANTIALIASING, -// textFont.smooth ? -// RenderingHints.VALUE_ANTIALIAS_ON : -// RenderingHints.VALUE_ANTIALIAS_OFF); - fillPaint.setAntiAlias(textFont.isSmooth()); - - //System.out.println("setting frac metrics"); - //g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, - // RenderingHints.VALUE_FRACTIONALMETRICS_ON); - -// canvas.setColor(fillColorObject); - int length = stop - start; -// canvas.drawChars(buffer, start, length, (int) (x + 0.5f), (int) (y + 0.5f)); - canvas.drawText(buffer, start, length, x, y, fillPaint); - - // return to previous smoothing state if it was changed -// canvas.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antialias); - fillPaint.setAntiAlias(0 < smooth); - -// textX = x + textWidthImpl(buffer, start, stop); -// textY = y; -// textZ = 0; // this will get set by the caller if non-zero - } - - - - ////////////////////////////////////////////////////////////// - - // MATRIX STACK - - - @Override - public void pushMatrix() { - if (transformCount == transformStack.length) { - throw new RuntimeException("pushMatrix() cannot use push more than " + - transformStack.length + " times"); - } - transform.get(transformStack[transformCount]); - transformCount++; - -// canvas.save(); - } - - - @Override - public void popMatrix() { - if (transformCount == 0) { - throw new RuntimeException("missing a popMatrix() " + - "to go with that pushMatrix()"); - } - transformCount--; - transform.set(transformStack[transformCount]); - updateTransformMatrix(); - - // Using canvas.restore() here and canvas.save() in popMatrix() and should achieve - // the same effect as setting copying transform into transformMatrix with updateTransformMatrix() - // and setting it below, although it has been reported that with the later approach, a push/pop - // would not result in the initial matrix state: - // https://github.com/processing/processing-android/issues/445 - // However, cannot find - canvas.setMatrix(transformMatrix); -// canvas.restore(); - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX TRANSFORMS - - - @Override - public void translate(float tx, float ty) { - transform.translate(tx, ty); - canvas.translate(tx, ty); - } - - - @Override - public void rotate(float angle) { - transform.rotate(angle); - canvas.rotate(angle * RAD_TO_DEG); - } - - - @Override - public void rotateX(float angle) { - showDepthWarning("rotateX"); - } - - - @Override - public void rotateY(float angle) { - showDepthWarning("rotateY"); - } - - - @Override - public void rotateZ(float angle) { - showDepthWarning("rotateZ"); - } - - - @Override - public void rotate(float angle, float vx, float vy, float vz) { - showVariationWarning("rotate"); - } - - - @Override - public void scale(float s) { - transform.scale(s, s); - canvas.scale(s, s); - } - - - @Override - public void scale(float sx, float sy) { - transform.scale(sx, sy); - canvas.scale(sx, sy); - } - - - @Override - public void scale(float sx, float sy, float sz) { - showDepthWarningXYZ("scale"); - } - - - @Override - public void shearX(float angle) { - float t = (float) Math.tan(angle); - transform.apply(1, t, 0, 0, 1, 0); - canvas.skew(t, 0); - } - - - @Override - public void shearY(float angle) { - float t = (float) Math.tan(angle); - transform.apply(1, 0, 0, t, 1, 0); - canvas.skew(0, t); - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX MORE - - - @Override - public void resetMatrix() { - transform.reset(); - canvas.setMatrix(null); - } - - - //public void applyMatrix(PMatrix2D source) - - - @Override - public void applyMatrix(float n00, float n01, float n02, - float n10, float n11, float n12) { - transform.apply(n00, n01, n02, n10, n11, n12); - updateTransformMatrix(); - canvas.concat(transformMatrix); - } - - - //public void applyMatrix(PMatrix3D source) - - - @Override - public void applyMatrix(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - showVariationWarning("applyMatrix"); - } - - - - ////////////////////////////////////////////////////////////// - - // MATRIX GET/SET - - - @Override - public PMatrix getMatrix() { - return getMatrix((PMatrix2D) null); - } - - - @Override - public PMatrix2D getMatrix(PMatrix2D target) { - if (target == null) { - target = new PMatrix2D(); - } - target.set(transform); - return target; - } - - - @Override - public PMatrix3D getMatrix(PMatrix3D target) { - showVariationWarning("getMatrix"); - return target; - } - - - //public void setMatrix(PMatrix source) - - - @Override - public void setMatrix(PMatrix2D source) { - transform.set(source); - updateTransformMatrix(); - canvas.setMatrix(transformMatrix); - } - - - @Override - public void setMatrix(PMatrix3D source) { - showVariationWarning("setMatrix"); - } - - - @Override - public void printMatrix() { - getMatrix((PMatrix2D) null).print(); - } - - - protected Matrix getMatrixImp() { - Matrix m = new Matrix(); - updateTransformMatrix(); - m.set(transformMatrix); - return m; -// return canvas.getMatrix(); - } - - - public void updateTransformMatrix() { - transformArray[0] = transform.m00; - transformArray[1] = transform.m01; - transformArray[2] = transform.m02; - transformArray[3] = transform.m10; - transformArray[4] = transform.m11; - transformArray[5] = transform.m12; - transformArray[6] = 0; - transformArray[7] = 0; - transformArray[8] = 1; - transformMatrix.setValues(transformArray); - } - - - ////////////////////////////////////////////////////////////// - - // CAMERA and PROJECTION - - // Inherit the plaintive warnings from PGraphics - - - //public void beginCamera() - //public void endCamera() - //public void camera() - //public void camera(float eyeX, float eyeY, float eyeZ, - // float centerX, float centerY, float centerZ, - // float upX, float upY, float upZ) - //public void printCamera() - - //public void ortho() - //public void ortho(float left, float right, - // float bottom, float top, - // float near, float far) - //public void perspective() - //public void perspective(float fov, float aspect, float near, float far) - //public void frustum(float left, float right, - // float bottom, float top, - // float near, float far) - //public void printProjection() - - - - ////////////////////////////////////////////////////////////// - - // SCREEN and MODEL transforms - - float[] screenPoint; - - @Override - public float screenX(float x, float y) { - if (screenPoint == null) { - screenPoint = new float[2]; - } - screenPoint[0] = x; - screenPoint[1] = y; - getMatrixImp().mapPoints(screenPoint); - return screenPoint[0]; - } - - - @Override - public float screenY(float x, float y) { - if (screenPoint == null) { - screenPoint = new float[2]; - } - screenPoint[0] = x; - screenPoint[1] = y; - getMatrixImp().mapPoints(screenPoint); - return screenPoint[1]; - } - - - @Override - public float screenX(float x, float y, float z) { - showDepthWarningXYZ("screenX"); - return 0; - } - - - @Override - public float screenY(float x, float y, float z) { - showDepthWarningXYZ("screenY"); - return 0; - } - - - @Override - public float screenZ(float x, float y, float z) { - showDepthWarningXYZ("screenZ"); - return 0; - } - - - //public float modelX(float x, float y, float z) - - - //public float modelY(float x, float y, float z) - - - //public float modelZ(float x, float y, float z) - - - - ////////////////////////////////////////////////////////////// - - // STYLE - - // pushStyle(), popStyle(), style() and getStyle() inherited. - - - - ////////////////////////////////////////////////////////////// - - // STROKE CAP/JOIN/WEIGHT - - - @Override - public void strokeCap(int cap) { - super.strokeCap(cap); - - if (strokeCap == ROUND) { - strokePaint.setStrokeCap(Paint.Cap.ROUND); - } else if (strokeCap == PROJECT) { - strokePaint.setStrokeCap(Paint.Cap.SQUARE); - } else { - strokePaint.setStrokeCap(Paint.Cap.BUTT); - } - } - - - @Override - public void strokeJoin(int join) { - super.strokeJoin(join); - - if (strokeJoin == MITER) { - strokePaint.setStrokeJoin(Paint.Join.MITER); - } else if (strokeJoin == ROUND) { - strokePaint.setStrokeJoin(Paint.Join.ROUND); - } else { - strokePaint.setStrokeJoin(Paint.Join.BEVEL); - } - } - - - @Override - public void strokeWeight(float weight) { - super.strokeWeight(weight); - strokePaint.setStrokeWidth(weight); - } - - - - ////////////////////////////////////////////////////////////// - - // STROKE - - // noStroke() and stroke() inherited from PGraphics. - - - @Override - protected void strokeFromCalc() { - super.strokeFromCalc(); -// strokeColorObject = new Color(strokeColor, true); - strokePaint.setColor(strokeColor); -// strokeGradient = false; - strokePaint.setShader(null); - } - - - - ////////////////////////////////////////////////////////////// - - // TINT - - // noTint() and tint() inherited from PGraphics. - - - @Override - protected void tintFromCalc() { - super.tintFromCalc(); - tintPaint.setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.MULTIPLY)); - } - - - - ////////////////////////////////////////////////////////////// - - // FILL - - // noFill() and fill() inherited from PGraphics. - - - @Override - protected void fillFromCalc() { - super.fillFromCalc(); -// fillColorObject = new Color(fillColor, true); - fillPaint.setColor(fillColor); -// fillGradient = false; - fillPaint.setShader(null); - } - - - - ////////////////////////////////////////////////////////////// - - // MATERIAL PROPERTIES - - - //public void ambient(int rgb) - //public void ambient(float gray) - //public void ambient(float x, float y, float z) - //protected void ambientFromCalc() - //public void specular(int rgb) - //public void specular(float gray) - //public void specular(float x, float y, float z) - //protected void specularFromCalc() - //public void shininess(float shine) - //public void emissive(int rgb) - //public void emissive(float gray) - //public void emissive(float x, float y, float z ) - //protected void emissiveFromCalc() - - - - ////////////////////////////////////////////////////////////// - - // LIGHTS - - - //public void lights() - //public void noLights() - //public void ambientLight(float red, float green, float blue) - //public void ambientLight(float red, float green, float blue, - // float x, float y, float z) - //public void directionalLight(float red, float green, float blue, - // float nx, float ny, float nz) - //public void pointLight(float red, float green, float blue, - // float x, float y, float z) - //public void spotLight(float red, float green, float blue, - // float x, float y, float z, - // float nx, float ny, float nz, - // float angle, float concentration) - //public void lightFalloff(float constant, float linear, float quadratic) - //public void lightSpecular(float x, float y, float z) - //protected void lightPosition(int num, float x, float y, float z) - //protected void lightDirection(int num, float x, float y, float z) - - - - ////////////////////////////////////////////////////////////// - - // BACKGROUND - - // background() methods inherited from PGraphics, along with the - // PImage version of backgroundImpl(), since it just calls set(). - - - //public void backgroundImpl(PImage image) - - -// int[] clearPixels; - - @Override - public void backgroundImpl() { - canvas.drawColor(backgroundColor); - -// if (backgroundAlpha) { -// WritableRaster raster = ((BufferedImage) image).getRaster(); -// if ((clearPixels == null) || (clearPixels.length < width)) { -// clearPixels = new int[width]; -// } -// java.util.Arrays.fill(clearPixels, backgroundColor); -// for (int i = 0; i < height; i++) { -// raster.setDataElements(0, i, width, 1, clearPixels); -// } -// } else { -// //new Exception().printStackTrace(System.out); -// // in case people do transformations before background(), -// // need to handle this with a push/reset/pop -// pushMatrix(); -// resetMatrix(); -// canvas.setColor(new Color(backgroundColor)); //, backgroundAlpha)); -// canvas.fillRect(0, 0, width, height); -// popMatrix(); -// } - } - - - - ////////////////////////////////////////////////////////////// - - // COLOR MODE - - // All colorMode() variations are inherited from PGraphics. - - - - ////////////////////////////////////////////////////////////// - - // COLOR CALC - - // colorCalc() and colorCalcARGB() inherited from PGraphics. - - - - ////////////////////////////////////////////////////////////// - - // COLOR DATATYPE STUFFING - - // final color() variations inherited. - - - - ////////////////////////////////////////////////////////////// - - // COLOR DATATYPE EXTRACTION - - // final methods alpha, red, green, blue, - // hue, saturation, and brightness all inherited. - - - - ////////////////////////////////////////////////////////////// - - // COLOR DATATYPE INTERPOLATION - - // both lerpColor variants inherited. - - - - ////////////////////////////////////////////////////////////// - - // BEGIN/END RAW - - - @Override - public void beginRaw(PGraphics recorderRaw) { - showMethodWarning("beginRaw"); - } - - - @Override - public void endRaw() { - showMethodWarning("endRaw"); - } - - - - ////////////////////////////////////////////////////////////// - - // WARNINGS and EXCEPTIONS - - // showWarning and showException inherited. - - - - ////////////////////////////////////////////////////////////// - - // RENDERER SUPPORT QUERIES - - - //public boolean displayable() // true - - - //public boolean is2D() // true - - - //public boolean is3D() // false - - - - ////////////////////////////////////////////////////////////// - - // PIMAGE METHODS - - - // getImage, setCache, getCache, removeCache, isModified, setModified - - - @Override - public void loadPixels() { - if (bitmap == null) { - throw new RuntimeException("The pixels array is not available in this " + - "renderer withouth a backing bitmap"); - } - - if ((pixels == null) || (pixels.length != width * height)) { - pixels = new int[width * height]; - } -// WritableRaster raster = ((BufferedImage) image).getRaster(); -// raster.getDataElements(0, 0, width, height, pixels); - bitmap.getPixels(pixels, 0, width, 0, 0, width, height); - } - - - /** - * Update the pixels[] buffer to the PGraphics image. - *

- * Unlike in PImage, where updatePixels() only requests that the - * update happens, in PGraphicsJava2D, this will happen immediately. - */ - @Override - public void updatePixels() { - if (bitmap == null) { - throw new RuntimeException("The pixels array is not available in this " + - "renderer withouth a backing bitmap"); - } - -// WritableRaster raster = ((BufferedImage) image).getRaster(); -// raster.setDataElements(0, 0, width, height, pixels); - bitmap.setPixels(pixels, 0, width, 0, 0, width, height); - } - - - /** - * Update the pixels[] buffer to the PGraphics image. - *

- * Unlike in PImage, where updatePixels() only requests that the - * update happens, in PGraphicsJava2D, this will happen immediately. - */ - @Override - public void updatePixels(int x, int y, int c, int d) { - //if ((x == 0) && (y == 0) && (c == width) && (d == height)) { - if ((x != 0) || (y != 0) || (c != width) || (d != height)) { - // Show a warning message, but continue anyway. - showVariationWarning("updatePixels(x, y, w, h)"); - } - updatePixels(); - } - - - @Override - public void resize(int wide, int high) { - showMethodWarning("resize"); - } - - - @Override - protected void clearState() { - super.clearState(); - if (restoreFilename != null) { - File cacheFile = new File(restoreFilename); - cacheFile.delete(); - } - } - - - @Override - protected void saveState() { - super.saveState(); - - Context context = parent.getContext(); - if (context == null || bitmap == null || parent.getSurface().getComponent().isService()) return; - try { - // Saving current width and height to avoid restoring the screen after a screen rotation - restoreWidth = pixelWidth; - restoreHeight = pixelHeight; - - int size = bitmap.getHeight() * bitmap.getRowBytes(); - ByteBuffer restoreBitmap = ByteBuffer.allocate(size); - bitmap.copyPixelsToBuffer(restoreBitmap); - - // Tries to use external but if not mounted, falls back on internal storage, as shown in - // https://developer.android.com/topic/performance/graphics/cache-bitmap#java - File cacheDir = Environment.MEDIA_MOUNTED == Environment.getExternalStorageState() || !isExternalStorageRemovable() ? - context.getExternalCacheDir() : context.getCacheDir(); - File cacheFile = new File(cacheDir + File.separator + "restore_pixels"); - restoreFilename = cacheFile.getAbsolutePath(); - - FileOutputStream stream = new FileOutputStream(cacheFile); - ObjectOutputStream dout = new ObjectOutputStream(stream); - byte[] array = new byte[size]; - restoreBitmap.rewind(); - restoreBitmap.get(array); - dout.writeObject(array); - dout.flush(); - stream.getFD().sync(); - stream.close(); - } catch (Exception ex) { - PGraphics.showWarning("Could not save screen contents to cache"); - ex.printStackTrace(); - } - } - - - @Override - protected void restoreSurface() { - if (changed) { - changed = false; - if (restoreFilename != null && restoreWidth == pixelWidth && restoreHeight == pixelHeight) { - // Set the counter to 1 so the restore bitmap is drawn in the next frame. - restoreCount = 1; - } - } else if (restoreCount > 0) { - restoreCount--; - if (restoreCount == 0) { - Context context = parent.getContext(); - if (context == null) return; - try { - // Load cached bitmap and draw - File cacheFile = new File(restoreFilename); - FileInputStream inStream = new FileInputStream(cacheFile); - ObjectInputStream din = new ObjectInputStream(inStream); - byte[] array = (byte[]) din.readObject(); - ByteBuffer restoreBitmap = ByteBuffer.wrap(array); - if (restoreBitmap.capacity() == bitmap.getHeight() * bitmap.getRowBytes()) { - restoreBitmap.rewind(); - bitmap.copyPixelsFromBuffer(restoreBitmap); - } - inStream.close(); - cacheFile.delete(); - } catch (Exception ex) { - PGraphics.showWarning("Could not restore screen contents from cache"); - ex.printStackTrace(); - } finally { - restoreFilename = null; - restoreWidth = -1; - restoreHeight = -1; - restoredSurface = true; - } - } - } - super.restoreSurface(); - } - - - ////////////////////////////////////////////////////////////// - - // GET/SET - - - static int getset[] = new int[1]; - - - @Override - public int get(int x, int y) { - if ((bitmap == null) || (x < 0) || (y < 0) || (x >= width) || (y >= height)) return 0; -// WritableRaster raster = ((BufferedImage) image).getRaster(); -// raster.getDataElements(x, y, getset); -// return getset[0]; - return bitmap.getPixel(x, y); - } - - - //public PImage get(int x, int y, int w, int h) - - -// @Override -// public PImage getImpl(int x, int y, int w, int h) { -// PImage output = new PImage(); -// output.width = w; -// output.height = h; -// output.parent = parent; -// -// Bitmap bitsy = Bitmap.createBitmap(bitmap, x, y, w, h); -// // guessing it's more efficient to use Bitmap instead of pixels[] -// //bitsy.getPixels(output.pixels, 0, w, 0, 0, w, h); -// output.bitmap = bitsy; -// -// return output; -// } - - - @Override - public PImage get() { - return get(0, 0, width, height); - } - - - @Override - public void set(int x, int y, int argb) { - if ((bitmap == null) || (x < 0) || (y < 0) || (x >= width) || (y >= height)) return; -// getset[0] = argb; -// WritableRaster raster = ((BufferedImage) image).getRaster(); -// raster.setDataElements(x, y, getset); - bitmap.setPixel(x, y, argb); - } - - - @Override - public void set(int x, int y, PImage src) { - if (src.format == ALPHA) { - // set() doesn't really make sense for an ALPHA image, since it - // directly replaces pixels and does no blending. - throw new RuntimeException("set() not available for ALPHA images"); - } - - Bitmap bitmap = (Bitmap)src.getNative(); - if (bitmap == null) { - bitmap = Bitmap.createBitmap(src.width, src.height, Config.ARGB_8888); - src.setNative(bitmap); - src.setModified(); - } - if (src.width != bitmap.getWidth() || - src.height != bitmap.getHeight()) { - bitmap.recycle(); - bitmap = Bitmap.createBitmap(src.width, src.height, Config.ARGB_8888); - src.setNative(bitmap); - src.setModified(); - } - if (src.isModified()) { - if (!bitmap.isMutable()) { - bitmap.recycle(); - bitmap = Bitmap.createBitmap(src.width, src.height, Config.ARGB_8888); - setNative(bitmap); - } - bitmap.setPixels(src.pixels, 0, src.width, 0, 0, src.width, src.height); - src.setModified(false); - } - // set() happens in screen coordinates, so need to clear the ctm - pushMatrix(); - canvas.setMatrix(null); // set to identity - canvas.drawBitmap(bitmap, x, y, null); - popMatrix(); - } - - - // elaborate but silly version, since android will happily do this work -// private Rect setImplSrcRect; -// private Rect setImplDstRect; -// -// protected void setImpl(int dx, int dy, int sx, int sy, int sw, int sh, -// PImage src) { -// if (setImplSrcRect == null) { -// setImplSrcRect = new Rect(sx, sy, sx+sw, sy+sh); -// setImplDstRect = new Rect(dx, dy, dx+sw, dy+sh); -// } else { -// setImplSrcRect.set(sx, sy, sx+sw, sy+sh); -// setImplDstRect.set(dx, dy, dx+sw, dy+sh); -// } -// // set() happens in screen coordinates, so need to nuke the ctm -// canvas.save(Canvas.MATRIX_SAVE_FLAG); -// canvas.setMatrix(null); // set to identity -// canvas.drawBitmap(src.image, setImplSrcRect, setImplDstRect, null); -// canvas.restore(); -// } - - // PImage version -// int srcOffset = sy * src.width + sx; -// int dstOffset = dy * width + dx; -// -// for (int y = sy; y < sy + sh; y++) { -// System.arraycopy(src.pixels, srcOffset, pixels, dstOffset, sw); -// srcOffset += src.width; -// dstOffset += width; -// } -// updatePixelsImpl(sx, sy, sx+sw, sy+sh); - - // PGraphicsJava2D version -// WritableRaster raster = ((BufferedImage) image).getRaster(); -// if ((sx == 0) && (sy == 0) && (sw == src.width) && (sh == src.height)) { -// raster.setDataElements(dx, dy, src.width, src.height, src.pixels); -// } else { -// // TODO Optimize, incredibly inefficient to reallocate this much memory -// PImage temp = src.get(sx, sy, sw, sh); -// raster.setDataElements(dx, dy, temp.width, temp.height, temp.pixels); -// } - - - - ////////////////////////////////////////////////////////////// - - // MASK - - - @Override - public void mask(int alpha[]) { - showMethodWarning("mask"); - } - - - @Override - public void mask(PImage alpha) { - showMethodWarning("mask"); - } - - - - ////////////////////////////////////////////////////////////// - - // FILTER - - // Because the PImage versions call loadPixels() and - // updatePixels(), no need to override anything here. - - - //public void filter(int kind) - - - //public void filter(int kind, float param) - - - - ////////////////////////////////////////////////////////////// - - // COPY - - - @Override - public void copy(int sx, int sy, int sw, int sh, - int dx, int dy, int dw, int dh) { - if (bitmap == null) { - throw new RuntimeException("The pixels array is not available in this " + - "renderer withouth a backing bitmap"); - } - -// Bitmap bitsy = Bitmap.createBitmap(image, sx, sy, sw, sh); -// rect.set(dx, dy, dx + dw, dy + dh); -// canvas.drawBitmap(bitsy, - rect.set(dx, dy, dx+dw, dy+dh); - Rect src = new Rect(sx, sy, sx+sw, sy+sh); - canvas.drawBitmap(bitmap, src, rect, null); - -// if ((sw != dw) || (sh != dh)) { -// // use slow version if changing size -// copy(this, sx, sy, sw, sh, dx, dy, dw, dh); -// -// } else { -// dx = dx - sx; // java2d's "dx" is the delta, not dest -// dy = dy - sy; -// canvas.copyArea(sx, sy, sw, sh, dx, dy); -// } - } - - -// public void copy(PImage src, -// int sx1, int sy1, int sx2, int sy2, -// int dx1, int dy1, int dx2, int dy2) { -// loadPixels(); -// super.copy(src, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2); -// updatePixels(); -// } - - - - ////////////////////////////////////////////////////////////// - - // BLEND - - -// static public int blendColor(int c1, int c2, int mode) - - -// public void blend(int sx, int sy, int sw, int sh, -// int dx, int dy, int dw, int dh, int mode) - - -// public void blend(PImage src, -// int sx, int sy, int sw, int sh, -// int dx, int dy, int dw, int dh, int mode) - - - - ////////////////////////////////////////////////////////////// - - // SAVE - - -// public void save(String filename) { -// loadPixels(); -// super.save(filename); -// } -} \ No newline at end of file diff --git a/core/src/processing/a2d/PShapeAndroid2D.java b/core/src/processing/a2d/PShapeAndroid2D.java deleted file mode 100644 index b9bb2c019..000000000 --- a/core/src/processing/a2d/PShapeAndroid2D.java +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.a2d; - -import android.graphics.Shader; - -import processing.core.PGraphics; -import processing.core.PShapeSVG; -import processing.data.XML; - -public class PShapeAndroid2D extends PShapeSVG { - protected Shader strokeGradientPaint; - protected Shader fillGradientPaint; - - - public PShapeAndroid2D(XML svg) { - super(svg); - } - - - public PShapeAndroid2D(PShapeSVG parent, XML properties, boolean parseKids) { - super(parent, properties, parseKids); - } - - - @Override - protected void setParent(PShapeSVG parent) { - super.setParent(parent); - - if (parent instanceof PShapeAndroid2D) { - PShapeAndroid2D pj = (PShapeAndroid2D) parent; - fillGradientPaint = pj.fillGradientPaint; - strokeGradientPaint = pj.strokeGradientPaint; - - } else { // parent is null or not Android2D - fillGradientPaint = null; - strokeGradientPaint = null; - } - } - - - /** Factory method for subclasses. */ - @Override - protected PShapeSVG createShape(PShapeSVG parent, XML properties, boolean parseKids) { - return new PShapeAndroid2D(parent, properties, parseKids); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - protected Shader calcGradientPaint(Gradient gradient) { - // TODO just do this with the other parsing - int[] colors = new int[gradient.count]; - int opacityMask = ((int) (opacity * 255)) << 24; - for (int i = 0; i < gradient.count; i++) { - colors[i] = opacityMask | (gradient.color[i] & 0xFFFFFF); - } - - if (gradient instanceof LinearGradient) { - LinearGradient grad = (LinearGradient) gradient; -// return new LinearGradientPaint(grad.x1, grad.y1, grad.x2, grad.y2, -// grad.offset, grad.color, grad.count, -// opacity); - return new android.graphics.LinearGradient(grad.x1, grad.y1, - grad.x2, grad.y2, - colors, grad.offset, - Shader.TileMode.CLAMP ); - - } else if (gradient instanceof RadialGradient) { - RadialGradient grad = (RadialGradient) gradient; -// return new RadialGradientPaint(grad.cx, grad.cy, grad.r, -// grad.offset, grad.color, grad.count, -// opacity); - return new android.graphics.RadialGradient(grad.cx, grad.cy, grad.r, - colors, grad.offset, - Shader.TileMode.CLAMP); - } - return null; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - @Override - protected void styles(PGraphics g) { - super.styles(g); - - if (g instanceof PGraphicsAndroid2D) { - PGraphicsAndroid2D gg = (PGraphicsAndroid2D) g; - - if (strokeGradient != null) { -// gg.strokeGradient = true; - if (strokeGradientPaint == null) { - strokeGradientPaint = calcGradientPaint(strokeGradient); - } - gg.strokePaint.setShader(strokeGradientPaint); - } - if (fillGradient != null) { -// gg.fillGradient = true; - if (fillGradientPaint == null) { - fillGradientPaint = calcGradientPaint(fillGradient); - } - gg.fillPaint.setShader(fillGradientPaint); - } else { - // need to shut off, in case parent object has a gradient applied - //gg.fillGradient = false; - } - } - } -} diff --git a/core/src/processing/a2d/PSurfaceAndroid2D.java b/core/src/processing/a2d/PSurfaceAndroid2D.java deleted file mode 100644 index eb7635b87..000000000 --- a/core/src/processing/a2d/PSurfaceAndroid2D.java +++ /dev/null @@ -1,159 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.a2d; - -import android.content.Context; -import android.graphics.Color; -import android.graphics.PixelFormat; -import android.service.wallpaper.WallpaperService; -import android.support.wearable.watchface.CanvasWatchFaceService; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.SurfaceView; - -import processing.android.AppComponent; -import processing.android.PFragment; -import processing.core.PApplet; -import processing.core.PGraphics; -import processing.core.PSurfaceNone; - -public class PSurfaceAndroid2D extends PSurfaceNone { - - public PSurfaceAndroid2D() { } - - public PSurfaceAndroid2D(PGraphics graphics, AppComponent component, SurfaceHolder holder) { - this.sketch = graphics.parent; - this.graphics = graphics; - this.component = component; - if (component.getKind() == AppComponent.FRAGMENT) { - PFragment frag = (PFragment)component; - activity = frag.getActivity(); - surfaceView = new SurfaceViewAndroid2D(activity, null); - } else if (component.getKind() == AppComponent.WALLPAPER) { - wallpaper = (WallpaperService)component; - surfaceView = new SurfaceViewAndroid2D(wallpaper, holder); - } else if (component.getKind() == AppComponent.WATCHFACE) { - watchface = (CanvasWatchFaceService)component; - surfaceView = null; - // Set as ready here, as watch faces don't have a surface view with a - // surfaceCreate() event to do it. - surfaceReady = true; - } - } - - /////////////////////////////////////////////////////////// - - // SurfaceView - - public class SurfaceViewAndroid2D extends SurfaceView implements SurfaceHolder.Callback { - SurfaceHolder holder; - - public SurfaceViewAndroid2D(Context context, SurfaceHolder holder) { - super(context); - this.holder = holder; - -// println("surface holder"); - // Install a SurfaceHolder.Callback so we get notified when the - // underlying surface is created and destroyed - SurfaceHolder h = getHolder(); - h.addCallback(this); -// surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU); // no longer needed. - -// println("setting focusable, requesting focus"); - setFocusable(true); - setFocusableInTouchMode(true); - requestFocus(); -// println("done making surface view"); - - surfaceReady = false; // Will be ready when the surfaceCreated() event is called - - // Solves screen flickering: - // https://github.com/processing/processing-android/issues/570 - setBackgroundColor(Color.argb(0, 0, 0, 0)); - getHolder().setFormat(PixelFormat.TRANSPARENT); - } - - @Override - public SurfaceHolder getHolder() { - if (holder == null) { - return super.getHolder(); - } else { - return holder; - } - } - - // part of SurfaceHolder.Callback - public void surfaceCreated(SurfaceHolder holder) { - surfaceReady = true; - if (requestedThreadStart) { - // Only start the thread once the surface has been created, otherwise it will not be able to draw - startThread(); - } - if (PApplet.DEBUG) { - System.out.println("surfaceCreated()"); - } - } - - - // part of SurfaceHolder.Callback - public void surfaceDestroyed(SurfaceHolder holder) { - if (PApplet.DEBUG) { - System.out.println("surfaceDestroyed()"); - } - } - - - // part of SurfaceHolder.Callback - public void surfaceChanged(SurfaceHolder holder, int format, int iwidth, int iheight) { - if (PApplet.DEBUG) { - System.out.println("SketchSurfaceView.surfaceChanged() " + iwidth + " " + iheight); - } - - sketch.surfaceChanged(); - sketch.setSize(iwidth, iheight); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - sketch.surfaceWindowFocusChanged(hasFocus); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - return sketch.surfaceTouchEvent(event); - } - - @Override - public boolean onKeyDown(int code, android.view.KeyEvent event) { - sketch.surfaceKeyDown(code, event); - return super.onKeyDown(code, event); - } - - @Override - public boolean onKeyUp(int code, android.view.KeyEvent event) { - sketch.surfaceKeyUp(code, event); - return super.onKeyUp(code, event); - } - } -} diff --git a/core/src/processing/android/ActivityAPI.java b/core/src/processing/android/ActivityAPI.java deleted file mode 100644 index 751ec2048..000000000 --- a/core/src/processing/android/ActivityAPI.java +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.android; - -import android.content.Intent; -import android.os.Bundle; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.app.FragmentManager; - - -// Methods that should be implemented in PApplet to maintain backward -// compatibility with (some) functionality available from Activity/Fragment -public interface ActivityAPI { - // Lifecycle events - public void onCreate(Bundle savedInstanceState); - public void onDestroy(); - public void onStart(); - public void onStop(); - public void onPause(); - public void onResume(); - - // Activity and intent events - public void onActivityResult(int requestCode, int resultCode, Intent data); - public void onNewIntent(Intent intent); - - // Menu API - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater); - public boolean onOptionsItemSelected(MenuItem item); - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo); - public boolean onContextItemSelected(MenuItem item); - public void setHasOptionsMenu(boolean hasMenu); - - // IO events - public void onBackPressed(); - - // Activity management - public FragmentManager getFragmentManager(); - public Window getWindow(); -} diff --git a/core/src/processing/android/AppComponent.java b/core/src/processing/android/AppComponent.java deleted file mode 100644 index 396e01126..000000000 --- a/core/src/processing/android/AppComponent.java +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.android; - -import android.content.Intent; - -import processing.core.PApplet; -import processing.core.PConstants; - -abstract public interface AppComponent extends PConstants { - static public final int FRAGMENT = 0; - static public final int WALLPAPER = 1; - static public final int WATCHFACE = 2; - - public void initDimensions(); - public int getDisplayWidth(); - public int getDisplayHeight(); - public float getDisplayDensity(); - public int getKind(); - public void setSketch(PApplet sketch); - public PApplet getSketch(); - - public boolean isService(); - public ServiceEngine getEngine(); - - public void startActivity(Intent intent); - - public void requestDraw(); - public boolean canDraw(); - - public void dispose(); -} diff --git a/core/src/processing/android/CompatUtils.java b/core/src/processing/android/CompatUtils.java deleted file mode 100644 index e218e860b..000000000 --- a/core/src/processing/android/CompatUtils.java +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2017-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.android; - -import android.annotation.SuppressLint; -import android.os.Build; -import android.util.DisplayMetrics; -import android.view.Display; -import android.view.View; -import android.graphics.Point; - -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Compatibility utilities that work across versions of Android. Even though - * the mode sets API level 17 (Android 4.2) as the minimum target, because the - * core library could be used from another IDE and lower targets, then this - * compatibility methods are still needed. - */ -public class CompatUtils { - // Start at 15,000,000, taking into account the comment from Singed - // http://stackoverflow.com/a/39307421 - private static final AtomicInteger nextId = new AtomicInteger(15000000); - - - /** - * This method retrieves the "real" display metrics and size, without - * subtracting any window decor or applying any compatibility scale factors. - * @param display the Display object - * @param metrics the metrics to retrieve - * @param size the size to retrieve - */ - static public void getDisplayParams(Display display, - DisplayMetrics metrics, Point size) { - if (Build.VERSION_CODES.JELLY_BEAN_MR1 <= Build.VERSION.SDK_INT) { - display.getRealMetrics(metrics); - display.getRealSize(size); - } if (Build.VERSION_CODES.ICE_CREAM_SANDWICH <= Build.VERSION.SDK_INT) { - display.getMetrics(metrics); - // Use undocumented methods getRawWidth, getRawHeight - try { - size.x = (Integer) Display.class.getMethod("getRawWidth").invoke(display); - size.y = (Integer) Display.class.getMethod("getRawHeight").invoke(display); - } catch (Exception e) { - display.getSize(size); - } - } else { - display.getMetrics(metrics); - display.getSize(size); - } - } - - - /** - * This method generates a unique View ID's. Handles the lack of - * View.generateViewId() in Android versions lower than 17, using a technique - * based on fantouch's code at http://stackoverflow.com/a/21000252 - * @return view ID - */ - @SuppressLint("NewApi") - static public int getUniqueViewId() { - if (Build.VERSION_CODES.JELLY_BEAN_MR1 <= Build.VERSION.SDK_INT) { - return View.generateViewId(); - } else { - for (;;) { - final int result = nextId.get(); - // aapt-generated IDs have the high byte nonzero; clamp to the range under that. - int newValue = result + 1; - if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. - if (nextId.compareAndSet(result, newValue)) { - return result; - } - } - } - } - - - /** - * This method returns the UTF-8 charset - * @return UTF-8 charset - */ - @SuppressLint("NewApi") - static public Charset getCharsetUTF8() { - if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT) { - return StandardCharsets.UTF_8; - } else { - return Charset.forName("UTF-8"); - } - } -} diff --git a/core/src/processing/android/PFragment.java b/core/src/processing/android/PFragment.java deleted file mode 100644 index 8fe80d72c..000000000 --- a/core/src/processing/android/PFragment.java +++ /dev/null @@ -1,261 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.android; - -import android.util.DisplayMetrics; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.res.Configuration; -import android.graphics.Point; -import android.os.Bundle; -import android.view.ContextMenu; -import android.view.Display; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.view.ContextMenu.ContextMenuInfo; - -import androidx.annotation.IdRes; -import androidx.annotation.LayoutRes; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; - -import processing.core.PApplet; - -public class PFragment extends Fragment implements AppComponent { - private DisplayMetrics metrics; - private Point size; - private PApplet sketch; - private @LayoutRes int layout = -1; - - - public PFragment() { - super(); - } - - - public PFragment(PApplet sketch) { - super(); - setSketch(sketch); - } - - - public void initDimensions() { - metrics = new DisplayMetrics(); - size = new Point(); - WindowManager wm = getActivity().getWindowManager(); - Display display = wm.getDefaultDisplay(); - CompatUtils.getDisplayParams(display, metrics, size); - } - - - public int getDisplayWidth() { - return size.x; - } - - - public int getDisplayHeight() { - return size.y; - } - - - public float getDisplayDensity() { - return metrics.density; - } - - - public int getKind() { - return FRAGMENT; - } - - - public void setSketch(PApplet sketch) { - this.sketch = sketch; - if (layout != -1) { - sketch.parentLayout = layout; - } - } - - - public PApplet getSketch() { - return sketch; - } - - - public void setLayout(@LayoutRes int layout, @IdRes int id, FragmentActivity activity) { - this.layout = layout; - if (sketch != null) { - sketch.parentLayout = layout; - } - FragmentManager manager = activity.getSupportFragmentManager(); - FragmentTransaction transaction = manager.beginTransaction(); - transaction.add(id, this); - transaction.commit(); - } - - - public void setView(View view, FragmentActivity activity) { - FragmentManager manager = activity.getSupportFragmentManager(); - FragmentTransaction transaction = manager.beginTransaction(); - transaction.add(view.getId(), this); - transaction.commit(); - } - - - public boolean isService() { - return false; - } - - - public ServiceEngine getEngine() { - return null; - } - - - public void dispose() { - } - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - if (sketch != null) { - sketch.initSurface(inflater, container, savedInstanceState, this, null); - - // For compatibility with older sketches that run some hardware initialization - // inside onCreate(), don't call from Fragment.onCreate() because the surface - // will not be yet ready, and so the reference to the activity and other - // system variables will be null. In any case, onCreateView() is called - // immediately after onCreate(): - // https://developer.android.com/reference/android/app/Fragment.html#Lifecycle - sketch.onCreate(savedInstanceState); - - return sketch.getSurface().getRootView(); - } else { - return null; - } - } - - - @Override - public void onStart() { - super.onStart(); - if (sketch != null) { - sketch.onStart(); - } - } - - - @Override - public void onResume() { - super.onResume(); - if (sketch != null) { - sketch.onResume(); - } - } - - - @Override - public void onPause() { - super.onPause(); - if (sketch != null) { - sketch.onPause(); - } - } - - - @Override - public void onStop() { - super.onStop(); - if (sketch != null) { - sketch.onStop(); - } - } - - - @Override - public void onDestroy() { - super.onDestroy(); - if (sketch != null) { - sketch.onDestroy(); - } - } - - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (sketch != null) sketch.onActivityResult(requestCode, resultCode, data); - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if (sketch != null) sketch.onCreateOptionsMenu(menu, inflater); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (sketch != null) return sketch.onOptionsItemSelected(item); - return super.onOptionsItemSelected(item); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { - if (sketch != null) sketch.onCreateContextMenu(menu, v, menuInfo); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - if (sketch != null) return sketch.onContextItemSelected(item); - return super.onContextItemSelected(item); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - if (PApplet.DEBUG) System.out.println("configuration changed: " + newConfig); - super.onConfigurationChanged(newConfig); - } - - - public void setOrientation(int which) { - if (which == PORTRAIT) { - getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - } else if (which == LANDSCAPE) { - getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); - } - } - - - public void requestDraw() { - } - - - public boolean canDraw() { - return sketch != null && sketch.isLooping(); - } -} diff --git a/core/src/processing/android/PWallpaper.java b/core/src/processing/android/PWallpaper.java deleted file mode 100644 index 850339100..000000000 --- a/core/src/processing/android/PWallpaper.java +++ /dev/null @@ -1,302 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.android; - -import android.service.wallpaper.WallpaperService; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.WindowManager; -import android.util.DisplayMetrics; -import android.view.Display; -import android.graphics.Point; -import android.graphics.Rect; - -import processing.core.PApplet; - -public class PWallpaper extends WallpaperService implements AppComponent { - private Point size; - private DisplayMetrics metrics; - private WallpaperEngine engine; - - - public void initDimensions() { - metrics = new DisplayMetrics(); - size = new Point(); - WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - CompatUtils.getDisplayParams(display, metrics, size); - } - - - public int getDisplayWidth() { - return size.x; - } - - - public int getDisplayHeight() { - return size.y; - } - - - public float getDisplayDensity() { - return metrics.density; - } - - - public int getKind() { - return WALLPAPER; - } - - - public PApplet createSketch() { - return new PApplet(); - } - - - public void setSketch(PApplet sketch) { - engine.sketch = sketch; - } - - - public PApplet getSketch() { - return engine.sketch; - } - - - public boolean isService() { - return true; - } - - - public ServiceEngine getEngine() { - return engine; - } - - - public void requestDraw() { - } - - - public boolean canDraw() { - return true; - } - - - public void dispose() { - } - - - public void requestPermissions() { - } - - - @Override - public Engine onCreateEngine() { - engine = new WallpaperEngine(); - return engine; - } - - - @Override - public void onDestroy() { - super.onDestroy(); - - if (engine != null){ - //engine.sketch = null; - engine.onDestroy(); - } - } - - - public class WallpaperEngine extends Engine implements ServiceEngine { - PApplet sketch; - private float xOffset, xOffsetStep; - private float yOffset, yOffsetStep; - private int xPixelOffset, yPixelOffset; - - - @Override - public void onCreate(SurfaceHolder surfaceHolder) { - super.onCreate(surfaceHolder); - sketch = createSketch(); - sketch.initSurface(PWallpaper.this, getSurfaceHolder()); - if (isPreview()) requestPermissions(); - setTouchEventsEnabled(true); - } - - - @Override - public void onSurfaceCreated(SurfaceHolder surfaceHolder) { - super.onSurfaceCreated(surfaceHolder); - } - - - @Override - public void onSurfaceChanged(final SurfaceHolder holder, final int format, - final int width, final int height) { - // When the surface of a live wallpaper changes (eg: after a screen rotation) the same sketch - // continues to run (unlike the case of regular apps, where its re-created) so we need to - // force a reset of the renderer so the backing FBOs (in the case of the OpenGL renderers) - // get reinitalized with the correct size. - sketch.g.reset(); - super.onSurfaceChanged(holder, format, width, height); - } - - - @Override - public void onVisibilityChanged(boolean visible) { - if (sketch != null) { - if (visible) { - sketch.onResume(); - } else { - sketch.onPause(); - } - } - super.onVisibilityChanged(visible); - } - - - /* - * Store the position of the touch event so we can use it for drawing - * later - */ - @Override - public void onTouchEvent(MotionEvent event) { - super.onTouchEvent(event); - if (sketch != null) { - sketch.surfaceTouchEvent(event); - } - } - - - @Override - public void onOffsetsChanged(float xOffset, float yOffset, - float xOffsetStep, float yOffsetStep, - int xPixelOffset, int yPixelOffset) { - - if (sketch != null) { - this.xOffset = xOffset; - this.yOffset = yOffset; - this.xOffsetStep = xOffsetStep; - this.yOffsetStep = yOffsetStep; - this.xPixelOffset = xPixelOffset; - this.yPixelOffset = yPixelOffset; - } - } - - - @Override - public void onSurfaceDestroyed(SurfaceHolder holder) { - // This is called immediately before a surface is being destroyed. - // After returning from this call, you should no longer try to access this - // surface. If you have a rendering thread that directly accesses the - // surface, you must ensure that thread is no longer touching the Surface - // before returning from this function. - super.onSurfaceDestroyed(holder); - } - - - @Override - public void onDestroy() { - super.onDestroy(); - if (sketch != null) { - sketch.onDestroy(); - } - } - - - @Override - public float getXOffset() { - return xOffset; - } - - - @Override - public float getYOffset() { - return yOffset; - } - - - @Override - public float getXOffsetStep() { - return xOffsetStep; - } - - - @Override - public float getYOffsetStep() { - return yOffsetStep; - } - - - @Override - public int getXPixelOffset() { - return xPixelOffset; - } - - - @Override - public int getYPixelOffset() { - return yPixelOffset; - } - - - @Override - public boolean isInAmbientMode() { - return false; - } - - - @Override - public boolean isRound() { - return false; - } - - - @Override - public Rect getInsets() { - return null; - } - - - @Override - public boolean useLowBitAmbient() { - return false; - } - - - @Override - public boolean requireBurnInProtection() { - return false; - } - - @Override - public void onRequestPermissionsResult(int requestCode, - String permissions[], - int[] grantResults) { - if (sketch != null) { - sketch.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - } - } -} diff --git a/core/src/processing/android/PWatchFaceCanvas.java b/core/src/processing/android/PWatchFaceCanvas.java deleted file mode 100644 index ee4222dfc..000000000 --- a/core/src/processing/android/PWatchFaceCanvas.java +++ /dev/null @@ -1,368 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.android; - -import java.lang.reflect.Method; - -import android.annotation.TargetApi; -import android.graphics.Canvas; -import android.graphics.Point; -import android.os.Bundle; -import android.graphics.Rect; -import android.support.wearable.complications.ComplicationData; -import android.support.wearable.watchface.CanvasWatchFaceService; -import android.support.wearable.watchface.WatchFaceStyle; -import android.util.DisplayMetrics; -import android.view.Display; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.WindowInsets; -import android.view.WindowManager; - -import processing.a2d.PGraphicsAndroid2D; -import processing.core.PApplet; - -@TargetApi(21) -public class PWatchFaceCanvas extends CanvasWatchFaceService implements AppComponent { - private Point size; - private DisplayMetrics metrics; - private CanvasEngine engine; - - public void initDimensions() { - metrics = new DisplayMetrics(); - size = new Point(); - WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - CompatUtils.getDisplayParams(display, metrics, size); - } - - - public int getDisplayWidth() { - return size.x; - } - - - public int getDisplayHeight() { - return size.y; - } - - - public float getDisplayDensity() { - return metrics.density; - } - - - public int getKind() { - return WATCHFACE; - } - - - public PApplet createSketch() { - return new PApplet(); - } - - - public void setSketch(PApplet sketch) { - engine.sketch = sketch; - } - - - public PApplet getSketch() { - return engine.sketch; - } - - - public boolean isService() { - return true; - } - - - public ServiceEngine getEngine() { - return engine; - } - - - public void requestDraw() { - if (engine != null) engine.invalidateIfNecessary(); - } - - - public boolean canDraw() { - // The rendering loop should never call handleDraw() directly, - // it only needs to invalidate the screen - return false; - } - - - public void dispose() { - } - - - public void requestPermissions() { - } - - - @Override - public Engine onCreateEngine() { - engine = new CanvasEngine(); - return engine; - } - - - @Override - public void onDestroy() { - super.onDestroy(); - if (engine != null) engine.onDestroy(); - } - - - private class CanvasEngine extends CanvasWatchFaceService.Engine implements ServiceEngine { - private PApplet sketch; - private Method compUpdatedMethod; - private Method tapCommandMethod; - private boolean isRound = false; - private Rect insets = new Rect(); - private boolean lowBitAmbient = false; - private boolean burnInProtection = false; - - @Override - public void onCreate(SurfaceHolder surfaceHolder) { - super.onCreate(surfaceHolder); - setWatchFaceStyle(new WatchFaceStyle.Builder(PWatchFaceCanvas.this) - .setAcceptsTapEvents(true) - .build()); - sketch = createSketch(); - PGraphicsAndroid2D.useBitmap = false; - sketch.initSurface(PWatchFaceCanvas.this, null); - initTapEvents(); - initComplications(); - requestPermissions(); - } - - - private void initTapEvents() { - try { - tapCommandMethod = sketch.getClass().getMethod("onTapCommand", - new Class[] {int.class, int.class, int.class, long.class}); - } catch (Exception e) { - tapCommandMethod = null; - } - } - - - private void initComplications() { - try { - compUpdatedMethod = sketch.getClass().getMethod("onComplicationDataUpdate", - new Class[] {int.class, ComplicationData.class}); - } catch (Exception e) { - compUpdatedMethod = null; - } - } - - - private void invalidateIfNecessary() { - if (isVisible() && !isInAmbientMode()) { - invalidate(); - } - } - - - @Override - public void onAmbientModeChanged(boolean inAmbientMode) { - super.onAmbientModeChanged(inAmbientMode); - invalidateIfNecessary(); - // call new event handlers in sketch (?) - } - - - @Override - public void onPropertiesChanged(Bundle properties) { - super.onPropertiesChanged(properties); - lowBitAmbient = properties.getBoolean(PROPERTY_LOW_BIT_AMBIENT, false); - burnInProtection = properties.getBoolean(PROPERTY_BURN_IN_PROTECTION, false); - } - - - @Override - public void onApplyWindowInsets(WindowInsets insets) { - super.onApplyWindowInsets(insets); - isRound = insets.isRound(); - this.insets.set(insets.getSystemWindowInsetLeft(), - insets.getSystemWindowInsetTop(), - insets.getSystemWindowInsetRight(), - insets.getSystemWindowInsetBottom()); - } - - - @Override - public void onVisibilityChanged(boolean visible) { - super.onVisibilityChanged(visible); - if (sketch != null) { - if (visible) { - sketch.onResume(); - } else { - sketch.onPause(); - } - } - } - - - @Override - public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { - super.onSurfaceChanged(holder, format, width, height); - if (sketch != null) { - sketch.surfaceChanged(); - sketch.setSize(width, height); - } - } - - - @Override - public void onPeekCardPositionUpdate(Rect rect) { } - - - @Override - public void onTimeTick() { - invalidate(); - } - - - @Override - public void onDraw(Canvas canvas, Rect bounds) { - super.onDraw(canvas, bounds); - if (sketch != null) { - PGraphicsAndroid2D g2 = (PGraphicsAndroid2D)sketch.g; - g2.canvas = canvas; - sketch.handleDraw(); - } - } - - - @Override - public void onTouchEvent(MotionEvent event) { - super.onTouchEvent(event); - if (sketch != null) sketch.surfaceTouchEvent(event); - } - - - @Override - public void onTapCommand(@TapType int tapType, int x, int y, long eventTime) { - if (tapCommandMethod != null) { - try { - tapCommandMethod.invoke(tapType, x, y, eventTime); - } catch (Exception e) { } - invalidate(); - } - } - - - @Override - public void onComplicationDataUpdate(int complicationId, - ComplicationData complicationData) { - if (compUpdatedMethod != null) { - try { - compUpdatedMethod.invoke(complicationId, complicationData); - } catch (Exception e) { } - invalidate(); - } - } - - - @Override - public void onDestroy() { - super.onDestroy(); - if (sketch != null) { - sketch.onDestroy(); - } - } - - - @Override - public float getXOffset() { - return 0; - } - - - @Override - public float getYOffset() { - return 0; - } - - - @Override - public float getXOffsetStep() { - return 0; - } - - - @Override - public float getYOffsetStep() { - return 0; - } - - - @Override - public int getXPixelOffset() { - return 0; - } - - - @Override - public int getYPixelOffset() { - return 0; - } - - - @Override - public boolean isRound() { - return isRound; - } - - - @Override - public Rect getInsets() { - return insets; - } - - - @Override - public boolean useLowBitAmbient() { - return lowBitAmbient; - } - - - @Override - public boolean requireBurnInProtection() { - return burnInProtection; - } - - @Override - public void onRequestPermissionsResult(int requestCode, - String permissions[], - int[] grantResults) { - if (sketch != null) { - sketch.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - } - } -} diff --git a/core/src/processing/android/PWatchFaceGLES.java b/core/src/processing/android/PWatchFaceGLES.java deleted file mode 100644 index e62ab7eb4..000000000 --- a/core/src/processing/android/PWatchFaceGLES.java +++ /dev/null @@ -1,393 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.android; - -import android.annotation.TargetApi; -import android.graphics.Point; -import android.opengl.EGL14; -import android.opengl.EGLConfig; -import android.opengl.EGLDisplay; -import android.os.Bundle; -import android.view.Display; -import android.view.WindowInsets; -import android.support.wearable.complications.ComplicationData; -import android.support.wearable.watchface.Gles2WatchFaceService; -import android.support.wearable.watchface.WatchFaceStyle; -import android.util.DisplayMetrics; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.WindowManager; -import android.graphics.Rect; - -import java.lang.reflect.Method; - -import processing.core.PApplet; - -@TargetApi(21) -public class PWatchFaceGLES extends Gles2WatchFaceService implements AppComponent { - private static final int[] CONFIG_ATTRIB_LIST = new int[]{ - EGL14.EGL_RENDERABLE_TYPE, 4, - EGL14.EGL_RED_SIZE, 8, - EGL14.EGL_GREEN_SIZE, 8, - EGL14.EGL_BLUE_SIZE, 8, - EGL14.EGL_ALPHA_SIZE, 8, - EGL14.EGL_DEPTH_SIZE, 16, // this was missing - EGL14.EGL_NONE}; - - private Point size; - private DisplayMetrics metrics; - private GLES2Engine engine; - - - public void initDimensions() { - metrics = new DisplayMetrics(); - size = new Point(); - WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - CompatUtils.getDisplayParams(display, metrics, size); - } - - - public int getDisplayWidth() { - return size.x; - } - - - public int getDisplayHeight() { - return size.y; - } - - - public float getDisplayDensity() { - return metrics.density; - } - - - public int getKind() { - return WATCHFACE; - } - - - public PApplet createSketch() { - return new PApplet(); - } - - - public void setSketch(PApplet sketch) { - engine.sketch = sketch; - } - - - public PApplet getSketch() { - return engine.sketch; - } - - - public boolean isService() { - return true; - } - - - public ServiceEngine getEngine() { - return engine; - } - - - public void requestDraw() { - if (engine != null) engine.invalidateIfNecessary(); - } - - - public boolean canDraw() { - // The rendering loop should never call handleDraw() directly, it only needs to invalidate the - // screen - return false; - } - - - public void dispose() { - } - - - public void requestPermissions() { - } - - - @Override - public Engine onCreateEngine() { - engine = new GLES2Engine(); - return engine; - } - - - @Override - public void onDestroy() { - super.onDestroy(); - if (engine != null) engine.onDestroy(); - } - - - private class GLES2Engine extends Gles2WatchFaceService.Engine implements ServiceEngine { - private PApplet sketch; - private Method compUpdatedMethod; - private Method tapCommandMethod; - private boolean isRound = false; - private Rect insets = new Rect(); - private boolean lowBitAmbient = false; - private boolean burnInProtection = false; - - @Override - public void onCreate(SurfaceHolder surfaceHolder) { - super.onCreate(surfaceHolder); - setWatchFaceStyle(new WatchFaceStyle.Builder(PWatchFaceGLES.this) - .setAcceptsTapEvents(true) - .build()); - sketch = createSketch(); - sketch.initSurface(PWatchFaceGLES.this, null); - initTapEvents(); - initComplications(); - requestPermissions(); - } - - - public EGLConfig chooseEglConfig(EGLDisplay eglDisplay) { - int[] numEglConfigs = new int[1]; - EGLConfig[] eglConfigs = new EGLConfig[1]; - if (!EGL14.eglChooseConfig(eglDisplay, CONFIG_ATTRIB_LIST, 0, eglConfigs, 0, eglConfigs.length, numEglConfigs, 0)) { - throw new RuntimeException("eglChooseConfig failed"); - } else if (numEglConfigs[0] == 0) { - throw new RuntimeException("no matching EGL configs"); - } else { - return eglConfigs[0]; - } - } - - @Override - public void onGlContextCreated() { - super.onGlContextCreated(); - } - - - @Override - public void onGlSurfaceCreated(int width, int height) { - super.onGlSurfaceCreated(width, height); - if (sketch != null) { - sketch.surfaceChanged(); - sketch.setSize(width, height); - } - } - - - private void initTapEvents() { - try { - tapCommandMethod = sketch.getClass().getMethod("onTapCommand", - new Class[] {int.class, int.class, int.class, long.class}); - } catch (Exception e) { - tapCommandMethod = null; - } - } - - - private void initComplications() { - try { - compUpdatedMethod = sketch.getClass().getMethod("onComplicationDataUpdate", - new Class[] {int.class, ComplicationData.class}); - } catch (Exception e) { - compUpdatedMethod = null; - } - } - - - private void invalidateIfNecessary() { - if (isVisible() && !isInAmbientMode()) { - invalidate(); - } - } - - - @Override - public void onAmbientModeChanged(boolean inAmbientMode) { - super.onAmbientModeChanged(inAmbientMode); - invalidateIfNecessary(); - // call new event handlers in sketch (?) - } - - - @Override - public void onPropertiesChanged(Bundle properties) { - super.onPropertiesChanged(properties); - lowBitAmbient = properties.getBoolean(PROPERTY_LOW_BIT_AMBIENT, false); - burnInProtection = properties.getBoolean(PROPERTY_BURN_IN_PROTECTION, false); - } - - - @Override - public void onApplyWindowInsets(WindowInsets insets) { - super.onApplyWindowInsets(insets); - this.insets.set(insets.getSystemWindowInsetLeft(), - insets.getSystemWindowInsetTop(), - insets.getSystemWindowInsetRight(), - insets.getSystemWindowInsetBottom()); - } - - - @Override - public void onVisibilityChanged(boolean visible) { - super.onVisibilityChanged(visible); - if (sketch != null) { - if (visible) { - sketch.onResume(); - } else { - sketch.onPause(); - } - } - } - - - @Override - public void onPeekCardPositionUpdate(Rect rect) { } - - - @Override - public void onTimeTick() { - invalidate(); - } - - - @Override - public void onDraw() { - super.onDraw(); - if (sketch != null) sketch.handleDraw(); - } - - - @Override - public void onTouchEvent(MotionEvent event) { - super.onTouchEvent(event); - if (sketch != null) sketch.surfaceTouchEvent(event); - } - - - @Override - public void onTapCommand(@TapType int tapType, int x, int y, long eventTime) { - if (tapCommandMethod != null) { - try { - tapCommandMethod.invoke(tapType, x, y, eventTime); - } catch (Exception e) { } - invalidate(); - } - } - - - @Override - public void onComplicationDataUpdate(int complicationId, - ComplicationData complicationData) { - if (compUpdatedMethod != null) { - try { - compUpdatedMethod.invoke(complicationId, complicationData); - } catch (Exception e) { - } - invalidate(); - } - } - - - @Override - public void onDestroy() { - super.onDestroy(); - if (sketch != null) { - sketch.onDestroy(); - } - } - - - @Override - public float getXOffset() { - return 0; - } - - - @Override - public float getYOffset() { - return 0; - } - - - @Override - public float getXOffsetStep() { - return 0; - } - - - @Override - public float getYOffsetStep() { - return 0; - } - - - @Override - public int getXPixelOffset() { - return 0; - } - - - @Override - public int getYPixelOffset() { - return 0; - } - - - @Override - public boolean isRound() { - return isRound; - } - - - @Override - public Rect getInsets() { - return insets; - } - - - @Override - public boolean useLowBitAmbient() { - return lowBitAmbient; - } - - - @Override - public boolean requireBurnInProtection() { - return burnInProtection; - } - - - @Override - public void onRequestPermissionsResult(int requestCode, - String permissions[], - int[] grantResults) { - if (sketch != null) { - sketch.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - } - } -} diff --git a/core/src/processing/android/PermissionRequestor.java b/core/src/processing/android/PermissionRequestor.java deleted file mode 100644 index 0754badc3..000000000 --- a/core/src/processing/android/PermissionRequestor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2017-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.android; - -import android.app.Activity; -import android.os.Bundle; - -import android.support.v4.os.ResultReceiver; -import androidx.core.app.ActivityCompat; - -// A simple utility activity to request permissions in a service. -public class PermissionRequestor extends Activity { - public static final String KEY_RESULT_RECEIVER = "resultReceiver"; - public static final String KEY_PERMISSIONS = "permissions"; - public static final String KEY_GRANT_RESULTS = "grantResults"; - public static final String KEY_REQUEST_CODE = "requestCode"; - - ResultReceiver resultReceiver; - String[] permissions; - int requestCode; - - @Override - protected void onStart() { - super.onStart(); - resultReceiver = this.getIntent().getParcelableExtra(KEY_RESULT_RECEIVER); - permissions = this.getIntent().getStringArrayExtra(KEY_PERMISSIONS); - requestCode = this.getIntent().getIntExtra(KEY_REQUEST_CODE, 0); - ActivityCompat.requestPermissions(this, permissions, requestCode); - } - - @Override - public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { - Bundle resultData = new Bundle(); - resultData.putStringArray(KEY_PERMISSIONS, permissions); - resultData.putIntArray(KEY_GRANT_RESULTS, grantResults); - resultReceiver.send(requestCode, resultData); - finish(); - } -} \ No newline at end of file diff --git a/core/src/processing/android/ServiceEngine.java b/core/src/processing/android/ServiceEngine.java deleted file mode 100644 index 11b1164f0..000000000 --- a/core/src/processing/android/ServiceEngine.java +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2017-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.android; - -import android.graphics.Rect; - -import processing.core.PConstants; - -public interface ServiceEngine extends PConstants { - // wallpapers - public boolean isPreview(); - public float getXOffset(); - public float getYOffset(); - public float getXOffsetStep(); - public float getYOffsetStep(); - public int getXPixelOffset(); - public int getYPixelOffset(); - - // wear - public boolean isInAmbientMode(); - public boolean isRound(); - public Rect getInsets(); - public boolean useLowBitAmbient(); - public boolean requireBurnInProtection(); - - // Service permissions - public void onRequestPermissionsResult(int requestCode, - String permissions[], - int[] grantResults); -} diff --git a/core/src/processing/core/PApplet.java b/core/src/processing/core/PApplet.java deleted file mode 100644 index 2b55cf67c..000000000 --- a/core/src/processing/core/PApplet.java +++ /dev/null @@ -1,12682 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - -import android.app.Activity; -import android.app.FragmentManager; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.res.AssetManager; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.inputmethod.InputMethodManager; - -import androidx.annotation.LayoutRes; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.*; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.HashMap; -import java.util.List; -import java.util.Random; -import java.util.StringTokenizer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -import processing.a2d.PGraphicsAndroid2D; -import processing.android.ActivityAPI; -import processing.android.AppComponent; -import processing.android.CompatUtils; -import processing.data.JSONArray; -import processing.data.JSONObject; -import processing.data.StringList; -import processing.data.Table; -import processing.data.XML; -import processing.event.Event; -import processing.event.KeyEvent; -import processing.event.MouseEvent; -import processing.event.TouchEvent; -import processing.opengl.PGL; -import processing.opengl.PGraphics2D; -import processing.opengl.PGraphics3D; -import processing.opengl.PShader; - -public class PApplet extends Object implements ActivityAPI, PConstants { - - static final public boolean DEBUG = false; -// static final public boolean DEBUG = true; - - // Convenience public constant holding the SDK version, akin to platform in Java mode - static final public int SDK = Build.VERSION.SDK_INT; - - //static final public int SDK = Build.VERSION_CODES.ICE_CREAM_SANDWICH; // Forcing older SDK for testing - - /** - * The surface this sketch draws to. - */ - protected PSurface surface; - - /** - * The view group containing the surface view of the PApplet. - */ - public @LayoutRes int parentLayout = -1; - - /** The PGraphics renderer associated with this PApplet */ - public PGraphics g; - - /** - * The screen size when the sketch was started. This is initialized inside - * onCreate(). - *

- * Note that this won't update if you change the resolution - * of your screen once the the applet is running. - *

- * This variable is not static because in the desktop version of Processing, - * not all instances of PApplet will necessarily be started on a screen of - * the same size. - */ - public int displayWidth, displayHeight; - - /** - * Command line options passed in from main(). - *

- * This does not include the arguments passed in to PApplet itself. - */ -// public String[] args; - - /** - * Path to where sketch can read/write files (read-only). - * Android: This is the writable area for the Activity, which is correct - * for purposes of how sketchPath is used in practice from a sketch, - * even though it's technically different than the desktop version. - */ - public String sketchPath; //folder; - - /** When debugging headaches */ -// static final boolean THREAD_DEBUG = false; - - /** Default width and height for applet when not specified */ - static public final int DEFAULT_WIDTH = -1; - static public final int DEFAULT_HEIGHT = -1; - - /** - * Set true when the surface dimensions have changed, so that the PGraphics - * object can be resized on the next trip through handleDraw(). - */ - protected boolean surfaceChanged; - - /** - * Pixel buffer from this applet's PGraphics. - *

- * When used with OpenGL or Java2D, this value will - * be null until loadPixels() has been called. - */ - public int[] pixels; - - /** width of this applet's associated PGraphics */ - public int width = DEFAULT_WIDTH; - - /** height of this applet's associated PGraphics */ - public int height = DEFAULT_HEIGHT; - - /** The logical density of the display from getDisplayMetrics().density - * According to Android's documentation: - * This is a scaling factor for the Density Independent Pixel unit, - * where one DIP is one pixel on an approximately 160 dpi screen - * (for example a 240x320, 1.5"x2" screen), providing the baseline of the - * system's display. Thus on a 160dpi screen this density value will be 1; - * on a 120 dpi screen it would be .75; etc. - */ - public float displayDensity = 1; - - // For future use - public int pixelDensity = 1; - public int pixelWidth; - public int pixelHeight; - - /////////////////////////////////////////////////////////////// - // Mouse events - - /** absolute x position of input on screen */ - public int mouseX; - - /** absolute x position of input on screen */ - public int mouseY; - - - /** - * Previous x/y position of the mouse. This will be a different value - * when inside a mouse handler (like the mouseMoved() method) versus - * when inside draw(). Inside draw(), pmouseX is updated once each - * frame, but inside mousePressed() and friends, it's updated each time - * an event comes through. Be sure to use only one or the other type of - * means for tracking pmouseX and pmouseY within your sketch, otherwise - * you're gonna run into trouble. - */ - public int pmouseX, pmouseY; - - public int mouseButton; - - public boolean mousePressed; - - - public boolean touchIsStarted; - - - public TouchEvent.Pointer[] touches = new TouchEvent.Pointer[0]; - - - /** - * previous mouseX/Y for the draw loop, separated out because this is - * separate from the pmouseX/Y when inside the mouse event handlers. - */ - protected int dmouseX, dmouseY; - - - /** - * pmotionX/Y for the event handlers (motionPressed(), motionDragged() etc) - * these are different because motion events are queued to the end of - * draw, so the previous position has to be updated on each event, - * as opposed to the pmotionX/Y that's used inside draw, which is expected - * to be updated once per trip through draw(). - */ - protected int emouseX, emouseY; - - - /** - * ID of the pointer tracked for mouse events. - */ - protected int mousePointerId; - - - /** - * ID of the most recently touch pointer gone up or down. - */ - protected int touchPointerId; - - /////////////////////////////////////////////////////////////// - // Key events - - /** - * Last key pressed. - *

- * If it's a coded key, i.e. UP/DOWN/CTRL/SHIFT/ALT, - * this will be set to CODED (0xffff or 65535). - */ - public char key; - - /** - * When "key" is set to CODED, this will contain a Java key code. - *

- * For the arrow keys, keyCode will be one of UP, DOWN, LEFT and RIGHT. - * Also available are ALT, CONTROL and SHIFT. A full set of constants - * can be obtained from java.awt.event.KeyEvent, from the VK_XXXX variables. - */ - public int keyCode; - - /** - * true if the mouse is currently pressed. - */ - public boolean keyPressed; - - /** - * the last KeyEvent object passed into a mouse function. - */ -// public KeyEvent keyEvent; - - /** - * Gets set to true/false as the applet gains/loses focus. - */ - public boolean focused = false; - - /** - * Keeps track of ENABLE_KEY_REPEAT hint - */ - protected boolean keyRepeatEnabled = false; - - /** - * Set to open when openKeyboard() is called, and used to close the keyboard when the sketch is - * paused, otherwise it remains visible. - */ - boolean keyboardIsOpen = false; - - /** - * Flag to determine if the back key was pressed. - */ - private boolean requestedBackPress = false; - - /** - * Flag to determine if the user handled the back press. - */ - public boolean handledBackPressed = true; - - /////////////////////////////////////////////////////////////// - // Permission handling - - /** - * Callback methods to handle permission requests - */ - protected HashMap permissionMethods = new HashMap(); - - - /** - * Permissions requested during one frame - */ - protected ArrayList reqPermissions = new ArrayList(); - - - /////////////////////////////////////////////////////////////// - // Rendering/timing - - /** - * Time in milliseconds when the applet was started. - *

- * Used by the millis() function. - */ - long millisOffset = System.currentTimeMillis(); - - protected boolean insideDraw; - - /** Last time in nanoseconds that frameRate was checked */ - protected long frameRateLastNanos = 0; - - /** - * The current value of frames per second. - *

- * The initial value will be 10 fps, and will be updated with each - * frame thereafter. The value is not instantaneous (since that - * wouldn't be very useful since it would jump around so much), - * but is instead averaged (integrated) over several frames. - * As such, this value won't be valid until after 5-10 frames. - */ - public float frameRate = 10; - - protected boolean looping; - - /** flag set to true when a redraw is asked for by the user */ - protected boolean redraw; - - /** - * How many frames have been displayed since the applet started. - *

- * This value is read-only do not attempt to set it, - * otherwise bad things will happen. - *

- * Inside setup(), frameCount is 0. - * For the first iteration of draw(), frameCount will equal 1. - */ - public int frameCount; - - /** - * true if this applet has had it. - */ - public boolean finished; - - /** - * true if exit() has been called so that things shut down - * once the main thread kicks off. - */ - protected boolean exitCalled; - - boolean insideSettings; - - String renderer = JAVA2D; - - int smooth = 1; // default smoothing (whatever that means for the renderer) - - boolean fullScreen = false; - - int display = -1; // use default - - // Background default needs to be different from the default value in - // PGraphics.backgroundColor, otherwise size(100, 100) bg spills over. - // https://github.com/processing/processing/issues/2297 - int windowColor = 0xffDDDDDD; - - /////////////////////////////////////////////////////////////// - // Error messages - - static final String ERROR_MIN_MAX = - "Cannot use min() or max() on an empty array."; - - /////////////////////////////////////////////////////////////// - // Command line options - - /** - * Position of the upper-lefthand corner of the editor window - * that launched this applet. - */ - static public final String ARGS_EDITOR_LOCATION = "--editor-location"; - - /** - * Location for where to position the applet window on screen. - *

- * This is used by the editor to when saving the previous applet - * location, or could be used by other classes to launch at a - * specific position on-screen. - */ - static public final String ARGS_EXTERNAL = "--external"; - - static public final String ARGS_LOCATION = "--location"; - - static public final String ARGS_DISPLAY = "--display"; - - static public final String ARGS_BGCOLOR = "--bgcolor"; - - static public final String ARGS_PRESENT = "--present"; - - static public final String ARGS_EXCLUSIVE = "--exclusive"; - - static public final String ARGS_STOP_COLOR = "--stop-color"; - - static public final String ARGS_HIDE_STOP = "--hide-stop"; - - /** - * Allows the user or PdeEditor to set a specific sketch folder path. - *

- * Used by PdeEditor to pass in the location where saveFrame() - * and all that stuff should write things. - */ - static public final String ARGS_SKETCH_FOLDER = "--sketch-path"; - - /** - * When run externally to a PdeEditor, - * this is sent by the applet when it quits. - */ - //static public final String EXTERNAL_QUIT = "__QUIT__"; - static public final String EXTERNAL_STOP = "__STOP__"; - - /** - * When run externally to a PDE Editor, this is sent by the applet - * whenever the window is moved. - *

- * This is used so that the editor can re-open the sketch window - * in the same position as the user last left it. - */ - static public final String EXTERNAL_MOVE = "__MOVE__"; - - /** true if this sketch is being run by the PDE */ - boolean external = false; - - - ////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////// - - /** - * Required empty constructor. - */ - public PApplet() { - - } - - - public PSurface getSurface() { - return surface; - } - - - public Context getContext() { - return surface.getContext(); - } - - - public Activity getActivity() { - return surface.getActivity(); - } - - - public void initSurface(AppComponent component, SurfaceHolder holder) { - parentLayout = -1; - initSurface(null, null, null, component, holder); - } - - - public void initSurface(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState, - AppComponent component, SurfaceHolder holder) { - if (DEBUG) println("initSurface() happening here: " + Thread.currentThread().getName()); - - component.initDimensions(); - displayWidth = component.getDisplayWidth(); - displayHeight = component.getDisplayHeight(); - displayDensity = component.getDisplayDensity(); - - handleSettings(); - - boolean parentSize = false; - if (parentLayout == -1) { - if (fullScreen || width == -1 || height == -1) { - // Either sketch explicitly set to full-screen mode, or not - // size/fullScreen provided, so sketch uses the entire display - width = displayWidth; - height = displayHeight; - } - } else { - if (fullScreen || width == -1 || height == -1) { - // Dummy weight and height to initialize the PGraphics, will be resized - // when the view associated to the parent layout is created - width = 100; - height = 100; - parentSize = true; - } - } - - pixelWidth = width * pixelDensity; - pixelHeight = height * pixelDensity; - - String rendererName = sketchRenderer(); - if (DEBUG) println("Renderer " + rendererName); - g = makeGraphics(width, height, rendererName, true); - if (DEBUG) println("Created renderer"); - surface = g.createSurface(component, holder, false); - if (DEBUG) println("Created surface"); - - if (parentLayout == -1) { - setFullScreenVisibility(); - surface.initView(width, height); - } else { - surface.initView(width, height, parentSize, - inflater, container, savedInstanceState); - } - - finished = false; // just for clarity - // this will be cleared by draw() if it is not overridden - looping = true; - redraw = true; // draw this guy once - - sketchPath = surface.getFilesDir().getAbsolutePath(); - - surface.startThread(); - - if (DEBUG) println("Done with init surface"); - } - - - private void setFullScreenVisibility() { - if (fullScreen) { - runOnUiThread(new Runnable() { - @Override - public void run() { - int visibility; - if (SDK < 19) { - // Pre-4.4 - visibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - } else { - // 4.4 and higher. Integer instead of constants defined in View so it can - // build with SDK < 4.4 - visibility = 256 | // View.SYSTEM_UI_FLAG_LAYOUT_STABLE - 512 | // View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - 1024 | // View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | - 4 | // View.SYSTEM_UI_FLAG_FULLSCREEN - 4096; // View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - // However, this visibility does not fix a bug where the navigation area - // turns black after resuming the app: - // https://code.google.com/p/android/issues/detail?id=170752 - } - surface.setSystemUiVisibility(visibility); - } - }); - } - } - - - public void onResume() { - if (DEBUG) System.out.println("PApplet.onResume() called"); - if (parentLayout == -1) { - setFullScreenVisibility(); - } - - handleMethods("resume"); - - // Don't call resume() when the app is starting and setup() has not been called yet: - // https://github.com/processing/processing-android/issues/274 - // Also, there is no need to call resume() from anywhere else (for example, from - // onStart) since onResume() is always called in the activity lifecyle: - // https://developer.android.com/guide/components/activities/activity-lifecycle.html - if (0 < frameCount) { - resume(); - } - - // Set the handledBackPressed to true to handle the situation where a fragment is popping - // right back after pressing the back button (the sketch does not exit). - handledBackPressed = true; - - if (g != null) { - g.restoreState(); - } - - surface.resumeThread(); - } - - - public void onPause() { - surface.pauseThread(); - - // Make sure that the keyboard is not left open after leaving the app - closeKeyboard(); - - if (g != null) { - g.saveState(); - } - - handleMethods("pause"); - - pause(); // handler for others to write - } - - - public void onStart() { - start(); - } - - - public void onStop() { - stop(); - } - - - public void onCreate(Bundle savedInstanceState) { - create(); - } - - - public void onDestroy() { - handleMethods("onDestroy"); - - surface.stopThread(); - - dispose(); - } - - - public void onActivityResult(int requestCode, int resultCode, Intent data) { - handleMethods("onActivityResult", new Object[] { requestCode, resultCode, data }); - } - - - public void onNewIntent(Intent intent) { - handleMethods("onNewIntent", new Object[] { intent }); - } - - - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){ - - } - - - public boolean onOptionsItemSelected(MenuItem item) { - return false; - } - - - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { - - } - - - public boolean onContextItemSelected(MenuItem item) { - return false; - } - - - public void setHasOptionsMenu(boolean hasMenu) { - surface.setHasOptionsMenu(hasMenu); - } - - - synchronized public void onBackPressed() { - requestedBackPress = true; - } - - - public FragmentManager getFragmentManager() { - if (getActivity() != null) { - return getActivity().getFragmentManager(); - } - return null; - } - - - public Window getWindow(){ - if (getActivity() != null) { - return getActivity().getWindow(); - } - return null; - } - - - public void startActivity(Intent intent) { - surface.startActivity(intent); - } - - - public void runOnUiThread(Runnable action) { - surface.runOnUiThread(action); - } - - - public boolean hasPermission(String permission) { - return surface.hasPermission(permission); - } - - - public void requestPermission(String permission) { - if (!hasPermission(permission)) { - reqPermissions.add(permission); - } - } - - - public void requestPermission(String permission, String callback) { - requestPermission(permission, callback, this); - } - - - public void requestPermission(String permission, String callback, Object target) { - registerWithArgs(callback, target, new Class[] { boolean.class }); - if (hasPermission(permission)) { - // If the app already has permission, still call the handle method as it - // may be doing some initialization - handleMethods(callback, new Object[] { true }); - } else { - permissionMethods.put(permission, callback); - // Accumulating permissions so they requested all at once at the end - // of draw. - reqPermissions.add(permission); - } - } - - - public void onRequestPermissionsResult(int requestCode, - String permissions[], - int[] grantResults) { - if (requestCode == PSurface.REQUEST_PERMISSIONS) { - for (int i = 0; i < grantResults.length; i++) { - boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED; - handlePermissionsResult(permissions[i], granted); - } - } - } - - - private void handlePermissionsResult(String permission, final boolean granted) { - String methodName = permissionMethods.get(permission); - final RegisteredMethods meth = registerMap.get(methodName); - if (meth != null) { - Handler handler = new Handler(Looper.getMainLooper()); - handler.post(new Runnable() { - @Override - public void run() { - meth.handle(new Object[] { granted }); - } - }); - } - } - - - private void handlePermissions() { - if (0 < reqPermissions.size()) { - String[] req = reqPermissions.toArray(new String[reqPermissions.size()]); - surface.requestPermissions(req); - reqPermissions.clear(); - } - } - - synchronized private void handleBackPressed() { - if (requestedBackPress) { - requestedBackPress = false; - backPressed(); - if (!handledBackPressed) { - if (getActivity() != null) { - // Services don't have an activity associated to them, but back press could not be triggered for those anyways - getActivity().finish(); - } - handledBackPressed = false; - } - } - } - - /** - * @param method "size" or "fullScreen" - * @param args parameters passed to the function so we can show the user - * @return true if safely inside the settings() method - */ - boolean insideSettings(String method, Object... args) { - if (insideSettings) { - return true; - } - final String url = "https://processing.org/reference/" + method + "_.html"; - if (!external) { // post a warning for users of Eclipse and other IDEs - StringList argList = new StringList(args); - System.err.println("When not using the PDE, " + method + "() can only be used inside settings()."); - System.err.println("Remove the " + method + "() method from setup(), and add the following:"); - System.err.println("public void settings() {"); - System.err.println(" " + method + "(" + argList.join(", ") + ");"); - System.err.println("}"); - } - throw new IllegalStateException(method + "() cannot be used here, see " + url); - } - - - void handleSettings() { - insideSettings = true; - //Do stuff - settings(); - insideSettings = false; - } - - - public void settings() { - //It'll be empty. Will be overridden by user's sketch class. - } - - - final public int sketchWidth() { - return width; - } - - - final public int sketchHeight() { - return height; - } - - - final public String sketchRenderer() { - return renderer; - } - - - public int sketchSmooth() { - return smooth; - } - - - final public boolean sketchFullScreen() { - return fullScreen; - } - - - final public int sketchDisplay() { - return display; - } - - - final public String sketchOutputPath() { - return null; - } - - - final public OutputStream sketchOutputStream() { - return null; - } - - - final public int sketchWindowColor() { - return windowColor; - } - - - final public int sketchPixelDensity() { - return pixelDensity; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public void surfaceChanged() { - surfaceChanged = true; - g.surfaceChanged(); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Called by the sketch surface view, thought it could conceivably be called - * by Android as well. - */ - public void surfaceWindowFocusChanged(boolean hasFocus) { - focused = hasFocus; - if (focused) { - focusGained(); - } else { - focusLost(); - } - } - - - /** - * If you override this function without calling super.surfaceTouchEvent(), - * then motionX, motionY, motionPressed, and motionEvent will not be set. - */ - public boolean surfaceTouchEvent(MotionEvent event) { - nativeMotionEvent(event); - return true; - } - - - public void surfaceKeyDown(int code, android.view.KeyEvent event) { - nativeKeyEvent(event); - } - - - public void surfaceKeyUp(int code, android.view.KeyEvent event) { - nativeKeyEvent(event); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Called by the browser or applet viewer to inform this applet that it - * should start its execution. It is called after the init method and - * each time the applet is revisited in a Web page. - *

- * Called explicitly via the first call to PApplet.paint(), because - * PAppletGL needs to have a usable screen before getting things rolling. - */ - public void start() { - } - - - /** - * Called by the browser or applet viewer to inform - * this applet that it should stop its execution. - *

- * Unfortunately, there are no guarantees from the Java spec - * when or if stop() will be called (i.e. on browser quit, - * or when moving between web pages), and it's not always called. - */ - public void stop() { - } - - - /** - * Developers can override here to save state. The 'paused' variable will be - * set before this function is called. - */ - public void pause() { - } - - - /** - * Developers can override here to restore state. The 'paused' variable - * will be cleared before this function is called. - */ - public void resume() { - } - - - public void backPressed() { - handledBackPressed = false; - } - - ////////////////////////////////////////////////////////////// - - - /** Map of registered methods, stored by name. */ - HashMap registerMap = - new HashMap(); - - - class RegisteredMethods { - int count; - Object[] objects; - // Because the Method comes from the class being called, - // it will be unique for most, if not all, objects. - Method[] methods; - Object[] emptyArgs = new Object[] { }; - - - void handle() { - handle(emptyArgs); - } - - - void handle(Object[] args) { - for (int i = 0; i < count; i++) { - try { - methods[i].invoke(objects[i], args); - } catch (Exception e) { - // check for wrapped exception, get root exception - Throwable t; - if (e instanceof InvocationTargetException) { - InvocationTargetException ite = (InvocationTargetException) e; - t = ite.getCause(); - } else { - t = e; - } - // check for RuntimeException, and allow to bubble up - if (t instanceof RuntimeException) { - // re-throw exception - throw (RuntimeException) t; - } else { - // trap and print as usual - t.printStackTrace(); - } - } - } - } - - - void add(Object object, Method method) { - if (findIndex(object) == -1) { - if (objects == null) { - objects = new Object[5]; - methods = new Method[5]; - - } else if (count == objects.length) { - objects = (Object[]) PApplet.expand(objects); - methods = (Method[]) PApplet.expand(methods); - } - objects[count] = object; - methods[count] = method; - count++; - } else { - die(method.getName() + "() already added for this instance of " + - object.getClass().getName()); - } - } - - - /** - * Removes first object/method pair matched (and only the first, - * must be called multiple times if object is registered multiple times). - * Does not shrink array afterwards, silently returns if method not found. - */ -// public void remove(Object object, Method method) { -// int index = findIndex(object, method); - public void remove(Object object) { - int index = findIndex(object); - if (index != -1) { - // shift remaining methods by one to preserve ordering - count--; - for (int i = index; i < count; i++) { - objects[i] = objects[i+1]; - methods[i] = methods[i+1]; - } - // clean things out for the gc's sake - objects[count] = null; - methods[count] = null; - } - } - - -// protected int findIndex(Object object, Method method) { - protected int findIndex(Object object) { - for (int i = 0; i < count; i++) { - if (objects[i] == object) { -// if (objects[i] == object && methods[i].equals(method)) { - //objects[i].equals() might be overridden, so use == for safety - // since here we do care about actual object identity - //methods[i]==method is never true even for same method, so must use - // equals(), this should be safe because of object identity - return i; - } - } - return -1; - } - } - - - /** - * Register a built-in event so that it can be fired for libraries, etc. - * Supported events include: - *

    - *
  • pre – at the very top of the draw() method (safe to draw) - *
  • draw – at the end of the draw() method (safe to draw) - *
  • post – after draw() has exited (not safe to draw) - *
  • pause – called when the sketch is paused - *
  • resume – called when the sketch is resumed - *
  • dispose – when the sketch is shutting down (definitely not safe to draw) - *
      - * In addition, the new (for 2.0) processing.event classes are passed to - * the following event types: - *
        - *
      • mouseEvent - *
      • keyEvent - *
      • touchEvent - *
      - * The older java.awt events are no longer supported. - * See the Library Wiki page for more details. - * @param methodName name of the method to be called - * @param target the target object that should receive the event - */ - public void registerMethod(String methodName, Object target) { - if (methodName.equals("mouseEvent")) { - registerWithArgs("mouseEvent", target, new Class[] { processing.event.MouseEvent.class }); - - } else if (methodName.equals("keyEvent")) { - registerWithArgs("keyEvent", target, new Class[] { processing.event.KeyEvent.class }); - - } else if (methodName.equals("touchEvent")) { - registerWithArgs("touchEvent", target, new Class[] { processing.event.TouchEvent.class }); - - // Android-lifecycle event handlers - } else if (methodName.equals("onDestroy")) { - registerNoArgs(methodName, target); - } else if (methodName.equals("onActivityResult")) { - registerWithArgs("onActivityResult", target, new Class[] { int.class, int.class, Intent.class }); - } else if (methodName.equals("onNewIntent")) { - registerWithArgs("onNewIntent", target, new Class[] { Intent.class }); - - } else { - registerNoArgs(methodName, target); - } - } - - - private void registerNoArgs(String name, Object o) { - RegisteredMethods meth = registerMap.get(name); - if (meth == null) { - meth = new RegisteredMethods(); - registerMap.put(name, meth); - } - Class c = o.getClass(); - try { - Method method = c.getMethod(name, new Class[] {}); - meth.add(o, method); - - } catch (NoSuchMethodException nsme) { - die("There is no public " + name + "() method in the class " + - o.getClass().getName()); - - } catch (Exception e) { - die("Could not register " + name + " + () for " + o, e); - } - } - - - private void registerWithArgs(String name, Object o, Class cargs[]) { - RegisteredMethods meth = registerMap.get(name); - if (meth == null) { - meth = new RegisteredMethods(); - registerMap.put(name, meth); - } - Class c = o.getClass(); - try { - Method method = c.getMethod(name, cargs); - meth.add(o, method); - - } catch (NoSuchMethodException nsme) { - die("There is no public " + name + "() method in the class " + - o.getClass().getName()); - - } catch (Exception e) { - die("Could not register " + name + " + () for " + o, e); - } - } - - -// public void registerMethod(String methodName, Object target, Object... args) { -// registerWithArgs(methodName, target, args); -// } - - - public void unregisterMethod(String name, Object target) { - RegisteredMethods meth = registerMap.get(name); - if (meth == null) { - die("No registered methods with the name " + name + "() were found."); - } - try { -// Method method = o.getClass().getMethod(name, new Class[] {}); -// meth.remove(o, method); - meth.remove(target); - } catch (Exception e) { - die("Could not unregister " + name + "() for " + target, e); - } - } - - - protected void handleMethods(String methodName) { - RegisteredMethods meth = registerMap.get(methodName); - if (meth != null) { - meth.handle(); - } - } - - - protected void handleMethods(String methodName, final Object[] args) { - final RegisteredMethods meth = registerMap.get(methodName); - if (meth != null) { - Handler handler = new Handler(Looper.getMainLooper()); - handler.post(new Runnable() { - @Override - public void run() { - meth.handle(args); - } - }); - } - } - - - @Deprecated - public void registerSize(Object o) { - System.err.println("The registerSize() command is no longer supported."); -// Class methodArgs[] = new Class[] { Integer.TYPE, Integer.TYPE }; -// registerWithArgs(sizeMethods, "size", o, methodArgs); - } - - - @Deprecated - public void registerPre(Object o) { - registerNoArgs("pre", o); - } - - - @Deprecated - public void registerDraw(Object o) { - registerNoArgs("draw", o); - } - - - @Deprecated - public void registerPost(Object o) { - registerNoArgs("post", o); - } - - - @Deprecated - public void registerDispose(Object o) { - registerNoArgs("dispose", o); - } - - - @Deprecated - public void unregisterSize(Object o) { - System.err.println("The unregisterSize() command is no longer supported."); -// Class methodArgs[] = new Class[] { Integer.TYPE, Integer.TYPE }; -// unregisterWithArgs(sizeMethods, "size", o, methodArgs); - } - - - @Deprecated - public void unregisterPre(Object o) { - unregisterMethod("pre", o); - } - - - @Deprecated - public void unregisterDraw(Object o) { - unregisterMethod("draw", o); - } - - - @Deprecated - public void unregisterPost(Object o) { - unregisterMethod("post", o); - } - - - @Deprecated - public void unregisterDispose(Object o) { - unregisterMethod("dispose", o); - } - - - ////////////////////////////////////////////////////////////// - - - public void setup() { - } - - - public void draw() { - // if no draw method, then shut things down - //System.out.println("no draw method, goodbye"); - finished = true; - } - - - ////////////////////////////////////////////////////////////// - - -// protected void resizeRenderer(int iwidth, int iheight) { -//// println("resizeRenderer request for " + iwidth + " " + iheight); -// if (width != iwidth || height != iheight) { -//// int left = (screenWidth - iwidth) / 2; -//// int right = screenWidth - (left + iwidth); -//// int top = (screenHeight - iheight) / 2; -//// int bottom = screenHeight - (top + iheight); -//// surfaceView.setPadding(left, top, right, bottom); -// -// g.setSize(iwidth, iheight); -// width = iwidth; -// height = iheight; -// overallLayout.invalidate(); -// layout.invalidate(); -// } -// } - - - /** - * Create a full-screen sketch using the default renderer. - */ - public void fullScreen() { - if (!fullScreen) { - if (insideSettings("fullScreen")) { - this.fullScreen = true; - } - } - } - - - public void fullScreen(int display) { - //Display index doesn't make sense in Android. - //Should we throw some error in log ? - if (!fullScreen /*|| display != this.display*/) { - if (insideSettings("fullScreen", display)) { - this.fullScreen = true; -// this.display = display; - } - } - } - - - public void fullScreen(String renderer) { - if (!fullScreen || - !renderer.equals(this.renderer)) { - if (insideSettings("fullScreen", renderer)) { - this.fullScreen = true; - this.renderer = renderer; - } - } - } - - - public void fullScreen(String renderer, int display) { - if (!fullScreen || - !renderer.equals(this.renderer) /*|| - display != this.display*/) { - if (insideSettings("fullScreen", renderer, display)) { - this.fullScreen = true; - this.renderer = renderer; -// this.display = display; - } - } - } - - - /** - * Starts up and creates a two-dimensional drawing surface, or resizes the - * current drawing surface. - *

      - * This should be the first thing called inside of setup(). - *

      - * If called once a renderer has already been set, this will use the - * previous renderer and simply resize it. - */ - public void size(int iwidth, int iheight) { - if (iwidth != this.width || iheight != this.height) { - if (insideSettings("size", iwidth, iheight)) { - this.width = iwidth; - this.height = iheight; - } - } - } - - - public void size(int iwidth, int iheight, String irenderer) { - if (iwidth != this.width || iheight != this.height || - !this.renderer.equals(irenderer)) { - if (insideSettings("size", iwidth, iheight, irenderer)) { - this.width = iwidth; - this.height = iheight; - this.renderer = irenderer; - } - } - } - - - public void setSize(int width, int height) { - if (fullScreen) { - this.displayWidth = width; - this.displayHeight = height; - } - this.width = width; - this.height = height; - pixelWidth = width * pixelDensity; - pixelHeight = height * pixelDensity; - g.setSize(sketchWidth(), sketchHeight()); - } - - - public void setExternal(boolean external) { - this.external = external; - } - - -//. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public void smooth() { - smooth(1); - } - - - public void smooth(int level) { - if (insideSettings) { - this.smooth = level; - } else if (this.smooth != level) { - smoothWarning("smooth"); - } - } - - - public void noSmooth() { - if (insideSettings) { - this.smooth = 0; - } else if (this.smooth != 0) { - smoothWarning("noSmooth"); - } - } - - private void smoothWarning(String method) { - // When running from the PDE, say setup(), otherwise say settings() - final String where = external ? "setup" : "settings"; - PGraphics.showWarning("%s() can only be used inside %s()", method, where); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public PGraphics getGraphics() { - return g; - } - - public void orientation(int which) { - surface.setOrientation(which); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - // not finished yet--will swap the renderer at a bad time - /* - public void renderer(String name) { - if (name.equals(A2D)) { - if (!(surfaceView instanceof SketchSurfaceView2D)) { - surfaceView = new SketchSurfaceView2D(this); - getWindow().setContentView(surfaceView); // set full screen - } - } else if (name.equals(A3D)) { - if (!(surfaceView instanceof SketchSurfaceView3D)) { - surfaceView = new SketchSurfaceView3D(this); - getWindow().setContentView(surfaceView); // set full screen - } - } - } - */ - - - /** - * Creates a new PGraphics object and sets it to the specified size. - * - * Note that you cannot change the renderer once outside of setup(). - * In most cases, you can call size() to give it a new size, - * but you need to always ask for the same renderer, otherwise - * you're gonna run into trouble. - * - * The size() method should *only* be called from inside the setup() or - * draw() methods, so that it is properly run on the main animation thread. - * To change the size of a PApplet externally, use setSize(), which will - * update the component size, and queue a resize of the renderer as well. - */ - public void size(final int iwidth, final int iheight, - final String irenderer, final String ipath) { - if (iwidth != this.width || iheight != this.height || - !this.renderer.equals(irenderer)) { - if (insideSettings("size", iwidth, iheight, irenderer, - ipath)) { - this.width = iwidth; - this.height = iheight; - this.renderer = irenderer; - } - } - } - - - public PGraphics createGraphics(int iwidth, int iheight) { - return createGraphics(iwidth, iheight, JAVA2D); - } - - - /** - * Create an offscreen PGraphics object for drawing. This can be used - * for bitmap or vector images drawing or rendering. - *

        - *
      • Do not use "new PGraphicsXxxx()", use this method. This method - * ensures that internal variables are set up properly that tie the - * new graphics context back to its parent PApplet. - *
      • The basic way to create bitmap images is to use the saveFrame() - * function. - *
      • If you want to create a really large scene and write that, - * first make sure that you've allocated a lot of memory in the Preferences. - *
      • If you want to create images that are larger than the screen, - * you should create your own PGraphics object, draw to that, and use - * save(). - * For now, it's best to use P3D in this scenario. - * P2D is currently disabled, and the JAVA2D default will give mixed - * results. An example of using P3D: - *
        -   *
        -   * PGraphics big;
        -   *
        -   * void setup() {
        -   *   big = createGraphics(3000, 3000, P3D);
        -   *
        -   *   big.beginDraw();
        -   *   big.background(128);
        -   *   big.line(20, 1800, 1800, 900);
        -   *   // etc..
        -   *   big.endDraw();
        -   *
        -   *   // make sure the file is written to the sketch folder
        -   *   big.save("big.tif");
        -   * }
        -   *
        -   * 
        - *
      • It's important to always wrap drawing to createGraphics() with - * beginDraw() and endDraw() (beginFrame() and endFrame() prior to - * revision 0115). The reason is that the renderer needs to know when - * drawing has stopped, so that it can update itself internally. - * This also handles calling the defaults() method, for people familiar - * with that. - *
      • It's not possible to use createGraphics() with the OPENGL renderer, - * because it doesn't allow offscreen use. - *
      • With Processing 0115 and later, it's possible to write images in - * formats other than the default .tga and .tiff. The exact formats and - * background information can be found in the developer's reference for - * PImage.save(). - *
      - */ - public PGraphics createGraphics(int iwidth, int iheight, String irenderer) { - return makeGraphics(iwidth, iheight, irenderer, false); - } - - - protected PGraphics makeGraphics(int w, int h, - String renderer, boolean primary) { - PGraphics pg = null; - if (renderer.equals(JAVA2D)) { - pg = new PGraphicsAndroid2D(); - } else if (renderer.equals(P2D)) { - if (!primary && !g.isGL()) { - throw new RuntimeException("createGraphics() with P2D requires size() to use P2D or P3D"); - } - pg = new PGraphics2D(); - - } else if (renderer.equals(P3D)) { - if (!primary && !g.isGL()) { - throw new RuntimeException("createGraphics() with P3D or OPENGL requires size() to use P2D or P3D"); - } - pg = new PGraphics3D(); - } else { - Class rendererClass = null; - Constructor constructor = null; - try { - // http://code.google.com/p/android/issues/detail?id=11101 - rendererClass = Thread.currentThread().getContextClassLoader().loadClass(renderer); - } catch (ClassNotFoundException cnfe) { - throw new RuntimeException("Missing renderer class"); - } - - if (rendererClass != null) { - try { - constructor = rendererClass.getConstructor(new Class[] { }); - } catch (NoSuchMethodException nsme) { - throw new RuntimeException("Missing renderer constructor"); - } - - if (constructor != null) { - try { - pg = (PGraphics) constructor.newInstance(); - } catch (InvocationTargetException e) { - printStackTrace(e); - throw new RuntimeException(e.getMessage()); - } catch (IllegalAccessException e) { - printStackTrace(e); - throw new RuntimeException(e.getMessage()); - } catch (InstantiationException e) { - printStackTrace(e); - throw new RuntimeException(e.getMessage()); - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - printStackTrace(e); - } - } - } - } - - pg.setParent(this); - pg.setPrimary(primary); - pg.setSize(w, h); - return pg; - } - - /** - * Create an offscreen graphics surface for drawing, in this case - * for a renderer that writes to a file (such as PDF or DXF). - * @param ipath can be an absolute or relative path - */ -// public PGraphics createGraphics(int iwidth, int iheight, -// String irenderer, String ipath) { -// if (ipath != null) { -// ipath = savePath(ipath); -// } -// PGraphics pg = makeGraphics(iwidth, iheight, irenderer, ipath, false); -// pg.parent = this; // make save() work -// return pg; -// } - - - /** - * Version of createGraphics() used internally. - * - * @param ipath must be an absolute path, usually set via savePath() - * @oaram applet the parent applet object, this should only be non-null - * in cases where this is the main drawing surface object. - */ - /* - protected PGraphics makeGraphics(int iwidth, int iheight, - String irenderer, String ipath, - boolean iprimary) { - try { - Class rendererClass = - Thread.currentThread().getContextClassLoader().loadClass(irenderer); - - Constructor constructor = rendererClass.getConstructor(new Class[] { }); - PGraphics pg = (PGraphics) constructor.newInstance(); - - pg.setParent(this); - pg.setPrimary(iprimary); - if (ipath != null) pg.setPath(ipath); - pg.setSize(iwidth, iheight); - - // everything worked, return it - return pg; - - } catch (InvocationTargetException ite) { - ite.getTargetException().printStackTrace(); - Throwable target = ite.getTargetException(); - throw new RuntimeException(target.getMessage()); - - } catch (ClassNotFoundException cnfe) { - throw new RuntimeException("You need to use \"Import Library\" " + - "to add " + irenderer + " to your sketch."); - } catch (Exception e) { - throw new RuntimeException(e.getMessage()); - } - } - */ - - - /** - * Creates a new PImage (the datatype for storing images). This provides a fresh buffer of pixels to play with. Set the size of the buffer with the width and height parameters. The format parameter defines how the pixels are stored. See the PImage reference for more information. - */ - public PImage createImage(int wide, int high, int format) { -// return createImage(wide, high, format, null); -// } -// -// -// /** -// * Preferred method of creating new PImage objects, ensures that a -// * reference to the parent PApplet is included, which makes save() work -// * without needing an absolute path. -// */ -// public PImage createImage(int wide, int high, int format, Object params) { - PImage image = new PImage(wide, high, format); -// if (params != null) { -// image.setParams(g, params); -// } - image.parent = this; // make save() work - return image; - } - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - // not necessary, ja? -// public void update(Graphics screen) { -// paint(screen); -// } - - - /* - //synchronized public void paint(Graphics screen) { // shutting off for 0146 - public void paint(Graphics screen) { - // ignore the very first call to paint, since it's coming - // from the o.s., and the applet will soon update itself anyway. - if (frameCount == 0) { -// println("Skipping frame"); - // paint() may be called more than once before things - // are finally painted to the screen and the thread gets going - return; - } - - // without ignoring the first call, the first several frames - // are confused because paint() gets called in the midst of - // the initial nextFrame() call, so there are multiple - // updates fighting with one another. - - // g.image is synchronized so that draw/loop and paint don't - // try to fight over it. this was causing a randomized slowdown - // that would cut the frameRate into a third on macosx, - // and is probably related to the windows sluggishness bug too - - // make sure the screen is visible and usable - // (also prevents over-drawing when using PGraphicsOpenGL) - if ((g != null) && (g.image != null)) { -// println("inside paint(), screen.drawImage()"); - screen.drawImage(g.image, 0, 0, null); - } - } - */ - - - // active paint method - /* - protected void paint() { - try { - Graphics screen = this.getGraphics(); - if (screen != null) { - if ((g != null) && (g.image != null)) { - screen.drawImage(g.image, 0, 0, null); - } - Toolkit.getDefaultToolkit().sync(); - } - } catch (Exception e) { - // Seen on applet destroy, maybe can ignore? - e.printStackTrace(); - - } finally { - if (g != null) { - g.dispose(); - } - } - } - */ - - - ////////////////////////////////////////////////////////////// - - -/* - public void run() { // not good to make this synchronized, locks things up - long beforeTime = System.nanoTime(); - long overSleepTime = 0L; - - int noDelays = 0; - // Number of frames with a delay of 0 ms before the - // animation thread yields to other running threads. - final int NO_DELAYS_PER_YIELD = 15; - - while (!finished) { - - while (paused) { - try{ - Thread.sleep(100L); - } catch (InterruptedException e) { - //ignore? - } - } - - // render a single frame - if (g != null) g.requestDraw(); - - // wait for update & paint to happen before drawing next frame - // this is necessary since the drawing is sometimes in a - // separate thread, meaning that the next frame will start - // before the update/paint is completed - - long afterTime = System.nanoTime(); - long timeDiff = afterTime - beforeTime; - //System.out.println("time diff is " + timeDiff); - long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime; - - if (sleepTime > 0) { // some time left in this cycle - try { -// Thread.sleep(sleepTime / 1000000L); // nanoseconds -> milliseconds - Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L)); - noDelays = 0; // Got some sleep, not delaying anymore - } catch (InterruptedException ex) { } - - overSleepTime = (System.nanoTime() - afterTime) - sleepTime; - //System.out.println(" oversleep is " + overSleepTime); - - } else { // sleepTime <= 0; the frame took longer than the period -// excess -= sleepTime; // store excess time value - overSleepTime = 0L; - - if (noDelays > NO_DELAYS_PER_YIELD) { - Thread.yield(); // give another thread a chance to run - noDelays = 0; - } - } - - beforeTime = System.nanoTime(); - } - - // if this isn't just a pause, shut it all down - if (!paused) { - stop(); // call to shutdown libs? - - // If the user called the exit() function, the window should close, - // rather than the sketch just halting. - if (exitCalled) { - exitActual(); - } - } - } -*/ - - public void handleDraw() { - //debug("handleDraw() " + g + " " + looping + " " + redraw + " valid:" + this.isValid() + " visible:" + this.isVisible()); - - if (g == null) return; - - if (!surfaceChanged && parentLayout != -1) { - // When using a parent layout, don't start drawing until the sketch - // has been properly sized. - return; - } - - if (!looping && !redraw) return; - - if (insideDraw) { - System.err.println("handleDraw() called before finishing"); - System.exit(1); - } - - insideDraw = true; - -// if (recorder != null) { -// recorder.beginDraw(); -// } - - if (handleSpecialDraw()) return; - - g.beginDraw(); - - long now = System.nanoTime(); - - if (frameCount == 0) { - setup(); - - } else { // frameCount > 0, meaning an actual draw() - // update the current frameRate - double rate = 1000000.0 / ((now - frameRateLastNanos) / 1000000.0); - float instantaneousRate = (float) (rate / 1000.0); - frameRate = (frameRate * 0.9f) + (instantaneousRate * 0.1f); - - if (frameCount != 0) { - handleMethods("pre"); - } - - // use dmouseX/Y as previous mouse pos, since this is the - // last position the mouse was in during the previous draw. - pmouseX = dmouseX; - pmouseY = dmouseY; - - draw(); - - // dmouseX/Y is updated only once per frame (unlike emouseX/Y) - dmouseX = mouseX; - dmouseY = mouseY; - - // these are called *after* loop so that valid - // drawing commands can be run inside them. it can't - // be before, since a call to background() would wipe - // out anything that had been drawn so far. - dequeueEvents(); - - handleMethods("draw"); - handlePermissions(); - handleBackPressed(); - - redraw = false; // unset 'redraw' flag in case it was set - // (only do this once draw() has run, not just setup()) - } - g.endDraw(); - -// if (recorder != null) { -// recorder.endDraw(); -// } - insideDraw = false; - - if (frameCount != 0) { - handleMethods("post"); - } - - frameRateLastNanos = now; - frameCount++; - } - - - // This method handles some special situations on Android where beginDraw/endDraw are needed, - // but not to render the actual contents of draw(). In general, these situations arise from - // having to refresh/restore the screen after requesting no loop, or resuming the sketch in - // no-loop state. - protected boolean handleSpecialDraw() { - boolean handled = false; - - if (g.restoringState()) { - // The sketch is restoring, so begin/end the frame properly and quit drawing. - g.beginDraw(); - g.endDraw(); - - handled = true; - } else if (g.requestedNoLoop) { - // noLoop() was called sometime in the previous frame with a GL renderer, but only now - // we are sure that the frame is properly displayed. - looping = false; - - // Perform a full frame draw, to ensure that the previous frame is properly displayed (see - // comment in the declaration of requestedNoLoop). - g.beginDraw(); - g.endDraw(); - - g.requestedNoLoop = false; - handled = true; - } - - if (handled) { - insideDraw = false; - return true; - } else { - return false; - } - } - - - ////////////////////////////////////////////////////////////// - - - synchronized public void redraw() { - if (!looping) { - redraw = true; -// if (thread != null) { -// // wake from sleep (necessary otherwise it'll be -// // up to 10 seconds before update) -// if (CRUSTY_THREADS) { -// thread.interrupt(); -// } else { -// synchronized (blocker) { -// blocker.notifyAll(); -// } -// } -// } - } - } - - - synchronized public void loop() { - if (!looping) { - looping = true; - } - } - - - synchronized public void noLoop() { - if (looping) { - if (g.requestNoLoop()) { - g.requestedNoLoop = true; - } else { - looping = false; - } - } - } - - - public boolean isLooping() { - return looping; - } - - - ////////////////////////////////////////////////////////////// - - - // all these are handled in SurfaceView, which is a listener for all of em -// public void addListeners() { -// addMouseListener(this); -// addMouseMotionListener(this); -// addKeyListener(this); -// addFocusListener(this); -// -// addComponentListener(new ComponentAdapter() { -// public void componentResized(ComponentEvent e) { -// Component c = e.getComponent(); -// //System.out.println("componentResized() " + c); -// Rectangle bounds = c.getBounds(); -// resizeRequest = true; -// resizeWidth = bounds.width; -// resizeHeight = bounds.height; -// } -// }); -// } - - - ////////////////////////////////////////////////////////////// - - - InternalEventQueue eventQueue = new InternalEventQueue(); - - - class InternalEventQueue { - protected Event queue[] = new Event[10]; - protected int offset; - protected int count; - - synchronized void add(Event e) { - if (count == queue.length) { - queue = (Event[]) expand(queue); - } - queue[count++] = e; - } - - synchronized Event remove() { - if (offset == count) { - throw new RuntimeException("Nothing left on the event queue."); - } - Event outgoing = queue[offset++]; - if (offset == count) { - // All done, time to reset - offset = 0; - count = 0; - } - return outgoing; - } - - synchronized boolean available() { - return count != 0; - } - } - - /** - * Add an event to the internal event queue, or process it immediately if - * the sketch is not currently looping. - */ - public void postEvent(processing.event.Event pe) { - eventQueue.add(pe); - - if (!looping) { - dequeueEvents(); - } - } - - - protected void dequeueEvents() { - while (eventQueue.available()) { - Event e = eventQueue.remove(); - - switch (e.getFlavor()) { - case Event.TOUCH: - handleTouchEvent((TouchEvent) e); - break; - case Event.MOUSE: - handleMouseEvent((MouseEvent) e); - break; - case Event.KEY: - handleKeyEvent((KeyEvent) e); - break; - } - } - } - - - ////////////////////////////////////////////////////////////// - - - protected void handleMouseEvent(MouseEvent event) { -// mouseEvent = event; - - // http://dev.processing.org/bugs/show_bug.cgi?id=170 - // also prevents mouseExited() on the mac from hosing the mouse - // position, because x/y are bizarre values on the exit event. - // see also the id check below.. both of these go together -// if ((id == java.awt.event.MouseEvent.MOUSE_DRAGGED) || -// (id == java.awt.event.MouseEvent.MOUSE_MOVED)) { - if (event.getAction() == MouseEvent.DRAG || - event.getAction() == MouseEvent.MOVE) { - pmouseX = emouseX; - pmouseY = emouseY; - mouseX = event.getX(); - mouseY = event.getY(); - } - - // Because we only get DRAGGED (and no MOVED) events, pmouseX/Y will make - // things jump because they aren't updated while a finger isn't on the - // screen. This makes for weirdness with the continuous lines example, - // causing it to jump. Since we're emulating the mouse here, do the right - // thing for mouse events. It breaks the situation where random taps/clicks - // to the screen won't show up as 'previous' values, but that's probably - // less common. -// if (event.getAction() == MouseEvent.PRESS) { -// System.out.println("resetting"); -//// pmouseX = event.getX(); -//// pmouseY = event.getY(); -// firstMotion = true; -// } - - // Get the (already processed) button code - mouseButton = event.getButton(); - - // Added in 0215 (2.0b7) so that pmouseX/Y behave more like one would - // expect from the desktop. This makes the ContinousLines example behave. - if (event.getAction() == MouseEvent.PRESS) { - mouseX = event.getX(); - mouseY = event.getY(); - pmouseX = mouseX; - pmouseY = mouseY; - dmouseX = mouseX; - dmouseY = mouseY; - } - -// if (event.getAction() == MouseEvent.RELEASE) { -// mouseX = event.getX(); -// mouseY = event.getY(); -// } - -// mouseEvent = event; - - // Do this up here in case a registered method relies on the - // boolean for mousePressed. - - switch (event.getAction()) { - case MouseEvent.PRESS: - mousePressed = true; - break; - case MouseEvent.RELEASE: - mousePressed = false; - break; - } - - handleMethods("mouseEvent", new Object[] { event }); - - switch (event.getAction()) { - case MouseEvent.PRESS: - mousePressed(event); - break; - case MouseEvent.RELEASE: - mouseReleased(event); - break; - case MouseEvent.CLICK: - mouseClicked(event); - break; - case MouseEvent.DRAG: - mouseDragged(event); - break; - case MouseEvent.MOVE: - mouseMoved(event); - break; - case MouseEvent.ENTER: - mouseEntered(event); - break; - case MouseEvent.EXIT: - mouseExited(event); - break; - } - - if ((event.getAction() == MouseEvent.DRAG) || - (event.getAction() == MouseEvent.MOVE)) { - emouseX = mouseX; - emouseY = mouseY; - } - if (event.getAction() == MouseEvent.PRESS) { // Android-only - emouseX = mouseX; - emouseY = mouseY; - } -// if (event.getAction() == MouseEvent.RELEASE) { // Android-only -// emouseX = mouseX; -// emouseY = mouseY; -// } - } - - - protected void handleTouchEvent(TouchEvent event) { - touches = event.getTouches(touches); - - switch (event.getAction()) { - case TouchEvent.START: - touchIsStarted = true; - break; - case TouchEvent.END: - touchIsStarted = false; - break; - } - - handleMethods("touchEvent", new Object[] { event }); - - switch (event.getAction()) { - case TouchEvent.START: - touchStarted(event); - break; - case TouchEvent.END: - touchEnded(event); - break; - case TouchEvent.MOVE: - touchMoved(event); - break; - case TouchEvent.CANCEL: - touchCancelled(event); - break; - } - } - - - /** - * Figure out how to process a mouse event. When loop() has been - * called, the events will be queued up until drawing is complete. - * If noLoop() has been called, then events will happen immediately. - */ - protected void nativeMotionEvent(MotionEvent motionEvent) { - int metaState = motionEvent.getMetaState(); - int modifiers = 0; - if ((metaState & android.view.KeyEvent.META_SHIFT_ON) != 0) { - modifiers |= Event.SHIFT; - } - if ((metaState & android.view.KeyEvent.META_CTRL_ON) != 0) { - modifiers |= Event.CTRL; - } - if ((metaState & android.view.KeyEvent.META_META_ON) != 0) { - modifiers |= Event.META; - } - if ((metaState & android.view.KeyEvent.META_ALT_ON) != 0) { - modifiers |= Event.ALT; - } - - int button; - int state = motionEvent.getButtonState(); - switch (state) { - case MotionEvent.BUTTON_PRIMARY: - button = LEFT; - break; - case MotionEvent.BUTTON_SECONDARY: - button = RIGHT; - break; - case MotionEvent.BUTTON_TERTIARY: - button = CENTER; - break; - default: - // Covers the BUTTON_FORWARD, BUTTON_BACK, - // BUTTON_STYLUS_PRIMARY, and BUTTON_STYLUS_SECONDARY - button = state; - } - - enqueueMouseEvents(motionEvent, button, modifiers); - enqueueTouchEvents(motionEvent, button, modifiers); - } - - - protected void enqueueTouchEvents(MotionEvent event, int button, int modifiers) { - int actionMasked = event.getActionMasked(); - int pAction = 0; - int pointerUp = 0; - int pointerUpIdx = -1; - switch (actionMasked) { - case MotionEvent.ACTION_DOWN: - pAction = TouchEvent.START; - break; - case MotionEvent.ACTION_POINTER_DOWN: - pAction = TouchEvent.START; - break; - case MotionEvent.ACTION_MOVE: - pAction = TouchEvent.MOVE; - break; - case MotionEvent.ACTION_UP: - pAction = TouchEvent.END; - break; - case MotionEvent.ACTION_POINTER_UP: - pAction = TouchEvent.END; - pointerUp = 1; - // We get the index of the pointer that is being released: - // https://developer.android.com/reference/android/view/MotionEvent#getActionIndex() - pointerUpIdx = event.getActionIndex(); - break; - default: - // Covers any other action value, including ACTION_CANCEL - pAction = TouchEvent.CANCEL; - break; - } - - if (pAction == TouchEvent.START || pAction == TouchEvent.END || pAction == TouchEvent.CANCEL) { - touchPointerId = event.getPointerId(0); - } - - // getPointerCount() will return the count including the pointer that is being released, so - // we substract 1 if if this current event is a pointer up - int activePointerCount = event.getPointerCount() - pointerUp; - - if (actionMasked == MotionEvent.ACTION_MOVE) { - // Post historical movement events, if any. - int historySize = event.getHistorySize(); - for (int h = 0; h < historySize; h++) { - TouchEvent touchEvent = new TouchEvent(event, event.getHistoricalEventTime(h), - pAction, modifiers, button); - touchEvent.setNumPointers(activePointerCount); - int p = 0; - for (int idx = 0; idx < event.getPointerCount(); idx++) { - if (idx == pointerUpIdx) continue; // Skip the released pointer - touchEvent.setPointer(p++, event.getPointerId(idx), event.getHistoricalX(idx, h), event.getHistoricalY(idx, h), - event.getHistoricalSize(idx, h), event.getHistoricalPressure(idx, h)); - } - postEvent(touchEvent); - } - } - - // Current event - TouchEvent touchEvent = new TouchEvent(event, event.getEventTime(), - pAction, modifiers, button); - if (actionMasked == MotionEvent.ACTION_UP || actionMasked == MotionEvent.ACTION_CANCEL) { - // Last pointer up - touchEvent.setNumPointers(0); - } else { - // We still have some pointers left - touchEvent.setNumPointers(activePointerCount); - int p = 0; - for (int idx = 0; idx < event.getPointerCount(); idx++) { - if (idx == pointerUpIdx) continue; // Skip the released pointer - touchEvent.setPointer(p++, event.getPointerId(idx), event.getX(idx), event.getY(idx), - event.getSize(idx), event.getPressure(idx)); - } - } - postEvent(touchEvent); - } - - - protected void enqueueMouseEvents(MotionEvent event, int button, int modifiers) { - int actionMasked = event.getActionMasked(); - - int clickCount = 1; // not really set... (i.e. not catching double taps) - int index; - - switch (actionMasked) { - case MotionEvent.ACTION_DOWN: - mousePointerId = event.getPointerId(0); - postEvent(new MouseEvent(event, event.getEventTime(), - MouseEvent.PRESS, modifiers, - (int) event.getX(), (int) event.getY(), - button, clickCount)); - break; - case MotionEvent.ACTION_MOVE: - index = event.findPointerIndex(mousePointerId); - if (index != -1) { - postEvent(new MouseEvent(event, event.getEventTime(), - MouseEvent.DRAG, modifiers, - (int) event.getX(index), (int) event.getY(index), - button, clickCount)); - } - break; - case MotionEvent.ACTION_UP: - index = event.findPointerIndex(mousePointerId); - if (index != -1) { - postEvent(new MouseEvent(event, event.getEventTime(), - MouseEvent.RELEASE, modifiers, - (int) event.getX(index), (int) event.getY(index), - button, clickCount)); - } - break; - } - } - - public void mousePressed() { } - - - public void mousePressed(MouseEvent event) { - mousePressed(); - } - - - public void mouseReleased() { } - - - public void mouseReleased(MouseEvent event) { - mouseReleased(); - } - - - /** - * mouseClicked is currently not fired at all (no direct match on Android). - * http://code.google.com/p/processing/issues/detail?id=215 - */ - public void mouseClicked() { } - - - public void mouseClicked(MouseEvent event) { - mouseClicked(); - } - - - public void mouseDragged() { } - - - public void mouseDragged(MouseEvent event) { - mouseDragged(); - } - - - public void mouseMoved() { } - - - public void mouseMoved(MouseEvent event) { - mouseMoved(); - } - - - public void mouseEntered() { } - - - public void mouseEntered(MouseEvent event) { - mouseEntered(); - } - - - public void mouseExited() { } - - - public void mouseExited(MouseEvent event) { - mouseExited(); - } - - - public void touchStarted() { } - - - public void touchStarted(TouchEvent event) { - touchStarted(); - } - - - public void touchMoved() { } - - - public void touchMoved(TouchEvent event) { - touchMoved(); - } - - - public void touchEnded() { } - - - public void touchEnded(TouchEvent event) { - touchEnded(); - } - - - public void touchCancelled() { } - - - public void touchCancelled(TouchEvent event) { - touchCancelled(); - } - - - ////////////////////////////////////////////////////////////// - - -// KeyEvent[] keyEventQueue = new KeyEvent[10]; -// int keyEventCount; -// -// protected void enqueueKeyEvent(KeyEvent e) { -// synchronized (keyEventQueue) { -// if (keyEventCount == keyEventQueue.length) { -// keyEventQueue = (KeyEvent[]) expand(keyEventQueue); -// } -// keyEventQueue[keyEventCount++] = e; -// } -// } -// -// protected void dequeueKeyEvents() { -// synchronized (keyEventQueue) { -// for (int i = 0; i < keyEventCount; i++) { -// handleKeyEvent(keyEventQueue[i]); -// } -// keyEventCount = 0; -// } -// } - - - protected void handleKeyEvent(KeyEvent event) { - - // Get rid of auto-repeating keys if desired and supported - if (!keyRepeatEnabled && event.isAutoRepeat()) return; - -// keyEvent = event; - key = event.getKey(); - keyCode = event.getKeyCode(); - - switch (event.getAction()) { - case KeyEvent.PRESS: - keyPressed = true; - keyPressed(event); - break; - case KeyEvent.RELEASE: - keyPressed = false; - keyReleased(event); - break; - } - - handleMethods("keyEvent", new Object[] { event }); - } - - - protected void nativeKeyEvent(android.view.KeyEvent event) { - // event.isPrintingKey() returns false for whitespace and others, - // which is a problem if the space bar or tab key are used. - char key = (char) event.getUnicodeChar(); - // if not mappable to a unicode character, instead mark as coded key - if (key == 0 || key == 0xFFFF) { - key = CODED; - } - - int keyCode = event.getKeyCode(); - - int keAction = 0; - int action = event.getAction(); - if (action == android.view.KeyEvent.ACTION_DOWN) { - keAction = KeyEvent.PRESS; - } else if (action == android.view.KeyEvent.ACTION_UP) { - keAction = KeyEvent.RELEASE; - } - - // TODO set up proper key modifier handling - int keModifiers = 0; - - KeyEvent ke = new KeyEvent(event, event.getEventTime(), - keAction, keModifiers, key, keyCode, 0 < event.getRepeatCount()); - - postEvent(ke); - } - - - public void openKeyboard() { - Context context = surface.getContext(); - InputMethodManager imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); - imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0); - keyboardIsOpen = true; - } - - - public void closeKeyboard() { - if (keyboardIsOpen) { - Context context = surface.getContext(); - InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); - imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); - keyboardIsOpen = false; - if (parentLayout == -1) { - setFullScreenVisibility(); - } - } - } - - - public void keyPressed() { } - - - public void keyPressed(KeyEvent event) { - keyPressed(); - } - - - /** - * See keyPressed(). - */ - public void keyReleased() { } - - - public void keyReleased(KeyEvent event) { - keyReleased(); - } - - - public void keyTyped() { } - - - public void keyTyped(KeyEvent event) { - keyTyped(); - } - - - ////////////////////////////////////////////////////////////// - - - public void focusGained() { } - -// public void focusGained(FocusEvent e) { -// focused = true; -// focusGained(); -// } - - - public void focusLost() { } - -// public void focusLost(FocusEvent e) { -// focused = false; -// focusLost(); -// } - - - ////////////////////////////////////////////////////////////// - - // getting the time - - - /** - * Get the number of milliseconds since the applet started. - *

      - * This is a function, rather than a variable, because it may - * change multiple times per frame. - */ - public int millis() { - return (int) (System.currentTimeMillis() - millisOffset); - } - - /** Seconds position of the current time. */ - static public int second() { - return Calendar.getInstance().get(Calendar.SECOND); - } - - /** Minutes position of the current time. */ - static public int minute() { - return Calendar.getInstance().get(Calendar.MINUTE); - } - - /** - * Hour position of the current time in international format (0-23). - *

      - * To convert this value to American time:
      - *

      int yankeeHour = (hour() % 12);
      -   * if (yankeeHour == 0) yankeeHour = 12;
      - */ - static public int hour() { - return Calendar.getInstance().get(Calendar.HOUR_OF_DAY); - } - - /** - * Get the current day of the month (1 through 31). - *

      - * If you're looking for the day of the week (M-F or whatever) - * or day of the year (1..365) then use java's Calendar.get() - */ - static public int day() { - return Calendar.getInstance().get(Calendar.DAY_OF_MONTH); - } - - /** - * Get the current month in range 1 through 12. - */ - static public int month() { - // months are number 0..11 so change to colloquial 1..12 - return Calendar.getInstance().get(Calendar.MONTH) + 1; - } - - /** - * Get the current year. - */ - static public int year() { - return Calendar.getInstance().get(Calendar.YEAR); - } - - - ////////////////////////////////////////////////////////////// - - // controlling time (playing god) - - - /** - * The delay() function causes the program to halt for a specified time. - * Delay times are specified in thousandths of a second. For example, - * running delay(3000) will stop the program for three seconds and - * delay(500) will stop the program for a half-second. - * - * The screen only updates when the end of draw() is reached, so delay() - * cannot be used to slow down drawing. For instance, you cannot use delay() - * to control the timing of an animation. - * - * The delay() function should only be used for pausing scripts (i.e. - * a script that needs to pause a few seconds before attempting a download, - * or a sketch that needs to wait a few milliseconds before reading from - * the serial port). - */ - public void delay(int napTime) { - //if (frameCount != 0) { - //if (napTime > 0) { - try { - Thread.sleep(napTime); - } catch (InterruptedException e) { } - //} - //} - } - - - /** - * ( begin auto-generated from frameRate.xml ) - * - * Specifies the number of frames to be displayed every second. If the - * processor is not fast enough to maintain the specified rate, it will not - * be achieved. For example, the function call frameRate(30) will - * attempt to refresh 30 times a second. It is recommended to set the frame - * rate within setup(). The default rate is 60 frames per second. - * - * ( end auto-generated ) - */ - public void frameRate(float fps) { -// -// frameRateTarget = newRateTarget; -// frameRatePeriod = (long) (1000000000.0 / frameRateTarget); -// g.setFrameRate(newRateTarget); - surface.setFrameRate(fps); - } - - - ////////////////////////////////////////////////////////////// - - - /** - * Get a param from the web page, or (eventually) - * from a properties file. - */ -// public String param(String what) { -// if (online) { -// return getParameter(what); -// -// } else { -// System.err.println("param() only works inside a web browser"); -// } -// return null; -// } - - - /** - * Show status in the status bar of a web browser, or in the - * System.out console. Eventually this might show status in the - * p5 environment itself, rather than relying on the console. - */ -// public void status(String what) { -// if (online) { -// showStatus(what); -// -// } else { -// System.out.println(what); // something more interesting? -// } -// } - - - public void link(String here) { - link(here, null); - } - - - /** - * Link to an external page without all the muss. - *

      - * When run with an applet, uses the browser to open the url, - * for applications, attempts to launch a browser with the url. - *

      - * Works on Mac OS X and Windows. For Linux, use: - *

      open(new String[] { "firefox", url });
      - * or whatever you want as your browser, since Linux doesn't - * yet have a standard method for launching URLs. - */ - public void link(String url, String frameTitle) { - Intent viewIntent = new Intent("android.intent.action.VIEW", Uri.parse(url)); - surface.startActivity(viewIntent); - } - - - /** - * Attempt to open a file using the platform's shell. - */ - static public void open(String filename) { - open(new String[] { filename }); - } - - - /** - * Launch a process using a platforms shell. This version uses an array - * to make it easier to deal with spaces in the individual elements. - * (This avoids the situation of trying to put single or double quotes - * around different bits). - */ - static public Process open(String argv[]) { - return exec(argv); - } - - - static public Process exec(String[] argv) { - try { - return Runtime.getRuntime().exec(argv); - } catch (Exception e) { - throw new RuntimeException("Could not open " + join(argv, ' ')); - } - } - - - ////////////////////////////////////////////////////////////// - - - /** - * Better way of handling e.printStackTrace() calls so that they can be - * handled by subclasses as necessary. - */ - protected void printStackTrace(Throwable t) { - t.printStackTrace(); - } - - - /** - * Function for an applet/application to kill itself and - * display an error. Mostly this is here to be improved later. - */ - public void die(String what) { - stop(); - throw new RuntimeException(what); - } - - - /** - * Same as above but with an exception. Also needs work. - */ - public void die(String what, Exception e) { - if (e != null) e.printStackTrace(); - die(what); - } - - - /** - * Conveniency method so perform initialization tasks when the activity is - * created, while avoiding the ackward call to onCreate() with the bundle - * and super.onCreate(). - */ - public void create() { - - } - - /** - * Should trigger a graceful activity/service shutdown (calling onPause/onStop, etc). - */ - public void exit() { - surface.finish(); - } - - - /** - * Called to dispose of resources and shut down the sketch. - * Destroys the thread, dispose the renderer, and notify listeners. - *

      - * Not to be called or overriden by users. If called multiple times, - * will only notify listeners once. Register a dispose listener instead. - */ - final public void dispose() { - // moved here from stop() - finished = true; // let the sketch know it is shut down time - - // call to shut down renderer, in case it needs it (pdf does) - if (surface != null) { - surface.stopThread(); - surface.dispose(); - } - if (g != null) { - g.clearState(); // This should probably go in dispose, but for the time being... - g.dispose(); - } - - handleMethods("dispose"); - } - - - - ////////////////////////////////////////////////////////////// - - - /** - * Call a method in the current class based on its name. - *

      - * Note that the function being called must be public. Inside the PDE, - * 'public' is automatically added, but when used without the preprocessor, - * (like from Eclipse) you'll have to do it yourself. - */ - public void method(String name) { - try { - Method method = getClass().getMethod(name, new Class[] {}); - method.invoke(this, new Object[] { }); - - } catch (IllegalArgumentException e) { - printStackTrace(e); - } catch (IllegalAccessException e) { - printStackTrace(e); - } catch (InvocationTargetException e) { - e.getTargetException().printStackTrace(); - } catch (NoSuchMethodException nsme) { - System.err.println("There is no public " + name + "() method " + - "in the class " + getClass().getName()); - } catch (Exception e) { - printStackTrace(e); - } - } - - - /** - * Launch a new thread and call the specified function from that new thread. - * This is a very simple way to do a thread without needing to get into - * classes, runnables, etc. - *

      - * Note that the function being called must be public. Inside the PDE, - * 'public' is automatically added, but when used without the preprocessor, - * (like from Eclipse) you'll have to do it yourself. - */ - public void thread(final String name) { - Thread later = new Thread() { - @Override - public void run() { - method(name); - } - }; - later.start(); - } - - - - ////////////////////////////////////////////////////////////// - - // SCREEN GRABASS - - - /** - * Intercepts any relative paths to make them absolute (relative - * to the sketch folder) before passing to save() in PImage. - * (Changed in 0100) - */ - public void save(String filename) { - g.save(savePath(filename)); - } - - - /** - * Grab an image of what's currently in the drawing area and save it - * as a .tif or .tga file. - *

      - * Best used just before endDraw() at the end of your draw(). - * This can only create .tif or .tga images, so if neither extension - * is specified it defaults to writing a tiff and adds a .tif suffix. - */ - public void saveFrame() { - try { - g.save(savePath("screen-" + nf(frameCount, 4) + ".tif")); - } catch (SecurityException se) { - System.err.println("Can't use saveFrame() when running in a browser, " + - "unless using a signed applet."); - } - } - - - /** - * Save the current frame as a .tif or .tga image. - *

      - * The String passed in can contain a series of # signs - * that will be replaced with the screengrab number. - *

      -   * i.e. saveFrame("blah-####.tif");
      -   *      // saves a numbered tiff image, replacing the
      -   *      // #### signs with zeros and the frame number 
      - */ - public void saveFrame(String what) { - try { - g.save(savePath(insertFrame(what))); - } catch (SecurityException se) { - System.err.println("Can't use saveFrame() when running in a browser, " + - "unless using a signed applet."); - } - } - - - /** - * Check a string for #### signs to see if the frame number should be - * inserted. Used for functions like saveFrame() and beginRecord() to - * replace the # marks with the frame number. If only one # is used, - * it will be ignored, under the assumption that it's probably not - * intended to be the frame number. - */ - protected String insertFrame(String what) { - int first = what.indexOf('#'); - int last = what.lastIndexOf('#'); - - if ((first != -1) && (last - first > 0)) { - String prefix = what.substring(0, first); - int count = last - first + 1; - String suffix = what.substring(last + 1); - return prefix + nf(frameCount, count) + suffix; - } - return what; // no change - } - - - - ////////////////////////////////////////////////////////////// - - // CURSOR - - // Removed, this doesn't make sense in a touch interface. - - -// int cursorType = ARROW; // cursor type -// boolean cursorVisible = true; // cursor visibility flag -// PImage invisibleCursor; - - - /** - * Set the cursor type - */ -// public void cursor(int cursorType) { -// setCursor(Cursor.getPredefinedCursor(cursorType)); -// cursorVisible = true; -// this.cursorType = cursorType; -// } - - - /** - * Replace the cursor with the specified PImage. The x- and y- - * coordinate of the center will be the center of the image. - */ -// public void cursor(PImage image) { -// cursor(image, image.width/2, image.height/2); -// } - - - /** - * Set a custom cursor to an image with a specific hotspot. - * Only works with JDK 1.2 and later. - * Currently seems to be broken on Java 1.4 for Mac OS X - *

      - * Based on code contributed by Amit Pitaru, plus additional - * code to handle Java versions via reflection by Jonathan Feinberg. - * Reflection removed for release 0128 and later. - */ -// public void cursor(PImage image, int hotspotX, int hotspotY) { -// // don't set this as cursor type, instead use cursor_type -// // to save the last cursor used in case cursor() is called -// //cursor_type = Cursor.CUSTOM_CURSOR; -// Image jimage = -// createImage(new MemoryImageSource(image.width, image.height, -// image.pixels, 0, image.width)); -// Point hotspot = new Point(hotspotX, hotspotY); -// Toolkit tk = Toolkit.getDefaultToolkit(); -// Cursor cursor = tk.createCustomCursor(jimage, hotspot, "Custom Cursor"); -// setCursor(cursor); -// cursorVisible = true; -// } - - - /** - * Show the cursor after noCursor() was called. - * Notice that the program remembers the last set cursor type - */ -// public void cursor() { -// // maybe should always set here? seems dangerous, since -// // it's likely that java will set the cursor to something -// // else on its own, and the applet will be stuck b/c bagel -// // thinks that the cursor is set to one particular thing -// if (!cursorVisible) { -// cursorVisible = true; -// setCursor(Cursor.getPredefinedCursor(cursorType)); -// } -// } - - - /** - * Hide the cursor by creating a transparent image - * and using it as a custom cursor. - */ -// public void noCursor() { -// if (!cursorVisible) return; // don't hide if already hidden. -// -// if (invisibleCursor == null) { -// invisibleCursor = new PImage(16, 16, ARGB); -// } -// // was formerly 16x16, but the 0x0 was added by jdf as a fix -// // for macosx, which wasn't honoring the invisible cursor -// cursor(invisibleCursor, 8, 8); -// cursorVisible = false; -// } - - - ////////////////////////////////////////////////////////////// - - - static public void print(byte what) { - System.out.print(what); - System.out.flush(); - } - - static public void print(boolean what) { - System.out.print(what); - System.out.flush(); - } - - static public void print(char what) { - System.out.print(what); - System.out.flush(); - } - - static public void print(int what) { - System.out.print(what); - System.out.flush(); - } - - static public void print(float what) { - System.out.print(what); - System.out.flush(); - } - - static public void print(String what) { - System.out.print(what); - System.out.flush(); - } - - /** - * @param variables list of data, separated by commas - */ - static public void print(Object... variables) { - StringBuilder sb = new StringBuilder(); - for (Object o : variables) { - if (sb.length() != 0) { - sb.append(" "); - } - if (o == null) { - sb.append("null"); - } else { - sb.append(o.toString()); - } - } - System.out.print(sb.toString()); - } - - /* - static public void print(Object what) { - if (what == null) { - // special case since this does fuggly things on > 1.1 - System.out.print("null"); - } else { - System.out.println(what.toString()); - } - } - */ - - // - - static public void println() { - System.out.println(); - } - - // - - static public void println(byte what) { - print(what); System.out.println(); - } - - static public void println(boolean what) { - print(what); System.out.println(); - } - - static public void println(char what) { - print(what); System.out.println(); - } - - static public void println(int what) { - print(what); System.out.println(); - } - - static public void println(float what) { - print(what); System.out.println(); - } - - static public void println(String what) { - print(what); System.out.println(); - } - - /** - * @param variables list of data, separated by commas - */ - static public void println(Object... variables) { -// System.out.println("got " + variables.length + " variables"); - print(variables); - println(); - } - - static public void println(Object what) { - if (what == null) { - // special case since this does fuggly things on > 1.1 - System.out.println("null"); - - } else { - String name = what.getClass().getName(); - if (name.charAt(0) == '[') { - switch (name.charAt(1)) { - case '[': - // don't even mess with multi-dimensional arrays (case '[') - // or anything else that's not int, float, boolean, char - System.out.println(what); - break; - - case 'L': - // print a 1D array of objects as individual elements - Object poo[] = (Object[]) what; - for (int i = 0; i < poo.length; i++) { - if (poo[i] instanceof String) { - System.out.println("[" + i + "] \"" + poo[i] + "\""); - } else { - System.out.println("[" + i + "] " + poo[i]); - } - } - break; - - case 'Z': // boolean - boolean zz[] = (boolean[]) what; - for (int i = 0; i < zz.length; i++) { - System.out.println("[" + i + "] " + zz[i]); - } - break; - - case 'B': // byte - byte bb[] = (byte[]) what; - for (int i = 0; i < bb.length; i++) { - System.out.println("[" + i + "] " + bb[i]); - } - break; - - case 'C': // char - char cc[] = (char[]) what; - for (int i = 0; i < cc.length; i++) { - System.out.println("[" + i + "] '" + cc[i] + "'"); - } - break; - - case 'I': // int - int ii[] = (int[]) what; - for (int i = 0; i < ii.length; i++) { - System.out.println("[" + i + "] " + ii[i]); - } - break; - - case 'F': // float - float ff[] = (float[]) what; - for (int i = 0; i < ff.length; i++) { - System.out.println("[" + i + "] " + ff[i]); - } - break; - - /* - case 'D': // double - double dd[] = (double[]) what; - for (int i = 0; i < dd.length; i++) { - System.out.println("[" + i + "] " + dd[i]); - } - break; - */ - - default: - System.out.println(what); - } - } else { // not an array - System.out.println(what); - } - } - } - - -/** - * @webref output:text_area - * @param what one-dimensional array - * @usage IDE - * @see PApplet#print(byte) - * @see PApplet#println() - */ - static public void printArray(Object what) { - if (what == null) { - // special case since this does fuggly things on > 1.1 - System.out.println("null"); - - } else { - String name = what.getClass().getName(); - if (name.charAt(0) == '[') { - switch (name.charAt(1)) { - case '[': - // don't even mess with multi-dimensional arrays (case '[') - // or anything else that's not int, float, boolean, char - System.out.println(what); - break; - - case 'L': - // print a 1D array of objects as individual elements - Object poo[] = (Object[]) what; - for (int i = 0; i < poo.length; i++) { - if (poo[i] instanceof String) { - System.out.println("[" + i + "] \"" + poo[i] + "\""); - } else { - System.out.println("[" + i + "] " + poo[i]); - } - } - break; - - case 'Z': // boolean - boolean zz[] = (boolean[]) what; - for (int i = 0; i < zz.length; i++) { - System.out.println("[" + i + "] " + zz[i]); - } - break; - - case 'B': // byte - byte bb[] = (byte[]) what; - for (int i = 0; i < bb.length; i++) { - System.out.println("[" + i + "] " + bb[i]); - } - break; - - case 'C': // char - char cc[] = (char[]) what; - for (int i = 0; i < cc.length; i++) { - System.out.println("[" + i + "] '" + cc[i] + "'"); - } - break; - - case 'I': // int - int ii[] = (int[]) what; - for (int i = 0; i < ii.length; i++) { - System.out.println("[" + i + "] " + ii[i]); - } - break; - - case 'J': // int - long jj[] = (long[]) what; - for (int i = 0; i < jj.length; i++) { - System.out.println("[" + i + "] " + jj[i]); - } - break; - - case 'F': // float - float ff[] = (float[]) what; - for (int i = 0; i < ff.length; i++) { - System.out.println("[" + i + "] " + ff[i]); - } - break; - - case 'D': // double - double dd[] = (double[]) what; - for (int i = 0; i < dd.length; i++) { - System.out.println("[" + i + "] " + dd[i]); - } - break; - - default: - System.out.println(what); - } - } else { // not an array - System.out.println(what); - } - } - System.out.flush(); - } - - // - - /* - // not very useful, because it only works for public (and protected?) - // fields of a class, not local variables to methods - public void printvar(String name) { - try { - Field field = getClass().getDeclaredField(name); - println(name + " = " + field.get(this)); - } catch (Exception e) { - e.printStackTrace(); - } - } - */ - - - ////////////////////////////////////////////////////////////// - - // MATH - - // lots of convenience methods for math with floats. - // doubles are overkill for processing applets, and casting - // things all the time is annoying, thus the functions below. - - - static public final float abs(float n) { - return (n < 0) ? -n : n; - } - - static public final int abs(int n) { - return (n < 0) ? -n : n; - } - - static public final float sq(float a) { - return a*a; - } - - static public final float sqrt(float a) { - return (float)Math.sqrt(a); - } - - static public final float log(float a) { - return (float)Math.log(a); - } - - static public final float exp(float a) { - return (float)Math.exp(a); - } - - static public final float pow(float a, float b) { - return (float)Math.pow(a, b); - } - - - static public final int max(int a, int b) { - return (a > b) ? a : b; - } - - static public final float max(float a, float b) { - return (a > b) ? a : b; - } - - - static public final int max(int a, int b, int c) { - return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c); - } - - static public final float max(float a, float b, float c) { - return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c); - } - - - /** - * Find the maximum value in an array. - * Throws an ArrayIndexOutOfBoundsException if the array is length 0. - * @param list the source array - * @return The maximum value - */ - static public final int max(int[] list) { - if (list.length == 0) { - throw new ArrayIndexOutOfBoundsException(ERROR_MIN_MAX); - } - int max = list[0]; - for (int i = 1; i < list.length; i++) { - if (list[i] > max) max = list[i]; - } - return max; - } - - /** - * Find the maximum value in an array. - * Throws an ArrayIndexOutOfBoundsException if the array is length 0. - * @param list the source array - * @return The maximum value - */ - static public final float max(float[] list) { - if (list.length == 0) { - throw new ArrayIndexOutOfBoundsException(ERROR_MIN_MAX); - } - float max = list[0]; - for (int i = 1; i < list.length; i++) { - if (list[i] > max) max = list[i]; - } - return max; - } - - - static public final int min(int a, int b) { - return (a < b) ? a : b; - } - - static public final float min(float a, float b) { - return (a < b) ? a : b; - } - - - static public final int min(int a, int b, int c) { - return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c); - } - - static public final float min(float a, float b, float c) { - return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c); - } - - - /** - * Find the minimum value in an array. - * Throws an ArrayIndexOutOfBoundsException if the array is length 0. - * @param list the source array - * @return The minimum value - */ - static public final int min(int[] list) { - if (list.length == 0) { - throw new ArrayIndexOutOfBoundsException(ERROR_MIN_MAX); - } - int min = list[0]; - for (int i = 1; i < list.length; i++) { - if (list[i] < min) min = list[i]; - } - return min; - } - /** - * Find the minimum value in an array. - * Throws an ArrayIndexOutOfBoundsException if the array is length 0. - * @param list the source array - * @return The minimum value - */ - static public final float min(float[] list) { - if (list.length == 0) { - throw new ArrayIndexOutOfBoundsException(ERROR_MIN_MAX); - } - float min = list[0]; - for (int i = 1; i < list.length; i++) { - if (list[i] < min) min = list[i]; - } - return min; - } - - - static public final int constrain(int amt, int low, int high) { - return (amt < low) ? low : ((amt > high) ? high : amt); - } - - static public final float constrain(float amt, float low, float high) { - return (amt < low) ? low : ((amt > high) ? high : amt); - } - - - static public final float sin(float angle) { - return (float)Math.sin(angle); - } - - static public final float cos(float angle) { - return (float)Math.cos(angle); - } - - static public final float tan(float angle) { - return (float)Math.tan(angle); - } - - - static public final float asin(float value) { - return (float)Math.asin(value); - } - - static public final float acos(float value) { - return (float)Math.acos(value); - } - - static public final float atan(float value) { - return (float)Math.atan(value); - } - - static public final float atan2(float a, float b) { - return (float)Math.atan2(a, b); - } - - - static public final float degrees(float radians) { - return radians * RAD_TO_DEG; - } - - static public final float radians(float degrees) { - return degrees * DEG_TO_RAD; - } - - - static public final int ceil(float what) { - return (int) Math.ceil(what); - } - - static public final int floor(float what) { - return (int) Math.floor(what); - } - - static public final int round(float what) { - return (int) Math.round(what); - } - - - static public final float mag(float a, float b) { - return (float)Math.sqrt(a*a + b*b); - } - - static public final float mag(float a, float b, float c) { - return (float)Math.sqrt(a*a + b*b + c*c); - } - - - static public final float dist(float x1, float y1, float x2, float y2) { - return sqrt(sq(x2-x1) + sq(y2-y1)); - } - - static public final float dist(float x1, float y1, float z1, - float x2, float y2, float z2) { - return sqrt(sq(x2-x1) + sq(y2-y1) + sq(z2-z1)); - } - - - static public final float lerp(float start, float stop, float amt) { - return start + (stop-start) * amt; - } - - /** - * Normalize a value to exist between 0 and 1 (inclusive). - * Mathematically the opposite of lerp(), figures out what proportion - * a particular value is relative to start and stop coordinates. - */ - static public final float norm(float value, float start, float stop) { - return (value - start) / (stop - start); - } - - /** - * Convenience function to map a variable from one coordinate space - * to another. Equivalent to unlerp() followed by lerp(). - */ - static public final float map(float value, - float istart, float istop, - float ostart, float ostop) { - return ostart + (ostop - ostart) * ((value - istart) / (istop - istart)); - } - - - - ////////////////////////////////////////////////////////////// - - // RANDOM NUMBERS - - - Random internalRandom; - - /** - * - */ - public final float random(float high) { - // avoid an infinite loop when 0 or NaN are passed in - if (high == 0 || high != high) { - return 0; - } - - if (internalRandom == null) { - internalRandom = new Random(); - } - - // for some reason (rounding error?) Math.random() * 3 - // can sometimes return '3' (once in ~30 million tries) - // so a check was added to avoid the inclusion of 'howbig' - float value = 0; - do { - value = internalRandom.nextFloat() * high; - } while (value == high); - return value; - } - - /** - * ( begin auto-generated from randomGaussian.xml ) - * - * Returns a float from a random series of numbers having a mean of 0 - * and standard deviation of 1. Each time the randomGaussian() - * function is called, it returns a number fitting a Gaussian, or - * normal, distribution. There is theoretically no minimum or maximum - * value that randomGaussian() might return. Rather, there is - * just a very low probability that values far from the mean will be - * returned; and a higher probability that numbers near the mean will - * be returned. - * - * ( end auto-generated ) - * @webref math:random - * @see PApplet#random(float,float) - * @see PApplet#noise(float, float, float) - */ - public final float randomGaussian() { - if (internalRandom == null) { - internalRandom = new Random(); - } - return (float) internalRandom.nextGaussian(); - } - - - /** - * ( begin auto-generated from random.xml ) - * - * Generates random numbers. Each time the random() function is - * called, it returns an unexpected value within the specified range. If - * one parameter is passed to the function it will return a float - * between zero and the value of the high parameter. The function - * call random(5) returns values between 0 and 5 (starting at zero, - * up to but not including 5). If two parameters are passed, it will return - * a float with a value between the the parameters. The function - * call random(-5, 10.2) returns values starting at -5 up to (but - * not including) 10.2. To convert a floating-point random number to an - * integer, use the int() function. - * - * ( end auto-generated ) - * @webref math:random - * @param low lower limit - * @param high upper limit - * @see PApplet#randomSeed(long) - * @see PApplet#noise(float, float, float) - */ - public final float random(float low, float high) { - if (low >= high) return low; - float diff = high - low; - float value = 0; - // because of rounding error, can't just add low, otherwise it may hit high - // https://github.com/processing/processing/issues/4551 - do { - value = random(diff) + low; - } while (value == high); - return value; - } - - - /** - * ( begin auto-generated from randomSeed.xml ) - * - * Sets the seed value for random(). By default, random() - * produces different results each time the program is run. Set the - * value parameter to a constant to return the same pseudo-random - * numbers each time the software is run. - * - * ( end auto-generated ) - * @webref math:random - * @param seed seed value - * @see PApplet#random(float,float) - * @see PApplet#noise(float, float, float) - * @see PApplet#noiseSeed(long) - */ - public final void randomSeed(long seed) { - if (internalRandom == null) { - internalRandom = new Random(); - } - internalRandom.setSeed(seed); - } - - - - - ////////////////////////////////////////////////////////////// - - // PERLIN NOISE - - // [toxi 040903] - // octaves and amplitude amount per octave are now user controlled - // via the noiseDetail() function. - - // [toxi 030902] - // cleaned up code and now using bagel's cosine table to speed up - - // [toxi 030901] - // implementation by the german demo group farbrausch - // as used in their demo "art": http://www.farb-rausch.de/fr010src.zip - - static final int PERLIN_YWRAPB = 4; - static final int PERLIN_YWRAP = 1<random() function. - * It was invented by Ken Perlin in the 1980s and been used since in - * graphical applications to produce procedural textures, natural motion, - * shapes, terrains etc.

      The main difference to the - * random() function is that Perlin noise is defined in an infinite - * n-dimensional space where each pair of coordinates corresponds to a - * fixed semi-random value (fixed only for the lifespan of the program). - * The resulting value will always be between 0.0 and 1.0. Processing can - * compute 1D, 2D and 3D noise, depending on the number of coordinates - * given. The noise value can be animated by moving through the noise space - * as demonstrated in the example above. The 2nd and 3rd dimension can also - * be interpreted as time.

      The actual noise is structured - * similar to an audio signal, in respect to the function's use of - * frequencies. Similar to the concept of harmonics in physics, perlin - * noise is computed over several octaves which are added together for the - * final result.

      Another way to adjust the character of the - * resulting sequence is the scale of the input coordinates. As the - * function works within an infinite space the value of the coordinates - * doesn't matter as such, only the distance between successive coordinates - * does (eg. when using noise() within a loop). As a general rule - * the smaller the difference between coordinates, the smoother the - * resulting noise sequence will be. Steps of 0.005-0.03 work best for most - * applications, but this will differ depending on use. - * - * ( end auto-generated ) - * - * @webref math:random - * @param x x-coordinate in noise space - * @param y y-coordinate in noise space - * @param z z-coordinate in noise space - * @see PApplet#noiseSeed(long) - * @see PApplet#noiseDetail(int, float) - * @see PApplet#random(float,float) - */ - public float noise(float x, float y, float z) { - if (perlin == null) { - if (perlinRandom == null) { - perlinRandom = new Random(); - } - perlin = new float[PERLIN_SIZE + 1]; - for (int i = 0; i < PERLIN_SIZE + 1; i++) { - perlin[i] = perlinRandom.nextFloat(); //(float)Math.random(); - } - // [toxi 031112] - // noise broke due to recent change of cos table in PGraphics - // this will take care of it - perlin_cosTable = PGraphics.cosLUT; - perlin_TWOPI = perlin_PI = PGraphics.SINCOS_LENGTH; - perlin_PI >>= 1; - } - - if (x<0) x=-x; - if (y<0) y=-y; - if (z<0) z=-z; - - int xi=(int)x, yi=(int)y, zi=(int)z; - float xf = x - xi; - float yf = y - yi; - float zf = z - zi; - float rxf, ryf; - - float r=0; - float ampl=0.5f; - - float n1,n2,n3; - - for (int i=0; i=1.0f) { xi++; xf--; } - if (yf>=1.0f) { yi++; yf--; } - if (zf>=1.0f) { zi++; zf--; } - } - return r; - } - - // [toxi 031112] - // now adjusts to the size of the cosLUT used via - // the new variables, defined above - private float noise_fsc(float i) { - // using bagel's cosine table instead - return 0.5f*(1.0f-perlin_cosTable[(int)(i*perlin_PI)%perlin_TWOPI]); - } - - // [toxi 040903] - // make perlin noise quality user controlled to allow - // for different levels of detail. lower values will produce - // smoother results as higher octaves are surpressed - - /** - * ( begin auto-generated from noiseDetail.xml ) - * - * Adjusts the character and level of detail produced by the Perlin noise - * function. Similar to harmonics in physics, noise is computed over - * several octaves. Lower octaves contribute more to the output signal and - * as such define the overal intensity of the noise, whereas higher octaves - * create finer grained details in the noise sequence. By default, noise is - * computed over 4 octaves with each octave contributing exactly half than - * its predecessor, starting at 50% strength for the 1st octave. This - * falloff amount can be changed by adding an additional function - * parameter. Eg. a falloff factor of 0.75 means each octave will now have - * 75% impact (25% less) of the previous lower octave. Any value between - * 0.0 and 1.0 is valid, however note that values greater than 0.5 might - * result in greater than 1.0 values returned by noise().

      By changing these parameters, the signal created by the noise() - * function can be adapted to fit very specific needs and characteristics. - * - * ( end auto-generated ) - * @webref math:random - * @param lod number of octaves to be used by the noise - * @see PApplet#noise(float, float, float) - */ - public void noiseDetail(int lod) { - if (lod>0) perlin_octaves=lod; - } - - /** - * @see #noiseDetail(int) - * @param falloff falloff factor for each octave - */ - public void noiseDetail(int lod, float falloff) { - if (lod>0) perlin_octaves=lod; - if (falloff>0) perlin_amp_falloff=falloff; - } - - /** - * ( begin auto-generated from noiseSeed.xml ) - * - * Sets the seed value for noise(). By default, noise() - * produces different results each time the program is run. Set the - * value parameter to a constant to return the same pseudo-random - * numbers each time the software is run. - * - * ( end auto-generated ) - * @webref math:random - * @param seed seed value - * @see PApplet#noise(float, float, float) - * @see PApplet#noiseDetail(int, float) - * @see PApplet#random(float,float) - * @see PApplet#randomSeed(long) - */ - public void noiseSeed(long seed) { - if (perlinRandom == null) perlinRandom = new Random(); - perlinRandom.setSeed(seed); - // force table reset after changing the random number seed [0122] - perlin = null; - } - - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - - public PImage loadImage(String filename) { //, Object params) { -// return loadImage(filename, null); - InputStream stream = createInput(filename); - if (stream == null) { - System.err.println("Could not find the image " + filename + "."); - return null; - } -// long t = System.currentTimeMillis(); - Bitmap bitmap = null; - try { - bitmap = BitmapFactory.decodeStream(stream); - } finally { - try { - stream.close(); - stream = null; - } catch (IOException e) { } - } -// int much = (int) (System.currentTimeMillis() - t); -// println("loadImage(" + filename + ") was " + nfc(much)); - if (bitmap == null) { - System.err.println("Could not load the image because the bitmap was empty."); - return null; - } else { - PImage image = new PImage(bitmap); - image.parent = this; - return image; - } - } - - - public PImage loadImage(String filename, String extension) { - return loadImage(filename); - } - - - public PImage requestImage(String filename) { - PImage vessel = createImage(0, 0, ARGB); - AsyncImageLoader ail = new AsyncImageLoader(filename, vessel); - ail.start(); - return vessel; - } - - - /** - * By trial and error, four image loading threads seem to work best when - * loading images from online. This is consistent with the number of open - * connections that web browsers will maintain. The variable is made public - * (however no accessor has been added since it's esoteric) if you really - * want to have control over the value used. For instance, when loading local - * files, it might be better to only have a single thread (or two) loading - * images so that you're disk isn't simply jumping around. - */ - public int requestImageMax = 4; - volatile int requestImageCount; - - // Removed 'extension' from the android version. If the extension is needed - // later, re-copy this from the original PApplet code. - class AsyncImageLoader extends Thread { - String filename; - PImage vessel; - - public AsyncImageLoader(String filename, PImage vessel) { - this.filename = filename; - this.vessel = vessel; - } - - @Override - public void run() { - while (requestImageCount == requestImageMax) { - try { - Thread.sleep(10); - } catch (InterruptedException e) { } - } - requestImageCount++; - - PImage actual = loadImage(filename); - - // An error message should have already printed - if (actual == null) { - vessel.width = -1; - vessel.height = -1; - - } else { - vessel.width = actual.width; - vessel.height = actual.height; - vessel.format = actual.format; - vessel.pixels = actual.pixels; - // an android, pixels[] will probably be null, we want this one - vessel.bitmap = actual.bitmap; - - vessel.pixelWidth = actual.width; - vessel.pixelHeight = actual.height; - vessel.pixelDensity = 1; - } - requestImageCount--; - } - } - - - - ////////////////////////////////////////////////////////////// - - // DATA I/O - - - public XML createXML(String name) { - try { - return new XML(name); - } catch (Exception e) { - printStackTrace(e); - return null; - } - } - - - /** - * @webref input:files - * @param filename name of a file in the data folder or a URL. - * @see XML#parse(String) - * @see PApplet#loadBytes(String) - * @see PApplet#loadStrings(String) - * @see PApplet#loadTable(String) - */ - public XML loadXML(String filename) { - return loadXML(filename, null); - } - - - // version that uses 'options' though there are currently no supported options - public XML loadXML(String filename, String options) { - try { - return new XML(createInput(filename), options); - } catch (Exception e) { - printStackTrace(e); - return null; - } - } - - - public XML parseXML(String xmlString) { - return parseXML(xmlString, null); - } - - - public XML parseXML(String xmlString, String options) { - try { - return XML.parse(xmlString, options); - } catch (Exception e) { - printStackTrace(e); - return null; - } - } - - - public boolean saveXML(XML xml, String filename) { - return saveXML(xml, filename, null); - } - - - public boolean saveXML(XML xml, String filename, String options) { - return xml.save(saveFile(filename), options); - } - - - /** - * @webref input:files - * @param input String to parse as a JSONObject - * @see PApplet#loadJSONObject(String) - * @see PApplet#saveJSONObject(JSONObject, String) - */ - public JSONObject parseJSONObject(String input) { - return new JSONObject(new StringReader(input)); - } - - - /** - * @webref input:files - * @param filename name of a file in the data folder or a URL - * @see JSONObject - * @see JSONArray - * @see PApplet#loadJSONArray(String) - * @see PApplet#saveJSONObject(JSONObject, String) - * @see PApplet#saveJSONArray(JSONArray, String) - */ - public JSONObject loadJSONObject(String filename) { - // can't pass of createReader() to the constructor b/c of resource leak - BufferedReader reader = createReader(filename); - JSONObject outgoing = new JSONObject(reader); - try { - reader.close(); - } catch (IOException e) { // not sure what would cause this - e.printStackTrace(); - } - return outgoing; - } - - - static public JSONObject loadJSONObject(File file) { - // can't pass of createReader() to the constructor b/c of resource leak - BufferedReader reader = createReader(file); - JSONObject outgoing = new JSONObject(reader); - try { - reader.close(); - } catch (IOException e) { // not sure what would cause this - e.printStackTrace(); - } - return outgoing; - } - - - /** - * @webref output:files - * @see JSONObject - * @see JSONArray - * @see PApplet#loadJSONObject(String) - * @see PApplet#loadJSONArray(String) - * @see PApplet#saveJSONArray(JSONArray, String) - */ - public boolean saveJSONObject(JSONObject json, String filename) { - return saveJSONObject(json, filename, null); - } - - - /** - * @nowebref - */ - public boolean saveJSONObject(JSONObject json, String filename, String options) { - return json.save(saveFile(filename), options); - } - - - /** - * @webref input:files - * @param input String to parse as a JSONArray - * @see JSONObject - * @see PApplet#loadJSONObject(String) - * @see PApplet#saveJSONObject(JSONObject, String) - */ - public JSONArray parseJSONArray(String input) { - return new JSONArray(new StringReader(input)); - } - - - /** - * @webref input:files - * @param filename name of a file in the data folder or a URL - * @see JSONArray - * @see PApplet#loadJSONObject(String) - * @see PApplet#saveJSONObject(JSONObject, String) - * @see PApplet#saveJSONArray(JSONArray, String) - */ - public JSONArray loadJSONArray(String filename) { - // can't pass of createReader() to the constructor b/c of resource leak - BufferedReader reader = createReader(filename); - JSONArray outgoing = new JSONArray(reader); - try { - reader.close(); - } catch (IOException e) { // not sure what would cause this - e.printStackTrace(); - } - return outgoing; - } - - - static public JSONArray loadJSONArray(File file) { - // can't pass of createReader() to the constructor b/c of resource leak - BufferedReader reader = createReader(file); - JSONArray outgoing = new JSONArray(reader); - try { - reader.close(); - } catch (IOException e) { // not sure what would cause this - e.printStackTrace(); - } - return outgoing; - } - - - /** - * @webref output:files - * @see JSONObject - * @see JSONArray - * @see PApplet#loadJSONObject(String) - * @see PApplet#loadJSONArray(String) - * @see PApplet#saveJSONObject(JSONObject, String) - */ - public boolean saveJSONArray(JSONArray json, String filename) { - return saveJSONArray(json, filename, null); - } - - - public boolean saveJSONArray(JSONArray json, String filename, String options) { - return json.save(saveFile(filename), options); - } - - - public Table createTable() { - return new Table(); - } - - - /** - * @webref input:files - * @param filename name of a file in the data folder or a URL. - * @see PApplet#loadBytes(String) - * @see PApplet#loadStrings(String) - * @see PApplet#loadXML(String) - */ - public Table loadTable(String filename) { - return loadTable(filename, null); - } - - - public Table loadTable(String filename, String options) { - try { - String ext = checkExtension(filename); - if (ext != null) { - if (ext.equals("csv") || ext.equals("tsv")) { - if (options == null) { - options = ext; - } else { - options = ext + "," + options; - } - } - } - return new Table(createInput(filename), options); - - } catch (IOException e) { - printStackTrace(e); - return null; - } - } - - - public boolean saveTable(Table table, String filename) { - return saveTable(table, filename, null); - } - - - public boolean saveTable(Table table, String filename, String options) { - try { - table.save(saveFile(filename), options); - return true; - } catch (IOException e) { - printStackTrace(e); - } - return false; - } - - - - // FONT I/O - - - public PFont loadFont(String filename) { - try { - InputStream input = createInput(filename); - return new PFont(input); - - } catch (Exception e) { - die("Could not load font " + filename + ". " + - "Make sure that the font has been copied " + - "to the data folder of your sketch.", e); - } - return null; - } - - - /** - * Used by PGraphics to remove the requirement for loading a font! - */ - protected PFont createDefaultFont(float size) { - return createFont("SansSerif", size, true, null); - } - - - public PFont createFont(String name, float size) { - return createFont(name, size, true, null); - } - - - public PFont createFont(String name, float size, boolean smooth) { - return createFont(name, size, smooth, null); - } - - - /** - * Create a bitmap font on the fly from either a font name that's - * installed on the system, or from a .ttf or .otf that's inside - * the data folder of this sketch. - *

      - * Use 'null' for the charset if you want to dynamically create - * character bitmaps only as they're needed. - */ - public PFont createFont(String name, float size, - boolean smooth, char[] charset) { - String lowerName = name.toLowerCase(); - Typeface baseFont = null; - - if (lowerName.endsWith(".otf") || lowerName.endsWith(".ttf")) { - AssetManager assets = surface.getAssets(); - baseFont = Typeface.createFromAsset(assets, name); - } else { - baseFont = (Typeface) PFont.findNative(name); - } - return new PFont(baseFont, round(size), smooth, charset); - } - - - ////////////////////////////////////////////////////////////// - - // FILE/FOLDER SELECTION - - // Doesn't appear to be implemented by Android, but this article might help: - // http://linuxdevices.com/articles/AT6247038002.html - -// public File selectedFile; -// protected Frame parentFrame; -// -// -// protected void checkParentFrame() { -// if (parentFrame == null) { -// Component comp = getParent(); -// while (comp != null) { -// if (comp instanceof Frame) { -// parentFrame = (Frame) comp; -// break; -// } -// comp = comp.getParent(); -// } -// // Who you callin' a hack? -// if (parentFrame == null) { -// parentFrame = new Frame(); -// } -// } -// } -// -// -// /** -// * Open a platform-specific file chooser dialog to select a file for input. -// * @return full path to the selected file, or null if no selection. -// */ -// public String selectInput() { -// return selectInput("Select a file..."); -// } -// -// -// /** -// * Open a platform-specific file chooser dialog to select a file for input. -// * @param prompt Mesage to show the user when prompting for a file. -// * @return full path to the selected file, or null if canceled. -// */ -// public String selectInput(String prompt) { -// return selectFileImpl(prompt, FileDialog.LOAD); -// } -// -// -// /** -// * Open a platform-specific file save dialog to select a file for output. -// * @return full path to the file entered, or null if canceled. -// */ -// public String selectOutput() { -// return selectOutput("Save as..."); -// } -// -// -// /** -// * Open a platform-specific file save dialog to select a file for output. -// * @param prompt Mesage to show the user when prompting for a file. -// * @return full path to the file entered, or null if canceled. -// */ -// public String selectOutput(String prompt) { -// return selectFileImpl(prompt, FileDialog.SAVE); -// } -// -// -// protected String selectFileImpl(final String prompt, final int mode) { -// checkParentFrame(); -// -// try { -// SwingUtilities.invokeAndWait(new Runnable() { -// public void run() { -// FileDialog fileDialog = -// new FileDialog(parentFrame, prompt, mode); -// fileDialog.setVisible(true); -// String directory = fileDialog.getDirectory(); -// String filename = fileDialog.getFile(); -// selectedFile = -// (filename == null) ? null : new File(directory, filename); -// } -// }); -// return (selectedFile == null) ? null : selectedFile.getAbsolutePath(); -// -// } catch (Exception e) { -// e.printStackTrace(); -// return null; -// } -// } -// -// -// /** -// * Open a platform-specific folder chooser dialog. -// * @return full path to the selected folder, or null if no selection. -// */ -// public String selectFolder() { -// return selectFolder("Select a folder..."); -// } -// -// -// /** -// * Open a platform-specific folder chooser dialog. -// * @param prompt Mesage to show the user when prompting for a file. -// * @return full path to the selected folder, or null if no selection. -// */ -// public String selectFolder(final String prompt) { -// checkParentFrame(); -// -// try { -// SwingUtilities.invokeAndWait(new Runnable() { -// public void run() { -// if (platform == MACOSX) { -// FileDialog fileDialog = -// new FileDialog(parentFrame, prompt, FileDialog.LOAD); -// System.setProperty("apple.awt.fileDialogForDirectories", "true"); -// fileDialog.setVisible(true); -// System.setProperty("apple.awt.fileDialogForDirectories", "false"); -// String filename = fileDialog.getFile(); -// selectedFile = (filename == null) ? null : -// new File(fileDialog.getDirectory(), fileDialog.getFile()); -// } else { -// JFileChooser fileChooser = new JFileChooser(); -// fileChooser.setDialogTitle(prompt); -// fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); -// -// int returned = fileChooser.showOpenDialog(parentFrame); -// System.out.println(returned); -// if (returned == JFileChooser.CANCEL_OPTION) { -// selectedFile = null; -// } else { -// selectedFile = fileChooser.getSelectedFile(); -// } -// } -// } -// }); -// return (selectedFile == null) ? null : selectedFile.getAbsolutePath(); -// -// } catch (Exception e) { -// e.printStackTrace(); -// return null; -// } -// } - - - ////////////////////////////////////////////////////////////// - - // LISTING DIRECTORIES - - - public String[] listPaths(String path, String... options) { - File[] list = listFiles(path, options); - - int offset = 0; - for (String opt : options) { - if (opt.equals("relative")) { - if (!path.endsWith(File.pathSeparator)) { - path += File.pathSeparator; - } - offset = path.length(); - break; - } - } - String[] outgoing = new String[list.length]; - for (int i = 0; i < list.length; i++) { - // as of Java 1.8, substring(0) returns the original object - outgoing[i] = list[i].getAbsolutePath().substring(offset); - } - return outgoing; - } - - - public File[] listFiles(String path, String... options) { - File file = new File(path); - // if not an absolute path, make it relative to the sketch folder - if (!file.isAbsolute()) { - file = sketchFile(path); - } - return listFiles(file, options); - } - - - // "relative" -> no effect with the Files version, but important for listPaths - // "recursive" - // "extension=js" or "extensions=js|csv|txt" (no dot) - // "directories" -> only directories - // "files" -> only files - // "hidden" -> include hidden files (prefixed with .) disabled by default - static public File[] listFiles(File base, String... options) { - boolean recursive = false; - String[] extensions = null; - boolean directories = true; - boolean files = true; - boolean hidden = false; - - for (String opt : options) { - if (opt.equals("recursive")) { - recursive = true; - } else if (opt.startsWith("extension=")) { - extensions = new String[] { opt.substring(10) }; - } else if (opt.startsWith("extensions=")) { - extensions = split(opt.substring(10), ','); - } else if (opt.equals("files")) { - directories = false; - } else if (opt.equals("directories")) { - files = false; - } else if (opt.equals("hidden")) { - hidden = true; - } else if (opt.equals("relative")) { - // ignored - } else { - throw new RuntimeException(opt + " is not a listFiles() option"); - } - } - - if (extensions != null) { - for (int i = 0; i < extensions.length; i++) { - extensions[i] = "." + extensions[i]; - } - } - - if (!files && !directories) { - // just make "only files" and "only directories" mean... both - files = true; - directories = true; - } - - if (!base.canRead()) { - return null; - } - - List outgoing = new ArrayList<>(); - listFilesImpl(base, recursive, extensions, hidden, directories, files, outgoing); - return outgoing.toArray(new File[0]); - } - - - static void listFilesImpl(File folder, boolean recursive, - String[] extensions, boolean hidden, - boolean directories, boolean files, - List list) { - File[] items = folder.listFiles(); - if (items != null) { - for (File item : items) { - String name = item.getName(); - if (!hidden && name.charAt(0) == '.') { - continue; - } - if (item.isDirectory()) { - if (recursive) { - listFilesImpl(item, recursive, extensions, hidden, directories, files, list); - } - if (directories) { - list.add(item); - } - } else if (files) { - if (extensions == null) { - list.add(item); - } else { - for (String ext : extensions) { - if (item.getName().toLowerCase().endsWith(ext)) { - list.add(item); - } - } - } - } - } - } - } - - - - ////////////////////////////////////////////////////////////// - - // EXTENSIONS - - - /** - * Get the compression-free extension for this filename. - * @param filename The filename to check - * @return an extension, skipping past .gz if it's present - */ - static public String checkExtension(String filename) { - // Don't consider the .gz as part of the name, createInput() - // and createOuput() will take care of fixing that up. - if (filename.toLowerCase().endsWith(".gz")) { - filename = filename.substring(0, filename.length() - 3); - } - int dotIndex = filename.lastIndexOf('.'); - if (dotIndex != -1) { - return filename.substring(dotIndex + 1).toLowerCase(); - } - return null; - } - - - ////////////////////////////////////////////////////////////// - - // READERS AND WRITERS - - - /** - * I want to read lines from a file. I have RSI from typing these - * eight lines of code so many times. - */ - public BufferedReader createReader(String filename) { - try { - InputStream is = createInput(filename); - if (is == null) { - System.err.println(filename + " does not exist or could not be read"); - return null; - } - return createReader(is); - - } catch (Exception e) { - if (filename == null) { - System.err.println("Filename passed to reader() was null"); - } else { - System.err.println("Couldn't create a reader for " + filename); - } - } - return null; - } - - - /** - * I want to read lines from a file. And I'm still annoyed. - */ - static public BufferedReader createReader(File file) { - try { - InputStream is = new FileInputStream(file); - if (file.getName().toLowerCase().endsWith(".gz")) { - is = new GZIPInputStream(is); - } - return createReader(is); - - } catch (Exception e) { - if (file == null) { - throw new RuntimeException("File passed to createReader() was null"); - } else { - e.printStackTrace(); - throw new RuntimeException("Couldn't create a reader for " + - file.getAbsolutePath()); - } - } - //return null; - } - - - /** - * I want to read lines from a stream. If I have to type the - * following lines any more I'm gonna send Sun my medical bills. - */ - static public BufferedReader createReader(InputStream input) { - InputStreamReader isr = - new InputStreamReader(input, CompatUtils.getCharsetUTF8()); - - BufferedReader reader = new BufferedReader(isr); - // consume the Unicode BOM (byte order marker) if present - try { - reader.mark(1); - int c = reader.read(); - // if not the BOM, back up to the beginning again - if (c != '\uFEFF') { - reader.reset(); - } - } catch (IOException e) { - e.printStackTrace(); - } - return reader; - } - - - /** - * I want to print lines to a file. Why can't I? - */ - public PrintWriter createWriter(String filename) { - return createWriter(saveFile(filename)); - } - - - /** - * I want to print lines to a file. I have RSI from typing these - * eight lines of code so many times. - */ - static public PrintWriter createWriter(File file) { - try { - OutputStream output = new FileOutputStream(file); - if (file.getName().toLowerCase().endsWith(".gz")) { - output = new GZIPOutputStream(output); - } - return createWriter(output); - - } catch (Exception e) { - if (file == null) { - throw new RuntimeException("File passed to createWriter() was null"); - } else { - e.printStackTrace(); - throw new RuntimeException("Couldn't create a writer for " + - file.getAbsolutePath()); - } - } - //return null; - } - - - /** - * I want to print lines to a file. Why am I always explaining myself? - * It's the JavaSoft API engineers who need to explain themselves. - */ - static public PrintWriter createWriter(OutputStream output) { - BufferedOutputStream bos = new BufferedOutputStream(output, 8192); - OutputStreamWriter osw = - new OutputStreamWriter(bos, CompatUtils.getCharsetUTF8()); - return new PrintWriter(osw); - } - - - ////////////////////////////////////////////////////////////// - - // FILE INPUT - - - /** - * Simplified method to open a Java InputStream. - *

      - * This method is useful if you want to use the facilities provided - * by PApplet to easily open things from the data folder or from a URL, - * but want an InputStream object so that you can use other Java - * methods to take more control of how the stream is read. - *

      - * If the requested item doesn't exist, null is returned. - * (Prior to 0096, die() would be called, killing the applet) - *

      - * For 0096+, the "data" folder is exported intact with subfolders, - * and openStream() properly handles subdirectories from the data folder - *

      - * If not online, this will also check to see if the user is asking - * for a file whose name isn't properly capitalized. This helps prevent - * issues when a sketch is exported to the web, where case sensitivity - * matters, as opposed to Windows and the Mac OS default where - * case sensitivity is preserved but ignored. - *

      - * It is strongly recommended that libraries use this method to open - * data files, so that the loading sequence is handled in the same way - * as functions like loadBytes(), loadImage(), etc. - *

      - * The filename passed in can be: - *

        - *
      • A URL, for instance openStream("http://processing.org/"); - *
      • A file in the sketch's data folder - *
      • Another file to be opened locally (when running as an application) - *
      - */ - public InputStream createInput(String filename) { - InputStream input = createInputRaw(filename); - final String lower = filename.toLowerCase(); - if ((input != null) && - (lower.endsWith(".gz") || lower.endsWith(".svgz"))) { - try { - // buffered has to go *around* the GZ, otherwise 25x slower - return new BufferedInputStream(new GZIPInputStream(input)); - } catch (IOException e) { - printStackTrace(e); - return null; - } - } - return new BufferedInputStream(input); - } - - - /** - * Call createInput() without automatic gzip decompression. - */ - public InputStream createInputRaw(String filename) { - // Additional considerations for Android version: - // http://developer.android.com/guide/topics/resources/resources-i18n.html - InputStream stream = null; - - if (filename == null) return null; - - if (filename.length() == 0) { - // an error will be called by the parent function - //System.err.println("The filename passed to openStream() was empty."); - return null; - } - - // safe to check for this as a url first. this will prevent online - // access logs from being spammed with GET /sketchfolder/http://blahblah - if (filename.indexOf(":") != -1) { // at least smells like URL - try { - // Workaround for Android bug 6066 - // http://code.google.com/p/android/issues/detail?id=6066 - // http://code.google.com/p/processing/issues/detail?id=629 -// URL url = new URL(filename); -// stream = url.openStream(); -// return stream; - URL url = new URL(filename); - HttpURLConnection con = (HttpURLConnection) url.openConnection(); - con.setRequestMethod("GET"); - con.setDoInput(true); - con.connect(); - return con.getInputStream(); - //The following code is deprecaded by Android -// HttpGet httpRequest = null; -// httpRequest = new HttpGet(URI.create(filename)); -// HttpClient httpclient = new DefaultHttpClient(); -// HttpResponse response = (HttpResponse) httpclient.execute(httpRequest); -// HttpEntity entity = response.getEntity(); -// return entity.getContent(); - // can't use BufferedHttpEntity because it may try to allocate a byte - // buffer of the size of the download, bad when DL is 25 MB... [0200] -// BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity); -// return bufHttpEntity.getContent(); - - } catch (MalformedURLException mfue) { - // not a url, that's fine - - } catch (FileNotFoundException fnfe) { - // Java 1.5 likes to throw this when URL not available. (fix for 0119) - // http://dev.processing.org/bugs/show_bug.cgi?id=403 - - } catch (IOException e) { - // changed for 0117, shouldn't be throwing exception - printStackTrace(e); - //System.err.println("Error downloading from URL " + filename); - return null; - //throw new RuntimeException("Error downloading from URL " + filename); - } - } - - /* - // Moved this earlier than the getResourceAsStream() checks, because - // calling getResourceAsStream() on a directory lists its contents. - // http://dev.processing.org/bugs/show_bug.cgi?id=716 - try { - // First see if it's in a data folder. This may fail by throwing - // a SecurityException. If so, this whole block will be skipped. - File file = new File(dataPath(filename)); - if (!file.exists()) { - // next see if it's just in the sketch folder - file = new File(sketchPath, filename); - } - if (file.isDirectory()) { - return null; - } - if (file.exists()) { - try { - // handle case sensitivity check - String filePath = file.getCanonicalPath(); - String filenameActual = new File(filePath).getName(); - // make sure there isn't a subfolder prepended to the name - String filenameShort = new File(filename).getName(); - // if the actual filename is the same, but capitalized - // differently, warn the user. - //if (filenameActual.equalsIgnoreCase(filenameShort) && - //!filenameActual.equals(filenameShort)) { - if (!filenameActual.equals(filenameShort)) { - throw new RuntimeException("This file is named " + - filenameActual + " not " + - filename + ". Rename the file " + - "or change your code."); - } - } catch (IOException e) { } - } - - // if this file is ok, may as well just load it - stream = new FileInputStream(file); - if (stream != null) return stream; - - // have to break these out because a general Exception might - // catch the RuntimeException being thrown above - } catch (IOException ioe) { - } catch (SecurityException se) { } - */ - - // Using getClassLoader() prevents Java from converting dots - // to slashes or requiring a slash at the beginning. - // (a slash as a prefix means that it'll load from the root of - // the jar, rather than trying to dig into the package location) - - /* - // this works, but requires files to be stored in the src folder - ClassLoader cl = getClass().getClassLoader(); - stream = cl.getResourceAsStream(filename); - if (stream != null) { - String cn = stream.getClass().getName(); - // this is an irritation of sun's java plug-in, which will return - // a non-null stream for an object that doesn't exist. like all good - // things, this is probably introduced in java 1.5. awesome! - // http://dev.processing.org/bugs/show_bug.cgi?id=359 - if (!cn.equals("sun.plugin.cache.EmptyInputStream")) { - return stream; - } - } - */ - - // Try the assets folder - AssetManager assets = surface.getAssets(); - try { - stream = assets.open(filename); - if (stream != null) { - return stream; - } - } catch (IOException e) { - // ignore this and move on - //e.printStackTrace(); - } - - // Maybe this is an absolute path, didja ever think of that? - File absFile = new File(filename); - if (absFile.exists()) { - try { - stream = new FileInputStream(absFile); - if (stream != null) { - return stream; - } - } catch (FileNotFoundException fnfe) { - //fnfe.printStackTrace(); - } - } - - // Maybe this is a file that was written by the sketch on another occasion. - File sketchFile = new File(sketchPath(filename)); - if (sketchFile.exists()) { - try { - stream = new FileInputStream(sketchFile); - if (stream != null) { - return stream; - } - } catch (FileNotFoundException fnfe) { - //fnfe.printStackTrace(); - } - } - - // Attempt to load the file more directly. Doesn't like paths. -// try { -// // MODE_PRIVATE is default, should we use something else? -// stream = surface.openFileInput(filename); -// if (stream != null) { -// return stream; -// } -// } catch (FileNotFoundException e) { -// // ignore this and move on -// //e.printStackTrace(); -// } - - return surface.openFileInput(filename); - } - - - static public InputStream createInput(File file) { - if (file == null) { - throw new IllegalArgumentException("File passed to createInput() was null"); - } - try { - InputStream input = new FileInputStream(file); - if (file.getName().toLowerCase().endsWith(".gz")) { - return new BufferedInputStream(new GZIPInputStream(input)); - } - return new BufferedInputStream(input); - - } catch (IOException e) { - System.err.println("Could not createInput() for " + file); - e.printStackTrace(); - return null; - } - } - - - public byte[] loadBytes(String filename) { - InputStream is = createInput(filename); - if (is != null) return loadBytes(is); - - System.err.println("The file \"" + filename + "\" " + - "is missing or inaccessible, make sure " + - "the URL is valid or that the file has been " + - "added to your sketch and is readable."); - return null; - } - - - static public byte[] loadBytes(InputStream input) { - try { - BufferedInputStream bis = new BufferedInputStream(input); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - int c = bis.read(); - while (c != -1) { - out.write(c); - c = bis.read(); - } - return out.toByteArray(); - - } catch (IOException e) { - e.printStackTrace(); - //throw new RuntimeException("Couldn't load bytes from stream"); - } - return null; - } - - - static public byte[] loadBytes(File file) { - InputStream is = createInput(file); - return loadBytes(is); - } - - - static public String[] loadStrings(File file) { - InputStream is = createInput(file); - if (is != null) return loadStrings(is); - return null; - } - - - static public String[] loadStrings(BufferedReader reader) { - try { - String lines[] = new String[100]; - int lineCount = 0; - String line = null; - while ((line = reader.readLine()) != null) { - if (lineCount == lines.length) { - String temp[] = new String[lineCount << 1]; - System.arraycopy(lines, 0, temp, 0, lineCount); - lines = temp; - } - lines[lineCount++] = line; - } - reader.close(); - - if (lineCount == lines.length) { - return lines; - } - - // resize array to appropriate amount for these lines - String output[] = new String[lineCount]; - System.arraycopy(lines, 0, output, 0, lineCount); - return output; - - } catch (IOException e) { - e.printStackTrace(); - //throw new RuntimeException("Error inside loadStrings()"); - } - return null; - } - - - /** - * Load data from a file and shove it into a String array. - *

      - * Exceptions are handled internally, when an error, occurs, an - * exception is printed to the console and 'null' is returned, - * but the program continues running. This is a tradeoff between - * 1) showing the user that there was a problem but 2) not requiring - * that all i/o code is contained in try/catch blocks, for the sake - * of new users (or people who are just trying to get things done - * in a "scripting" fashion. If you want to handle exceptions, - * use Java methods for I/O. - */ - public String[] loadStrings(String filename) { - InputStream is = createInput(filename); - if (is != null) return loadStrings(is); - - System.err.println("The file \"" + filename + "\" " + - "is missing or inaccessible, make sure " + - "the URL is valid or that the file has been " + - "added to your sketch and is readable."); - return null; - } - - - static public String[] loadStrings(InputStream input) { - try { - BufferedReader reader = - new BufferedReader(new InputStreamReader(input, "UTF-8")); - - String lines[] = new String[100]; - int lineCount = 0; - String line = null; - while ((line = reader.readLine()) != null) { - if (lineCount == lines.length) { - String temp[] = new String[lineCount << 1]; - System.arraycopy(lines, 0, temp, 0, lineCount); - lines = temp; - } - lines[lineCount++] = line; - } - reader.close(); - - if (lineCount == lines.length) { - return lines; - } - - // resize array to appropriate amount for these lines - String output[] = new String[lineCount]; - System.arraycopy(lines, 0, output, 0, lineCount); - return output; - - } catch (IOException e) { - e.printStackTrace(); - //throw new RuntimeException("Error inside loadStrings()"); - } - return null; - } - - - - ////////////////////////////////////////////////////////////// - - // FILE OUTPUT - - - /** - * Similar to createInput() (formerly openStream), this creates a Java - * OutputStream for a given filename or path. The file will be created in - * the sketch folder, or in the same folder as an exported application. - *

      - * If the path does not exist, intermediate folders will be created. If an - * exception occurs, it will be printed to the console, and null will be - * returned. - *

      - * Future releases may also add support for handling HTTP POST via this - * method (for better symmetry with createInput), however that's maybe a - * little too clever (and then we'd have to add the same features to the - * other file functions like createWriter). Who you callin' bloated? - */ - public OutputStream createOutput(String filename) { - try { - // in spite of appearing to be the 'correct' option, this doesn't allow - // for paths, so no subfolders, none of that savePath() goodness. -// Context context = getApplicationContext(); -// // MODE_PRIVATE is default, should we use that instead? -// return context.openFileOutput(filename, MODE_WORLD_READABLE); - - File file = new File(filename); - if (!file.isAbsolute()) { - file = new File(sketchPath(filename)); - } - FileOutputStream fos = new FileOutputStream(file); - if (file.getName().toLowerCase().endsWith(".gz")) { - return new GZIPOutputStream(fos); - } - return fos; - - } catch (IOException e) { - printStackTrace(e); - } - return null; - } - - - static public OutputStream createOutput(File file) { - try { - createPath(file); // make sure the path exists - OutputStream output = new FileOutputStream(file); - if (file.getName().toLowerCase().endsWith(".gz")) { - return new BufferedOutputStream(new GZIPOutputStream(output)); - } - return new BufferedOutputStream(output); - - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - - /** - * Save the contents of a stream to a file in the sketch folder. - * This is basically saveBytes(blah, loadBytes()), but done - * more efficiently (and with less confusing syntax). - */ - public boolean saveStream(String targetFilename, String sourceLocation) { - return saveStream(saveFile(targetFilename), sourceLocation); - } - - - /** - * Identical to the other saveStream(), but writes to a File - * object, for greater control over the file location. - * Note that unlike other api methods, this will not automatically - * compress or uncompress gzip files. - */ - public boolean saveStream(File targetFile, String sourceLocation) { - return saveStream(targetFile, createInputRaw(sourceLocation)); - } - - - public boolean saveStream(String targetFilename, InputStream sourceStream) { - return saveStream(saveFile(targetFilename), sourceStream); - } - - - static public boolean saveStream(File target, InputStream source) { - File tempFile = null; - try { - // make sure that this path actually exists before writing - createPath(target); - tempFile = createTempFile(target); - FileOutputStream targetStream = new FileOutputStream(tempFile); - - saveStream(targetStream, source); - targetStream.close(); - targetStream = null; - - if (target.exists()) { - if (!target.delete()) { - System.err.println("Could not replace " + - target.getAbsolutePath() + "."); - } - } - if (!tempFile.renameTo(target)) { - System.err.println("Could not rename temporary file " + - tempFile.getAbsolutePath()); - return false; - } - return true; - - } catch (IOException e) { - if (tempFile != null) { - tempFile.delete(); - } - e.printStackTrace(); - return false; - } - } - - - static public void saveStream(OutputStream target, - InputStream source) throws IOException { - BufferedInputStream bis = new BufferedInputStream(source, 16384); - BufferedOutputStream bos = new BufferedOutputStream(target); - - byte[] buffer = new byte[8192]; - int bytesRead; - while ((bytesRead = bis.read(buffer)) != -1) { - bos.write(buffer, 0, bytesRead); - } - - bos.flush(); - } - - - /** - * Saves bytes to a file to inside the sketch folder. - * The filename can be a relative path, i.e. "poo/bytefun.txt" - * would save to a file named "bytefun.txt" to a subfolder - * called 'poo' inside the sketch folder. If the in-between - * subfolders don't exist, they'll be created. - */ - public void saveBytes(String filename, byte[] data) { - saveBytes(saveFile(filename), data); - } - - - /** - * Creates a temporary file based on the name/extension of another file - * and in the same parent directory. Ensures that the same extension is used - * (i.e. so that .gz files are gzip compressed on output) and that it's done - * from the same directory so that renaming the file later won't cross file - * system boundaries. - */ - static private File createTempFile(File file) throws IOException { - File parentDir = file.getParentFile(); - String name = file.getName(); - String prefix; - String suffix = null; - int dot = name.lastIndexOf('.'); - if (dot == -1) { - prefix = name; - } else { - // preserve the extension so that .gz works properly - prefix = name.substring(0, dot); - suffix = name.substring(dot); - } - // Prefix must be three characters - if (prefix.length() < 3) { - prefix += "processing"; - } - return File.createTempFile(prefix, suffix, parentDir); - } - - - /** - * Saves bytes to a specific File location specified by the user. - */ - static public void saveBytes(File file, byte[] data) { - File tempFile = null; - try { - tempFile = createTempFile(file); - - OutputStream output = createOutput(tempFile); - saveBytes(output, data); - output.close(); - output = null; - - if (file.exists()) { - if (!file.delete()) { - System.err.println("Could not replace " + file.getAbsolutePath()); - } - } - - if (!tempFile.renameTo(file)) { - System.err.println("Could not rename temporary file " + - tempFile.getAbsolutePath()); - } - - } catch (IOException e) { - System.err.println("error saving bytes to " + file); - if (tempFile != null) { - tempFile.delete(); - } - e.printStackTrace(); - } - } - - - /** - * Spews a buffer of bytes to an OutputStream. - */ - static public void saveBytes(OutputStream output, byte[] data) { - try { - output.write(data); - output.flush(); - - } catch (IOException e) { - e.printStackTrace(); - } - } - - // - - public void saveStrings(String filename, String strings[]) { - saveStrings(saveFile(filename), strings); - } - - - static public void saveStrings(File file, String strings[]) { - try { - String location = file.getAbsolutePath(); - createPath(location); - OutputStream output = new FileOutputStream(location); - if (file.getName().toLowerCase().endsWith(".gz")) { - output = new GZIPOutputStream(output); - } - saveStrings(output, strings); - output.close(); - - } catch (IOException e) { - e.printStackTrace(); - } - } - - - static public void saveStrings(OutputStream output, String strings[]) { - try { - OutputStreamWriter osw = new OutputStreamWriter(output, "UTF-8"); - PrintWriter writer = new PrintWriter(osw); - for (int i = 0; i < strings.length; i++) { - writer.println(strings[i]); - } - writer.flush(); - } catch (UnsupportedEncodingException e) { } // will not happen - } - - - ////////////////////////////////////////////////////////////// - - - /** - * Prepend the sketch folder path to the filename (or path) that is - * passed in. External libraries should use this function to save to - * the sketch folder. - *

      - * Note that when running as an applet inside a web browser, - * the sketchPath will be set to null, because security restrictions - * prevent applets from accessing that information. - *

      - * This will also cause an error if the sketch is not inited properly, - * meaning that init() was never called on the PApplet when hosted - * my some other main() or by other code. For proper use of init(), - * see the examples in the main description text for PApplet. - */ - public String sketchPath(String where) { - if (sketchPath == null) { - return where; -// throw new RuntimeException("The applet was not inited properly, " + -// "or security restrictions prevented " + -// "it from determining its path."); - } - - // isAbsolute() could throw an access exception, but so will writing - // to the local disk using the sketch path, so this is safe here. - // for 0120, added a try/catch anyways. - try { - if (new File(where).isAbsolute()) return where; - } catch (Exception e) { } - - return surface.getFileStreamPath(where).getAbsolutePath(); - } - - - public File sketchFile(String where) { - return new File(sketchPath(where)); - } - - - /** - * Returns a path inside the applet folder to save to. Like sketchPath(), - * but creates any in-between folders so that things save properly. - *

      - * All saveXxxx() functions use the path to the sketch folder, rather than - * its data folder. Once exported, the data folder will be found inside the - * jar file of the exported application or applet. In this case, it's not - * possible to save data into the jar file, because it will often be running - * from a server, or marked in-use if running from a local file system. - * With this in mind, saving to the data path doesn't make sense anyway. - * If you know you're running locally, and want to save to the data folder, - * use saveXxxx("data/blah.dat"). - */ - public String savePath(String where) { - if (where == null) return null; -// System.out.println("filename before sketchpath is " + where); - String filename = sketchPath(where); -// System.out.println("filename after sketchpath is " + filename); - createPath(filename); - return filename; - } - - - /** - * Identical to savePath(), but returns a File object. - */ - public File saveFile(String where) { - return new File(savePath(where)); - } - - - /** - * Return a full path to an item in the data folder. - *

      - * The behavior of this function differs from the equivalent on the Java mode: files stored in - * the data folder of the sketch get packed as assets in the apk, and the path to the data folder - * is no longer valid. Only the name is needed to open them. However, if the file is not an asset, - * we can assume it has been created by the sketch, so it should have the sketch path. - * Discussed here: - * https://github.com/processing/processing-android/issues/450 - */ - public String dataPath(String where) { - // First, we check if it is asset: - boolean isAsset = false; - AssetManager assets = surface.getAssets(); - InputStream is = null; - try { - is = assets.open(where); - isAsset = true; - } catch (IOException ex) { - //file does not exist - } finally { - try { - is.close(); - } catch (Exception ex) { } - } - if (isAsset) return where; - // Not an asset, let's just use sketch path: - return sketchPath(where); - } - - - /** - * Return a full path to an item in the data folder as a File object. - * See the dataPath() method for more information. - */ - public File dataFile(String where) { - return new File(dataPath(where)); - } - - - /** - * Takes a path and creates any in-between folders if they don't - * already exist. Useful when trying to save to a subfolder that - * may not actually exist. - */ - static public void createPath(String path) { - createPath(new File(path)); - } - - - static public void createPath(File file) { - try { - String parent = file.getParent(); - if (parent != null) { - File unit = new File(parent); - if (!unit.exists()) unit.mkdirs(); - } - } catch (SecurityException se) { - System.err.println("You don't have permissions to create " + file.getAbsolutePath()); - } - } - - - static public String getExtension(String filename) { - String extension; - - String lower = filename.toLowerCase(); - int dot = filename.lastIndexOf('.'); - if (dot == -1) { - extension = "unknown"; // no extension found - } - extension = lower.substring(dot + 1); - - // check for, and strip any parameters on the url, i.e. - // filename.jpg?blah=blah&something=that - int question = extension.indexOf('?'); - if (question != -1) { - extension = extension.substring(0, question); - } - - return extension; - } - - - ////////////////////////////////////////////////////////////// - - // URL ENCODING - - static public String urlEncode(String what) { - try { - return URLEncoder.encode(what, "UTF-8"); - } catch (UnsupportedEncodingException e) { // oh c'mon - return null; - } - } - - - static public String urlDecode(String what) { - try { - return URLDecoder.decode(what, "UTF-8"); - } catch (UnsupportedEncodingException e) { // safe per the JDK source - return null; - } - } - - - - ////////////////////////////////////////////////////////////// - - // SORT - - - static public byte[] sort(byte what[]) { - return sort(what, what.length); - } - - - static public byte[] sort(byte[] what, int count) { - byte[] outgoing = new byte[what.length]; - System.arraycopy(what, 0, outgoing, 0, what.length); - Arrays.sort(outgoing, 0, count); - return outgoing; - } - - - static public char[] sort(char what[]) { - return sort(what, what.length); - } - - - static public char[] sort(char[] what, int count) { - char[] outgoing = new char[what.length]; - System.arraycopy(what, 0, outgoing, 0, what.length); - Arrays.sort(outgoing, 0, count); - return outgoing; - } - - - static public int[] sort(int what[]) { - return sort(what, what.length); - } - - - static public int[] sort(int[] what, int count) { - int[] outgoing = new int[what.length]; - System.arraycopy(what, 0, outgoing, 0, what.length); - Arrays.sort(outgoing, 0, count); - return outgoing; - } - - - static public float[] sort(float what[]) { - return sort(what, what.length); - } - - - static public float[] sort(float[] what, int count) { - float[] outgoing = new float[what.length]; - System.arraycopy(what, 0, outgoing, 0, what.length); - Arrays.sort(outgoing, 0, count); - return outgoing; - } - - - static public String[] sort(String what[]) { - return sort(what, what.length); - } - - - static public String[] sort(String[] what, int count) { - String[] outgoing = new String[what.length]; - System.arraycopy(what, 0, outgoing, 0, what.length); - Arrays.sort(outgoing, 0, count); - return outgoing; - } - - - - ////////////////////////////////////////////////////////////// - - // ARRAY UTILITIES - - - /** - * Calls System.arraycopy(), included here so that we can - * avoid people needing to learn about the System object - * before they can just copy an array. - */ - static public void arrayCopy(Object src, int srcPosition, - Object dst, int dstPosition, - int length) { - System.arraycopy(src, srcPosition, dst, dstPosition, length); - } - - - /** - * Convenience method for arraycopy(). - * Identical to arraycopy(src, 0, dst, 0, length); - */ - static public void arrayCopy(Object src, Object dst, int length) { - System.arraycopy(src, 0, dst, 0, length); - } - - - /** - * Shortcut to copy the entire contents of - * the source into the destination array. - * Identical to arraycopy(src, 0, dst, 0, src.length); - */ - static public void arrayCopy(Object src, Object dst) { - System.arraycopy(src, 0, dst, 0, Array.getLength(src)); - } - - // - - static public boolean[] expand(boolean list[]) { - return expand(list, list.length << 1); - } - - static public boolean[] expand(boolean list[], int newSize) { - boolean temp[] = new boolean[newSize]; - System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length)); - return temp; - } - - - static public byte[] expand(byte list[]) { - return expand(list, list.length << 1); - } - - static public byte[] expand(byte list[], int newSize) { - byte temp[] = new byte[newSize]; - System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length)); - return temp; - } - - - static public char[] expand(char list[]) { - return expand(list, list.length << 1); - } - - static public char[] expand(char list[], int newSize) { - char temp[] = new char[newSize]; - System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length)); - return temp; - } - - - static public int[] expand(int list[]) { - return expand(list, list.length << 1); - } - - static public int[] expand(int list[], int newSize) { - int temp[] = new int[newSize]; - System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length)); - return temp; - } - - static public long[] expand(long list[]) { - return expand(list, list.length > 0 ? list.length << 1 : 1); - } - - static public long[] expand(long list[], int newSize) { - long temp[] = new long[newSize]; - System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length)); - return temp; - } - - static public float[] expand(float list[]) { - return expand(list, list.length << 1); - } - - static public float[] expand(float list[], int newSize) { - float temp[] = new float[newSize]; - System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length)); - return temp; - } - - static public double[] expand(double list[]) { - return expand(list, list.length > 0 ? list.length << 1 : 1); - } - - static public double[] expand(double list[], int newSize) { - double temp[] = new double[newSize]; - System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length)); - return temp; - } - - static public String[] expand(String list[]) { - return expand(list, list.length << 1); - } - - static public String[] expand(String list[], int newSize) { - String temp[] = new String[newSize]; - // in case the new size is smaller than list.length - System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length)); - return temp; - } - - - static public Object expand(Object array) { - return expand(array, Array.getLength(array) << 1); - } - - static public Object expand(Object list, int newSize) { - Class type = list.getClass().getComponentType(); - Object temp = Array.newInstance(type, newSize); - System.arraycopy(list, 0, temp, 0, - Math.min(Array.getLength(list), newSize)); - return temp; - } - - // - - // contract() has been removed in revision 0124, use subset() instead. - // (expand() is also functionally equivalent) - - // - - static public byte[] append(byte b[], byte value) { - b = expand(b, b.length + 1); - b[b.length-1] = value; - return b; - } - - static public char[] append(char b[], char value) { - b = expand(b, b.length + 1); - b[b.length-1] = value; - return b; - } - - static public int[] append(int b[], int value) { - b = expand(b, b.length + 1); - b[b.length-1] = value; - return b; - } - - static public float[] append(float b[], float value) { - b = expand(b, b.length + 1); - b[b.length-1] = value; - return b; - } - - static public String[] append(String b[], String value) { - b = expand(b, b.length + 1); - b[b.length-1] = value; - return b; - } - - static public Object append(Object b, Object value) { - int length = Array.getLength(b); - b = expand(b, length + 1); - Array.set(b, length, value); - return b; - } - - // - - static public boolean[] shorten(boolean list[]) { - return subset(list, 0, list.length-1); - } - - static public byte[] shorten(byte list[]) { - return subset(list, 0, list.length-1); - } - - static public char[] shorten(char list[]) { - return subset(list, 0, list.length-1); - } - - static public int[] shorten(int list[]) { - return subset(list, 0, list.length-1); - } - - static public float[] shorten(float list[]) { - return subset(list, 0, list.length-1); - } - - static public String[] shorten(String list[]) { - return subset(list, 0, list.length-1); - } - - static public Object shorten(Object list) { - int length = Array.getLength(list); - return subset(list, 0, length - 1); - } - - // - - static final public boolean[] splice(boolean list[], - boolean v, int index) { - boolean outgoing[] = new boolean[list.length + 1]; - System.arraycopy(list, 0, outgoing, 0, index); - outgoing[index] = v; - System.arraycopy(list, index, outgoing, index + 1, - list.length - index); - return outgoing; - } - - static final public boolean[] splice(boolean list[], - boolean v[], int index) { - boolean outgoing[] = new boolean[list.length + v.length]; - System.arraycopy(list, 0, outgoing, 0, index); - System.arraycopy(v, 0, outgoing, index, v.length); - System.arraycopy(list, index, outgoing, index + v.length, - list.length - index); - return outgoing; - } - - - static final public byte[] splice(byte list[], - byte v, int index) { - byte outgoing[] = new byte[list.length + 1]; - System.arraycopy(list, 0, outgoing, 0, index); - outgoing[index] = v; - System.arraycopy(list, index, outgoing, index + 1, - list.length - index); - return outgoing; - } - - static final public byte[] splice(byte list[], - byte v[], int index) { - byte outgoing[] = new byte[list.length + v.length]; - System.arraycopy(list, 0, outgoing, 0, index); - System.arraycopy(v, 0, outgoing, index, v.length); - System.arraycopy(list, index, outgoing, index + v.length, - list.length - index); - return outgoing; - } - - - static final public char[] splice(char list[], - char v, int index) { - char outgoing[] = new char[list.length + 1]; - System.arraycopy(list, 0, outgoing, 0, index); - outgoing[index] = v; - System.arraycopy(list, index, outgoing, index + 1, - list.length - index); - return outgoing; - } - - static final public char[] splice(char list[], - char v[], int index) { - char outgoing[] = new char[list.length + v.length]; - System.arraycopy(list, 0, outgoing, 0, index); - System.arraycopy(v, 0, outgoing, index, v.length); - System.arraycopy(list, index, outgoing, index + v.length, - list.length - index); - return outgoing; - } - - - static final public int[] splice(int list[], - int v, int index) { - int outgoing[] = new int[list.length + 1]; - System.arraycopy(list, 0, outgoing, 0, index); - outgoing[index] = v; - System.arraycopy(list, index, outgoing, index + 1, - list.length - index); - return outgoing; - } - - static final public int[] splice(int list[], - int v[], int index) { - int outgoing[] = new int[list.length + v.length]; - System.arraycopy(list, 0, outgoing, 0, index); - System.arraycopy(v, 0, outgoing, index, v.length); - System.arraycopy(list, index, outgoing, index + v.length, - list.length - index); - return outgoing; - } - - - static final public float[] splice(float list[], - float v, int index) { - float outgoing[] = new float[list.length + 1]; - System.arraycopy(list, 0, outgoing, 0, index); - outgoing[index] = v; - System.arraycopy(list, index, outgoing, index + 1, - list.length - index); - return outgoing; - } - - static final public float[] splice(float list[], - float v[], int index) { - float outgoing[] = new float[list.length + v.length]; - System.arraycopy(list, 0, outgoing, 0, index); - System.arraycopy(v, 0, outgoing, index, v.length); - System.arraycopy(list, index, outgoing, index + v.length, - list.length - index); - return outgoing; - } - - - static final public String[] splice(String list[], - String v, int index) { - String outgoing[] = new String[list.length + 1]; - System.arraycopy(list, 0, outgoing, 0, index); - outgoing[index] = v; - System.arraycopy(list, index, outgoing, index + 1, - list.length - index); - return outgoing; - } - - static final public String[] splice(String list[], - String v[], int index) { - String outgoing[] = new String[list.length + v.length]; - System.arraycopy(list, 0, outgoing, 0, index); - System.arraycopy(v, 0, outgoing, index, v.length); - System.arraycopy(list, index, outgoing, index + v.length, - list.length - index); - return outgoing; - } - - - static final public Object splice(Object list, Object v, int index) { - Object[] outgoing = null; - int length = Array.getLength(list); - - // check whether item being spliced in is an array - if (v.getClass().getName().charAt(0) == '[') { - int vlength = Array.getLength(v); - outgoing = new Object[length + vlength]; - System.arraycopy(list, 0, outgoing, 0, index); - System.arraycopy(v, 0, outgoing, index, vlength); - System.arraycopy(list, index, outgoing, index + vlength, length - index); - - } else { - outgoing = new Object[length + 1]; - System.arraycopy(list, 0, outgoing, 0, index); - Array.set(outgoing, index, v); - System.arraycopy(list, index, outgoing, index + 1, length - index); - } - return outgoing; - } - - // - - static public boolean[] subset(boolean list[], int start) { - return subset(list, start, list.length - start); - } - - static public boolean[] subset(boolean list[], int start, int count) { - boolean output[] = new boolean[count]; - System.arraycopy(list, start, output, 0, count); - return output; - } - - - static public byte[] subset(byte list[], int start) { - return subset(list, start, list.length - start); - } - - static public byte[] subset(byte list[], int start, int count) { - byte output[] = new byte[count]; - System.arraycopy(list, start, output, 0, count); - return output; - } - - - static public char[] subset(char list[], int start) { - return subset(list, start, list.length - start); - } - - static public char[] subset(char list[], int start, int count) { - char output[] = new char[count]; - System.arraycopy(list, start, output, 0, count); - return output; - } - - - static public int[] subset(int list[], int start) { - return subset(list, start, list.length - start); - } - - static public int[] subset(int list[], int start, int count) { - int output[] = new int[count]; - System.arraycopy(list, start, output, 0, count); - return output; - } - - static public long[] subset(long[] list, int start) { - return subset(list, start, list.length - start); - } - - static public long[] subset(long[] list, int start, int count) { - long[] output = new long[count]; - System.arraycopy(list, start, output, 0, count); - return output; - } - - static public float[] subset(float list[], int start) { - return subset(list, start, list.length - start); - } - - static public float[] subset(float list[], int start, int count) { - float output[] = new float[count]; - System.arraycopy(list, start, output, 0, count); - return output; - } - - static public double[] subset(double[] list, int start) { - return subset(list, start, list.length - start); - } - - static public double[] subset(double[] list, int start, int count) { - double[] output = new double[count]; - System.arraycopy(list, start, output, 0, count); - return output; - } - - static public String[] subset(String list[], int start) { - return subset(list, start, list.length - start); - } - - static public String[] subset(String list[], int start, int count) { - String output[] = new String[count]; - System.arraycopy(list, start, output, 0, count); - return output; - } - - - static public Object subset(Object list, int start) { - int length = Array.getLength(list); - return subset(list, start, length - start); - } - - static public Object subset(Object list, int start, int count) { - Class type = list.getClass().getComponentType(); - Object outgoing = Array.newInstance(type, count); - System.arraycopy(list, start, outgoing, 0, count); - return outgoing; - } - - // - - static public boolean[] concat(boolean a[], boolean b[]) { - boolean c[] = new boolean[a.length + b.length]; - System.arraycopy(a, 0, c, 0, a.length); - System.arraycopy(b, 0, c, a.length, b.length); - return c; - } - - static public byte[] concat(byte a[], byte b[]) { - byte c[] = new byte[a.length + b.length]; - System.arraycopy(a, 0, c, 0, a.length); - System.arraycopy(b, 0, c, a.length, b.length); - return c; - } - - static public char[] concat(char a[], char b[]) { - char c[] = new char[a.length + b.length]; - System.arraycopy(a, 0, c, 0, a.length); - System.arraycopy(b, 0, c, a.length, b.length); - return c; - } - - static public int[] concat(int a[], int b[]) { - int c[] = new int[a.length + b.length]; - System.arraycopy(a, 0, c, 0, a.length); - System.arraycopy(b, 0, c, a.length, b.length); - return c; - } - - static public float[] concat(float a[], float b[]) { - float c[] = new float[a.length + b.length]; - System.arraycopy(a, 0, c, 0, a.length); - System.arraycopy(b, 0, c, a.length, b.length); - return c; - } - - static public String[] concat(String a[], String b[]) { - String c[] = new String[a.length + b.length]; - System.arraycopy(a, 0, c, 0, a.length); - System.arraycopy(b, 0, c, a.length, b.length); - return c; - } - - static public Object concat(Object a, Object b) { - Class type = a.getClass().getComponentType(); - int alength = Array.getLength(a); - int blength = Array.getLength(b); - Object outgoing = Array.newInstance(type, alength + blength); - System.arraycopy(a, 0, outgoing, 0, alength); - System.arraycopy(b, 0, outgoing, alength, blength); - return outgoing; - } - - // - - static public boolean[] reverse(boolean list[]) { - boolean outgoing[] = new boolean[list.length]; - int length1 = list.length - 1; - for (int i = 0; i < list.length; i++) { - outgoing[i] = list[length1 - i]; - } - return outgoing; - } - - static public byte[] reverse(byte list[]) { - byte outgoing[] = new byte[list.length]; - int length1 = list.length - 1; - for (int i = 0; i < list.length; i++) { - outgoing[i] = list[length1 - i]; - } - return outgoing; - } - - static public char[] reverse(char list[]) { - char outgoing[] = new char[list.length]; - int length1 = list.length - 1; - for (int i = 0; i < list.length; i++) { - outgoing[i] = list[length1 - i]; - } - return outgoing; - } - - static public int[] reverse(int list[]) { - int outgoing[] = new int[list.length]; - int length1 = list.length - 1; - for (int i = 0; i < list.length; i++) { - outgoing[i] = list[length1 - i]; - } - return outgoing; - } - - static public float[] reverse(float list[]) { - float outgoing[] = new float[list.length]; - int length1 = list.length - 1; - for (int i = 0; i < list.length; i++) { - outgoing[i] = list[length1 - i]; - } - return outgoing; - } - - static public String[] reverse(String list[]) { - String outgoing[] = new String[list.length]; - int length1 = list.length - 1; - for (int i = 0; i < list.length; i++) { - outgoing[i] = list[length1 - i]; - } - return outgoing; - } - - static public Object reverse(Object list) { - Class type = list.getClass().getComponentType(); - int length = Array.getLength(list); - Object outgoing = Array.newInstance(type, length); - for (int i = 0; i < length; i++) { - Array.set(outgoing, i, Array.get(list, (length - 1) - i)); - } - return outgoing; - } - - - - ////////////////////////////////////////////////////////////// - - // STRINGS - - - /** - * Remove whitespace characters from the beginning and ending - * of a String. Works like String.trim() but includes the - * unicode nbsp character as well. - */ - static public String trim(String str) { - return str.replace('\u00A0', ' ').trim(); - } - - - /** - * Trim the whitespace from a String array. This returns a new - * array and does not affect the passed-in array. - */ - static public String[] trim(String[] array) { - String[] outgoing = new String[array.length]; - for (int i = 0; i < array.length; i++) { - if (array[i] != null) { - outgoing[i] = array[i].replace('\u00A0', ' ').trim(); - } - } - return outgoing; - } - - - /** - * Join an array of Strings together as a single String, - * separated by the whatever's passed in for the separator. - */ - static public String join(String str[], char separator) { - return join(str, String.valueOf(separator)); - } - - - /** - * Join an array of Strings together as a single String, - * separated by the whatever's passed in for the separator. - *

      - * To use this on numbers, first pass the array to nf() or nfs() - * to get a list of String objects, then use join on that. - *

      -   * e.g. String stuff[] = { "apple", "bear", "cat" };
      -   *      String list = join(stuff, ", ");
      -   *      // list is now "apple, bear, cat"
      - */ - static public String join(String str[], String separator) { - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < str.length; i++) { - if (i != 0) buffer.append(separator); - buffer.append(str[i]); - } - return buffer.toString(); - } - - - /** - * Split the provided String at wherever whitespace occurs. - * Multiple whitespace (extra spaces or tabs or whatever) - * between items will count as a single break. - *

      - * The whitespace characters are "\t\n\r\f", which are the defaults - * for java.util.StringTokenizer, plus the unicode non-breaking space - * character, which is found commonly on files created by or used - * in conjunction with Mac OS X (character 160, or 0x00A0 in hex). - *

      -   * i.e. splitTokens("a b") -> { "a", "b" }
      -   *      splitTokens("a    b") -> { "a", "b" }
      -   *      splitTokens("a\tb") -> { "a", "b" }
      -   *      splitTokens("a \t  b  ") -> { "a", "b" }
      - */ - static public String[] splitTokens(String what) { - return splitTokens(what, WHITESPACE); - } - - - /** - * Splits a string into pieces, using any of the chars in the - * String 'delim' as separator characters. For instance, - * in addition to white space, you might want to treat commas - * as a separator. The delimeter characters won't appear in - * the returned String array. - *
      -   * i.e. splitTokens("a, b", " ,") -> { "a", "b" }
      -   * 
      - * To include all the whitespace possibilities, use the variable - * WHITESPACE, found in PConstants: - *
      -   * i.e. splitTokens("a   | b", WHITESPACE + "|");  ->  { "a", "b" }
      - */ - static public String[] splitTokens(String what, String delim) { - StringTokenizer toker = new StringTokenizer(what, delim); - String pieces[] = new String[toker.countTokens()]; - - int index = 0; - while (toker.hasMoreTokens()) { - pieces[index++] = toker.nextToken(); - } - return pieces; - } - - - /** - * Split a string into pieces along a specific character. - * Most commonly used to break up a String along a space or a tab - * character. - *

      - * This operates differently than the others, where the - * single delimeter is the only breaking point, and consecutive - * delimeters will produce an empty string (""). This way, - * one can split on tab characters, but maintain the column - * alignments (of say an excel file) where there are empty columns. - */ - static public String[] split(String what, char delim) { - // do this so that the exception occurs inside the user's - // program, rather than appearing to be a bug inside split() - if (what == null) return null; - //return split(what, String.valueOf(delim)); // huh - - char chars[] = what.toCharArray(); - int splitCount = 0; //1; - for (int i = 0; i < chars.length; i++) { - if (chars[i] == delim) splitCount++; - } - // make sure that there is something in the input string - //if (chars.length > 0) { - // if the last char is a delimeter, get rid of it.. - //if (chars[chars.length-1] == delim) splitCount--; - // on second thought, i don't agree with this, will disable - //} - if (splitCount == 0) { - String splits[] = new String[1]; - splits[0] = new String(what); - return splits; - } - //int pieceCount = splitCount + 1; - String splits[] = new String[splitCount + 1]; - int splitIndex = 0; - int startIndex = 0; - for (int i = 0; i < chars.length; i++) { - if (chars[i] == delim) { - splits[splitIndex++] = - new String(chars, startIndex, i-startIndex); - startIndex = i + 1; - } - } - //if (startIndex != chars.length) { - splits[splitIndex] = - new String(chars, startIndex, chars.length-startIndex); - //} - return splits; - } - - - /** - * Split a String on a specific delimiter. Unlike Java's String.split() - * method, this does not parse the delimiter as a regexp because it's more - * confusing than necessary, and String.split() is always available for - * those who want regexp. - */ - static public String[] split(String what, String delim) { - ArrayList items = new ArrayList(); - int index; - int offset = 0; - while ((index = what.indexOf(delim, offset)) != -1) { - items.add(what.substring(offset, index)); - offset = index + delim.length(); - } - items.add(what.substring(offset)); - String[] outgoing = new String[items.size()]; - items.toArray(outgoing); - return outgoing; - } - - - static protected HashMap matchPatterns; - - static Pattern matchPattern(String regexp) { - Pattern p = null; - if (matchPatterns == null) { - matchPatterns = new HashMap(); - } else { - p = matchPatterns.get(regexp); - } - if (p == null) { - if (matchPatterns.size() == 10) { - // Just clear out the match patterns here if more than 10 are being - // used. It's not terribly efficient, but changes that you have >10 - // different match patterns are very slim, unless you're doing - // something really tricky (like custom match() methods), in which - // case match() won't be efficient anyway. (And you should just be - // using your own Java code.) The alternative is using a queue here, - // but that's a silly amount of work for negligible benefit. - matchPatterns.clear(); - } - p = Pattern.compile(regexp, Pattern.MULTILINE | Pattern.DOTALL); - matchPatterns.put(regexp, p); - } - return p; - } - - - /** - * Match a string with a regular expression, and returns the match as an - * array. The first index is the matching expression, and array elements - * [1] and higher represent each of the groups (sequences found in parens). - * - * This uses multiline matching (Pattern.MULTILINE) and dotall mode - * (Pattern.DOTALL) by default, so that ^ and $ match the beginning and - * end of any lines found in the source, and the . operator will also - * pick up newline characters. - */ - static public String[] match(String what, String regexp) { - Pattern p = matchPattern(regexp); - Matcher m = p.matcher(what); - if (m.find()) { - int count = m.groupCount() + 1; - String[] groups = new String[count]; - for (int i = 0; i < count; i++) { - groups[i] = m.group(i); - } - return groups; - } - return null; - } - - - /** - * Identical to match(), except that it returns an array of all matches in - * the specified String, rather than just the first. - */ - static public String[][] matchAll(String what, String regexp) { - Pattern p = matchPattern(regexp); - Matcher m = p.matcher(what); - ArrayList results = new ArrayList(); - int count = m.groupCount() + 1; - while (m.find()) { - String[] groups = new String[count]; - for (int i = 0; i < count; i++) { - groups[i] = m.group(i); - } - results.add(groups); - } - if (results.isEmpty()) { - return null; - } - String[][] matches = new String[results.size()][count]; - for (int i = 0; i < matches.length; i++) { - matches[i] = (String[]) results.get(i); - } - return matches; - } - - - - ////////////////////////////////////////////////////////////// - - // CASTING FUNCTIONS, INSERTED BY PREPROC - - - /** - * Convert a char to a boolean. 'T', 't', and '1' will become the - * boolean value true, while 'F', 'f', or '0' will become false. - */ - /* - static final public boolean parseBoolean(char what) { - return ((what == 't') || (what == 'T') || (what == '1')); - } - */ - - /** - *

      Convert an integer to a boolean. Because of how Java handles upgrading - * numbers, this will also cover byte and char (as they will upgrade to - * an int without any sort of explicit cast).

      - *

      The preprocessor will convert boolean(what) to parseBoolean(what).

      - * @return false if 0, true if any other number - */ - static final public boolean parseBoolean(int what) { - return (what != 0); - } - - /* - // removed because this makes no useful sense - static final public boolean parseBoolean(float what) { - return (what != 0); - } - */ - - /** - * Convert the string "true" or "false" to a boolean. - * @return true if 'what' is "true" or "TRUE", false otherwise - */ - static final public boolean parseBoolean(String what) { - return Boolean.valueOf(what); - } - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - /* - // removed, no need to introduce strange syntax from other languages - static final public boolean[] parseBoolean(char what[]) { - boolean outgoing[] = new boolean[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = - ((what[i] == 't') || (what[i] == 'T') || (what[i] == '1')); - } - return outgoing; - } - */ - - /** - * Convert a byte array to a boolean array. Each element will be - * evaluated identical to the integer case, where a byte equal - * to zero will return false, and any other value will return true. - * @return array of boolean elements - */ - static final public boolean[] parseBoolean(byte what[]) { - boolean outgoing[] = new boolean[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = (what[i] != 0); - } - return outgoing; - } - - /** - * Convert an int array to a boolean array. An int equal - * to zero will return false, and any other value will return true. - * @return array of boolean elements - */ - static final public boolean[] parseBoolean(int what[]) { - boolean outgoing[] = new boolean[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = (what[i] != 0); - } - return outgoing; - } - - /* - // removed, not necessary... if necessary, convert to int array first - static final public boolean[] parseBoolean(float what[]) { - boolean outgoing[] = new boolean[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = (what[i] != 0); - } - return outgoing; - } - */ - - static final public boolean[] parseBoolean(String what[]) { - boolean outgoing[] = new boolean[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = Boolean.valueOf(what[i]); - } - return outgoing; - } - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - static final public byte parseByte(boolean what) { - return what ? (byte)1 : 0; - } - - static final public byte parseByte(char what) { - return (byte) what; - } - - static final public byte parseByte(int what) { - return (byte) what; - } - - static final public byte parseByte(float what) { - return (byte) what; - } - - /* - // nixed, no precedent - static final public byte[] parseByte(String what) { // note: array[] - return what.getBytes(); - } - */ - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - static final public byte[] parseByte(boolean what[]) { - byte outgoing[] = new byte[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = what[i] ? (byte)1 : 0; - } - return outgoing; - } - - static final public byte[] parseByte(char what[]) { - byte outgoing[] = new byte[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = (byte) what[i]; - } - return outgoing; - } - - static final public byte[] parseByte(int what[]) { - byte outgoing[] = new byte[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = (byte) what[i]; - } - return outgoing; - } - - static final public byte[] parseByte(float what[]) { - byte outgoing[] = new byte[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = (byte) what[i]; - } - return outgoing; - } - - /* - static final public byte[][] parseByte(String what[]) { // note: array[][] - byte outgoing[][] = new byte[what.length][]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = what[i].getBytes(); - } - return outgoing; - } - */ - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - /* - static final public char parseChar(boolean what) { // 0/1 or T/F ? - return what ? 't' : 'f'; - } - */ - - static final public char parseChar(byte what) { - return (char) (what & 0xff); - } - - static final public char parseChar(int what) { - return (char) what; - } - - /* - static final public char parseChar(float what) { // nonsensical - return (char) what; - } - - static final public char[] parseChar(String what) { // note: array[] - return what.toCharArray(); - } - */ - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - /* - static final public char[] parseChar(boolean what[]) { // 0/1 or T/F ? - char outgoing[] = new char[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = what[i] ? 't' : 'f'; - } - return outgoing; - } - */ - - static final public char[] parseChar(byte what[]) { - char outgoing[] = new char[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = (char) (what[i] & 0xff); - } - return outgoing; - } - - static final public char[] parseChar(int what[]) { - char outgoing[] = new char[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = (char) what[i]; - } - return outgoing; - } - - /* - static final public char[] parseChar(float what[]) { // nonsensical - char outgoing[] = new char[what.length]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = (char) what[i]; - } - return outgoing; - } - - static final public char[][] parseChar(String what[]) { // note: array[][] - char outgoing[][] = new char[what.length][]; - for (int i = 0; i < what.length; i++) { - outgoing[i] = what[i].toCharArray(); - } - return outgoing; - } - */ - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - static final public int parseInt(boolean what) { - return what ? 1 : 0; - } - - /** - * Note that parseInt() will un-sign a signed byte value. - */ - static final public int parseInt(byte what) { - return what & 0xff; - } - - /** - * Note that parseInt('5') is unlike String in the sense that it - * won't return 5, but the ascii value. This is because ((int) someChar) - * returns the ascii value, and parseInt() is just longhand for the cast. - */ - static final public int parseInt(char what) { - return what; - } - - /** - * Same as floor(), or an (int) cast. - */ - static final public int parseInt(float what) { - return (int) what; - } - - /** - * Parse a String into an int value. Returns 0 if the value is bad. - */ - static final public int parseInt(String what) { - return parseInt(what, 0); - } - - /** - * Parse a String to an int, and provide an alternate value that - * should be used when the number is invalid. - */ - static final public int parseInt(String what, int otherwise) { - try { - int offset = what.indexOf('.'); - if (offset == -1) { - return Integer.parseInt(what); - } else { - return Integer.parseInt(what.substring(0, offset)); - } - } catch (NumberFormatException e) { } - return otherwise; - } - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - static final public int[] parseInt(boolean what[]) { - int list[] = new int[what.length]; - for (int i = 0; i < what.length; i++) { - list[i] = what[i] ? 1 : 0; - } - return list; - } - - static final public int[] parseInt(byte what[]) { // note this unsigns - int list[] = new int[what.length]; - for (int i = 0; i < what.length; i++) { - list[i] = (what[i] & 0xff); - } - return list; - } - - static final public int[] parseInt(char what[]) { - int list[] = new int[what.length]; - for (int i = 0; i < what.length; i++) { - list[i] = what[i]; - } - return list; - } - - static public int[] parseInt(float what[]) { - int inties[] = new int[what.length]; - for (int i = 0; i < what.length; i++) { - inties[i] = (int)what[i]; - } - return inties; - } - - /** - * Make an array of int elements from an array of String objects. - * If the String can't be parsed as a number, it will be set to zero. - * - * String s[] = { "1", "300", "44" }; - * int numbers[] = parseInt(s); - * - * numbers will contain { 1, 300, 44 } - */ - static public int[] parseInt(String what[]) { - return parseInt(what, 0); - } - - /** - * Make an array of int elements from an array of String objects. - * If the String can't be parsed as a number, its entry in the - * array will be set to the value of the "missing" parameter. - * - * String s[] = { "1", "300", "apple", "44" }; - * int numbers[] = parseInt(s, 9999); - * - * numbers will contain { 1, 300, 9999, 44 } - */ - static public int[] parseInt(String what[], int missing) { - int output[] = new int[what.length]; - for (int i = 0; i < what.length; i++) { - try { - output[i] = Integer.parseInt(what[i]); - } catch (NumberFormatException e) { - output[i] = missing; - } - } - return output; - } - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - /* - static final public float parseFloat(boolean what) { - return what ? 1 : 0; - } - */ - - /** - * Convert an int to a float value. Also handles bytes because of - * Java's rules for upgrading values. - */ - static final public float parseFloat(int what) { // also handles byte - return (float)what; - } - - static final public float parseFloat(String what) { - return parseFloat(what, Float.NaN); - } - - static final public float parseFloat(String what, float otherwise) { - try { - return Float.valueOf(what); - } catch (NumberFormatException e) { } - - return otherwise; - } - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - /* - static final public float[] parseFloat(boolean what[]) { - float floaties[] = new float[what.length]; - for (int i = 0; i < what.length; i++) { - floaties[i] = what[i] ? 1 : 0; - } - return floaties; - } - - static final public float[] parseFloat(char what[]) { - float floaties[] = new float[what.length]; - for (int i = 0; i < what.length; i++) { - floaties[i] = (char) what[i]; - } - return floaties; - } - */ - - static final public float[] parseByte(byte what[]) { - float floaties[] = new float[what.length]; - for (int i = 0; i < what.length; i++) { - floaties[i] = what[i]; - } - return floaties; - } - - static final public float[] parseFloat(int what[]) { - float floaties[] = new float[what.length]; - for (int i = 0; i < what.length; i++) { - floaties[i] = what[i]; - } - return floaties; - } - - static final public float[] parseFloat(String what[]) { - return parseFloat(what, Float.NaN); - } - - static final public float[] parseFloat(String what[], float missing) { - float output[] = new float[what.length]; - for (int i = 0; i < what.length; i++) { - try { - output[i] = Float.valueOf(what[i]); - } catch (NumberFormatException e) { - output[i] = missing; - } - } - return output; - } - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - static final public String str(boolean x) { - return String.valueOf(x); - } - - static final public String str(byte x) { - return String.valueOf(x); - } - - static final public String str(char x) { - return String.valueOf(x); - } - - static final public String str(int x) { - return String.valueOf(x); - } - - static final public String str(float x) { - return String.valueOf(x); - } - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - static final public String[] str(boolean x[]) { - String s[] = new String[x.length]; - for (int i = 0; i < x.length; i++) s[i] = String.valueOf(x[i]); - return s; - } - - static final public String[] str(byte x[]) { - String s[] = new String[x.length]; - for (int i = 0; i < x.length; i++) s[i] = String.valueOf(x[i]); - return s; - } - - static final public String[] str(char x[]) { - String s[] = new String[x.length]; - for (int i = 0; i < x.length; i++) s[i] = String.valueOf(x[i]); - return s; - } - - static final public String[] str(int x[]) { - String s[] = new String[x.length]; - for (int i = 0; i < x.length; i++) s[i] = String.valueOf(x[i]); - return s; - } - - static final public String[] str(float x[]) { - String s[] = new String[x.length]; - for (int i = 0; i < x.length; i++) s[i] = String.valueOf(x[i]); - return s; - } - - - ////////////////////////////////////////////////////////////// - - // INT NUMBER FORMATTING - - - /** - * Integer number formatter. - */ - static private NumberFormat int_nf; - static private int int_nf_digits; - static private boolean int_nf_commas; - - - static public String[] nf(int num[], int digits) { - String formatted[] = new String[num.length]; - for (int i = 0; i < formatted.length; i++) { - formatted[i] = nf(num[i], digits); - } - return formatted; - } - - - static public String nf(int num, int digits) { - if ((int_nf != null) && - (int_nf_digits == digits) && - !int_nf_commas) { - return int_nf.format(num); - } - - int_nf = NumberFormat.getInstance(); - int_nf.setGroupingUsed(false); // no commas - int_nf_commas = false; - int_nf.setMinimumIntegerDigits(digits); - int_nf_digits = digits; - return int_nf.format(num); - } - - - static public String[] nfc(int num[]) { - String formatted[] = new String[num.length]; - for (int i = 0; i < formatted.length; i++) { - formatted[i] = nfc(num[i]); - } - return formatted; - } - - - static public String nfc(int num) { - if ((int_nf != null) && - (int_nf_digits == 0) && - int_nf_commas) { - return int_nf.format(num); - } - - int_nf = NumberFormat.getInstance(); - int_nf.setGroupingUsed(true); - int_nf_commas = true; - int_nf.setMinimumIntegerDigits(0); - int_nf_digits = 0; - return int_nf.format(num); - } - - - /** - * number format signed (or space) - * Formats a number but leaves a blank space in the front - * when it's positive so that it can be properly aligned with - * numbers that have a negative sign in front of them. - */ - static public String nfs(int num, int digits) { - return (num < 0) ? nf(num, digits) : (' ' + nf(num, digits)); - } - - static public String[] nfs(int num[], int digits) { - String formatted[] = new String[num.length]; - for (int i = 0; i < formatted.length; i++) { - formatted[i] = nfs(num[i], digits); - } - return formatted; - } - - // - - /** - * number format positive (or plus) - * Formats a number, always placing a - or + sign - * in the front when it's negative or positive. - */ - static public String nfp(int num, int digits) { - return (num < 0) ? nf(num, digits) : ('+' + nf(num, digits)); - } - - static public String[] nfp(int num[], int digits) { - String formatted[] = new String[num.length]; - for (int i = 0; i < formatted.length; i++) { - formatted[i] = nfp(num[i], digits); - } - return formatted; - } - - - - ////////////////////////////////////////////////////////////// - - // FLOAT NUMBER FORMATTING - - - static private NumberFormat float_nf; - static private int float_nf_left, float_nf_right; - static private boolean float_nf_commas; - - - static public String[] nf(float num[], int left, int right) { - String formatted[] = new String[num.length]; - for (int i = 0; i < formatted.length; i++) { - formatted[i] = nf(num[i], left, right); - } - return formatted; - } - - - static public String nf(float num, int left, int right) { - if ((float_nf != null) && - (float_nf_left == left) && - (float_nf_right == right) && - !float_nf_commas) { - return float_nf.format(num); - } - - float_nf = NumberFormat.getInstance(); - float_nf.setGroupingUsed(false); - float_nf_commas = false; - - if (left != 0) float_nf.setMinimumIntegerDigits(left); - if (right != 0) { - float_nf.setMinimumFractionDigits(right); - float_nf.setMaximumFractionDigits(right); - } - float_nf_left = left; - float_nf_right = right; - return float_nf.format(num); - } - - - static public String[] nfc(float num[], int right) { - String formatted[] = new String[num.length]; - for (int i = 0; i < formatted.length; i++) { - formatted[i] = nfc(num[i], right); - } - return formatted; - } - - - static public String nfc(float num, int right) { - if ((float_nf != null) && - (float_nf_left == 0) && - (float_nf_right == right) && - float_nf_commas) { - return float_nf.format(num); - } - - float_nf = NumberFormat.getInstance(); - float_nf.setGroupingUsed(true); - float_nf_commas = true; - - if (right != 0) { - float_nf.setMinimumFractionDigits(right); - float_nf.setMaximumFractionDigits(right); - } - float_nf_left = 0; - float_nf_right = right; - return float_nf.format(num); - } - - - /** - * Number formatter that takes into account whether the number - * has a sign (positive, negative, etc) in front of it. - */ - static public String[] nfs(float num[], int left, int right) { - String formatted[] = new String[num.length]; - for (int i = 0; i < formatted.length; i++) { - formatted[i] = nfs(num[i], left, right); - } - return formatted; - } - - static public String nfs(float num, int left, int right) { - return (num < 0) ? nf(num, left, right) : (' ' + nf(num, left, right)); - } - - - static public String[] nfp(float num[], int left, int right) { - String formatted[] = new String[num.length]; - for (int i = 0; i < formatted.length; i++) { - formatted[i] = nfp(num[i], left, right); - } - return formatted; - } - - static public String nfp(float num, int left, int right) { - return (num < 0) ? nf(num, left, right) : ('+' + nf(num, left, right)); - } - - - - ////////////////////////////////////////////////////////////// - - // HEX/BINARY CONVERSION - - - /** - * Convert a byte into a two digit hex string. - */ - static final public String hex(byte what) { - return hex(what, 2); - } - - /** - * Convert a Unicode character into a four digit hex string. - */ - static final public String hex(char what) { - return hex(what, 4); - } - - /** - * Convert an integer into an eight digit hex string. - */ - static final public String hex(int what) { - return hex(what, 8); - } - - /** - * Format an integer as a hex string using the specified number of digits. - * @param what the value to format - * @param digits the number of digits (maximum 8) - * @return a String object with the formatted values - */ - static final public String hex(int what, int digits) { - String stuff = Integer.toHexString(what).toUpperCase(); - if (digits > 8) { - digits = 8; - } - - int length = stuff.length(); - if (length > digits) { - return stuff.substring(length - digits); - - } else if (length < digits) { - return "00000000".substring(8 - (digits-length)) + stuff; - } - return stuff; - } - - static final public int unhex(String what) { - // has to parse as a Long so that it'll work for numbers bigger than 2^31 - return (int) (Long.parseLong(what, 16)); - } - - // - - /** - * Returns a String that contains the binary value of a byte. - * The returned value will always have 8 digits. - */ - static final public String binary(byte what) { - return binary(what, 8); - } - - /** - * Returns a String that contains the binary value of a char. - * The returned value will always have 16 digits because chars - * are two bytes long. - */ - static final public String binary(char what) { - return binary(what, 16); - } - - /** - * Returns a String that contains the binary value of an int. The length - * depends on the size of the number itself. If you want a specific number - * of digits use binary(int what, int digits) to specify how many. - */ - static final public String binary(int what) { - return binary(what, 32); - } - - /** - * Returns a String that contains the binary value of an int. - * The digits parameter determines how many digits will be used. - */ - static final public String binary(int what, int digits) { - String stuff = Integer.toBinaryString(what); - if (digits > 32) { - digits = 32; - } - - int length = stuff.length(); - if (length > digits) { - return stuff.substring(length - digits); - - } else if (length < digits) { - int offset = 32 - (digits-length); - return "00000000000000000000000000000000".substring(offset) + stuff; - } - return stuff; - } - - - /** - * Unpack a binary String into an int. - * i.e. unbinary("00001000") would return 8. - */ - static final public int unbinary(String what) { - return Integer.parseInt(what, 2); - } - - - - ////////////////////////////////////////////////////////////// - - // COLOR FUNCTIONS - - // moved here so that they can work without - // the graphics actually being instantiated (outside setup) - - - public final int color(int gray) { - if (g == null) { - if (gray > 255) gray = 255; else if (gray < 0) gray = 0; - return 0xff000000 | (gray << 16) | (gray << 8) | gray; - } - return g.color(gray); - } - - - public final int color(float fgray) { - if (g == null) { - int gray = (int) fgray; - if (gray > 255) gray = 255; else if (gray < 0) gray = 0; - return 0xff000000 | (gray << 16) | (gray << 8) | gray; - } - return g.color(fgray); - } - - - /** - * As of 0116 this also takes color(#FF8800, alpha) - */ - public final int color(int gray, int alpha) { - if (g == null) { - if (alpha > 255) alpha = 255; else if (alpha < 0) alpha = 0; - if (gray > 255) { - // then assume this is actually a #FF8800 - return (alpha << 24) | (gray & 0xFFFFFF); - } else { - //if (gray > 255) gray = 255; else if (gray < 0) gray = 0; - return (alpha << 24) | (gray << 16) | (gray << 8) | gray; - } - } - return g.color(gray, alpha); - } - - - public final int color(float fgray, float falpha) { - if (g == null) { - int gray = (int) fgray; - int alpha = (int) falpha; - if (gray > 255) gray = 255; else if (gray < 0) gray = 0; - if (alpha > 255) alpha = 255; else if (alpha < 0) alpha = 0; - return 0xff000000 | (gray << 16) | (gray << 8) | gray; - } - return g.color(fgray, falpha); - } - - - public final int color(int x, int y, int z) { - if (g == null) { - if (x > 255) x = 255; else if (x < 0) x = 0; - if (y > 255) y = 255; else if (y < 0) y = 0; - if (z > 255) z = 255; else if (z < 0) z = 0; - - return 0xff000000 | (x << 16) | (y << 8) | z; - } - return g.color(x, y, z); - } - - - public final int color(float x, float y, float z) { - if (g == null) { - if (x > 255) x = 255; else if (x < 0) x = 0; - if (y > 255) y = 255; else if (y < 0) y = 0; - if (z > 255) z = 255; else if (z < 0) z = 0; - - return 0xff000000 | ((int)x << 16) | ((int)y << 8) | (int)z; - } - return g.color(x, y, z); - } - - - public final int color(int x, int y, int z, int a) { - if (g == null) { - if (a > 255) a = 255; else if (a < 0) a = 0; - if (x > 255) x = 255; else if (x < 0) x = 0; - if (y > 255) y = 255; else if (y < 0) y = 0; - if (z > 255) z = 255; else if (z < 0) z = 0; - - return (a << 24) | (x << 16) | (y << 8) | z; - } - return g.color(x, y, z, a); - } - - - public final int color(float x, float y, float z, float a) { - if (g == null) { - if (a > 255) a = 255; else if (a < 0) a = 0; - if (x > 255) x = 255; else if (x < 0) x = 0; - if (y > 255) y = 255; else if (y < 0) y = 0; - if (z > 255) z = 255; else if (z < 0) z = 0; - - return ((int)a << 24) | ((int)x << 16) | ((int)y << 8) | (int)z; - } - return g.color(x, y, z, a); - } - - - public int lerpColor(int c1, int c2, float amt) { - if (g != null) { - return g.lerpColor(c1, c2, amt); - } - // use the default mode (RGB) if lerpColor is called before setup() - return PGraphics.lerpColor(c1, c2, amt, RGB); - } - - - static public int blendColor(int c1, int c2, int mode) { - return PImage.blendColor(c1, c2, mode); - } - - - ////////////////////////////////////////////////////////////// - - // MAIN - - - /** - * Set this sketch to communicate its state back to the PDE. - *

      - * This uses the stderr stream to write positions of the window - * (so that it will be saved by the PDE for the next run) and - * notify on quit. See more notes in the Worker class. - */ -// public void setupExternalMessages() { -// -// frame.addComponentListener(new ComponentAdapter() { -// public void componentMoved(ComponentEvent e) { -// Point where = ((Frame) e.getSource()).getLocation(); -// System.err.println(PApplet.EXTERNAL_MOVE + " " + -// where.x + " " + where.y); -// System.err.flush(); // doesn't seem to help or hurt -// } -// }); -// -// frame.addWindowListener(new WindowAdapter() { -// public void windowClosing(WindowEvent e) { -// exit(); // don't quit, need to just shut everything down (0133) -// } -// }); -// } - - - /** - * Set up a listener that will fire proper component resize events - * in cases where frame.setResizable(true) is called. - */ -// public void setupFrameResizeListener() { -// frame.addComponentListener(new ComponentAdapter() { -// -// public void componentResized(ComponentEvent e) { -// // Ignore bad resize events fired during setup to fix -// // http://dev.processing.org/bugs/show_bug.cgi?id=341 -// // This should also fix the blank screen on Linux bug -// // http://dev.processing.org/bugs/show_bug.cgi?id=282 -// if (frame.isResizable()) { -// // might be multiple resize calls before visible (i.e. first -// // when pack() is called, then when it's resized for use). -// // ignore them because it's not the user resizing things. -// Frame farm = (Frame) e.getComponent(); -// if (farm.isVisible()) { -// Insets insets = farm.getInsets(); -// Dimension windowSize = farm.getSize(); -// int usableW = windowSize.width - insets.left - insets.right; -// int usableH = windowSize.height - insets.top - insets.bottom; -// -// // the ComponentListener in PApplet will handle calling size() -// setBounds(insets.left, insets.top, usableW, usableH); -// } -// } -// } -// }); -// } - - - /** - * GIF image of the Processing logo. - */ - static public final byte[] ICON_IMAGE = { - 71, 73, 70, 56, 57, 97, 16, 0, 16, 0, -77, 0, 0, 0, 0, 0, -1, -1, -1, 12, - 12, 13, -15, -15, -14, 45, 57, 74, 54, 80, 111, 47, 71, 97, 62, 88, 117, - 1, 14, 27, 7, 41, 73, 15, 52, 85, 2, 31, 55, 4, 54, 94, 18, 69, 109, 37, - 87, 126, -1, -1, -1, 33, -7, 4, 1, 0, 0, 15, 0, 44, 0, 0, 0, 0, 16, 0, 16, - 0, 0, 4, 122, -16, -107, 114, -86, -67, 83, 30, -42, 26, -17, -100, -45, - 56, -57, -108, 48, 40, 122, -90, 104, 67, -91, -51, 32, -53, 77, -78, -100, - 47, -86, 12, 76, -110, -20, -74, -101, 97, -93, 27, 40, 20, -65, 65, 48, - -111, 99, -20, -112, -117, -123, -47, -105, 24, 114, -112, 74, 69, 84, 25, - 93, 88, -75, 9, 46, 2, 49, 88, -116, -67, 7, -19, -83, 60, 38, 3, -34, 2, - 66, -95, 27, -98, 13, 4, -17, 55, 33, 109, 11, 11, -2, -128, 121, 123, 62, - 91, 120, -128, 127, 122, 115, 102, 2, 119, 0, -116, -113, -119, 6, 102, - 121, -108, -126, 5, 18, 6, 4, -102, -101, -100, 114, 15, 17, 0, 59 - }; - - - /** - * main() method for running this class from the command line. - *

      - * The options shown here are not yet finalized and will be - * changing over the next several releases. - *

      - * The simplest way to turn and applet into an application is to - * add the following code to your program: - *

      static public void main(String args[]) {
      -   *   PApplet.main(new String[] { "YourSketchName" });
      -   * }
      - * This will properly launch your applet from a double-clickable - * .jar or from the command line. - *
      -   * Parameters useful for launching or also used by the PDE:
      -   *
      -   * --location=x,y        upper-lefthand corner of where the applet
      -   *                       should appear on screen. if not used,
      -   *                       the default is to center on the main screen.
      -   *
      -   * --present             put the applet into full screen presentation
      -   *                       mode. requires java 1.4 or later.
      -   *
      -   * --exclusive           use full screen exclusive mode when presenting.
      -   *                       disables new windows or interaction with other
      -   *                       monitors, this is like a "game" mode.
      -   *
      -   * --hide-stop           use to hide the stop button in situations where
      -   *                       you don't want to allow users to exit. also
      -   *                       see the FAQ on information for capturing the ESC
      -   *                       key when running in presentation mode.
      -   *
      -   * --stop-color=#xxxxxx  color of the 'stop' text used to quit an
      -   *                       sketch when it's in present mode.
      -   *
      -   * --bgcolor=#xxxxxx     background color of the window.
      -   *
      -   * --sketch-path         location of where to save files from functions
      -   *                       like saveStrings() or saveFrame(). defaults to
      -   *                       the folder that the java application was
      -   *                       launched from, which means if this isn't set by
      -   *                       the pde, everything goes into the same folder
      -   *                       as processing.exe.
      -   *
      -   * --display=n           set what display should be used by this applet.
      -   *                       displays are numbered starting from 1.
      -   *
      -   * Parameters used by Processing when running via the PDE
      -   *
      -   * --external            set when the applet is being used by the PDE
      -   *
      -   * --editor-location=x,y position of the upper-lefthand corner of the
      -   *                       editor window, for placement of applet window
      -   * 
      - */ - static public void main(String args[]) { - // just do a no-op for now - } - -// static public void main(String args[]) { -// // Disable abyssmally slow Sun renderer on OS X 10.5. -// if (platform == MACOSX) { -// // Only run this on OS X otherwise it can cause a permissions error. -// // http://dev.processing.org/bugs/show_bug.cgi?id=976 -// System.setProperty("apple.awt.graphics.UseQuartz", "true"); -// } -// -// // This doesn't do anything. -//// if (platform == WINDOWS) { -//// // For now, disable the D3D renderer on Java 6u10 because -//// // it causes problems with Present mode. -//// // http://dev.processing.org/bugs/show_bug.cgi?id=1009 -//// System.setProperty("sun.java2d.d3d", "false"); -//// } -// -// if (args.length < 1) { -// System.err.println("Usage: PApplet "); -// System.err.println("For additional options, " + -// "see the Javadoc for PApplet"); -// System.exit(1); -// } -// -// try { -// boolean external = false; -// int[] location = null; -// int[] editorLocation = null; -// -// String name = null; -// boolean present = false; -// boolean exclusive = false; -// Color backgroundColor = Color.BLACK; -// Color stopColor = Color.GRAY; -// GraphicsDevice displayDevice = null; -// boolean hideStop = false; -// -// String param = null, value = null; -// -// // try to get the user folder. if running under java web start, -// // this may cause a security exception if the code is not signed. -// // http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Integrate;action=display;num=1159386274 -// String folder = null; -// try { -// folder = System.getProperty("user.dir"); -// } catch (Exception e) { } -// -// int argIndex = 0; -// while (argIndex < args.length) { -// int equals = args[argIndex].indexOf('='); -// if (equals != -1) { -// param = args[argIndex].substring(0, equals); -// value = args[argIndex].substring(equals + 1); -// -// if (param.equals(ARGS_EDITOR_LOCATION)) { -// external = true; -// editorLocation = parseInt(split(value, ',')); -// -// } else if (param.equals(ARGS_DISPLAY)) { -// int deviceIndex = Integer.parseInt(value) - 1; -// -// //DisplayMode dm = device.getDisplayMode(); -// //if ((dm.getWidth() == 1024) && (dm.getHeight() == 768)) { -// -// GraphicsEnvironment environment = -// GraphicsEnvironment.getLocalGraphicsEnvironment(); -// GraphicsDevice devices[] = environment.getScreenDevices(); -// if ((deviceIndex >= 0) && (deviceIndex < devices.length)) { -// displayDevice = devices[deviceIndex]; -// } else { -// System.err.println("Display " + value + " does not exist, " + -// "using the default display instead."); -// } -// -// } else if (param.equals(ARGS_BGCOLOR)) { -// if (value.charAt(0) == '#') value = value.substring(1); -// backgroundColor = new Color(Integer.parseInt(value, 16)); -// -// } else if (param.equals(ARGS_STOP_COLOR)) { -// if (value.charAt(0) == '#') value = value.substring(1); -// stopColor = new Color(Integer.parseInt(value, 16)); -// -// } else if (param.equals(ARGS_SKETCH_FOLDER)) { -// folder = value; -// -// } else if (param.equals(ARGS_LOCATION)) { -// location = parseInt(split(value, ',')); -// } -// -// } else { -// if (args[argIndex].equals(ARGS_PRESENT)) { -// present = true; -// -// } else if (args[argIndex].equals(ARGS_EXCLUSIVE)) { -// exclusive = true; -// -// } else if (args[argIndex].equals(ARGS_HIDE_STOP)) { -// hideStop = true; -// -// } else if (args[argIndex].equals(ARGS_EXTERNAL)) { -// external = true; -// -// } else { -// name = args[argIndex]; -// break; -// } -// } -// argIndex++; -// } -// -// // Set this property before getting into any GUI init code -// //System.setProperty("com.apple.mrj.application.apple.menu.about.name", name); -// // This )*)(*@#$ Apple crap don't work no matter where you put it -// // (static method of the class, at the top of main, wherever) -// -// if (displayDevice == null) { -// GraphicsEnvironment environment = -// GraphicsEnvironment.getLocalGraphicsEnvironment(); -// displayDevice = environment.getDefaultScreenDevice(); -// } -// -// Frame frame = new Frame(displayDevice.getDefaultConfiguration()); -// /* -// Frame frame = null; -// if (displayDevice != null) { -// frame = new Frame(displayDevice.getDefaultConfiguration()); -// } else { -// frame = new Frame(); -// } -// */ -// //Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); -// -// // remove the grow box by default -// // users who want it back can call frame.setResizable(true) -// frame.setResizable(false); -// -// // Set the trimmings around the image -// Image image = Toolkit.getDefaultToolkit().createImage(ICON_IMAGE); -// frame.setIconImage(image); -// frame.setTitle(name); -// -//// Class c = Class.forName(name); -// Class c = Thread.currentThread().getContextClassLoader().loadClass(name); -// final PApplet applet = (PApplet) c.newInstance(); -// -// // these are needed before init/start -// applet.frame = frame; -// applet.sketchPath = folder; -// applet.args = PApplet.subset(args, 1); -// applet.external = external; -// -// // Need to save the window bounds at full screen, -// // because pack() will cause the bounds to go to zero. -// // http://dev.processing.org/bugs/show_bug.cgi?id=923 -// Rectangle fullScreenRect = null; -// -// // For 0149, moving this code (up to the pack() method) before init(). -// // For OpenGL (and perhaps other renderers in the future), a peer is -// // needed before a GLDrawable can be created. So pack() needs to be -// // called on the Frame before applet.init(), which itself calls size(), -// // and launches the Thread that will kick off setup(). -// // http://dev.processing.org/bugs/show_bug.cgi?id=891 -// // http://dev.processing.org/bugs/show_bug.cgi?id=908 -// if (present) { -// frame.setUndecorated(true); -// frame.setBackground(backgroundColor); -// if (exclusive) { -// displayDevice.setFullScreenWindow(frame); -// fullScreenRect = frame.getBounds(); -// } else { -// DisplayMode mode = displayDevice.getDisplayMode(); -// fullScreenRect = new Rectangle(0, 0, mode.getWidth(), mode.getHeight()); -// frame.setBounds(fullScreenRect); -// frame.setVisible(true); -// } -// } -// frame.setLayout(null); -// frame.add(applet); -// if (present) { -// frame.invalidate(); -// } else { -// frame.pack(); -// } -// // insufficient, places the 100x100 sketches offset strangely -// //frame.validate(); -// -// applet.init(); -// -// // Wait until the applet has figured out its width. -// // In a static mode app, this will be after setup() has completed, -// // and the empty draw() has set "finished" to true. -// // TODO make sure this won't hang if the applet has an exception. -// while (applet.defaultSize && !applet.finished) { -// //System.out.println("default size"); -// try { -// Thread.sleep(5); -// -// } catch (InterruptedException e) { -// //System.out.println("interrupt"); -// } -// } -// //println("not default size " + applet.width + " " + applet.height); -// //println(" (g width/height is " + applet.g.width + "x" + applet.g.height + ")"); -// -// if (present) { -// // After the pack(), the screen bounds are gonna be 0s -// frame.setBounds(fullScreenRect); -// applet.setBounds((fullScreenRect.width - applet.width) / 2, -// (fullScreenRect.height - applet.height) / 2, -// applet.width, applet.height); -// -// if (!hideStop) { -// Label label = new Label("stop"); -// label.setForeground(stopColor); -// label.addMouseListener(new MouseAdapter() { -// public void mousePressed(MouseEvent e) { -// System.exit(0); -// } -// }); -// frame.add(label); -// -// Dimension labelSize = label.getPreferredSize(); -// // sometimes shows up truncated on mac -// //System.out.println("label width is " + labelSize.width); -// labelSize = new Dimension(100, labelSize.height); -// label.setSize(labelSize); -// label.setLocation(20, fullScreenRect.height - labelSize.height - 20); -// } -// -// // not always running externally when in present mode -// if (external) { -// applet.setupExternalMessages(); -// } -// -// } else { // if not presenting -// // can't do pack earlier cuz present mode don't like it -// // (can't go full screen with a frame after calling pack) -//// frame.pack(); // get insets. get more. -// Insets insets = frame.getInsets(); -// -// int windowW = Math.max(applet.width, MIN_WINDOW_WIDTH) + -// insets.left + insets.right; -// int windowH = Math.max(applet.height, MIN_WINDOW_HEIGHT) + -// insets.top + insets.bottom; -// -// frame.setSize(windowW, windowH); -// -// if (location != null) { -// // a specific location was received from PdeRuntime -// // (applet has been run more than once, user placed window) -// frame.setLocation(location[0], location[1]); -// -// } else if (external) { -// int locationX = editorLocation[0] - 20; -// int locationY = editorLocation[1]; -// -// if (locationX - windowW > 10) { -// // if it fits to the left of the window -// frame.setLocation(locationX - windowW, locationY); -// -// } else { // doesn't fit -// // if it fits inside the editor window, -// // offset slightly from upper lefthand corner -// // so that it's plunked inside the text area -// locationX = editorLocation[0] + 66; -// locationY = editorLocation[1] + 66; -// -// if ((locationX + windowW > applet.screen.width - 33) || -// (locationY + windowH > applet.screen.height - 33)) { -// // otherwise center on screen -// locationX = (applet.screen.width - windowW) / 2; -// locationY = (applet.screen.height - windowH) / 2; -// } -// frame.setLocation(locationX, locationY); -// } -// } else { // just center on screen -// frame.setLocation((applet.screen.width - applet.width) / 2, -// (applet.screen.height - applet.height) / 2); -// } -// -//// frame.setLayout(null); -//// frame.add(applet); -// -// if (backgroundColor == Color.black) { //BLACK) { -// // this means no bg color unless specified -// backgroundColor = SystemColor.control; -// } -// frame.setBackground(backgroundColor); -// -// int usableWindowH = windowH - insets.top - insets.bottom; -// applet.setBounds((windowW - applet.width)/2, -// insets.top + (usableWindowH - applet.height)/2, -// applet.width, applet.height); -// -// if (external) { -// applet.setupExternalMessages(); -// -// } else { // !external -// frame.addWindowListener(new WindowAdapter() { -// public void windowClosing(WindowEvent e) { -// System.exit(0); -// } -// }); -// } -// -// // handle frame resizing events -// applet.setupFrameResizeListener(); -// -// // all set for rockin -// if (applet.displayable()) { -// frame.setVisible(true); -// } -// } -// -// applet.requestFocus(); // ask for keydowns -// //System.out.println("exiting main()"); -// -// } catch (Exception e) { -// e.printStackTrace(); -// System.exit(1); -// } -// } - - - ////////////////////////////////////////////////////////////// - - - /** - * Begin recording to a new renderer of the specified type, using the width - * and height of the main drawing surface. - */ -// public PGraphics beginRecord(String renderer, String filename) { -// filename = insertFrame(filename); -// PGraphics rec = createGraphics(width, height, renderer, filename); -// beginRecord(rec); -// return rec; -// } - - - /** - * Begin recording (echoing) commands to the specified PGraphics object. - */ -// public void beginRecord(PGraphics recorder) { -// PGraphics.showMethodWarning("beginRecord"); -// } - - -// public void endRecord() { -// PGraphics.showMethodWarning("endRecord"); -// } - - - /** - * Begin recording raw shape data to a renderer of the specified type, - * using the width and height of the main drawing surface. - * - * If hashmarks (###) are found in the filename, they'll be replaced - * by the current frame number (frameCount). - */ -// public PGraphics beginRaw(String renderer, String filename) { -// filename = insertFrame(filename); -// PGraphics rec = createGraphics(width, height, renderer, filename); -// g.beginRaw(rec); -// return rec; -// } - - - /** - * Begin recording raw shape data to the specified renderer. - * - * This simply echoes to g.beginRaw(), but since is placed here (rather than - * generated by preproc.pl) for clarity and so that it doesn't echo the - * command should beginRecord() be in use. - */ -// public void beginRaw(PGraphics rawGraphics) { -// g.beginRaw(rawGraphics); -// } - - - /** - * Stop recording raw shape data to the specified renderer. - * - * This simply echoes to g.beginRaw(), but since is placed here (rather than - * generated by preproc.pl) for clarity and so that it doesn't echo the - * command should beginRecord() be in use. - */ -// public void endRaw() { -// g.endRaw(); -// } - - - ////////////////////////////////////////////////////////////// - - - /** - * Override the g.pixels[] function to set the pixels[] array - * that's part of the PApplet object. Allows the use of - * pixels[] in the code, rather than g.pixels[]. - */ - public void loadPixels() { - g.loadPixels(); - pixels = g.pixels; - } - - - public void updatePixels() { - g.updatePixels(); - } - - - public void updatePixels(int x1, int y1, int x2, int y2) { - g.updatePixels(x1, y1, x2, y2); - } - - - ////////////////////////////////////////////////////////////// - - // ANDROID-SPECIFIC API - - - // Wallpaper and wear API - - - public boolean wallpaperPreview() { - return surface.getEngine().isPreview(); - } - - - public float wallpaperOffset() { - return surface.getEngine().getXOffset(); - } - - - public int wallpaperHomeCount() { - float step = surface.getEngine().getXOffsetStep(); - if (0 < step) { - return (int)(1 + 1 / step); - } else { - return 1; - } - } - - - public boolean wearAmbient() { - return surface.getEngine().isInAmbientMode(); - } - - - public boolean wearInteractive() { - return !surface.getEngine().isInAmbientMode(); - } - - - public boolean wearRound() { - return surface.getEngine().isRound(); - } - - - public boolean wearSquare() { - return !surface.getEngine().isRound(); - } - - - public Rect wearInsets() { - return surface.getEngine().getInsets(); - } - - - public boolean wearLowBit() { - return surface.getEngine().useLowBitAmbient(); - } - - - public boolean wearBurnIn() { - return surface.getEngine().requireBurnInProtection(); - } - - - // Ray casting API - - - public PVector[] getRayFromScreen(float screenX, float screenY, PVector[] ray) { - return g.getRayFromScreen(screenX, screenY, ray); - } - - - public void getRayFromScreen(float screenX, float screenY, PVector origin, PVector direction) { - g.getRayFromScreen(screenX, screenY, origin, direction); - } - - - public boolean intersectsSphere(float r, float screenX, float screenY) { - return g.intersectsSphere(r, screenX, screenY); - } - - - public boolean intersectsSphere(float r, PVector origin, PVector direction) { - return g.intersectsSphere(r, origin, direction); - } - - - public boolean intersectsBox(float w, float screenX, float screenY) { - return g.intersectsBox(w, screenX, screenY); - } - - - public boolean intersectsBox(float w, float h, float d, float screenX, float screenY) { - return g.intersectsBox(w, h, d, screenX, screenY); - } - - - public boolean intersectsBox(float size, PVector origin, PVector direction) { - return g.intersectsBox(size, origin, direction); - } - - - public boolean intersectsBox(float w, float h, float d, PVector origin, PVector direction) { - return g.intersectsBox(w, h, d, origin, direction); - } - - - public PVector intersectsPlane(float screenX, float screenY) { - return g.intersectsPlane(screenX, screenY); - } - - - public PVector intersectsPlane(PVector origin, PVector direction) { - return g.intersectsPlane(origin, direction); - } - - - public void eye() { - g.eye(); - } - - - public void calculate() { - } - - - /** - * Sets the coordinate system in 3D centered at (width/2, height/2) - * and with the Y axis pointing up. - */ - - public void cameraUp() { - g.cameraUp(); - } - - - /** - * Returns a copy of the current object matrix. - * Pass in null to create a new matrix. - */ - public PMatrix3D getObjectMatrix() { - return g.getObjectMatrix(); - } - - - /** - * Copy the current object matrix into the specified target. - * Pass in null to create a new matrix. - */ - public PMatrix3D getObjectMatrix(PMatrix3D target) { - return g.getObjectMatrix(target); - } - - - /** - * Returns a copy of the current eye matrix. - * Pass in null to create a new matrix. - */ - public PMatrix3D getEyeMatrix() { - return g.getEyeMatrix(); - } - - - /** - * Copy the current eye matrix into the specified target. - * Pass in null to create a new matrix. - */ - public PMatrix3D getEyeMatrix(PMatrix3D target) { - return g.getEyeMatrix(target); - } - - - ////////////////////////////////////////////////////////////// - - // EVERYTHING BELOW THIS LINE IS AUTOMATICALLY GENERATED. DO NOT TOUCH! - // This includes the Javadoc comments, which are automatically copied from - // the PImage and PGraphics source code files. - - // public functions for processing.core - - - public PGL beginPGL() { - return g.beginPGL(); - } - - - public void endPGL() { - g.endPGL(); - } - - - public void flush() { - g.flush(); - } - - - public void hint(int which) { - g.hint(which); - } - - - /** - * Start a new shape of type POLYGON - */ - public void beginShape() { - g.beginShape(); - } - - - /** - * ( begin auto-generated from beginShape.xml ) - * - * Using the beginShape() and endShape() functions allow - * creating more complex forms. beginShape() begins recording - * vertices for a shape and endShape() stops recording. The value of - * the MODE parameter tells it which types of shapes to create from - * the provided vertices. With no mode specified, the shape can be any - * irregular polygon. The parameters available for beginShape() are POINTS, - * LINES, TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, and QUAD_STRIP. - * After calling the beginShape() function, a series of - * vertex() commands must follow. To stop drawing the shape, call - * endShape(). The vertex() function with two parameters - * specifies a position in 2D and the vertex() function with three - * parameters specifies a position in 3D. Each shape will be outlined with - * the current stroke color and filled with the fill color. - *

      - * Transformations such as translate(), rotate(), and - * scale() do not work within beginShape(). It is also not - * possible to use other shapes, such as ellipse() or rect() - * within beginShape(). - *

      - * The P3D renderer settings allow stroke() and fill() - * settings to be altered per-vertex, however the default P2D renderer does - * not. Settings such as strokeWeight(), strokeCap(), and - * strokeJoin() cannot be changed while inside a - * beginShape()/endShape() block with any renderer. - * - * ( end auto-generated ) - * @webref shape:vertex - * @param kind Either POINTS, LINES, TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, or QUAD_STRIP - * @see PShape - * @see PGraphics#endShape() - * @see PGraphics#vertex(float, float, float, float, float) - * @see PGraphics#curveVertex(float, float, float) - * @see PGraphics#bezierVertex(float, float, float, float, float, float, float, float, float) - */ - public void beginShape(int kind) { - g.beginShape(kind); - } - - - /** - * Sets whether the upcoming vertex is part of an edge. - * Equivalent to glEdgeFlag(), for people familiar with OpenGL. - */ - public void edge(boolean edge) { - g.edge(edge); - } - - - /** - * ( begin auto-generated from normal.xml ) - * - * Sets the current normal vector. This is for drawing three dimensional - * shapes and surfaces and specifies a vector perpendicular to the surface - * of the shape which determines how lighting affects it. Processing - * attempts to automatically assign normals to shapes, but since that's - * imperfect, this is a better option when you want more control. This - * function is identical to glNormal3f() in OpenGL. - * - * ( end auto-generated ) - * @webref lights_camera:lights - * @param nx x direction - * @param ny y direction - * @param nz z direction - * @see PGraphics#beginShape(int) - * @see PGraphics#endShape(int) - * @see PGraphics#lights() - */ - public void normal(float nx, float ny, float nz) { - g.normal(nx, ny, nz); - } - - - public void attribPosition(String name, float x, float y, float z) { - g.attribPosition(name, x, y, z); - } - - - public void attribNormal(String name, float nx, float ny, float nz) { - g.attribNormal(name, nx, ny, nz); - } - - - public void attribColor(String name, int color) { - g.attribColor(name, color); - } - - - public void attrib(String name, float... values) { - g.attrib(name, values); - } - - - public void attrib(String name, int... values) { - g.attrib(name, values); - } - - - public void attrib(String name, boolean... values) { - g.attrib(name, values); - } - - - /** - * ( begin auto-generated from textureMode.xml ) - * - * Sets the coordinate space for texture mapping. There are two options, - * IMAGE, which refers to the actual coordinates of the image, and - * NORMAL, which refers to a normalized space of values ranging from 0 - * to 1. The default mode is IMAGE. In IMAGE, if an image is 100 x 200 - * pixels, mapping the image onto the entire size of a quad would require - * the points (0,0) (0,100) (100,200) (0,200). The same mapping in - * NORMAL_SPACE is (0,0) (0,1) (1,1) (0,1). - * - * ( end auto-generated ) - * @webref image:textures - * @param mode either IMAGE or NORMAL - * @see PGraphics#texture(PImage) - * @see PGraphics#textureWrap(int) - */ - public void textureMode(int mode) { - g.textureMode(mode); - } - - - /** - * ( begin auto-generated from textureWrap.xml ) - * - * Description to come... - * - * ( end auto-generated from textureWrap.xml ) - * - * @webref image:textures - * @param wrap Either CLAMP (default) or REPEAT - * @see PGraphics#texture(PImage) - * @see PGraphics#textureMode(int) - */ - public void textureWrap(int wrap) { - g.textureWrap(wrap); - } - - - /** - * ( begin auto-generated from texture.xml ) - * - * Sets a texture to be applied to vertex points. The texture() - * function must be called between beginShape() and - * endShape() and before any calls to vertex(). - *

      - * When textures are in use, the fill color is ignored. Instead, use tint() - * to specify the color of the texture as it is applied to the shape. - * - * ( end auto-generated ) - * @webref image:textures - * @param image reference to a PImage object - * @see PGraphics#textureMode(int) - * @see PGraphics#textureWrap(int) - * @see PGraphics#beginShape(int) - * @see PGraphics#endShape(int) - * @see PGraphics#vertex(float, float, float, float, float) - */ - public void texture(PImage image) { - g.texture(image); - } - - - /** - * Removes texture image for current shape. - * Needs to be called between beginShape and endShape - * - */ - public void noTexture() { - g.noTexture(); - } - - - public void vertex(float x, float y) { - g.vertex(x, y); - } - - - public void vertex(float x, float y, float z) { - g.vertex(x, y, z); - } - - - /** - * Used by renderer subclasses or PShape to efficiently pass in already - * formatted vertex information. - * @param v vertex parameters, as a float array of length VERTEX_FIELD_COUNT - */ - public void vertex(float[] v) { - g.vertex(v); - } - - - public void vertex(float x, float y, float u, float v) { - g.vertex(x, y, u, v); - } - - - /** - * ( begin auto-generated from vertex.xml ) - * - * All shapes are constructed by connecting a series of vertices. - * vertex() is used to specify the vertex coordinates for points, - * lines, triangles, quads, and polygons and is used exclusively within the - * beginShape() and endShape() function.
      - *
      - * Drawing a vertex in 3D using the z parameter requires the P3D - * parameter in combination with size as shown in the above example.
      - *
      - * This function is also used to map a texture onto the geometry. The - * texture() function declares the texture to apply to the geometry - * and the u and v coordinates set define the mapping of this - * texture to the form. By default, the coordinates used for u and - * v are specified in relation to the image's size in pixels, but - * this relation can be changed with textureMode(). - * - * ( end auto-generated ) - * @webref shape:vertex - * @param x x-coordinate of the vertex - * @param y y-coordinate of the vertex - * @param z z-coordinate of the vertex - * @param u horizontal coordinate for the texture mapping - * @param v vertical coordinate for the texture mapping - * @see PGraphics#beginShape(int) - * @see PGraphics#endShape(int) - * @see PGraphics#bezierVertex(float, float, float, float, float, float, float, float, float) - * @see PGraphics#quadraticVertex(float, float, float, float, float, float) - * @see PGraphics#curveVertex(float, float, float) - * @see PGraphics#texture(PImage) - */ - public void vertex(float x, float y, float z, float u, float v) { - g.vertex(x, y, z, u, v); - } - - - /** - * @webref shape:vertex - */ - public void beginContour() { - g.beginContour(); - } - - - /** - * @webref shape:vertex - */ - public void endContour() { - g.endContour(); - } - - - public void endShape() { - g.endShape(); - } - - - /** - * ( begin auto-generated from endShape.xml ) - * - * The endShape() function is the companion to beginShape() - * and may only be called after beginShape(). When endshape() - * is called, all of image data defined since the previous call to - * beginShape() is written into the image buffer. The constant CLOSE - * as the value for the MODE parameter to close the shape (to connect the - * beginning and the end). - * - * ( end auto-generated ) - * @webref shape:vertex - * @param mode use CLOSE to close the shape - * @see PShape - * @see PGraphics#beginShape(int) - */ - public void endShape(int mode) { - g.endShape(mode); - } - - - /** - * @webref shape - * @param filename name of file to load, can be .svg or .obj - * @see PShape - * @see PApplet#createShape() - */ - public PShape loadShape(String filename) { - return g.loadShape(filename); - } - - - /** - * @nowebref - */ - public PShape loadShape(String filename, String options) { - return g.loadShape(filename, options); - } - - - /** - * @webref shape - * @see PShape - * @see PShape#endShape() - * @see PApplet#loadShape(String) - */ - public PShape createShape() { - return g.createShape(); - } - - - public PShape createShape(int type) { - return g.createShape(type); - } - - - /** - * @param kind either POINT, LINE, TRIANGLE, QUAD, RECT, ELLIPSE, ARC, BOX, SPHERE - * @param p parameters that match the kind of shape - */ - public PShape createShape(int kind, float... p) { - return g.createShape(kind, p); - } - - - /** - * ( begin auto-generated from loadShader.xml ) - * - * This is a new reference entry for Processing 2.0. It will be updated shortly. - * - * ( end auto-generated ) - * - * @webref rendering:shaders - * @param fragFilename name of fragment shader file - */ - public PShader loadShader(String fragFilename) { - return g.loadShader(fragFilename); - } - - - /** - * @param vertFilename name of vertex shader file - */ - public PShader loadShader(String fragFilename, String vertFilename) { - return g.loadShader(fragFilename, vertFilename); - } - - - /** - * ( begin auto-generated from shader.xml ) - * - * This is a new reference entry for Processing 2.0. It will be updated shortly. - * - * ( end auto-generated ) - * - * @webref rendering:shaders - * @param shader name of shader file - */ - public void shader(PShader shader) { - g.shader(shader); - } - - - /** - * @param kind type of shader, either POINTS, LINES, or TRIANGLES - */ - public void shader(PShader shader, int kind) { - g.shader(shader, kind); - } - - - /** - * ( begin auto-generated from resetShader.xml ) - * - * This is a new reference entry for Processing 2.0. It will be updated shortly. - * - * ( end auto-generated ) - * - * @webref rendering:shaders - */ - public void resetShader() { - g.resetShader(); - } - - - /** - * @param kind type of shader, either POINTS, LINES, or TRIANGLES - */ - public void resetShader(int kind) { - g.resetShader(kind); - } - - - /** - * @param shader the fragment shader to apply - */ - public void filter(PShader shader) { - g.filter(shader); - } - - - /** - * ( begin auto-generated from clip.xml ) - * - * Limits the rendering to the boundaries of a rectangle defined - * by the parameters. The boundaries are drawn based on the state - * of the imageMode() fuction, either CORNER, CORNERS, or CENTER. - * - * ( end auto-generated ) - * - * @webref rendering - * @param a x-coordinate of the rectangle, by default - * @param b y-coordinate of the rectangle, by default - * @param c width of the rectangle, by default - * @param d height of the rectangle, by default - */ - public void clip(float a, float b, float c, float d) { - g.clip(a, b, c, d); - } - - - /** - * ( begin auto-generated from noClip.xml ) - * - * Disables the clipping previously started by the clip() function. - * - * ( end auto-generated ) - * - * @webref rendering - */ - public void noClip() { - g.noClip(); - } - - - /** - * ( begin auto-generated from blendMode.xml ) - * - * This is a new reference entry for Processing 2.0. It will be updated shortly. - * - * ( end auto-generated ) - * - * @webref rendering - * @param mode the blending mode to use - */ - public void blendMode(int mode) { - g.blendMode(mode); - } - - - public void bezierVertex(float x2, float y2, - float x3, float y3, - float x4, float y4) { - g.bezierVertex(x2, y2, x3, y3, x4, y4); - } - - - /** - * ( begin auto-generated from bezierVertex.xml ) - * - * Specifies vertex coordinates for Bezier curves. Each call to - * bezierVertex() defines the position of two control points and one - * anchor point of a Bezier curve, adding a new segment to a line or shape. - * The first time bezierVertex() is used within a - * beginShape() call, it must be prefaced with a call to - * vertex() to set the first anchor point. This function must be - * used between beginShape() and endShape() and only when - * there is no MODE parameter specified to beginShape(). Using the - * 3D version requires rendering with P3D (see the Environment reference - * for more information). - * - * ( end auto-generated ) - * @webref shape:vertex - * @param x2 the x-coordinate of the 1st control point - * @param y2 the y-coordinate of the 1st control point - * @param z2 the z-coordinate of the 1st control point - * @param x3 the x-coordinate of the 2nd control point - * @param y3 the y-coordinate of the 2nd control point - * @param z3 the z-coordinate of the 2nd control point - * @param x4 the x-coordinate of the anchor point - * @param y4 the y-coordinate of the anchor point - * @param z4 the z-coordinate of the anchor point - * @see PGraphics#curveVertex(float, float, float) - * @see PGraphics#vertex(float, float, float, float, float) - * @see PGraphics#quadraticVertex(float, float, float, float, float, float) - * @see PGraphics#bezier(float, float, float, float, float, float, float, float, float, float, float, float) - */ - public void bezierVertex(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - g.bezierVertex(x2, y2, z2, x3, y3, z3, x4, y4, z4); - } - - - /** - * @webref shape:vertex - * @param cx the x-coordinate of the control point - * @param cy the y-coordinate of the control point - * @param x3 the x-coordinate of the anchor point - * @param y3 the y-coordinate of the anchor point - * @see PGraphics#curveVertex(float, float, float) - * @see PGraphics#vertex(float, float, float, float, float) - * @see PGraphics#bezierVertex(float, float, float, float, float, float) - * @see PGraphics#bezier(float, float, float, float, float, float, float, float, float, float, float, float) - */ - public void quadraticVertex(float cx, float cy, - float x3, float y3) { - g.quadraticVertex(cx, cy, x3, y3); - } - - - /** - * @param cz the z-coordinate of the control point - * @param z3 the z-coordinate of the anchor point - */ - public void quadraticVertex(float cx, float cy, float cz, - float x3, float y3, float z3) { - g.quadraticVertex(cx, cy, cz, x3, y3, z3); - } - - - /** - * ( begin auto-generated from curveVertex.xml ) - * - * Specifies vertex coordinates for curves. This function may only be used - * between beginShape() and endShape() and only when there is - * no MODE parameter specified to beginShape(). The first and last - * points in a series of curveVertex() lines will be used to guide - * the beginning and end of a the curve. A minimum of four points is - * required to draw a tiny curve between the second and third points. - * Adding a fifth point with curveVertex() will draw the curve - * between the second, third, and fourth points. The curveVertex() - * function is an implementation of Catmull-Rom splines. Using the 3D - * version requires rendering with P3D (see the Environment reference for - * more information). - * - * ( end auto-generated ) - * - * @webref shape:vertex - * @param x the x-coordinate of the vertex - * @param y the y-coordinate of the vertex - * @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float) - * @see PGraphics#beginShape(int) - * @see PGraphics#endShape(int) - * @see PGraphics#vertex(float, float, float, float, float) - * @see PGraphics#bezier(float, float, float, float, float, float, float, float, float, float, float, float) - * @see PGraphics#quadraticVertex(float, float, float, float, float, float) - */ - public void curveVertex(float x, float y) { - g.curveVertex(x, y); - } - - - /** - * @param z the z-coordinate of the vertex - */ - public void curveVertex(float x, float y, float z) { - g.curveVertex(x, y, z); - } - - - /** - * ( begin auto-generated from point.xml ) - * - * Draws a point, a coordinate in space at the dimension of one pixel. The - * first parameter is the horizontal value for the point, the second value - * is the vertical value for the point, and the optional third value is the - * depth value. Drawing this shape in 3D with the z parameter - * requires the P3D parameter in combination with size() as shown in - * the above example. - * - * ( end auto-generated ) - * - * @webref shape:2d_primitives - * @param x x-coordinate of the point - * @param y y-coordinate of the point - * @see PGraphics#stroke(int) - */ - public void point(float x, float y) { - g.point(x, y); - } - - - /** - * @param z z-coordinate of the point - */ - public void point(float x, float y, float z) { - g.point(x, y, z); - } - - - /** - * ( begin auto-generated from line.xml ) - * - * Draws a line (a direct path between two points) to the screen. The - * version of line() with four parameters draws the line in 2D. To - * color a line, use the stroke() function. A line cannot be filled, - * therefore the fill() function will not affect the color of a - * line. 2D lines are drawn with a width of one pixel by default, but this - * can be changed with the strokeWeight() function. The version with - * six parameters allows the line to be placed anywhere within XYZ space. - * Drawing this shape in 3D with the z parameter requires the P3D - * parameter in combination with size() as shown in the above example. - * - * ( end auto-generated ) - * @webref shape:2d_primitives - * @param x1 x-coordinate of the first point - * @param y1 y-coordinate of the first point - * @param x2 x-coordinate of the second point - * @param y2 y-coordinate of the second point - * @see PGraphics#strokeWeight(float) - * @see PGraphics#strokeJoin(int) - * @see PGraphics#strokeCap(int) - * @see PGraphics#beginShape() - */ - public void line(float x1, float y1, float x2, float y2) { - g.line(x1, y1, x2, y2); - } - - - /** - * @param z1 z-coordinate of the first point - * @param z2 z-coordinate of the second point - */ - public void line(float x1, float y1, float z1, - float x2, float y2, float z2) { - g.line(x1, y1, z1, x2, y2, z2); - } - - - /** - * ( begin auto-generated from triangle.xml ) - * - * A triangle is a plane created by connecting three points. The first two - * arguments specify the first point, the middle two arguments specify the - * second point, and the last two arguments specify the third point. - * - * ( end auto-generated ) - * @webref shape:2d_primitives - * @param x1 x-coordinate of the first point - * @param y1 y-coordinate of the first point - * @param x2 x-coordinate of the second point - * @param y2 y-coordinate of the second point - * @param x3 x-coordinate of the third point - * @param y3 y-coordinate of the third point - * @see PApplet#beginShape() - */ - public void triangle(float x1, float y1, float x2, float y2, - float x3, float y3) { - g.triangle(x1, y1, x2, y2, x3, y3); - } - - - /** - * ( begin auto-generated from quad.xml ) - * - * A quad is a quadrilateral, a four sided polygon. It is similar to a - * rectangle, but the angles between its edges are not constrained to - * ninety degrees. The first pair of parameters (x1,y1) sets the first - * vertex and the subsequent pairs should proceed clockwise or - * counter-clockwise around the defined shape. - * - * ( end auto-generated ) - * @webref shape:2d_primitives - * @param x1 x-coordinate of the first corner - * @param y1 y-coordinate of the first corner - * @param x2 x-coordinate of the second corner - * @param y2 y-coordinate of the second corner - * @param x3 x-coordinate of the third corner - * @param y3 y-coordinate of the third corner - * @param x4 x-coordinate of the fourth corner - * @param y4 y-coordinate of the fourth corner - */ - public void quad(float x1, float y1, float x2, float y2, - float x3, float y3, float x4, float y4) { - g.quad(x1, y1, x2, y2, x3, y3, x4, y4); - } - - - /** - * ( begin auto-generated from rectMode.xml ) - * - * Modifies the location from which rectangles draw. The default mode is - * rectMode(CORNER), which specifies the location to be the upper - * left corner of the shape and uses the third and fourth parameters of - * rect() to specify the width and height. The syntax - * rectMode(CORNERS) uses the first and second parameters of - * rect() to set the location of one corner and uses the third and - * fourth parameters to set the opposite corner. The syntax - * rectMode(CENTER) draws the image from its center point and uses - * the third and forth parameters of rect() to specify the image's - * width and height. The syntax rectMode(RADIUS) draws the image - * from its center point and uses the third and forth parameters of - * rect() to specify half of the image's width and height. The - * parameter must be written in ALL CAPS because Processing is a case - * sensitive language. Note: In version 125, the mode named CENTER_RADIUS - * was shortened to RADIUS. - * - * ( end auto-generated ) - * @webref shape:attributes - * @param mode either CORNER, CORNERS, CENTER, or RADIUS - * @see PGraphics#rect(float, float, float, float) - */ - public void rectMode(int mode) { - g.rectMode(mode); - } - - - /** - * ( begin auto-generated from rect.xml ) - * - * Draws a rectangle to the screen. A rectangle is a four-sided shape with - * every angle at ninety degrees. By default, the first two parameters set - * the location of the upper-left corner, the third sets the width, and the - * fourth sets the height. These parameters may be changed with the - * rectMode() function. - * - * ( end auto-generated ) - * - * @webref shape:2d_primitives - * @param a x-coordinate of the rectangle by default - * @param b y-coordinate of the rectangle by default - * @param c width of the rectangle by default - * @param d height of the rectangle by default - * @see PGraphics#rectMode(int) - * @see PGraphics#quad(float, float, float, float, float, float, float, float) - */ - public void rect(float a, float b, float c, float d) { - g.rect(a, b, c, d); - } - - - /** - * @param r radii for all four corners - */ - public void rect(float a, float b, float c, float d, float r) { - g.rect(a, b, c, d, r); - } - - - /** - * @param tl radius for top-left corner - * @param tr radius for top-right corner - * @param br radius for bottom-right corner - * @param bl radius for bottom-left corner - */ - public void rect(float a, float b, float c, float d, - float tl, float tr, float br, float bl) { - g.rect(a, b, c, d, tl, tr, br, bl); - } - - - /** - * ( begin auto-generated from square.xml ) - * - * Draws a square to the screen. A square is a four-sided shape with - * every angle at ninety degrees and each side is the same length. - * By default, the first two parameters set the location of the - * upper-left corner, the third sets the width and height. The way - * these parameters are interpreted, however, may be changed with the - * rectMode() function. - * - * ( end auto-generated ) - * - * @webref shape:2d_primitives - * @param x x-coordinate of the rectangle by default - * @param y y-coordinate of the rectangle by default - * @param extent width and height of the rectangle by default - * @see PGraphics#rect(float, float, float, float) - * @see PGraphics#rectMode(int) - */ - public void square(float x, float y, float extent) { - g.square(x, y, extent); - } - - - /** - * ( begin auto-generated from ellipseMode.xml ) - * - * The origin of the ellipse is modified by the ellipseMode() - * function. The default configuration is ellipseMode(CENTER), which - * specifies the location of the ellipse as the center of the shape. The - * RADIUS mode is the same, but the width and height parameters to - * ellipse() specify the radius of the ellipse, rather than the - * diameter. The CORNER mode draws the shape from the upper-left - * corner of its bounding box. The CORNERS mode uses the four - * parameters to ellipse() to set two opposing corners of the - * ellipse's bounding box. The parameter must be written in ALL CAPS - * because Processing is a case-sensitive language. - * - * ( end auto-generated ) - * @webref shape:attributes - * @param mode either CENTER, RADIUS, CORNER, or CORNERS - * @see PApplet#ellipse(float, float, float, float) - * @see PApplet#arc(float, float, float, float, float, float) - */ - public void ellipseMode(int mode) { - g.ellipseMode(mode); - } - - - /** - * ( begin auto-generated from ellipse.xml ) - * - * Draws an ellipse (oval) in the display window. An ellipse with an equal - * width and height is a circle. The first two parameters set - * the location, the third sets the width, and the fourth sets the height. - * The origin may be changed with the ellipseMode() function. - * - * ( end auto-generated ) - * @webref shape:2d_primitives - * @param a x-coordinate of the ellipse - * @param b y-coordinate of the ellipse - * @param c width of the ellipse by default - * @param d height of the ellipse by default - * @see PApplet#ellipseMode(int) - * @see PApplet#arc(float, float, float, float, float, float) - */ - public void ellipse(float a, float b, float c, float d) { - g.ellipse(a, b, c, d); - } - - - /** - * ( begin auto-generated from arc.xml ) - * - * Draws an arc in the display window. Arcs are drawn along the outer edge - * of an ellipse defined by the x, y, width and - * height parameters. The origin or the arc's ellipse may be changed - * with the ellipseMode() function. The start and stop - * parameters specify the angles at which to draw the arc. - * - * ( end auto-generated ) - * @webref shape:2d_primitives - * @param a x-coordinate of the arc's ellipse - * @param b y-coordinate of the arc's ellipse - * @param c width of the arc's ellipse by default - * @param d height of the arc's ellipse by default - * @param start angle to start the arc, specified in radians - * @param stop angle to stop the arc, specified in radians - * @see PApplet#ellipse(float, float, float, float) - * @see PApplet#ellipseMode(int) - * @see PApplet#radians(float) - * @see PApplet#degrees(float) - */ - public void arc(float a, float b, float c, float d, - float start, float stop) { - g.arc(a, b, c, d, start, stop); - } - - - /* - * @param mode either OPEN, CHORD, or PIE - */ - public void arc(float a, float b, float c, float d, - float start, float stop, int mode) { - g.arc(a, b, c, d, start, stop, mode); - } - - - /** - * ( begin auto-generated from circle.xml ) - * - * Draws a circle to the screen. By default, the first two parameters - * set the location of the center, and the third sets the shape's width - * and height. The origin may be changed with the ellipseMode() - * function. - * - * ( end auto-generated ) - * @webref shape:2d_primitives - * @param x x-coordinate of the ellipse - * @param y y-coordinate of the ellipse - * @param extent width and height of the ellipse by default - * @see PApplet#ellipse(float, float, float, float) - * @see PApplet#ellipseMode(int) - */ - public void circle(float x, float y, float extent) { - g.circle(x, y, extent); - } - - - /** - * ( begin auto-generated from box.xml ) - * - * A box is an extruded rectangle. A box with equal dimension on all sides - * is a cube. - * - * ( end auto-generated ) - * - * @webref shape:3d_primitives - * @param size dimension of the box in all dimensions (creates a cube) - * @see PGraphics#sphere(float) - */ - public void box(float size) { - g.box(size); - } - - - /** - * @param w dimension of the box in the x-dimension - * @param h dimension of the box in the y-dimension - * @param d dimension of the box in the z-dimension - */ - public void box(float w, float h, float d) { - g.box(w, h, d); - } - - - /** - * ( begin auto-generated from sphereDetail.xml ) - * - * Controls the detail used to render a sphere by adjusting the number of - * vertices of the sphere mesh. The default resolution is 30, which creates - * a fairly detailed sphere definition with vertices every 360/30 = 12 - * degrees. If you're going to render a great number of spheres per frame, - * it is advised to reduce the level of detail using this function. The - * setting stays active until sphereDetail() is called again with a - * new parameter and so should not be called prior to every - * sphere() statement, unless you wish to render spheres with - * different settings, e.g. using less detail for smaller spheres or ones - * further away from the camera. To control the detail of the horizontal - * and vertical resolution independently, use the version of the functions - * with two parameters. - * - * ( end auto-generated ) - * - *

      Advanced

      - * Code for sphereDetail() submitted by toxi [031031]. - * Code for enhanced u/v version from davbol [080801]. - * - * @param res number of segments (minimum 3) used per full circle revolution - * @webref shape:3d_primitives - * @see PGraphics#sphere(float) - */ - public void sphereDetail(int res) { - g.sphereDetail(res); - } - - - /** - * @param ures number of segments used longitudinally per full circle revolutoin - * @param vres number of segments used latitudinally from top to bottom - */ - public void sphereDetail(int ures, int vres) { - g.sphereDetail(ures, vres); - } - - - /** - * ( begin auto-generated from sphere.xml ) - * - * A sphere is a hollow ball made from tessellated triangles. - * - * ( end auto-generated ) - * - *

      Advanced

      - *

      - * Implementation notes: - *

      - * cache all the points of the sphere in a static array - * top and bottom are just a bunch of triangles that land - * in the center point - *

      - * sphere is a series of concentric circles who radii vary - * along the shape, based on, er.. cos or something - *

      -   * [toxi 031031] new sphere code. removed all multiplies with
      -   * radius, as scale() will take care of that anyway
      -   *
      -   * [toxi 031223] updated sphere code (removed modulos)
      -   * and introduced sphereAt(x,y,z,r)
      -   * to avoid additional translate()'s on the user/sketch side
      -   *
      -   * [davbol 080801] now using separate sphereDetailU/V
      -   * 
      - * - * @webref shape:3d_primitives - * @param r the radius of the sphere - * @see PGraphics#sphereDetail(int) - */ - public void sphere(float r) { - g.sphere(r); - } - - - /** - * ( begin auto-generated from bezierPoint.xml ) - * - * Evaluates the Bezier at point t for points a, b, c, d. The parameter t - * varies between 0 and 1, a and d are points on the curve, and b and c are - * the control points. This can be done once with the x coordinates and a - * second time with the y coordinates to get the location of a bezier curve - * at t. - * - * ( end auto-generated ) - * - *

      Advanced

      - * For instance, to convert the following example:
      -   * stroke(255, 102, 0);
      -   * line(85, 20, 10, 10);
      -   * line(90, 90, 15, 80);
      -   * stroke(0, 0, 0);
      -   * bezier(85, 20, 10, 10, 90, 90, 15, 80);
      -   *
      -   * // draw it in gray, using 10 steps instead of the default 20
      -   * // this is a slower way to do it, but useful if you need
      -   * // to do things with the coordinates at each step
      -   * stroke(128);
      -   * beginShape(LINE_STRIP);
      -   * for (int i = 0; i <= 10; i++) {
      -   *   float t = i / 10.0f;
      -   *   float x = bezierPoint(85, 10, 90, 15, t);
      -   *   float y = bezierPoint(20, 10, 90, 80, t);
      -   *   vertex(x, y);
      -   * }
      -   * endShape();
      - * - * @webref shape:curves - * @param a coordinate of first point on the curve - * @param b coordinate of first control point - * @param c coordinate of second control point - * @param d coordinate of second point on the curve - * @param t value between 0 and 1 - * @see PGraphics#bezier(float, float, float, float, float, float, float, float, float, float, float, float) - * @see PGraphics#bezierVertex(float, float, float, float, float, float) - * @see PGraphics#curvePoint(float, float, float, float, float) - */ - public float bezierPoint(float a, float b, float c, float d, float t) { - return g.bezierPoint(a, b, c, d, t); - } - - - /** - * ( begin auto-generated from bezierTangent.xml ) - * - * Calculates the tangent of a point on a Bezier curve. There is a good - * definition of tangent on Wikipedia. - * - * ( end auto-generated ) - * - *

      Advanced

      - * Code submitted by Dave Bollinger (davol) for release 0136. - * - * @webref shape:curves - * @param a coordinate of first point on the curve - * @param b coordinate of first control point - * @param c coordinate of second control point - * @param d coordinate of second point on the curve - * @param t value between 0 and 1 - * @see PGraphics#bezier(float, float, float, float, float, float, float, float, float, float, float, float) - * @see PGraphics#bezierVertex(float, float, float, float, float, float) - * @see PGraphics#curvePoint(float, float, float, float, float) - */ - public float bezierTangent(float a, float b, float c, float d, float t) { - return g.bezierTangent(a, b, c, d, t); - } - - - /** - * ( begin auto-generated from bezierDetail.xml ) - * - * Sets the resolution at which Beziers display. The default value is 20. - * This function is only useful when using the P3D renderer as the default - * P2D renderer does not use this information. - * - * ( end auto-generated ) - * - * @webref shape:curves - * @param detail resolution of the curves - * @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float) - * @see PGraphics#curveVertex(float, float, float) - * @see PGraphics#curveTightness(float) - */ - public void bezierDetail(int detail) { - g.bezierDetail(detail); - } - - - public void bezier(float x1, float y1, - float x2, float y2, - float x3, float y3, - float x4, float y4) { - g.bezier(x1, y1, x2, y2, x3, y3, x4, y4); - } - - - /** - * ( begin auto-generated from bezier.xml ) - * - * Draws a Bezier curve on the screen. These curves are defined by a series - * of anchor and control points. The first two parameters specify the first - * anchor point and the last two parameters specify the other anchor point. - * The middle parameters specify the control points which define the shape - * of the curve. Bezier curves were developed by French engineer Pierre - * Bezier. Using the 3D version requires rendering with P3D (see the - * Environment reference for more information). - * - * ( end auto-generated ) - * - *

      Advanced

      - * Draw a cubic bezier curve. The first and last points are - * the on-curve points. The middle two are the 'control' points, - * or 'handles' in an application like Illustrator. - *

      - * Identical to typing: - *

      beginShape();
      -   * vertex(x1, y1);
      -   * bezierVertex(x2, y2, x3, y3, x4, y4);
      -   * endShape();
      -   * 
      - * In Postscript-speak, this would be: - *
      moveto(x1, y1);
      -   * curveto(x2, y2, x3, y3, x4, y4);
      - * If you were to try and continue that curve like so: - *
      curveto(x5, y5, x6, y6, x7, y7);
      - * This would be done in processing by adding these statements: - *
      bezierVertex(x5, y5, x6, y6, x7, y7)
      -   * 
      - * To draw a quadratic (instead of cubic) curve, - * use the control point twice by doubling it: - *
      bezier(x1, y1, cx, cy, cx, cy, x2, y2);
      - * - * @webref shape:curves - * @param x1 coordinates for the first anchor point - * @param y1 coordinates for the first anchor point - * @param z1 coordinates for the first anchor point - * @param x2 coordinates for the first control point - * @param y2 coordinates for the first control point - * @param z2 coordinates for the first control point - * @param x3 coordinates for the second control point - * @param y3 coordinates for the second control point - * @param z3 coordinates for the second control point - * @param x4 coordinates for the second anchor point - * @param y4 coordinates for the second anchor point - * @param z4 coordinates for the second anchor point - * - * @see PGraphics#bezierVertex(float, float, float, float, float, float) - * @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float) - */ - public void bezier(float x1, float y1, float z1, - float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - g.bezier(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4); - } - - - /** - * ( begin auto-generated from curvePoint.xml ) - * - * Evalutes the curve at point t for points a, b, c, d. The parameter t - * varies between 0 and 1, a and d are the control points, and b and c are - * the points on the curve. This can be done once with the x coordinates and a - * second time with the y coordinates to get the location of a curve at t. - * - * ( end auto-generated ) - * - * @webref shape:curves - * @param a coordinate of first control point - * @param b coordinate of first point on the curve - * @param c coordinate of second point on the curve - * @param d coordinate of second control point - * @param t value between 0 and 1 - * @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float) - * @see PGraphics#curveVertex(float, float) - * @see PGraphics#bezierPoint(float, float, float, float, float) - */ - public float curvePoint(float a, float b, float c, float d, float t) { - return g.curvePoint(a, b, c, d, t); - } - - - /** - * ( begin auto-generated from curveTangent.xml ) - * - * Calculates the tangent of a point on a curve. There's a good definition - * of tangent on Wikipedia. - * - * ( end auto-generated ) - * - *

      Advanced

      - * Code thanks to Dave Bollinger (Bug #715) - * - * @webref shape:curves - * @param a coordinate of first point on the curve - * @param b coordinate of first control point - * @param c coordinate of second control point - * @param d coordinate of second point on the curve - * @param t value between 0 and 1 - * @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float) - * @see PGraphics#curveVertex(float, float) - * @see PGraphics#curvePoint(float, float, float, float, float) - * @see PGraphics#bezierTangent(float, float, float, float, float) - */ - public float curveTangent(float a, float b, float c, float d, float t) { - return g.curveTangent(a, b, c, d, t); - } - - - /** - * ( begin auto-generated from curveDetail.xml ) - * - * Sets the resolution at which curves display. The default value is 20. - * This function is only useful when using the P3D renderer as the default - * P2D renderer does not use this information. - * - * ( end auto-generated ) - * - * @webref shape:curves - * @param detail resolution of the curves - * @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float) - * @see PGraphics#curveVertex(float, float) - * @see PGraphics#curveTightness(float) - */ - public void curveDetail(int detail) { - g.curveDetail(detail); - } - - - /** - * ( begin auto-generated from curveTightness.xml ) - * - * Modifies the quality of forms created with curve() and - * curveVertex(). The parameter squishy determines how the - * curve fits to the vertex points. The value 0.0 is the default value for - * squishy (this value defines the curves to be Catmull-Rom splines) - * and the value 1.0 connects all the points with straight lines. Values - * within the range -5.0 and 5.0 will deform the curves but will leave them - * recognizable and as values increase in magnitude, they will continue to deform. - * - * ( end auto-generated ) - * - * @webref shape:curves - * @param tightness amount of deformation from the original vertices - * @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float) - * @see PGraphics#curveVertex(float, float) - */ - public void curveTightness(float tightness) { - g.curveTightness(tightness); - } - - - /** - * ( begin auto-generated from curve.xml ) - * - * Draws a curved line on the screen. The first and second parameters - * specify the beginning control point and the last two parameters specify - * the ending control point. The middle parameters specify the start and - * stop of the curve. Longer curves can be created by putting a series of - * curve() functions together or using curveVertex(). An - * additional function called curveTightness() provides control for - * the visual quality of the curve. The curve() function is an - * implementation of Catmull-Rom splines. Using the 3D version requires - * rendering with P3D (see the Environment reference for more information). - * - * ( end auto-generated ) - * - *

      Advanced

      - * As of revision 0070, this function no longer doubles the first - * and last points. The curves are a bit more boring, but it's more - * mathematically correct, and properly mirrored in curvePoint(). - *

      - * Identical to typing out:

      -   * beginShape();
      -   * curveVertex(x1, y1);
      -   * curveVertex(x2, y2);
      -   * curveVertex(x3, y3);
      -   * curveVertex(x4, y4);
      -   * endShape();
      -   * 
      - * - * @webref shape:curves - * @param x1 coordinates for the beginning control point - * @param y1 coordinates for the beginning control point - * @param x2 coordinates for the first point - * @param y2 coordinates for the first point - * @param x3 coordinates for the second point - * @param y3 coordinates for the second point - * @param x4 coordinates for the ending control point - * @param y4 coordinates for the ending control point - * @see PGraphics#curveVertex(float, float) - * @see PGraphics#curveTightness(float) - * @see PGraphics#bezier(float, float, float, float, float, float, float, float, float, float, float, float) - */ - public void curve(float x1, float y1, - float x2, float y2, - float x3, float y3, - float x4, float y4) { - g.curve(x1, y1, x2, y2, x3, y3, x4, y4); - } - - - /** - * @param z1 coordinates for the beginning control point - * @param z2 coordinates for the first point - * @param z3 coordinates for the second point - * @param z4 coordinates for the ending control point - */ - public void curve(float x1, float y1, float z1, - float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - g.curve(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4); - } - - - /** - * ( begin auto-generated from imageMode.xml ) - * - * Modifies the location from which images draw. The default mode is - * imageMode(CORNER), which specifies the location to be the upper - * left corner and uses the fourth and fifth parameters of image() - * to set the image's width and height. The syntax - * imageMode(CORNERS) uses the second and third parameters of - * image() to set the location of one corner of the image and uses - * the fourth and fifth parameters to set the opposite corner. Use - * imageMode(CENTER) to draw images centered at the given x and y - * position.
      - *
      - * The parameter to imageMode() must be written in ALL CAPS because - * Processing is a case-sensitive language. - * - * ( end auto-generated ) - * - * @webref image:loading_displaying - * @param mode either CORNER, CORNERS, or CENTER - * @see PApplet#loadImage(String, String) - * @see PImage - * @see PGraphics#image(PImage, float, float, float, float) - * @see PGraphics#background(float, float, float, float) - */ - public void imageMode(int mode) { - g.imageMode(mode); - } - - - /** - * ( begin auto-generated from image.xml ) - * - * Displays images to the screen. The images must be in the sketch's "data" - * directory to load correctly. Select "Add file..." from the "Sketch" menu - * to add the image. Processing currently works with GIF, JPEG, and Targa - * images. The img parameter specifies the image to display and the - * x and y parameters define the location of the image from - * its upper-left corner. The image is displayed at its original size - * unless the width and height parameters specify a different - * size.
      - *
      - * The imageMode() function changes the way the parameters work. For - * example, a call to imageMode(CORNERS) will change the - * width and height parameters to define the x and y values - * of the opposite corner of the image.
      - *
      - * The color of an image may be modified with the tint() function. - * This function will maintain transparency for GIF and PNG images. - * - * ( end auto-generated ) - * - *

      Advanced

      - * Starting with release 0124, when using the default (JAVA2D) renderer, - * smooth() will also improve image quality of resized images. - * - * @webref image:loading_displaying - * @param img the image to display - * @param a x-coordinate of the image by default - * @param b y-coordinate of the image by default - * @see PApplet#loadImage(String, String) - * @see PImage - * @see PGraphics#imageMode(int) - * @see PGraphics#tint(float) - * @see PGraphics#background(float, float, float, float) - * @see PGraphics#alpha(int) - */ - public void image(PImage img, float a, float b) { - g.image(img, a, b); - } - - - /** - * @param c width to display the image by default - * @param d height to display the image by default - */ - public void image(PImage img, float a, float b, float c, float d) { - g.image(img, a, b, c, d); - } - - - /** - * Draw an image(), also specifying u/v coordinates. - * In this method, the u, v coordinates are always based on image space - * location, regardless of the current textureMode(). - * - * @nowebref - */ - public void image(PImage img, - float a, float b, float c, float d, - int u1, int v1, int u2, int v2) { - g.image(img, a, b, c, d, u1, v1, u2, v2); - } - - - /** - * ( begin auto-generated from shapeMode.xml ) - * - * Modifies the location from which shapes draw. The default mode is - * shapeMode(CORNER), which specifies the location to be the upper - * left corner of the shape and uses the third and fourth parameters of - * shape() to specify the width and height. The syntax - * shapeMode(CORNERS) uses the first and second parameters of - * shape() to set the location of one corner and uses the third and - * fourth parameters to set the opposite corner. The syntax - * shapeMode(CENTER) draws the shape from its center point and uses - * the third and forth parameters of shape() to specify the width - * and height. The parameter must be written in "ALL CAPS" because - * Processing is a case sensitive language. - * - * ( end auto-generated ) - * - * @webref shape:loading_displaying - * @param mode either CORNER, CORNERS, CENTER - * @see PShape - * @see PGraphics#shape(PShape) - * @see PGraphics#rectMode(int) - */ - public void shapeMode(int mode) { - g.shapeMode(mode); - } - - - public void shape(PShape shape) { - g.shape(shape); - } - - - /** - * ( begin auto-generated from shape.xml ) - * - * Displays shapes to the screen. The shapes must be in the sketch's "data" - * directory to load correctly. Select "Add file..." from the "Sketch" menu - * to add the shape. Processing currently works with SVG shapes only. The - * sh parameter specifies the shape to display and the x and - * y parameters define the location of the shape from its upper-left - * corner. The shape is displayed at its original size unless the - * width and height parameters specify a different size. The - * shapeMode() function changes the way the parameters work. A call - * to shapeMode(CORNERS), for example, will change the width and - * height parameters to define the x and y values of the opposite corner of - * the shape. - *

      - * Note complex shapes may draw awkwardly with P3D. This renderer does not - * yet support shapes that have holes or complicated breaks. - * - * ( end auto-generated ) - * - * @webref shape:loading_displaying - * @param shape the shape to display - * @param x x-coordinate of the shape - * @param y y-coordinate of the shape - * @see PShape - * @see PApplet#loadShape(String) - * @see PGraphics#shapeMode(int) - * - * Convenience method to draw at a particular location. - */ - public void shape(PShape shape, float x, float y) { - g.shape(shape, x, y); - } - - - /** - * @param a x-coordinate of the shape - * @param b y-coordinate of the shape - * @param c width to display the shape - * @param d height to display the shape - */ - public void shape(PShape shape, float a, float b, float c, float d) { - g.shape(shape, a, b, c, d); - } - - - public void textAlign(int alignX) { - g.textAlign(alignX); - } - - - /** - * ( begin auto-generated from textAlign.xml ) - * - * Sets the current alignment for drawing text. The parameters LEFT, - * CENTER, and RIGHT set the display characteristics of the letters in - * relation to the values for the x and y parameters of the - * text() function. - *

      - * In Processing 0125 and later, an optional second parameter can be used - * to vertically align the text. BASELINE is the default, and the vertical - * alignment will be reset to BASELINE if the second parameter is not used. - * The TOP and CENTER parameters are straightforward. The BOTTOM parameter - * offsets the line based on the current textDescent(). For multiple - * lines, the final line will be aligned to the bottom, with the previous - * lines appearing above it. - *

      - * When using text() with width and height parameters, BASELINE is - * ignored, and treated as TOP. (Otherwise, text would by default draw - * outside the box, since BASELINE is the default setting. BASELINE is not - * a useful drawing mode for text drawn in a rectangle.) - *

      - * The vertical alignment is based on the value of textAscent(), - * which many fonts do not specify correctly. It may be necessary to use a - * hack and offset by a few pixels by hand so that the offset looks - * correct. To do this as less of a hack, use some percentage of - * textAscent() or textDescent() so that the hack works even - * if you change the size of the font. - * - * ( end auto-generated ) - * - * @webref typography:attributes - * @param alignX horizontal alignment, either LEFT, CENTER, or RIGHT - * @param alignY vertical alignment, either TOP, BOTTOM, CENTER, or BASELINE - * @see PApplet#loadFont(String) - * @see PFont - * @see PGraphics#text(String, float, float) - * @see PGraphics#textSize(float) - * @see PGraphics#textAscent() - * @see PGraphics#textDescent() - */ - public void textAlign(int alignX, int alignY) { - g.textAlign(alignX, alignY); - } - - - /** - * ( begin auto-generated from textAscent.xml ) - * - * Returns ascent of the current font at its current size. This information - * is useful for determining the height of the font above the baseline. For - * example, adding the textAscent() and textDescent() values - * will give you the total height of the line. - * - * ( end auto-generated ) - * - * @webref typography:metrics - * @see PGraphics#textDescent() - */ - public float textAscent() { - return g.textAscent(); - } - - - /** - * ( begin auto-generated from textDescent.xml ) - * - * Returns descent of the current font at its current size. This - * information is useful for determining the height of the font below the - * baseline. For example, adding the textAscent() and - * textDescent() values will give you the total height of the line. - * - * ( end auto-generated ) - * - * @webref typography:metrics - * @see PGraphics#textAscent() - */ - public float textDescent() { - return g.textDescent(); - } - - - /** - * ( begin auto-generated from textFont.xml ) - * - * Sets the current font that will be drawn with the text() - * function. Fonts must be loaded with loadFont() before it can be - * used. This font will be used in all subsequent calls to the - * text() function. If no size parameter is input, the font - * will appear at its original size (the size it was created at with the - * "Create Font..." tool) until it is changed with textSize().

      Because fonts are usually bitmaped, you should create fonts at - * the sizes that will be used most commonly. Using textFont() - * without the size parameter will result in the cleanest-looking text.

      With the default (JAVA2D) and PDF renderers, it's also possible - * to enable the use of native fonts via the command - * hint(ENABLE_NATIVE_FONTS). This will produce vector text in - * JAVA2D sketches and PDF output in cases where the vector data is - * available: when the font is still installed, or the font is created via - * the createFont() function (rather than the Create Font tool). - * - * ( end auto-generated ) - * - * @webref typography:loading_displaying - * @param which any variable of the type PFont - * @see PApplet#createFont(String, float, boolean) - * @see PApplet#loadFont(String) - * @see PFont - * @see PGraphics#text(String, float, float) - * @see PGraphics#textSize(float) - */ - public void textFont(PFont which) { - g.textFont(which); - } - - - /** - * @param size the size of the letters in units of pixels - */ - public void textFont(PFont which, float size) { - g.textFont(which, size); - } - - - /** - * ( begin auto-generated from textLeading.xml ) - * - * Sets the spacing between lines of text in units of pixels. This setting - * will be used in all subsequent calls to the text() function. - * - * ( end auto-generated ) - * - * @webref typography:attributes - * @param leading the size in pixels for spacing between lines - * @see PApplet#loadFont(String) - * @see PFont#PFont - * @see PGraphics#text(String, float, float) - * @see PGraphics#textFont(PFont) - * @see PGraphics#textSize(float) - */ - public void textLeading(float leading) { - g.textLeading(leading); - } - - - /** - * ( begin auto-generated from textMode.xml ) - * - * Sets the way text draws to the screen. In the default configuration, the - * MODEL mode, it's possible to rotate, scale, and place letters in - * two and three dimensional space.
      - *
      - * The SHAPE mode draws text using the the glyph outlines of - * individual characters rather than as textures. This mode is only - * supported with the PDF and P3D renderer settings. With the - * PDF renderer, you must call textMode(SHAPE) before any - * other drawing occurs. If the outlines are not available, then - * textMode(SHAPE) will be ignored and textMode(MODEL) will - * be used instead.
      - *
      - * The textMode(SHAPE) option in P3D can be combined with - * beginRaw() to write vector-accurate text to 2D and 3D output - * files, for instance DXF or PDF. The SHAPE mode is - * not currently optimized for P3D, so if recording shape data, use - * textMode(MODEL) until you're ready to capture the geometry with beginRaw(). - * - * ( end auto-generated ) - * - * @webref typography:attributes - * @param mode either MODEL or SHAPE - * @see PApplet#loadFont(String) - * @see PFont#PFont - * @see PGraphics#text(String, float, float) - * @see PGraphics#textFont(PFont) - * @see PGraphics#beginRaw(PGraphics) - * @see PApplet#createFont(String, float, boolean) - */ - public void textMode(int mode) { - g.textMode(mode); - } - - - /** - * ( begin auto-generated from textSize.xml ) - * - * Sets the current font size. This size will be used in all subsequent - * calls to the text() function. Font size is measured in units of pixels. - * - * ( end auto-generated ) - * - * @webref typography:attributes - * @param size the size of the letters in units of pixels - * @see PApplet#loadFont(String) - * @see PFont#PFont - * @see PGraphics#text(String, float, float) - * @see PGraphics#textFont(PFont) - */ - public void textSize(float size) { - g.textSize(size); - } - - - /** - * @param c the character to measure - */ - public float textWidth(char c) { - return g.textWidth(c); - } - - - /** - * ( begin auto-generated from textWidth.xml ) - * - * Calculates and returns the width of any character or text string. - * - * ( end auto-generated ) - * - * @webref typography:attributes - * @param str the String of characters to measure - * @see PApplet#loadFont(String) - * @see PFont#PFont - * @see PGraphics#text(String, float, float) - * @see PGraphics#textFont(PFont) - * @see PGraphics#textSize(float) - */ - public float textWidth(String str) { - return g.textWidth(str); - } - - - /** - * @nowebref - */ - public float textWidth(char[] chars, int start, int length) { - return g.textWidth(chars, start, length); - } - - - /** - * ( begin auto-generated from text.xml ) - * - * Draws text to the screen. Displays the information specified in the - * data or stringdata parameters on the screen in the - * position specified by the x and y parameters and the - * optional z parameter. A default font will be used unless a font - * is set with the textFont() function. Change the color of the text - * with the fill() function. The text displays in relation to the - * textAlign() function, which gives the option to draw to the left, - * right, and center of the coordinates. - *

      - * The x2 and y2 parameters define a rectangular area to - * display within and may only be used with string data. For text drawn - * inside a rectangle, the coordinates are interpreted based on the current - * rectMode() setting. - * - * ( end auto-generated ) - * - * @webref typography:loading_displaying - * @param c the alphanumeric character to be displayed - * @param x x-coordinate of text - * @param y y-coordinate of text - * @see PGraphics#textAlign(int, int) - * @see PGraphics#textFont(PFont) - * @see PGraphics#textMode(int) - * @see PGraphics#textSize(float) - * @see PGraphics#textLeading(float) - * @see PGraphics#textWidth(String) - * @see PGraphics#textAscent() - * @see PGraphics#textDescent() - * @see PGraphics#rectMode(int) - * @see PGraphics#fill(int, float) - * @see_external String - */ - public void text(char c, float x, float y) { - g.text(c, x, y); - } - - - /** - * @param z z-coordinate of text - */ - public void text(char c, float x, float y, float z) { - g.text(c, x, y, z); - } - - - /** - *

      Advanced

      - * Draw a chunk of text. - * Newlines that are \n (Unix newline or linefeed char, ascii 10) - * are honored, but \r (carriage return, Windows and Mac OS) are - * ignored. - */ - public void text(String str, float x, float y) { - g.text(str, x, y); - } - - - /** - *

      Advanced

      - * Method to draw text from an array of chars. This method will usually be - * more efficient than drawing from a String object, because the String will - * not be converted to a char array before drawing. - * @param chars the alphanumberic symbols to be displayed - * @param start array index at which to start writing characters - * @param stop array index at which to stop writing characters - */ - public void text(char[] chars, int start, int stop, float x, float y) { - g.text(chars, start, stop, x, y); - } - - - /** - * Same as above but with a z coordinate. - */ - public void text(String str, float x, float y, float z) { - g.text(str, x, y, z); - } - - - public void text(char[] chars, int start, int stop, - float x, float y, float z) { - g.text(chars, start, stop, x, y, z); - } - - - /** - *

      Advanced

      - * Draw text in a box that is constrained to a particular size. - * The current rectMode() determines what the coordinates mean - * (whether x1/y1/x2/y2 or x/y/w/h). - *

      - * Note that the x,y coords of the start of the box - * will align with the *ascent* of the text, not the baseline, - * as is the case for the other text() functions. - *

      - * Newlines that are \n (Unix newline or linefeed char, ascii 10) - * are honored, and \r (carriage return, Windows and Mac OS) are - * ignored. - * - * @param x1 by default, the x-coordinate of text, see rectMode() for more info - * @param y1 by default, the y-coordinate of text, see rectMode() for more info - * @param x2 by default, the width of the text box, see rectMode() for more info - * @param y2 by default, the height of the text box, see rectMode() for more info - */ - public void text(String str, float x1, float y1, float x2, float y2) { - g.text(str, x1, y1, x2, y2); - } - - - public void text(int num, float x, float y) { - g.text(num, x, y); - } - - - public void text(int num, float x, float y, float z) { - g.text(num, x, y, z); - } - - - /** - * This does a basic number formatting, to avoid the - * generally ugly appearance of printing floats. - * Users who want more control should use their own nf() cmmand, - * or if they want the long, ugly version of float, - * use String.valueOf() to convert the float to a String first. - * - * @param num the numeric value to be displayed - */ - public void text(float num, float x, float y) { - g.text(num, x, y); - } - - - public void text(float num, float x, float y, float z) { - g.text(num, x, y, z); - } - - - /** - * ( begin auto-generated from push.xml ) - * - * The push() function saves the current drawing style - * settings and transformations, while pop() restores these - * settings. Note that these functions are always used together. - * They allow you to change the style and transformation settings - * and later return to what you had. When a new state is started - * with push(), it builds on the current style and transform - * information.
      - *
      - * push() stores information related to the current - * transformation state and style settings controlled by the - * following functions: rotate(), translate(), - * scale(), fill(), stroke(), tint(), - * strokeWeight(), strokeCap(), strokeJoin(), - * imageMode(), rectMode(), ellipseMode(), - * colorMode(), textAlign(), textFont(), - * textMode(), textSize(), textLeading().
      - *
      - * The push() and pop() functions were added with - * Processing 3.5. They can be used in place of pushMatrix(), - * popMatrix(), pushStyles(), and popStyles(). - * The difference is that push() and pop() control both the - * transformations (rotate, scale, translate) and the drawing styles - * at the same time. - * - * ( end auto-generated ) - * - * @webref structure - * @see PGraphics#pop() - */ - public void push() { - g.push(); - } - - - /** - * ( begin auto-generated from pop.xml ) - * - * The pop() function restores the previous drawing style - * settings and transformations after push() has changed them. - * Note that these functions are always used together. They allow - * you to change the style and transformation settings and later - * return to what you had. When a new state is started with push(), - * it builds on the current style and transform information.
      - *
      - *
      - * push() stores information related to the current - * transformation state and style settings controlled by the - * following functions: rotate(), translate(), - * scale(), fill(), stroke(), tint(), - * strokeWeight(), strokeCap(), strokeJoin(), - * imageMode(), rectMode(), ellipseMode(), - * colorMode(), textAlign(), textFont(), - * textMode(), textSize(), textLeading().
      - *
      - * The push() and pop() functions were added with - * Processing 3.5. They can be used in place of pushMatrix(), - * popMatrix(), pushStyles(), and popStyles(). - * The difference is that push() and pop() control both the - * transformations (rotate, scale, translate) and the drawing styles - * at the same time. - * - * ( end auto-generated ) - * - * @webref structure - * @see PGraphics#push() - */ - public void pop() { - g.pop(); - } - - - /** - * ( begin auto-generated from pushMatrix.xml ) - * - * Pushes the current transformation matrix onto the matrix stack. - * Understanding pushMatrix() and popMatrix() requires - * understanding the concept of a matrix stack. The pushMatrix() - * function saves the current coordinate system to the stack and - * popMatrix() restores the prior coordinate system. - * pushMatrix() and popMatrix() are used in conjuction with - * the other transformation functions and may be embedded to control the - * scope of the transformations. - * - * ( end auto-generated ) - * - * @webref transform - * @see PGraphics#popMatrix() - * @see PGraphics#translate(float, float, float) - * @see PGraphics#scale(float) - * @see PGraphics#rotate(float) - * @see PGraphics#rotateX(float) - * @see PGraphics#rotateY(float) - * @see PGraphics#rotateZ(float) - */ - public void pushMatrix() { - g.pushMatrix(); - } - - - /** - * ( begin auto-generated from popMatrix.xml ) - * - * Pops the current transformation matrix off the matrix stack. - * Understanding pushing and popping requires understanding the concept of - * a matrix stack. The pushMatrix() function saves the current - * coordinate system to the stack and popMatrix() restores the prior - * coordinate system. pushMatrix() and popMatrix() are used - * in conjuction with the other transformation functions and may be - * embedded to control the scope of the transformations. - * - * ( end auto-generated ) - * - * @webref transform - * @see PGraphics#pushMatrix() - */ - public void popMatrix() { - g.popMatrix(); - } - - - /** - * ( begin auto-generated from translate.xml ) - * - * Specifies an amount to displace objects within the display window. The - * x parameter specifies left/right translation, the y - * parameter specifies up/down translation, and the z parameter - * specifies translations toward/away from the screen. Using this function - * with the z parameter requires using P3D as a parameter in - * combination with size as shown in the above example. Transformations - * apply to everything that happens after and subsequent calls to the - * function accumulates the effect. For example, calling translate(50, - * 0) and then translate(20, 0) is the same as translate(70, - * 0). If translate() is called within draw(), the - * transformation is reset when the loop begins again. This function can be - * further controlled by the pushMatrix() and popMatrix(). - * - * ( end auto-generated ) - * - * @webref transform - * @param x left/right translation - * @param y up/down translation - * @see PGraphics#popMatrix() - * @see PGraphics#pushMatrix() - * @see PGraphics#rotate(float) - * @see PGraphics#rotateX(float) - * @see PGraphics#rotateY(float) - * @see PGraphics#rotateZ(float) - * @see PGraphics#scale(float, float, float) - */ - public void translate(float x, float y) { - g.translate(x, y); - } - - - /** - * @param z forward/backward translation - */ - public void translate(float x, float y, float z) { - g.translate(x, y, z); - } - - - /** - * ( begin auto-generated from rotate.xml ) - * - * Rotates a shape the amount specified by the angle parameter. - * Angles should be specified in radians (values from 0 to TWO_PI) or - * converted to radians with the radians() function. - *

      - * Objects are always rotated around their relative position to the origin - * and positive numbers rotate objects in a clockwise direction. - * Transformations apply to everything that happens after and subsequent - * calls to the function accumulates the effect. For example, calling - * rotate(HALF_PI) and then rotate(HALF_PI) is the same as - * rotate(PI). All tranformations are reset when draw() - * begins again. - *

      - * Technically, rotate() multiplies the current transformation - * matrix by a rotation matrix. This function can be further controlled by - * the pushMatrix() and popMatrix(). - * - * ( end auto-generated ) - * - * @webref transform - * @param angle angle of rotation specified in radians - * @see PGraphics#popMatrix() - * @see PGraphics#pushMatrix() - * @see PGraphics#rotateX(float) - * @see PGraphics#rotateY(float) - * @see PGraphics#rotateZ(float) - * @see PGraphics#scale(float, float, float) - * @see PApplet#radians(float) - */ - public void rotate(float angle) { - g.rotate(angle); - } - - - /** - * ( begin auto-generated from rotateX.xml ) - * - * Rotates a shape around the x-axis the amount specified by the - * angle parameter. Angles should be specified in radians (values - * from 0 to PI*2) or converted to radians with the radians() - * function. Objects are always rotated around their relative position to - * the origin and positive numbers rotate objects in a counterclockwise - * direction. Transformations apply to everything that happens after and - * subsequent calls to the function accumulates the effect. For example, - * calling rotateX(PI/2) and then rotateX(PI/2) is the same - * as rotateX(PI). If rotateX() is called within the - * draw(), the transformation is reset when the loop begins again. - * This function requires using P3D as a third parameter to size() - * as shown in the example above. - * - * ( end auto-generated ) - * - * @webref transform - * @param angle angle of rotation specified in radians - * @see PGraphics#popMatrix() - * @see PGraphics#pushMatrix() - * @see PGraphics#rotate(float) - * @see PGraphics#rotateY(float) - * @see PGraphics#rotateZ(float) - * @see PGraphics#scale(float, float, float) - * @see PGraphics#translate(float, float, float) - */ - public void rotateX(float angle) { - g.rotateX(angle); - } - - - /** - * ( begin auto-generated from rotateY.xml ) - * - * Rotates a shape around the y-axis the amount specified by the - * angle parameter. Angles should be specified in radians (values - * from 0 to PI*2) or converted to radians with the radians() - * function. Objects are always rotated around their relative position to - * the origin and positive numbers rotate objects in a counterclockwise - * direction. Transformations apply to everything that happens after and - * subsequent calls to the function accumulates the effect. For example, - * calling rotateY(PI/2) and then rotateY(PI/2) is the same - * as rotateY(PI). If rotateY() is called within the - * draw(), the transformation is reset when the loop begins again. - * This function requires using P3D as a third parameter to size() - * as shown in the examples above. - * - * ( end auto-generated ) - * - * @webref transform - * @param angle angle of rotation specified in radians - * @see PGraphics#popMatrix() - * @see PGraphics#pushMatrix() - * @see PGraphics#rotate(float) - * @see PGraphics#rotateX(float) - * @see PGraphics#rotateZ(float) - * @see PGraphics#scale(float, float, float) - * @see PGraphics#translate(float, float, float) - */ - public void rotateY(float angle) { - g.rotateY(angle); - } - - - /** - * ( begin auto-generated from rotateZ.xml ) - * - * Rotates a shape around the z-axis the amount specified by the - * angle parameter. Angles should be specified in radians (values - * from 0 to PI*2) or converted to radians with the radians() - * function. Objects are always rotated around their relative position to - * the origin and positive numbers rotate objects in a counterclockwise - * direction. Transformations apply to everything that happens after and - * subsequent calls to the function accumulates the effect. For example, - * calling rotateZ(PI/2) and then rotateZ(PI/2) is the same - * as rotateZ(PI). If rotateZ() is called within the - * draw(), the transformation is reset when the loop begins again. - * This function requires using P3D as a third parameter to size() - * as shown in the examples above. - * - * ( end auto-generated ) - * - * @webref transform - * @param angle angle of rotation specified in radians - * @see PGraphics#popMatrix() - * @see PGraphics#pushMatrix() - * @see PGraphics#rotate(float) - * @see PGraphics#rotateX(float) - * @see PGraphics#rotateY(float) - * @see PGraphics#scale(float, float, float) - * @see PGraphics#translate(float, float, float) - */ - public void rotateZ(float angle) { - g.rotateZ(angle); - } - - - /** - *

      Advanced

      - * Rotate about a vector in space. Same as the glRotatef() function. - * @nowebref - * @param x - * @param y - * @param z - */ - public void rotate(float angle, float x, float y, float z) { - g.rotate(angle, x, y, z); - } - - - /** - * ( begin auto-generated from scale.xml ) - * - * Increases or decreases the size of a shape by expanding and contracting - * vertices. Objects always scale from their relative origin to the - * coordinate system. Scale values are specified as decimal percentages. - * For example, the function call scale(2.0) increases the dimension - * of a shape by 200%. Transformations apply to everything that happens - * after and subsequent calls to the function multiply the effect. For - * example, calling scale(2.0) and then scale(1.5) is the - * same as scale(3.0). If scale() is called within - * draw(), the transformation is reset when the loop begins again. - * Using this fuction with the z parameter requires using P3D as a - * parameter for size() as shown in the example above. This function - * can be further controlled by pushMatrix() and popMatrix(). - * - * ( end auto-generated ) - * - * @webref transform - * @param s percentage to scale the object - * @see PGraphics#pushMatrix() - * @see PGraphics#popMatrix() - * @see PGraphics#translate(float, float, float) - * @see PGraphics#rotate(float) - * @see PGraphics#rotateX(float) - * @see PGraphics#rotateY(float) - * @see PGraphics#rotateZ(float) - */ - public void scale(float s) { - g.scale(s); - } - - - /** - *

      Advanced

      - * Scale in X and Y. Equivalent to scale(sx, sy, 1). - * - * Not recommended for use in 3D, because the z-dimension is just - * scaled by 1, since there's no way to know what else to scale it by. - * - * @param x percentage to scale the object in the x-axis - * @param y percentage to scale the object in the y-axis - */ - public void scale(float x, float y) { - g.scale(x, y); - } - - - /** - * @param z percentage to scale the object in the z-axis - */ - public void scale(float x, float y, float z) { - g.scale(x, y, z); - } - - - /** - * ( begin auto-generated from shearX.xml ) - * - * Shears a shape around the x-axis the amount specified by the - * angle parameter. Angles should be specified in radians (values - * from 0 to PI*2) or converted to radians with the radians() - * function. Objects are always sheared around their relative position to - * the origin and positive numbers shear objects in a clockwise direction. - * Transformations apply to everything that happens after and subsequent - * calls to the function accumulates the effect. For example, calling - * shearX(PI/2) and then shearX(PI/2) is the same as - * shearX(PI). If shearX() is called within the - * draw(), the transformation is reset when the loop begins again. - *

      - * Technically, shearX() multiplies the current transformation - * matrix by a rotation matrix. This function can be further controlled by - * the pushMatrix() and popMatrix() functions. - * - * ( end auto-generated ) - * - * @webref transform - * @param angle angle of shear specified in radians - * @see PGraphics#popMatrix() - * @see PGraphics#pushMatrix() - * @see PGraphics#shearY(float) - * @see PGraphics#scale(float, float, float) - * @see PGraphics#translate(float, float, float) - * @see PApplet#radians(float) - */ - public void shearX(float angle) { - g.shearX(angle); - } - - - /** - * ( begin auto-generated from shearY.xml ) - * - * Shears a shape around the y-axis the amount specified by the - * angle parameter. Angles should be specified in radians (values - * from 0 to PI*2) or converted to radians with the radians() - * function. Objects are always sheared around their relative position to - * the origin and positive numbers shear objects in a clockwise direction. - * Transformations apply to everything that happens after and subsequent - * calls to the function accumulates the effect. For example, calling - * shearY(PI/2) and then shearY(PI/2) is the same as - * shearY(PI). If shearY() is called within the - * draw(), the transformation is reset when the loop begins again. - *

      - * Technically, shearY() multiplies the current transformation - * matrix by a rotation matrix. This function can be further controlled by - * the pushMatrix() and popMatrix() functions. - * - * ( end auto-generated ) - * - * @webref transform - * @param angle angle of shear specified in radians - * @see PGraphics#popMatrix() - * @see PGraphics#pushMatrix() - * @see PGraphics#shearX(float) - * @see PGraphics#scale(float, float, float) - * @see PGraphics#translate(float, float, float) - * @see PApplet#radians(float) - */ - public void shearY(float angle) { - g.shearY(angle); - } - - - /** - * ( begin auto-generated from resetMatrix.xml ) - * - * Replaces the current matrix with the identity matrix. The equivalent - * function in OpenGL is glLoadIdentity(). - * - * ( end auto-generated ) - * - * @webref transform - * @see PGraphics#pushMatrix() - * @see PGraphics#popMatrix() - * @see PGraphics#applyMatrix(PMatrix) - * @see PGraphics#printMatrix() - */ - public void resetMatrix() { - g.resetMatrix(); - } - - - /** - * ( begin auto-generated from applyMatrix.xml ) - * - * Multiplies the current matrix by the one specified through the - * parameters. This is very slow because it will try to calculate the - * inverse of the transform, so avoid it whenever possible. The equivalent - * function in OpenGL is glMultMatrix(). - * - * ( end auto-generated ) - * - * @webref transform - * @source - * @see PGraphics#pushMatrix() - * @see PGraphics#popMatrix() - * @see PGraphics#resetMatrix() - * @see PGraphics#printMatrix() - */ - public void applyMatrix(PMatrix source) { - g.applyMatrix(source); - } - - - public void applyMatrix(PMatrix2D source) { - g.applyMatrix(source); - } - - - /** - * @param n00 numbers which define the 4x4 matrix to be multiplied - * @param n01 numbers which define the 4x4 matrix to be multiplied - * @param n02 numbers which define the 4x4 matrix to be multiplied - * @param n10 numbers which define the 4x4 matrix to be multiplied - * @param n11 numbers which define the 4x4 matrix to be multiplied - * @param n12 numbers which define the 4x4 matrix to be multiplied - */ - public void applyMatrix(float n00, float n01, float n02, - float n10, float n11, float n12) { - g.applyMatrix(n00, n01, n02, n10, n11, n12); - } - - - public void applyMatrix(PMatrix3D source) { - g.applyMatrix(source); - } - - - /** - * @param n03 numbers which define the 4x4 matrix to be multiplied - * @param n13 numbers which define the 4x4 matrix to be multiplied - * @param n20 numbers which define the 4x4 matrix to be multiplied - * @param n21 numbers which define the 4x4 matrix to be multiplied - * @param n22 numbers which define the 4x4 matrix to be multiplied - * @param n23 numbers which define the 4x4 matrix to be multiplied - * @param n30 numbers which define the 4x4 matrix to be multiplied - * @param n31 numbers which define the 4x4 matrix to be multiplied - * @param n32 numbers which define the 4x4 matrix to be multiplied - * @param n33 numbers which define the 4x4 matrix to be multiplied - */ - public void applyMatrix(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - g.applyMatrix(n00, n01, n02, n03, n10, n11, n12, n13, n20, n21, n22, n23, n30, n31, n32, n33); - } - - - public PMatrix getMatrix() { - return g.getMatrix(); - } - - - /** - * Copy the current transformation matrix into the specified target. - * Pass in null to create a new matrix. - */ - public PMatrix2D getMatrix(PMatrix2D target) { - return g.getMatrix(target); - } - - - /** - * Copy the current transformation matrix into the specified target. - * Pass in null to create a new matrix. - */ - public PMatrix3D getMatrix(PMatrix3D target) { - return g.getMatrix(target); - } - - - /** - * Set the current transformation matrix to the contents of another. - */ - public void setMatrix(PMatrix source) { - g.setMatrix(source); - } - - - /** - * Set the current transformation to the contents of the specified source. - */ - public void setMatrix(PMatrix2D source) { - g.setMatrix(source); - } - - - /** - * Set the current transformation to the contents of the specified source. - */ - public void setMatrix(PMatrix3D source) { - g.setMatrix(source); - } - - - /** - * ( begin auto-generated from printMatrix.xml ) - * - * Prints the current matrix to the Console (the text window at the bottom - * of Processing). - * - * ( end auto-generated ) - * - * @webref transform - * @see PGraphics#pushMatrix() - * @see PGraphics#popMatrix() - * @see PGraphics#resetMatrix() - * @see PGraphics#applyMatrix(PMatrix) - */ - public void printMatrix() { - g.printMatrix(); - } - - - /** - * ( begin auto-generated from beginCamera.xml ) - * - * The beginCamera() and endCamera() functions enable - * advanced customization of the camera space. The functions are useful if - * you want to more control over camera movement, however for most users, - * the camera() function will be sufficient.

      The camera - * functions will replace any transformations (such as rotate() or - * translate()) that occur before them in draw(), but they - * will not automatically replace the camera transform itself. For this - * reason, camera functions should be placed at the beginning of - * draw() (so that transformations happen afterwards), and the - * camera() function can be used after beginCamera() if you - * want to reset the camera before applying transformations.

      This function sets the matrix mode to the camera matrix so calls such - * as translate(), rotate(), applyMatrix() and resetMatrix() - * affect the camera. beginCamera() should always be used with a - * following endCamera() and pairs of beginCamera() and - * endCamera() cannot be nested. - * - * ( end auto-generated ) - * - * @webref lights_camera:camera - * @see PGraphics#camera() - * @see PGraphics#endCamera() - * @see PGraphics#applyMatrix(PMatrix) - * @see PGraphics#resetMatrix() - * @see PGraphics#translate(float, float, float) - * @see PGraphics#scale(float, float, float) - */ - public void beginCamera() { - g.beginCamera(); - } - - - /** - * ( begin auto-generated from endCamera.xml ) - * - * The beginCamera() and endCamera() functions enable - * advanced customization of the camera space. Please see the reference for - * beginCamera() for a description of how the functions are used. - * - * ( end auto-generated ) - * - * @webref lights_camera:camera - * @see PGraphics#beginCamera() - * @see PGraphics#camera(float, float, float, float, float, float, float, float, float) - */ - public void endCamera() { - g.endCamera(); - } - - - /** - * ( begin auto-generated from camera.xml ) - * - * Sets the position of the camera through setting the eye position, the - * center of the scene, and which axis is facing upward. Moving the eye - * position and the direction it is pointing (the center of the scene) - * allows the images to be seen from different angles. The version without - * any parameters sets the camera to the default position, pointing to the - * center of the display window with the Y axis as up. The default values - * are camera(width/2.0, height/2.0, (height/2.0) / tan(PI*30.0 / - * 180.0), width/2.0, height/2.0, 0, 0, 1, 0). This function is similar - * to gluLookAt() in OpenGL, but it first clears the current camera settings. - * - * ( end auto-generated ) - * - * @webref lights_camera:camera - * @see PGraphics#beginCamera() - * @see PGraphics#endCamera() - * @see PGraphics#frustum(float, float, float, float, float, float) - */ - public void camera() { - g.camera(); - } - - - /** - * @param eyeX x-coordinate for the eye - * @param eyeY y-coordinate for the eye - * @param eyeZ z-coordinate for the eye - * @param centerX x-coordinate for the center of the scene - * @param centerY y-coordinate for the center of the scene - * @param centerZ z-coordinate for the center of the scene - * @param upX usually 0.0, 1.0, or -1.0 - * @param upY usually 0.0, 1.0, or -1.0 - * @param upZ usually 0.0, 1.0, or -1.0 - */ - public void camera(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - g.camera(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); - } - - - /** - * ( begin auto-generated from printCamera.xml ) - * - * Prints the current camera matrix to the Console (the text window at the - * bottom of Processing). - * - * ( end auto-generated ) - * @webref lights_camera:camera - * @see PGraphics#camera(float, float, float, float, float, float, float, float, float) - */ - public void printCamera() { - g.printCamera(); - } - - - /** - * ( begin auto-generated from ortho.xml ) - * - * Sets an orthographic projection and defines a parallel clipping volume. - * All objects with the same dimension appear the same size, regardless of - * whether they are near or far from the camera. The parameters to this - * function specify the clipping volume where left and right are the - * minimum and maximum x values, top and bottom are the minimum and maximum - * y values, and near and far are the minimum and maximum z values. If no - * parameters are given, the default is used: ortho(0, width, 0, height, - * -10, 10). - * - * ( end auto-generated ) - * - * @webref lights_camera:camera - */ - public void ortho() { - g.ortho(); - } - - - /** - * @param left left plane of the clipping volume - * @param right right plane of the clipping volume - * @param bottom bottom plane of the clipping volume - * @param top top plane of the clipping volume - */ - public void ortho(float left, float right, - float bottom, float top) { - g.ortho(left, right, bottom, top); - } - - - /** - * @param near maximum distance from the origin to the viewer - * @param far maximum distance from the origin away from the viewer - */ - public void ortho(float left, float right, - float bottom, float top, - float near, float far) { - g.ortho(left, right, bottom, top, near, far); - } - - - /** - * ( begin auto-generated from perspective.xml ) - * - * Sets a perspective projection applying foreshortening, making distant - * objects appear smaller than closer ones. The parameters define a viewing - * volume with the shape of truncated pyramid. Objects near to the front of - * the volume appear their actual size, while farther objects appear - * smaller. This projection simulates the perspective of the world more - * accurately than orthographic projection. The version of perspective - * without parameters sets the default perspective and the version with - * four parameters allows the programmer to set the area precisely. The - * default values are: perspective(PI/3.0, width/height, cameraZ/10.0, - * cameraZ*10.0) where cameraZ is ((height/2.0) / tan(PI*60.0/360.0)); - * - * ( end auto-generated ) - * - * @webref lights_camera:camera - */ - public void perspective() { - g.perspective(); - } - - - /** - * @param fovy field-of-view angle (in radians) for vertical direction - * @param aspect ratio of width to height - * @param zNear z-position of nearest clipping plane - * @param zFar z-position of farthest clipping plane - */ - public void perspective(float fovy, float aspect, float zNear, float zFar) { - g.perspective(fovy, aspect, zNear, zFar); - } - - - /** - * ( begin auto-generated from frustum.xml ) - * - * Sets a perspective matrix defined through the parameters. Works like - * glFrustum, except it wipes out the current perspective matrix rather - * than muliplying itself with it. - * - * ( end auto-generated ) - * - * @webref lights_camera:camera - * @param left left coordinate of the clipping plane - * @param right right coordinate of the clipping plane - * @param bottom bottom coordinate of the clipping plane - * @param top top coordinate of the clipping plane - * @param near near component of the clipping plane; must be greater than zero - * @param far far component of the clipping plane; must be greater than the near value - * @see PGraphics#camera(float, float, float, float, float, float, float, float, float) - * @see PGraphics#beginCamera() - * @see PGraphics#endCamera() - * @see PGraphics#perspective(float, float, float, float) - */ - public void frustum(float left, float right, - float bottom, float top, - float near, float far) { - g.frustum(left, right, bottom, top, near, far); - } - - - /** - * ( begin auto-generated from printProjection.xml ) - * - * Prints the current projection matrix to the Console (the text window at - * the bottom of Processing). - * - * ( end auto-generated ) - * - * @webref lights_camera:camera - * @see PGraphics#camera(float, float, float, float, float, float, float, float, float) - */ - public void printProjection() { - g.printProjection(); - } - - - /** - * ( begin auto-generated from screenX.xml ) - * - * Takes a three-dimensional X, Y, Z position and returns the X value for - * where it will appear on a (two-dimensional) screen. - * - * ( end auto-generated ) - * - * @webref lights_camera:coordinates - * @param x 3D x-coordinate to be mapped - * @param y 3D y-coordinate to be mapped - * @see PGraphics#screenY(float, float, float) - * @see PGraphics#screenZ(float, float, float) - */ - public float screenX(float x, float y) { - return g.screenX(x, y); - } - - - /** - * ( begin auto-generated from screenY.xml ) - * - * Takes a three-dimensional X, Y, Z position and returns the Y value for - * where it will appear on a (two-dimensional) screen. - * - * ( end auto-generated ) - * - * @webref lights_camera:coordinates - * @param x 3D x-coordinate to be mapped - * @param y 3D y-coordinate to be mapped - * @see PGraphics#screenX(float, float, float) - * @see PGraphics#screenZ(float, float, float) - */ - public float screenY(float x, float y) { - return g.screenY(x, y); - } - - - /** - * @param z 3D z-coordinate to be mapped - */ - public float screenX(float x, float y, float z) { - return g.screenX(x, y, z); - } - - - /** - * @param z 3D z-coordinate to be mapped - */ - public float screenY(float x, float y, float z) { - return g.screenY(x, y, z); - } - - - /** - * ( begin auto-generated from screenZ.xml ) - * - * Takes a three-dimensional X, Y, Z position and returns the Z value for - * where it will appear on a (two-dimensional) screen. - * - * ( end auto-generated ) - * - * @webref lights_camera:coordinates - * @param x 3D x-coordinate to be mapped - * @param y 3D y-coordinate to be mapped - * @param z 3D z-coordinate to be mapped - * @see PGraphics#screenX(float, float, float) - * @see PGraphics#screenY(float, float, float) - */ - public float screenZ(float x, float y, float z) { - return g.screenZ(x, y, z); - } - - - /** - * ( begin auto-generated from modelX.xml ) - * - * Returns the three-dimensional X, Y, Z position in model space. This - * returns the X value for a given coordinate based on the current set of - * transformations (scale, rotate, translate, etc.) The X value can be used - * to place an object in space relative to the location of the original - * point once the transformations are no longer in use. - *

      - * In the example, the modelX(), modelY(), and - * modelZ() functions record the location of a box in space after - * being placed using a series of translate and rotate commands. After - * popMatrix() is called, those transformations no longer apply, but the - * (x, y, z) coordinate returned by the model functions is used to place - * another box in the same location. - * - * ( end auto-generated ) - * - * @webref lights_camera:coordinates - * @param x 3D x-coordinate to be mapped - * @param y 3D y-coordinate to be mapped - * @param z 3D z-coordinate to be mapped - * @see PGraphics#modelY(float, float, float) - * @see PGraphics#modelZ(float, float, float) - */ - public float modelX(float x, float y, float z) { - return g.modelX(x, y, z); - } - - - /** - * ( begin auto-generated from modelY.xml ) - * - * Returns the three-dimensional X, Y, Z position in model space. This - * returns the Y value for a given coordinate based on the current set of - * transformations (scale, rotate, translate, etc.) The Y value can be used - * to place an object in space relative to the location of the original - * point once the transformations are no longer in use.
      - *
      - * In the example, the modelX(), modelY(), and - * modelZ() functions record the location of a box in space after - * being placed using a series of translate and rotate commands. After - * popMatrix() is called, those transformations no longer apply, but the - * (x, y, z) coordinate returned by the model functions is used to place - * another box in the same location. - * - * ( end auto-generated ) - * - * @webref lights_camera:coordinates - * @param x 3D x-coordinate to be mapped - * @param y 3D y-coordinate to be mapped - * @param z 3D z-coordinate to be mapped - * @see PGraphics#modelX(float, float, float) - * @see PGraphics#modelZ(float, float, float) - */ - public float modelY(float x, float y, float z) { - return g.modelY(x, y, z); - } - - - /** - * ( begin auto-generated from modelZ.xml ) - * - * Returns the three-dimensional X, Y, Z position in model space. This - * returns the Z value for a given coordinate based on the current set of - * transformations (scale, rotate, translate, etc.) The Z value can be used - * to place an object in space relative to the location of the original - * point once the transformations are no longer in use.
      - *
      - * In the example, the modelX(), modelY(), and - * modelZ() functions record the location of a box in space after - * being placed using a series of translate and rotate commands. After - * popMatrix() is called, those transformations no longer apply, but the - * (x, y, z) coordinate returned by the model functions is used to place - * another box in the same location. - * - * ( end auto-generated ) - * - * @webref lights_camera:coordinates - * @param x 3D x-coordinate to be mapped - * @param y 3D y-coordinate to be mapped - * @param z 3D z-coordinate to be mapped - * @see PGraphics#modelX(float, float, float) - * @see PGraphics#modelY(float, float, float) - */ - public float modelZ(float x, float y, float z) { - return g.modelZ(x, y, z); - } - - - /** - * ( begin auto-generated from pushStyle.xml ) - * - * The pushStyle() function saves the current style settings and - * popStyle() restores the prior settings. Note that these functions - * are always used together. They allow you to change the style settings - * and later return to what you had. When a new style is started with - * pushStyle(), it builds on the current style information. The - * pushStyle() and popStyle() functions can be embedded to - * provide more control (see the second example above for a demonstration.) - *

      - * The style information controlled by the following functions are included - * in the style: - * fill(), stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), - * imageMode(), rectMode(), ellipseMode(), shapeMode(), colorMode(), - * textAlign(), textFont(), textMode(), textSize(), textLeading(), - * emissive(), specular(), shininess(), ambient() - * - * ( end auto-generated ) - * - * @webref structure - * @see PGraphics#popStyle() - */ - public void pushStyle() { - g.pushStyle(); - } - - - /** - * ( begin auto-generated from popStyle.xml ) - * - * The pushStyle() function saves the current style settings and - * popStyle() restores the prior settings; these functions are - * always used together. They allow you to change the style settings and - * later return to what you had. When a new style is started with - * pushStyle(), it builds on the current style information. The - * pushStyle() and popStyle() functions can be embedded to - * provide more control (see the second example above for a demonstration.) - * - * ( end auto-generated ) - * - * @webref structure - * @see PGraphics#pushStyle() - */ - public void popStyle() { - g.popStyle(); - } - - - public void style(PStyle s) { - g.style(s); - } - - - /** - * ( begin auto-generated from strokeWeight.xml ) - * - * Sets the width of the stroke used for lines, points, and the border - * around shapes. All widths are set in units of pixels. - *

      - * When drawing with P3D, series of connected lines (such as the stroke - * around a polygon, triangle, or ellipse) produce unattractive results - * when a thick stroke weight is set (see - * Issue 123). With P3D, the minimum and maximum values for - * strokeWeight() are controlled by the graphics card and the - * operating system's OpenGL implementation. For instance, the thickness - * may not go higher than 10 pixels. - * - * ( end auto-generated ) - * - * @webref shape:attributes - * @param weight the weight (in pixels) of the stroke - * @see PGraphics#stroke(int, float) - * @see PGraphics#strokeJoin(int) - * @see PGraphics#strokeCap(int) - */ - public void strokeWeight(float weight) { - g.strokeWeight(weight); - } - - - /** - * ( begin auto-generated from strokeJoin.xml ) - * - * Sets the style of the joints which connect line segments. These joints - * are either mitered, beveled, or rounded and specified with the - * corresponding parameters MITER, BEVEL, and ROUND. The default joint is - * MITER. - *

      - * This function is not available with the P3D renderer, (see - * Issue 123). More information about the renderers can be found in the - * size() reference. - * - * ( end auto-generated ) - * - * @webref shape:attributes - * @param join either MITER, BEVEL, ROUND - * @see PGraphics#stroke(int, float) - * @see PGraphics#strokeWeight(float) - * @see PGraphics#strokeCap(int) - */ - public void strokeJoin(int join) { - g.strokeJoin(join); - } - - - /** - * ( begin auto-generated from strokeCap.xml ) - * - * Sets the style for rendering line endings. These ends are either - * squared, extended, or rounded and specified with the corresponding - * parameters SQUARE, PROJECT, and ROUND. The default cap is ROUND. - *

      - * This function is not available with the P3D renderer (see - * Issue 123). More information about the renderers can be found in the - * size() reference. - * - * ( end auto-generated ) - * - * @webref shape:attributes - * @param cap either SQUARE, PROJECT, or ROUND - * @see PGraphics#stroke(int, float) - * @see PGraphics#strokeWeight(float) - * @see PGraphics#strokeJoin(int) - * @see PApplet#size(int, int, String, String) - */ - public void strokeCap(int cap) { - g.strokeCap(cap); - } - - - /** - * ( begin auto-generated from noStroke.xml ) - * - * Disables drawing the stroke (outline). If both noStroke() and - * noFill() are called, nothing will be drawn to the screen. - * - * ( end auto-generated ) - * - * @webref color:setting - * @see PGraphics#stroke(int, float) - * @see PGraphics#fill(float, float, float, float) - * @see PGraphics#noFill() - */ - public void noStroke() { - g.noStroke(); - } - - - /** - * ( begin auto-generated from stroke.xml ) - * - * Sets the color used to draw lines and borders around shapes. This color - * is either specified in terms of the RGB or HSB color depending on the - * current colorMode() (the default color space is RGB, with each - * value in the range from 0 to 255). - *

      - * When using hexadecimal notation to specify a color, use "#" or "0x" - * before the values (e.g. #CCFFAA, 0xFFCCFFAA). The # syntax uses six - * digits to specify a color (the way colors are specified in HTML and - * CSS). When using the hexadecimal notation starting with "0x", the - * hexadecimal value must be specified with eight characters; the first two - * characters define the alpha component and the remainder the red, green, - * and blue components. - *

      - * The value for the parameter "gray" must be less than or equal to the - * current maximum value as specified by colorMode(). The default - * maximum value is 255. - * - * ( end auto-generated ) - * - * @param rgb color value in hexadecimal notation - * @see PGraphics#noStroke() - * @see PGraphics#strokeWeight(float) - * @see PGraphics#strokeJoin(int) - * @see PGraphics#strokeCap(int) - * @see PGraphics#fill(int, float) - * @see PGraphics#noFill() - * @see PGraphics#tint(int, float) - * @see PGraphics#background(float, float, float, float) - * @see PGraphics#colorMode(int, float, float, float, float) - */ - public void stroke(int rgb) { - g.stroke(rgb); - } - - - /** - * @param alpha opacity of the stroke - */ - public void stroke(int rgb, float alpha) { - g.stroke(rgb, alpha); - } - - - /** - * @param gray specifies a value between white and black - */ - public void stroke(float gray) { - g.stroke(gray); - } - - - public void stroke(float gray, float alpha) { - g.stroke(gray, alpha); - } - - - /** - * @param v1 red or hue value (depending on current color mode) - * @param v2 green or saturation value (depending on current color mode) - * @param v3 blue or brightness value (depending on current color mode) - * @webref color:setting - */ - public void stroke(float v1, float v2, float v3) { - g.stroke(v1, v2, v3); - } - - - public void stroke(float v1, float v2, float v3, float alpha) { - g.stroke(v1, v2, v3, alpha); - } - - - /** - * ( begin auto-generated from noTint.xml ) - * - * Removes the current fill value for displaying images and reverts to - * displaying images with their original hues. - * - * ( end auto-generated ) - * - * @webref image:loading_displaying - * @usage web_application - * @see PGraphics#tint(float, float, float, float) - * @see PGraphics#image(PImage, float, float, float, float) - */ - public void noTint() { - g.noTint(); - } - - - /** - * ( begin auto-generated from tint.xml ) - * - * Sets the fill value for displaying images. Images can be tinted to - * specified colors or made transparent by setting the alpha.
      - *
      - * To make an image transparent, but not change it's color, use white as - * the tint color and specify an alpha value. For instance, tint(255, 128) - * will make an image 50% transparent (unless colorMode() has been - * used).
      - *
      - * When using hexadecimal notation to specify a color, use "#" or "0x" - * before the values (e.g. #CCFFAA, 0xFFCCFFAA). The # syntax uses six - * digits to specify a color (the way colors are specified in HTML and - * CSS). When using the hexadecimal notation starting with "0x", the - * hexadecimal value must be specified with eight characters; the first two - * characters define the alpha component and the remainder the red, green, - * and blue components.
      - *
      - * The value for the parameter "gray" must be less than or equal to the - * current maximum value as specified by colorMode(). The default - * maximum value is 255.
      - *
      - * The tint() function is also used to control the coloring of - * textures in 3D. - * - * ( end auto-generated ) - * - * @webref image:loading_displaying - * @usage web_application - * @param rgb color value in hexadecimal notation - * @see PGraphics#noTint() - * @see PGraphics#image(PImage, float, float, float, float) - */ - public void tint(int rgb) { - g.tint(rgb); - } - - - /** - * @param alpha opacity of the image - */ - public void tint(int rgb, float alpha) { - g.tint(rgb, alpha); - } - - - /** - * @param gray specifies a value between white and black - */ - public void tint(float gray) { - g.tint(gray); - } - - - public void tint(float gray, float alpha) { - g.tint(gray, alpha); - } - - - /** - * @param v1 red or hue value (depending on current color mode) - * @param v2 green or saturation value (depending on current color mode) - * @param v3 blue or brightness value (depending on current color mode) - */ - public void tint(float v1, float v2, float v3) { - g.tint(v1, v2, v3); - } - - - public void tint(float v1, float v2, float v3, float alpha) { - g.tint(v1, v2, v3, alpha); - } - - - /** - * ( begin auto-generated from noFill.xml ) - * - * Disables filling geometry. If both noStroke() and noFill() - * are called, nothing will be drawn to the screen. - * - * ( end auto-generated ) - * - * @webref color:setting - * @usage web_application - * @see PGraphics#fill(float, float, float, float) - * @see PGraphics#stroke(int, float) - * @see PGraphics#noStroke() - */ - public void noFill() { - g.noFill(); - } - - - /** - * ( begin auto-generated from fill.xml ) - * - * Sets the color used to fill shapes. For example, if you run fill(204, - * 102, 0), all subsequent shapes will be filled with orange. This - * color is either specified in terms of the RGB or HSB color depending on - * the current colorMode() (the default color space is RGB, with - * each value in the range from 0 to 255). - *

      - * When using hexadecimal notation to specify a color, use "#" or "0x" - * before the values (e.g. #CCFFAA, 0xFFCCFFAA). The # syntax uses six - * digits to specify a color (the way colors are specified in HTML and - * CSS). When using the hexadecimal notation starting with "0x", the - * hexadecimal value must be specified with eight characters; the first two - * characters define the alpha component and the remainder the red, green, - * and blue components. - *

      - * The value for the parameter "gray" must be less than or equal to the - * current maximum value as specified by colorMode(). The default - * maximum value is 255. - *

      - * To change the color of an image (or a texture), use tint(). - * - * ( end auto-generated ) - * - * @webref color:setting - * @usage web_application - * @param rgb color variable or hex value - * @see PGraphics#noFill() - * @see PGraphics#stroke(int, float) - * @see PGraphics#noStroke() - * @see PGraphics#tint(int, float) - * @see PGraphics#background(float, float, float, float) - * @see PGraphics#colorMode(int, float, float, float, float) - */ - public void fill(int rgb) { - g.fill(rgb); - } - - - /** - * @param alpha opacity of the fill - */ - public void fill(int rgb, float alpha) { - g.fill(rgb, alpha); - } - - - /** - * @param gray number specifying value between white and black - */ - public void fill(float gray) { - g.fill(gray); - } - - - public void fill(float gray, float alpha) { - g.fill(gray, alpha); - } - - - /** - * @param v1 red or hue value (depending on current color mode) - * @param v2 green or saturation value (depending on current color mode) - * @param v3 blue or brightness value (depending on current color mode) - */ - public void fill(float v1, float v2, float v3) { - g.fill(v1, v2, v3); - } - - - public void fill(float v1, float v2, float v3, float alpha) { - g.fill(v1, v2, v3, alpha); - } - - - /** - * ( begin auto-generated from ambient.xml ) - * - * Sets the ambient reflectance for shapes drawn to the screen. This is - * combined with the ambient light component of environment. The color - * components set through the parameters define the reflectance. For - * example in the default color mode, setting v1=255, v2=126, v3=0, would - * cause all the red light to reflect and half of the green light to - * reflect. Used in combination with emissive(), specular(), - * and shininess() in setting the material properties of shapes. - * - * ( end auto-generated ) - * - * @webref lights_camera:material_properties - * @usage web_application - * @param rgb any value of the color datatype - * @see PGraphics#emissive(float, float, float) - * @see PGraphics#specular(float, float, float) - * @see PGraphics#shininess(float) - */ - public void ambient(int rgb) { - g.ambient(rgb); - } - - - /** - * @param gray number specifying value between white and black - */ - public void ambient(float gray) { - g.ambient(gray); - } - - - /** - * @param v1 red or hue value (depending on current color mode) - * @param v2 green or saturation value (depending on current color mode) - * @param v3 blue or brightness value (depending on current color mode) - */ - public void ambient(float v1, float v2, float v3) { - g.ambient(v1, v2, v3); - } - - - /** - * ( begin auto-generated from specular.xml ) - * - * Sets the specular color of the materials used for shapes drawn to the - * screen, which sets the color of hightlights. Specular refers to light - * which bounces off a surface in a perferred direction (rather than - * bouncing in all directions like a diffuse light). Used in combination - * with emissive(), ambient(), and shininess() in - * setting the material properties of shapes. - * - * ( end auto-generated ) - * - * @webref lights_camera:material_properties - * @usage web_application - * @param rgb color to set - * @see PGraphics#lightSpecular(float, float, float) - * @see PGraphics#ambient(float, float, float) - * @see PGraphics#emissive(float, float, float) - * @see PGraphics#shininess(float) - */ - public void specular(int rgb) { - g.specular(rgb); - } - - - /** - * gray number specifying value between white and black - * - * @param gray value between black and white, by default 0 to 255 - */ - public void specular(float gray) { - g.specular(gray); - } - - - /** - * @param v1 red or hue value (depending on current color mode) - * @param v2 green or saturation value (depending on current color mode) - * @param v3 blue or brightness value (depending on current color mode) - */ - public void specular(float v1, float v2, float v3) { - g.specular(v1, v2, v3); - } - - - /** - * ( begin auto-generated from shininess.xml ) - * - * Sets the amount of gloss in the surface of shapes. Used in combination - * with ambient(), specular(), and emissive() in - * setting the material properties of shapes. - * - * ( end auto-generated ) - * - * @webref lights_camera:material_properties - * @usage web_application - * @param shine degree of shininess - * @see PGraphics#emissive(float, float, float) - * @see PGraphics#ambient(float, float, float) - * @see PGraphics#specular(float, float, float) - */ - public void shininess(float shine) { - g.shininess(shine); - } - - - /** - * ( begin auto-generated from emissive.xml ) - * - * Sets the emissive color of the material used for drawing shapes drawn to - * the screen. Used in combination with ambient(), - * specular(), and shininess() in setting the material - * properties of shapes. - * - * ( end auto-generated ) - * - * @webref lights_camera:material_properties - * @usage web_application - * @param rgb color to set - * @see PGraphics#ambient(float, float, float) - * @see PGraphics#specular(float, float, float) - * @see PGraphics#shininess(float) - */ - public void emissive(int rgb) { - g.emissive(rgb); - } - - - /** - * gray number specifying value between white and black - * - * @param gray value between black and white, by default 0 to 255 - */ - public void emissive(float gray) { - g.emissive(gray); - } - - - /** - * @param v1 red or hue value (depending on current color mode) - * @param v2 green or saturation value (depending on current color mode) - * @param v3 blue or brightness value (depending on current color mode) - */ - public void emissive(float v1, float v2, float v3) { - g.emissive(v1, v2, v3); - } - - - /** - * ( begin auto-generated from lights.xml ) - * - * Sets the default ambient light, directional light, falloff, and specular - * values. The defaults are ambientLight(128, 128, 128) and - * directionalLight(128, 128, 128, 0, 0, -1), lightFalloff(1, 0, 0), and - * lightSpecular(0, 0, 0). Lights need to be included in the draw() to - * remain persistent in a looping program. Placing them in the setup() of a - * looping program will cause them to only have an effect the first time - * through the loop. - * - * ( end auto-generated ) - * - * @webref lights_camera:lights - * @usage web_application - * @see PGraphics#ambientLight(float, float, float, float, float, float) - * @see PGraphics#directionalLight(float, float, float, float, float, float) - * @see PGraphics#pointLight(float, float, float, float, float, float) - * @see PGraphics#spotLight(float, float, float, float, float, float, float, float, float, float, float) - * @see PGraphics#noLights() - */ - public void lights() { - g.lights(); - } - - - /** - * ( begin auto-generated from noLights.xml ) - * - * Disable all lighting. Lighting is turned off by default and enabled with - * the lights() function. This function can be used to disable - * lighting so that 2D geometry (which does not require lighting) can be - * drawn after a set of lighted 3D geometry. - * - * ( end auto-generated ) - * - * @webref lights_camera:lights - * @usage web_application - * @see PGraphics#lights() - */ - public void noLights() { - g.noLights(); - } - - - /** - * ( begin auto-generated from ambientLight.xml ) - * - * Adds an ambient light. Ambient light doesn't come from a specific - * direction, the rays have light have bounced around so much that objects - * are evenly lit from all sides. Ambient lights are almost always used in - * combination with other types of lights. Lights need to be included in - * the draw() to remain persistent in a looping program. Placing - * them in the setup() of a looping program will cause them to only - * have an effect the first time through the loop. The effect of the - * parameters is determined by the current color mode. - * - * ( end auto-generated ) - * - * @webref lights_camera:lights - * @usage web_application - * @param v1 red or hue value (depending on current color mode) - * @param v2 green or saturation value (depending on current color mode) - * @param v3 blue or brightness value (depending on current color mode) - * @see PGraphics#lights() - * @see PGraphics#directionalLight(float, float, float, float, float, float) - * @see PGraphics#pointLight(float, float, float, float, float, float) - * @see PGraphics#spotLight(float, float, float, float, float, float, float, float, float, float, float) - */ - public void ambientLight(float v1, float v2, float v3) { - g.ambientLight(v1, v2, v3); - } - - - /** - * @param x x-coordinate of the light - * @param y y-coordinate of the light - * @param z z-coordinate of the light - */ - public void ambientLight(float v1, float v2, float v3, - float x, float y, float z) { - g.ambientLight(v1, v2, v3, x, y, z); - } - - - /** - * ( begin auto-generated from directionalLight.xml ) - * - * Adds a directional light. Directional light comes from one direction and - * is stronger when hitting a surface squarely and weaker if it hits at a a - * gentle angle. After hitting a surface, a directional lights scatters in - * all directions. Lights need to be included in the draw() to - * remain persistent in a looping program. Placing them in the - * setup() of a looping program will cause them to only have an - * effect the first time through the loop. The affect of the v1, - * v2, and v3 parameters is determined by the current color - * mode. The nx, ny, and nz parameters specify the - * direction the light is facing. For example, setting ny to -1 will - * cause the geometry to be lit from below (the light is facing directly upward). - * - * ( end auto-generated ) - * - * @webref lights_camera:lights - * @usage web_application - * @param v1 red or hue value (depending on current color mode) - * @param v2 green or saturation value (depending on current color mode) - * @param v3 blue or brightness value (depending on current color mode) - * @param nx direction along the x-axis - * @param ny direction along the y-axis - * @param nz direction along the z-axis - * @see PGraphics#lights() - * @see PGraphics#ambientLight(float, float, float, float, float, float) - * @see PGraphics#pointLight(float, float, float, float, float, float) - * @see PGraphics#spotLight(float, float, float, float, float, float, float, float, float, float, float) - */ - public void directionalLight(float v1, float v2, float v3, - float nx, float ny, float nz) { - g.directionalLight(v1, v2, v3, nx, ny, nz); - } - - - /** - * ( begin auto-generated from pointLight.xml ) - * - * Adds a point light. Lights need to be included in the draw() to - * remain persistent in a looping program. Placing them in the - * setup() of a looping program will cause them to only have an - * effect the first time through the loop. The affect of the v1, - * v2, and v3 parameters is determined by the current color - * mode. The x, y, and z parameters set the position - * of the light. - * - * ( end auto-generated ) - * - * @webref lights_camera:lights - * @usage web_application - * @param v1 red or hue value (depending on current color mode) - * @param v2 green or saturation value (depending on current color mode) - * @param v3 blue or brightness value (depending on current color mode) - * @param x x-coordinate of the light - * @param y y-coordinate of the light - * @param z z-coordinate of the light - * @see PGraphics#lights() - * @see PGraphics#directionalLight(float, float, float, float, float, float) - * @see PGraphics#ambientLight(float, float, float, float, float, float) - * @see PGraphics#spotLight(float, float, float, float, float, float, float, float, float, float, float) - */ - public void pointLight(float v1, float v2, float v3, - float x, float y, float z) { - g.pointLight(v1, v2, v3, x, y, z); - } - - - /** - * ( begin auto-generated from spotLight.xml ) - * - * Adds a spot light. Lights need to be included in the draw() to - * remain persistent in a looping program. Placing them in the - * setup() of a looping program will cause them to only have an - * effect the first time through the loop. The affect of the v1, - * v2, and v3 parameters is determined by the current color - * mode. The x, y, and z parameters specify the - * position of the light and nx, ny, nz specify the - * direction or light. The angle parameter affects angle of the - * spotlight cone. - * - * ( end auto-generated ) - * - * @webref lights_camera:lights - * @usage web_application - * @param v1 red or hue value (depending on current color mode) - * @param v2 green or saturation value (depending on current color mode) - * @param v3 blue or brightness value (depending on current color mode) - * @param x x-coordinate of the light - * @param y y-coordinate of the light - * @param z z-coordinate of the light - * @param nx direction along the x axis - * @param ny direction along the y axis - * @param nz direction along the z axis - * @param angle angle of the spotlight cone - * @param concentration exponent determining the center bias of the cone - * @see PGraphics#lights() - * @see PGraphics#directionalLight(float, float, float, float, float, float) - * @see PGraphics#pointLight(float, float, float, float, float, float) - * @see PGraphics#ambientLight(float, float, float, float, float, float) - */ - public void spotLight(float v1, float v2, float v3, - float x, float y, float z, - float nx, float ny, float nz, - float angle, float concentration) { - g.spotLight(v1, v2, v3, x, y, z, nx, ny, nz, angle, concentration); - } - - - /** - * ( begin auto-generated from lightFalloff.xml ) - * - * Sets the falloff rates for point lights, spot lights, and ambient - * lights. The parameters are used to determine the falloff with the - * following equation:

      d = distance from light position to - * vertex position
      falloff = 1 / (CONSTANT + d * LINEAR + (d*d) * - * QUADRATIC)

      Like fill(), it affects only the elements - * which are created after it in the code. The default value if - * LightFalloff(1.0, 0.0, 0.0). Thinking about an ambient light with - * a falloff can be tricky. It is used, for example, if you wanted a region - * of your scene to be lit ambiently one color and another region to be lit - * ambiently by another color, you would use an ambient light with location - * and falloff. You can think of it as a point light that doesn't care - * which direction a surface is facing. - * - * ( end auto-generated ) - * - * @webref lights_camera:lights - * @usage web_application - * @param constant constant value or determining falloff - * @param linear linear value for determining falloff - * @param quadratic quadratic value for determining falloff - * @see PGraphics#lights() - * @see PGraphics#ambientLight(float, float, float, float, float, float) - * @see PGraphics#pointLight(float, float, float, float, float, float) - * @see PGraphics#spotLight(float, float, float, float, float, float, float, float, float, float, float) - * @see PGraphics#lightSpecular(float, float, float) - */ - public void lightFalloff(float constant, float linear, float quadratic) { - g.lightFalloff(constant, linear, quadratic); - } - - - /** - * ( begin auto-generated from lightSpecular.xml ) - * - * Sets the specular color for lights. Like fill(), it affects only - * the elements which are created after it in the code. Specular refers to - * light which bounces off a surface in a perferred direction (rather than - * bouncing in all directions like a diffuse light) and is used for - * creating highlights. The specular quality of a light interacts with the - * specular material qualities set through the specular() and - * shininess() functions. - * - * ( end auto-generated ) - * - * @webref lights_camera:lights - * @usage web_application - * @param v1 red or hue value (depending on current color mode) - * @param v2 green or saturation value (depending on current color mode) - * @param v3 blue or brightness value (depending on current color mode) - * @see PGraphics#specular(float, float, float) - * @see PGraphics#lights() - * @see PGraphics#ambientLight(float, float, float, float, float, float) - * @see PGraphics#pointLight(float, float, float, float, float, float) - * @see PGraphics#spotLight(float, float, float, float, float, float, float, float, float, float, float) - */ - public void lightSpecular(float v1, float v2, float v3) { - g.lightSpecular(v1, v2, v3); - } - - - /** - * ( begin auto-generated from background.xml ) - * - * The background() function sets the color used for the background - * of the Processing window. The default background is light gray. In the - * draw() function, the background color is used to clear the - * display window at the beginning of each frame. - *

      - * An image can also be used as the background for a sketch, however its - * width and height must be the same size as the sketch window. To resize - * an image 'b' to the size of the sketch window, use b.resize(width, height). - *

      - * Images used as background will ignore the current tint() setting. - *

      - * It is not possible to use transparency (alpha) in background colors with - * the main drawing surface, however they will work properly with createGraphics(). - * - * ( end auto-generated ) - * - *

      Advanced

      - *

      Clear the background with a color that includes an alpha value. This can - * only be used with objects created by createGraphics(), because the main - * drawing surface cannot be set transparent.

      - *

      It might be tempting to use this function to partially clear the screen - * on each frame, however that's not how this function works. When calling - * background(), the pixels will be replaced with pixels that have that level - * of transparency. To do a semi-transparent overlay, use fill() with alpha - * and draw a rectangle.

      - * - * @webref color:setting - * @usage web_application - * @param rgb any value of the color datatype - * @see PGraphics#stroke(float) - * @see PGraphics#fill(float) - * @see PGraphics#tint(float) - * @see PGraphics#colorMode(int) - */ - public void background(int rgb) { - g.background(rgb); - } - - - /** - * @param alpha opacity of the background - */ - public void background(int rgb, float alpha) { - g.background(rgb, alpha); - } - - - /** - * @param gray specifies a value between white and black - */ - public void background(float gray) { - g.background(gray); - } - - - public void background(float gray, float alpha) { - g.background(gray, alpha); - } - - - /** - * @param v1 red or hue value (depending on the current color mode) - * @param v2 green or saturation value (depending on the current color mode) - * @param v3 blue or brightness value (depending on the current color mode) - */ - public void background(float v1, float v2, float v3) { - g.background(v1, v2, v3); - } - - - public void background(float v1, float v2, float v3, float alpha) { - g.background(v1, v2, v3, alpha); - } - - - /** - * @webref color:setting - */ - public void clear() { - g.clear(); - } - - - /** - * Takes an RGB or ARGB image and sets it as the background. - * The width and height of the image must be the same size as the sketch. - * Use image.resize(width, height) to make short work of such a task.
      - *
      - * Note that even if the image is set as RGB, the high 8 bits of each pixel - * should be set opaque (0xFF000000) because the image data will be copied - * directly to the screen, and non-opaque background images may have strange - * behavior. Use image.filter(OPAQUE) to handle this easily.
      - *
      - * When using 3D, this will also clear the zbuffer (if it exists). - * - * @param image PImage to set as background (must be same size as the sketch window) - */ - public void background(PImage image) { - g.background(image); - } - - - /** - * ( begin auto-generated from colorMode.xml ) - * - * Changes the way Processing interprets color data. By default, the - * parameters for fill(), stroke(), background(), and - * color() are defined by values between 0 and 255 using the RGB - * color model. The colorMode() function is used to change the - * numerical range used for specifying colors and to switch color systems. - * For example, calling colorMode(RGB, 1.0) will specify that values - * are specified between 0 and 1. The limits for defining colors are - * altered by setting the parameters range1, range2, range3, and range 4. - * - * ( end auto-generated ) - * - * @webref color:setting - * @usage web_application - * @param mode Either RGB or HSB, corresponding to Red/Green/Blue and Hue/Saturation/Brightness - * @see PGraphics#background(float) - * @see PGraphics#fill(float) - * @see PGraphics#stroke(float) - */ - public void colorMode(int mode) { - g.colorMode(mode); - } - - - /** - * @param max range for all color elements - */ - public void colorMode(int mode, float max) { - g.colorMode(mode, max); - } - - - /** - * @param max1 range for the red or hue depending on the current color mode - * @param max2 range for the green or saturation depending on the current color mode - * @param max3 range for the blue or brightness depending on the current color mode - */ - public void colorMode(int mode, float max1, float max2, float max3) { - g.colorMode(mode, max1, max2, max3); - } - - - /** - * @param maxA range for the alpha - */ - public void colorMode(int mode, - float max1, float max2, float max3, float maxA) { - g.colorMode(mode, max1, max2, max3, maxA); - } - - - /** - * ( begin auto-generated from alpha.xml ) - * - * Extracts the alpha value from a color. - * - * ( end auto-generated ) - * @webref color:creating_reading - * @usage web_application - * @param rgb any value of the color datatype - * @see PGraphics#red(int) - * @see PGraphics#green(int) - * @see PGraphics#blue(int) - * @see PGraphics#hue(int) - * @see PGraphics#saturation(int) - * @see PGraphics#brightness(int) - */ - public final float alpha(int rgb) { - return g.alpha(rgb); - } - - - /** - * ( begin auto-generated from red.xml ) - * - * Extracts the red value from a color, scaled to match current - * colorMode(). This value is always returned as a float so be - * careful not to assign it to an int value.

      The red() function - * is easy to use and undestand, but is slower than another technique. To - * achieve the same results when working in colorMode(RGB, 255), but - * with greater speed, use the >> (right shift) operator with a bit - * mask. For example, the following two lines of code are equivalent:
      float r1 = red(myColor);
      float r2 = myColor >> 16 - * & 0xFF;
      - * - * ( end auto-generated ) - * - * @webref color:creating_reading - * @usage web_application - * @param rgb any value of the color datatype - * @see PGraphics#green(int) - * @see PGraphics#blue(int) - * @see PGraphics#alpha(int) - * @see PGraphics#hue(int) - * @see PGraphics#saturation(int) - * @see PGraphics#brightness(int) - * @see_external rightshift - */ - public final float red(int rgb) { - return g.red(rgb); - } - - - /** - * ( begin auto-generated from green.xml ) - * - * Extracts the green value from a color, scaled to match current - * colorMode(). This value is always returned as a float so be - * careful not to assign it to an int value.

      The green() - * function is easy to use and undestand, but is slower than another - * technique. To achieve the same results when working in colorMode(RGB, - * 255), but with greater speed, use the >> (right shift) - * operator with a bit mask. For example, the following two lines of code - * are equivalent:
      float r1 = green(myColor);
      float r2 = - * myColor >> 8 & 0xFF;
      - * - * ( end auto-generated ) - * - * @webref color:creating_reading - * @usage web_application - * @param rgb any value of the color datatype - * @see PGraphics#red(int) - * @see PGraphics#blue(int) - * @see PGraphics#alpha(int) - * @see PGraphics#hue(int) - * @see PGraphics#saturation(int) - * @see PGraphics#brightness(int) - * @see_external rightshift - */ - public final float green(int rgb) { - return g.green(rgb); - } - - - /** - * ( begin auto-generated from blue.xml ) - * - * Extracts the blue value from a color, scaled to match current - * colorMode(). This value is always returned as a float so be - * careful not to assign it to an int value.

      The blue() - * function is easy to use and undestand, but is slower than another - * technique. To achieve the same results when working in colorMode(RGB, - * 255), but with greater speed, use a bit mask to remove the other - * color components. For example, the following two lines of code are - * equivalent:
      float r1 = blue(myColor);
      float r2 = myColor - * & 0xFF;
      - * - * ( end auto-generated ) - * - * @webref color:creating_reading - * @usage web_application - * @param rgb any value of the color datatype - * @see PGraphics#red(int) - * @see PGraphics#green(int) - * @see PGraphics#alpha(int) - * @see PGraphics#hue(int) - * @see PGraphics#saturation(int) - * @see PGraphics#brightness(int) - * @see_external rightshift - */ - public final float blue(int rgb) { - return g.blue(rgb); - } - - - /** - * ( begin auto-generated from hue.xml ) - * - * Extracts the hue value from a color. - * - * ( end auto-generated ) - * @webref color:creating_reading - * @usage web_application - * @param rgb any value of the color datatype - * @see PGraphics#red(int) - * @see PGraphics#green(int) - * @see PGraphics#blue(int) - * @see PGraphics#alpha(int) - * @see PGraphics#saturation(int) - * @see PGraphics#brightness(int) - */ - public final float hue(int rgb) { - return g.hue(rgb); - } - - - /** - * ( begin auto-generated from saturation.xml ) - * - * Extracts the saturation value from a color. - * - * ( end auto-generated ) - * @webref color:creating_reading - * @usage web_application - * @param rgb any value of the color datatype - * @see PGraphics#red(int) - * @see PGraphics#green(int) - * @see PGraphics#blue(int) - * @see PGraphics#alpha(int) - * @see PGraphics#hue(int) - * @see PGraphics#brightness(int) - */ - public final float saturation(int rgb) { - return g.saturation(rgb); - } - - - /** - * ( begin auto-generated from brightness.xml ) - * - * Extracts the brightness value from a color. - * - * ( end auto-generated ) - * - * @webref color:creating_reading - * @usage web_application - * @param rgb any value of the color datatype - * @see PGraphics#red(int) - * @see PGraphics#green(int) - * @see PGraphics#blue(int) - * @see PGraphics#alpha(int) - * @see PGraphics#hue(int) - * @see PGraphics#saturation(int) - */ - public final float brightness(int rgb) { - return g.brightness(rgb); - } - - - /** - * @nowebref - * Interpolate between two colors. Like lerp(), but for the - * individual color components of a color supplied as an int value. - */ - static public int lerpColor(int c1, int c2, float amt, int mode) { - return PGraphics.lerpColor(c1, c2, amt, mode); - } - - - /** - * Display a warning that the specified method is only available with 3D. - * @param method The method name (no parentheses) - */ - static public void showDepthWarning(String method) { - PGraphics.showDepthWarning(method); - } - - - /** - * Display a warning that the specified method that takes x, y, z parameters - * can only be used with x and y parameters in this renderer. - * @param method The method name (no parentheses) - */ - static public void showDepthWarningXYZ(String method) { - PGraphics.showDepthWarningXYZ(method); - } - - - /** - * Display a warning that the specified method is simply unavailable. - */ - static public void showMethodWarning(String method) { - PGraphics.showMethodWarning(method); - } - - - /** - * Error that a particular variation of a method is unavailable (even though - * other variations are). For instance, if vertex(x, y, u, v) is not - * available, but vertex(x, y) is just fine. - */ - static public void showVariationWarning(String str) { - PGraphics.showVariationWarning(str); - } - - - /** - * Display a warning that the specified method is not implemented, meaning - * that it could be either a completely missing function, although other - * variations of it may still work properly. - */ - static public void showMissingWarning(String method) { - PGraphics.showMissingWarning(method); - } - - - /** - * ( begin auto-generated from PImage_get.xml ) - * - * Reads the color of any pixel or grabs a section of an image. If no - * parameters are specified, the entire image is returned. Use the x - * and y parameters to get the value of one pixel. Get a section of - * the display window by specifying an additional width and - * height parameter. When getting an image, the x and - * y parameters define the coordinates for the upper-left corner of - * the image, regardless of the current imageMode().
      - *
      - * If the pixel requested is outside of the image window, black is - * returned. The numbers returned are scaled according to the current color - * ranges, but only RGB values are returned by this function. For example, - * even though you may have drawn a shape with colorMode(HSB), the - * numbers returned will be in RGB format.
      - *
      - * Getting the color of a single pixel with get(x, y) is easy, but - * not as fast as grabbing the data directly from pixels[]. The - * equivalent statement to get(x, y) using pixels[] is - * pixels[y*width+x]. See the reference for pixels[] for more information. - * - * ( end auto-generated ) - * - *

      Advanced

      - * Returns an ARGB "color" type (a packed 32 bit int with the color. - * If the coordinate is outside the image, zero is returned - * (black, but completely transparent). - *

      - * If the image is in RGB format (i.e. on a PVideo object), - * the value will get its high bits set, just to avoid cases where - * they haven't been set already. - *

      - * If the image is in ALPHA format, this returns a white with its - * alpha value set. - *

      - * This function is included primarily for beginners. It is quite - * slow because it has to check to see if the x, y that was provided - * is inside the bounds, and then has to check to see what image - * type it is. If you want things to be more efficient, access the - * pixels[] array directly. - * - * @webref image:pixels - * @brief Reads the color of any pixel or grabs a rectangle of pixels - * @usage web_application - * @param x x-coordinate of the pixel - * @param y y-coordinate of the pixel - * @see PApplet#set(int, int, int) - * @see PApplet#pixels - * @see PApplet#copy(PImage, int, int, int, int, int, int, int, int) - */ - public int get(int x, int y) { - return g.get(x, y); - } - - - /** - * @param w width of pixel rectangle to get - * @param h height of pixel rectangle to get - */ - public PImage get(int x, int y, int w, int h) { - return g.get(x, y, w, h); - } - - - /** - * Returns a copy of this PImage. Equivalent to get(0, 0, width, height). - * Deprecated, just use copy() instead. - */ - public PImage get() { - return g.get(); - } - - - public PImage copy() { - return g.copy(); - } - - - /** - * ( begin auto-generated from PImage_set.xml ) - * - * Changes the color of any pixel or writes an image directly into the - * display window.
      - *
      - * The x and y parameters specify the pixel to change and the - * color parameter specifies the color value. The color parameter is - * affected by the current color mode (the default is RGB values from 0 to - * 255). When setting an image, the x and y parameters define - * the coordinates for the upper-left corner of the image, regardless of - * the current imageMode(). - *

      - * Setting the color of a single pixel with set(x, y) is easy, but - * not as fast as putting the data directly into pixels[]. The - * equivalent statement to set(x, y, #000000) using pixels[] - * is pixels[y*width+x] = #000000. See the reference for - * pixels[] for more information. - * - * ( end auto-generated ) - * - * @webref image:pixels - * @brief writes a color to any pixel or writes an image into another - * @usage web_application - * @param x x-coordinate of the pixel - * @param y y-coordinate of the pixel - * @param c any value of the color datatype - * @see PImage#get(int, int, int, int) - * @see PImage#pixels - * @see PImage#copy(PImage, int, int, int, int, int, int, int, int) - */ - public void set(int x, int y, int c) { - g.set(x, y, c); - } - - - /** - *

      Advanced

      - * Efficient method of drawing an image's pixels directly to this surface. - * No variations are employed, meaning that any scale, tint, or imageMode - * settings will be ignored. - * - * @param img image to copy into the original image - */ - public void set(int x, int y, PImage img) { - g.set(x, y, img); - } - - - /** - * ( begin auto-generated from PImage_mask.xml ) - * - * Masks part of an image from displaying by loading another image and - * using it as an alpha channel. This mask image should only contain - * grayscale data, but only the blue color channel is used. The mask image - * needs to be the same size as the image to which it is applied.
      - *
      - * In addition to using a mask image, an integer array containing the alpha - * channel data can be specified directly. This method is useful for - * creating dynamically generated alpha masks. This array must be of the - * same length as the target image's pixels array and should contain only - * grayscale data of values between 0-255. - * - * ( end auto-generated ) - * - *

      Advanced

      - * - * Set alpha channel for an image. Black colors in the source - * image will make the destination image completely transparent, - * and white will make things fully opaque. Gray values will - * be in-between steps. - *

      - * Strictly speaking the "blue" value from the source image is - * used as the alpha color. For a fully grayscale image, this - * is correct, but for a color image it's not 100% accurate. - * For a more accurate conversion, first use filter(GRAY) - * which will make the image into a "correct" grayscale by - * performing a proper luminance-based conversion. - * - * @webref pimage:method - * @usage web_application - * @param img image to use as the mask - * @brief Masks part of an image with another image as an alpha channel - */ - public void mask(PImage img) { - g.mask(img); - } - - - public void filter(int kind) { - g.filter(kind); - } - - - /** - * ( begin auto-generated from PImage_filter.xml ) - * - * Filters an image as defined by one of the following modes:

      THRESHOLD - converts the image to black and white pixels depending if - * they are above or below the threshold defined by the level parameter. - * The level must be between 0.0 (black) and 1.0(white). If no level is - * specified, 0.5 is used.
      - *
      - * GRAY - converts any colors in the image to grayscale equivalents
      - *
      - * INVERT - sets each pixel to its inverse value
      - *
      - * POSTERIZE - limits each channel of the image to the number of colors - * specified as the level parameter
      - *
      - * BLUR - executes a Guassian blur with the level parameter specifying the - * extent of the blurring. If no level parameter is used, the blur is - * equivalent to Guassian blur of radius 1
      - *
      - * OPAQUE - sets the alpha channel to entirely opaque
      - *
      - * ERODE - reduces the light areas with the amount defined by the level - * parameter
      - *
      - * DILATE - increases the light areas with the amount defined by the level parameter - * - * ( end auto-generated ) - * - *

      Advanced

      - * Method to apply a variety of basic filters to this image. - *

      - *

        - *
      • filter(BLUR) provides a basic blur. - *
      • filter(GRAY) converts the image to grayscale based on luminance. - *
      • filter(INVERT) will invert the color components in the image. - *
      • filter(OPAQUE) set all the high bits in the image to opaque - *
      • filter(THRESHOLD) converts the image to black and white. - *
      • filter(DILATE) grow white/light areas - *
      • filter(ERODE) shrink white/light areas - *
      - * Luminance conversion code contributed by - * toxi - *

      - * Gaussian blur code contributed by - * Mario Klingemann - * - * @webref image:pixels - * @brief Converts the image to grayscale or black and white - * @usage web_application - * @param kind Either THRESHOLD, GRAY, OPAQUE, INVERT, POSTERIZE, BLUR, ERODE, or DILATE - * @param param unique for each, see above - */ - public void filter(int kind, float param) { - g.filter(kind, param); - } - - - /** - * ( begin auto-generated from PImage_copy.xml ) - * - * Copies a region of pixels from one image into another. If the source and - * destination regions aren't the same size, it will automatically resize - * source pixels to fit the specified target region. No alpha information - * is used in the process, however if the source image has an alpha channel - * set, it will be copied as well. - *

      - * As of release 0149, this function ignores imageMode(). - * - * ( end auto-generated ) - * - * @webref image:pixels - * @brief Copies the entire image - * @usage web_application - * @param sx X coordinate of the source's upper left corner - * @param sy Y coordinate of the source's upper left corner - * @param sw source image width - * @param sh source image height - * @param dx X coordinate of the destination's upper left corner - * @param dy Y coordinate of the destination's upper left corner - * @param dw destination image width - * @param dh destination image height - * @see PGraphics#alpha(int) - * @see PImage#blend(PImage, int, int, int, int, int, int, int, int, int) - */ - public void copy(int sx, int sy, int sw, int sh, - int dx, int dy, int dw, int dh) { - g.copy(sx, sy, sw, sh, dx, dy, dw, dh); - } - - - /** - * @param src an image variable referring to the source image. - */ - public void copy(PImage src, - int sx, int sy, int sw, int sh, - int dx, int dy, int dw, int dh) { - g.copy(src, sx, sy, sw, sh, dx, dy, dw, dh); - } - - - public void blend(int sx, int sy, int sw, int sh, - int dx, int dy, int dw, int dh, int mode) { - g.blend(sx, sy, sw, sh, dx, dy, dw, dh, mode); - } - - - /** - * ( begin auto-generated from PImage_blend.xml ) - * - * Blends a region of pixels into the image specified by the img - * parameter. These copies utilize full alpha channel support and a choice - * of the following modes to blend the colors of source pixels (A) with the - * ones of pixels in the destination image (B):
      - *
      - * BLEND - linear interpolation of colours: C = A*factor + B
      - *
      - * ADD - additive blending with white clip: C = min(A*factor + B, 255)
      - *
      - * SUBTRACT - subtractive blending with black clip: C = max(B - A*factor, - * 0)
      - *
      - * DARKEST - only the darkest colour succeeds: C = min(A*factor, B)
      - *
      - * LIGHTEST - only the lightest colour succeeds: C = max(A*factor, B)
      - *
      - * DIFFERENCE - subtract colors from underlying image.
      - *
      - * EXCLUSION - similar to DIFFERENCE, but less extreme.
      - *
      - * MULTIPLY - Multiply the colors, result will always be darker.
      - *
      - * SCREEN - Opposite multiply, uses inverse values of the colors.
      - *
      - * OVERLAY - A mix of MULTIPLY and SCREEN. Multiplies dark values, - * and screens light values.
      - *
      - * HARD_LIGHT - SCREEN when greater than 50% gray, MULTIPLY when lower.
      - *
      - * SOFT_LIGHT - Mix of DARKEST and LIGHTEST. - * Works like OVERLAY, but not as harsh.
      - *
      - * DODGE - Lightens light tones and increases contrast, ignores darks. - * Called "Color Dodge" in Illustrator and Photoshop.
      - *
      - * BURN - Darker areas are applied, increasing contrast, ignores lights. - * Called "Color Burn" in Illustrator and Photoshop.
      - *
      - * All modes use the alpha information (highest byte) of source image - * pixels as the blending factor. If the source and destination regions are - * different sizes, the image will be automatically resized to match the - * destination size. If the srcImg parameter is not used, the - * display window is used as the source image.
      - *
      - * As of release 0149, this function ignores imageMode(). - * - * ( end auto-generated ) - * - * @webref image:pixels - * @brief Copies a pixel or rectangle of pixels using different blending modes - * @param src an image variable referring to the source image - * @param sx X coordinate of the source's upper left corner - * @param sy Y coordinate of the source's upper left corner - * @param sw source image width - * @param sh source image height - * @param dx X coordinate of the destinations's upper left corner - * @param dy Y coordinate of the destinations's upper left corner - * @param dw destination image width - * @param dh destination image height - * @param mode Either BLEND, ADD, SUBTRACT, LIGHTEST, DARKEST, DIFFERENCE, EXCLUSION, MULTIPLY, SCREEN, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN - * - * @see PApplet#alpha(int) - * @see PImage#copy(PImage, int, int, int, int, int, int, int, int) - * @see PImage#blendColor(int,int,int) - */ - public void blend(PImage src, - int sx, int sy, int sw, int sh, - int dx, int dy, int dw, int dh, int mode) { - g.blend(src, sx, sy, sw, sh, dx, dy, dw, dh, mode); - } -} diff --git a/core/src/processing/core/PConstants.java b/core/src/processing/core/PConstants.java deleted file mode 100644 index 14753a133..000000000 --- a/core/src/processing/core/PConstants.java +++ /dev/null @@ -1,465 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - -import android.view.KeyEvent; -//import java.awt.Cursor; -//import java.awt.event.KeyEvent; - - -/** - * Numbers shared throughout processing.core. - *

      - * An attempt is made to keep the constants as short/non-verbose - * as possible. For instance, the constant is TIFF instead of - * FILE_TYPE_TIFF. We'll do this as long as we can get away with it. - */ -public interface PConstants { - - // vertex fields - static public final int X = 0; // model coords xyz (formerly MX/MY/MZ) - static public final int Y = 1; - static public final int Z = 2; - - // built-in rendering options - static final String JAVA2D = "processing.core.PGraphicsAndroid2D"; - static final String P2D = "processing.opengl.PGraphics2D"; - static final String P2DX = "processing.opengl.PGraphics2DX"; - static final String P3D = "processing.opengl.PGraphics3D"; - static final String OPENGL = P3D; - static final String STEREO = "processing.vr.VRGraphicsStereo"; - static final String MONO = "processing.vr.VRGraphicsMono"; - static final String VR = STEREO; - static final String AR = "processing.ar.ARGraphics"; - static final String ARCORE = AR; - - // The PDF and DXF renderers are not available for Android. - - - // platform IDs for PApplet.platform - - static final int OTHER = 0; - static final int WINDOWS = 1; - static final int MACOSX = 2; - static final int LINUX = 3; - - static final String[] platformNames = { - "other", "windows", "macosx", "linux" - }; - - - static final float EPSILON = 0.0001f; - - - // max/min values for numbers - - /** - * Same as Float.MAX_VALUE, but included for parity with MIN_VALUE, - * and to avoid teaching static methods on the first day. - */ - static final float MAX_FLOAT = Float.MAX_VALUE; - /** - * Note that Float.MIN_VALUE is the smallest positive value - * for a floating point number, not actually the minimum (negative) value - * for a float. This constant equals 0xFF7FFFFF, the smallest (farthest - * negative) value a float can have before it hits NaN. - */ - static final float MIN_FLOAT = -Float.MAX_VALUE; - /** Largest possible (positive) integer value */ - static final int MAX_INT = Integer.MAX_VALUE; - /** Smallest possible (negative) integer value */ - static final int MIN_INT = Integer.MIN_VALUE; - - - // shapes - - static public final int VERTEX = 0; - static public final int BEZIER_VERTEX = 1; - static public final int QUADRATIC_VERTEX = 2; - static public final int CURVE_VERTEX = 3; - static public final int BREAK = 4; - - @Deprecated - static public final int QUAD_BEZIER_VERTEX = 2; // should not have been exposed - - // useful goodness - - static final float PI = (float) Math.PI; - static final float HALF_PI = PI / 2.0f; - static final float THIRD_PI = PI / 3.0f; - static final float QUARTER_PI = PI / 4.0f; - static final float TWO_PI = PI * 2.0f; - static final float TAU = PI * 2.0f; - - static final float DEG_TO_RAD = PI/180.0f; - static final float RAD_TO_DEG = 180.0f/PI; - - - // angle modes - - //static final int RADIANS = 0; - //static final int DEGREES = 1; - - - // used by split, all the standard whitespace chars - // (also includes unicode nbsp, that little bostage) - - static final String WHITESPACE = " \t\n\r\f\u00A0"; - - - // for colors and/or images - - static final int RGB = 1; // image & color - static final int ARGB = 2; // image - static final int HSB = 3; // color - static final int ALPHA = 4; // image - static final int CMYK = 5; // image & color (someday) - static final int YUV420 = 6; // Android video preview. - - - // image file types - - static final int TIFF = 0; - static final int TARGA = 1; - static final int JPEG = 2; - static final int GIF = 3; - - - // filter/convert types - - static final int BLUR = 11; - static final int GRAY = 12; - static final int INVERT = 13; - static final int OPAQUE = 14; - static final int POSTERIZE = 15; - static final int THRESHOLD = 16; - static final int ERODE = 17; - static final int DILATE = 18; - - - // blend mode keyword definitions - // @see processing.core.PImage#blendColor(int,int,int) - - public final static int REPLACE = 0; - public final static int BLEND = 1 << 0; - public final static int ADD = 1 << 1; - public final static int SUBTRACT = 1 << 2; - public final static int LIGHTEST = 1 << 3; - public final static int DARKEST = 1 << 4; - public final static int DIFFERENCE = 1 << 5; - public final static int EXCLUSION = 1 << 6; - public final static int MULTIPLY = 1 << 7; - public final static int SCREEN = 1 << 8; - public final static int OVERLAY = 1 << 9; - public final static int HARD_LIGHT = 1 << 10; - public final static int SOFT_LIGHT = 1 << 11; - public final static int DODGE = 1 << 12; - public final static int BURN = 1 << 13; - - - // for messages - - static final int CHATTER = 0; - static final int COMPLAINT = 1; - static final int PROBLEM = 2; - - // types of transformation matrices - - static final int PROJECTION = 0; - static final int MODELVIEW = 1; - - // types of projection matrices - - static final int CUSTOM = 0; // user-specified fanciness - static final int ORTHOGRAPHIC = 2; // 2D isometric projection - static final int PERSPECTIVE = 3; // perspective matrix - - - // shapes - - // the low four bits set the variety, - // higher bits set the specific shape type - - static final int GROUP = 0; // createShape() - - static final int POINT = 2; // primitive - static final int POINTS = 3; // vertices - - static final int LINE = 4; // primitive - static final int LINES = 5; // beginShape(), createShape() - static final int LINE_STRIP = 50; // beginShape() - static final int LINE_LOOP = 51; - - static final int TRIANGLE = 8; // primitive - static final int TRIANGLES = 9; // vertices - static final int TRIANGLE_STRIP = 10; // vertices - static final int TRIANGLE_FAN = 11; // vertices - - static final int QUAD = 16; // primitive - static final int QUADS = 17; // vertices - static final int QUAD_STRIP = 18; // vertices - - static final int POLYGON = 20; // in the end, probably cannot - static final int PATH = 21; // separate these two - - static final int RECT = 30; // primitive - static final int ELLIPSE = 31; // primitive - static final int ARC = 32; // primitive - - static final int SPHERE = 40; // primitive - static final int BOX = 41; // primitive - -// static public final int LINE_STRIP = 50; -// static public final int LINE_LOOP = 51; -// static public final int POINT_SPRITES = 52; - - - // shape closing modes - - static final int OPEN = 1; - static final int CLOSE = 2; - - - // shape drawing modes - - /** Draw mode convention to use (x, y) to (width, height) */ - static final int CORNER = 0; - /** Draw mode convention to use (x1, y1) to (x2, y2) coordinates */ - static final int CORNERS = 1; - /** Draw mode from the center, and using the radius */ - static final int RADIUS = 2; - /** @deprecated Use RADIUS instead. */ - static final int CENTER_RADIUS = 2; - /** - * Draw from the center, using second pair of values as the diameter. - * Formerly called CENTER_DIAMETER in alpha releases. - */ - static final int CENTER = 3; - /** - * Synonym for the CENTER constant. Draw from the center, - * using second pair of values as the diameter. - */ - static final int DIAMETER = 3; - /** @deprecated Use DIAMETER instead. */ - static final int CENTER_DIAMETER = 3; - - - // arc drawing modes - - //static final int OPEN = 1; // shared - static final int CHORD = 2; - static final int PIE = 3; - - - // vertically alignment modes for text - - /** Default vertical alignment for text placement */ - static final int BASELINE = 0; - /** Align text to the top */ - static final int TOP = 101; - /** Align text from the bottom, using the baseline. */ - static final int BOTTOM = 102; - - - // uv texture orientation modes - - /** texture coordinates in 0..1 range */ - static final int NORMAL = 1; - /** texture coordinates based on image width/height */ - static final int IMAGE = 2; - - - // texture wrapping modes - - /** textures are clamped to their edges */ - public static final int CLAMP = 0; - /** textures wrap around when uv values go outside 0..1 range */ - public static final int REPEAT = 1; - - - // text placement modes - - /** - * textMode(MODEL) is the default, meaning that characters - * will be affected by transformations like any other shapes. - *

      - * Changed value in 0093 to not interfere with LEFT, CENTER, and RIGHT. - */ - static final int MODEL = 4; - - /** - * textMode(SHAPE) draws text using the the glyph outlines of - * individual characters rather than as textures. If the outlines are - * not available, then textMode(SHAPE) will be ignored and textMode(MODEL) - * will be used instead. For this reason, be sure to call textMode() - * after calling textFont(). - *

      - * Currently, textMode(SHAPE) is only supported by OPENGL mode. - * It also requires Java 1.2 or higher (OPENGL requires 1.4 anyway) - */ - static final int SHAPE = 5; - - - // text alignment modes - // are inherited from LEFT, CENTER, RIGHT - - - // stroke modes - - static final int SQUARE = 1 << 0; // called 'butt' in the svg spec - static final int ROUND = 1 << 1; - static final int PROJECT = 1 << 2; // called 'square' in the svg spec - static final int MITER = 1 << 3; - static final int BEVEL = 1 << 5; - - - // lighting - - static final int AMBIENT = 0; - static final int DIRECTIONAL = 1; - //static final int POINT = 2; // shared with shape feature - static final int SPOT = 3; - - - // key constants - - // only including the most-used of these guys - // if people need more esoteric keys, they can learn about - // the esoteric java KeyEvent api and of virtual keys - - // both key and keyCode will equal these values - // for 0125, these were changed to 'char' values, because they - // can be upgraded to ints automatically by Java, but having them - // as ints prevented split(blah, TAB) from working - static final char BACKSPACE = KeyEvent.KEYCODE_DEL; - static final char TAB = KeyEvent.KEYCODE_TAB; - static final char ENTER = KeyEvent.KEYCODE_ENTER; - static final char RETURN = KeyEvent.KEYCODE_ENTER; - static final char ESC = KeyEvent.KEYCODE_ESCAPE; - static final char DELETE = KeyEvent.KEYCODE_DEL; - - // i.e. if ((key == CODED) && (keyCode == UP)) - static final int CODED = 0xffff; - - // key will be CODED and keyCode will be this value - static final int UP = KeyEvent.KEYCODE_DPAD_UP; - static final int DOWN = KeyEvent.KEYCODE_DPAD_DOWN; - static final int LEFT = KeyEvent.KEYCODE_DPAD_LEFT; - static final int RIGHT = KeyEvent.KEYCODE_DPAD_RIGHT; - - // These seem essential for most sketches, so they're included. - // Others can be found in the KeyEvent reference: - // http://developer.android.com/reference/android/view/KeyEvent.html - static final int BACK = KeyEvent.KEYCODE_BACK; - static final int MENU = KeyEvent.KEYCODE_MENU; - static final int DPAD = KeyEvent.KEYCODE_DPAD_CENTER; - - - // key will be CODED and keyCode will be this value -// static final int ALT = KeyEvent.VK_ALT; -// static final int CONTROL = KeyEvent.VK_CONTROL; - static final int SHIFT = KeyEvent.KEYCODE_SHIFT_LEFT; - - // cursor types - -// static final int ARROW = Cursor.DEFAULT_CURSOR; -// static final int CROSS = Cursor.CROSSHAIR_CURSOR; -// static final int HAND = Cursor.HAND_CURSOR; -// static final int MOVE = Cursor.MOVE_CURSOR; -// static final int TEXT = Cursor.TEXT_CURSOR; -// static final int WAIT = Cursor.WAIT_CURSOR; - - - /** Screen orientation constant for portrait (the hamburger way). */ - static final int PORTRAIT = 1; - /** Screen orientation constant for landscape (the hot dog way). */ - static final int LANDSCAPE = 2; - - - // hints - hint values are positive for the alternate version, - // negative of the same value returns to the normal/default state - - @Deprecated - static final int ENABLE_NATIVE_FONTS = 1; - @Deprecated - static final int DISABLE_NATIVE_FONTS = -1; - - static final int DISABLE_DEPTH_TEST = 2; - static final int ENABLE_DEPTH_TEST = -2; - - static final int ENABLE_DEPTH_SORT = 3; - static final int DISABLE_DEPTH_SORT = -3; - - static final int DISABLE_OPENGL_ERRORS = 4; - static final int ENABLE_OPENGL_ERRORS = -4; - - static final int DISABLE_DEPTH_MASK = 5; - static final int ENABLE_DEPTH_MASK = -5; - - static final int DISABLE_OPTIMIZED_STROKE = 6; - static final int ENABLE_OPTIMIZED_STROKE = -6; - - static final int ENABLE_STROKE_PERSPECTIVE = 7; - static final int DISABLE_STROKE_PERSPECTIVE = -7; - - static final int DISABLE_TEXTURE_MIPMAPS = 8; - static final int ENABLE_TEXTURE_MIPMAPS = -8; - - static final int ENABLE_STROKE_PURE = 9; - static final int DISABLE_STROKE_PURE = -9; - - static final int ENABLE_BUFFER_READING = 10; - static final int DISABLE_BUFFER_READING = -10; - - static final int DISABLE_KEY_REPEAT = 11; - static final int ENABLE_KEY_REPEAT = -11; - - static final int DISABLE_ASYNC_SAVEFRAME = 12; - static final int ENABLE_ASYNC_SAVEFRAME = -12; - - static final int HINT_COUNT = 13; - - - // error messages - - static final String ERROR_BACKGROUND_IMAGE_SIZE = - "background image must be the same size as your application"; - static final String ERROR_BACKGROUND_IMAGE_FORMAT = - "background images should be RGB or ARGB"; - - static final String ERROR_TEXTFONT_NULL_PFONT = - "A null PFont was passed to textFont()"; - - static final String ERROR_PUSHMATRIX_OVERFLOW = - "Too many calls to pushMatrix()."; - static final String ERROR_PUSHMATRIX_UNDERFLOW = - "Too many calls to popMatrix(), and not enough to pushMatrix()."; - - - // Some currently missing GLES constants. - -// static final int GL_MIN_EXT = 0x8007; -// static final int GL_MAX_EXT = 0x8008; -} diff --git a/core/src/processing/core/PFont.java b/core/src/processing/core/PFont.java deleted file mode 100644 index 48a01b3cc..000000000 --- a/core/src/processing/core/PFont.java +++ /dev/null @@ -1,907 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - -import java.io.*; -import java.util.*; - -import android.graphics.*; -import android.graphics.Bitmap.Config; - -/** - * Grayscale bitmap font class used by Processing. - *

      - * Awful (and by that, I mean awesome) ASCII (non-)art for how this works: - *

      - *   |
      - *   |                   height is the full used height of the image
      - *   |
      - *   |   ..XX..       }
      - *   |   ..XX..       }
      - *   |   ......       }
      - *   |   XXXX..       }  topExtent (top y is baseline - topExtent)
      - *   |   ..XX..       }
      - *   |   ..XX..       }  dotted areas are where the image data
      - *   |   ..XX..       }  is actually located for the character
      - *   +---XXXXXX----   }  (it extends to the right and down
      - *   |                   for power of two texture sizes)
      - *   ^^^^ leftExtent (amount to move over before drawing the image
      - *
      - *   ^^^^^^^^^^^^^^ setWidth (width displaced by char)
      - * 
      - */ -public class PFont implements PConstants { - - /** Number of character glyphs in this font. */ - protected int glyphCount; - - /** - * Actual glyph data. The length of this array won't necessarily be the - * same size as glyphCount, in cases where lazy font loading is in use. - */ - protected Glyph[] glyphs; - - /** - * Name of the font as seen by Java when it was created. - * If the font is available, the native version will be used. - */ - protected String name; - - /** - * Postscript name of the font that this bitmap was created from. - */ - protected String psname; - - /** - * The original size of the font when it was first created - */ - protected int size; - - /** true if smoothing was enabled for this font, used for native impl */ - protected boolean smooth; - - /** - * The ascent of the font. If the 'd' character is present in this PFont, - * this value is replaced with its pixel height, because the values returned - * by FontMetrics.getAscent() seem to be terrible. - */ - protected int ascent; - - /** - * The descent of the font. If the 'p' character is present in this PFont, - * this value is replaced with its lowest pixel height, because the values - * returned by FontMetrics.getDescent() are gross. - */ - protected int descent; - - /** - * A more efficient array lookup for straight ASCII characters. For Unicode - * characters, a QuickSort-style search is used. - */ - protected int[] ascii; - - /** - * True if this font is set to load dynamically. This is the default when - * createFont() method is called without a character set. Bitmap versions of - * characters are only created when prompted by an index() call. - */ - protected boolean lazy; - - /** - * Native Android version of the font. If possible, this allows the - * PGraphics subclass to just use Android's font rendering stuff - * in situations where that's faster. - */ - protected Typeface typeface; - - /** - * True if this font should return 'null' for getFont(), so that the native - * font will be used to create a subset, but the native version of the font - * will not be used. - */ - protected boolean subsetting; - - /** - * True if we've already tried to find the native version of this font. - */ - protected boolean typefaceSearched; - - /** - * Array of the native system fonts. Used to lookup native fonts by their - * PostScript name. This is a workaround for a several year old Apple Java - * bug that they can't be bothered to fix. - */ - static protected Typeface[] typefaces; - - // objects to handle creation of font characters only as they're needed - Bitmap lazyBitmap; - Canvas lazyCanvas; - Paint lazyPaint; -// FontMetrics lazyMetrics; - int[] lazySamples; - - /** for subclasses that need to store metadata about the font */ - protected HashMap cacheMap; - - - public PFont() { } // for subclasses - - - /** - * Create a new Processing font from a native font, but don't create all the - * characters at once, instead wait until they're used to include them. - * @param font - * @param smooth - */ - public PFont(Typeface font, int size, boolean smooth) { - this(font, size, smooth, null); - } - - - /** - * Create a new image-based font on the fly. If charset is set to null, - * the characters will only be created as bitmaps when they're drawn. - * - * @param font the font object to create from - * @param charset array of all unicode chars that should be included - * @param smooth true to enable smoothing/anti-aliasing - */ - public PFont(Typeface font, int size, boolean smooth, char charset[]) { - // save this so that we can use the native version - this.typeface = font; - this.smooth = smooth; - - name = ""; //font.getName(); - psname = ""; //font.getPSName(); - this.size = size; //font.getSize(); - - int initialCount = 10; - glyphs = new Glyph[initialCount]; - - ascii = new int[128]; - Arrays.fill(ascii, -1); - - int mbox3 = size * 3; - -// lazyImage = new BufferedImage(mbox3, mbox3, BufferedImage.TYPE_INT_RGB); - lazyBitmap = Bitmap.createBitmap(mbox3, mbox3, Config.ARGB_8888); -// lazyGraphics = (Graphics2D) lazyImage.getGraphics(); - lazyCanvas = new Canvas(lazyBitmap); - -// lazyGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, -// smooth ? -// RenderingHints.VALUE_ANTIALIAS_ON : -// RenderingHints.VALUE_ANTIALIAS_OFF); -// // adding this for post-1.0.9 -// lazyGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, -// smooth ? -// RenderingHints.VALUE_TEXT_ANTIALIAS_ON : -// RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); - lazyPaint = new Paint(); - lazyPaint.setAntiAlias(smooth); - -// lazyGraphics.setFont(font); - lazyPaint.setTypeface(font); -// lazyMetrics = lazyGraphics.getFontMetrics(); - lazyPaint.setTextSize(size); - lazySamples = new int[mbox3 * mbox3]; - -// ascent = lazyMetrics.getAscent(); -// descent = lazyMetrics.getDescent(); - - if (charset == null) { - lazy = true; - - } else { - // charset needs to be sorted to make index lookup run more quickly - // http://dev.processing.org/bugs/show_bug.cgi?id=494 - Arrays.sort(charset); - - glyphs = new Glyph[charset.length]; - - glyphCount = 0; - for (char c : charset) { - Glyph glyf = new Glyph(c); - if (glyf.value < 128) { - ascii[glyf.value] = glyphCount; - } - glyf.index = glyphCount; - glyphs[glyphCount++] = glyf; - } - - // shorten the array if necessary -// if (glyphCount != charset.length) { -// glyphs = (Glyph[]) PApplet.subset(glyphs, 0, glyphCount); -// } - } - - // If not already created, just create these two characters to calculate - // the ascent and descent values for the font. This was tested to only - // require 5-10 ms on a 2.4 GHz MacBook Pro. - // In versions 1.0.9 and earlier, fonts that could not display d or p - // used the max up/down values as calculated by looking through the font. - // That's no longer valid with the auto-generating fonts, so we'll just - // use getAscent() and getDescent() in such (minor) cases. - if (ascent == 0) { - new Glyph('d'); - if (ascent == 0) { // character not valid - ascent = PApplet.round(lazyPaint.ascent()); - } - } - if (descent == 0) { - new Glyph('p'); - if (descent == 0) { - descent = PApplet.round(lazyPaint.descent()); - } - } - } - - - public PFont(InputStream input) throws IOException { - DataInputStream is = new DataInputStream(input); - - // number of character images stored in this font - glyphCount = is.readInt(); - - // used to be the bitCount, but now used for version number. - // version 8 is any font before 69, so 9 is anything from 83+ - // 9 was buggy so gonna increment to 10. - int version = is.readInt(); - - // this was formerly ignored, now it's the actual font size - //mbox = is.readInt(); - size = is.readInt(); - - // this was formerly mboxY, the one that was used - // this will make new fonts downward compatible - is.readInt(); // ignore the other mbox attribute - - ascent = is.readInt(); // formerly baseHt (zero/ignored) - descent = is.readInt(); // formerly ignored struct padding - - // allocate enough space for the character info - glyphs = new Glyph[glyphCount]; - - ascii = new int[128]; - Arrays.fill(ascii, -1); - - // read the information about the individual characters - for (int i = 0; i < glyphCount; i++) { - Glyph glyph = new Glyph(is); - // cache locations of the ascii charset - if (glyph.value < 128) { - ascii[glyph.value] = i; - } - glyph.index = i; - glyphs[i] = glyph; - } - - // not a roman font, so throw an error and ask to re-build. - // that way can avoid a bunch of error checking hacks in here. - if ((ascent == 0) && (descent == 0)) { - throw new RuntimeException("Please use \"Create Font\" to " + - "re-create this font."); - } - - for (Glyph glyph : glyphs) { - glyph.readBitmap(is); - } - - if (version >= 10) { // includes the font name at the end of the file - name = is.readUTF(); - psname = is.readUTF(); - } - if (version == 11) { - smooth = is.readBoolean(); - } - } - - - /** - * Write this PFont to an OutputStream. - *

      - * This is used by the Create Font tool, or whatever anyone else dreams - * up for messing with fonts themselves. - *

      - * It is assumed that the calling class will handle closing - * the stream when finished. - */ - public void save(OutputStream output) throws IOException { - DataOutputStream os = new DataOutputStream(output); - - os.writeInt(glyphCount); - - if ((name == null) || (psname == null)) { - name = ""; - psname = ""; - } - - os.writeInt(11); // formerly numBits, now used for version number - os.writeInt(size); // formerly mboxX (was 64, now 48) - os.writeInt(0); // formerly mboxY, now ignored - os.writeInt(ascent); // formerly baseHt (was ignored) - os.writeInt(descent); // formerly struct padding for c version - - for (int i = 0; i < glyphCount; i++) { - glyphs[i].writeHeader(os); - } - - for (int i = 0; i < glyphCount; i++) { - glyphs[i].writeBitmap(os); - } - - // version 11 - os.writeUTF(name); - os.writeUTF(psname); - os.writeBoolean(smooth); - - os.flush(); - } - - - /** - * Create a new glyph, and add the character to the current font. - * @param c character to create an image for. - */ - protected void addGlyph(char c) { - Glyph glyph = new Glyph(c); - - if (glyphCount == glyphs.length) { - glyphs = (Glyph[]) PApplet.expand(glyphs); - } - if (glyphCount == 0) { - glyph.index = 0; - glyphs[glyphCount] = glyph; - if (glyph.value < 128) { - ascii[glyph.value] = 0; - } - - } else if (glyphs[glyphCount-1].value < glyph.value) { - glyphs[glyphCount] = glyph; - if (glyph.value < 128) { - ascii[glyph.value] = glyphCount; - } - - } else { - for (int i = 0; i < glyphCount; i++) { - if (glyphs[i].value > c) { - for (int j = glyphCount; j > i; --j) { - glyphs[j] = glyphs[j-1]; - if (glyphs[j].value < 128) { - ascii[glyphs[j].value] = j; - } - } - glyph.index = i; - glyphs[i] = glyph; - // cache locations of the ascii charset - if (c < 128) ascii[c] = i; - break; - } - } - } - glyphCount++; - } - - - public String getName() { - return name; - } - - - /** - * Return size of this font. - */ - public int getSize() { - return size; - } - - - /** - * Returns the size that will be used when textFont(font) is called. - */ - public int getDefaultSize() { - return size; - } - - - public boolean isSmooth() { - return smooth; - } - - - public void setSubsetting() { - subsetting = true; - } - - - public String getPostScriptName() { - return psname; - } - - - /** - * Set the native complement of this font. - */ - public void setNative(Object typeface) { - this.typeface = (Typeface) typeface; - } - - - /** - * Return the native Typeface object associated with this PFont (if any). - */ - public Object getNative() { - if (subsetting) { - return null; - } - return typeface; - } - - - /** - * Attempt to find the native version of this font. - * (Public so that it can be used by OpenGL or other renderers.) - */ - static public Object findNative(String name) { - loadTypefaces(); - return typefaceMap.get(name); - } - - - public Glyph getGlyph(char c) { - int index = index(c); - return (index == -1) ? null : glyphs[index]; - } - - - /** - * Get index for the character. - * @return index into arrays or -1 if not found - */ - protected int index(char c) { - if (lazy) { - int index = indexActual(c); - if (index != -1) { - return index; - } -// if (font.canDisplay(c)) { - // create the glyph - addGlyph(c); - // now where did i put that? - return indexActual(c); - -// } else { -// return -1; -// } - - } else { - return indexActual(c); - } - } - - - protected int indexActual(char c) { - // degenerate case, but the find function will have trouble - // if there are somehow zero chars in the lookup - //if (value.length == 0) return -1; - if (glyphCount == 0) return -1; - - // quicker lookup for the ascii fellers - if (c < 128) return ascii[c]; - - // some other unicode char, hunt it out - //return index_hunt(c, 0, value.length-1); - return indexHunt(c, 0, glyphCount-1); - } - - - protected int indexHunt(int c, int start, int stop) { - int pivot = (start + stop) / 2; - - // if this is the char, then return it - if (c == glyphs[pivot].value) return pivot; - - // char doesn't exist, otherwise would have been the pivot - //if (start == stop) return -1; - if (start >= stop) return -1; - - // if it's in the lower half, continue searching that - if (c < glyphs[pivot].value) return indexHunt(c, start, pivot-1); - - // if it's in the upper half, continue there - return indexHunt(c, pivot+1, stop); - } - - - /** - * Currently un-implemented for .vlw fonts, - * but honored for layout in case subclasses use it. - */ - public float kern(char a, char b) { - return 0; - } - - - /** - * Returns the ascent of this font from the baseline. - * The value is based on a font of size 1. - */ - public float ascent() { - return ((float) ascent / (float) size); - } - - - /** - * Returns how far this font descends from the baseline. - * The value is based on a font size of 1. - */ - public float descent() { - return ((float) descent / (float) size); - } - - - /** - * Width of this character for a font of size 1. - */ - public float width(char c) { - if (c == 32) return width('i'); - - int cc = index(c); - if (cc == -1) return 0; - - return ((float) glyphs[cc].setWidth / (float) size); - } - - - ////////////////////////////////////////////////////////////// - - // METADATA REQUIRED BY THE RENDERERS - - - /** - * Store data of some kind for a renderer that requires extra metadata of - * some kind. Usually this is a renderer-specific representation of the - * font data, for instance a custom OpenGL texture for PGraphicsOpenGL2. - * @param renderer The PGraphics renderer associated to the font - * @param storage The metadata required by the renderer - */ - public void setCache(PGraphics renderer, Object storage) { - if (cacheMap == null) cacheMap = new HashMap(); - cacheMap.put(renderer, storage); - } - - - /** - * Get cache storage data for the specified renderer. Because each renderer - * will cache data in different formats, it's necessary to store cache data - * keyed by the renderer object. Otherwise, attempting to draw the same - * image to both a PGraphicsJava2D and a PGraphicsOpenGL2 will cause errors. - * @param renderer The PGraphics renderer associated to the font - * @return metadata stored for the specified renderer - */ - public Object getCache(PGraphics renderer) { - if (cacheMap == null) return null; - return cacheMap.get(renderer); - } - - - /** - * Remove information associated with this renderer from the cache, if any. - * @param parent The PGraphics renderer whose cache data should be removed - */ - public void removeCache(PGraphics renderer) { - if (cacheMap != null) { - cacheMap.remove(renderer); - } - } - - - ////////////////////////////////////////////////////////////// - - public int getGlyphCount() { - return glyphCount; - } - - public Glyph getGlyph(int i) { - return glyphs[i]; - } - - ////////////////////////////////////////////////////////////// - - - static final char[] EXTRA_CHARS = { - 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, - 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, - 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, - 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00BA, - 0x00BB, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, - 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, - 0x00CE, 0x00CF, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, - 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, - 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FF, 0x0102, 0x0103, - 0x0104, 0x0105, 0x0106, 0x0107, 0x010C, 0x010D, 0x010E, 0x010F, - 0x0110, 0x0111, 0x0118, 0x0119, 0x011A, 0x011B, 0x0131, 0x0139, - 0x013A, 0x013D, 0x013E, 0x0141, 0x0142, 0x0143, 0x0144, 0x0147, - 0x0148, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155, 0x0158, - 0x0159, 0x015A, 0x015B, 0x015E, 0x015F, 0x0160, 0x0161, 0x0162, - 0x0163, 0x0164, 0x0165, 0x016E, 0x016F, 0x0170, 0x0171, 0x0178, - 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x0192, 0x02C6, - 0x02C7, 0x02D8, 0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x03A9, - 0x03C0, 0x2013, 0x2014, 0x2018, 0x2019, 0x201A, 0x201C, 0x201D, - 0x201E, 0x2020, 0x2021, 0x2022, 0x2026, 0x2030, 0x2039, 0x203A, - 0x2044, 0x20AC, 0x2122, 0x2202, 0x2206, 0x220F, 0x2211, 0x221A, - 0x221E, 0x222B, 0x2248, 0x2260, 0x2264, 0x2265, 0x25CA, 0xF8FF, - 0xFB01, 0xFB02 - }; - - - /** - * The default Processing character set. - *

      - * This is the union of the Mac Roman and Windows ANSI (CP1250) - * character sets. ISO 8859-1 Latin 1 is Unicode characters 0x80 -> 0xFF, - * and would seem a good standard, but in practice, most P5 users would - * rather have characters that they expect from their platform's fonts. - *

      - * This is more of an interim solution until a much better - * font solution can be determined. (i.e. create fonts on - * the fly from some sort of vector format). - *

      - * Not that I expect that to happen. - */ - static public char[] CHARSET; - static { - CHARSET = new char[126-33+1 + EXTRA_CHARS.length]; - int index = 0; - for (int i = 33; i <= 126; i++) { - CHARSET[index++] = (char)i; - } - for (int i = 0; i < EXTRA_CHARS.length; i++) { - CHARSET[index++] = EXTRA_CHARS[i]; - } - }; - - - static HashMap typefaceMap; - static String[] fontList; - - - /** - * Get a list of the built-in fonts. - */ - static public String[] list() { - loadTypefaces(); - return fontList; - } - - - static public void loadTypefaces() { - if (typefaceMap == null) { - typefaceMap = new HashMap(); - - typefaceMap.put("Serif", - Typeface.create(Typeface.SERIF, Typeface.NORMAL)); - typefaceMap.put("Serif-Bold", - Typeface.create(Typeface.SERIF, Typeface.BOLD)); - typefaceMap.put("Serif-Italic", - Typeface.create(Typeface.SERIF, Typeface.ITALIC)); - typefaceMap.put("Serif-BoldItalic", - Typeface.create(Typeface.SERIF, Typeface.BOLD_ITALIC)); - - typefaceMap.put("SansSerif", - Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL)); - typefaceMap.put("SansSerif-Bold", - Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)); - typefaceMap.put("SansSerif-Italic", - Typeface.create(Typeface.SANS_SERIF, Typeface.ITALIC)); - typefaceMap.put("SansSerif-BoldItalic", - Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD_ITALIC)); - - typefaceMap.put("Monospaced", - Typeface.create(Typeface.MONOSPACE, Typeface.NORMAL)); - typefaceMap.put("Monospaced-Bold", - Typeface.create(Typeface.MONOSPACE, Typeface.BOLD)); - typefaceMap.put("Monospaced-Italic", - Typeface.create(Typeface.MONOSPACE, Typeface.ITALIC)); - typefaceMap.put("Monospaced-BoldItalic", - Typeface.create(Typeface.MONOSPACE, Typeface.BOLD_ITALIC)); - - fontList = new String[typefaceMap.size()]; - typefaceMap.keySet().toArray(fontList); - } - } - - - ///////////////////////////////////////////////////////////// - - /** - * A single character, and its visage. - */ - public class Glyph { - public PImage image; - public int value; - public int height; - public int width; - public int index; - public int setWidth; - public int topExtent; - public int leftExtent; - public boolean fromStream = false; - - - protected Glyph() { - // used when reading from a stream or for subclasses - } - - - protected Glyph(DataInputStream is) throws IOException { - readHeader(is); - } - - - protected void readHeader(DataInputStream is) throws IOException { - value = is.readInt(); - height = is.readInt(); - width = is.readInt(); - setWidth = is.readInt(); - topExtent = is.readInt(); - leftExtent = is.readInt(); - - // pointer from a struct in the c version, ignored - is.readInt(); - - // the values for getAscent() and getDescent() from FontMetrics - // seem to be way too large.. perhaps they're the max? - // as such, use a more traditional marker for ascent/descent - if (value == 'd') { - if (ascent == 0) ascent = topExtent; - } - if (value == 'p') { - if (descent == 0) descent = -topExtent + height; - } - } - - - protected void writeHeader(DataOutputStream os) throws IOException { - os.writeInt(value); - os.writeInt(height); - os.writeInt(width); - os.writeInt(setWidth); - os.writeInt(topExtent); - os.writeInt(leftExtent); - os.writeInt(0); // padding - } - - - protected void readBitmap(DataInputStream is) throws IOException { - image = new PImage(width, height, ALPHA); - int bitmapSize = width * height; - - byte[] temp = new byte[bitmapSize]; - is.readFully(temp); - - // convert the bitmap to an alpha channel - int w = width; - int h = height; - int[] pixels = image.pixels; - for (int y = 0; y < h; y++) { - for (int x = 0; x < w; x++) { - pixels[y * width + x] = temp[y*w + x] & 0xff; -// System.out.print((image.pixels[y*64+x] > 128) ? "*" : "."); - } -// System.out.println(); - } - fromStream = true; -// System.out.println(); - } - - - protected void writeBitmap(DataOutputStream os) throws IOException { - int[] pixels = image.pixels; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - os.write(pixels[y * width + x] & 0xff); - } - } - } - - - protected Glyph(char c) { - int mbox3 = size * 3; -// lazyGraphics.setColor(Color.white); -// lazyGraphics.fillRect(0, 0, mbox3, mbox3); - lazyCanvas.drawColor(Color.WHITE); // fill canvas with white -// lazyGraphics.setColor(Color.black); - lazyPaint.setColor(Color.BLACK); -// lazyGraphics.drawString(String.valueOf(c), size, size * 2); - lazyCanvas.drawText(String.valueOf(c), size, size * 2, lazyPaint); - -// WritableRaster raster = lazyImage.getRaster(); -// raster.getDataElements(0, 0, mbox3, mbox3, lazySamples); - lazyBitmap.getPixels(lazySamples, 0, mbox3, 0, 0, mbox3, mbox3); - - int minX = 1000, maxX = 0; - int minY = 1000, maxY = 0; - boolean pixelFound = false; - - for (int y = 0; y < mbox3; y++) { - for (int x = 0; x < mbox3; x++) { - int sample = lazySamples[y * mbox3 + x] & 0xff; - if (sample != 255) { - if (x < minX) minX = x; - if (y < minY) minY = y; - if (x > maxX) maxX = x; - if (y > maxY) maxY = y; - pixelFound = true; - } - } - } - - if (!pixelFound) { - minX = minY = 0; - maxX = maxY = 0; - // this will create a 1 pixel white (clear) character.. - // maybe better to set one to -1 so nothing is added? - } - - value = c; - height = (maxY - minY) + 1; - width = (maxX - minX) + 1; -// setWidth = lazyMetrics.charWidth(c); - setWidth = (int) lazyPaint.measureText(String.valueOf(c)); - - // offset from vertical location of baseline - // of where the char was drawn (size*2) - topExtent = size*2 - minY; - - // offset from left of where coord was drawn - leftExtent = minX - size; - - image = new PImage(width, height, ALPHA); - int[] pixels = image.pixels; - for (int y = minY; y <= maxY; y++) { - for (int x = minX; x <= maxX; x++) { - int val = 255 - (lazySamples[y * mbox3 + x] & 0xff); - int pindex = (y - minY) * width + (x - minX); - pixels[pindex] = val; - } - } - - // replace the ascent/descent values with something.. err, decent. - if (value == 'd') { - if (ascent == 0) ascent = topExtent; - } - if (value == 'p') { - if (descent == 0) descent = -topExtent + height; - } - } - } -} diff --git a/core/src/processing/core/PGraphics.java b/core/src/processing/core/PGraphics.java deleted file mode 100644 index dc1657cb2..000000000 --- a/core/src/processing/core/PGraphics.java +++ /dev/null @@ -1,6135 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - -import java.util.HashMap; -import java.util.WeakHashMap; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.TimeUnit; - -import processing.android.AppComponent; -import processing.opengl.PGL; -import processing.opengl.PShader; -import android.graphics.Color; -import android.view.SurfaceHolder; - - -/** - * Main graphics and rendering context, as well as the base API implementation. - * - *

      Subclassing and initializing PGraphics objects

      - * Starting in release 0149, subclasses of PGraphics are handled differently. - * The constructor for subclasses takes no parameters, instead a series of - * functions are called by the hosting PApplet to specify its attributes. - *
        - *
      • setParent(PApplet) - is called to specify the parent PApplet. - *
      • setPrimary(boolean) - called with true if this PGraphics will be the - * primary drawing surface used by the sketch, or false if not. - *
      • setPath(String) - called when the renderer needs a filename or output - * path, such as with the PDF or DXF renderers. - *
      • setSize(int, int) - this is called last, at which point it's safe for - * the renderer to complete its initialization routine. - *
      - * The functions were broken out because of the growing number of parameters - * such as these that might be used by a renderer, yet with the exception of - * setSize(), it's not clear which will be necessary. So while the size could - * be passed in to the constructor instead of a setSize() function, a function - * would still be needed that would notify the renderer that it was time to - * finish its initialization. Thus, setSize() simply does both. - * - *

      Know your rights: public vs. private methods

      - * Methods that are protected are often subclassed by other renderers, however - * they are not set 'public' because they shouldn't be part of the user-facing - * public API accessible from PApplet. That is, we don't want sketches calling - * textModeCheck() or vertexTexture() directly. - * - *

      Handling warnings and exceptions

      - * Methods that are unavailable generally show a warning, unless their lack of - * availability will soon cause another exception. For instance, if a method - * like getMatrix() returns null because it is unavailable, an exception will - * be thrown stating that the method is unavailable, rather than waiting for - * the NullPointerException that will occur when the sketch tries to use that - * method. As of release 0149, warnings will only be shown once, and exceptions - * have been changed to warnings where possible. - * - *

      Using xxxxImpl() for subclassing smoothness

      - * The xxxImpl() methods are generally renderer-specific handling for some - * subset if tasks for a particular function (vague enough for you?) For - * instance, imageImpl() handles drawing an image whose x/y/w/h and u/v coords - * have been specified, and screen placement (independent of imageMode) has - * been determined. There's no point in all renderers implementing the - * if (imageMode == BLAH) placement/sizing logic, so that's handled - * by PGraphics, which then calls imageImpl() once all that is figured out. - * - *

      His brother PImage

      - * PGraphics subclasses PImage so that it can be drawn and manipulated in a - * similar fashion. As such, many methods are inherited from PGraphics, - * though many are unavailable: for instance, resize() is not likely to be - * implemented; the same goes for mask(), depending on the situation. - * - *

      What's in PGraphics, what ain't

      - * For the benefit of subclasses, as much as possible has been placed inside - * PGraphics. For instance, bezier interpolation code and implementations of - * the strokeCap() method (that simply sets the strokeCap variable) are - * handled here. Features that will vary widely between renderers are located - * inside the subclasses themselves. For instance, all matrix handling code - * is per-renderer: Java 2D uses its own AffineTransform, P2D uses a PMatrix2D, - * and PGraphics3D needs to keep continually update forward and reverse - * transformations. A proper (future) OpenGL implementation will have all its - * matrix madness handled by the card. Lighting also falls under this - * category, however the base material property settings (emissive, specular, - * et al.) are handled in PGraphics because they use the standard colorMode() - * logic. Subclasses should override methods like emissiveFromCalc(), which - * is a point where a valid color has been defined internally, and can be - * applied in some manner based on the calcXxxx values. - * - *

      What's in the PGraphics documentation, what ain't

      - * Some things are noted here, some things are not. For public API, always - * refer to the reference - * on Processing.org for proper explanations. No attempt has been made to - * keep the javadoc up to date or complete. It's an enormous task for - * which we simply do not have the time. That is, it's not something that - * to be done once—it's a matter of keeping the multiple references - * synchronized (to say nothing of the translation issues), while targeting - * them for their separate audiences. Ouch. - */ -public class PGraphics extends PImage implements PConstants { - // ........................................................ - - // width and height are already inherited from PImage - - -// /// width minus one (useful for many calculations) -// protected int width1; -// -// /// height minus one (useful for many calculations) -// protected int height1; - - /// width * height (useful for many calculations) - public int pixelCount; - - /// true if smoothing is enabled (read-only) - public int smooth; - - // ........................................................ - - /// true if defaults() has been called a first time - protected boolean settingsInited; - - /// true if settings should be re-applied on next beginDraw() - protected boolean reapplySettings; - - /// set to a PGraphics object being used inside a beginRaw/endRaw() block - protected PGraphics raw; - - // ........................................................ - - /** path to the file being saved for this renderer (if any) */ - protected String path; - - /** - * true if this is the main drawing surface for a particular sketch. - * This would be set to false for an offscreen buffer or if it were - * created any other way than size(). When this is set, the listeners - * are also added to the sketch. - */ - protected boolean primaryGraphics; - - // ........................................................ - - /** - * Array of hint[] items. These are hacks to get around various - * temporary workarounds inside the environment. - *

      - * Note that this array cannot be static, as a hint() may result in a - * runtime change specific to a renderer. For instance, calling - * hint(DISABLE_DEPTH_TEST) has to call glDisable() right away on an - * instance of PGraphicsOpenGL. - *

      - * The hints[] array is allocated early on because it might - * be used inside beginDraw(), allocate(), etc. - */ - protected boolean[] hints = new boolean[HINT_COUNT]; - - // ........................................................ - - /** - * Storage for renderer-specific image data. In 1.x, renderers wrote cache - * data into the image object. In 2.x, the renderer has a weak-referenced - * map that points at any of the images it has worked on already. When the - * images go out of scope, they will be properly garbage collected. - */ - protected WeakHashMap cacheMap = - new WeakHashMap(); - - - //////////////////////////////////////////////////////////// - - // Vertex fields, moved from PConstants (after 2.0a8) because they're too - // general to show up in all sketches as defined variables. - - // X, Y and Z are still stored in PConstants because of their general - // usefulness, and that X we'll always want to be 0, etc. - - static public final int R = 3; // actual rgb, after lighting - static public final int G = 4; // fill stored here, transform in place - static public final int B = 5; // TODO don't do that anymore (?) - static public final int A = 6; - - static public final int U = 7; // texture - static public final int V = 8; - - static public final int NX = 9; // normal - static public final int NY = 10; - static public final int NZ = 11; - - static public final int EDGE = 12; - - // stroke - - /** stroke argb values */ - static public final int SR = 13; - static public final int SG = 14; - static public final int SB = 15; - static public final int SA = 16; - - /** stroke weight */ - static public final int SW = 17; - - // transformations (2D and 3D) - - static public final int TX = 18; // transformed xyzw - static public final int TY = 19; - static public final int TZ = 20; - - static public final int VX = 21; // view space coords - static public final int VY = 22; - static public final int VZ = 23; - static public final int VW = 24; - - - // material properties - - // Ambient color (usually to be kept the same as diffuse) - // fill(_) sets both ambient and diffuse. - static public final int AR = 25; - static public final int AG = 26; - static public final int AB = 27; - - // Diffuse is shared with fill. - static public final int DR = 3; // TODO needs to not be shared, this is a material property - static public final int DG = 4; - static public final int DB = 5; - static public final int DA = 6; - - // specular (by default kept white) - static public final int SPR = 28; - static public final int SPG = 29; - static public final int SPB = 30; - - static public final int SHINE = 31; - - // emissive (by default kept black) - static public final int ER = 32; - static public final int EG = 33; - static public final int EB = 34; - - // has this vertex been lit yet - static public final int BEEN_LIT = 35; - - // has this vertex been assigned a normal yet - static public final int HAS_NORMAL = 36; - - static public final int VERTEX_FIELD_COUNT = 37; - - - - //////////////////////////////////////////////////////////// - - // STYLE PROPERTIES - - // Also inherits imageMode() and smooth() (among others) from PImage. - - /** The current colorMode */ - public int colorMode; // = RGB; - - /** Max value for red (or hue) set by colorMode */ - public float colorModeX; // = 255; - - /** Max value for green (or saturation) set by colorMode */ - public float colorModeY; // = 255; - - /** Max value for blue (or value) set by colorMode */ - public float colorModeZ; // = 255; - - /** Max value for alpha set by colorMode */ - public float colorModeA; // = 255; - - /** True if colors are not in the range 0..1 */ - boolean colorModeScale; // = true; - - /** True if colorMode(RGB, 255) */ - boolean colorModeDefault; // = true; - - // ........................................................ - - // Tint color for images - - /** - * True if tint() is enabled (read-only). - * - * Using tint/tintColor seems a better option for naming than - * tintEnabled/tint because the latter seems ugly, even though - * g.tint as the actual color seems a little more intuitive, - * it's just that g.tintEnabled is even more unintuitive. - * Same goes for fill and stroke, et al. - */ - public boolean tint; - - /** tint that was last set (read-only) */ - public int tintColor; - - protected boolean tintAlpha; - protected float tintR, tintG, tintB, tintA; - protected int tintRi, tintGi, tintBi, tintAi; - - // ........................................................ - - // Fill color - - /** true if fill() is enabled, (read-only) */ - public boolean fill; - - /** fill that was last set (read-only) */ - public int fillColor = 0xffFFFFFF; - - protected boolean fillAlpha; - protected float fillR, fillG, fillB, fillA; - protected int fillRi, fillGi, fillBi, fillAi; - - // ........................................................ - - // Stroke color - - /** true if stroke() is enabled, (read-only) */ - public boolean stroke; - - /** stroke that was last set (read-only) */ - public int strokeColor = 0xff000000; - - protected boolean strokeAlpha; - protected float strokeR, strokeG, strokeB, strokeA; - protected int strokeRi, strokeGi, strokeBi, strokeAi; - - // ........................................................ - - // Additional stroke properties - - static protected final float DEFAULT_STROKE_WEIGHT = 1; - static protected final int DEFAULT_STROKE_JOIN = MITER; - static protected final int DEFAULT_STROKE_CAP = ROUND; - - /** - * Last value set by strokeWeight() (read-only). This has a default - * setting, rather than fighting with renderers about whether that - * renderer supports thick lines. - */ - public float strokeWeight = DEFAULT_STROKE_WEIGHT; - - /** - * Set by strokeJoin() (read-only). This has a default setting - * so that strokeJoin() need not be called by defaults, - * because subclasses may not implement it (i.e. PGraphicsGL) - */ - public int strokeJoin = DEFAULT_STROKE_JOIN; - - /** - * Set by strokeCap() (read-only). This has a default setting - * so that strokeCap() need not be called by defaults, - * because subclasses may not implement it (i.e. PGraphicsGL) - */ - public int strokeCap = DEFAULT_STROKE_CAP; - - // ........................................................ - - // Shape placement properties - - // imageMode() is inherited from PImage - - /** The current rect mode (read-only) */ - public int rectMode; - - /** The current ellipse mode (read-only) */ - public int ellipseMode; - - /** The current shape alignment mode (read-only) */ - public int shapeMode; - - /** The current image alignment (read-only) */ - public int imageMode = CORNER; - - // ........................................................ - - // Text and font properties - - /** The current text font (read-only) */ - public PFont textFont; - - /** The current text align (read-only) */ - public int textAlign = LEFT; - - /** The current vertical text alignment (read-only) */ - public int textAlignY = BASELINE; - - /** The current text mode (read-only) */ - public int textMode = MODEL; - - /** The current text size (read-only) */ - public float textSize; - - /** The current text leading (read-only) */ - public float textLeading; - - // ........................................................ - - // Material properties - -// PMaterial material; -// PMaterial[] materialStack; -// int materialStackPointer; - - public int ambientColor; - public float ambientR, ambientG, ambientB; - public boolean setAmbient; - - public int specularColor; - public float specularR, specularG, specularB; - - public int emissiveColor; - public float emissiveR, emissiveG, emissiveB; - - public float shininess; - - - // Style stack - - static final int STYLE_STACK_DEPTH = 64; - PStyle[] styleStack = new PStyle[STYLE_STACK_DEPTH]; - int styleStackDepth; - - - //////////////////////////////////////////////////////////// - - - /** Last background color that was set, zero if an image */ - public int backgroundColor = 0xffCCCCCC; - - protected boolean backgroundAlpha; - protected float backgroundR, backgroundG, backgroundB, backgroundA; - protected int backgroundRi, backgroundGi, backgroundBi, backgroundAi; - - - /** The current blending mode. */ - protected int blendMode; - - - // ........................................................ - - /** - * Current model-view matrix transformation of the form m[row][column], - * which is a "column vector" (as opposed to "row vector") matrix. - */ -// PMatrix matrix; -// public float m00, m01, m02, m03; -// public float m10, m11, m12, m13; -// public float m20, m21, m22, m23; -// public float m30, m31, m32, m33; - -// static final int MATRIX_STACK_DEPTH = 32; -// float[][] matrixStack = new float[MATRIX_STACK_DEPTH][16]; -// float[][] matrixInvStack = new float[MATRIX_STACK_DEPTH][16]; -// int matrixStackDepth; - - static final int MATRIX_STACK_DEPTH = 32; - - // ........................................................ - - // internal color for setting/calculating - protected float calcR, calcG, calcB, calcA; - protected int calcRi, calcGi, calcBi, calcAi; - protected int calcColor; - protected boolean calcAlpha; - - /** The last RGB value converted to HSB */ - int cacheHsbKey; - /** Result of the last conversion to HSB */ - float[] cacheHsbValue = new float[3]; - - // ........................................................ - - /** - * Type of shape passed to beginShape(), - * zero if no shape is currently being drawn. - */ - protected int shape; - - // vertices - static final int DEFAULT_VERTICES = 512; - protected float vertices[][] = - new float[DEFAULT_VERTICES][VERTEX_FIELD_COUNT]; - protected int vertexCount; // total number of vertices - - // ........................................................ - - protected boolean bezierInited = false; - public int bezierDetail = 20; - - // used by both curve and bezier, so just init here - protected PMatrix3D bezierBasisMatrix = - new PMatrix3D(-1, 3, -3, 1, - 3, -6, 3, 0, - -3, 3, 0, 0, - 1, 0, 0, 0); - - //protected PMatrix3D bezierForwardMatrix; - protected PMatrix3D bezierDrawMatrix; - - // ........................................................ - - protected boolean curveInited = false; - public int curveDetail = 20; - public float curveTightness = 0; - // catmull-rom basis matrix, perhaps with optional s parameter - protected PMatrix3D curveBasisMatrix; - protected PMatrix3D curveDrawMatrix; - - protected PMatrix3D bezierBasisInverse; - protected PMatrix3D curveToBezierMatrix; - - // ........................................................ - - // spline vertices - - protected float curveVertices[][]; - protected int curveVertexCount; - - // ........................................................ - - // precalculate sin/cos lookup tables [toxi] - // circle resolution is determined from the actual used radii - // passed to ellipse() method. this will automatically take any - // scale transformations into account too - - // [toxi 031031] - // changed table's precision to 0.5 degree steps - // introduced new vars for more flexible code - static final protected float sinLUT[]; - static final protected float cosLUT[]; - static final protected float SINCOS_PRECISION = 0.5f; - static final protected int SINCOS_LENGTH = (int) (360f / SINCOS_PRECISION); - static { - sinLUT = new float[SINCOS_LENGTH]; - cosLUT = new float[SINCOS_LENGTH]; - for (int i = 0; i < SINCOS_LENGTH; i++) { - sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION); - cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION); - } - } - - // ........................................................ - - /** The current font if a Java version of it is installed */ - //protected Font textFontNative; - - /** Metrics for the current native Java font */ - //protected FontMetrics textFontNativeMetrics; - -// /** Last text position, because text often mixed on lines together */ -// protected float textX, textY, textZ; - - /** - * Internal buffer used by the text() functions - * because the String object is slow - */ - protected char[] textBuffer = new char[8 * 1024]; - protected char[] textWidthBuffer = new char[8 * 1024]; - - protected int textBreakCount; - protected int[] textBreakStart; - protected int[] textBreakStop; - - // ........................................................ - - public boolean edge = true; - - // ........................................................ - - /// normal calculated per triangle - static protected final int NORMAL_MODE_AUTO = 0; - /// one normal manually specified per shape - static protected final int NORMAL_MODE_SHAPE = 1; - /// normals specified for each shape vertex - static protected final int NORMAL_MODE_VERTEX = 2; - - /// Current mode for normals, one of AUTO, SHAPE, or VERTEX - protected int normalMode; - - /// Keep track of how many calls to normal, to determine the mode. - //protected int normalCount; - - protected boolean autoNormal; - - /** Current normal vector. */ - public float normalX, normalY, normalZ; - - // ........................................................ - - /** - * Sets whether texture coordinates passed to - * vertex() calls will be based on coordinates that are - * based on the IMAGE or NORMALIZED. - */ - public int textureMode = IMAGE; - - /** - * Current horizontal coordinate for texture, will always - * be between 0 and 1, even if using textureMode(IMAGE). - */ - public float textureU; - - /** Current vertical coordinate for texture, see above. */ - public float textureV; - - /** Current image being used as a texture */ - public PImage textureImage = null; - - // ........................................................ - - // [toxi031031] new & faster sphere code w/ support flexibile resolutions - // will be set by sphereDetail() or 1st call to sphere() - protected float sphereX[], sphereY[], sphereZ[]; - - /// Number of U steps (aka "theta") around longitudinally spanning 2*pi - public int sphereDetailU = 0; - /// Number of V steps (aka "phi") along latitudinally top-to-bottom spanning pi - public int sphereDetailV = 0; - - // ........................................................ - - // Variables used to save the surface contents before the activity is taken to the background. - protected String restoreFilename; - protected int restoreWidth, restoreHeight; - protected int restoreCount; - protected boolean restartedLoopingAfterResume = false; - protected boolean restoredSurface = true; - - // This auxiliary variable is used to implement a little hack that fixes - // https://github.com/processing/processing-android/issues/147 - // on older devices where the last frame cannot be maintained after ending - // the rendering in GL. The trick consists in running one more frame after the - // noLoop() call, which ensures that the FBO layer is properly initialized - // and drawn with the contents of the previous frame. - protected boolean requestedNoLoop = false; - - ////////////////////////////////////////////////////////////// - - // INTERNAL - - - /** - * Constructor for the PGraphics object. Use this to ensure that - * the defaults get set properly. In a subclass, use this(w, h) - * as the first line of a subclass' constructor to properly set - * the internal fields and defaults. - */ - public PGraphics() { - } - - - public void setParent(PApplet parent) { // ignore - this.parent = parent; - } - - - /** - * Set (or unset) this as the main drawing surface. Meaning that it can - * safely be set to opaque (and given a default gray background), or anything - * else that goes along with that. - */ - public void setPrimary(boolean primary) { // ignore - this.primaryGraphics = primary; - - // base images must be opaque (for performance and general - // headache reasons.. argh, a semi-transparent opengl surface?) - // use createGraphics() if you want a transparent surface. - if (primaryGraphics) { - format = RGB; - } - } - - - public void setPath(String path) { // ignore - this.path = path; - } - - - public void setFrameRate(float framerate) { // ignore - } - - - public void surfaceChanged() { // ignore - } - - - public void reset() { // ignore - } - - - /** - * The final step in setting up a renderer, set its size of this renderer. - * This was formerly handled by the constructor, but instead it's been broken - * out so that setParent/setPrimary/setPath can be handled differently. - * - * Important that this is ignored by preproc.pl because otherwise it will - * override setSize() in PApplet/Applet/Component, which will 1) not call - * super.setSize(), and 2) will cause the renderer to be resized from the - * event thread (EDT), causing a nasty crash as it collides with the - * animation thread. - */ - public void setSize(int w, int h) { // ignore - width = w; - height = h; - - pixelWidth = width * pixelDensity; - pixelHeight = height * pixelDensity; - - reapplySettings = true; - } - - - /** - * Handle any takedown for this graphics context. - *

      - * This is called when a sketch is shut down and this renderer was - * specified using the size() command, or inside endRecord() and - * endRaw(), in order to shut things off. - */ - public void dispose() { // ignore - parent = null; - } - - - public PSurface createSurface(AppComponent component, SurfaceHolder holder, boolean reset) { // ignore - return null; - } - - - ////////////////////////////////////////////////////////////// - - // IMAGE METADATA FOR THIS RENDERER - - /** - * Store data of some kind for the renderer that requires extra metadata of - * some kind. Usually this is a renderer-specific representation of the - * image data, for instance a BufferedImage with tint() settings applied for - * PGraphicsJava2D, or resized image data and OpenGL texture indices for - * PGraphicsOpenGL. - * @param image The image to be stored - * @param storage The metadata required by the renderer - */ - public void setCache(PImage image, Object storage) { // ignore - cacheMap.put(image, storage); - } - - - /** - * Get cache storage data for the specified renderer. Because each renderer - * will cache data in different formats, it's necessary to store cache data - * keyed by the renderer object. Otherwise, attempting to draw the same - * image to both a PGraphicsJava2D and a PGraphicsOpenGL will cause errors. - * @return metadata stored for the specified renderer - */ - public Object getCache(PImage image) { // ignore - return cacheMap.get(image); - } - - - /** - * Remove information associated with this renderer from the cache, if any. - * @param image The image whose cache data should be removed - */ - public void removeCache(PImage image) { // ignore - cacheMap.remove(image); - } - - - ////////////////////////////////////////////////////////////// - - // FRAME - - - /** - * Handle grabbing the focus from the parent applet. Other renderers can - * override this if handling needs to be different. - */ - public void requestFocus() { // ignore - } - - - /** - * Some renderers have requirements re: when they are ready to draw. - */ -// public boolean canDraw() { // ignore -// return true; -// } - - - /** - * Try to draw, or put a draw request on the queue. - */ -// public void requestDraw() { // ignore -// } - - - /** - * Prepares the PGraphics for drawing. - *

      - * When creating your own PGraphics, you should call this before - * drawing anything. - */ - public void beginDraw() { // ignore - } - - - /** - * This will finalize rendering so that it can be shown on-screen. - *

      - * When creating your own PGraphics, you should call this when - * you're finished drawing. - */ - public void endDraw() { // ignore - } - - - public void flush() { - // no-op, mostly for P3D to write sorted stuff - } - - - public PGL beginPGL() { - showMethodWarning("beginPGL"); - return null; - } - - - public void endPGL() { - showMethodWarning("endPGL"); - } - - - protected void checkSettings() { - if (!settingsInited) defaultSettings(); - if (reapplySettings) reapplySettings(); - } - - - /** - * Set engine's default values. This has to be called by PApplet, - * somewhere inside setup() or draw() because it talks to the - * graphics buffer, meaning that for subclasses like OpenGL, there - * needs to be a valid graphics context to mess with otherwise - * you'll get some good crashing action. - * - * This is currently called by checkSettings(), during beginDraw(). - */ - protected void defaultSettings() { // ignore - colorMode(RGB, 255); - fill(255); - stroke(0); - - // added for 0178 for subclasses that need them - strokeWeight(DEFAULT_STROKE_WEIGHT); - strokeJoin(DEFAULT_STROKE_JOIN); - strokeCap(DEFAULT_STROKE_CAP); - - // init shape stuff - shape = 0; - - // init matrices (must do before lights) - //matrixStackDepth = 0; - - rectMode(CORNER); - ellipseMode(DIAMETER); - - autoNormal = true; - - // no current font - textFont = null; - textSize = 12; - textLeading = 14; - textAlign = LEFT; - textMode = MODEL; - - // if this fella is associated with an applet, then clear its background. - // if it's been created by someone else through createGraphics, - // they have to call background() themselves, otherwise everything gets - // a gray background (when just a transparent surface or an empty pdf - // is what's desired). - // this background() call is for the Java 2D and OpenGL renderers. - if (primaryGraphics) { - //System.out.println("main drawing surface bg " + getClass().getName()); - background(backgroundColor); - } - - blendMode(BLEND); - - settingsInited = true; - // defaultSettings() overlaps reapplySettings(), don't do both - reapplySettings = false; - } - - - /** - * Re-apply current settings. Some methods, such as textFont(), require that - * their methods be called (rather than simply setting the textFont variable) - * because they affect the graphics context, or they require parameters from - * the context (e.g. getting native fonts for text). - * - * This will only be called from an allocate(), which is only called from - * size(), which is safely called from inside beginDraw(). And it cannot be - * called before defaultSettings(), so we should be safe. - */ - protected void reapplySettings() { // ignore -// System.out.println("attempting reapplySettings()"); - if (!settingsInited) return; // if this is the initial setup, no need to reapply - -// System.out.println(" doing reapplySettings"); -// new Exception().printStackTrace(System.out); - - colorMode(colorMode, colorModeX, colorModeY, colorModeZ); - if (fill) { -// PApplet.println(" fill " + PApplet.hex(fillColor)); - fill(fillColor); - } else { - noFill(); - } - if (stroke) { - stroke(strokeColor); - - // The if() statements should be handled inside the functions, - // otherwise an actual reset/revert won't work properly. - //if (strokeWeight != DEFAULT_STROKE_WEIGHT) { - strokeWeight(strokeWeight); - //} -// if (strokeCap != DEFAULT_STROKE_CAP) { - strokeCap(strokeCap); -// } -// if (strokeJoin != DEFAULT_STROKE_JOIN) { - strokeJoin(strokeJoin); -// } - } else { - noStroke(); - } - if (tint) { - tint(tintColor); - } else { - noTint(); - } -// if (smooth) { -// smooth(); -// } else { -// // Don't bother setting this, cuz it'll anger P3D. -// noSmooth(); -// } - if (textFont != null) { -// System.out.println(" textFont in reapply is " + textFont); - // textFont() resets the leading, so save it in case it's changed - float saveLeading = textLeading; - textFont(textFont, textSize); - textLeading(saveLeading); - } - textMode(textMode); - textAlign(textAlign, textAlignY); - background(backgroundColor); - - blendMode(blendMode); - - reapplySettings = false; - } - - ////////////////////////////////////////////////////////////// - - // RENDERER STATE - - - protected void clearState() { // ignore - // Nothing to do here, it depends on the renderer's implementation. - } - - - protected void saveState() { // ignore - // Nothing to do here, it depends on the renderer's implementation. - } - - - protected void restoreState() { // ignore - // This method probably does not need to be re-implemented in the subclasses. All we need to - // do is to check for the resume in no-loop state situation: - restoredSurface = false; - if (!parent.looping) { - // The sketch needs to draw a few frames after resuming so it has the chance to restore the - // screen contents: - // https://github.com/processing/processing-android/issues/492 - // so we restart looping: - parent.loop(); - // and flag this situation when the surface has been restored: - restartedLoopingAfterResume = true; - } - } - - - protected boolean restoringState() { // ignore - return !restoredSurface && restartedLoopingAfterResume; - } - - - protected void restoreSurface() { // ignore - // When implementing this method in a subclass of PGraphics, it should add a call to the super - // implementation, to make sure that the looping is stopped in the case where the sketch was - // resumed in no-loop state (see comment in restoreState() method above). - if (restoredSurface && restartedLoopingAfterResume) { - restartedLoopingAfterResume = false; - parent.noLoop(); - } - } - - - protected boolean requestNoLoop() { // ignore - // Some renderers (OpenGL) cannot be set to no-loop right away, it has to be requested so - // any pending frames are properly rendered. Override as needed. - return false; - } - - - protected boolean isLooping() { // ignore - return parent.isLooping() && (!requestNoLoop() || !requestedNoLoop); - } - - - ////////////////////////////////////////////////////////////// - - // HINTS - - /** - * Enable a hint option. - *

      - * For the most part, hints are temporary api quirks, - * for which a proper api hasn't been properly worked out. - * for instance SMOOTH_IMAGES existed because smooth() - * wasn't yet implemented, but it will soon go away. - *

      - * They also exist for obscure features in the graphics - * engine, like enabling/disabling single pixel lines - * that ignore the zbuffer, the way they do in alphabot. - *

      - * Current hint options: - *

        - *
      • DISABLE_DEPTH_TEST - - * turns off the z-buffer in the P3D or OPENGL renderers. - *
      - */ - @SuppressWarnings("deprecation") - public void hint(int which) { - if (which == ENABLE_NATIVE_FONTS || - which == DISABLE_NATIVE_FONTS) { - showWarning("hint(ENABLE_NATIVE_FONTS) no longer supported. " + - "Use createFont() instead."); - } - if (which == ENABLE_KEY_REPEAT) { - parent.keyRepeatEnabled = true; - } else if (which == DISABLE_KEY_REPEAT) { - parent.keyRepeatEnabled = false; - } - if (which > 0) { - hints[which] = true; - } else { - hints[-which] = false; - } - } - - - ////////////////////////////////////////////////////////////// - - // VERTEX SHAPES - - /** - * Start a new shape of type POLYGON - */ - public void beginShape() { - beginShape(POLYGON); - } - - - /** - * Start a new shape. - *

      - * Differences between beginShape() and line() and point() methods. - *

      - * beginShape() is intended to be more flexible at the expense of being - * a little more complicated to use. it handles more complicated shapes - * that can consist of many connected lines (so you get joins) or lines - * mixed with curves. - *

      - * The line() and point() command are for the far more common cases - * (particularly for our audience) that simply need to draw a line - * or a point on the screen. - *

      - * From the code side of things, line() may or may not call beginShape() - * to do the drawing. In the beta code, they do, but in the alpha code, - * they did not. they might be implemented one way or the other depending - * on tradeoffs of runtime efficiency vs. implementation efficiency &mdash - * meaning the speed that things run at vs. the speed it takes me to write - * the code and maintain it. for beta, the latter is most important so - * that's how things are implemented. - */ - public void beginShape(int kind) { - shape = kind; - } - - - /** - * Sets whether the upcoming vertex is part of an edge. - * Equivalent to glEdgeFlag(), for people familiar with OpenGL. - */ - public void edge(boolean edge) { - this.edge = edge; - } - - - /** - * Sets the current normal vector. Only applies with 3D rendering - * and inside a beginShape/endShape block. - *

      - * This is for drawing three dimensional shapes and surfaces, - * allowing you to specify a vector perpendicular to the surface - * of the shape, which determines how lighting affects it. - *

      - * For people familiar with OpenGL, this function is basically - * identical to glNormal3f(). - */ - public void normal(float nx, float ny, float nz) { - normalX = nx; - normalY = ny; - normalZ = nz; - - // if drawing a shape and the normal hasn't been set yet, - // then we need to set the normals for each vertex so far - if (shape != 0) { - if (normalMode == NORMAL_MODE_AUTO) { - // One normal per begin/end shape - normalMode = NORMAL_MODE_SHAPE; - } else if (normalMode == NORMAL_MODE_SHAPE) { - // a separate normal for each vertex - normalMode = NORMAL_MODE_VERTEX; - } - } - } - - - public void attribPosition(String name, float x, float y, float z) { - showMissingWarning("attrib"); - } - - - public void attribNormal(String name, float nx, float ny, float nz) { - showMissingWarning("attrib"); - } - - - public void attribColor(String name, int color) { - showMissingWarning("attrib"); - } - - - public void attrib(String name, float... values) { - showMissingWarning("attrib"); - } - - - public void attrib(String name, int... values) { - showMissingWarning("attrib"); - } - - - public void attrib(String name, boolean... values) { - showMissingWarning("attrib"); - } - - - /** - * Set texture mode to either to use coordinates based on the IMAGE - * (more intuitive for new users) or NORMALIZED (better for advanced chaps) - */ - public void textureMode(int mode) { - this.textureMode = mode; - } - - - public void textureWrap(int wrap) { - showMissingWarning("textureWrap"); - } - - - /** - * Set texture image for current shape. - * Needs to be called between @see beginShape and @see endShape - * - * @param image reference to a PImage object - */ - public void texture(PImage image) { - textureImage = image; - } - - - /** - * Removes texture image for current shape. - * Needs to be called between @see beginShape and @see endShape - * - */ - public void noTexture() { - textureImage = null; - } - - - protected void vertexCheck() { - if (vertexCount == vertices.length) { - float temp[][] = new float[vertexCount << 1][VERTEX_FIELD_COUNT]; - System.arraycopy(vertices, 0, temp, 0, vertexCount); - vertices = temp; - } - } - - - public void vertex(float x, float y) { - vertexCheck(); - float[] vertex = vertices[vertexCount]; - - curveVertexCount = 0; - - vertex[X] = x; - vertex[Y] = y; - vertex[Z] = 0; - - vertex[EDGE] = edge ? 1 : 0; - - boolean textured = textureImage != null; - if (fill || textured) { - if (!textured) { - vertex[R] = fillR; - vertex[G] = fillG; - vertex[B] = fillB; - vertex[A] = fillA; - } else { - if (tint) { - vertex[R] = tintR; - vertex[G] = tintG; - vertex[B] = tintB; - vertex[A] = tintA; - } else { - vertex[R] = 1; - vertex[G] = 1; - vertex[B] = 1; - vertex[A] = 1; - } - } - } - - if (stroke) { - vertex[SR] = strokeR; - vertex[SG] = strokeG; - vertex[SB] = strokeB; - vertex[SA] = strokeA; - vertex[SW] = strokeWeight; - } - - vertex[U] = textureU; - vertex[V] = textureV; - - if (autoNormal) { - float norm2 = normalX * normalX + normalY * normalY + normalZ * normalZ; - if (norm2 < EPSILON) { - vertex[HAS_NORMAL] = 0; - } else { - if (Math.abs(norm2 - 1) > EPSILON) { - // The normal vector is not normalized. - float norm = PApplet.sqrt(norm2); - normalX /= norm; - normalY /= norm; - normalZ /= norm; - } - vertex[HAS_NORMAL] = 1; - } - } else { - vertex[HAS_NORMAL] = 1; - } - - vertex[NX] = normalX; - vertex[NY] = normalY; - vertex[NZ] = normalZ; - - vertexCount++; - } - - - public void vertex(float x, float y, float z) { - vertexCheck(); - float[] vertex = vertices[vertexCount]; - - // only do this if we're using an irregular (POLYGON) shape that - // will go through the triangulator. otherwise it'll do thinks like - // disappear in mathematically odd ways - // http://dev.processing.org/bugs/show_bug.cgi?id=444 - if (shape == POLYGON) { - if (vertexCount > 0) { - float pvertex[] = vertices[vertexCount-1]; - if ((Math.abs(pvertex[X] - x) < EPSILON) && - (Math.abs(pvertex[Y] - y) < EPSILON) && - (Math.abs(pvertex[Z] - z) < EPSILON)) { - // this vertex is identical, don't add it, - // because it will anger the triangulator - return; - } - } - } - - // User called vertex(), so that invalidates anything queued up for curve - // vertices. If this is internally called by curveVertexSegment, - // then curveVertexCount will be saved and restored. - curveVertexCount = 0; - - vertex[X] = x; - vertex[Y] = y; - vertex[Z] = z; - - vertex[EDGE] = edge ? 1 : 0; - - boolean textured = textureImage != null; - if (fill || textured) { - if (!textured) { - vertex[R] = fillR; - vertex[G] = fillG; - vertex[B] = fillB; - vertex[A] = fillA; - } else { - if (tint) { - vertex[R] = tintR; - vertex[G] = tintG; - vertex[B] = tintB; - vertex[A] = tintA; - } else { - vertex[R] = 1; - vertex[G] = 1; - vertex[B] = 1; - vertex[A] = 1; - } - } - - /* - vertex[AR] = ambientR; - vertex[AG] = ambientG; - vertex[AB] = ambientB; - - vertex[SPR] = specularR; - vertex[SPG] = specularG; - vertex[SPB] = specularB; - //vertex[SPA] = specularA; - - vertex[SHINE] = shininess; - - vertex[ER] = emissiveR; - vertex[EG] = emissiveG; - vertex[EB] = emissiveB; - */ - } - - if (stroke) { - vertex[SR] = strokeR; - vertex[SG] = strokeG; - vertex[SB] = strokeB; - vertex[SA] = strokeA; - vertex[SW] = strokeWeight; - } - - vertex[U] = textureU; - vertex[V] = textureV; - - if (autoNormal) { - float norm2 = normalX * normalX + normalY * normalY + normalZ * normalZ; - if (norm2 < EPSILON) { - vertex[HAS_NORMAL] = 0; - } else { - if (Math.abs(norm2 - 1) > EPSILON) { - // The normal vector is not normalized. - float norm = PApplet.sqrt(norm2); - normalX /= norm; - normalY /= norm; - normalZ /= norm; - } - vertex[HAS_NORMAL] = 1; - } - } else { - vertex[HAS_NORMAL] = 1; - } - - vertex[NX] = normalX; - vertex[NY] = normalY; - vertex[NZ] = normalZ; - - vertexCount++; - } - - - /** - * Used by renderer subclasses or PShape to efficiently pass in already - * formatted vertex information. - * @param v vertex parameters, as a float array of length VERTEX_FIELD_COUNT - */ - public void vertex(float[] v) { - vertexCheck(); - curveVertexCount = 0; - float[] vertex = vertices[vertexCount]; - System.arraycopy(v, 0, vertex, 0, VERTEX_FIELD_COUNT); - vertexCount++; - } - - - public void vertex(float x, float y, float u, float v) { - vertexTexture(u, v); - vertex(x, y); - } - - - public void vertex(float x, float y, float z, float u, float v) { - vertexTexture(u, v); - vertex(x, y, z); - } - - - /** - * Internal method to copy all style information for the given vertex. - * Can be overridden by subclasses to handle only properties pertinent to - * that renderer. (e.g. no need to copy the emissive color in P2D) - */ -// protected void vertexStyle() { -// } - - - /** - * Set (U, V) coords for the next vertex in the current shape. - * This is ugly as its own function, and will (almost?) always be - * coincident with a call to vertex. As of beta, this was moved to - * the protected method you see here, and called from an optional - * param of and overloaded vertex(). - *

      - * The parameters depend on the current textureMode. When using - * textureMode(IMAGE), the coordinates will be relative to the size - * of the image texture, when used with textureMode(NORMAL), - * they'll be in the range 0..1. - *

      - * Used by both PGraphics2D (for images) and PGraphics3D. - */ - protected void vertexTexture(float u, float v) { - if (textureImage == null) { - throw new RuntimeException("You must first call texture() before " + - "using u and v coordinates with vertex()"); - } - if (textureMode == IMAGE) { - u /= (float) textureImage.width; - v /= (float) textureImage.height; - } - - textureU = u; - textureV = v; - } - - - /** This feature is in testing, do not use or rely upon its implementation */ - public void breakShape() { - showWarning("This renderer cannot currently handle concave shapes, " + - "or shapes with holes."); - } - - - public void beginContour() { - showMissingWarning("beginContour"); - } - - - public void endContour() { - showMissingWarning("endContour"); - } - - - public void endShape() { - endShape(OPEN); - } - - - public void endShape(int mode) { - } - - - ////////////////////////////////////////////////////////////// - - // CLIPPING - - - public void clip(float a, float b, float c, float d) { - if (imageMode == CORNER) { - if (c < 0) { // reset a negative width - a += c; c = -c; - } - if (d < 0) { // reset a negative height - b += d; d = -d; - } - - clipImpl(a, b, a + c, b + d); - - } else if (imageMode == CORNERS) { - if (c < a) { // reverse because x2 < x1 - float temp = a; a = c; c = temp; - } - if (d < b) { // reverse because y2 < y1 - float temp = b; b = d; d = temp; - } - - clipImpl(a, b, c, d); - - } else if (imageMode == CENTER) { - // c and d are width/height - if (c < 0) c = -c; - if (d < 0) d = -d; - float x1 = a - c/2; - float y1 = b - d/2; - - clipImpl(x1, y1, x1 + c, y1 + d); - } - } - - - protected void clipImpl(float x1, float y1, float x2, float y2) { - showMissingWarning("clip"); - } - - - public void noClip() { - showMissingWarning("noClip"); - } - - - ////////////////////////////////////////////////////////////// - - // BLEND - - - public void blendMode(int mode) { - this.blendMode = mode; - blendModeImpl(); - } - - - protected void blendModeImpl() { - if (blendMode != BLEND) { - showMissingWarning("blendMode"); - } - } - - - ////////////////////////////////////////////////////////////// - - // SHAPE I/O - - - public PShape loadShape(String filename) { - showMissingWarning("loadShape"); - return null; - } - - - public PShape loadShape(String filename, String options) { - showMissingWarning("loadShape"); - return null; - } - - - ////////////////////////////////////////////////////////////// - - // SHAPE CREATION - - - /** - * @webref shape - * @see PShape - * @see PShape#endShape() - * @see PApplet#loadShape(String) - */ - public PShape createShape() { - // Defaults to GEOMETRY (rather than GROUP like the default constructor) - // because that's how people will use it within a sketch. - return createShape(PShape.GEOMETRY); - } - - - // POINTS, LINES, TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, QUAD_STRIP - public PShape createShape(int type) { - // If it's a PRIMITIVE, it needs the 'params' field anyway - if (type == PConstants.GROUP || - type == PShape.PATH || - type == PShape.GEOMETRY) { - return createShapeFamily(type); - } - final String msg = - "Only GROUP, PShape.PATH, and PShape.GEOMETRY work with createShape()"; - throw new IllegalArgumentException(msg); - } - - - /** Override this method to return an appropriate shape for your renderer */ - protected PShape createShapeFamily(int type) { - return new PShape(this, type); -// showMethodWarning("createShape()"); -// return null; - } - - - /** - * @param kind either POINT, LINE, TRIANGLE, QUAD, RECT, ELLIPSE, ARC, BOX, SPHERE - * @param p parameters that match the kind of shape - */ - public PShape createShape(int kind, float... p) { - int len = p.length; - - if (kind == POINT) { - if (is3D() && len != 2 && len != 3) { - throw new IllegalArgumentException("Use createShape(POINT, x, y) or createShape(POINT, x, y, z)"); - } else if (len != 2) { - throw new IllegalArgumentException("Use createShape(POINT, x, y)"); - } - return createShapePrimitive(kind, p); - - } else if (kind == LINE) { - if (is3D() && len != 4 && len != 6) { - throw new IllegalArgumentException("Use createShape(LINE, x1, y1, x2, y2) or createShape(LINE, x1, y1, z1, x2, y2, z1)"); - } else if (len != 4) { - throw new IllegalArgumentException("Use createShape(LINE, x1, y1, x2, y2)"); - } - return createShapePrimitive(kind, p); - - } else if (kind == TRIANGLE) { - if (len != 6) { - throw new IllegalArgumentException("Use createShape(TRIANGLE, x1, y1, x2, y2, x3, y3)"); - } - return createShapePrimitive(kind, p); - - } else if (kind == QUAD) { - if (len != 8) { - throw new IllegalArgumentException("Use createShape(QUAD, x1, y1, x2, y2, x3, y3, x4, y4)"); - } - return createShapePrimitive(kind, p); - - } else if (kind == RECT) { - if (len != 4 && len != 5 && len != 8 && len != 9) { - throw new IllegalArgumentException("Wrong number of parameters for createShape(RECT), see the reference"); - } - return createShapePrimitive(kind, p); - - } else if (kind == ELLIPSE) { - if (len != 4 && len != 5) { - throw new IllegalArgumentException("Use createShape(ELLIPSE, x, y, w, h) or createShape(ELLIPSE, x, y, w, h, mode)"); - } - return createShapePrimitive(kind, p); - - } else if (kind == ARC) { - if (len != 6 && len != 7) { - throw new IllegalArgumentException("Use createShape(ARC, x, y, w, h, start, stop)"); - } - return createShapePrimitive(kind, p); - - } else if (kind == BOX) { - if (!is3D()) { - throw new IllegalArgumentException("createShape(BOX) is not supported in 2D"); - } else if (len != 1 && len != 3) { - throw new IllegalArgumentException("Use createShape(BOX, size) or createShape(BOX, width, height, depth)"); - } - return createShapePrimitive(kind, p); - - } else if (kind == SPHERE) { - if (!is3D()) { - throw new IllegalArgumentException("createShape(SPHERE) is not supported in 2D"); - } else if (len != 1) { - throw new IllegalArgumentException("Use createShape(SPHERE, radius)"); - } - return createShapePrimitive(kind, p); - } - throw new IllegalArgumentException("Unknown shape type passed to createShape()"); - } - - - /** Override this to have a custom shape object used by your renderer. */ - protected PShape createShapePrimitive(int kind, float... p) { -// showMethodWarning("createShape()"); -// return null; - return new PShape(this, kind, p); - } - - - ////////////////////////////////////////////////////////////// - - // SHADERS - - - public PShader loadShader(String fragFilename) { - showMissingWarning("loadShader"); - return null; - } - - - public PShader loadShader(String fragFilename, String vertFilename) { - showMissingWarning("loadShader"); - return null; - } - - - public void shader(PShader shader) { - showMissingWarning("shader"); - } - - - public void shader(PShader shader, int kind) { - showMissingWarning("shader"); - } - - - public void resetShader() { - showMissingWarning("resetShader"); - } - - - public void resetShader(int kind) { - showMissingWarning("resetShader"); - } - - - public PShader getShader(int kind) { - showMissingWarning("getShader"); - return null; - } - - - public void filter(PShader shader) { - showMissingWarning("filter"); - } - - - - ////////////////////////////////////////////////////////////// - - // CURVE/BEZIER VERTEX HANDLING - - - protected void bezierVertexCheck() { - bezierVertexCheck(shape, vertexCount); - } - - - protected void bezierVertexCheck(int shape, int vertexCount) { - if (shape == 0 || shape != POLYGON) { - throw new RuntimeException("beginShape() or beginShape(POLYGON) " + - "must be used before bezierVertex() or quadraticVertex()"); - } - if (vertexCount == 0) { - throw new RuntimeException("vertex() must be used at least once" + - "before bezierVertex() or quadraticVertex()"); - } - } - - - public void bezierVertex(float x2, float y2, - float x3, float y3, - float x4, float y4) { - bezierInitCheck(); - bezierVertexCheck(); - PMatrix3D draw = bezierDrawMatrix; - - float[] prev = vertices[vertexCount-1]; - float x1 = prev[X]; - float y1 = prev[Y]; - - float xplot1 = draw.m10*x1 + draw.m11*x2 + draw.m12*x3 + draw.m13*x4; - float xplot2 = draw.m20*x1 + draw.m21*x2 + draw.m22*x3 + draw.m23*x4; - float xplot3 = draw.m30*x1 + draw.m31*x2 + draw.m32*x3 + draw.m33*x4; - - float yplot1 = draw.m10*y1 + draw.m11*y2 + draw.m12*y3 + draw.m13*y4; - float yplot2 = draw.m20*y1 + draw.m21*y2 + draw.m22*y3 + draw.m23*y4; - float yplot3 = draw.m30*y1 + draw.m31*y2 + draw.m32*y3 + draw.m33*y4; - - for (int j = 0; j < bezierDetail; j++) { - x1 += xplot1; xplot1 += xplot2; xplot2 += xplot3; - y1 += yplot1; yplot1 += yplot2; yplot2 += yplot3; - vertex(x1, y1); - } - } - - - public void bezierVertex(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - bezierInitCheck(); - bezierVertexCheck(); - PMatrix3D draw = bezierDrawMatrix; - - float[] prev = vertices[vertexCount-1]; - float x1 = prev[X]; - float y1 = prev[Y]; - float z1 = prev[Z]; - - float xplot1 = draw.m10*x1 + draw.m11*x2 + draw.m12*x3 + draw.m13*x4; - float xplot2 = draw.m20*x1 + draw.m21*x2 + draw.m22*x3 + draw.m23*x4; - float xplot3 = draw.m30*x1 + draw.m31*x2 + draw.m32*x3 + draw.m33*x4; - - float yplot1 = draw.m10*y1 + draw.m11*y2 + draw.m12*y3 + draw.m13*y4; - float yplot2 = draw.m20*y1 + draw.m21*y2 + draw.m22*y3 + draw.m23*y4; - float yplot3 = draw.m30*y1 + draw.m31*y2 + draw.m32*y3 + draw.m33*y4; - - float zplot1 = draw.m10*z1 + draw.m11*z2 + draw.m12*z3 + draw.m13*z4; - float zplot2 = draw.m20*z1 + draw.m21*z2 + draw.m22*z3 + draw.m23*z4; - float zplot3 = draw.m30*z1 + draw.m31*z2 + draw.m32*z3 + draw.m33*z4; - - for (int j = 0; j < bezierDetail; j++) { - x1 += xplot1; xplot1 += xplot2; xplot2 += xplot3; - y1 += yplot1; yplot1 += yplot2; yplot2 += yplot3; - z1 += zplot1; zplot1 += zplot2; zplot2 += zplot3; - vertex(x1, y1, z1); - } - } - - - public void quadraticVertex(float cx, float cy, - float x3, float y3) { - bezierVertexCheck(); - float[] prev = vertices[vertexCount-1]; - float x1 = prev[X]; - float y1 = prev[Y]; - - bezierVertex(x1 + ((cx-x1)*2/3.0f), y1 + ((cy-y1)*2/3.0f), - x3 + ((cx-x3)*2/3.0f), y3 + ((cy-y3)*2/3.0f), - x3, y3); - } - - - public void quadraticVertex(float cx, float cy, float cz, - float x3, float y3, float z3) { - bezierVertexCheck(); - float[] prev = vertices[vertexCount-1]; - float x1 = prev[X]; - float y1 = prev[Y]; - float z1 = prev[Z]; - - bezierVertex(x1 + ((cx-x1)*2/3.0f), y1 + ((cy-y1)*2/3.0f), z1 + ((cz-z1)*2/3.0f), - x3 + ((cx-x3)*2/3.0f), y3 + ((cy-y3)*2/3.0f), z3 + ((cz-z3)*2/3.0f), - x3, y3, z3); - } - - - protected void curveVertexCheck() { - curveVertexCheck(shape); - } - - - /** - * Perform initialization specific to curveVertex(), and handle standard - * error modes. Can be overridden by subclasses that need the flexibility. - */ - protected void curveVertexCheck(int shape) { - if (shape != POLYGON) { - throw new RuntimeException("You must use beginShape() or " + - "beginShape(POLYGON) before curveVertex()"); - } - // to improve code init time, allocate on first use. - if (curveVertices == null) { - curveVertices = new float[128][3]; - } - - if (curveVertexCount == curveVertices.length) { - // Can't use PApplet.expand() cuz it doesn't do the copy properly - float[][] temp = new float[curveVertexCount << 1][3]; - System.arraycopy(curveVertices, 0, temp, 0, curveVertexCount); - curveVertices = temp; - } - curveInitCheck(); - } - - - public void curveVertex(float x, float y) { - curveVertexCheck(); - float[] vertex = curveVertices[curveVertexCount]; - vertex[X] = x; - vertex[Y] = y; - curveVertexCount++; - - // draw a segment if there are enough points - if (curveVertexCount > 3) { - curveVertexSegment(curveVertices[curveVertexCount-4][X], - curveVertices[curveVertexCount-4][Y], - curveVertices[curveVertexCount-3][X], - curveVertices[curveVertexCount-3][Y], - curveVertices[curveVertexCount-2][X], - curveVertices[curveVertexCount-2][Y], - curveVertices[curveVertexCount-1][X], - curveVertices[curveVertexCount-1][Y]); - } - } - - - public void curveVertex(float x, float y, float z) { - curveVertexCheck(); - float[] vertex = curveVertices[curveVertexCount]; - vertex[X] = x; - vertex[Y] = y; - vertex[Z] = z; - curveVertexCount++; - - // draw a segment if there are enough points - if (curveVertexCount > 3) { - curveVertexSegment(curveVertices[curveVertexCount-4][X], - curveVertices[curveVertexCount-4][Y], - curveVertices[curveVertexCount-4][Z], - curveVertices[curveVertexCount-3][X], - curveVertices[curveVertexCount-3][Y], - curveVertices[curveVertexCount-3][Z], - curveVertices[curveVertexCount-2][X], - curveVertices[curveVertexCount-2][Y], - curveVertices[curveVertexCount-2][Z], - curveVertices[curveVertexCount-1][X], - curveVertices[curveVertexCount-1][Y], - curveVertices[curveVertexCount-1][Z]); - } - } - - - /** - * Handle emitting a specific segment of Catmull-Rom curve. This can be - * overridden by subclasses that need more efficient rendering options. - */ - protected void curveVertexSegment(float x1, float y1, - float x2, float y2, - float x3, float y3, - float x4, float y4) { - float x0 = x2; - float y0 = y2; - - PMatrix3D draw = curveDrawMatrix; - - float xplot1 = draw.m10*x1 + draw.m11*x2 + draw.m12*x3 + draw.m13*x4; - float xplot2 = draw.m20*x1 + draw.m21*x2 + draw.m22*x3 + draw.m23*x4; - float xplot3 = draw.m30*x1 + draw.m31*x2 + draw.m32*x3 + draw.m33*x4; - - float yplot1 = draw.m10*y1 + draw.m11*y2 + draw.m12*y3 + draw.m13*y4; - float yplot2 = draw.m20*y1 + draw.m21*y2 + draw.m22*y3 + draw.m23*y4; - float yplot3 = draw.m30*y1 + draw.m31*y2 + draw.m32*y3 + draw.m33*y4; - - // vertex() will reset splineVertexCount, so save it - int savedCount = curveVertexCount; - - vertex(x0, y0); - for (int j = 0; j < curveDetail; j++) { - x0 += xplot1; xplot1 += xplot2; xplot2 += xplot3; - y0 += yplot1; yplot1 += yplot2; yplot2 += yplot3; - vertex(x0, y0); - } - curveVertexCount = savedCount; - } - - - /** - * Handle emitting a specific segment of Catmull-Rom curve. This can be - * overridden by subclasses that need more efficient rendering options. - */ - protected void curveVertexSegment(float x1, float y1, float z1, - float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - float x0 = x2; - float y0 = y2; - float z0 = z2; - - PMatrix3D draw = curveDrawMatrix; - - float xplot1 = draw.m10*x1 + draw.m11*x2 + draw.m12*x3 + draw.m13*x4; - float xplot2 = draw.m20*x1 + draw.m21*x2 + draw.m22*x3 + draw.m23*x4; - float xplot3 = draw.m30*x1 + draw.m31*x2 + draw.m32*x3 + draw.m33*x4; - - float yplot1 = draw.m10*y1 + draw.m11*y2 + draw.m12*y3 + draw.m13*y4; - float yplot2 = draw.m20*y1 + draw.m21*y2 + draw.m22*y3 + draw.m23*y4; - float yplot3 = draw.m30*y1 + draw.m31*y2 + draw.m32*y3 + draw.m33*y4; - - // vertex() will reset splineVertexCount, so save it - int savedCount = curveVertexCount; - - float zplot1 = draw.m10*z1 + draw.m11*z2 + draw.m12*z3 + draw.m13*z4; - float zplot2 = draw.m20*z1 + draw.m21*z2 + draw.m22*z3 + draw.m23*z4; - float zplot3 = draw.m30*z1 + draw.m31*z2 + draw.m32*z3 + draw.m33*z4; - - vertex(x0, y0, z0); - for (int j = 0; j < curveDetail; j++) { - x0 += xplot1; xplot1 += xplot2; xplot2 += xplot3; - y0 += yplot1; yplot1 += yplot2; yplot2 += yplot3; - z0 += zplot1; zplot1 += zplot2; zplot2 += zplot3; - vertex(x0, y0, z0); - } - curveVertexCount = savedCount; - } - - - - ////////////////////////////////////////////////////////////// - - // SIMPLE SHAPES WITH ANALOGUES IN beginShape() - - - public void point(float x, float y) { - beginShape(POINTS); - vertex(x, y); - endShape(); - } - - - public void point(float x, float y, float z) { - beginShape(POINTS); - vertex(x, y, z); - endShape(); - } - - - public void line(float x1, float y1, float x2, float y2) { - beginShape(LINES); - vertex(x1, y1); - vertex(x2, y2); - endShape(); - } - - - public void line(float x1, float y1, float z1, - float x2, float y2, float z2) { - beginShape(LINES); - vertex(x1, y1, z1); - vertex(x2, y2, z2); - endShape(); - } - - - public void triangle(float x1, float y1, float x2, float y2, - float x3, float y3) { - beginShape(TRIANGLES); - vertex(x1, y1); - vertex(x2, y2); - vertex(x3, y3); - endShape(); - } - - - public void quad(float x1, float y1, float x2, float y2, - float x3, float y3, float x4, float y4) { - beginShape(QUADS); - vertex(x1, y1); - vertex(x2, y2); - vertex(x3, y3); - vertex(x4, y4); - endShape(); - } - - - - ////////////////////////////////////////////////////////////// - - // RECT - - - public void rectMode(int mode) { - rectMode = mode; - } - - - public void rect(float a, float b, float c, float d) { - float hradius, vradius; - switch (rectMode) { - case CORNERS: - break; - case CORNER: - c += a; d += b; - break; - case RADIUS: - hradius = c; - vradius = d; - c = a + hradius; - d = b + vradius; - a -= hradius; - b -= vradius; - break; - case CENTER: - hradius = c / 2.0f; - vradius = d / 2.0f; - c = a + hradius; - d = b + vradius; - a -= hradius; - b -= vradius; - } - - if (a > c) { - float temp = a; a = c; c = temp; - } - - if (b > d) { - float temp = b; b = d; d = temp; - } - - rectImpl(a, b, c, d); - } - - - protected void rectImpl(float x1, float y1, float x2, float y2) { - quad(x1, y1, x2, y1, x2, y2, x1, y2); - } - - - public void rect(float a, float b, float c, float d, float r) { - rect(a, b, c, d, r, r, r, r); - } - - - public void rect(float a, float b, float c, float d, - float tl, float tr, float br, float bl) { - float hradius, vradius; - switch (rectMode) { - case CORNERS: - break; - case CORNER: - c += a; d += b; - break; - case RADIUS: - hradius = c; - vradius = d; - c = a + hradius; - d = b + vradius; - a -= hradius; - b -= vradius; - break; - case CENTER: - hradius = c / 2.0f; - vradius = d / 2.0f; - c = a + hradius; - d = b + vradius; - a -= hradius; - b -= vradius; - } - - if (a > c) { - float temp = a; a = c; c = temp; - } - - if (b > d) { - float temp = b; b = d; d = temp; - } - - float maxRounding = PApplet.min((c - a) / 2, (d - b) / 2); - if (tl > maxRounding) tl = maxRounding; - if (tr > maxRounding) tr = maxRounding; - if (br > maxRounding) br = maxRounding; - if (bl > maxRounding) bl = maxRounding; - - rectImpl(a, b, c, d, tl, tr, br, bl); - } - - - protected void rectImpl(float x1, float y1, float x2, float y2, - float tl, float tr, float br, float bl) { - beginShape(); -// vertex(x1+tl, y1); - if (tr != 0) { - vertex(x2-tr, y1); - quadraticVertex(x2, y1, x2, y1+tr); - } else { - vertex(x2, y1); - } - if (br != 0) { - vertex(x2, y2-br); - quadraticVertex(x2, y2, x2-br, y2); - } else { - vertex(x2, y2); - } - if (bl != 0) { - vertex(x1+bl, y2); - quadraticVertex(x1, y2, x1, y2-bl); - } else { - vertex(x1, y2); - } - if (tl != 0) { - vertex(x1, y1+tl); - quadraticVertex(x1, y1, x1+tl, y1); - } else { - vertex(x1, y1); - } -// endShape(); - endShape(CLOSE); - } - - - public void square(float x, float y, float extent) { - rect(x, y, extent, extent); - } - - - ////////////////////////////////////////////////////////////// - - // ELLIPSE AND ARC - - - public void ellipseMode(int mode) { - ellipseMode = mode; - } - - - public void ellipse(float a, float b, float c, float d) { - float x = a; - float y = b; - float w = c; - float h = d; - - if (ellipseMode == CORNERS) { - w = c - a; - h = d - b; - - } else if (ellipseMode == RADIUS) { - x = a - c; - y = b - d; - w = c * 2; - h = d * 2; - - } else if (ellipseMode == DIAMETER) { - x = a - c/2f; - y = b - d/2f; - } - - if (w < 0) { // undo negative width - x += w; - w = -w; - } - - if (h < 0) { // undo negative height - y += h; - h = -h; - } - - ellipseImpl(x, y, w, h); - } - - - protected void ellipseImpl(float x, float y, float w, float h) { - } - - - /** - * Identical parameters and placement to ellipse, - * but draws only an arc of that ellipse. - *

      - * start and stop are always radians because angleMode() was goofy. - * ellipseMode() sets the placement. - *

      - * also tries to be smart about start < stop. - */ - public void arc(float a, float b, float c, float d, - float start, float stop) { - arc(a, b, c, d, start, stop, 0); - } - - - public void arc(float a, float b, float c, float d, - float start, float stop, int mode) { - float x = a; - float y = b; - float w = c; - float h = d; - - if (ellipseMode == CORNERS) { - w = c - a; - h = d - b; - - } else if (ellipseMode == RADIUS) { - x = a - c; - y = b - d; - w = c * 2; - h = d * 2; - - } else if (ellipseMode == CENTER) { - x = a - c/2f; - y = b - d/2f; - } - - // make sure the loop will exit before starting while - if (!Float.isInfinite(start) && !Float.isInfinite(stop)) { - // ignore equal and degenerate cases - if (stop > start) { - // make sure that we're starting at a useful point - while (start < 0) { - start += TWO_PI; - stop += TWO_PI; - } - - if (stop - start > TWO_PI) { - start = 0; - stop = TWO_PI; - } - arcImpl(x, y, w, h, start, stop, mode); - } - } - } - - - /** - * Start and stop are in radians, converted by the parent function. - * Note that the radians can be greater (or less) than TWO_PI. - * This is so that an arc can be drawn that crosses zero mark, - * and the user will still collect $200. - */ - protected void arcImpl(float x, float y, float w, float h, - float start, float stop, int mode) { - showMissingWarning("arc"); - } - - - public void circle(float x, float y, float extent) { - ellipse(x, y, extent, extent); - } - - - ////////////////////////////////////////////////////////////// - - // BOX - - - public void box(float size) { - box(size, size, size); - } - - - // TODO not the least bit efficient, it even redraws lines - // along the vertices. ugly ugly ugly! - public void box(float w, float h, float d) { - float x1 = -w/2f; float x2 = w/2f; - float y1 = -h/2f; float y2 = h/2f; - float z1 = -d/2f; float z2 = d/2f; - - beginShape(QUADS); - - // front - normal(0, 0, 1); - vertex(x1, y1, z1); - vertex(x2, y1, z1); - vertex(x2, y2, z1); - vertex(x1, y2, z1); - - // right - normal(1, 0, 0); - vertex(x2, y1, z1); - vertex(x2, y1, z2); - vertex(x2, y2, z2); - vertex(x2, y2, z1); - - // back - normal(0, 0, -1); - vertex(x2, y1, z2); - vertex(x1, y1, z2); - vertex(x1, y2, z2); - vertex(x2, y2, z2); - - // left - normal(-1, 0, 0); - vertex(x1, y1, z2); - vertex(x1, y1, z1); - vertex(x1, y2, z1); - vertex(x1, y2, z2); - - // top - normal(0, 1, 0); - vertex(x1, y1, z2); - vertex(x2, y1, z2); - vertex(x2, y1, z1); - vertex(x1, y1, z1); - - // bottom - normal(0, -1, 0); - vertex(x1, y2, z1); - vertex(x2, y2, z1); - vertex(x2, y2, z2); - vertex(x1, y2, z2); - - endShape(); - } - - - - ////////////////////////////////////////////////////////////// - - // SPHERE - - - public void sphereDetail(int res) { - sphereDetail(res, res); - } - - - /** - * Set the detail level for approximating a sphere. The ures and vres params - * control the horizontal and vertical resolution. - * - * Code for sphereDetail() submitted by toxi [031031]. - * Code for enhanced u/v version from davbol [080801]. - */ - public void sphereDetail(int ures, int vres) { - if (ures < 3) ures = 3; // force a minimum res - if (vres < 2) vres = 2; // force a minimum res - if ((ures == sphereDetailU) && (vres == sphereDetailV)) return; - - float delta = (float)SINCOS_LENGTH/ures; - float[] cx = new float[ures]; - float[] cz = new float[ures]; - // calc unit circle in XZ plane - for (int i = 0; i < ures; i++) { - cx[i] = cosLUT[(int) (i*delta) % SINCOS_LENGTH]; - cz[i] = sinLUT[(int) (i*delta) % SINCOS_LENGTH]; - } - // computing vertexlist - // vertexlist starts at south pole - int vertCount = ures * (vres-1) + 2; - int currVert = 0; - - // re-init arrays to store vertices - sphereX = new float[vertCount]; - sphereY = new float[vertCount]; - sphereZ = new float[vertCount]; - - float angle_step = (SINCOS_LENGTH*0.5f)/vres; - float angle = angle_step; - - // step along Y axis - for (int i = 1; i < vres; i++) { - float curradius = sinLUT[(int) angle % SINCOS_LENGTH]; - float currY = cosLUT[(int) angle % SINCOS_LENGTH]; - for (int j = 0; j < ures; j++) { - sphereX[currVert] = cx[j] * curradius; - sphereY[currVert] = currY; - sphereZ[currVert++] = cz[j] * curradius; - } - angle += angle_step; - } - sphereDetailU = ures; - sphereDetailV = vres; - } - - - /** - * Draw a sphere with radius r centered at coordinate 0, 0, 0. - *

      - * Implementation notes: - *

      - * cache all the points of the sphere in a static array - * top and bottom are just a bunch of triangles that land - * in the center point - *

      - * sphere is a series of concentric circles who radii vary - * along the shape, based on, er.. cos or something - *

      -   * [toxi 031031] new sphere code. removed all multiplies with
      -   * radius, as scale() will take care of that anyway
      -   *
      -   * [toxi 031223] updated sphere code (removed modulos)
      -   * and introduced sphereAt(x,y,z,r)
      -   * to avoid additional translate()'s on the user/sketch side
      -   *
      -   * [davbol 080801] now using separate sphereDetailU/V
      -   * 
      - */ - public void sphere(float r) { - if ((sphereDetailU < 3) || (sphereDetailV < 2)) { - sphereDetail(30); - } - - edge(false); - - // 1st ring from south pole - beginShape(TRIANGLE_STRIP); - for (int i = 0; i < sphereDetailU; i++) { - normal(0, -1, 0); - vertex(0, -r, 0); - normal(sphereX[i], sphereY[i], sphereZ[i]); - vertex(r * sphereX[i], r * sphereY[i], r * sphereZ[i]); - } - normal(0, -r, 0); - vertex(0, -r, 0); - normal(sphereX[0], sphereY[0], sphereZ[0]); - vertex(r * sphereX[0], r * sphereY[0], r * sphereZ[0]); - endShape(); - - int v1,v11,v2; - - // middle rings - int voff = 0; - for (int i = 2; i < sphereDetailV; i++) { - v1 = v11 = voff; - voff += sphereDetailU; - v2 = voff; - beginShape(TRIANGLE_STRIP); - for (int j = 0; j < sphereDetailU; j++) { - normal(sphereX[v1], sphereY[v1], sphereZ[v1]); - vertex(r * sphereX[v1], r * sphereY[v1], r * sphereZ[v1++]); - normal(sphereX[v2], sphereY[v2], sphereZ[v2]); - vertex(r * sphereX[v2], r * sphereY[v2], r * sphereZ[v2++]); - } - // close each ring - v1 = v11; - v2 = voff; - normal(sphereX[v1], sphereY[v1], sphereZ[v1]); - vertex(r * sphereX[v1], r * sphereY[v1], r * sphereZ[v1]); - normal(sphereX[v2], sphereY[v2], sphereZ[v2]); - vertex(r * sphereX[v2], r * sphereY[v2], r * sphereZ[v2]); - endShape(); - } - - // add the northern cap - beginShape(TRIANGLE_STRIP); - for (int i = 0; i < sphereDetailU; i++) { - v2 = voff + i; - normal(sphereX[v2], sphereY[v2], sphereZ[v2]); - vertex(r * sphereX[v2], r * sphereY[v2], r * sphereZ[v2]); - normal(0, 1, 0); - vertex(0, r, 0); - } - normal(sphereX[voff], sphereY[voff], sphereZ[voff]); - vertex(r * sphereX[voff], r * sphereY[voff], r * sphereZ[voff]); - normal(0, 1, 0); - vertex(0, r, 0); - endShape(); - - edge(true); - } - - - - ////////////////////////////////////////////////////////////// - - // BEZIER - - - /** - * Evalutes quadratic bezier at point t for points a, b, c, d. - * t varies between 0 and 1, and a and d are the on curve points, - * b and c are the control points. this can be done once with the - * x coordinates and a second time with the y coordinates to get - * the location of a bezier curve at t. - *

      - * For instance, to convert the following example:

      -   * stroke(255, 102, 0);
      -   * line(85, 20, 10, 10);
      -   * line(90, 90, 15, 80);
      -   * stroke(0, 0, 0);
      -   * bezier(85, 20, 10, 10, 90, 90, 15, 80);
      -   *
      -   * // draw it in gray, using 10 steps instead of the default 20
      -   * // this is a slower way to do it, but useful if you need
      -   * // to do things with the coordinates at each step
      -   * stroke(128);
      -   * beginShape(LINE_STRIP);
      -   * for (int i = 0; i <= 10; i++) {
      -   *   float t = i / 10.0f;
      -   *   float x = bezierPoint(85, 10, 90, 15, t);
      -   *   float y = bezierPoint(20, 10, 90, 80, t);
      -   *   vertex(x, y);
      -   * }
      -   * endShape();
      - */ - public float bezierPoint(float a, float b, float c, float d, float t) { - float t1 = t-1.0f; - return t * ( 3*t1*(b*t1-c*t) + d*t*t ) - a*t1*t1*t1; - } - - /** - * Provide the tangent at the given point on the bezier curve. - * Fix from davbol for 0136. - */ - public float bezierTangent(float a, float b, float c, float d, float t) { - return (3*t*t * (-a+3*b-3*c+d) + - 6*t * (a-2*b+c) + - 3 * (-a+b)); - } - - - protected void bezierInitCheck() { - if (!bezierInited) { - bezierInit(); - } - } - - - protected void bezierInit() { - // overkill to be broken out, but better parity with the curve stuff below - bezierDetail(bezierDetail); - bezierInited = true; - } - - - public void bezierDetail(int detail) { - bezierDetail = detail; - - if (bezierDrawMatrix == null) { - bezierDrawMatrix = new PMatrix3D(); - } - - // setup matrix for forward differencing to speed up drawing - splineForward(detail, bezierDrawMatrix); - - // multiply the basis and forward diff matrices together - // saves much time since this needn't be done for each curve - //mult_spline_matrix(bezierForwardMatrix, bezier_basis, bezierDrawMatrix, 4); - //bezierDrawMatrix.set(bezierForwardMatrix); - bezierDrawMatrix.apply(bezierBasisMatrix); - } - - - /** - * Draw a cubic bezier curve. The first and last points are - * the on-curve points. The middle two are the 'control' points, - * or 'handles' in an application like Illustrator. - *

      - * Identical to typing: - *

      beginShape();
      -   * vertex(x1, y1);
      -   * bezierVertex(x2, y2, x3, y3, x4, y4);
      -   * endShape();
      -   * 
      - * In Postscript-speak, this would be: - *
      moveto(x1, y1);
      -   * curveto(x2, y2, x3, y3, x4, y4);
      - * If you were to try and continue that curve like so: - *
      curveto(x5, y5, x6, y6, x7, y7);
      - * This would be done in processing by adding these statements: - *
      bezierVertex(x5, y5, x6, y6, x7, y7)
      -   * 
      - * To draw a quadratic (instead of cubic) curve, - * use the control point twice by doubling it: - *
      bezier(x1, y1, cx, cy, cx, cy, x2, y2);
      - */ - public void bezier(float x1, float y1, - float x2, float y2, - float x3, float y3, - float x4, float y4) { - beginShape(); - vertex(x1, y1); - bezierVertex(x2, y2, x3, y3, x4, y4); - endShape(); - } - - - public void bezier(float x1, float y1, float z1, - float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - beginShape(); - vertex(x1, y1, z1); - bezierVertex(x2, y2, z2, - x3, y3, z3, - x4, y4, z4); - endShape(); - } - - - - ////////////////////////////////////////////////////////////// - - // CATMULL-ROM CURVE - - - /** - * Get a location along a catmull-rom curve segment. - * - * @param t Value between zero and one for how far along the segment - */ - public float curvePoint(float a, float b, float c, float d, float t) { - curveInitCheck(); - - float tt = t * t; - float ttt = t * tt; - PMatrix3D cb = curveBasisMatrix; - - // not optimized (and probably need not be) - return (a * (ttt*cb.m00 + tt*cb.m10 + t*cb.m20 + cb.m30) + - b * (ttt*cb.m01 + tt*cb.m11 + t*cb.m21 + cb.m31) + - c * (ttt*cb.m02 + tt*cb.m12 + t*cb.m22 + cb.m32) + - d * (ttt*cb.m03 + tt*cb.m13 + t*cb.m23 + cb.m33)); - } - - - /** - * Calculate the tangent at a t value (0..1) on a Catmull-Rom curve. - * Code thanks to Dave Bollinger (Bug #715) - */ - public float curveTangent(float a, float b, float c, float d, float t) { - curveInitCheck(); - - float tt3 = t * t * 3; - float t2 = t * 2; - PMatrix3D cb = curveBasisMatrix; - - // not optimized (and probably need not be) - return (a * (tt3*cb.m00 + t2*cb.m10 + cb.m20) + - b * (tt3*cb.m01 + t2*cb.m11 + cb.m21) + - c * (tt3*cb.m02 + t2*cb.m12 + cb.m22) + - d * (tt3*cb.m03 + t2*cb.m13 + cb.m23) ); - } - - - public void curveDetail(int detail) { - curveDetail = detail; - curveInit(); - } - - - public void curveTightness(float tightness) { - curveTightness = tightness; - curveInit(); - } - - - protected void curveInitCheck() { - if (!curveInited) { - curveInit(); - } - } - - - /** - * Set the number of segments to use when drawing a Catmull-Rom - * curve, and setting the s parameter, which defines how tightly - * the curve fits to each vertex. Catmull-Rom curves are actually - * a subset of this curve type where the s is set to zero. - *

      - * (This function is not optimized, since it's not expected to - * be called all that often. there are many juicy and obvious - * opimizations in here, but it's probably better to keep the - * code more readable) - */ - protected void curveInit() { - // allocate only if/when used to save startup time - if (curveDrawMatrix == null) { - curveBasisMatrix = new PMatrix3D(); - curveDrawMatrix = new PMatrix3D(); - curveInited = true; - } - - float s = curveTightness; - curveBasisMatrix.set((s-1)/2f, (s+3)/2f, (-3-s)/2f, (1-s)/2f, - (1-s), (-5-s)/2f, (s+2), (s-1)/2f, - (s-1)/2f, 0, (1-s)/2f, 0, - 0, 1, 0, 0); - - //setup_spline_forward(segments, curveForwardMatrix); - splineForward(curveDetail, curveDrawMatrix); - - if (bezierBasisInverse == null) { - bezierBasisInverse = bezierBasisMatrix.get(); - bezierBasisInverse.invert(); - curveToBezierMatrix = new PMatrix3D(); - } - - // TODO only needed for PGraphicsJava2D? if so, move it there - // actually, it's generally useful for other renderers, so keep it - // or hide the implementation elsewhere. - curveToBezierMatrix.set(curveBasisMatrix); - curveToBezierMatrix.preApply(bezierBasisInverse); - - // multiply the basis and forward diff matrices together - // saves much time since this needn't be done for each curve - curveDrawMatrix.apply(curveBasisMatrix); - } - - - /** - * Draws a segment of Catmull-Rom curve. - *

      - * As of 0070, this function no longer doubles the first and - * last points. The curves are a bit more boring, but it's more - * mathematically correct, and properly mirrored in curvePoint(). - *

      - * Identical to typing out:

      -   * beginShape();
      -   * curveVertex(x1, y1);
      -   * curveVertex(x2, y2);
      -   * curveVertex(x3, y3);
      -   * curveVertex(x4, y4);
      -   * endShape();
      -   * 
      - */ - public void curve(float x1, float y1, - float x2, float y2, - float x3, float y3, - float x4, float y4) { - beginShape(); - curveVertex(x1, y1); - curveVertex(x2, y2); - curveVertex(x3, y3); - curveVertex(x4, y4); - endShape(); - } - - - public void curve(float x1, float y1, float z1, - float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - beginShape(); - curveVertex(x1, y1, z1); - curveVertex(x2, y2, z2); - curveVertex(x3, y3, z3); - curveVertex(x4, y4, z4); - endShape(); - } - - - - ////////////////////////////////////////////////////////////// - - // SPLINE UTILITY FUNCTIONS (used by both Bezier and Catmull-Rom) - - - /** - * Setup forward-differencing matrix to be used for speedy - * curve rendering. It's based on using a specific number - * of curve segments and just doing incremental adds for each - * vertex of the segment, rather than running the mathematically - * expensive cubic equation. - * @param segments number of curve segments to use when drawing - * @param matrix target object for the new matrix - */ - protected void splineForward(int segments, PMatrix3D matrix) { - float f = 1.0f / segments; - float ff = f * f; - float fff = ff * f; - - matrix.set(0, 0, 0, 1, - fff, ff, f, 0, - 6*fff, 2*ff, 0, 0, - 6*fff, 0, 0, 0); - } - - - - ////////////////////////////////////////////////////////////// - - // SMOOTHING - - - public void smooth() { // ignore - smooth(1); - } - - - public void smooth(int quality) { // ignore - if (primaryGraphics) { - parent.smooth(quality); - } else { - // for createGraphics(), make sure beginDraw() not called yet - if (settingsInited) { - // ignore if it's just a repeat of the current state - if (this.smooth != quality) { - smoothWarning("smooth"); - } - } else { - this.smooth = quality; - } - } - } - - - public void noSmooth() { // ignore - smooth(0); - } - - - private void smoothWarning(String method) { - PGraphics.showWarning("%s() can only be used before beginDraw()", method); - } - - - ////////////////////////////////////////////////////////////// - - // IMAGE - - - /** - * The mode can only be set to CORNERS, CORNER, and CENTER. - *

      - * Support for CENTER was added in release 0146. - */ - public void imageMode(int mode) { - if ((mode == CORNER) || (mode == CORNERS) || (mode == CENTER)) { - imageMode = mode; - } else { - String msg = - "imageMode() only works with CORNER, CORNERS, or CENTER"; - throw new RuntimeException(msg); - } - } - - - public void image(PImage image, float x, float y) { - // Starting in release 0144, image errors are simply ignored. - // loadImageAsync() sets width and height to -1 when loading fails. - if (image.width == -1 || image.height == -1) return; - - // If not loaded yet, don't try to draw - if (image.width == 0 || image.height == 0) return; - - if (imageMode == CORNER || imageMode == CORNERS) { - imageImpl(image, - x, y, x+image.width, y+image.height, - 0, 0, image.width, image.height); - - } else if (imageMode == CENTER) { - float x1 = x - image.width/2; - float y1 = y - image.height/2; - imageImpl(image, - x1, y1, x1+image.width, y1+image.height, - 0, 0, image.width, image.height); - } - } - - - public void image(PImage image, float x, float y, float c, float d) { - image(image, x, y, c, d, 0, 0, image.width, image.height); - } - - - /** - * Draw an image(), also specifying u/v coordinates. - * In this method, the u, v coordinates are always based on image space - * location, regardless of the current textureMode(). - */ - public void image(PImage image, - float a, float b, float c, float d, - int u1, int v1, int u2, int v2) { - // Starting in release 0144, image errors are simply ignored. - // loadImageAsync() sets width and height to -1 when loading fails. - if (image.width == -1 || image.height == -1) return; - - if (imageMode == CORNER) { - if (c < 0) { // reset a negative width - a += c; c = -c; - } - if (d < 0) { // reset a negative height - b += d; d = -d; - } - - imageImpl(image, - a, b, a + c, b + d, - u1, v1, u2, v2); - - } else if (imageMode == CORNERS) { - if (c < a) { // reverse because x2 < x1 - float temp = a; a = c; c = temp; - } - if (d < b) { // reverse because y2 < y1 - float temp = b; b = d; d = temp; - } - - imageImpl(image, - a, b, c, d, - u1, v1, u2, v2); - - } else if (imageMode == CENTER) { - // c and d are width/height - if (c < 0) c = -c; - if (d < 0) d = -d; - float x1 = a - c/2; - float y1 = b - d/2; - - imageImpl(image, - x1, y1, x1 + c, y1 + d, - u1, v1, u2, v2); - } - } - - - /** - * Expects x1, y1, x2, y2 coordinates where (x2 >= x1) and (y2 >= y1). - * If tint() has been called, the image will be colored. - *

      - * The default implementation draws an image as a textured quad. - * The (u, v) coordinates are in image space (they're ints, after all..) - */ - protected void imageImpl(PImage image, - float x1, float y1, float x2, float y2, - int u1, int v1, int u2, int v2) { - boolean savedStroke = stroke; - boolean savedFill = fill; - int savedTextureMode = textureMode; - - stroke = false; - fill = true; - textureMode = IMAGE; - - float savedFillR = fillR; - float savedFillG = fillG; - float savedFillB = fillB; - float savedFillA = fillA; - - if (tint) { - fillR = tintR; - fillG = tintG; - fillB = tintB; - fillA = tintA; - - } else { - fillR = 1; - fillG = 1; - fillB = 1; - fillA = 1; - } - - beginShape(QUADS); - texture(image); - vertex(x1, y1, u1, v1); - vertex(x1, y2, u1, v2); - vertex(x2, y2, u2, v2); - vertex(x2, y1, u2, v1); - endShape(); - - stroke = savedStroke; - fill = savedFill; - textureMode = savedTextureMode; - - fillR = savedFillR; - fillG = savedFillG; - fillB = savedFillB; - fillA = savedFillA; - } - - - ////////////////////////////////////////////////////////////// - - // SHAPE - - - /** - * Set the orientation for the shape() command (like imageMode() or rectMode()). - * @param mode Either CORNER, CORNERS, or CENTER. - */ - public void shapeMode(int mode) { - this.shapeMode = mode; - } - - - public void shape(PShape shape) { - if (shape.isVisible()) { // don't do expensive matrix ops if invisible - if (shapeMode == CENTER) { - pushMatrix(); - translate(-shape.getWidth()/2, -shape.getHeight()/2); - } - - shape.draw(this); // needs to handle recorder too - - if (shapeMode == CENTER) { - popMatrix(); - } - } - } - - - /** - * Convenience method to draw at a particular location. - */ - public void shape(PShape shape, float x, float y) { - if (shape.isVisible()) { // don't do expensive matrix ops if invisible - pushMatrix(); - - if (shapeMode == CENTER) { - translate(x - shape.getWidth()/2, y - shape.getHeight()/2); - - } else if ((shapeMode == CORNER) || (shapeMode == CORNERS)) { - translate(x, y); - } - shape.draw(this); - - popMatrix(); - } - } - - - // TODO unapproved - protected void shape(PShape shape, float x, float y, float z) { - showMissingWarning("shape"); - } - - - public void shape(PShape shape, float x, float y, float c, float d) { - if (shape.isVisible()) { // don't do expensive matrix ops if invisible - pushMatrix(); - - if (shapeMode == CENTER) { - // x and y are center, c and d refer to a diameter - translate(x - c/2f, y - d/2f); - scale(c / shape.getWidth(), d / shape.getHeight()); - - } else if (shapeMode == CORNER) { - translate(x, y); - scale(c / shape.getWidth(), d / shape.getHeight()); - - } else if (shapeMode == CORNERS) { - // c and d are x2/y2, make them into width/height - c -= x; - d -= y; - // then same as above - translate(x, y); - scale(c / shape.getWidth(), d / shape.getHeight()); - } - shape.draw(this); - - popMatrix(); - } - } - - - // TODO unapproved - protected void shape(PShape shape, float x, float y, float z, float c, float d, float e) { - showMissingWarning("shape"); - } - - - ////////////////////////////////////////////////////////////// - - // TEXT/FONTS - - - /** - * Sets the alignment of the text to one of LEFT, CENTER, or RIGHT. - * This will also reset the vertical text alignment to BASELINE. - */ - public void textAlign(int align) { - textAlign(align, BASELINE); - } - - - /** - * Sets the horizontal and vertical alignment of the text. The horizontal - * alignment can be one of LEFT, CENTER, or RIGHT. The vertical alignment - * can be TOP, BOTTOM, CENTER, or the BASELINE (the default). - */ - public void textAlign(int alignX, int alignY) { - textAlign = alignX; - textAlignY = alignY; - } - - - /** - * Returns the ascent of the current font at the current size. - * This is a method, rather than a variable inside the PGraphics object - * because it requires calculation. - */ - public float textAscent() { - if (textFont == null) { - defaultFontOrDeath("textAscent"); - } - return textFont.ascent() * textSize; - } - - - /** - * Returns the descent of the current font at the current size. - * This is a method, rather than a variable inside the PGraphics object - * because it requires calculation. - */ - public float textDescent() { - if (textFont == null) { - defaultFontOrDeath("textDescent"); - } - return textFont.descent() * textSize; - } - - - /** - * Sets the current font. The font's size will be the "natural" - * size of this font (the size that was set when using "Create Font"). - * The leading will also be reset. - */ - public void textFont(PFont which) { - if (which == null) { - throw new RuntimeException(ERROR_TEXTFONT_NULL_PFONT); - } - textFontImpl(which, which.getDefaultSize()); - } - - - /** - * Useful function to set the font and size at the same time. - */ - public void textFont(PFont which, float size) { - if (which == null) { - throw new RuntimeException(ERROR_TEXTFONT_NULL_PFONT); - } - // https://github.com/processing/processing/issues/3110 - if (size <= 0) { - // Using System.err instead of showWarning to avoid running out of - // memory with a bunch of textSize() variants (cause of this bug is - // usually something done with map() or in a loop). - System.err.println("textFont: ignoring size " + size + " px:" + - "the text size must be larger than zero"); - size = textSize; - } - textFontImpl(which, size); - } - - - /** - * Called from textFont. Check the validity of args and - * print possible errors to the user before calling this. - * Subclasses will want to override this one. - * - * @param which font to set, not null - * @param size size to set, greater than zero - */ - protected void textFontImpl(PFont which, float size) { - textFont = which; -// if (hints[ENABLE_NATIVE_FONTS]) { -// //if (which.font == null) { -// which.findNative(); -// //} -// } - /* - textFontNative = which.font; - - //textFontNativeMetrics = null; - // changed for rev 0104 for textMode(SHAPE) in opengl - if (textFontNative != null) { - // TODO need a better way to handle this. could use reflection to get - // rid of the warning, but that'd be a little silly. supporting this is - // an artifact of supporting java 1.1, otherwise we'd use getLineMetrics, - // as recommended by the @deprecated flag. - textFontNativeMetrics = - Toolkit.getDefaultToolkit().getFontMetrics(textFontNative); - // The following is what needs to be done, however we need to be able - // to get the actual graphics context where the drawing is happening. - // For instance, parent.getGraphics() doesn't work for OpenGL since - // an OpenGL drawing surface is an embedded component. -// if (parent != null) { -// textFontNativeMetrics = parent.getGraphics().getFontMetrics(textFontNative); -// } - - // float w = font.getStringBounds(text, g2.getFontRenderContext()).getWidth(); - } - */ - - handleTextSize(size); - } - - - /** - * Set the text leading to a specific value. If using a custom - * value for the text leading, you'll have to call textLeading() - * again after any calls to textSize(). - */ - public void textLeading(float leading) { - textLeading = leading; - } - - - /** - * Sets the text rendering/placement to be either SCREEN (direct - * to the screen, exact coordinates, only use the font's original size) - * or MODEL (the default, where text is manipulated by translate() and - * can have a textSize). The text size cannot be set when using - * textMode(SCREEN), because it uses the pixels directly from the font. - */ - public void textMode(int mode) { - // CENTER and MODEL overlap (they're both 3) - if ((mode == LEFT) || (mode == RIGHT)) { - showWarning("Since Processing beta, textMode() is now textAlign()."); - return; - } - if (mode == SCREEN) { - showWarning("textMode(SCREEN) has been removed from Processing 2.0."); - } - - if (textModeCheck(mode)) { - textMode = mode; - } else { - String modeStr = String.valueOf(mode); - switch (mode) { - case MODEL: modeStr = "MODEL"; break; - case SHAPE: modeStr = "SHAPE"; break; - } - showWarning("textMode(" + modeStr + ") is not supported by this renderer."); - } - } - - - protected boolean textModeCheck(int mode) { - return true; - } - - - /** - * Sets the text size, also resets the value for the leading. - */ - public void textSize(float size) { - // https://github.com/processing/processing/issues/3110 - if (size <= 0) { - // Using System.err instead of showWarning to avoid running out of - // memory with a bunch of textSize() variants (cause of this bug is - // usually something done with map() or in a loop). - System.err.println("textSize(" + size + ") ignored: " + - "the text size must be larger than zero"); - return; - } - if (textFont == null) { - defaultFontOrDeath("textSize", size); - } - textSizeImpl(size); - } - - - /** - * Called from textSize() after validating size. Subclasses - * will want to override this one. - * @param size size of the text, greater than zero - */ - protected void textSizeImpl(float size) { - handleTextSize(size); - } - - - /** - * Sets the actual size. Called from textSizeImpl and - * from textFontImpl after setting the font. - * @param size size of the text, greater than zero - */ - protected void handleTextSize(float size) { - textSize = size; - textLeading = (textAscent() + textDescent()) * 1.275f; - } - - - // ........................................................ - - - public float textWidth(char c) { - textWidthBuffer[0] = c; - return textWidthImpl(textWidthBuffer, 0, 1); - } - - - /** - * Return the width of a line of text. If the text has multiple - * lines, this returns the length of the longest line. - */ - public float textWidth(String str) { - if (textFont == null) { - defaultFontOrDeath("textWidth"); - } - - int length = str.length(); - if (length > textWidthBuffer.length) { - textWidthBuffer = new char[length + 10]; - } - str.getChars(0, length, textWidthBuffer, 0); - - float wide = 0; - int index = 0; - int start = 0; - - while (index < length) { - if (textWidthBuffer[index] == '\n') { - wide = Math.max(wide, textWidthImpl(textWidthBuffer, start, index)); - start = index+1; - } - index++; - } - if (start < length) { - wide = Math.max(wide, textWidthImpl(textWidthBuffer, start, index)); - } - return wide; - } - - - public float textWidth(char[] chars, int start, int length) { - return textWidthImpl(chars, start, start + length); - } - - - /** - * Implementation of returning the text width of - * the chars [start, stop) in the buffer. - * Unlike the previous version that was inside PFont, this will - * return the size not of a 1 pixel font, but the actual current size. - */ - protected float textWidthImpl(char buffer[], int start, int stop) { - float wide = 0; - for (int i = start; i < stop; i++) { - // could add kerning here, but it just ain't implemented - wide += textFont.width(buffer[i]) * textSize; - } - return wide; - } - - - // ........................................................ - - -// /** -// * Write text where we just left off. -// */ -// public void text(char c) { -// text(c, textX, textY, textZ); -// } - - - /** - * Draw a single character on screen. - * Extremely slow when used with textMode(SCREEN) and Java 2D, - * because loadPixels has to be called first and updatePixels last. - */ - public void text(char c, float x, float y) { - if (textFont == null) { - defaultFontOrDeath("text"); - } - - if (textAlignY == CENTER) { - y += textAscent() / 2; - } else if (textAlignY == TOP) { - y += textAscent(); - } else if (textAlignY == BOTTOM) { - y -= textDescent(); - //} else if (textAlignY == BASELINE) { - // do nothing - } - - textBuffer[0] = c; - textLineAlignImpl(textBuffer, 0, 1, x, y); - } - - - /** - * Draw a single character on screen (with a z coordinate) - */ - public void text(char c, float x, float y, float z) { -// if ((z != 0) && (textMode == SCREEN)) { -// String msg = "textMode(SCREEN) cannot have a z coordinate"; -// throw new RuntimeException(msg); -// } - - if (z != 0) translate(0, 0, z); // slowness, badness - - text(c, x, y); -// textZ = z; - - if (z != 0) translate(0, 0, -z); - } - - - /** - * Draw a chunk of text. - * Newlines that are \n (Unix newline or linefeed char, ascii 10) - * are honored, but \r (carriage return, Windows and Mac OS) are - * ignored. - */ - public void text(String str, float x, float y) { - if (textFont == null) { - defaultFontOrDeath("text"); - } - - int length = str.length(); - if (length > textBuffer.length) { - textBuffer = new char[length + 10]; - } - str.getChars(0, length, textBuffer, 0); - - // If multiple lines, sum the height of the additional lines - float high = 0; //-textAscent(); - for (int i = 0; i < length; i++) { - if (textBuffer[i] == '\n') { - high += textLeading; - } - } - if (textAlignY == CENTER) { - // for a single line, this adds half the textAscent to y - // for multiple lines, subtract half the additional height - //y += (textAscent() - textDescent() - high)/2; - y += (textAscent() - high)/2; - } else if (textAlignY == TOP) { - // for a single line, need to add textAscent to y - // for multiple lines, no different - y += textAscent(); - } else if (textAlignY == BOTTOM) { - // for a single line, this is just offset by the descent - // for multiple lines, subtract leading for each line - y -= textDescent() + high; - //} else if (textAlignY == BASELINE) { - // do nothing - } - - int start = 0; - int index = 0; - while (index < length) { - if (textBuffer[index] == '\n') { - textLineAlignImpl(textBuffer, start, index, x, y); - start = index + 1; - y += textLeading; - } - index++; - } - if (start < length) { - textLineAlignImpl(textBuffer, start, index, x, y); - } - } - - - /** - * Method to draw text from an array of chars. This method will usually be - * more efficient than drawing from a String object, because the String will - * not be converted to a char array before drawing. - */ - public void text(char[] chars, int start, int stop, float x, float y) { - // If multiple lines, sum the height of the additional lines - float high = 0; //-textAscent(); - for (int i = start; i < stop; i++) { - if (chars[i] == '\n') { - high += textLeading; - } - } - if (textAlignY == CENTER) { - // for a single line, this adds half the textAscent to y - // for multiple lines, subtract half the additional height - //y += (textAscent() - textDescent() - high)/2; - y += (textAscent() - high)/2; - } else if (textAlignY == TOP) { - // for a single line, need to add textAscent to y - // for multiple lines, no different - y += textAscent(); - } else if (textAlignY == BOTTOM) { - // for a single line, this is just offset by the descent - // for multiple lines, subtract leading for each line - y -= textDescent() + high; - //} else if (textAlignY == BASELINE) { - // do nothing - } - -// int start = 0; - int index = 0; - while (index < stop) { //length) { - if (chars[index] == '\n') { - textLineAlignImpl(chars, start, index, x, y); - start = index + 1; - y += textLeading; - } - index++; - } - if (start < stop) { //length) { - textLineAlignImpl(chars, start, index, x, y); - } - } - - - /** - * Same as above but with a z coordinate. - */ - public void text(String str, float x, float y, float z) { -// if ((z != 0) && (textMode == SCREEN)) { -// String msg = "textMode(SCREEN) cannot have a z coordinate"; -// throw new RuntimeException(msg); -// } - - if (z != 0) translate(0, 0, z); // slow! - - text(str, x, y); -// textZ = z; - - if (z != 0) translate(0, 0, -z); - } - - - public void text(char[] chars, int start, int stop, - float x, float y, float z) { - if (z != 0) translate(0, 0, z); // slow! - - text(chars, start, stop, x, y); -// textZ = z; - - if (z != 0) translate(0, 0, -z); // inaccurate! - } - - - /** - * Draw text in a box that is constrained to a particular size. - * The current rectMode() determines what the coordinates mean - * (whether x1/y1/x2/y2 or x/y/w/h). - *

      - * Note that the x,y coords of the start of the box - * will align with the *ascent* of the text, not the baseline, - * as is the case for the other text() functions. - *

      - * Newlines that are \n (Unix newline or linefeed char, ascii 10) - * are honored, and \r (carriage return, Windows and Mac OS) are - * ignored. - */ - public void text(String str, float x1, float y1, float x2, float y2) { - if (textFont == null) { - defaultFontOrDeath("text"); - } - - float hradius, vradius; - switch (rectMode) { - case CORNER: - x2 += x1; y2 += y1; - break; - case RADIUS: - hradius = x2; - vradius = y2; - x2 = x1 + hradius; - y2 = y1 + vradius; - x1 -= hradius; - y1 -= vradius; - break; - case CENTER: - hradius = x2 / 2.0f; - vradius = y2 / 2.0f; - x2 = x1 + hradius; - y2 = y1 + vradius; - x1 -= hradius; - y1 -= vradius; - } - if (x2 < x1) { - float temp = x1; x1 = x2; x2 = temp; - } - if (y2 < y1) { - float temp = y1; y1 = y2; y2 = temp; - } - -// float currentY = y1; - float boxWidth = x2 - x1; - -// // ala illustrator, the text itself must fit inside the box -// currentY += textAscent(); //ascent() * textSize; -// // if the box is already too small, tell em to f off -// if (currentY > y2) return; - - float spaceWidth = textWidth(' '); - - if (textBreakStart == null) { - textBreakStart = new int[20]; - textBreakStop = new int[20]; - } - textBreakCount = 0; - - int length = str.length(); - if (length + 1 > textBuffer.length) { - textBuffer = new char[length + 1]; - } - str.getChars(0, length, textBuffer, 0); - // add a fake newline to simplify calculations - textBuffer[length++] = '\n'; - - int sentenceStart = 0; - for (int i = 0; i < length; i++) { - if (textBuffer[i] == '\n') { -// currentY = textSentence(textBuffer, sentenceStart, i, -// lineX, boxWidth, currentY, y2, spaceWidth); - boolean legit = - textSentence(textBuffer, sentenceStart, i, boxWidth, spaceWidth); - if (!legit) break; -// if (Float.isNaN(currentY)) break; // word too big (or error) -// if (currentY > y2) break; // past the box - sentenceStart = i + 1; - } - } - - // lineX is the position where the text starts, which is adjusted - // to left/center/right based on the current textAlign - float lineX = x1; //boxX1; - if (textAlign == CENTER) { - lineX = lineX + boxWidth/2f; - } else if (textAlign == RIGHT) { - lineX = x2; //boxX2; - } - - float boxHeight = y2 - y1; - //int lineFitCount = 1 + PApplet.floor((boxHeight - textAscent()) / textLeading); - // incorporate textAscent() for the top (baseline will be y1 + ascent) - // and textDescent() for the bottom, so that lower parts of letters aren't - // outside the box. [0151] - float topAndBottom = textAscent() + textDescent(); - int lineFitCount = 1 + PApplet.floor((boxHeight - topAndBottom) / textLeading); - int lineCount = Math.min(textBreakCount, lineFitCount); - - if (textAlignY == CENTER) { - float lineHigh = textAscent() + textLeading * (lineCount - 1); - float y = y1 + textAscent() + (boxHeight - lineHigh) / 2; - for (int i = 0; i < lineCount; i++) { - textLineAlignImpl(textBuffer, textBreakStart[i], textBreakStop[i], lineX, y); - y += textLeading; - } - - } else if (textAlignY == BOTTOM) { - float y = y2 - textDescent() - textLeading * (lineCount - 1); - for (int i = 0; i < lineCount; i++) { - textLineAlignImpl(textBuffer, textBreakStart[i], textBreakStop[i], lineX, y); - y += textLeading; - } - - } else { // TOP or BASELINE just go to the default - float y = y1 + textAscent(); - for (int i = 0; i < lineCount; i++) { - textLineAlignImpl(textBuffer, textBreakStart[i], textBreakStop[i], lineX, y); - y += textLeading; - } - } - } - - - /** - * Emit a sentence of text, defined as a chunk of text without any newlines. - * @param stop non-inclusive, the end of the text in question - */ - protected boolean textSentence(char[] buffer, int start, int stop, - float boxWidth, float spaceWidth) { - float runningX = 0; - - // Keep track of this separately from index, since we'll need to back up - // from index when breaking words that are too long to fit. - int lineStart = start; - int wordStart = start; - int index = start; - while (index <= stop) { - // boundary of a word or end of this sentence - if ((buffer[index] == ' ') || (index == stop)) { - float wordWidth = textWidthImpl(buffer, wordStart, index); - - if (runningX + wordWidth > boxWidth) { - if (runningX != 0) { - // Next word is too big, output the current line and advance - index = wordStart; - textSentenceBreak(lineStart, index); - // Eat whitespace because multiple spaces don't count for s* - // when they're at the end of a line. - while ((index < stop) && (buffer[index] == ' ')) { - index++; - } - } else { // (runningX == 0) - // If this is the first word on the line, and its width is greater - // than the width of the text box, then break the word where at the - // max width, and send the rest of the word to the next line. - do { - index--; - if (index == wordStart) { - // Not a single char will fit on this line. screw 'em. - //System.out.println("screw you"); - return false; //Float.NaN; - } - wordWidth = textWidthImpl(buffer, wordStart, index); - } while (wordWidth > boxWidth); - - //textLineImpl(buffer, lineStart, index, x, y); - textSentenceBreak(lineStart, index); - } - lineStart = index; - wordStart = index; - runningX = 0; - - } else if (index == stop) { - // last line in the block, time to unload - //textLineImpl(buffer, lineStart, index, x, y); - textSentenceBreak(lineStart, index); -// y += textLeading; - index++; - - } else { // this word will fit, just add it to the line - runningX += wordWidth + spaceWidth; - wordStart = index + 1; // move on to the next word - index++; - } - } else { // not a space or the last character - index++; // this is just another letter - } - } -// return y; - return true; - } - - - protected void textSentenceBreak(int start, int stop) { - if (textBreakCount == textBreakStart.length) { - textBreakStart = PApplet.expand(textBreakStart); - textBreakStop = PApplet.expand(textBreakStop); - } - textBreakStart[textBreakCount] = start; - textBreakStop[textBreakCount] = stop; - textBreakCount++; - } - - -// public void text(String s, float x1, float y1, float x2, float y2, float z) { -// if (z != 0) translate(0, 0, z); // slowness, badness -// -// text(s, x1, y1, x2, y2); -// textZ = z; -// -// if (z != 0) translate(0, 0, -z); // TEMPORARY HACK! SLOW! -// } - - - public void text(int num, float x, float y) { - text(String.valueOf(num), x, y); - } - - - public void text(int num, float x, float y, float z) { - text(String.valueOf(num), x, y, z); - } - - - /** - * This does a basic number formatting, to avoid the - * generally ugly appearance of printing floats. - * Users who want more control should use their own nf() cmmand, - * or if they want the long, ugly version of float, - * use String.valueOf() to convert the float to a String first. - */ - public void text(float num, float x, float y) { - text(PApplet.nfs(num, 0, 3), x, y); - } - - - public void text(float num, float x, float y, float z) { - text(PApplet.nfs(num, 0, 3), x, y, z); - } - - ////////////////////////////////////////////////////////////// - - // TEXT IMPL - - // These are most likely to be overridden by subclasses, since the other - // (public) functions handle generic features like setting alignment. - - - /** - * Handles placement of a text line, then calls textLineImpl - * to actually render at the specific point. - */ - protected void textLineAlignImpl(char buffer[], int start, int stop, - float x, float y) { - if (textAlign == CENTER) { - x -= textWidthImpl(buffer, start, stop) / 2f; - - } else if (textAlign == RIGHT) { - x -= textWidthImpl(buffer, start, stop); - } - - textLineImpl(buffer, start, stop, x, y); - } - - - /** - * Implementation of actual drawing for a line of text. - */ - protected void textLineImpl(char buffer[], int start, int stop, - float x, float y) { - for (int index = start; index < stop; index++) { - textCharImpl(buffer[index], x, y); - - // this doesn't account for kerning - x += textWidth(buffer[index]); - } -// textX = x; -// textY = y; -// textZ = 0; // this will get set by the caller if non-zero - } - - - protected void textCharImpl(char ch, float x, float y) { - PFont.Glyph glyph = textFont.getGlyph(ch); - if (glyph != null) { - if (textMode == MODEL) { - float high = glyph.height / (float) textFont.size; - float bwidth = glyph.width / (float) textFont.size; - float lextent = glyph.leftExtent / (float) textFont.size; - float textent = glyph.topExtent / (float) textFont.size; - - float x1 = x + lextent * textSize; - float y1 = y - textent * textSize; - float x2 = x1 + bwidth * textSize; - float y2 = y1 + high * textSize; - - textCharModelImpl(glyph.image, - x1, y1, x2, y2, - glyph.width, glyph.height); - } - } - } - - - protected void textCharModelImpl(PImage glyph, - float x1, float y1, //float z1, - float x2, float y2, //float z2, - int u2, int v2) { - boolean savedTint = tint; - int savedTintColor = tintColor; - tint(fillColor); - - imageImpl(glyph, x1, y1, x2, y2, 0, 0, u2, v2); - - if (savedTint) { - tint(savedTintColor); - } else { - noTint(); - } - } - - - ////////////////////////////////////////////////////////////// - - // PARITY WITH P5.JS - - - public void push() { - pushStyle(); - pushMatrix(); - } - - - public void pop() { - popStyle(); - popMatrix(); - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX STACK - - - /** - * Push a copy of the current transformation matrix onto the stack. - */ - public void pushMatrix() { - showMethodWarning("pushMatrix"); - } - - - /** - * Replace the current transformation matrix with the top of the stack. - */ - public void popMatrix() { - showMethodWarning("popMatrix"); - } - - - - ////////////////////////////////////////////////////////////// - - // MATRIX TRANSFORMATIONS - - - /** - * Translate in X and Y. - */ - public void translate(float tx, float ty) { - showMissingWarning("translate"); - } - - - /** - * Translate in X, Y, and Z. - */ - public void translate(float tx, float ty, float tz) { - showMissingWarning("translate"); - } - - - /** - * Two dimensional rotation. - * - * Same as rotateZ (this is identical to a 3D rotation along the z-axis) - * but included for clarity. It'd be weird for people drawing 2D graphics - * to be using rotateZ. And they might kick our a-- for the confusion. - * - * Additional background. - */ - public void rotate(float angle) { - showMissingWarning("rotate"); - } - - - /** - * Rotate around the X axis. - */ - public void rotateX(float angle) { - showMethodWarning("rotateX"); - } - - - /** - * Rotate around the Y axis. - */ - public void rotateY(float angle) { - showMethodWarning("rotateY"); - } - - - /** - * Rotate around the Z axis. - * - * The functions rotate() and rotateZ() are identical, it's just that it make - * sense to have rotate() and then rotateX() and rotateY() when using 3D; - * nor does it make sense to use a function called rotateZ() if you're only - * doing things in 2D. so we just decided to have them both be the same. - */ - public void rotateZ(float angle) { - showMethodWarning("rotateZ"); - } - - - /** - * Rotate about a vector in space. Same as the glRotatef() function. - */ - public void rotate(float angle, float vx, float vy, float vz) { - showMissingWarning("rotate"); - } - - - /** - * Scale in all dimensions. - */ - public void scale(float s) { - showMissingWarning("scale"); - } - - - /** - * Scale in X and Y. Equivalent to scale(sx, sy, 1). - * - * Not recommended for use in 3D, because the z-dimension is just - * scaled by 1, since there's no way to know what else to scale it by. - */ - public void scale(float sx, float sy) { - showMissingWarning("scale"); - } - - - /** - * Scale in X, Y, and Z. - */ - public void scale(float x, float y, float z) { - showMissingWarning("scale"); - } - - - /** - * Shear along X axis - */ - public void shearX(float angle) { - showMissingWarning("shearX"); - } - - - /** - * Skew along Y axis - */ - public void shearY(float angle) { - showMissingWarning("shearY"); - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX FULL MONTY - - - /** - * Set the current transformation matrix to identity. - */ - public void resetMatrix() { - showMethodWarning("resetMatrix"); - } - - - public void applyMatrix(PMatrix source) { - if (source instanceof PMatrix2D) { - applyMatrix((PMatrix2D) source); - } else if (source instanceof PMatrix3D) { - applyMatrix((PMatrix3D) source); - } - } - - - public void applyMatrix(PMatrix2D source) { - applyMatrix(source.m00, source.m01, source.m02, - source.m10, source.m11, source.m12); - } - - - /** - * Apply a 3x2 affine transformation matrix. - */ - public void applyMatrix(float n00, float n01, float n02, - float n10, float n11, float n12) { - showMissingWarning("applyMatrix"); - } - - - public void applyMatrix(PMatrix3D source) { - applyMatrix(source.m00, source.m01, source.m02, source.m03, - source.m10, source.m11, source.m12, source.m13, - source.m20, source.m21, source.m22, source.m23, - source.m30, source.m31, source.m32, source.m33); - } - - - /** - * Apply a 4x4 transformation matrix. - */ - public void applyMatrix(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - showMissingWarning("applyMatrix"); - } - - - - ////////////////////////////////////////////////////////////// - - // MATRIX GET/SET/PRINT - - - public PMatrix getMatrix() { - showMissingWarning("getMatrix"); - return null; - } - - - /** - * Copy the current transformation matrix into the specified target. - * Pass in null to create a new matrix. - */ - public PMatrix2D getMatrix(PMatrix2D target) { - showMissingWarning("getMatrix"); - return null; - } - - - /** - * Copy the current transformation matrix into the specified target. - * Pass in null to create a new matrix. - */ - public PMatrix3D getMatrix(PMatrix3D target) { - showMissingWarning("getMatrix"); - return null; - } - - - /** - * Returns a copy of the current object matrix. - * Pass in null to create a new matrix. - */ - public PMatrix3D getObjectMatrix() { - showMissingWarning("getObjectMatrix"); - return null; - } - - - /** - * Copy the current object matrix into the specified target. - * Pass in null to create a new matrix. - */ - public PMatrix3D getObjectMatrix(PMatrix3D target) { - showMissingWarning("getObjectMatrix"); - return null; - } - - - /** - * Returns a copy of the current eye matrix. - * Pass in null to create a new matrix. - */ - public PMatrix3D getEyeMatrix() { - showMissingWarning("getEyeMatrix"); - return null; - } - - - /** - * Copy the current eye matrix into the specified target. - * Pass in null to create a new matrix. - */ - public PMatrix3D getEyeMatrix(PMatrix3D target) { - showMissingWarning("getEyeMatrix"); - return null; - } - - - /** - * Set the current transformation matrix to the contents of another. - */ - public void setMatrix(PMatrix source) { - if (source instanceof PMatrix2D) { - setMatrix((PMatrix2D) source); - } else if (source instanceof PMatrix3D) { - setMatrix((PMatrix3D) source); - } - } - - - /** - * Set the current transformation to the contents of the specified source. - */ - public void setMatrix(PMatrix2D source) { - showMissingWarning("setMatrix"); - } - - - /** - * Set the current transformation to the contents of the specified source. - */ - public void setMatrix(PMatrix3D source) { - showMissingWarning("setMatrix"); - } - - - /** - * Print the current model (or "transformation") matrix. - */ - public void printMatrix() { - showMethodWarning("printMatrix"); - } - - - ////////////////////////////////////////////////////////////// - - // CAMERA - - - public void cameraUp() { - showMethodWarning("cameraUp"); - } - - - public void beginCamera() { - showMethodWarning("beginCamera"); - } - - - public void endCamera() { - showMethodWarning("endCamera"); - } - - - public void camera() { - showMissingWarning("camera"); - } - - - public void camera(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - showMissingWarning("camera"); - } - - - public void printCamera() { - showMethodWarning("printCamera"); - } - - - public void eye() { - showMethodWarning("eye"); - } - - - ////////////////////////////////////////////////////////////// - - // PROJECTION - - - public void ortho() { - showMissingWarning("ortho"); - } - - public void ortho(float left, float right, - float bottom, float top) { - showMissingWarning("ortho"); - } - - public void ortho(float left, float right, - float bottom, float top, - float near, float far) { - showMissingWarning("ortho"); - } - - - public void perspective() { - showMissingWarning("perspective"); - } - - - public void perspective(float fovy, float aspect, float zNear, float zFar) { - showMissingWarning("perspective"); - } - - - public void frustum(float left, float right, - float bottom, float top, - float near, float far) { - showMethodWarning("frustum"); - } - - - public void printProjection() { - showMethodWarning("printCamera"); - } - - - - ////////////////////////////////////////////////////////////// - - // SCREEN TRANSFORMS - - - /** - * Given an x and y coordinate, returns the x position of where - * that point would be placed on screen, once affected by translate(), - * scale(), or any other transformations. - */ - public float screenX(float x, float y) { - showMissingWarning("screenX"); - return 0; - } - - - /** - * Given an x and y coordinate, returns the y position of where - * that point would be placed on screen, once affected by translate(), - * scale(), or any other transformations. - */ - public float screenY(float x, float y) { - showMissingWarning("screenY"); - return 0; - } - - - /** - * Maps a three dimensional point to its placement on-screen. - *

      - * Given an (x, y, z) coordinate, returns the x position of where - * that point would be placed on screen, once affected by translate(), - * scale(), or any other transformations. - */ - public float screenX(float x, float y, float z) { - showMissingWarning("screenX"); - return 0; - } - - - /** - * Maps a three dimensional point to its placement on-screen. - *

      - * Given an (x, y, z) coordinate, returns the y position of where - * that point would be placed on screen, once affected by translate(), - * scale(), or any other transformations. - */ - public float screenY(float x, float y, float z) { - showMissingWarning("screenY"); - return 0; - } - - - /** - * Maps a three dimensional point to its placement on-screen. - *

      - * Given an (x, y, z) coordinate, returns its z value. - * This value can be used to determine if an (x, y, z) coordinate - * is in front or in back of another (x, y, z) coordinate. - * The units are based on how the zbuffer is set up, and don't - * relate to anything "real". They're only useful for in - * comparison to another value obtained from screenZ(), - * or directly out of the zbuffer[]. - */ - public float screenZ(float x, float y, float z) { - showMissingWarning("screenZ"); - return 0; - } - - - /** - * Returns the model space x value for an x, y, z coordinate. - *

      - * This will give you a coordinate after it has been transformed - * by translate(), rotate(), and camera(), but not yet transformed - * by the projection matrix. For instance, his can be useful for - * figuring out how points in 3D space relate to the edge - * coordinates of a shape. - */ - public float modelX(float x, float y, float z) { - showMissingWarning("modelX"); - return 0; - } - - - /** - * Returns the model space y value for an x, y, z coordinate. - */ - public float modelY(float x, float y, float z) { - showMissingWarning("modelY"); - return 0; - } - - - /** - * Returns the model space z value for an x, y, z coordinate. - */ - public float modelZ(float x, float y, float z) { - showMissingWarning("modelZ"); - return 0; - } - - - ////////////////////////////////////////////////////////////// - - // RAY CASTING - - - public PVector[] getRayFromScreen(float screenX, float screenY, PVector[] ray) { - showMissingWarning("getRayFromScreen"); - return null; - } - - - public void getRayFromScreen(float screenX, float screenY, PVector origin, PVector direction) { - showMissingWarning("getRayFromScreen"); - } - - - public boolean intersectsSphere(float r, float screenX, float screenY) { - showMissingWarning("intersectsSphere"); - return false; - } - - - public boolean intersectsSphere(float r, PVector origin, PVector direction) { - showMissingWarning("intersectsSphere"); - return false; - } - - - public boolean intersectsBox(float size, float screenX, float screenY) { - showMissingWarning("intersectsBox"); - return false; - } - - - public boolean intersectsBox(float w, float h, float d, float screenX, float screenY) { - showMissingWarning("intersectsBox"); - return false; - } - - - public boolean intersectsBox(float size, PVector origin, PVector direction) { - showMissingWarning("intersectsBox"); - return false; - } - - - public boolean intersectsBox(float w, float h, float d, PVector origin, PVector direction) { - showMissingWarning("intersectsBox"); - return false; - } - - - public PVector intersectsPlane(float screenX, float screenY) { - showMissingWarning("intersectsPlane"); - return null; - } - - - public PVector intersectsPlane(PVector origin, PVector direction) { - showMissingWarning("intersectsPlane"); - return null; - } - - - ////////////////////////////////////////////////////////////// - - // STYLE - - - public void pushStyle() { - if (styleStackDepth == styleStack.length) { - styleStack = (PStyle[]) PApplet.expand(styleStack); - } - if (styleStack[styleStackDepth] == null) { - styleStack[styleStackDepth] = new PStyle(); - } - PStyle s = styleStack[styleStackDepth++]; - getStyle(s); - } - - - public void popStyle() { - if (styleStackDepth == 0) { - throw new RuntimeException("Too many popStyle() without enough pushStyle()"); - } - styleStackDepth--; - style(styleStack[styleStackDepth]); - } - - - public void style(PStyle s) { - // if (s.smooth) { - // smooth(); - // } else { - // noSmooth(); - // } - - imageMode(s.imageMode); - rectMode(s.rectMode); - ellipseMode(s.ellipseMode); - shapeMode(s.shapeMode); - - blendMode(s.blendMode); - - if (s.tint) { - tint(s.tintColor); - } else { - noTint(); - } - if (s.fill) { - fill(s.fillColor); - } else { - noFill(); - } - if (s.stroke) { - stroke(s.strokeColor); - } else { - noStroke(); - } - strokeWeight(s.strokeWeight); - strokeCap(s.strokeCap); - strokeJoin(s.strokeJoin); - - // Set the colorMode() for the material properties. - // TODO this is really inefficient, need to just have a material() method, - // but this has the least impact to the API. - colorMode(RGB, 1); - ambient(s.ambientR, s.ambientG, s.ambientB); - emissive(s.emissiveR, s.emissiveG, s.emissiveB); - specular(s.specularR, s.specularG, s.specularB); - shininess(s.shininess); - - /* - s.ambientR = ambientR; - s.ambientG = ambientG; - s.ambientB = ambientB; - s.specularR = specularR; - s.specularG = specularG; - s.specularB = specularB; - s.emissiveR = emissiveR; - s.emissiveG = emissiveG; - s.emissiveB = emissiveB; - s.shininess = shininess; - */ - // material(s.ambientR, s.ambientG, s.ambientB, - // s.emissiveR, s.emissiveG, s.emissiveB, - // s.specularR, s.specularG, s.specularB, - // s.shininess); - - // Set this after the material properties. - colorMode(s.colorMode, - s.colorModeX, s.colorModeY, s.colorModeZ, s.colorModeA); - - // This is a bit asymmetric, since there's no way to do "noFont()", - // and a null textFont will produce an error (since usually that means that - // the font couldn't load properly). So in some cases, the font won't be - // 'cleared' to null, even though that's technically correct. - if (s.textFont != null) { - textFont(s.textFont, s.textSize); - textLeading(s.textLeading); - } - // These don't require a font to be set. - textAlign(s.textAlign, s.textAlignY); - textMode(s.textMode); - } - - - public PStyle getStyle() { // ignore - return getStyle(null); - } - - - public PStyle getStyle(PStyle s) { // ignore - if (s == null) { - s = new PStyle(); - } - - s.imageMode = imageMode; - s.rectMode = rectMode; - s.ellipseMode = ellipseMode; - s.shapeMode = shapeMode; - - s.blendMode = blendMode; - - s.colorMode = colorMode; - s.colorModeX = colorModeX; - s.colorModeY = colorModeY; - s.colorModeZ = colorModeZ; - s.colorModeA = colorModeA; - - s.tint = tint; - s.tintColor = tintColor; - s.fill = fill; - s.fillColor = fillColor; - s.stroke = stroke; - s.strokeColor = strokeColor; - s.strokeWeight = strokeWeight; - s.strokeCap = strokeCap; - s.strokeJoin = strokeJoin; - - s.ambientR = ambientR; - s.ambientG = ambientG; - s.ambientB = ambientB; - s.specularR = specularR; - s.specularG = specularG; - s.specularB = specularB; - s.emissiveR = emissiveR; - s.emissiveG = emissiveG; - s.emissiveB = emissiveB; - s.shininess = shininess; - - s.textFont = textFont; - s.textAlign = textAlign; - s.textAlignY = textAlignY; - s.textMode = textMode; - s.textSize = textSize; - s.textLeading = textLeading; - - return s; - } - - - - ////////////////////////////////////////////////////////////// - - // STROKE CAP/JOIN/WEIGHT - - - public void strokeWeight(float weight) { - strokeWeight = weight; - } - - - public void strokeJoin(int join) { - strokeJoin = join; - } - - - public void strokeCap(int cap) { - strokeCap = cap; - } - - - - ////////////////////////////////////////////////////////////// - - // STROKE COLOR - - - public void noStroke() { - stroke = false; - } - - - /** - * Set the tint to either a grayscale or ARGB value. - * See notes attached to the fill() function. - */ - public void stroke(int rgb) { -// if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { // see above -// stroke((float) rgb); -// -// } else { -// colorCalcARGB(rgb, colorModeA); -// strokeFromCalc(); -// } - colorCalc(rgb); - strokeFromCalc(); - } - - - public void stroke(int rgb, float alpha) { -// if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { -// stroke((float) rgb, alpha); -// -// } else { -// colorCalcARGB(rgb, alpha); -// strokeFromCalc(); -// } - colorCalc(rgb, alpha); - strokeFromCalc(); - } - - - public void stroke(float gray) { - colorCalc(gray); - strokeFromCalc(); - } - - - public void stroke(float gray, float alpha) { - colorCalc(gray, alpha); - strokeFromCalc(); - } - - - public void stroke(float x, float y, float z) { - colorCalc(x, y, z); - strokeFromCalc(); - } - - - public void stroke(float x, float y, float z, float a) { - colorCalc(x, y, z, a); - strokeFromCalc(); - } - - - protected void strokeFromCalc() { - stroke = true; - strokeR = calcR; - strokeG = calcG; - strokeB = calcB; - strokeA = calcA; - strokeRi = calcRi; - strokeGi = calcGi; - strokeBi = calcBi; - strokeAi = calcAi; - strokeColor = calcColor; - strokeAlpha = calcAlpha; - } - - - - ////////////////////////////////////////////////////////////// - - // TINT COLOR - - - public void noTint() { - tint = false; - } - - - /** - * Set the tint to either a grayscale or ARGB value. - */ - public void tint(int rgb) { -// if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { -// tint((float) rgb); -// -// } else { -// colorCalcARGB(rgb, colorModeA); -// tintFromCalc(); -// } - colorCalc(rgb); - tintFromCalc(); - } - - public void tint(int rgb, float alpha) { -// if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { -// tint((float) rgb, alpha); -// -// } else { -// colorCalcARGB(rgb, alpha); -// tintFromCalc(); -// } - colorCalc(rgb, alpha); - tintFromCalc(); - } - - public void tint(float gray) { - colorCalc(gray); - tintFromCalc(); - } - - - public void tint(float gray, float alpha) { - colorCalc(gray, alpha); - tintFromCalc(); - } - - - public void tint(float x, float y, float z) { - colorCalc(x, y, z); - tintFromCalc(); - } - - - public void tint(float x, float y, float z, float a) { - colorCalc(x, y, z, a); - tintFromCalc(); - } - - - protected void tintFromCalc() { - tint = true; - tintR = calcR; - tintG = calcG; - tintB = calcB; - tintA = calcA; - tintRi = calcRi; - tintGi = calcGi; - tintBi = calcBi; - tintAi = calcAi; - tintColor = calcColor; - tintAlpha = calcAlpha; - } - - - - ////////////////////////////////////////////////////////////// - - // FILL COLOR - - - public void noFill() { - fill = false; - } - - - /** - * Set the fill to either a grayscale value or an ARGB int. - */ - public void fill(int rgb) { -// if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { // see above -// fill((float) rgb); -// -// } else { -// colorCalcARGB(rgb, colorModeA); -// fillFromCalc(); -// } - colorCalc(rgb); - fillFromCalc(); - } - - - public void fill(int rgb, float alpha) { -// if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { // see above -// fill((float) rgb, alpha); -// -// } else { -// colorCalcARGB(rgb, alpha); -// fillFromCalc(); -// } - colorCalc(rgb, alpha); - fillFromCalc(); - } - - - public void fill(float gray) { - colorCalc(gray); - fillFromCalc(); - } - - - public void fill(float gray, float alpha) { - colorCalc(gray, alpha); - fillFromCalc(); - } - - - public void fill(float x, float y, float z) { - colorCalc(x, y, z); - fillFromCalc(); - } - - - public void fill(float x, float y, float z, float a) { - colorCalc(x, y, z, a); - fillFromCalc(); - } - - - protected void fillFromCalc() { - fill = true; - fillR = calcR; - fillG = calcG; - fillB = calcB; - fillA = calcA; - fillRi = calcRi; - fillGi = calcGi; - fillBi = calcBi; - fillAi = calcAi; - fillColor = calcColor; - fillAlpha = calcAlpha; - } - - - - ////////////////////////////////////////////////////////////// - - // MATERIAL PROPERTIES - - - public void ambient(int rgb) { -// if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { -// ambient((float) rgb); -// -// } else { -// colorCalcARGB(rgb, colorModeA); -// ambientFromCalc(); -// } - colorCalc(rgb); - ambientFromCalc(); - } - - - public void ambient(float gray) { - colorCalc(gray); - ambientFromCalc(); - } - - - public void ambient(float x, float y, float z) { - colorCalc(x, y, z); - ambientFromCalc(); - } - - - protected void ambientFromCalc() { - ambientColor = calcColor; - ambientR = calcR; - ambientG = calcG; - ambientB = calcB; - setAmbient = true; - } - - - public void specular(int rgb) { -// if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { -// specular((float) rgb); -// -// } else { -// colorCalcARGB(rgb, colorModeA); -// specularFromCalc(); -// } - colorCalc(rgb); - specularFromCalc(); - } - - - public void specular(float gray) { - colorCalc(gray); - specularFromCalc(); - } - - - public void specular(float x, float y, float z) { - colorCalc(x, y, z); - specularFromCalc(); - } - - - protected void specularFromCalc() { - specularColor = calcColor; - specularR = calcR; - specularG = calcG; - specularB = calcB; - } - - - public void shininess(float shine) { - shininess = shine; - } - - - public void emissive(int rgb) { -// if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { -// emissive((float) rgb); -// -// } else { -// colorCalcARGB(rgb, colorModeA); -// emissiveFromCalc(); -// } - colorCalc(rgb); - emissiveFromCalc(); - } - - - public void emissive(float gray) { - colorCalc(gray); - emissiveFromCalc(); - } - - - public void emissive(float x, float y, float z) { - colorCalc(x, y, z); - emissiveFromCalc(); - } - - - protected void emissiveFromCalc() { - emissiveColor = calcColor; - emissiveR = calcR; - emissiveG = calcG; - emissiveB = calcB; - } - - - - ////////////////////////////////////////////////////////////// - - // LIGHTS - - // The details of lighting are very implementation-specific, so this base - // class does not handle any details of settings lights. It does however - // display warning messages that the functions are not available. - - - public void lights() { - showMethodWarning("lights"); - } - - public void noLights() { - showMethodWarning("noLights"); - } - - public void ambientLight(float red, float green, float blue) { - showMethodWarning("ambientLight"); - } - - public void ambientLight(float red, float green, float blue, - float x, float y, float z) { - showMethodWarning("ambientLight"); - } - - public void directionalLight(float red, float green, float blue, - float nx, float ny, float nz) { - showMethodWarning("directionalLight"); - } - - public void pointLight(float red, float green, float blue, - float x, float y, float z) { - showMethodWarning("pointLight"); - } - - public void spotLight(float red, float green, float blue, - float x, float y, float z, - float nx, float ny, float nz, - float angle, float concentration) { - showMethodWarning("spotLight"); - } - - public void lightFalloff(float constant, float linear, float quadratic) { - showMethodWarning("lightFalloff"); - } - - public void lightSpecular(float x, float y, float z) { - showMethodWarning("lightSpecular"); - } - - - - ////////////////////////////////////////////////////////////// - - // BACKGROUND - - /** - * Set the background to a gray or ARGB color. - *

      - * For the main drawing surface, the alpha value will be ignored. However, - * alpha can be used on PGraphics objects from createGraphics(). This is - * the only way to set all the pixels partially transparent, for instance. - *

      - * Note that background() should be called before any transformations occur, - * because some implementations may require the current transformation matrix - * to be identity before drawing. - */ - public void background(int rgb) { -// if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { -// background((float) rgb); -// -// } else { -// if (format == RGB) { -// rgb |= 0xff000000; // ignore alpha for main drawing surface -// } -// colorCalcARGB(rgb, colorModeA); -// backgroundFromCalc(); -// backgroundImpl(); -// } - colorCalc(rgb); - backgroundFromCalc(); - } - - - /** - * See notes about alpha in background(x, y, z, a). - */ - public void background(int rgb, float alpha) { -// if (format == RGB) { -// background(rgb); // ignore alpha for main drawing surface -// -// } else { -// if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { -// background((float) rgb, alpha); -// -// } else { -// colorCalcARGB(rgb, alpha); -// backgroundFromCalc(); -// backgroundImpl(); -// } -// } - colorCalc(rgb, alpha); - backgroundFromCalc(); - } - - - /** - * Set the background to a grayscale value, based on the - * current colorMode. - */ - public void background(float gray) { - colorCalc(gray); - backgroundFromCalc(); -// backgroundImpl(); - } - - - /** - * See notes about alpha in background(x, y, z, a). - */ - public void background(float gray, float alpha) { - if (format == RGB) { - background(gray); // ignore alpha for main drawing surface - - } else { - colorCalc(gray, alpha); - backgroundFromCalc(); -// backgroundImpl(); - } - } - - - /** - * Set the background to an r, g, b or h, s, b value, - * based on the current colorMode. - */ - public void background(float x, float y, float z) { - colorCalc(x, y, z); - backgroundFromCalc(); -// backgroundImpl(); - } - - - /** - * Clear the background with a color that includes an alpha value. This can - * only be used with objects created by createGraphics(), because the main - * drawing surface cannot be set transparent. - *

      - * It might be tempting to use this function to partially clear the screen - * on each frame, however that's not how this function works. When calling - * background(), the pixels will be replaced with pixels that have that level - * of transparency. To do a semi-transparent overlay, use fill() with alpha - * and draw a rectangle. - */ - public void background(float x, float y, float z, float a) { - colorCalc(x, y, z, a); - backgroundFromCalc(); - } - - - public void clear() { - background(0, 0, 0, 0); - } - - - protected void backgroundFromCalc() { - backgroundR = calcR; - backgroundG = calcG; - backgroundB = calcB; - backgroundA = (format == RGB) ? colorModeA : calcA; - backgroundRi = calcRi; - backgroundGi = calcGi; - backgroundBi = calcBi; - backgroundAi = (format == RGB) ? 255 : calcAi; - backgroundAlpha = (format == RGB) ? false : calcAlpha; - backgroundColor = calcColor; - - backgroundImpl(); - } - - - /** - * Takes an RGB or ARGB image and sets it as the background. - * The width and height of the image must be the same size as the sketch. - * Use image.resize(width, height) to make short work of such a task. - *

      - * Note that even if the image is set as RGB, the high 8 bits of each pixel - * should be set opaque (0xFF000000), because the image data will be copied - * directly to the screen, and non-opaque background images may have strange - * behavior. Using image.filter(OPAQUE) will handle this easily. - *

      - * When using 3D, this will also clear the zbuffer (if it exists). - */ - public void background(PImage image) { - if ((image.width != width) || (image.height != height)) { - throw new RuntimeException(ERROR_BACKGROUND_IMAGE_SIZE); - } - if ((image.format != RGB) && (image.format != ARGB)) { - throw new RuntimeException(ERROR_BACKGROUND_IMAGE_FORMAT); - } - backgroundColor = 0; // just zero it out for images - backgroundImpl(image); - } - - - /** - * Actually set the background image. This is separated from the error - * handling and other semantic goofiness that is shared across renderers. - */ - protected void backgroundImpl(PImage image) { - // blit image to the screen - set(0, 0, image); - } - - - /** - * Actual implementation of clearing the background, now that the - * internal variables for background color have been set. Called by the - * backgroundFromCalc() method, which is what all the other background() - * methods call once the work is done. - */ - protected void backgroundImpl() { - pushStyle(); - pushMatrix(); - resetMatrix(); - fill(backgroundColor); - rect(0, 0, width, height); - popMatrix(); - popStyle(); - } - - - /** - * Callback to handle clearing the background when begin/endRaw is in use. - * Handled as separate function for OpenGL (or other) subclasses that - * override backgroundImpl() but still needs this to work properly. - */ -// protected void backgroundRawImpl() { -// if (raw != null) { -// raw.colorMode(RGB, 1); -// raw.noStroke(); -// raw.fill(backgroundR, backgroundG, backgroundB); -// raw.beginShape(TRIANGLES); -// -// raw.vertex(0, 0); -// raw.vertex(width, 0); -// raw.vertex(0, height); -// -// raw.vertex(width, 0); -// raw.vertex(width, height); -// raw.vertex(0, height); -// -// raw.endShape(); -// } -// } - - - - ////////////////////////////////////////////////////////////// - - // COLOR MODE - - - public void colorMode(int mode) { - colorMode(mode, colorModeX, colorModeY, colorModeZ, colorModeA); - } - - - public void colorMode(int mode, float max) { - colorMode(mode, max, max, max, max); - } - - - /** - * Set the colorMode and the maximum values for (r, g, b) - * or (h, s, b). - *

      - * Note that this doesn't set the maximum for the alpha value, - * which might be confusing if for instance you switched to - *

      colorMode(HSB, 360, 100, 100);
      - * because the alpha values were still between 0 and 255. - */ - public void colorMode(int mode, float maxX, float maxY, float maxZ) { - colorMode(mode, maxX, maxY, maxZ, colorModeA); - } - - - public void colorMode(int mode, - float maxX, float maxY, float maxZ, float maxA) { - colorMode = mode; - - colorModeX = maxX; // still needs to be set for hsb - colorModeY = maxY; - colorModeZ = maxZ; - colorModeA = maxA; - - // if color max values are all 1, then no need to scale - colorModeScale = - ((maxA != 1) || (maxX != maxY) || (maxY != maxZ) || (maxZ != maxA)); - - // if color is rgb/0..255 this will make it easier for the - // red() green() etc functions - colorModeDefault = (colorMode == RGB) && - (colorModeA == 255) && (colorModeX == 255) && - (colorModeY == 255) && (colorModeZ == 255); - } - - - - ////////////////////////////////////////////////////////////// - - // COLOR CALCULATIONS - - // Given input values for coloring, these functions will fill the calcXxxx - // variables with values that have been properly filtered through the - // current colorMode settings. - - // Renderers that need to subclass any drawing properties such as fill or - // stroke will usally want to override methods like fillFromCalc (or the - // same for stroke, ambient, etc.) That way the color calcuations are - // covered by this based PGraphics class, leaving only a single function - // to override/implement in the subclass. - - - /** - * Set the fill to either a grayscale value or an ARGB int. - *

      - * The problem with this code is that it has to detect between these two - * situations automatically. This is done by checking to see if the high bits - * (the alpha for 0xAA000000) is set, and if not, whether the color value - * that follows is less than colorModeX (first param passed to colorMode). - *

      - * This auto-detect would break in the following situation: - *

      size(256, 256);
      -   * for (int i = 0; i < 256; i++) {
      -   *   color c = color(0, 0, 0, i);
      -   *   stroke(c);
      -   *   line(i, 0, i, 256);
      -   * }
      - * ...on the first time through the loop, where (i == 0), since the color - * itself is zero (black) then it would appear indistinguishable from code - * that reads "fill(0)". The solution is to use the four parameter versions - * of stroke or fill to more directly specify the desired result. - */ - protected void colorCalc(int rgb) { - if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { - colorCalc((float) rgb); - - } else { - colorCalcARGB(rgb, colorModeA); - } - } - - - protected void colorCalc(int rgb, float alpha) { - if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { // see above - colorCalc((float) rgb, alpha); - - } else { - colorCalcARGB(rgb, alpha); - } - } - - - protected void colorCalc(float gray) { - colorCalc(gray, colorModeA); - } - - - protected void colorCalc(float gray, float alpha) { - if (gray > colorModeX) gray = colorModeX; - if (alpha > colorModeA) alpha = colorModeA; - - if (gray < 0) gray = 0; - if (alpha < 0) alpha = 0; - - calcR = colorModeScale ? (gray / colorModeX) : gray; - calcG = calcR; - calcB = calcR; - calcA = colorModeScale ? (alpha / colorModeA) : alpha; - - calcRi = (int)(calcR*255); calcGi = (int)(calcG*255); - calcBi = (int)(calcB*255); calcAi = (int)(calcA*255); - calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi; - calcAlpha = (calcAi != 255); - } - - - protected void colorCalc(float x, float y, float z) { - colorCalc(x, y, z, colorModeA); - } - - - protected void colorCalc(float x, float y, float z, float a) { - if (x > colorModeX) x = colorModeX; - if (y > colorModeY) y = colorModeY; - if (z > colorModeZ) z = colorModeZ; - if (a > colorModeA) a = colorModeA; - - if (x < 0) x = 0; - if (y < 0) y = 0; - if (z < 0) z = 0; - if (a < 0) a = 0; - - switch (colorMode) { - case RGB: - if (colorModeScale) { - calcR = x / colorModeX; - calcG = y / colorModeY; - calcB = z / colorModeZ; - calcA = a / colorModeA; - } else { - calcR = x; calcG = y; calcB = z; calcA = a; - } - break; - - case HSB: - x /= colorModeX; // h - y /= colorModeY; // s - z /= colorModeZ; // b - - calcA = colorModeScale ? (a/colorModeA) : a; - - if (y == 0) { // saturation == 0 - calcR = calcG = calcB = z; - - } else { - float which = (x - (int)x) * 6.0f; - float f = which - (int)which; - float p = z * (1.0f - y); - float q = z * (1.0f - y * f); - float t = z * (1.0f - (y * (1.0f - f))); - - switch ((int)which) { - case 0: calcR = z; calcG = t; calcB = p; break; - case 1: calcR = q; calcG = z; calcB = p; break; - case 2: calcR = p; calcG = z; calcB = t; break; - case 3: calcR = p; calcG = q; calcB = z; break; - case 4: calcR = t; calcG = p; calcB = z; break; - case 5: calcR = z; calcG = p; calcB = q; break; - } - } - break; - } - calcRi = (int)(255*calcR); calcGi = (int)(255*calcG); - calcBi = (int)(255*calcB); calcAi = (int)(255*calcA); - calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi; - calcAlpha = (calcAi != 255); - } - - - /** - * Unpacks AARRGGBB color for direct use with colorCalc. - *

      - * Handled here with its own function since this is indepenent - * of the color mode. - *

      - * Strangely the old version of this code ignored the alpha - * value. not sure if that was a bug or what. - *

      - * Note, no need for a bounds check since it's a 32 bit number. - */ - protected void colorCalcARGB(int argb, float alpha) { - if (alpha == colorModeA) { - calcAi = (argb >> 24) & 0xff; - calcColor = argb; - } else { - calcAi = (int) (((argb >> 24) & 0xff) * (alpha / colorModeA)); - calcColor = (calcAi << 24) | (argb & 0xFFFFFF); - } - calcRi = (argb >> 16) & 0xff; - calcGi = (argb >> 8) & 0xff; - calcBi = argb & 0xff; - calcA = (float)calcAi / 255.0f; - calcR = (float)calcRi / 255.0f; - calcG = (float)calcGi / 255.0f; - calcB = (float)calcBi / 255.0f; - calcAlpha = (calcAi != 255); - } - - - - ////////////////////////////////////////////////////////////// - - // COLOR DATATYPE STUFFING - - // The 'color' primitive type in Processing syntax is in fact a 32-bit int. - // These functions handle stuffing color values into a 32-bit cage based - // on the current colorMode settings. - - // These functions are really slow (because they take the current colorMode - // into account), but they're easy to use. Advanced users can write their - // own bit shifting operations to setup 'color' data types. - - - public final int color(int gray) { // ignore - if (((gray & 0xff000000) == 0) && (gray <= colorModeX)) { - if (colorModeDefault) { - // bounds checking to make sure the numbers aren't to high or low - if (gray > 255) gray = 255; else if (gray < 0) gray = 0; - return 0xff000000 | (gray << 16) | (gray << 8) | gray; - } else { - colorCalc(gray); - } - } else { - colorCalcARGB(gray, colorModeA); - } - return calcColor; - } - - - public final int color(float gray) { // ignore - colorCalc(gray); - return calcColor; - } - - - /** - * @param gray can be packed ARGB or a gray in this case - */ - public final int color(int gray, int alpha) { // ignore - if (colorModeDefault) { - // bounds checking to make sure the numbers aren't to high or low - if (gray > 255) gray = 255; else if (gray < 0) gray = 0; - if (alpha > 255) alpha = 255; else if (alpha < 0) alpha = 0; - - return ((alpha & 0xff) << 24) | (gray << 16) | (gray << 8) | gray; - } - colorCalc(gray, alpha); - return calcColor; - } - - - /** - * @param rgb can be packed ARGB or a gray in this case - */ - public final int color(int rgb, float alpha) { // ignore - if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { - colorCalc(rgb, alpha); - } else { - colorCalcARGB(rgb, alpha); - } - return calcColor; - } - - - public final int color(float gray, float alpha) { // ignore - colorCalc(gray, alpha); - return calcColor; - } - - - public final int color(int x, int y, int z) { // ignore - if (colorModeDefault) { - // bounds checking to make sure the numbers aren't to high or low - if (x > 255) x = 255; else if (x < 0) x = 0; - if (y > 255) y = 255; else if (y < 0) y = 0; - if (z > 255) z = 255; else if (z < 0) z = 0; - - return 0xff000000 | (x << 16) | (y << 8) | z; - } - colorCalc(x, y, z); - return calcColor; - } - - - public final int color(float x, float y, float z) { // ignore - colorCalc(x, y, z); - return calcColor; - } - - - public final int color(int x, int y, int z, int a) { // ignore - if (colorModeDefault) { - // bounds checking to make sure the numbers aren't to high or low - if (a > 255) a = 255; else if (a < 0) a = 0; - if (x > 255) x = 255; else if (x < 0) x = 0; - if (y > 255) y = 255; else if (y < 0) y = 0; - if (z > 255) z = 255; else if (z < 0) z = 0; - - return (a << 24) | (x << 16) | (y << 8) | z; - } - colorCalc(x, y, z, a); - return calcColor; - } - - - public final int color(float x, float y, float z, float a) { // ignore - colorCalc(x, y, z, a); - return calcColor; - } - - - - ////////////////////////////////////////////////////////////// - - // COLOR DATATYPE EXTRACTION - - // Vee have veys of making the colors talk. - - - public final float alpha(int what) { - float c = (what >> 24) & 0xff; - if (colorModeA == 255) return c; - return (c / 255.0f) * colorModeA; - } - - - public final float red(int what) { - float c = (what >> 16) & 0xff; - if (colorModeDefault) return c; - return (c / 255.0f) * colorModeX; - } - - - public final float green(int what) { - float c = (what >> 8) & 0xff; - if (colorModeDefault) return c; - return (c / 255.0f) * colorModeY; - } - - - public final float blue(int what) { - float c = (what) & 0xff; - if (colorModeDefault) return c; - return (c / 255.0f) * colorModeZ; - } - - - public final float hue(int what) { - if (what != cacheHsbKey) { - Color.RGBToHSV((what >> 16) & 0xff, (what >> 8) & 0xff, - what & 0xff, cacheHsbValue); - cacheHsbKey = what; - } - return (cacheHsbValue[0] / 360f) * colorModeX; - } - - - public final float saturation(int what) { - if (what != cacheHsbKey) { - Color.RGBToHSV((what >> 16) & 0xff, (what >> 8) & 0xff, - what & 0xff, cacheHsbValue); - cacheHsbKey = what; - } - return cacheHsbValue[1] * colorModeY; - } - - - public final float brightness(int what) { - if (what != cacheHsbKey) { - Color.RGBToHSV((what >> 16) & 0xff, (what >> 8) & 0xff, - what & 0xff, cacheHsbValue); - cacheHsbKey = what; - } - return cacheHsbValue[2] * colorModeZ; - } - - - - ////////////////////////////////////////////////////////////// - - // COLOR DATATYPE INTERPOLATION - - // Against our better judgement. - - - /** - * Interpolate between two colors, using the current color mode. - */ - public int lerpColor(int c1, int c2, float amt) { - return lerpColor(c1, c2, amt, colorMode); - } - - static float[] lerpColorHSB1; - static float[] lerpColorHSB2; - static float[] lerpColorHSB3; - - /** - * Interpolate between two colors. Like lerp(), but for the - * individual color components of a color supplied as an int value. - */ - static public int lerpColor(int c1, int c2, float amt, int mode) { - if (amt < 0) amt = 0; - if (amt > 1) amt = 1; - - if (mode == RGB) { - float a1 = ((c1 >> 24) & 0xff); - float r1 = (c1 >> 16) & 0xff; - float g1 = (c1 >> 8) & 0xff; - float b1 = c1 & 0xff; - float a2 = (c2 >> 24) & 0xff; - float r2 = (c2 >> 16) & 0xff; - float g2 = (c2 >> 8) & 0xff; - float b2 = c2 & 0xff; - - return ((PApplet.round(a1 + (a2-a1)*amt) << 24) | - (PApplet.round(r1 + (r2-r1)*amt) << 16) | - (PApplet.round(g1 + (g2-g1)*amt) << 8) | - (PApplet.round(b1 + (b2-b1)*amt))); - - } else if (mode == HSB) { - if (lerpColorHSB1 == null) { - lerpColorHSB1 = new float[3]; - lerpColorHSB2 = new float[3]; - lerpColorHSB3 = new float[3]; - } - - float a1 = (c1 >> 24) & 0xff; - float a2 = (c2 >> 24) & 0xff; - int alfa = (PApplet.round(a1 + (a2-a1)*amt)) << 24; - - Color.RGBToHSV((c1 >> 16) & 0xff, (c1 >> 8) & 0xff, c1 & 0xff, - lerpColorHSB1); - Color.RGBToHSV((c2 >> 16) & 0xff, (c2 >> 8) & 0xff, c2 & 0xff, - lerpColorHSB2); - - /* If mode is HSB, this will take the shortest path around the - * color wheel to find the new color. For instance, red to blue - * will go red violet blue (backwards in hue space) rather than - * cycling through ROYGBIV. - */ - // Disabling rollover (wasn't working anyway) for 0126. - // Otherwise it makes full spectrum scale impossible for - // those who might want it...in spite of how despicable - // a full spectrum scale might be. - // roll around when 0.9 to 0.1 - // more than 0.5 away means that it should roll in the other direction - /* - float h1 = lerpColorHSB1[0]; - float h2 = lerpColorHSB2[0]; - if (Math.abs(h1 - h2) > 0.5f) { - if (h1 > h2) { - // i.e. h1 is 0.7, h2 is 0.1 - h2 += 1; - } else { - // i.e. h1 is 0.1, h2 is 0.7 - h1 += 1; - } - } - float ho = (PApplet.lerp(lerpColorHSB1[0], lerpColorHSB2[0], amt)) % 1.0f; - */ - // float ho = PApplet.lerp(lerpColorHSB1[0], lerpColorHSB2[0], amt); - // float so = PApplet.lerp(lerpColorHSB1[1], lerpColorHSB2[1], amt); - // float bo = PApplet.lerp(lerpColorHSB1[2], lerpColorHSB2[2], amt); - - // return alfa | (Color.RGBToHSV(ho, so, bo) & 0xFFFFFF); - - lerpColorHSB3[0] = PApplet.lerp(lerpColorHSB1[0], lerpColorHSB2[0], amt); - lerpColorHSB3[1] = PApplet.lerp(lerpColorHSB1[1], lerpColorHSB2[1], amt); - lerpColorHSB3[2] = PApplet.lerp(lerpColorHSB1[2], lerpColorHSB2[2], amt); - return Color.HSVToColor(alfa, lerpColorHSB3); - } - return 0; - } - - - ////////////////////////////////////////////////////////////// - - // BEGINRAW/ENDRAW - - - /** - * Record individual lines and triangles by echoing them to another renderer. - */ - public void beginRaw(PGraphics rawGraphics) { // ignore - this.raw = rawGraphics; - rawGraphics.beginDraw(); - } - - - public void endRaw() { // ignore - if (raw != null) { - // for 3D, need to flush any geometry that's been stored for sorting - // (particularly if the ENABLE_DEPTH_SORT hint is set) - flush(); - - // just like beginDraw, this will have to be called because - // endDraw() will be happening outside of draw() - raw.endDraw(); - raw.dispose(); - raw = null; - } - } - - - public boolean haveRaw() { // ignore - return raw != null; - } - - - public PGraphics getRaw() { // ignore - return raw; - } - - - ////////////////////////////////////////////////////////////// - - // WARNINGS and EXCEPTIONS - - - static protected HashMap warnings; - - - /** - * Show a renderer error, and keep track of it so that it's only shown once. - * @param msg the error message (which will be stored for later comparison) - */ - static public void showWarning(String msg) { // ignore - if (warnings == null) { - warnings = new HashMap(); - } - if (!warnings.containsKey(msg)) { - System.err.println(msg); - warnings.put(msg, new Object()); - } - } - - - /** - * Version of showWarning() that takes a parsed String. - */ - static public void showWarning(String msg, Object... args) { // ignore - showWarning(String.format(msg, args)); - } - - - /** - * Display a warning that the specified method is only available with 3D. - * @param method The method name (no parentheses) - */ - static public void showDepthWarning(String method) { - showWarning(method + "() can only be used with a renderer that " + - "supports 3D, such as P3D or OPENGL."); - } - - - /** - * Display a warning that the specified method that takes x, y, z parameters - * can only be used with x and y parameters in this renderer. - * @param method The method name (no parentheses) - */ - static public void showDepthWarningXYZ(String method) { - showWarning(method + "() with x, y, and z coordinates " + - "can only be used with a renderer that " + - "supports 3D, such as P3D or OPENGL. " + - "Use a version without a z-coordinate instead."); - } - - - /** - * Display a warning that the specified method is simply unavailable. - */ - static public void showMethodWarning(String method) { - showWarning(method + "() is not available with this renderer."); - } - - - /** - * Error that a particular variation of a method is unavailable (even though - * other variations are). For instance, if vertex(x, y, u, v) is not - * available, but vertex(x, y) is just fine. - */ - static public void showVariationWarning(String str) { - showWarning(str + " is not available with this renderer."); - } - - - /** - * Display a warning that the specified method is not implemented, meaning - * that it could be either a completely missing function, although other - * variations of it may still work properly. - */ - static public void showMissingWarning(String method) { - showWarning(method + "(), or this particular variation of it, " + - "is not available with this renderer."); - } - - - /** - * Show an renderer-related exception that halts the program. Currently just - * wraps the message as a RuntimeException and throws it, but might do - * something more specific might be used in the future. - */ - static public void showException(String msg) { // ignore - throw new RuntimeException(msg); - } - - - /** - * Same as below, but defaults to a 12 point font, just as MacWrite intended. - */ - protected void defaultFontOrDeath(String method) { - defaultFontOrDeath(method, 12); - } - - - /** - * First try to create a default font, but if that's not possible, throw - * an exception that halts the program because textFont() has not been used - * prior to the specified method. - */ - protected void defaultFontOrDeath(String method, float size) { - if (parent != null) { - textFont = parent.createDefaultFont(size); - } else { - throw new RuntimeException("Use textFont() before " + method + "()"); - } - } - - - - ////////////////////////////////////////////////////////////// - - // RENDERER SUPPORT QUERIES - - - /** - * Return true if this renderer should be drawn to the screen. Defaults to - * returning true, since nearly all renderers are on-screen beasts. But can - * be overridden for subclasses like PDF so that a window doesn't open up. - *

      - * A better name? showFrame, displayable, isVisible, visible, shouldDisplay, - * what to call this? - */ - public boolean displayable() { - return true; - } - - - /** - * Return true if this renderer supports 2D drawing. Defaults to true. - */ - public boolean is2D() { - return true; - } - - - /** - * Return true if this renderer supports 2D drawing. Defaults to false. - */ - public boolean is3D() { - return false; - } - - - /** - * Return true if this renderer does rendering through OpenGL. Defaults to false. - */ - public boolean isGL() { - return false; - } - - - ////////////////////////////////////////////////////////////// - - // ASYNC IMAGE SAVING - - - @Override - public boolean save(String filename) { // ignore - - if (hints[DISABLE_ASYNC_SAVEFRAME]) { - return super.save(filename); - } - - if (asyncImageSaver == null) { - asyncImageSaver = new AsyncImageSaver(); - } - - if (!loaded) loadPixels(); - PImage target = asyncImageSaver.getAvailableTarget(pixelWidth, pixelHeight, - format); - if (target == null) return false; - int count = PApplet.min(pixels.length, target.pixels.length); - System.arraycopy(pixels, 0, target.pixels, 0, count); - asyncImageSaver.saveTargetAsync(this, target, filename); - - return true; - } - - protected void processImageBeforeAsyncSave(PImage image) { } - - - protected static AsyncImageSaver asyncImageSaver; - - protected static class AsyncImageSaver { - - static final int TARGET_COUNT = - Math.max(1, Runtime.getRuntime().availableProcessors() - 1); - - BlockingQueue targetPool = new ArrayBlockingQueue<>(TARGET_COUNT); - ExecutorService saveExecutor = Executors.newFixedThreadPool(TARGET_COUNT); - - int targetsCreated = 0; - - - static final int TIME_AVG_FACTOR = 32; - - volatile long avgNanos = 0; - long lastTime = 0; - int lastFrameCount = 0; - - - public AsyncImageSaver() { } // ignore - - - public void dispose() { // ignore - saveExecutor.shutdown(); - try { - saveExecutor.awaitTermination(5000, TimeUnit.SECONDS); - } catch (InterruptedException e) { } - } - - - public boolean hasAvailableTarget() { // ignore - return targetsCreated < TARGET_COUNT || targetPool.isEmpty(); - } - - - /** - * After taking a target, you must call saveTargetAsync() or - * returnUnusedTarget(), otherwise one thread won't be able to run - */ - public PImage getAvailableTarget(int requestedWidth, int requestedHeight, // ignore - int format) { - try { - PImage target; - if (targetsCreated < TARGET_COUNT && targetPool.isEmpty()) { - target = new PImage(requestedWidth, requestedHeight); - targetsCreated++; - } else { - target = targetPool.take(); - if (target.width != requestedWidth || - target.height != requestedHeight) { - target.width = requestedWidth; - target.height = requestedHeight; - // TODO: this kills performance when saving different sizes - target.pixels = new int[requestedWidth * requestedHeight]; - } - } - target.format = format; - return target; - } catch (InterruptedException e) { - return null; - } - } - - - public void returnUnusedTarget(PImage target) { // ignore - targetPool.offer(target); - } - - - public void saveTargetAsync(final PGraphics renderer, final PImage target, // ignore - final String filename) { - target.parent = renderer.parent; - - // if running every frame, smooth the framerate - if (target.parent.frameCount - 1 == lastFrameCount && TARGET_COUNT > 1) { - - // count with one less thread to reduce jitter - // 2 cores - 1 save thread - no wait - // 4 cores - 3 save threads - wait 1/2 of save time - // 8 cores - 7 save threads - wait 1/6 of save time - long avgTimePerFrame = avgNanos / (Math.max(1, TARGET_COUNT - 1)); - long now = System.nanoTime(); - long delay = PApplet.round((lastTime + avgTimePerFrame - now) / 1e6f); - try { - if (delay > 0) Thread.sleep(delay); - } catch (InterruptedException e) { } - } - - lastFrameCount = target.parent.frameCount; - lastTime = System.nanoTime(); - - try { - saveExecutor.submit(new Runnable() { - @Override - public void run() { // ignore - try { - long startTime = System.nanoTime(); - renderer.processImageBeforeAsyncSave(target); - target.save(filename); - long saveNanos = System.nanoTime() - startTime; - synchronized (AsyncImageSaver.this) { - if (avgNanos == 0) { - avgNanos = saveNanos; - } else if (saveNanos < avgNanos) { - avgNanos = (avgNanos * (TIME_AVG_FACTOR - 1) + saveNanos) / - (TIME_AVG_FACTOR); - } else { - avgNanos = saveNanos; - } - } - } finally { - targetPool.offer(target); - } - } - }); - } catch (RejectedExecutionException e) { - // the executor service was probably shut down, no more saving for us - } - } - } - -} diff --git a/core/src/processing/core/PImage.java b/core/src/processing/core/PImage.java deleted file mode 100644 index 8eceaf2c4..000000000 --- a/core/src/processing/core/PImage.java +++ /dev/null @@ -1,2881 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - -import java.io.*; -import java.util.HashMap; - -import android.graphics.Bitmap; -import android.graphics.Bitmap.CompressFormat; -import android.graphics.Bitmap.Config; - - -/** - * Storage class for pixel data. This is the base class for most image and - * pixel information, such as PGraphics and the video library classes. - *

      - * Code for copying, resizing, scaling, and blending contributed - * by toxi. - *

      - */ -public class PImage implements PConstants, Cloneable { - - /** - * Format for this image, one of RGB, ARGB or ALPHA. - * note that RGB images still require 0xff in the high byte - * because of how they'll be manipulated by other functions - */ - public int format; - - public int[] pixels; - public int width, height; - - /** - * For the time being, simply to ensure compatibility with Java mode code - */ - public int pixelDensity = 1; - public int pixelWidth; - public int pixelHeight; - - /** - * Path to parent object that will be used with save(). - * This prevents users from needing savePath() to use PImage.save(). - */ - public PApplet parent; - - protected Bitmap bitmap; - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** for renderers that need to store info about the image */ - protected HashMap cacheMap; - - /** for renderers that need to store parameters about the image */ - protected HashMap paramMap; - - - /** modified portion of the image */ - protected boolean modified; - protected int mx1, my1, mx2, my2; - - /** Loaded pixels flag */ - public boolean loaded = false; - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - // private fields - private int fracU, ifU, fracV, ifV, u1, u2, v1, v2, sX, sY, iw, iw1, ih1; - private int ul, ll, ur, lr, cUL, cLL, cUR, cLR; - private int srcXOffset, srcYOffset; - private int r, g, b, a; - private int[] srcBuffer; - - // fixed point precision is limited to 15 bits!! - static final int PRECISIONB = 15; - static final int PRECISIONF = 1 << PRECISIONB; - static final int PREC_MAXVAL = PRECISIONF-1; - static final int PREC_ALPHA_SHIFT = 24-PRECISIONB; - static final int PREC_RED_SHIFT = 16-PRECISIONB; - - // internal kernel stuff for the gaussian blur filter - private int blurRadius; - private int blurKernelSize; - private int[] blurKernel; - private int[][] blurMult; - - // colour component bitmasks (moved from PConstants in 2.0b7) - public static final int ALPHA_MASK = 0xff000000; - public static final int RED_MASK = 0x00ff0000; - public static final int GREEN_MASK = 0x0000ff00; - public static final int BLUE_MASK = 0x000000ff; - - - ////////////////////////////////////////////////////////////// - - - /** - * Create an empty image object, set its format to RGB. - * The pixel array is not allocated. - */ - public PImage() { - format = ARGB; // default to ARGB images for release 0116 -// cache = null; - } - - - /** - * Create a new RGB (alpha ignored) image of a specific size. - * All pixels are set to zero, meaning black, but since the - * alpha is zero, it will be transparent. - */ - public PImage(int width, int height) { - init(width, height, RGB); - } - - - public PImage(int width, int height, int format) { - init(width, height, format); - } - - - /** - * Function to be used by subclasses of PImage to init later than - * at the constructor, or re-init later when things changes. - * Used by Capture and Movie classes (and perhaps others), - * because the width/height will not be known when super() is called. - * (Leave this public so that other libraries can do the same.) - */ - public void init(int width, int height, int format) { // ignore - this.width = width; - this.height = height; - this.pixels = new int[width*height]; - this.format = format; -// this.cache = null; - - pixelWidth = width * pixelDensity; - pixelHeight = height * pixelDensity; - this.pixels = new int[pixelWidth * pixelHeight]; - } - - - /** - * Check the alpha on an image, using a really primitive loop. - */ - protected void checkAlpha() { - if (pixels == null) return; - - for (int i = 0; i < pixels.length; i++) { - // since transparency is often at corners, hopefully this - // will find a non-transparent pixel quickly and exit - if ((pixels[i] & 0xff000000) != 0xff000000) { - format = ARGB; - break; - } - } - } - - - ////////////////////////////////////////////////////////////// - - - /** - * Construct a new PImage from an Android bitmap. The pixels[] array is not - * initialized, nor is data copied to it, until loadPixels() is called. - */ - public PImage(Object nativeObject) { - Bitmap bitmap = (Bitmap) nativeObject; - this.bitmap = bitmap; - this.width = bitmap.getWidth(); - this.height = bitmap.getHeight(); - this.pixels = null; - this.format = bitmap.hasAlpha() ? ARGB : RGB; - this.pixelDensity = 1; - this.pixelWidth = width; - this.pixelHeight = height; - } - - - /** - * Returns the native Bitmap object for this PImage. - */ - public Object getNative() { - return bitmap; - } - - - public void setNative(Object nativeObject) { - Bitmap bitmap = (Bitmap) nativeObject; - this.bitmap = bitmap; - } - - - - ////////////////////////////////////////////////////////////// - - // MARKING IMAGE AS MODIFIED / FOR USE w/ GET/SET - - - public boolean isModified() { // ignore - return modified; - } - - - public void setModified() { // ignore - modified = true; - } - - - public void setModified(boolean m) { // ignore - modified = m; - } - - public int getModifiedX1() { // ignore - return mx1; - } - - - public int getModifiedX2() { // ignore - return mx2; - } - - - public int getModifiedY1() { // ignore - return my1; - } - - - public int getModifiedY2() { // ignore - return my2; - } - - - /** - * Call this when you want to mess with the pixels[] array. - *

      - * For subclasses where the pixels[] buffer isn't set by default, - * this should copy all data into the pixels[] array - */ - public void loadPixels() { // ignore - if (pixels == null || pixels.length != width*height) { - pixels = new int[width*height]; - } - - if (bitmap != null) { - if (modified) { - // The pixels array has been used to do color manipulations, so - // the bitmap should be updated - if (!bitmap.isMutable()) { - // create a mutable version of this bitmap - bitmap = bitmap.copy(Config.ARGB_8888, true); - } - bitmap.setPixels(pixels, 0, width, mx1, my1, mx2 - mx1, my2 - my1); - modified = false; - } else { - // Get wherever it is in the bitmap right now, we assume is the most - // up-to-date version of the image. - bitmap.getPixels(pixels, 0, width, 0, 0, width, height); - } - } - - setLoaded(); - } - - - /** - * Call this when finished messing with the pixels[] array. - *

      - * Mark all pixels as needing update. - */ - public void updatePixels() { // ignore - updatePixelsImpl(0, 0, width, height); - } - - - /** - * Mark the pixels in this region as needing an update. - *

      - * This is not currently used by any of the renderers, however the api - * is structured this way in the hope of being able to use this to - * speed things up in the future. - */ - public void updatePixels(int x, int y, int w, int h) { // ignore -// if (imageMode == CORNER) { // x2, y2 are w/h -// x2 += x1; -// y2 += y1; -// -// } else if (imageMode == CENTER) { -// x1 -= x2 / 2; -// y1 -= y2 / 2; -// x2 += x1; -// y2 += y1; -// } - updatePixelsImpl(x, y, w, h); - } - - - protected void updatePixelsImpl(int x, int y, int w, int h) { - int x2 = x + w; - int y2 = y + h; - - if (!modified) { - mx1 = PApplet.max(0, x); - //mx2 = PApplet.min(width - 1, x2); - mx2 = PApplet.min(width, x2); - my1 = PApplet.max(0, y); - //my2 = PApplet.min(height - 1, y2); - my2 = PApplet.min(height, y2); - modified = true; - - } else { - if (x < mx1) mx1 = PApplet.max(0, x); - //if (x > mx2) mx2 = PApplet.min(width - 1, x); - if (x > mx2) mx2 = PApplet.min(width, x); - if (y < my1) my1 = PApplet.max(0, y); - //if (y > my2) my2 = y; - if (y > my2) my2 = PApplet.min(height, y); - - if (x2 < mx1) mx1 = PApplet.max(0, x2); - //if (x2 > mx2) mx2 = PApplet.min(width - 1, x2); - if (x2 > mx2) mx2 = PApplet.min(width, x2); - if (y2 < my1) my1 = PApplet.max(0, y2); - //if (y2 > my2) my2 = PApplet.min(height - 1, y2); - if (y2 > my2) my2 = PApplet.min(height, y2); - } - } - - - ////////////////////////////////////////////////////////////// - - // COPYING IMAGE DATA - - - /** - * Duplicate an image, returns new PImage object. - * The pixels[] array for the new object will be unique - * and recopied from the source image. This is implemented as an - * override of Object.clone(). We recommend using get() instead, - * because it prevents you from needing to catch the - * CloneNotSupportedException, and from doing a cast from the result. - */ - @Override - public Object clone() throws CloneNotSupportedException { // ignore - return get(); - } - - - /** - * Resize this image to a new width and height. - * Use 0 for wide or high to make that dimension scale proportionally. - */ - public void resize(int w, int h) { // ignore - if (bitmap == null) { - return; // Cannot resize an image not backed by a bitmap - } - - if (w <= 0 && h <= 0) { - throw new IllegalArgumentException("width or height must be > 0 for resize"); - } - - if (w == 0) { // Use height to determine relative size - float diff = (float) h / (float) height; - w = (int) (width * diff); - } else if (h == 0) { // Use the width to determine relative size - float diff = (float) w / (float) width; - h = (int) (height * diff); - } - bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true); - if (pixels != null) { - // Resize pixels array, if in use. - pixels = new int[w * h]; - bitmap.getPixels(pixels, 0, w, 0, 0, w, h); - } - this.width = w; - this.height = h; - this.pixelWidth = w * pixelDensity; - this.pixelHeight = h * pixelDensity; - } - - - ////////////////////////////////////////////////////////////// - - // MARKING IMAGE AS LOADED / FOR USE IN RENDERERS - - - public boolean isLoaded() { // ignore - return loaded; - } - - - public void setLoaded() { // ignore - loaded = true; - } - - - public void setLoaded(boolean l) { // ignore - loaded = l; - } - - - ////////////////////////////////////////////////////////////// - - // GET/SET PIXELS - - - /** - * Returns an ARGB "color" type (a packed 32 bit int with the color. - * If the coordinate is outside the image, zero is returned - * (black, but completely transparent). - *

      - * If the image is in RGB format (i.e. on a PVideo object), - * the value will get its high bits set, just to avoid cases where - * they haven't been set already. - *

      - * If the image is in ALPHA format, this returns a white with its - * alpha value set. - *

      - * This function is included primarily for beginners. It is quite - * slow because it has to check to see if the x, y that was provided - * is inside the bounds, and then has to check to see what image - * type it is. If you want things to be more efficient, access the - * pixels[] array directly. - */ - public int get(int x, int y) { - if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return 0; - - if (pixels == null) { - return bitmap.getPixel(x, y); - - } else { - // If the pixels array exists, it's fairly safe to assume that it's - // the most up to date, and that it's faster for access. - switch (format) { - case RGB: - return pixels[y*width + x] | 0xff000000; - - case ARGB: - return pixels[y*width + x]; - - case ALPHA: - return (pixels[y*width + x] << 24) | 0xffffff; - } - } - return 0; - } - - - /** - * Grab a subsection of a PImage, and copy it into a fresh PImage. - * As of release 0149, no longer honors imageMode() for the coordinates. - */ - /** - * @param w width of pixel rectangle to get - * @param h height of pixel rectangle to get - */ - public PImage get(int x, int y, int w, int h) { - int targetX = 0; - int targetY = 0; - int targetWidth = w; - int targetHeight = h; - boolean cropped = false; - - if (x < 0) { - w += x; // x is negative, removes the left edge from the width - targetX = -x; - cropped = true; - x = 0; - } - if (y < 0) { - h += y; // y is negative, clip the number of rows - targetY = -y; - cropped = true; - y = 0; - } - - if (x + w > width) { - w = width - x; - cropped = true; - } - if (y + h > height) { - h = height - y; - cropped = true; - } - - if (w < 0) { - w = 0; - } - if (h < 0) { - h = 0; - } - - int targetFormat = format; - if (cropped && format == RGB) { - targetFormat = ARGB; - } - - PImage target = new PImage(targetWidth, targetHeight, targetFormat); - target.parent = parent; // parent may be null so can't use createImage() - if (w > 0 && h > 0) { - getImpl(x, y, w, h, target, targetX, targetY); - Bitmap nat = Bitmap.createBitmap(target.pixels, targetWidth, targetHeight, Config.ARGB_8888); - target.setNative(nat); - } - return target; - } - - - /** - * Internal function to actually handle getting a block of pixels that - * has already been properly cropped to a valid region. That is, x/y/w/h - * are guaranteed to be inside the image space, so the implementation can - * use the fastest possible pixel copying method. - */ - protected void getImpl(int sourceX, int sourceY, - int sourceWidth, int sourceHeight, - PImage target, int targetX, int targetY) { - if (bitmap != null) { - bitmap.getPixels(target.pixels, - targetY*target.width + targetX, target.width, - sourceX, sourceY, sourceWidth, sourceHeight); - } else if (pixels != null) { - int sourceIndex = sourceY*width + sourceX; - int targetIndex = targetY*target.width + targetX; - for (int row = 0; row < sourceHeight; row++) { - System.arraycopy(pixels, sourceIndex, target.pixels, targetIndex, sourceWidth); - sourceIndex += width; - targetIndex += target.width; - } - } - } - - - /** - * Returns a copy of this PImage. Equivalent to get(0, 0, width, height). - */ - public PImage get() { - // Formerly this used clone(), which caused memory problems. - // http://code.google.com/p/processing/issues/detail?id=42 - return get(0, 0, width, height); - } - - - public PImage copy() { - return get(0, 0, pixelWidth, pixelHeight); - } - - - /** - * Set a single pixel to the specified color. - */ - public void set(int x, int y, int c) { - if (pixels == null) { - bitmap.setPixel(x, y, c); - - } else { - if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return; - pixels[y*width + x] = c; - updatePixelsImpl(x, y, 1, 1); // slow? - } - } - - - /** - * Efficient method of drawing an image's pixels directly to this surface. - * No variations are employed, meaning that any scale, tint, or imageMode - * settings will be ignored. - */ - public void set(int x, int y, PImage img) { - if (img.format == ALPHA) { - // set() doesn't really make sense for an ALPHA image, since it - // directly replaces pixels and does no blending. - throw new IllegalArgumentException("set() not available for ALPHA images"); - } - - int sx = 0; - int sy = 0; - int sw = img.width; - int sh = img.height; - - if (x < 0) { // off left edge - sx -= x; - sw += x; - x = 0; - } - if (y < 0) { // off top edge - sy -= y; - sh += y; - y = 0; - } - if (x + sw > width) { // off right edge - sw = width - x; - } - if (y + sh > height) { // off bottom edge - sh = height - y; - } - - // this could be nonexistent - if ((sw <= 0) || (sh <= 0)) return; - - setImpl(img, sx, sy, sw, sh, x, y); - } - - - /** - * Internal function to actually handle setting a block of pixels that - * has already been properly cropped from the image to a valid region. - */ - protected void setImpl(PImage sourceImage, - int sourceX, int sourceY, - int sourceWidth, int sourceHeight, - int targetX, int targetY) { - if (sourceImage.pixels == null) { - sourceImage.loadPixels(); - } - - // if this.pixels[] is null, copying directly into this.bitmap - if (pixels == null) { - // if this.pixels[] is null, this.bitmap cannot be null - // make sure the bitmap is writable - if (!bitmap.isMutable()) { - // create a mutable version of this bitmap - bitmap = bitmap.copy(Config.ARGB_8888, true); - } - - // copy from src.pixels to this.bitmap - int offset = sourceY * sourceImage.width + sourceX; - bitmap.setPixels(sourceImage.pixels, - offset, sourceImage.width, - targetX, targetY, sourceWidth, sourceHeight); - - } else { // pixels != null - // copy into this.pixels[] and mark as modified - int srcOffset = sourceY * sourceImage.width + sourceX; - int dstOffset = targetY * width + targetX; - for (int y = sourceY; y < sourceY + sourceHeight; y++) { - System.arraycopy(sourceImage.pixels, srcOffset, pixels, dstOffset, sourceWidth); - srcOffset += sourceImage.width; - dstOffset += width; - } - updatePixelsImpl(targetX, targetY, sourceWidth, sourceHeight); - } - } - - - - ////////////////////////////////////////////////////////////// - - // ALPHA CHANNEL - - - /** - * Set alpha channel for an image. Black colors in the source - * image will make the destination image completely transparent, - * and white will make things fully opaque. Gray values will - * be in-between steps. - *

      - * Strictly speaking the "blue" value from the source image is - * used as the alpha color. For a fully grayscale image, this - * is correct, but for a color image it's not 100% accurate. - * For a more accurate conversion, first use filter(GRAY) - * which will make the image into a "correct" grayscake by - * performing a proper luminance-based conversion. - */ - public void mask(int alpha[]) { - loadPixels(); - // don't execute if mask image is different size - if (alpha.length != pixels.length) { - throw new RuntimeException("The PImage used with mask() must be " + - "the same size as the applet."); - } - for (int i = 0; i < pixels.length; i++) { - pixels[i] = ((alpha[i] & 0xff) << 24) | (pixels[i] & 0xffffff); - } - format = ARGB; - updatePixels(); - } - - - /** - * Set alpha channel for an image using another image as the source. - */ - public void mask(PImage alpha) { - if (alpha.pixels == null) { - // if pixels haven't been loaded by the user, then only load them - // temporarily to save memory when finished. - alpha.loadPixels(); - mask(alpha.pixels); - alpha.pixels = null; - } else { - mask(alpha.pixels); - } - } - - - - ////////////////////////////////////////////////////////////// - - // IMAGE FILTERS - - - /** - * Method to apply a variety of basic filters to this image. - *

      - *

        - *
      • filter(BLUR) provides a basic blur. - *
      • filter(GRAY) converts the image to grayscale based on luminance. - *
      • filter(INVERT) will invert the color components in the image. - *
      • filter(OPAQUE) set all the high bits in the image to opaque - *
      • filter(THRESHOLD) converts the image to black and white. - *
      • filter(DILATE) grow white/light areas - *
      • filter(ERODE) shrink white/light areas - *
      - * Luminance conversion code contributed by - * toxi - *

      - * Gaussian blur code contributed by - * Mario Klingemann - */ - public void filter(int kind) { - loadPixels(); - - switch (kind) { - case BLUR: - // TODO write basic low-pass filter blur here - // what does photoshop do on the edges with this guy? - // better yet.. why bother? just use gaussian with radius 1 - filter(BLUR, 1); - break; - - case GRAY: - if (format == ALPHA) { - // for an alpha image, convert it to an opaque grayscale - for (int i = 0; i < pixels.length; i++) { - int col = 255 - pixels[i]; - pixels[i] = 0xff000000 | (col << 16) | (col << 8) | col; - } - format = RGB; - - } else { - // Converts RGB image data into grayscale using - // weighted RGB components, and keeps alpha channel intact. - // [toxi 040115] - for (int i = 0; i < pixels.length; i++) { - int col = pixels[i]; - // luminance = 0.3*red + 0.59*green + 0.11*blue - // 0.30 * 256 = 77 - // 0.59 * 256 = 151 - // 0.11 * 256 = 28 - int lum = (77*(col>>16&0xff) + 151*(col>>8&0xff) + 28*(col&0xff))>>8; - pixels[i] = (col & ALPHA_MASK) | lum<<16 | lum<<8 | lum; - } - } - break; - - case INVERT: - for (int i = 0; i < pixels.length; i++) { - //pixels[i] = 0xff000000 | - pixels[i] ^= 0xffffff; - } - break; - - case POSTERIZE: - throw new RuntimeException("Use filter(POSTERIZE, int levels) " + - "instead of filter(POSTERIZE)"); - - case RGB: - for (int i = 0; i < pixels.length; i++) { - pixels[i] |= 0xff000000; - } - format = RGB; - break; - - case THRESHOLD: - filter(THRESHOLD, 0.5f); - break; - - // [toxi20050728] added new filters - case ERODE: - dilate(true); - break; - - case DILATE: - dilate(false); - break; - } - updatePixels(); // mark as modified - } - - - /** - * Method to apply a variety of basic filters to this image. - * These filters all take a parameter. - *

      - *

        - *
      • filter(BLUR, int radius) performs a gaussian blur of the - * specified radius. - *
      • filter(POSTERIZE, int levels) will posterize the image to - * between 2 and 255 levels. - *
      • filter(THRESHOLD, float center) allows you to set the - * center point for the threshold. It takes a value from 0 to 1.0. - *
      - * Gaussian blur code contributed by - * Mario Klingemann - * and later updated by toxi for better speed. - */ - public void filter(int kind, float param) { - loadPixels(); - - switch (kind) { - case BLUR: - if (format == ALPHA) - blurAlpha(param); - else if (format == ARGB) - blurARGB(param); - else - blurRGB(param); - break; - - case GRAY: - throw new RuntimeException("Use filter(GRAY) instead of " + - "filter(GRAY, param)"); - - case INVERT: - throw new RuntimeException("Use filter(INVERT) instead of " + - "filter(INVERT, param)"); - - case OPAQUE: - throw new RuntimeException("Use filter(OPAQUE) instead of " + - "filter(OPAQUE, param)"); - - case POSTERIZE: - int levels = (int)param; - if ((levels < 2) || (levels > 255)) { - throw new RuntimeException("Levels must be between 2 and 255 for " + - "filter(POSTERIZE, levels)"); - } - int levels1 = levels - 1; - for (int i = 0; i < pixels.length; i++) { - int rlevel = (pixels[i] >> 16) & 0xff; - int glevel = (pixels[i] >> 8) & 0xff; - int blevel = pixels[i] & 0xff; - rlevel = (((rlevel * levels) >> 8) * 255) / levels1; - glevel = (((glevel * levels) >> 8) * 255) / levels1; - blevel = (((blevel * levels) >> 8) * 255) / levels1; - pixels[i] = ((0xff000000 & pixels[i]) | - (rlevel << 16) | - (glevel << 8) | - blevel); - } - break; - - case THRESHOLD: // greater than or equal to the threshold - int thresh = (int) (param * 255); - for (int i = 0; i < pixels.length; i++) { - int max = Math.max((pixels[i] & RED_MASK) >> 16, - Math.max((pixels[i] & GREEN_MASK) >> 8, - (pixels[i] & BLUE_MASK))); - pixels[i] = (pixels[i] & ALPHA_MASK) | - ((max < thresh) ? 0x000000 : 0xffffff); - } - break; - - // [toxi20050728] added new filters - case ERODE: - throw new RuntimeException("Use filter(ERODE) instead of " + - "filter(ERODE, param)"); - case DILATE: - throw new RuntimeException("Use filter(DILATE) instead of " + - "filter(DILATE, param)"); - } - updatePixels(); // mark as modified - } - - - /** - * Optimized code for building the blur kernel. - * further optimized blur code (approx. 15% for radius=20) - * bigger speed gains for larger radii (~30%) - * added support for various image types (ALPHA, RGB, ARGB) - * [toxi 050728] - */ - protected void buildBlurKernel(float r) { - int radius = (int) (r * 3.5f); - radius = (radius < 1) ? 1 : ((radius < 248) ? radius : 248); - if (blurRadius != radius) { - blurRadius = radius; - blurKernelSize = 1 + blurRadius<<1; - blurKernel = new int[blurKernelSize]; - blurMult = new int[blurKernelSize][256]; - - int bk,bki; - int[] bm,bmi; - - for (int i = 1, radiusi = radius - 1; i < radius; i++) { - blurKernel[radius+i] = blurKernel[radiusi] = bki = radiusi * radiusi; - bm=blurMult[radius+i]; - bmi=blurMult[radiusi--]; - for (int j = 0; j < 256; j++) - bm[j] = bmi[j] = bki*j; - } - bk = blurKernel[radius] = radius * radius; - bm = blurMult[radius]; - for (int j = 0; j < 256; j++) - bm[j] = bk*j; - } - } - - - protected void blurAlpha(float r) { - int sum, cb; - int read, ri, ym, ymi, bk0; - int b2[] = new int[pixels.length]; - int yi = 0; - - buildBlurKernel(r); - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - //cb = cg = cr = sum = 0; - cb = sum = 0; - read = x - blurRadius; - if (read<0) { - bk0=-read; - read=0; - } else { - if (read >= width) - break; - bk0=0; - } - for (int i = bk0; i < blurKernelSize; i++) { - if (read >= width) - break; - int c = pixels[read + yi]; - int[] bm=blurMult[i]; - cb += bm[c & BLUE_MASK]; - sum += blurKernel[i]; - read++; - } - ri = yi + x; - b2[ri] = cb / sum; - } - yi += width; - } - - yi = 0; - ym=-blurRadius; - ymi=ym*width; - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - //cb = cg = cr = sum = 0; - cb = sum = 0; - if (ym<0) { - bk0 = ri = -ym; - read = x; - } else { - if (ym >= height) - break; - bk0 = 0; - ri = ym; - read = x + ymi; - } - for (int i = bk0; i < blurKernelSize; i++) { - if (ri >= height) - break; - int[] bm=blurMult[i]; - cb += bm[b2[read]]; - sum += blurKernel[i]; - ri++; - read += width; - } - pixels[x+yi] = (cb/sum); - } - yi += width; - ymi += width; - ym++; - } - } - - - protected void blurRGB(float r) { - int sum, cr, cg, cb; //, k; - int /*pixel,*/ read, ri, /*roff,*/ ym, ymi, /*riw,*/ bk0; - int r2[] = new int[pixels.length]; - int g2[] = new int[pixels.length]; - int b2[] = new int[pixels.length]; - int yi = 0; - - buildBlurKernel(r); - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - cb = cg = cr = sum = 0; - read = x - blurRadius; - if (read<0) { - bk0=-read; - read=0; - } else { - if (read >= width) - break; - bk0=0; - } - for (int i = bk0; i < blurKernelSize; i++) { - if (read >= width) - break; - int c = pixels[read + yi]; - int[] bm=blurMult[i]; - cr += bm[(c & RED_MASK) >> 16]; - cg += bm[(c & GREEN_MASK) >> 8]; - cb += bm[c & BLUE_MASK]; - sum += blurKernel[i]; - read++; - } - ri = yi + x; - r2[ri] = cr / sum; - g2[ri] = cg / sum; - b2[ri] = cb / sum; - } - yi += width; - } - - yi = 0; - ym=-blurRadius; - ymi=ym*width; - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - cb = cg = cr = sum = 0; - if (ym<0) { - bk0 = ri = -ym; - read = x; - } else { - if (ym >= height) - break; - bk0 = 0; - ri = ym; - read = x + ymi; - } - for (int i = bk0; i < blurKernelSize; i++) { - if (ri >= height) - break; - int[] bm=blurMult[i]; - cr += bm[r2[read]]; - cg += bm[g2[read]]; - cb += bm[b2[read]]; - sum += blurKernel[i]; - ri++; - read += width; - } - pixels[x+yi] = 0xff000000 | (cr/sum)<<16 | (cg/sum)<<8 | (cb/sum); - } - yi += width; - ymi += width; - ym++; - } - } - - - protected void blurARGB(float r) { - int sum, cr, cg, cb, ca; - int /*pixel,*/ read, ri, /*roff,*/ ym, ymi, /*riw,*/ bk0; - int wh = pixels.length; - int r2[] = new int[wh]; - int g2[] = new int[wh]; - int b2[] = new int[wh]; - int a2[] = new int[wh]; - int yi = 0; - - buildBlurKernel(r); - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - cb = cg = cr = ca = sum = 0; - read = x - blurRadius; - if (read<0) { - bk0=-read; - read=0; - } else { - if (read >= width) - break; - bk0=0; - } - for (int i = bk0; i < blurKernelSize; i++) { - if (read >= width) - break; - int c = pixels[read + yi]; - int[] bm=blurMult[i]; - ca += bm[(c & ALPHA_MASK) >>> 24]; - cr += bm[(c & RED_MASK) >> 16]; - cg += bm[(c & GREEN_MASK) >> 8]; - cb += bm[c & BLUE_MASK]; - sum += blurKernel[i]; - read++; - } - ri = yi + x; - a2[ri] = ca / sum; - r2[ri] = cr / sum; - g2[ri] = cg / sum; - b2[ri] = cb / sum; - } - yi += width; - } - - yi = 0; - ym=-blurRadius; - ymi=ym*width; - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - cb = cg = cr = ca = sum = 0; - if (ym<0) { - bk0 = ri = -ym; - read = x; - } else { - if (ym >= height) - break; - bk0 = 0; - ri = ym; - read = x + ymi; - } - for (int i = bk0; i < blurKernelSize; i++) { - if (ri >= height) - break; - int[] bm=blurMult[i]; - ca += bm[a2[read]]; - cr += bm[r2[read]]; - cg += bm[g2[read]]; - cb += bm[b2[read]]; - sum += blurKernel[i]; - ri++; - read += width; - } - pixels[x+yi] = (ca/sum)<<24 | (cr/sum)<<16 | (cg/sum)<<8 | (cb/sum); - } - yi += width; - ymi += width; - ym++; - } - } - - - /** - * Generic dilate/erode filter using luminance values - * as decision factor. [toxi 050728] - */ - protected void dilate(boolean isInverted) { - int currIdx=0; - int maxIdx=pixels.length; - int[] out=new int[maxIdx]; - - if (!isInverted) { - // erosion (grow light areas) - while (currIdx=maxRowIdx) - idxRight=currIdx; - if (idxUp<0) - idxUp=0; - if (idxDown>=maxIdx) - idxDown=currIdx; - - int colUp=pixels[idxUp]; - int colLeft=pixels[idxLeft]; - int colDown=pixels[idxDown]; - int colRight=pixels[idxRight]; - - // compute luminance - int currLum = - 77*(colOrig>>16&0xff) + 151*(colOrig>>8&0xff) + 28*(colOrig&0xff); - int lumLeft = - 77*(colLeft>>16&0xff) + 151*(colLeft>>8&0xff) + 28*(colLeft&0xff); - int lumRight = - 77*(colRight>>16&0xff) + 151*(colRight>>8&0xff) + 28*(colRight&0xff); - int lumUp = - 77*(colUp>>16&0xff) + 151*(colUp>>8&0xff) + 28*(colUp&0xff); - int lumDown = - 77*(colDown>>16&0xff) + 151*(colDown>>8&0xff) + 28*(colDown&0xff); - - if (lumLeft>currLum) { - colOut=colLeft; - currLum=lumLeft; - } - if (lumRight>currLum) { - colOut=colRight; - currLum=lumRight; - } - if (lumUp>currLum) { - colOut=colUp; - currLum=lumUp; - } - if (lumDown>currLum) { - colOut=colDown; - currLum=lumDown; - } - out[currIdx++]=colOut; - } - } - } else { - // dilate (grow dark areas) - while (currIdx=maxRowIdx) - idxRight=currIdx; - if (idxUp<0) - idxUp=0; - if (idxDown>=maxIdx) - idxDown=currIdx; - - int colUp=pixels[idxUp]; - int colLeft=pixels[idxLeft]; - int colDown=pixels[idxDown]; - int colRight=pixels[idxRight]; - - // compute luminance - int currLum = - 77*(colOrig>>16&0xff) + 151*(colOrig>>8&0xff) + 28*(colOrig&0xff); - int lumLeft = - 77*(colLeft>>16&0xff) + 151*(colLeft>>8&0xff) + 28*(colLeft&0xff); - int lumRight = - 77*(colRight>>16&0xff) + 151*(colRight>>8&0xff) + 28*(colRight&0xff); - int lumUp = - 77*(colUp>>16&0xff) + 151*(colUp>>8&0xff) + 28*(colUp&0xff); - int lumDown = - 77*(colDown>>16&0xff) + 151*(colDown>>8&0xff) + 28*(colDown&0xff); - - if (lumLeft - *
    • REPLACE - destination colour equals colour of source pixel: C = A. - * Sometimes called "Normal" or "Copy" in other software. - * - *
    • BLEND - linear interpolation of colours: - * C = A*factor + B - * - *
    • ADD - additive blending with white clip: - * C = min(A*factor + B, 255). - * Clipped to 0..255, Photoshop calls this "Linear Burn", - * and Director calls it "Add Pin". - * - *
    • SUBTRACT - substractive blend with black clip: - * C = max(B - A*factor, 0). - * Clipped to 0..255, Photoshop calls this "Linear Dodge", - * and Director calls it "Subtract Pin". - * - *
    • DARKEST - only the darkest colour succeeds: - * C = min(A*factor, B). - * Illustrator calls this "Darken". - * - *
    • LIGHTEST - only the lightest colour succeeds: - * C = max(A*factor, B). - * Illustrator calls this "Lighten". - * - *
    • DIFFERENCE - subtract colors from underlying image. - * - *
    • EXCLUSION - similar to DIFFERENCE, but less extreme. - * - *
    • MULTIPLY - Multiply the colors, result will always be darker. - * - *
    • SCREEN - Opposite multiply, uses inverse values of the colors. - * - *
    • OVERLAY - A mix of MULTIPLY and SCREEN. Multiplies dark values, - * and screens light values. - * - *
    • HARD_LIGHT - SCREEN when greater than 50% gray, MULTIPLY when lower. - * - *
    • SOFT_LIGHT - Mix of DARKEST and LIGHTEST. - * Works like OVERLAY, but not as harsh. - * - *
    • DODGE - Lightens light tones and increases contrast, ignores darks. - * Called "Color Dodge" in Illustrator and Photoshop. - * - *
    • BURN - Darker areas are applied, increasing contrast, ignores lights. - * Called "Color Burn" in Illustrator and Photoshop. - *
    - *

    A useful reference for blending modes and their algorithms can be - * found in the SVG - * specification.

    - *

    It is important to note that Processing uses "fast" code, not - * necessarily "correct" code. No biggie, most software does. A nitpicker - * can find numerous "off by 1 division" problems in the blend code where - * >>8 or >>7 is used when strictly speaking - * /255.0 or /127.0 should have been used.

    - *

    For instance, exclusion (not intended for real-time use) reads - * r1 + r2 - ((2 * r1 * r2) / 255) because 255 == 1.0 - * not 256 == 1.0. In other words, (255*255)>>8 is not - * the same as (255*255)/255. But for real-time use the shifts - * are preferrable, and the difference is insignificant for applications - * built with Processing.

    - */ - static public int blendColor(int c1, int c2, int mode) { // ignore - switch (mode) { - case REPLACE: return c2; - case BLEND: return blend_blend(c1, c2); - - case ADD: return blend_add_pin(c1, c2); - case SUBTRACT: return blend_sub_pin(c1, c2); - - case LIGHTEST: return blend_lightest(c1, c2); - case DARKEST: return blend_darkest(c1, c2); - - case DIFFERENCE: return blend_difference(c1, c2); - case EXCLUSION: return blend_exclusion(c1, c2); - - case MULTIPLY: return blend_multiply(c1, c2); - case SCREEN: return blend_screen(c1, c2); - - case HARD_LIGHT: return blend_hard_light(c1, c2); - case SOFT_LIGHT: return blend_soft_light(c1, c2); - case OVERLAY: return blend_overlay(c1, c2); - - case DODGE: return blend_dodge(c1, c2); - case BURN: return blend_burn(c1, c2); - } - return 0; - } - - - /** - * Blends one area of this image to another area. - * @see processing.core.PImage#blendColor(int,int,int) - */ - public void blend(int sx, int sy, int sw, int sh, - int dx, int dy, int dw, int dh, int mode) { - blend(this, sx, sy, sw, sh, dx, dy, dw, dh, mode); - } - - - /** - * Copies area of one image into another PImage object. - * @see processing.core.PImage#blendColor(int,int,int) - */ - public void blend(PImage src, - int sx, int sy, int sw, int sh, - int dx, int dy, int dw, int dh, int mode) { - int sx2 = sx + sw; - int sy2 = sy + sh; - int dx2 = dx + dw; - int dy2 = dy + dh; - - loadPixels(); - if (src == this) { - if (intersect(sx, sy, sx2, sy2, dx, dy, dx2, dy2)) { - blit_resize(get(sx, sy, sw, sh), - 0, 0, sw, sh, - pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode); - } else { - // same as below, except skip the loadPixels() because it'd be redundant - blit_resize(src, sx, sy, sx2, sy2, - pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode); - } - } else { - src.loadPixels(); - blit_resize(src, sx, sy, sx2, sy2, - pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode); - //src.updatePixels(); - } - updatePixels(); - } - - - /** - * Check to see if two rectangles intersect one another - */ - private boolean intersect(int sx1, int sy1, int sx2, int sy2, - int dx1, int dy1, int dx2, int dy2) { - int sw = sx2 - sx1 + 1; - int sh = sy2 - sy1 + 1; - int dw = dx2 - dx1 + 1; - int dh = dy2 - dy1 + 1; - - if (dx1 < sx1) { - dw += dx1 - sx1; - if (dw > sw) { - dw = sw; - } - } else { - int w = sw + sx1 - dx1; - if (dw > w) { - dw = w; - } - } - if (dy1 < sy1) { - dh += dy1 - sy1; - if (dh > sh) { - dh = sh; - } - } else { - int h = sh + sy1 - dy1; - if (dh > h) { - dh = h; - } - } - return !(dw <= 0 || dh <= 0); - } - - - ////////////////////////////////////////////////////////////// - - - /** - * Internal blitter/resizer/copier from toxi. - * Uses bilinear filtering if smooth() has been enabled - * 'mode' determines the blending mode used in the process. - */ - private void blit_resize(PImage img, - int srcX1, int srcY1, int srcX2, int srcY2, - int[] destPixels, int screenW, int screenH, - int destX1, int destY1, int destX2, int destY2, - int mode) { - if (srcX1 < 0) srcX1 = 0; - if (srcY1 < 0) srcY1 = 0; - if (srcX2 > img.pixelWidth) srcX2 = img.pixelWidth; - if (srcY2 > img.pixelHeight) srcY2 = img.pixelHeight; - - int srcW = srcX2 - srcX1; - int srcH = srcY2 - srcY1; - int destW = destX2 - destX1; - int destH = destY2 - destY1; - - boolean smooth = true; // may as well go with the smoothing these days - - if (!smooth) { - srcW++; srcH++; - } - - if (destW <= 0 || destH <= 0 || - srcW <= 0 || srcH <= 0 || - destX1 >= screenW || destY1 >= screenH || - srcX1 >= img.pixelWidth || srcY1 >= img.pixelHeight) { - return; - } - - int dx = (int) (srcW / (float) destW * PRECISIONF); - int dy = (int) (srcH / (float) destH * PRECISIONF); - - srcXOffset = destX1 < 0 ? -destX1 * dx : srcX1 * PRECISIONF; - srcYOffset = destY1 < 0 ? -destY1 * dy : srcY1 * PRECISIONF; - - if (destX1 < 0) { - destW += destX1; - destX1 = 0; - } - if (destY1 < 0) { - destH += destY1; - destY1 = 0; - } - - destW = min(destW, screenW - destX1); - destH = min(destH, screenH - destY1); - - int destOffset = destY1 * screenW + destX1; - srcBuffer = img.pixels; - - if (smooth) { - // use bilinear filtering - iw = img.pixelWidth; - iw1 = img.pixelWidth - 1; - ih1 = img.pixelHeight - 1; - - switch (mode) { - - case BLEND: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - // davbol - renamed old blend_multiply to blend_blend - destPixels[destOffset + x] = - blend_blend(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case ADD: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_add_pin(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case SUBTRACT: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_sub_pin(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case LIGHTEST: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_lightest(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case DARKEST: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_darkest(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case REPLACE: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = filter_bilinear(); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case DIFFERENCE: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_difference(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case EXCLUSION: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_exclusion(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case MULTIPLY: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_multiply(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case SCREEN: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_screen(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case OVERLAY: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_overlay(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case HARD_LIGHT: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_hard_light(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case SOFT_LIGHT: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_soft_light(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - // davbol - proposed 2007-01-09 - case DODGE: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_dodge(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case BURN: - for (int y = 0; y < destH; y++) { - filter_new_scanline(); - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_burn(destPixels[destOffset + x], filter_bilinear()); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - } - - } else { - // nearest neighbour scaling (++fast!) - switch (mode) { - - case BLEND: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - // davbol - renamed old blend_multiply to blend_blend - destPixels[destOffset + x] = - blend_blend(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case ADD: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_add_pin(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case SUBTRACT: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_sub_pin(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case LIGHTEST: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_lightest(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case DARKEST: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_darkest(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case REPLACE: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = srcBuffer[sY + (sX >> PRECISIONB)]; - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case DIFFERENCE: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_difference(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case EXCLUSION: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_exclusion(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case MULTIPLY: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_multiply(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case SCREEN: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_screen(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case OVERLAY: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_overlay(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case HARD_LIGHT: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_hard_light(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case SOFT_LIGHT: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_soft_light(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - // davbol - proposed 2007-01-09 - case DODGE: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_dodge(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - case BURN: - for (int y = 0; y < destH; y++) { - sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; - for (int x = 0; x < destW; x++) { - destPixels[destOffset + x] = - blend_burn(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); - sX += dx; - } - destOffset += screenW; - srcYOffset += dy; - } - break; - - } - } - } - - - private void filter_new_scanline() { - sX = srcXOffset; - fracV = srcYOffset & PREC_MAXVAL; - ifV = PREC_MAXVAL - fracV + 1; - v1 = (srcYOffset >> PRECISIONB) * iw; - v2 = min((srcYOffset >> PRECISIONB) + 1, ih1) * iw; - } - - - private int filter_bilinear() { - fracU = sX & PREC_MAXVAL; - ifU = PREC_MAXVAL - fracU + 1; - ul = (ifU * ifV) >> PRECISIONB; - ll = ifU - ul; - ur = ifV - ul; - lr = PREC_MAXVAL + 1 - ul - ll - ur; - u1 = (sX >> PRECISIONB); - u2 = min(u1 + 1, iw1); - - // get color values of the 4 neighbouring texels - cUL = srcBuffer[v1 + u1]; - cUR = srcBuffer[v1 + u2]; - cLL = srcBuffer[v2 + u1]; - cLR = srcBuffer[v2 + u2]; - - r = ((ul*((cUL&RED_MASK)>>16) + ll*((cLL&RED_MASK)>>16) + - ur*((cUR&RED_MASK)>>16) + lr*((cLR&RED_MASK)>>16)) - << PREC_RED_SHIFT) & RED_MASK; - - g = ((ul*(cUL&GREEN_MASK) + ll*(cLL&GREEN_MASK) + - ur*(cUR&GREEN_MASK) + lr*(cLR&GREEN_MASK)) - >>> PRECISIONB) & GREEN_MASK; - - b = (ul*(cUL&BLUE_MASK) + ll*(cLL&BLUE_MASK) + - ur*(cUR&BLUE_MASK) + lr*(cLR&BLUE_MASK)) - >>> PRECISIONB; - - a = ((ul*((cUL&ALPHA_MASK)>>>24) + ll*((cLL&ALPHA_MASK)>>>24) + - ur*((cUR&ALPHA_MASK)>>>24) + lr*((cLR&ALPHA_MASK)>>>24)) - << PREC_ALPHA_SHIFT) & ALPHA_MASK; - - return a | r | g | b; - } - - - - ////////////////////////////////////////////////////////////// - - // internal blending methods - - - private static int min(int a, int b) { - return (a < b) ? a : b; - } - - - private static int max(int a, int b) { - return (a > b) ? a : b; - } - - - ///////////////////////////////////////////////////////////// - - // BLEND MODE IMPLEMENTATIONS - - /* - * Jakub Valtar - * - * All modes use SRC alpha to interpolate between DST and the result of - * the operation: - * - * R = (1 - SRC_ALPHA) * DST + SRC_ALPHA * - * - * Comments above each mode only specify the formula of its operation. - * - * These implementations treat alpha 127 (=255/2) as a perfect 50 % mix. - * - * One alpha value between 126 and 127 is intentionally left out, - * so the step 126 -> 127 is twice as big compared to other steps. - * This is because our colors are in 0..255 range, but we divide - * by right shifting 8 places (=256) which is much faster than - * (correct) float division by 255.0f. The missing value was placed - * between 126 and 127, because limits of the range (near 0 and 255) and - * the middle value (127) have to blend correctly. - * - * Below you will often see RED and BLUE channels (RB) manipulated together - * and GREEN channel (GN) manipulated separately. It is sometimes possible - * because the operation won't use more than 16 bits, so we process the RED - * channel in the upper 16 bits and BLUE channel in the lower 16 bits. This - * decreases the number of operations per pixel and thus makes things faster. - * - * Some of the modes are hand tweaked (various +1s etc.) to be more accurate - * and to produce correct values in extremes. Below is a sketch you can use - * to check any blending function for - * - * 1) Discrepancies between color channels: - * - highlighted by the offending color - * 2) Behavior at extremes (set colorCount to 256): - * - values of all corners are printed to the console - * 3) Rounding errors: - * - set colorCount to lower value to better see color bands - * - -// use powers of 2 in range 2..256 -// to better see color bands -final int colorCount = 256; - -final int blockSize = 3; - -void settings() { - size(blockSize * 256, blockSize * 256); -} - -void setup() { } - -void draw() { - noStroke(); - colorMode(RGB, colorCount-1); - int alpha = (mouseX / blockSize) << 24; - int r, g, b, r2, g2, b2 = 0; - for (int x = 0; x <= 0xFF; x++) { - for (int y = 0; y <= 0xFF; y++) { - int dst = (x << 16) | (x << 8) | x; - int src = (y << 16) | (y << 8) | y | alpha; - int result = testFunction(dst, src); - r = r2 = (result >> 16 & 0xFF); - g = g2 = (result >> 8 & 0xFF); - b = b2 = (result >> 0 & 0xFF); - if (r != g && r != b) r2 = (128 + r2) % 255; - if (g != r && g != b) g2 = (128 + g2) % 255; - if (b != r && b != g) b2 = (128 + b2) % 255; - fill(r2 % colorCount, g2 % colorCount, b2 % colorCount); - rect(x * blockSize, y * blockSize, blockSize, blockSize); - } - } - println( - "alpha:", mouseX/blockSize, - "TL:", hex(get(0, 0)), - "TR:", hex(get(width-1, 0)), - "BR:", hex(get(width-1, height-1)), - "BL:", hex(get(0, height-1))); -} - -int testFunction(int dst, int src) { - // your function here - return dst; -} - - * - * - */ - - private static final int RB_MASK = 0x00FF00FF; - private static final int GN_MASK = 0x0000FF00; - - /** - * Blend - * O = S - */ - private static int blend_blend(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - return min((dst >>> 24) + a, 0xFF) << 24 | - ((dst & RB_MASK) * d_a + (src & RB_MASK) * s_a) >>> 8 & RB_MASK | - ((dst & GN_MASK) * d_a + (src & GN_MASK) * s_a) >>> 8 & GN_MASK; - } - - - /** - * Add - * O = MIN(D + S, 1) - */ - private static int blend_add_pin(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - - int rb = (dst & RB_MASK) + ((src & RB_MASK) * s_a >>> 8 & RB_MASK); - int gn = (dst & GN_MASK) + ((src & GN_MASK) * s_a >>> 8); - - return min((dst >>> 24) + a, 0xFF) << 24 | - min(rb & 0xFFFF0000, RED_MASK) | - min(gn & 0x00FFFF00, GREEN_MASK) | - min(rb & 0x0000FFFF, BLUE_MASK); - } - - - /** - * Subtract - * O = MAX(0, D - S) - */ - private static int blend_sub_pin(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - - int rb = ((src & RB_MASK) * s_a >>> 8); - int gn = ((src & GREEN_MASK) * s_a >>> 8); - - return min((dst >>> 24) + a, 0xFF) << 24 | - max((dst & RED_MASK) - (rb & RED_MASK), 0) | - max((dst & GREEN_MASK) - (gn & GREEN_MASK), 0) | - max((dst & BLUE_MASK) - (rb & BLUE_MASK), 0); - } - - - /** - * Lightest - * O = MAX(D, S) - */ - private static int blend_lightest(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - int rb = max(src & RED_MASK, dst & RED_MASK) | - max(src & BLUE_MASK, dst & BLUE_MASK); - int gn = max(src & GREEN_MASK, dst & GREEN_MASK); - - return min((dst >>> 24) + a, 0xFF) << 24 | - ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK | - ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK; - } - - - /** - * Darkest - * O = MIN(D, S) - */ - private static int blend_darkest(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - int rb = min(src & RED_MASK, dst & RED_MASK) | - min(src & BLUE_MASK, dst & BLUE_MASK); - int gn = min(src & GREEN_MASK, dst & GREEN_MASK); - - return min((dst >>> 24) + a, 0xFF) << 24 | - ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK | - ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK; - } - - - /** - * Difference - * O = ABS(D - S) - */ - private static int blend_difference(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - int r = (dst & RED_MASK) - (src & RED_MASK); - int b = (dst & BLUE_MASK) - (src & BLUE_MASK); - int g = (dst & GREEN_MASK) - (src & GREEN_MASK); - - int rb = (r < 0 ? -r : r) | - (b < 0 ? -b : b); - int gn = (g < 0 ? -g : g); - - return min((dst >>> 24) + a, 0xFF) << 24 | - ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK | - ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK; - } - - - /** - * Exclusion - * O = (1 - S)D + S(1 - D) - * O = D + S - 2DS - */ - private static int blend_exclusion(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - int d_rb = dst & RB_MASK; - int d_gn = dst & GN_MASK; - - int s_gn = src & GN_MASK; - - int f_r = (dst & RED_MASK) >> 16; - int f_b = (dst & BLUE_MASK); - - int rb_sub = - ((src & RED_MASK) * (f_r + (f_r >= 0x7F ? 1 : 0)) | - (src & BLUE_MASK) * (f_b + (f_b >= 0x7F ? 1 : 0))) - >>> 7 & 0x01FF01FF; - int gn_sub = s_gn * (d_gn + (d_gn >= 0x7F00 ? 0x100 : 0)) - >>> 15 & 0x0001FF00; - - return min((dst >>> 24) + a, 0xFF) << 24 | - (d_rb * d_a + (d_rb + (src & RB_MASK) - rb_sub) * s_a) >>> 8 & RB_MASK | - (d_gn * d_a + (d_gn + s_gn - gn_sub) * s_a) >>> 8 & GN_MASK; - } - - - /* - * Multiply - * O = DS - */ - private static int blend_multiply(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - int d_gn = dst & GN_MASK; - - int f_r = (dst & RED_MASK) >> 16; - int f_b = (dst & BLUE_MASK); - - int rb = - ((src & RED_MASK) * (f_r + 1) | - (src & BLUE_MASK) * (f_b + 1)) - >>> 8 & RB_MASK; - int gn = - (src & GREEN_MASK) * (d_gn + 0x100) - >>> 16 & GN_MASK; - - return min((dst >>> 24) + a, 0xFF) << 24 | - ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK | - (d_gn * d_a + gn * s_a) >>> 8 & GN_MASK; - } - - - /** - * Screen - * O = 1 - (1 - D)(1 - S) - * O = D + S - DS - */ - private static int blend_screen(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - int d_rb = dst & RB_MASK; - int d_gn = dst & GN_MASK; - - int s_gn = src & GN_MASK; - - int f_r = (dst & RED_MASK) >> 16; - int f_b = (dst & BLUE_MASK); - - int rb_sub = - ((src & RED_MASK) * (f_r + 1) | - (src & BLUE_MASK) * (f_b + 1)) - >>> 8 & RB_MASK; - int gn_sub = s_gn * (d_gn + 0x100) - >>> 16 & GN_MASK; - - return min((dst >>> 24) + a, 0xFF) << 24 | - (d_rb * d_a + (d_rb + (src & RB_MASK) - rb_sub) * s_a) >>> 8 & RB_MASK | - (d_gn * d_a + (d_gn + s_gn - gn_sub) * s_a) >>> 8 & GN_MASK; - } - - - /** - * Overlay - * O = 2 * MULTIPLY(D, S) = 2DS for D < 0.5 - * O = 2 * SCREEN(D, S) - 1 = 2(S + D - DS) - 1 otherwise - */ - private static int blend_overlay(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - int d_r = dst & RED_MASK; - int d_g = dst & GREEN_MASK; - int d_b = dst & BLUE_MASK; - - int s_r = src & RED_MASK; - int s_g = src & GREEN_MASK; - int s_b = src & BLUE_MASK; - - int r = (d_r < 0x800000) ? - d_r * ((s_r >>> 16) + 1) >>> 7 : - 0xFF0000 - ((0x100 - (s_r >>> 16)) * (RED_MASK - d_r) >>> 7); - int g = (d_g < 0x8000) ? - d_g * (s_g + 0x100) >>> 15 : - (0xFF00 - ((0x10000 - s_g) * (GREEN_MASK - d_g) >>> 15)); - int b = (d_b < 0x80) ? - d_b * (s_b + 1) >>> 7 : - (0xFF00 - ((0x100 - s_b) * (BLUE_MASK - d_b) << 1)) >>> 8; - - return min((dst >>> 24) + a, 0xFF) << 24 | - ((dst & RB_MASK) * d_a + ((r | b) & RB_MASK) * s_a) >>> 8 & RB_MASK | - ((dst & GN_MASK) * d_a + (g & GN_MASK) * s_a) >>> 8 & GN_MASK; - } - - - /** - * Hard Light - * O = OVERLAY(S, D) - * - * O = 2 * MULTIPLY(D, S) = 2DS for S < 0.5 - * O = 2 * SCREEN(D, S) - 1 = 2(S + D - DS) - 1 otherwise - */ - private static int blend_hard_light(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - int d_r = dst & RED_MASK; - int d_g = dst & GREEN_MASK; - int d_b = dst & BLUE_MASK; - - int s_r = src & RED_MASK; - int s_g = src & GREEN_MASK; - int s_b = src & BLUE_MASK; - - int r = (s_r < 0x800000) ? - s_r * ((d_r >>> 16) + 1) >>> 7 : - 0xFF0000 - ((0x100 - (d_r >>> 16)) * (RED_MASK - s_r) >>> 7); - int g = (s_g < 0x8000) ? - s_g * (d_g + 0x100) >>> 15 : - (0xFF00 - ((0x10000 - d_g) * (GREEN_MASK - s_g) >>> 15)); - int b = (s_b < 0x80) ? - s_b * (d_b + 1) >>> 7 : - (0xFF00 - ((0x100 - d_b) * (BLUE_MASK - s_b) << 1)) >>> 8; - - return min((dst >>> 24) + a, 0xFF) << 24 | - ((dst & RB_MASK) * d_a + ((r | b) & RB_MASK) * s_a) >>> 8 & RB_MASK | - ((dst & GN_MASK) * d_a + (g & GN_MASK) * s_a) >>> 8 & GN_MASK; - } - - - /** - * Soft Light (Pegtop) - * O = (1 - D) * MULTIPLY(D, S) + D * SCREEN(D, S) - * O = (1 - D) * DS + D * (1 - (1 - D)(1 - S)) - * O = 2DS + DD - 2DDS - */ - private static int blend_soft_light(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - int d_r = dst & RED_MASK; - int d_g = dst & GREEN_MASK; - int d_b = dst & BLUE_MASK; - - int s_r1 = src & RED_MASK >> 16; - int s_g1 = src & GREEN_MASK >> 8; - int s_b1 = src & BLUE_MASK; - - int d_r1 = (d_r >> 16) + (s_r1 < 7F ? 1 : 0); - int d_g1 = (d_g >> 8) + (s_g1 < 7F ? 1 : 0); - int d_b1 = d_b + (s_b1 < 7F ? 1 : 0); - - int r = (s_r1 * d_r >> 7) + 0xFF * d_r1 * (d_r1 + 1) - - ((s_r1 * d_r1 * d_r1) << 1) & RED_MASK; - int g = (s_g1 * d_g << 1) + 0xFF * d_g1 * (d_g1 + 1) - - ((s_g1 * d_g1 * d_g1) << 1) >>> 8 & GREEN_MASK; - int b = (s_b1 * d_b << 9) + 0xFF * d_b1 * (d_b1 + 1) - - ((s_b1 * d_b1 * d_b1) << 1) >>> 16; - - return min((dst >>> 24) + a, 0xFF) << 24 | - ((dst & RB_MASK) * d_a + (r | b) * s_a) >>> 8 & RB_MASK | - ((dst & GN_MASK) * d_a + g * s_a) >>> 8 & GN_MASK; - } - - - /** - * Dodge - * O = D / (1 - S) - */ - private static int blend_dodge(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - int r = (dst & RED_MASK) / (256 - ((src & RED_MASK) >> 16)); - int g = ((dst & GREEN_MASK) << 8) / (256 - ((src & GREEN_MASK) >> 8)); - int b = ((dst & BLUE_MASK) << 8) / (256 - (src & BLUE_MASK)); - - int rb = - (r > 0xFF00 ? 0xFF0000 : ((r << 8) & RED_MASK)) | - (b > 0x00FF ? 0x0000FF : b); - int gn = - (g > 0xFF00 ? 0x00FF00 : (g & GREEN_MASK)); - - return min((dst >>> 24) + a, 0xFF) << 24 | - ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK | - ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK; - } - - - /** - * Burn - * O = 1 - (1 - A) / B - */ - private static int blend_burn(int dst, int src) { - int a = src >>> 24; - - int s_a = a + (a >= 0x7F ? 1 : 0); - int d_a = 0x100 - s_a; - - int r = ((0xFF0000 - (dst & RED_MASK))) / (1 + (src & RED_MASK >> 16)); - int g = ((0x00FF00 - (dst & GREEN_MASK)) << 8) / (1 + (src & GREEN_MASK >> 8)); - int b = ((0x0000FF - (dst & BLUE_MASK)) << 8) / (1 + (src & BLUE_MASK)); - - int rb = RB_MASK - - (r > 0xFF00 ? 0xFF0000 : ((r << 8) & RED_MASK)) - - (b > 0x00FF ? 0x0000FF : b); - int gn = GN_MASK - - (g > 0xFF00 ? 0x00FF00 : (g & GREEN_MASK)); - - return min((dst >>> 24) + a, 0xFF) << 24 | - ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK | - ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK; - } - - - ////////////////////////////////////////////////////////////// - - // FILE I/O - - - static byte TIFF_HEADER[] = { - 77, 77, 0, 42, 0, 0, 0, 8, 0, 9, 0, -2, 0, 4, 0, 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 3, 0, 0, 0, 1, - 0, 0, 0, 0, 1, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 122, 1, 6, 0, 3, 0, - 0, 0, 1, 0, 2, 0, 0, 1, 17, 0, 4, 0, 0, 0, 1, 0, 0, 3, 0, 1, 21, - 0, 3, 0, 0, 0, 1, 0, 3, 0, 0, 1, 22, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, - 1, 23, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8 - }; - - - static final String TIFF_ERROR = - "Error: Processing can only read its own TIFF files."; - - static protected PImage loadTIFF(byte tiff[]) { - if ((tiff[42] != tiff[102]) || // width/height in both places - (tiff[43] != tiff[103])) { - System.err.println(TIFF_ERROR); - return null; - } - - int width = - ((tiff[30] & 0xff) << 8) | (tiff[31] & 0xff); - int height = - ((tiff[42] & 0xff) << 8) | (tiff[43] & 0xff); - - int count = - ((tiff[114] & 0xff) << 24) | - ((tiff[115] & 0xff) << 16) | - ((tiff[116] & 0xff) << 8) | - (tiff[117] & 0xff); - if (count != width * height * 3) { - System.err.println(TIFF_ERROR + " (" + width + ", " + height +")"); - return null; - } - - // check the rest of the header - for (int i = 0; i < TIFF_HEADER.length; i++) { - if ((i == 30) || (i == 31) || (i == 42) || (i == 43) || - (i == 102) || (i == 103) || - (i == 114) || (i == 115) || (i == 116) || (i == 117)) continue; - - if (tiff[i] != TIFF_HEADER[i]) { - System.err.println(TIFF_ERROR + " (" + i + ")"); - return null; - } - } - - PImage outgoing = new PImage(width, height, RGB); - - // Not possible because this method is static, so careful when using it. - // outgoing.parent = parent; - - int index = 768; - count /= 3; - for (int i = 0; i < count; i++) { - outgoing.pixels[i] = - 0xFF000000 | - (tiff[index++] & 0xff) << 16 | - (tiff[index++] & 0xff) << 8 | - (tiff[index++] & 0xff); - } - return outgoing; - } - - - protected boolean saveTIFF(OutputStream output) { - // shutting off the warning, people can figure this out themselves - /* - if (format != RGB) { - System.err.println("Warning: only RGB information is saved with " + - ".tif files. Use .tga or .png for ARGB images and others."); - } - */ - try { - byte tiff[] = new byte[768]; - System.arraycopy(TIFF_HEADER, 0, tiff, 0, TIFF_HEADER.length); - - tiff[30] = (byte) ((width >> 8) & 0xff); - tiff[31] = (byte) ((width) & 0xff); - tiff[42] = tiff[102] = (byte) ((height >> 8) & 0xff); - tiff[43] = tiff[103] = (byte) ((height) & 0xff); - - int count = width*height*3; - tiff[114] = (byte) ((count >> 24) & 0xff); - tiff[115] = (byte) ((count >> 16) & 0xff); - tiff[116] = (byte) ((count >> 8) & 0xff); - tiff[117] = (byte) ((count) & 0xff); - - // spew the header to the disk - output.write(tiff); - - for (int i = 0; i < pixels.length; i++) { - output.write((pixels[i] >> 16) & 0xff); - output.write((pixels[i] >> 8) & 0xff); - output.write(pixels[i] & 0xff); - } - output.flush(); - return true; - - } catch (IOException e) { - e.printStackTrace(); - } - return false; - } - - - /** - * Creates a Targa32 formatted byte sequence of specified - * pixel buffer using RLE compression. - *

    - * Also figured out how to avoid parsing the image upside-down - * (there's a header flag to set the image origin to top-left) - *

    - * Starting with revision 0092, the format setting is taken into account: - *
      - *
    • ALPHA images written as 8bit grayscale (uses lowest byte) - *
    • RGB → 24 bits - *
    • ARGB → 32 bits - *
    - * All versions are RLE compressed. - *

    - * Contributed by toxi 8-10 May 2005, based on this RLE - * specification - */ - protected boolean saveTGA(OutputStream output) { - byte header[] = new byte[18]; - - if (format == ALPHA) { // save ALPHA images as 8bit grayscale - header[2] = 0x0B; - header[16] = 0x08; - header[17] = 0x28; - - } else if (format == RGB) { - header[2] = 0x0A; - header[16] = 24; - header[17] = 0x20; - - } else if (format == ARGB) { - header[2] = 0x0A; - header[16] = 32; - header[17] = 0x28; - - } else { - throw new RuntimeException("Image format not recognized inside save()"); - } - // set image dimensions lo-hi byte order - header[12] = (byte) (width & 0xff); - header[13] = (byte) (width >> 8); - header[14] = (byte) (height & 0xff); - header[15] = (byte) (height >> 8); - - try { - output.write(header); - - int maxLen = height * width; - int index = 0; - int col; //, prevCol; - int[] currChunk = new int[128]; - - // 8bit image exporter is in separate loop - // to avoid excessive conditionals... - if (format == ALPHA) { - while (index < maxLen) { - boolean isRLE = false; - int rle = 1; - currChunk[0] = col = pixels[index] & 0xff; - while (index + rle < maxLen) { - if (col != (pixels[index + rle]&0xff) || rle == 128) { - isRLE = (rle > 1); - break; - } - rle++; - } - if (isRLE) { - output.write(0x80 | (rle - 1)); - output.write(col); - - } else { - rle = 1; - while (index + rle < maxLen) { - int cscan = pixels[index + rle] & 0xff; - if ((col != cscan && rle < 128) || rle < 3) { - currChunk[rle] = col = cscan; - } else { - if (col == cscan) rle -= 2; - break; - } - rle++; - } - output.write(rle - 1); - for (int i = 0; i < rle; i++) output.write(currChunk[i]); - } - index += rle; - } - } else { // export 24/32 bit TARGA - while (index < maxLen) { - boolean isRLE = false; - currChunk[0] = col = pixels[index]; - int rle = 1; - // try to find repeating bytes (min. len = 2 pixels) - // maximum chunk size is 128 pixels - while (index + rle < maxLen) { - if (col != pixels[index + rle] || rle == 128) { - isRLE = (rle > 1); // set flag for RLE chunk - break; - } - rle++; - } - if (isRLE) { - output.write(128 | (rle - 1)); - output.write(col & 0xff); - output.write(col >> 8 & 0xff); - output.write(col >> 16 & 0xff); - if (format == ARGB) output.write(col >>> 24 & 0xff); - - } else { // not RLE - rle = 1; - while (index + rle < maxLen) { - if ((col != pixels[index + rle] && rle < 128) || rle < 3) { - currChunk[rle] = col = pixels[index + rle]; - } else { - // check if the exit condition was the start of - // a repeating colour - if (col == pixels[index + rle]) rle -= 2; - break; - } - rle++; - } - // write uncompressed chunk - output.write(rle - 1); - if (format == ARGB) { - for (int i = 0; i < rle; i++) { - col = currChunk[i]; - output.write(col & 0xff); - output.write(col >> 8 & 0xff); - output.write(col >> 16 & 0xff); - output.write(col >>> 24 & 0xff); - } - } else { - for (int i = 0; i < rle; i++) { - col = currChunk[i]; - output.write(col & 0xff); - output.write(col >> 8 & 0xff); - output.write(col >> 16 & 0xff); - } - } - } - index += rle; - } - } - output.flush(); - return true; - - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - - - /** - * Use ImageIO functions from Java 1.4 and later to handle image save. - * Various formats are supported, typically jpeg, png, bmp, and wbmp. - * To get a list of the supported formats for writing, use:
    - * println(javax.imageio.ImageIO.getReaderFormatNames()) - */ -// protected void saveImageIO(String path) throws IOException { -// try { -// BufferedImage bimage = -// new BufferedImage(width, height, (format == ARGB) ? -// BufferedImage.TYPE_INT_ARGB : -// BufferedImage.TYPE_INT_RGB); -// -// bimage.setRGB(0, 0, width, height, pixels, 0, width); -// -// File file = new File(path); -// String extension = path.substring(path.lastIndexOf('.') + 1); -// -// ImageIO.write(bimage, extension, file); -// -// } catch (Exception e) { -// e.printStackTrace(); -// throw new IOException("image save failed."); -// } -// } - - - protected String[] saveImageFormats; - - /** - * Save this image to disk. - *

    - * As of revision 0100, this function requires an absolute path, - * in order to avoid confusion. To save inside the sketch folder, - * use the function savePath() from PApplet, or use saveFrame() instead. - * As of revision 0116, savePath() is not needed if this object has been - * created (as recommended) via createImage() or createGraphics() or - * one of its neighbors. - *

    - * As of revision 0115, when using Java 1.4 and later, you can write - * to several formats besides tga and tiff. If Java 1.4 is installed - * and the extension used is supported (usually png, jpg, jpeg, bmp, - * and tiff), then those methods will be used to write the image. - * To get a list of the supported formats for writing, use:
    - * println(javax.imageio.ImageIO.getReaderFormatNames()) - *

    - * To use the original built-in image writers, use .tga or .tif as the - * extension, or don't include an extension. When no extension is used, - * the extension .tif will be added to the file name. - *

    - * The ImageIO API claims to support wbmp files, however they probably - * require a black and white image. Basic testing produced a zero-length - * file with no error. - */ - public boolean save(String path) { // ignore - boolean success = false; - - // Make sure the pixel data is ready to go - loadPixels(); - - try { - OutputStream output = - new BufferedOutputStream(parent.createOutput(path), 16 * 1024); - - String lower = path.toLowerCase(); - String extension = lower.substring(lower.lastIndexOf('.') + 1); - if (extension.equals("jpg") || extension.equals("jpeg")) { - // TODO probably not necessary to create another bitmap - Bitmap outgoing = Bitmap.createBitmap(pixels, width, height, Config.ARGB_8888); - success = outgoing.compress(CompressFormat.JPEG, 100, output); - - } else if (extension.equals("png")) { - Bitmap outgoing = Bitmap.createBitmap(pixels, width, height, Config.ARGB_8888); - success = outgoing.compress(CompressFormat.PNG, 100, output); - - } else if (extension.equals("tga")) { - success = saveTGA(output); //, pixels, width, height, format); - - } else { - if (!extension.equals("tif") && !extension.equals("tiff")) { - // if no .tif extension, add it.. - path += ".tif"; - } - success = saveTIFF(output); - } - output.flush(); - output.close(); - - } catch (IOException e) { - e.printStackTrace(); - } - if (!success) { - System.err.println("Could not write the image to " + path); - } - return success; - } -} diff --git a/core/src/processing/core/PMatrix.java b/core/src/processing/core/PMatrix.java deleted file mode 100644 index 1c6fabc3f..000000000 --- a/core/src/processing/core/PMatrix.java +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2005-12 Ben Fry and Casey Reas - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - - -public interface PMatrix { - - public void reset(); - - /** - * Returns a copy of this PMatrix. - */ - public PMatrix get(); - - /** - * Copies the matrix contents into a float array. - * If target is null (or not the correct size), a new array will be created. - */ - public float[] get(float[] target); - - - public void set(PMatrix src); - - public void set(float[] source); - - public void set(float m00, float m01, float m02, - float m10, float m11, float m12); - - public void set(float m00, float m01, float m02, float m03, - float m10, float m11, float m12, float m13, - float m20, float m21, float m22, float m23, - float m30, float m31, float m32, float m33); - - - public void translate(float tx, float ty); - - public void translate(float tx, float ty, float tz); - - public void rotate(float angle); - - public void rotateX(float angle); - - public void rotateY(float angle); - - public void rotateZ(float angle); - - public void rotate(float angle, float v0, float v1, float v2); - - public void scale(float s); - - public void scale(float sx, float sy); - - public void scale(float x, float y, float z); - - public void shearX(float angle); - - public void shearY(float angle); - - /** - * Multiply this matrix by another. - */ - public void apply(PMatrix source); - - public void apply(PMatrix2D source); - - public void apply(PMatrix3D source); - - public void apply(float n00, float n01, float n02, - float n10, float n11, float n12); - - public void apply(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33); - - /** - * Apply another matrix to the left of this one. - */ - public void preApply(PMatrix left); - - /** - * Apply another matrix to the left of this one. - */ - public void preApply(PMatrix2D left); - - /** - * Apply another matrix to the left of this one. 3D only. - */ - public void preApply(PMatrix3D left); - - /** - * Apply another matrix to the left of this one. - */ - public void preApply(float n00, float n01, float n02, - float n10, float n11, float n12); - - /** - * Apply another matrix to the left of this one. 3D only. - */ - public void preApply(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33); - - - /** - * Multiply source by this matrix, and return the result. - * The result will be stored in target if target is non-null, and target - * will then be the matrix returned. This improves performance if you reuse - * target, so it's recommended if you call this many times in draw(). - */ - public PVector mult(PVector source, PVector target); - - - /** - * Multiply a multi-element vector against this matrix. - * Supplying and recycling a target array improves performance, so it's - * recommended if you call this many times in draw(). - */ - public float[] mult(float[] source, float[] target); - - -// public float multX(float x, float y); -// public float multY(float x, float y); - -// public float multX(float x, float y, float z); -// public float multY(float x, float y, float z); -// public float multZ(float x, float y, float z); - - - /** - * Transpose this matrix; rows become columns and columns rows. - */ - public void transpose(); - - - /** - * Invert this matrix. Will not necessarily succeed, because some matrices - * map more than one point to the same image point, and so are irreversible. - * @return true if successful - */ - public boolean invert(); - - - /** - * @return the determinant of the matrix - */ - public float determinant(); -} \ No newline at end of file diff --git a/core/src/processing/core/PMatrix2D.java b/core/src/processing/core/PMatrix2D.java deleted file mode 100644 index 8d13979b7..000000000 --- a/core/src/processing/core/PMatrix2D.java +++ /dev/null @@ -1,467 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2005-12 Ben Fry and Casey Reas - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - - -/** - * 3x2 affine matrix implementation. - */ -public class PMatrix2D implements PMatrix { - - public float m00, m01, m02; - public float m10, m11, m12; - - - public PMatrix2D() { - reset(); - } - - - public PMatrix2D(float m00, float m01, float m02, - float m10, float m11, float m12) { - set(m00, m01, m02, - m10, m11, m12); - } - - - public PMatrix2D(PMatrix matrix) { - set(matrix); - } - - - public void reset() { - set(1, 0, 0, - 0, 1, 0); - } - - - /** - * Returns a copy of this PMatrix. - */ - public PMatrix2D get() { - PMatrix2D outgoing = new PMatrix2D(); - outgoing.set(this); - return outgoing; - } - - - /** - * Copies the matrix contents into a 6 entry float array. - * If target is null (or not the correct size), a new array will be created. - */ - public float[] get(float[] target) { - if ((target == null) || (target.length != 6)) { - target = new float[6]; - } - target[0] = m00; - target[1] = m01; - target[2] = m02; - - target[3] = m10; - target[4] = m11; - target[5] = m12; - - return target; - } - - - public void set(PMatrix matrix) { - if (matrix instanceof PMatrix2D) { - PMatrix2D src = (PMatrix2D) matrix; - set(src.m00, src.m01, src.m02, - src.m10, src.m11, src.m12); - } else { - throw new IllegalArgumentException("PMatrix2D.set() only accepts PMatrix2D objects."); - } - } - - - public void set(PMatrix3D src) { - } - - - public void set(float[] source) { - m00 = source[0]; - m01 = source[1]; - m02 = source[2]; - - m10 = source[3]; - m11 = source[4]; - m12 = source[5]; - } - - - public void set(float m00, float m01, float m02, - float m10, float m11, float m12) { - this.m00 = m00; this.m01 = m01; this.m02 = m02; - this.m10 = m10; this.m11 = m11; this.m12 = m12; - } - - - public void set(float m00, float m01, float m02, float m03, - float m10, float m11, float m12, float m13, - float m20, float m21, float m22, float m23, - float m30, float m31, float m32, float m33) { - - } - - - public void translate(float tx, float ty) { - m02 = tx*m00 + ty*m01 + m02; - m12 = tx*m10 + ty*m11 + m12; - } - - - public void translate(float x, float y, float z) { - throw new IllegalArgumentException("Cannot use translate(x, y, z) on a PMatrix2D."); - } - - - // Implementation roughly based on AffineTransform. - public void rotate(float angle) { - float s = sin(angle); - float c = cos(angle); - - float temp1 = m00; - float temp2 = m01; - m00 = c * temp1 + s * temp2; - m01 = -s * temp1 + c * temp2; - temp1 = m10; - temp2 = m11; - m10 = c * temp1 + s * temp2; - m11 = -s * temp1 + c * temp2; - } - - - public void rotateX(float angle) { - throw new IllegalArgumentException("Cannot use rotateX() on a PMatrix2D."); - } - - - public void rotateY(float angle) { - throw new IllegalArgumentException("Cannot use rotateY() on a PMatrix2D."); - } - - - public void rotateZ(float angle) { - rotate(angle); - } - - - public void rotate(float angle, float v0, float v1, float v2) { - throw new IllegalArgumentException("Cannot use this version of rotate() on a PMatrix2D."); - } - - - public void scale(float s) { - scale(s, s); - } - - - public void scale(float sx, float sy) { - m00 *= sx; m01 *= sy; - m10 *= sx; m11 *= sy; - } - - - public void scale(float x, float y, float z) { - throw new IllegalArgumentException("Cannot use this version of scale() on a PMatrix2D."); - } - - - public void shearX(float angle) { - apply(1, 0, 1, tan(angle), 0, 0); - } - - - public void shearY(float angle) { - apply(1, 0, 1, 0, tan(angle), 0); - } - - - public void apply(PMatrix source) { - if (source instanceof PMatrix2D) { - apply((PMatrix2D) source); - } else if (source instanceof PMatrix3D) { - apply((PMatrix3D) source); - } - } - - - public void apply(PMatrix2D source) { - apply(source.m00, source.m01, source.m02, - source.m10, source.m11, source.m12); - } - - - public void apply(PMatrix3D source) { - throw new IllegalArgumentException("Cannot use apply(PMatrix3D) on a PMatrix2D."); - } - - - public void apply(float n00, float n01, float n02, - float n10, float n11, float n12) { - float t0 = m00; - float t1 = m01; - m00 = n00 * t0 + n10 * t1; - m01 = n01 * t0 + n11 * t1; - m02 += n02 * t0 + n12 * t1; - - t0 = m10; - t1 = m11; - m10 = n00 * t0 + n10 * t1; - m11 = n01 * t0 + n11 * t1; - m12 += n02 * t0 + n12 * t1; - } - - - public void apply(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - throw new IllegalArgumentException("Cannot use this version of apply() on a PMatrix2D."); - } - - - /** - * Apply another matrix to the left of this one. - */ - public void preApply(PMatrix source) { - if (source instanceof PMatrix2D) { - preApply((PMatrix2D) source); - } else if (source instanceof PMatrix3D) { - preApply((PMatrix3D) source); - } - } - - - /** - * Apply another matrix to the left of this one. - */ - public void preApply(PMatrix2D left) { - preApply(left.m00, left.m01, left.m02, - left.m10, left.m11, left.m12); - } - - - public void preApply(PMatrix3D left) { - throw new IllegalArgumentException("Cannot use preApply(PMatrix3D) on a PMatrix2D."); - } - - - public void preApply(float n00, float n01, float n02, - float n10, float n11, float n12) { - float t0 = m02; - float t1 = m12; - n02 += t0 * n00 + t1 * n01; - n12 += t0 * n10 + t1 * n11; - - m02 = n02; - m12 = n12; - - t0 = m00; - t1 = m10; - m00 = t0 * n00 + t1 * n01; - m10 = t0 * n10 + t1 * n11; - - t0 = m01; - t1 = m11; - m01 = t0 * n00 + t1 * n01; - m11 = t0 * n10 + t1 * n11; - } - - - public void preApply(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - throw new IllegalArgumentException("Cannot use this version of preApply() on a PMatrix2D."); - } - - - ////////////////////////////////////////////////////////////// - - - /** - * Multiply the x and y coordinates of a PVector against this matrix. - */ - public PVector mult(PVector source, PVector target) { - if (target == null) { - target = new PVector(); - } - target.x = m00*source.x + m01*source.y + m02; - target.y = m10*source.x + m11*source.y + m12; - return target; - } - - - /** - * Multiply a two element vector against this matrix. - * If out is null or not length four, a new float array will be returned. - * The values for vec and out can be the same (though that's less efficient). - */ - public float[] mult(float vec[], float out[]) { - if (out == null || out.length != 2) { - out = new float[2]; - } - - if (vec == out) { - float tx = m00*vec[0] + m01*vec[1] + m02; - float ty = m10*vec[0] + m11*vec[1] + m12; - - out[0] = tx; - out[1] = ty; - - } else { - out[0] = m00*vec[0] + m01*vec[1] + m02; - out[1] = m10*vec[0] + m11*vec[1] + m12; - } - - return out; - } - - - public float multX(float x, float y) { - return m00*x + m01*y + m02; - } - - - public float multY(float x, float y) { - return m10*x + m11*y + m12; - } - - - /** - * Transpose this matrix. - */ - public void transpose() { - } - - - /** - * Invert this matrix. Implementation stolen from OpenJDK. - * @return true if successful - */ - public boolean invert() { - float determinant = determinant(); - if (Math.abs(determinant) <= Float.MIN_VALUE) { - return false; - } - - float t00 = m00; - float t01 = m01; - float t02 = m02; - float t10 = m10; - float t11 = m11; - float t12 = m12; - - m00 = t11 / determinant; - m10 = -t10 / determinant; - m01 = -t01 / determinant; - m11 = t00 / determinant; - m02 = (t01 * t12 - t11 * t02) / determinant; - m12 = (t10 * t02 - t00 * t12) / determinant; - - return true; - } - - - /** - * @return the determinant of the matrix - */ - public float determinant() { - return m00 * m11 - m01 * m10; - } - - - ////////////////////////////////////////////////////////////// - - - public void print() { - int big = (int) abs(max(PApplet.max(abs(m00), abs(m01), abs(m02)), - PApplet.max(abs(m10), abs(m11), abs(m12)))); - - int digits = 1; - if (Float.isNaN(big) || Float.isInfinite(big)) { // avoid infinite loop - digits = 5; - } else { - while ((big /= 10) != 0) digits++; // cheap log() - } - - System.out.println(PApplet.nfs(m00, digits, 4) + " " + - PApplet.nfs(m01, digits, 4) + " " + - PApplet.nfs(m02, digits, 4)); - - System.out.println(PApplet.nfs(m10, digits, 4) + " " + - PApplet.nfs(m11, digits, 4) + " " + - PApplet.nfs(m12, digits, 4)); - - System.out.println(); - } - - - ////////////////////////////////////////////////////////////// - - // TODO these need to be added as regular API, but the naming and - // implementation needs to be improved first. (e.g. actually keeping track - // of whether the matrix is in fact identity internally.) - - - protected boolean isIdentity() { - return ((m00 == 1) && (m01 == 0) && (m02 == 0) && - (m10 == 0) && (m11 == 1) && (m12 == 0)); - } - - - // TODO make this more efficient, or move into PMatrix2D - protected boolean isWarped() { - // was &&, but changed so shearX and shearY will work - return ((m00 != 1) || (m01 != 0) || - (m10 != 0) || (m11 != 1)); - } - - - ////////////////////////////////////////////////////////////// - - - private final float max(float a, float b) { - return (a > b) ? a : b; - } - - private final float abs(float a) { - return (a < 0) ? -a : a; - } - - private final float sin(float angle) { - return (float)Math.sin(angle); - } - - private final float cos(float angle) { - return (float)Math.cos(angle); - } - - private final float tan(float angle) { - return (float)Math.tan(angle); - } -} diff --git a/core/src/processing/core/PMatrix3D.java b/core/src/processing/core/PMatrix3D.java deleted file mode 100644 index 9167af1f0..000000000 --- a/core/src/processing/core/PMatrix3D.java +++ /dev/null @@ -1,806 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2005-12 Ben Fry and Casey Reas - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - - -/** - * 4x4 matrix implementation. - */ -public final class PMatrix3D implements PMatrix /*, PConstants*/ { - - public float m00, m01, m02, m03; - public float m10, m11, m12, m13; - public float m20, m21, m22, m23; - public float m30, m31, m32, m33; - - - // locally allocated version to avoid creating new memory - protected PMatrix3D inverseCopy; - - - public PMatrix3D() { - reset(); - } - - - public PMatrix3D(float m00, float m01, float m02, - float m10, float m11, float m12) { - set(m00, m01, m02, 0, - m10, m11, m12, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - public PMatrix3D(float m00, float m01, float m02, float m03, - float m10, float m11, float m12, float m13, - float m20, float m21, float m22, float m23, - float m30, float m31, float m32, float m33) { - set(m00, m01, m02, m03, - m10, m11, m12, m13, - m20, m21, m22, m23, - m30, m31, m32, m33); - } - - - public PMatrix3D(PMatrix matrix) { - set(matrix); - } - - - public void reset() { - set(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - /** - * Returns a copy of this PMatrix. - */ - public PMatrix3D get() { - PMatrix3D outgoing = new PMatrix3D(); - outgoing.set(this); - return outgoing; - } - - - /** - * Copies the matrix contents into a 16 entry float array. - * If target is null (or not the correct size), a new array will be created. - */ - public float[] get(float[] target) { - if ((target == null) || (target.length != 16)) { - target = new float[16]; - } - target[0] = m00; - target[1] = m01; - target[2] = m02; - target[3] = m03; - - target[4] = m10; - target[5] = m11; - target[6] = m12; - target[7] = m13; - - target[8] = m20; - target[9] = m21; - target[10] = m22; - target[11] = m23; - - target[12] = m30; - target[13] = m31; - target[14] = m32; - target[15] = m33; - - return target; - } - - - public void set(PMatrix matrix) { - if (matrix instanceof PMatrix3D) { - PMatrix3D src = (PMatrix3D) matrix; - set(src.m00, src.m01, src.m02, src.m03, - src.m10, src.m11, src.m12, src.m13, - src.m20, src.m21, src.m22, src.m23, - src.m30, src.m31, src.m32, src.m33); - } else { - PMatrix2D src = (PMatrix2D) matrix; - set(src.m00, src.m01, 0, src.m02, - src.m10, src.m11, 0, src.m12, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - } - - - public void set(float[] source) { - if (source.length == 6) { - set(source[0], source[1], source[2], - source[3], source[4], source[5]); - - } else if (source.length == 16) { - m00 = source[0]; - m01 = source[1]; - m02 = source[2]; - m03 = source[3]; - - m10 = source[4]; - m11 = source[5]; - m12 = source[6]; - m13 = source[7]; - - m20 = source[8]; - m21 = source[9]; - m22 = source[10]; - m23 = source[11]; - - m30 = source[12]; - m31 = source[13]; - m32 = source[14]; - m33 = source[15]; - } - } - - - public void set(float m00, float m01, float m02, - float m10, float m11, float m12) { - set(m00, m01, 0, m02, - m10, m11, 0, m12, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - public void set(float m00, float m01, float m02, float m03, - float m10, float m11, float m12, float m13, - float m20, float m21, float m22, float m23, - float m30, float m31, float m32, float m33) { - this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; - this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; - this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; - this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; - } - - - public void translate(float tx, float ty) { - translate(tx, ty, 0); - } - -// public void invTranslate(float tx, float ty) { -// invTranslate(tx, ty, 0); -// } - - - public void translate(float tx, float ty, float tz) { - m03 += tx*m00 + ty*m01 + tz*m02; - m13 += tx*m10 + ty*m11 + tz*m12; - m23 += tx*m20 + ty*m21 + tz*m22; - m33 += tx*m30 + ty*m31 + tz*m32; - } - - - public void rotate(float angle) { - rotateZ(angle); - } - - - public void rotateX(float angle) { - float c = cos(angle); - float s = sin(angle); - apply(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1); - } - - - public void rotateY(float angle) { - float c = cos(angle); - float s = sin(angle); - apply(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1); - } - - - public void rotateZ(float angle) { - float c = cos(angle); - float s = sin(angle); - apply(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - - - public void rotate(float angle, float v0, float v1, float v2) { - float norm2 = v0 * v0 + v1 * v1 + v2 * v2; - if (norm2 < PConstants.EPSILON) { - // The vector is zero, cannot apply rotation. - return; - } - - if (Math.abs(norm2 - 1) > PConstants.EPSILON) { - // The rotation vector is not normalized. - float norm = PApplet.sqrt(norm2); - v0 /= norm; - v1 /= norm; - v2 /= norm; - } - - float c = cos(angle); - float s = sin(angle); - float t = 1.0f - c; - - apply((t*v0*v0) + c, (t*v0*v1) - (s*v2), (t*v0*v2) + (s*v1), 0, - (t*v0*v1) + (s*v2), (t*v1*v1) + c, (t*v1*v2) - (s*v0), 0, - (t*v0*v2) - (s*v1), (t*v1*v2) + (s*v0), (t*v2*v2) + c, 0, - 0, 0, 0, 1); - } - - - public void scale(float s) { - //apply(s, 0, 0, 0, 0, s, 0, 0, 0, 0, s, 0, 0, 0, 0, 1); - scale(s, s, s); - } - - - public void scale(float sx, float sy) { - //apply(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - scale(sx, sy, 1); - } - - - public void scale(float x, float y, float z) { - //apply(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1); - m00 *= x; m01 *= y; m02 *= z; - m10 *= x; m11 *= y; m12 *= z; - m20 *= x; m21 *= y; m22 *= z; - m30 *= x; m31 *= y; m32 *= z; - } - - - public void shearX(float angle) { - float t = (float) Math.tan(angle); - apply(1, t, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - public void shearY(float angle) { - float t = (float) Math.tan(angle); - apply(1, 0, 0, 0, - t, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - public void apply(PMatrix source) { - if (source instanceof PMatrix2D) { - apply((PMatrix2D) source); - } else if (source instanceof PMatrix3D) { - apply((PMatrix3D) source); - } - } - - - public void apply(PMatrix2D source) { - apply(source.m00, source.m01, 0, source.m02, - source.m10, source.m11, 0, source.m12, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - public void apply(PMatrix3D source) { - apply(source.m00, source.m01, source.m02, source.m03, - source.m10, source.m11, source.m12, source.m13, - source.m20, source.m21, source.m22, source.m23, - source.m30, source.m31, source.m32, source.m33); - } - - - public void apply(float n00, float n01, float n02, - float n10, float n11, float n12) { - apply(n00, n01, 0, n02, - n10, n11, 0, n12, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - public void apply(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - - float r00 = m00*n00 + m01*n10 + m02*n20 + m03*n30; - float r01 = m00*n01 + m01*n11 + m02*n21 + m03*n31; - float r02 = m00*n02 + m01*n12 + m02*n22 + m03*n32; - float r03 = m00*n03 + m01*n13 + m02*n23 + m03*n33; - - float r10 = m10*n00 + m11*n10 + m12*n20 + m13*n30; - float r11 = m10*n01 + m11*n11 + m12*n21 + m13*n31; - float r12 = m10*n02 + m11*n12 + m12*n22 + m13*n32; - float r13 = m10*n03 + m11*n13 + m12*n23 + m13*n33; - - float r20 = m20*n00 + m21*n10 + m22*n20 + m23*n30; - float r21 = m20*n01 + m21*n11 + m22*n21 + m23*n31; - float r22 = m20*n02 + m21*n12 + m22*n22 + m23*n32; - float r23 = m20*n03 + m21*n13 + m22*n23 + m23*n33; - - float r30 = m30*n00 + m31*n10 + m32*n20 + m33*n30; - float r31 = m30*n01 + m31*n11 + m32*n21 + m33*n31; - float r32 = m30*n02 + m31*n12 + m32*n22 + m33*n32; - float r33 = m30*n03 + m31*n13 + m32*n23 + m33*n33; - - m00 = r00; m01 = r01; m02 = r02; m03 = r03; - m10 = r10; m11 = r11; m12 = r12; m13 = r13; - m20 = r20; m21 = r21; m22 = r22; m23 = r23; - m30 = r30; m31 = r31; m32 = r32; m33 = r33; - } - - - /** - * Apply another matrix to the left of this one. - */ - public void preApply(PMatrix source) { - if (source instanceof PMatrix2D) { - preApply((PMatrix2D) source); - } else if (source instanceof PMatrix3D) { - preApply((PMatrix3D) source); - } - } - - - public void preApply(PMatrix2D left) { - preApply(left.m00, left.m01, 0, left.m02, - left.m10, left.m11, 0, left.m12, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - /** - * Apply another matrix to the left of this one. - */ - public void preApply(PMatrix3D left) { - preApply(left.m00, left.m01, left.m02, left.m03, - left.m10, left.m11, left.m12, left.m13, - left.m20, left.m21, left.m22, left.m23, - left.m30, left.m31, left.m32, left.m33); - } - - - public void preApply(float n00, float n01, float n02, - float n10, float n11, float n12) { - preApply(n00, n01, 0, n02, - n10, n11, 0, n12, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - public void preApply(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - - float r00 = n00*m00 + n01*m10 + n02*m20 + n03*m30; - float r01 = n00*m01 + n01*m11 + n02*m21 + n03*m31; - float r02 = n00*m02 + n01*m12 + n02*m22 + n03*m32; - float r03 = n00*m03 + n01*m13 + n02*m23 + n03*m33; - - float r10 = n10*m00 + n11*m10 + n12*m20 + n13*m30; - float r11 = n10*m01 + n11*m11 + n12*m21 + n13*m31; - float r12 = n10*m02 + n11*m12 + n12*m22 + n13*m32; - float r13 = n10*m03 + n11*m13 + n12*m23 + n13*m33; - - float r20 = n20*m00 + n21*m10 + n22*m20 + n23*m30; - float r21 = n20*m01 + n21*m11 + n22*m21 + n23*m31; - float r22 = n20*m02 + n21*m12 + n22*m22 + n23*m32; - float r23 = n20*m03 + n21*m13 + n22*m23 + n23*m33; - - float r30 = n30*m00 + n31*m10 + n32*m20 + n33*m30; - float r31 = n30*m01 + n31*m11 + n32*m21 + n33*m31; - float r32 = n30*m02 + n31*m12 + n32*m22 + n33*m32; - float r33 = n30*m03 + n31*m13 + n32*m23 + n33*m33; - - m00 = r00; m01 = r01; m02 = r02; m03 = r03; - m10 = r10; m11 = r11; m12 = r12; m13 = r13; - m20 = r20; m21 = r21; m22 = r22; m23 = r23; - m30 = r30; m31 = r31; m32 = r32; m33 = r33; - } - - - ////////////////////////////////////////////////////////////// - - - public PVector mult(PVector source, PVector target) { - if (target == null) { - target = new PVector(); - } - target.set(m00*source.x + m01*source.y + m02*source.z + m03, - m10*source.x + m11*source.y + m12*source.z + m13, - m20*source.x + m21*source.y + m22*source.z + m23); -// float tw = m30*source.x + m31*source.y + m32*source.z + m33; -// if (tw != 0 && tw != 1) { -// target.div(tw); -// } - return target; - } - - - /* - public PVector cmult(PVector source, PVector target) { - if (target == null) { - target = new PVector(); - } - target.x = m00*source.x + m10*source.y + m20*source.z + m30; - target.y = m01*source.x + m11*source.y + m21*source.z + m31; - target.z = m02*source.x + m12*source.y + m22*source.z + m32; - float tw = m03*source.x + m13*source.y + m23*source.z + m33; - if (tw != 0 && tw != 1) { - target.div(tw); - } - return target; - } - */ - - - /** - * Multiply a three or four element vector against this matrix. If out is - * null or not length 3 or 4, a new float array (length 3) will be returned. - */ - public float[] mult(float[] source, float[] target) { - if (target == null || target.length < 3) { - target = new float[3]; - } - if (source == target) { - throw new RuntimeException("The source and target vectors used in " + - "PMatrix3D.mult() cannot be identical."); - } - if (target.length == 3) { - target[0] = m00*source[0] + m01*source[1] + m02*source[2] + m03; - target[1] = m10*source[0] + m11*source[1] + m12*source[2] + m13; - target[2] = m20*source[0] + m21*source[1] + m22*source[2] + m23; - //float w = m30*source[0] + m31*source[1] + m32*source[2] + m33; - //if (w != 0 && w != 1) { - // target[0] /= w; target[1] /= w; target[2] /= w; - //} - } else if (target.length > 3) { - target[0] = m00*source[0] + m01*source[1] + m02*source[2] + m03*source[3]; - target[1] = m10*source[0] + m11*source[1] + m12*source[2] + m13*source[3]; - target[2] = m20*source[0] + m21*source[1] + m22*source[2] + m23*source[3]; - target[3] = m30*source[0] + m31*source[1] + m32*source[2] + m33*source[3]; - } - return target; - } - - - public float multX(float x, float y) { - return m00*x + m01*y + m03; - } - - - public float multY(float x, float y) { - return m10*x + m11*y + m13; - } - - - public float multX(float x, float y, float z) { - return m00*x + m01*y + m02*z + m03; - } - - - public float multY(float x, float y, float z) { - return m10*x + m11*y + m12*z + m13; - } - - - public float multZ(float x, float y, float z) { - return m20*x + m21*y + m22*z + m23; - } - - - public float multW(float x, float y, float z) { - return m30*x + m31*y + m32*z + m33; - } - - - public float multX(float x, float y, float z, float w) { - return m00*x + m01*y + m02*z + m03*w; - } - - - public float multY(float x, float y, float z, float w) { - return m10*x + m11*y + m12*z + m13*w; - } - - - public float multZ(float x, float y, float z, float w) { - return m20*x + m21*y + m22*z + m23*w; - } - - - public float multW(float x, float y, float z, float w) { - return m30*x + m31*y + m32*z + m33*w; - } - - - /** - * Transpose this matrix. - */ - public void transpose() { - float temp; - temp = m01; m01 = m10; m10 = temp; - temp = m02; m02 = m20; m20 = temp; - temp = m03; m03 = m30; m30 = temp; - temp = m12; m12 = m21; m21 = temp; - temp = m13; m13 = m31; m31 = temp; - temp = m23; m23 = m32; m32 = temp; - } - - - /** - * Invert this matrix. - * @return true if successful - */ - public boolean invert() { - float determinant = determinant(); - if (determinant == 0) { - return false; - } - - // first row - float t00 = determinant3x3(m11, m12, m13, m21, m22, m23, m31, m32, m33); - float t01 = -determinant3x3(m10, m12, m13, m20, m22, m23, m30, m32, m33); - float t02 = determinant3x3(m10, m11, m13, m20, m21, m23, m30, m31, m33); - float t03 = -determinant3x3(m10, m11, m12, m20, m21, m22, m30, m31, m32); - - // second row - float t10 = -determinant3x3(m01, m02, m03, m21, m22, m23, m31, m32, m33); - float t11 = determinant3x3(m00, m02, m03, m20, m22, m23, m30, m32, m33); - float t12 = -determinant3x3(m00, m01, m03, m20, m21, m23, m30, m31, m33); - float t13 = determinant3x3(m00, m01, m02, m20, m21, m22, m30, m31, m32); - - // third row - float t20 = determinant3x3(m01, m02, m03, m11, m12, m13, m31, m32, m33); - float t21 = -determinant3x3(m00, m02, m03, m10, m12, m13, m30, m32, m33); - float t22 = determinant3x3(m00, m01, m03, m10, m11, m13, m30, m31, m33); - float t23 = -determinant3x3(m00, m01, m02, m10, m11, m12, m30, m31, m32); - - // fourth row - float t30 = -determinant3x3(m01, m02, m03, m11, m12, m13, m21, m22, m23); - float t31 = determinant3x3(m00, m02, m03, m10, m12, m13, m20, m22, m23); - float t32 = -determinant3x3(m00, m01, m03, m10, m11, m13, m20, m21, m23); - float t33 = determinant3x3(m00, m01, m02, m10, m11, m12, m20, m21, m22); - - // transpose and divide by the determinant - m00 = t00 / determinant; - m01 = t10 / determinant; - m02 = t20 / determinant; - m03 = t30 / determinant; - - m10 = t01 / determinant; - m11 = t11 / determinant; - m12 = t21 / determinant; - m13 = t31 / determinant; - - m20 = t02 / determinant; - m21 = t12 / determinant; - m22 = t22 / determinant; - m23 = t32 / determinant; - - m30 = t03 / determinant; - m31 = t13 / determinant; - m32 = t23 / determinant; - m33 = t33 / determinant; - - return true; - } - - - /** - * Calculate the determinant of a 3x3 matrix. - * @return result - */ - private float determinant3x3(float t00, float t01, float t02, - float t10, float t11, float t12, - float t20, float t21, float t22) { - return (t00 * (t11 * t22 - t12 * t21) + - t01 * (t12 * t20 - t10 * t22) + - t02 * (t10 * t21 - t11 * t20)); - } - - - /** - * @return the determinant of the matrix - */ - public float determinant() { - float f = - m00 - * ((m11 * m22 * m33 + m12 * m23 * m31 + m13 * m21 * m32) - - m13 * m22 * m31 - - m11 * m23 * m32 - - m12 * m21 * m33); - f -= m01 - * ((m10 * m22 * m33 + m12 * m23 * m30 + m13 * m20 * m32) - - m13 * m22 * m30 - - m10 * m23 * m32 - - m12 * m20 * m33); - f += m02 - * ((m10 * m21 * m33 + m11 * m23 * m30 + m13 * m20 * m31) - - m13 * m21 * m30 - - m10 * m23 * m31 - - m11 * m20 * m33); - f -= m03 - * ((m10 * m21 * m32 + m11 * m22 * m30 + m12 * m20 * m31) - - m12 * m21 * m30 - - m10 * m22 * m31 - - m11 * m20 * m32); - return f; - } - - - ////////////////////////////////////////////////////////////// - - // REVERSE VERSIONS OF MATRIX OPERATIONS - - // These functions should not be used, as they will be removed in the future. - - - protected void invTranslate(float tx, float ty, float tz) { - preApply(1, 0, 0, -tx, - 0, 1, 0, -ty, - 0, 0, 1, -tz, - 0, 0, 0, 1); - } - - - protected void invRotateX(float angle) { - float c = cos(-angle); - float s = sin(-angle); - preApply(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1); - } - - - protected void invRotateY(float angle) { - float c = cos(-angle); - float s = sin(-angle); - preApply(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1); - } - - - protected void invRotateZ(float angle) { - float c = cos(-angle); - float s = sin(-angle); - preApply(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - } - - - protected void invRotate(float angle, float v0, float v1, float v2) { - //TODO should make sure this vector is normalized - - float c = cos(-angle); - float s = sin(-angle); - float t = 1.0f - c; - - preApply((t*v0*v0) + c, (t*v0*v1) - (s*v2), (t*v0*v2) + (s*v1), 0, - (t*v0*v1) + (s*v2), (t*v1*v1) + c, (t*v1*v2) - (s*v0), 0, - (t*v0*v2) - (s*v1), (t*v1*v2) + (s*v0), (t*v2*v2) + c, 0, - 0, 0, 0, 1); - } - - - protected void invScale(float x, float y, float z) { - preApply(1/x, 0, 0, 0, 0, 1/y, 0, 0, 0, 0, 1/z, 0, 0, 0, 0, 1); - } - - - protected boolean invApply(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - if (inverseCopy == null) { - inverseCopy = new PMatrix3D(); - } - inverseCopy.set(n00, n01, n02, n03, - n10, n11, n12, n13, - n20, n21, n22, n23, - n30, n31, n32, n33); - if (!inverseCopy.invert()) { - return false; - } - preApply(inverseCopy); - return true; - } - - - ////////////////////////////////////////////////////////////// - - - public void print() { - /* - System.out.println(m00 + " " + m01 + " " + m02 + " " + m03 + "\n" + - m10 + " " + m11 + " " + m12 + " " + m13 + "\n" + - m20 + " " + m21 + " " + m22 + " " + m23 + "\n" + - m30 + " " + m31 + " " + m32 + " " + m33 + "\n"); - */ - int big = (int) Math.abs(max(max(max(max(abs(m00), abs(m01)), - max(abs(m02), abs(m03))), - max(max(abs(m10), abs(m11)), - max(abs(m12), abs(m13)))), - max(max(max(abs(m20), abs(m21)), - max(abs(m22), abs(m23))), - max(max(abs(m30), abs(m31)), - max(abs(m32), abs(m33)))))); - - int digits = 1; - if (Float.isNaN(big) || Float.isInfinite(big)) { // avoid infinite loop - digits = 5; - } else { - while ((big /= 10) != 0) digits++; // cheap log() - } - - System.out.println(PApplet.nfs(m00, digits, 4) + " " + - PApplet.nfs(m01, digits, 4) + " " + - PApplet.nfs(m02, digits, 4) + " " + - PApplet.nfs(m03, digits, 4)); - - System.out.println(PApplet.nfs(m10, digits, 4) + " " + - PApplet.nfs(m11, digits, 4) + " " + - PApplet.nfs(m12, digits, 4) + " " + - PApplet.nfs(m13, digits, 4)); - - System.out.println(PApplet.nfs(m20, digits, 4) + " " + - PApplet.nfs(m21, digits, 4) + " " + - PApplet.nfs(m22, digits, 4) + " " + - PApplet.nfs(m23, digits, 4)); - - System.out.println(PApplet.nfs(m30, digits, 4) + " " + - PApplet.nfs(m31, digits, 4) + " " + - PApplet.nfs(m32, digits, 4) + " " + - PApplet.nfs(m33, digits, 4)); - - System.out.println(); - } - - - ////////////////////////////////////////////////////////////// - - - static private final float max(float a, float b) { - return (a > b) ? a : b; - } - - static private final float abs(float a) { - return (a < 0) ? -a : a; - } - - static private final float sin(float angle) { - return (float) Math.sin(angle); - } - - static private final float cos(float angle) { - return (float) Math.cos(angle); - } -} diff --git a/core/src/processing/core/PShape.java b/core/src/processing/core/PShape.java deleted file mode 100644 index a609a9e4e..000000000 --- a/core/src/processing/core/PShape.java +++ /dev/null @@ -1,3569 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2006-12 Ben Fry and Casey Reas - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; - -import java.util.HashMap; -import java.util.Map; - - -/** - * ( begin auto-generated from PShape.xml ) - * - * Datatype for storing shapes. Processing can currently load and display - * SVG (Scalable Vector Graphics) shapes. Before a shape is used, it must - * be loaded with the loadShape() function. The shape() - * function is used to draw the shape to the display window. The - * PShape object contain a group of methods, linked below, that can - * operate on the shape data. - *

    - * The loadShape() function supports SVG files created with Inkscape - * and Adobe Illustrator. It is not a full SVG implementation, but offers - * some straightforward support for handling vector data. - * - * ( end auto-generated ) - *

    Advanced

    - * - * In-progress class to handle shape data, currently to be considered of - * alpha or beta quality. Major structural work may be performed on this class - * after the release of Processing 1.0. Such changes may include: - * - *
      - *
    • addition of proper accessors to read shape vertex and coloring data - * (this is the second most important part of having a PShape class after all). - *
    • a means of creating PShape objects ala beginShape() and endShape(). - *
    • load(), update(), and cache methods ala PImage, so that shapes can - * have renderer-specific optimizations, such as vertex arrays in OpenGL. - *
    • splitting this class into multiple classes to handle different - * varieties of shape data (primitives vs collections of vertices vs paths) - *
    • change of package declaration, for instance moving the code into - * package processing.shape (if the code grows too much). - *
    - * - *

    For the time being, this class and its shape() and loadShape() friends in - * PApplet exist as placeholders for more exciting things to come. If you'd - * like to work with this class, make a subclass (see how PShapeSVG works) - * and you can play with its internal methods all you like.

    - * - *

    Library developers are encouraged to create PShape objects when loading - * shape data, so that they can eventually hook into the bounty that will be - * the PShape interface, and the ease of loadShape() and shape().

    - * - * @webref shape - * @usage Web & Application - * @see PApplet#loadShape(String) - * @see PApplet#createShape() - * @see PApplet#shapeMode(int) - * @instanceName sh any variable of type PShape - */ -public class PShape implements PConstants { - protected String name; - protected Map nameTable; - -// /** Generic, only draws its child objects. */ -// static public final int GROUP = 0; - // GROUP now inherited from PConstants, and is still zero - - // These constants were updated in 3.0b6 so that they could be distinguished - // from others in PConstants and improve how some typos were handled. - // https://github.com/processing/processing/issues/3776 - /** A line, ellipse, arc, image, etc. */ - static public final int PRIMITIVE = 101; - /** A series of vertex, curveVertex, and bezierVertex calls. */ - static public final int PATH = 102; - /** Collections of vertices created with beginShape(). */ - static public final int GEOMETRY = 103; - /** The shape type, one of GROUP, PRIMITIVE, PATH, or GEOMETRY. */ - protected int family; - - /** ELLIPSE, LINE, QUAD; TRIANGLE_FAN, QUAD_STRIP; etc. */ - protected int kind; - - protected PMatrix matrix; - - protected int textureMode; - - /** Texture or image data associated with this shape. */ - protected PImage image; - protected String imagePath = null; - - public static final String OUTSIDE_BEGIN_END_ERROR = - "%1$s can only be called between beginShape() and endShape()"; - - public static final String INSIDE_BEGIN_END_ERROR = - "%1$s can only be called outside beginShape() and endShape()"; - - public static final String NO_SUCH_VERTEX_ERROR = - "%1$s vertex index does not exist"; - - static public final String NO_VERTICES_ERROR = - "getVertexCount() only works with PATH or GEOMETRY shapes"; - - public static final String NOT_A_SIMPLE_VERTEX = - "%1$s can not be called on quadratic or bezier vertices"; - - static public final String PER_VERTEX_UNSUPPORTED = - "This renderer does not support %1$s for individual vertices"; - - /** - * ( begin auto-generated from PShape_width.xml ) - * - * The width of the PShape document. - * - * ( end auto-generated ) - * @webref pshape:field - * @usage web_application - * @brief Shape document width - * @see PShape#height - */ - public float width; - /** - * ( begin auto-generated from PShape_height.xml ) - * - * The height of the PShape document. - * - * ( end auto-generated ) - * @webref pshape:field - * @usage web_application - * @brief Shape document height - * @see PShape#width - */ - public float height; - - public float depth; - - PGraphics g; - - // set to false if the object is hidden in the layers palette - protected boolean visible = true; - - /** Retained shape being created with beginShape/endShape */ - protected boolean openShape = false; - - protected boolean openContour = false; - - protected boolean stroke; - protected int strokeColor; - protected float strokeWeight; // default is 1 - protected int strokeCap; - protected int strokeJoin; - - protected boolean fill; - protected int fillColor; - - protected boolean tint; - protected int tintColor; - - protected int ambientColor; - protected boolean setAmbient; - protected int specularColor; - protected int emissiveColor; - protected float shininess; - - protected int sphereDetailU, sphereDetailV; - protected int rectMode; - protected int ellipseMode; - - /** Temporary toggle for whether styles should be honored. */ - protected boolean style = true; - - /** For primitive shapes in particular, params like x/y/w/h or x1/y1/x2/y2. */ - protected float[] params; - - protected int vertexCount; - /** - * When drawing POLYGON shapes, the second param is an array of length - * VERTEX_FIELD_COUNT. When drawing PATH shapes, the second param has only - * two variables. - */ - protected float[][] vertices; - - protected PShape parent; - protected int childCount; - protected PShape[] children; - - - /** Array of VERTEX, BEZIER_VERTEX, and CURVE_VERTEX calls. */ - protected int vertexCodeCount; - protected int[] vertexCodes; - /** True if this is a closed path. */ - protected boolean close; - - // ........................................................ - - // internal color for setting/calculating - protected float calcR, calcG, calcB, calcA; - protected int calcRi, calcGi, calcBi, calcAi; - protected int calcColor; - protected boolean calcAlpha; - - /** The current colorMode */ - public int colorMode; // = RGB; - - /** Max value for red (or hue) set by colorMode */ - public float colorModeX; // = 255; - - /** Max value for green (or saturation) set by colorMode */ - public float colorModeY; // = 255; - - /** Max value for blue (or value) set by colorMode */ - public float colorModeZ; // = 255; - - /** Max value for alpha set by colorMode */ - public float colorModeA; // = 255; - - /** True if colors are not in the range 0..1 */ - boolean colorModeScale; // = true; - - /** True if colorMode(RGB, 255) */ - boolean colorModeDefault; // = true; - - /** True if contains 3D data */ - protected boolean is3D = false; - - protected boolean perVertexStyles = false; - - - // should this be called vertices (consistent with PGraphics internals) - // or does that hurt flexibility? - - - // POINTS, LINES, xLINE_STRIP, xLINE_LOOP - // TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN - // QUADS, QUAD_STRIP - // xPOLYGON -// static final int PATH = 1; // POLYGON, LINE_LOOP, LINE_STRIP -// static final int GROUP = 2; - - // how to handle rectmode/ellipsemode? - // are they bitshifted into the constant? - // CORNER, CORNERS, CENTER, (CENTER_RADIUS?) -// static final int RECT = 3; // could just be QUAD, but would be x1/y1/x2/y2 -// static final int ELLIPSE = 4; -// -// static final int VERTEX = 7; -// static final int CURVE = 5; -// static final int BEZIER = 6; - - - // fill and stroke functions will need a pointer to the parent - // PGraphics object.. may need some kind of createShape() fxn - // or maybe the values are stored until draw() is called? - - // attaching images is very tricky.. it's a different type of data - - // material parameters will be thrown out, - // except those currently supported (kinds of lights) - - // pivot point for transformations -// public float px; -// public float py; - - - /** - * @nowebref - */ - public PShape() { - this.family = GROUP; - } - - - /** - * @nowebref - */ - public PShape(int family) { - this.family = family; - } - - - /** - * @nowebref - */ - public PShape(PGraphics g, int family) { - this.g = g; - this.family = family; - - // Style parameters are retrieved from the current values in the renderer. - textureMode = g.textureMode; - - colorMode(g.colorMode, - g.colorModeX, g.colorModeY, g.colorModeZ, g.colorModeA); - - // Initial values for fill, stroke and tint colors are also imported from - // the renderer. This is particular relevant for primitive shapes, since is - // not possible to set their color separately when creating them, and their - // input vertices are actually generated at rendering time, by which the - // color configuration of the renderer might have changed. - fill = g.fill; - fillColor = g.fillColor; - - stroke = g.stroke; - strokeColor = g.strokeColor; - strokeWeight = g.strokeWeight; - strokeCap = g.strokeCap; - strokeJoin = g.strokeJoin; - - tint = g.tint; - tintColor = g.tintColor; - - setAmbient = g.setAmbient; - ambientColor = g.ambientColor; - specularColor = g.specularColor; - emissiveColor = g.emissiveColor; - shininess = g.shininess; - - sphereDetailU = g.sphereDetailU; - sphereDetailV = g.sphereDetailV; - -// bezierDetail = pg.bezierDetail; -// curveDetail = pg.curveDetail; -// curveTightness = pg.curveTightness; - - rectMode = g.rectMode; - ellipseMode = g.ellipseMode; - -// normalX = normalY = 0; -// normalZ = 1; -// -// normalMode = NORMAL_MODE_AUTO; - - // To make sure that the first vertex is marked as a break. - // Same behavior as in the immediate mode. -// breakShape = false; - - if (family == GROUP) { - // GROUP shapes are always marked as ended. -// shapeCreated = true; - // TODO why was this commented out? - } - } - - - public PShape(PGraphics g, int kind, float... params) { - this(g, PRIMITIVE); - setKind(kind); - setParams(params); - } - - - public void setFamily(int family) { - this.family = family; - } - - - public void setKind(int kind) { - this.kind = kind; - } - - - public void setName(String name) { - this.name = name; - } - - - public String getName() { - return name; - } - - /** - * ( begin auto-generated from PShape_isVisible.xml ) - * - * Returns a boolean value "true" if the image is set to be visible, - * "false" if not. This is modified with the setVisible() parameter. - *

    - * The visibility of a shape is usually controlled by whatever program - * created the SVG file. For instance, this parameter is controlled by - * showing or hiding the shape in the layers palette in Adobe Illustrator. - * - * ( end auto-generated ) - * @webref pshape:method - * @usage web_application - * @brief Returns a boolean value "true" if the image is set to be visible, "false" if not - * @see PShape#setVisible(boolean) - */ - public boolean isVisible() { - return visible; - } - - - /** - * ( begin auto-generated from PShape_setVisible.xml ) - * - * Sets the shape to be visible or invisible. This is determined by the - * value of the visible parameter. - *

    - * The visibility of a shape is usually controlled by whatever program - * created the SVG file. For instance, this parameter is controlled by - * showing or hiding the shape in the layers palette in Adobe Illustrator. - * - * ( end auto-generated ) - * @webref pshape:mathod - * @usage web_application - * @brief Sets the shape to be visible or invisible - * @param visible "false" makes the shape invisible and "true" makes it visible - * @see PShape#isVisible() - */ - public void setVisible(boolean visible) { - this.visible = visible; - } - - - /** - * ( begin auto-generated from PShape_disableStyle.xml ) - * - * Disables the shape's style data and uses Processing's current styles. - * Styles include attributes such as colors, stroke weight, and stroke - * joints. - * - * ( end auto-generated ) - *

    Advanced

    - * Overrides this shape's style information and uses PGraphics styles and - * colors. Identical to ignoreStyles(true). Also disables styles for all - * child shapes. - * @webref pshape:method - * @usage web_application - * @brief Disables the shape's style data and uses Processing styles - * @see PShape#enableStyle() - */ - public void disableStyle() { - style = false; - - for (int i = 0; i < childCount; i++) { - children[i].disableStyle(); - } - } - - - /** - * ( begin auto-generated from PShape_enableStyle.xml ) - * - * Enables the shape's style data and ignores Processing's current styles. - * Styles include attributes such as colors, stroke weight, and stroke - * joints. - * - * ( end auto-generated ) - * - * @webref pshape:method - * @usage web_application - * @brief Enables the shape's style data and ignores the Processing styles - * @see PShape#disableStyle() - */ - public void enableStyle() { - style = true; - - for (int i = 0; i < childCount; i++) { - children[i].enableStyle(); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - -// protected void checkBounds() { -// if (width == 0 || height == 0) { -// // calculate bounds here (also take kids into account) -// width = 1; -// height = 1; -// } -// } - - - /** - * Get the width of the drawing area (not necessarily the shape boundary). - */ - public float getWidth() { - //checkBounds(); - return width; - } - - - /** - * Get the height of the drawing area (not necessarily the shape boundary). - */ - public float getHeight() { - //checkBounds(); - return height; - } - - - /** - * Get the depth of the shape area (not necessarily the shape boundary). Only makes sense for 3D PShape subclasses, - * such as PShape3D. - */ - public float getDepth() { - //checkBounds(); - return depth; - } - - - - /* - // TODO unapproved - protected PVector getTop() { - return getTop(null); - } - - - protected PVector getTop(PVector top) { - if (top == null) { - top = new PVector(); - } - return top; - } - - - protected PVector getBottom() { - return getBottom(null); - } - - - protected PVector getBottom(PVector bottom) { - if (bottom == null) { - bottom = new PVector(); - } - return bottom; - } - */ - - - /** - * Return true if this shape is 2D. Defaults to true. - */ - public boolean is2D() { - return !is3D; - } - - - /** - * Return true if this shape is 3D. Defaults to false. - */ - public boolean is3D() { - return is3D; - } - - - public void set3D(boolean val) { - is3D = val; - } - - -// /** -// * Return true if this shape requires rendering through OpenGL. Defaults to false. -// */ -// // TODO unapproved -// public boolean isGL() { -// return false; -// } - - - /////////////////////////////////////////////////////////// - - // - - // Drawing methods - - public void textureMode(int mode) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "textureMode()"); - return; - } - - textureMode = mode; - } - - public void texture(PImage tex) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "texture()"); - return; - } - - image = tex; - } - - public void noTexture() { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "noTexture()"); - return; - } - - image = null; - } - - - // TODO unapproved - protected void solid(boolean solid) { - } - - - /** - * @webref shape:vertex - * @brief Starts a new contour - * @see PShape#endContour() - */ - public void beginContour() { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "beginContour()"); - return; - } - - if (family == GROUP) { - PGraphics.showWarning("Cannot begin contour in GROUP shapes"); - return; - } - - if (openContour) { - PGraphics.showWarning("Already called beginContour()."); - return; - } - openContour = true; - beginContourImpl(); - } - - - protected void beginContourImpl() { - if (vertexCodes == null) { - vertexCodes = new int[10]; - } else if (vertexCodes.length == vertexCodeCount) { - vertexCodes = PApplet.expand(vertexCodes); - } - vertexCodes[vertexCodeCount++] = BREAK; - } - - - /** - * @webref shape:vertex - * @brief Ends a contour - * @see PShape#beginContour() - */ - public void endContour() { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "endContour()"); - return; - } - - if (family == GROUP) { - PGraphics.showWarning("Cannot end contour in GROUP shapes"); - return; - } - - if (!openContour) { - PGraphics.showWarning("Need to call beginContour() first."); - return; - } - endContourImpl(); - openContour = false; - } - - - protected void endContourImpl() { - } - - - public void vertex(float x, float y) { - if (vertices == null) { - vertices = new float[10][2]; - } else if (vertices.length == vertexCount) { - vertices = (float[][]) PApplet.expand(vertices); - } - vertices[vertexCount++] = new float[] { x, y }; - - if (vertexCodes == null) { - vertexCodes = new int[10]; - } else if (vertexCodes.length == vertexCodeCount) { - vertexCodes = PApplet.expand(vertexCodes); - } - vertexCodes[vertexCodeCount++] = VERTEX; - - if (x > width) { - width = x; - } - if (y > height) { - height = y; - } - } - - - public void vertex(float x, float y, float u, float v) { - } - - - public void vertex(float x, float y, float z) { - vertex(x, y); // maybe? maybe not? - } - - - public void vertex(float x, float y, float z, float u, float v) { - } - - - public void normal(float nx, float ny, float nz) { - } - - - public void attribPosition(String name, float x, float y, float z) { - } - - public void attribNormal(String name, float nx, float ny, float nz) { - } - - - public void attribColor(String name, int color) { - } - - - public void attrib(String name, float... values) { - } - - - public void attrib(String name, int... values) { - } - - - public void attrib(String name, boolean... values) { - } - - - /** - * @webref pshape:method - * @brief Starts the creation of a new PShape - * @see PApplet#endShape() - */ - public void beginShape() { - beginShape(POLYGON); - } - - - public void beginShape(int kind) { - this.kind = kind; - openShape = true; - } - - /** - * @webref pshape:method - * @brief Finishes the creation of a new PShape - * @see PApplet#beginShape() - */ - public void endShape() { - endShape(OPEN); - } - - - public void endShape(int mode) { - if (family == GROUP) { - PGraphics.showWarning("Cannot end GROUP shape"); - return; - } - - if (!openShape) { - PGraphics.showWarning("Need to call beginShape() first"); - return; - } - - close = (mode==CLOSE); - - // this is the state of the shape - openShape = false; - } - - - ////////////////////////////////////////////////////////////// - - // STROKE CAP/JOIN/WEIGHT - - - public void strokeWeight(float weight) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "strokeWeight()"); - return; - } - - strokeWeight = weight; - } - - public void strokeJoin(int join) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "strokeJoin()"); - return; - } - - strokeJoin = join; - } - - public void strokeCap(int cap) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "strokeCap()"); - return; - } - - strokeCap = cap; - } - - - ////////////////////////////////////////////////////////////// - - // FILL COLOR - - - public void noFill() { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "noFill()"); - return; - } - - fill = false; - fillColor = 0x0; - - if (!setAmbient) { - ambientColor = fillColor; - } - } - - - public void fill(int rgb) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "fill()"); - return; - } - - fill = true; - colorCalc(rgb); - fillColor = calcColor; - - if (!setAmbient) { - ambientColor = fillColor; - } - } - - - public void fill(int rgb, float alpha) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "fill()"); - return; - } - - fill = true; - colorCalc(rgb, alpha); - fillColor = calcColor; - - if (!setAmbient) { - ambientColor = fillColor; - } - } - - - public void fill(float gray) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "fill()"); - return; - } - - fill = true; - colorCalc(gray); - fillColor = calcColor; - - if (!setAmbient) { - ambientColor = fillColor; - } - } - - - public void fill(float gray, float alpha) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "fill()"); - return; - } - - fill = true; - colorCalc(gray, alpha); - fillColor = calcColor; - - if (!setAmbient) { - ambient(fillColor); - setAmbient = false; - } - - if (!setAmbient) { - ambientColor = fillColor; - } - } - - - public void fill(float x, float y, float z) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "fill()"); - return; - } - - fill = true; - colorCalc(x, y, z); - fillColor = calcColor; - - if (!setAmbient) { - ambientColor = fillColor; - } - } - - - public void fill(float x, float y, float z, float a) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "fill()"); - return; - } - - fill = true; - colorCalc(x, y, z, a); - fillColor = calcColor; - - if (!setAmbient) { - ambientColor = fillColor; - } - } - - - ////////////////////////////////////////////////////////////// - - // STROKE COLOR - - - public void noStroke() { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "noStroke()"); - return; - } - - stroke = false; - } - - - public void stroke(int rgb) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "stroke()"); - return; - } - - stroke = true; - colorCalc(rgb); - strokeColor = calcColor; - } - - - public void stroke(int rgb, float alpha) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "stroke()"); - return; - } - - stroke = true; - colorCalc(rgb, alpha); - strokeColor = calcColor; - } - - - public void stroke(float gray) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "stroke()"); - return; - } - - stroke = true; - colorCalc(gray); - strokeColor = calcColor; - } - - - public void stroke(float gray, float alpha) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "stroke()"); - return; - } - - stroke = true; - colorCalc(gray, alpha); - strokeColor = calcColor; - } - - - public void stroke(float x, float y, float z) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "stroke()"); - return; - } - - stroke = true; - colorCalc(x, y, z); - strokeColor = calcColor; - } - - - public void stroke(float x, float y, float z, float alpha) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "stroke()"); - return; - } - - stroke = true; - colorCalc(x, y, z, alpha); - strokeColor = calcColor; - } - - - ////////////////////////////////////////////////////////////// - - // TINT COLOR - - - public void noTint() { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "noTint()"); - return; - } - - tint = false; - } - - - public void tint(int rgb) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "tint()"); - return; - } - - tint = true; - colorCalc(rgb); - tintColor = calcColor; - } - - - public void tint(int rgb, float alpha) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "tint()"); - return; - } - - tint = true; - colorCalc(rgb, alpha); - tintColor = calcColor; - } - - - public void tint(float gray) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "tint()"); - return; - } - - tint = true; - colorCalc(gray); - tintColor = calcColor; - } - - - public void tint(float gray, float alpha) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "tint()"); - return; - } - - tint = true; - colorCalc(gray, alpha); - tintColor = calcColor; - } - - - public void tint(float x, float y, float z) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "tint()"); - return; - } - - tint = true; - colorCalc(x, y, z); - tintColor = calcColor; - } - - - public void tint(float x, float y, float z, float alpha) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "tint()"); - return; - } - - tint = true; - colorCalc(x, y, z, alpha); - tintColor = calcColor; - } - - - ////////////////////////////////////////////////////////////// - - // Ambient set/update - - public void ambient(int rgb) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "ambient()"); - return; - } - - setAmbient = true; - colorCalc(rgb); - ambientColor = calcColor; - } - - - public void ambient(float gray) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "ambient()"); - return; - } - - setAmbient = true; - colorCalc(gray); - ambientColor = calcColor; - } - - - public void ambient(float x, float y, float z) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "ambient()"); - return; - } - - setAmbient = true; - colorCalc(x, y, z); - ambientColor = calcColor; - } - - - ////////////////////////////////////////////////////////////// - - // Specular set/update - - public void specular(int rgb) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "specular()"); - return; - } - - colorCalc(rgb); - specularColor = calcColor; - } - - - public void specular(float gray) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "specular()"); - return; - } - - colorCalc(gray); - specularColor = calcColor; - } - - - public void specular(float x, float y, float z) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "specular()"); - return; - } - - colorCalc(x, y, z); - specularColor = calcColor; - } - - - ////////////////////////////////////////////////////////////// - - // Emissive set/update - - public void emissive(int rgb) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "emissive()"); - return; - } - - colorCalc(rgb); - emissiveColor = calcColor; - } - - - public void emissive(float gray) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "emissive()"); - return; - } - - colorCalc(gray); - emissiveColor = calcColor; - } - - - public void emissive(float x, float y, float z) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "emissive()"); - return; - } - - colorCalc(x, y, z); - emissiveColor = calcColor; - } - - - ////////////////////////////////////////////////////////////// - - // Shininess set/update - - public void shininess(float shine) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "shininess()"); - return; - } - - shininess = shine; - } - - /////////////////////////////////////////////////////////// - - // - - // Bezier curves - - - public void bezierDetail(int detail) { - } - - - public void bezierVertex(float x2, float y2, - float x3, float y3, - float x4, float y4) { - if (vertices == null) { - vertices = new float[10][]; - } else if (vertexCount + 2 >= vertices.length) { - vertices = (float[][]) PApplet.expand(vertices); - } - vertices[vertexCount++] = new float[] { x2, y2 }; - vertices[vertexCount++] = new float[] { x3, y3 }; - vertices[vertexCount++] = new float[] { x4, y4 }; - - // vertexCodes must be allocated because a vertex() call is required - if (vertexCodes.length == vertexCodeCount) { - vertexCodes = PApplet.expand(vertexCodes); - } - vertexCodes[vertexCodeCount++] = BEZIER_VERTEX; - - if (x4 > width) { - width = x4; - } - if (y4 > height) { - height = y4; - } - } - - - public void bezierVertex(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - } - - - public void quadraticVertex(float cx, float cy, - float x3, float y3) { - if (vertices == null) { - vertices = new float[10][]; - } else if (vertexCount + 1 >= vertices.length) { - vertices = (float[][]) PApplet.expand(vertices); - } - vertices[vertexCount++] = new float[] { cx, cy }; - vertices[vertexCount++] = new float[] { x3, y3 }; - - // vertexCodes must be allocated because a vertex() call is required - if (vertexCodes.length == vertexCodeCount) { - vertexCodes = PApplet.expand(vertexCodes); - } - vertexCodes[vertexCodeCount++] = QUADRATIC_VERTEX; - - if (x3 > width) { - width = x3; - } - if (y3 > height) { - height = y3; - } - } - - - public void quadraticVertex(float cx, float cy, float cz, - float x3, float y3, float z3) { - } - - - /////////////////////////////////////////////////////////// - - // - - // Catmull-Rom curves - - public void curveDetail(int detail) { - } - - public void curveTightness(float tightness) { - } - - public void curveVertex(float x, float y) { - } - - public void curveVertex(float x, float y, float z) { - } - - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /* - boolean strokeSaved; - int strokeColorSaved; - float strokeWeightSaved; - int strokeCapSaved; - int strokeJoinSaved; - - boolean fillSaved; - int fillColorSaved; - - int rectModeSaved; - int ellipseModeSaved; - int shapeModeSaved; - */ - - - protected void pre(PGraphics g) { - if (matrix != null) { - g.pushMatrix(); - g.applyMatrix(matrix); - } - - /* - strokeSaved = g.stroke; - strokeColorSaved = g.strokeColor; - strokeWeightSaved = g.strokeWeight; - strokeCapSaved = g.strokeCap; - strokeJoinSaved = g.strokeJoin; - - fillSaved = g.fill; - fillColorSaved = g.fillColor; - - rectModeSaved = g.rectMode; - ellipseModeSaved = g.ellipseMode; - shapeModeSaved = g.shapeMode; - */ - if (style) { - g.pushStyle(); - styles(g); - } - } - - - protected void styles(PGraphics g) { - // should not be necessary because using only the int version of color - //parent.colorMode(PConstants.RGB, 255); - - if (stroke) { - g.stroke(strokeColor); - g.strokeWeight(strokeWeight); - g.strokeCap(strokeCap); - g.strokeJoin(strokeJoin); - } else { - g.noStroke(); - } - - if (fill) { - //System.out.println("filling " + PApplet.hex(fillColor)); - g.fill(fillColor); - } else { - g.noFill(); - } - } - - - protected void post(PGraphics g) { -// for (int i = 0; i < childCount; i++) { -// children[i].draw(g); -// } - - /* - // TODO this is not sufficient, since not saving fillR et al. - g.stroke = strokeSaved; - g.strokeColor = strokeColorSaved; - g.strokeWeight = strokeWeightSaved; - g.strokeCap = strokeCapSaved; - g.strokeJoin = strokeJoinSaved; - - g.fill = fillSaved; - g.fillColor = fillColorSaved; - - g.ellipseMode = ellipseModeSaved; - */ - - if (matrix != null) { - g.popMatrix(); - } - - if (style) { - g.popStyle(); - } - } - - - //////////////////////////////////////////////////////////////////////// - // - // Shape copy - - - // TODO unapproved - static protected PShape createShape(PApplet parent, PShape src) { - PShape dest = null; - if (src.family == GROUP) { - dest = parent.createShape(GROUP); - PShape.copyGroup(parent, src, dest); - } else if (src.family == PRIMITIVE) { - dest = parent.createShape(src.kind, src.params); - PShape.copyPrimitive(src, dest); - } else if (src.family == GEOMETRY) { - dest = parent.createShape(src.kind); - PShape.copyGeometry(src, dest); - } else if (src.family == PATH) { - dest = parent.createShape(PATH); - PShape.copyPath(src, dest); - } - dest.setName(src.name); - return dest; - } - - - // TODO unapproved - static protected void copyGroup(PApplet parent, PShape src, PShape dest) { - copyMatrix(src, dest); - copyStyles(src, dest); - copyImage(src, dest); - for (int i = 0; i < src.childCount; i++) { - PShape c = PShape.createShape(parent, src.children[i]); - dest.addChild(c); - } - } - - - // TODO unapproved - static protected void copyPrimitive(PShape src, PShape dest) { - copyMatrix(src, dest); - copyStyles(src, dest); - copyImage(src, dest); - } - - - // TODO unapproved - static protected void copyGeometry(PShape src, PShape dest) { - dest.beginShape(src.getKind()); - - copyMatrix(src, dest); - copyStyles(src, dest); - copyImage(src, dest); - - if (src.style) { - for (int i = 0; i < src.vertexCount; i++) { - float[] vert = src.vertices[i]; - - dest.fill((int)(vert[PGraphics.A] * 255) << 24 | - (int)(vert[PGraphics.R] * 255) << 16 | - (int)(vert[PGraphics.G] * 255) << 8 | - (int)(vert[PGraphics.B] * 255)); - - // Do we need to copy these as well? -// dest.ambient(vert[PGraphics.AR] * 255, vert[PGraphics.AG] * 255, vert[PGraphics.AB] * 255); -// dest.specular(vert[PGraphics.SPR] * 255, vert[PGraphics.SPG] * 255, vert[PGraphics.SPB] * 255); -// dest.emissive(vert[PGraphics.ER] * 255, vert[PGraphics.EG] * 255, vert[PGraphics.EB] * 255); -// dest.shininess(vert[PGraphics.SHINE]); - - if (0 < PApplet.dist(vert[PGraphics.NX], - vert[PGraphics.NY], - vert[PGraphics.NZ], 0, 0, 0)) { - dest.normal(vert[PGraphics.NX], - vert[PGraphics.NY], - vert[PGraphics.NZ]); - } - dest.vertex(vert[X], vert[Y], vert[Z], - vert[PGraphics.U], - vert[PGraphics.V]); - } - } else { - for (int i = 0; i < src.vertexCount; i++) { - float[] vert = src.vertices[i]; - if (vert[Z] == 0) { - dest.vertex(vert[X], vert[Y]); - } else { - dest.vertex(vert[X], vert[Y], vert[Z]); - } - } - } - - dest.endShape(); - } - - - // TODO unapproved - static protected void copyPath(PShape src, PShape dest) { - copyMatrix(src, dest); - copyStyles(src, dest); - copyImage(src, dest); - dest.close = src.close; - dest.setPath(src.vertexCount, src.vertices, src.vertexCodeCount, src.vertexCodes); - } - - - // TODO unapproved - static protected void copyMatrix(PShape src, PShape dest) { - if (src.matrix != null) { - dest.applyMatrix(src.matrix); - } - } - - - // TODO unapproved - static protected void copyStyles(PShape src, PShape dest) { - dest.ellipseMode = src.ellipseMode; - dest.rectMode = src.rectMode; - - if (src.stroke) { - dest.stroke = true; - dest.strokeColor = src.strokeColor; - dest.strokeWeight = src.strokeWeight; - dest.strokeCap = src.strokeCap; - dest.strokeJoin = src.strokeJoin; - } else { - dest.stroke = false; - } - - if (src.fill) { - dest.fill = true; - dest.fillColor = src.fillColor; - } else { - dest.fill = false; - } - } - - - // TODO unapproved - static protected void copyImage(PShape src, PShape dest) { - if (src.image != null) { - dest.texture(src.image); - } - } - - - - //////////////////////////////////////////////////////////////////////// - - - /** - * Called by the following (the shape() command adds the g) - * PShape s = loadShape("blah.svg"); - * shape(s); - */ - public void draw(PGraphics g) { - if (visible) { - pre(g); - drawImpl(g); - post(g); - } - } - - - /** - * Draws the SVG document. - */ - protected void drawImpl(PGraphics g) { - if (family == GROUP) { - drawGroup(g); - } else if (family == PRIMITIVE) { - drawPrimitive(g); - } else if (family == GEOMETRY) { - // Not same as path: `kind` matters. -// drawPath(g); - drawGeometry(g); - } else if (family == PATH) { - drawPath(g); - } - } - - - protected void drawGroup(PGraphics g) { - for (int i = 0; i < childCount; i++) { - children[i].draw(g); - } - } - - - protected void drawPrimitive(PGraphics g) { - if (kind == POINT) { - g.point(params[0], params[1]); - - } else if (kind == LINE) { - if (params.length == 4) { // 2D - g.line(params[0], params[1], - params[2], params[3]); - } else { // 3D - g.line(params[0], params[1], params[2], - params[3], params[4], params[5]); - } - - } else if (kind == TRIANGLE) { - g.triangle(params[0], params[1], - params[2], params[3], - params[4], params[5]); - - } else if (kind == QUAD) { - g.quad(params[0], params[1], - params[2], params[3], - params[4], params[5], - params[6], params[7]); - - } else if (kind == RECT) { - - if (imagePath != null){ - loadImage(g); - } - if (image != null) { - int oldMode = g.imageMode; - g.imageMode(CORNER); - g.image(image, params[0], params[1], params[2], params[3]); - g.imageMode(oldMode); - } else { - int oldMode = g.rectMode; - g.rectMode(rectMode); - if (params.length == 4) { - g.rect(params[0], params[1], - params[2], params[3]); - } else if (params.length == 5) { - g.rect(params[0], params[1], - params[2], params[3], - params[4]); - } else if (params.length == 8) { - g.rect(params[0], params[1], - params[2], params[3], - params[4], params[5], - params[6], params[7]); - } - g.rectMode(oldMode); - } - } else if (kind == ELLIPSE) { - int oldMode = g.ellipseMode; - g.ellipseMode(ellipseMode); - g.ellipse(params[0], params[1], - params[2], params[3]); - g.ellipseMode(oldMode); - - } else if (kind == ARC) { - int oldMode = g.ellipseMode; - g.ellipseMode(ellipseMode); - if (params.length == 6) { - g.arc(params[0], params[1], - params[2], params[3], - params[4], params[5]); - } else if (params.length == 7) { - g.arc(params[0], params[1], - params[2], params[3], - params[4], params[5], - (int) params[6]); - } - g.ellipseMode(oldMode); - - } else if (kind == BOX) { - if (params.length == 1) { - g.box(params[0]); - } else { - g.box(params[0], params[1], params[2]); - } - - } else if (kind == SPHERE) { - g.sphere(params[0]); - } - } - - - protected void drawGeometry(PGraphics g) { - // get cache object using g. - g.beginShape(kind); - if (style) { - for (int i = 0; i < vertexCount; i++) { - g.vertex(vertices[i]); - } - } else { - for (int i = 0; i < vertexCount; i++) { - float[] vert = vertices[i]; - if (vert[Z] == 0) { - g.vertex(vert[X], vert[Y]); - } else { - g.vertex(vert[X], vert[Y], vert[Z]); - } - } - } - g.endShape(close ? CLOSE : OPEN); - } - - - /* - protected void drawPath(PGraphics g) { - g.beginShape(); - for (int j = 0; j < childCount; j++) { - if (j > 0) g.breakShape(); - int count = children[j].vertexCount; - float[][] vert = children[j].vertices; - int[] code = children[j].vertexCodes; - - for (int i = 0; i < count; i++) { - if (style) { - if (children[j].fill) { - g.fill(vert[i][R], vert[i][G], vert[i][B]); - } else { - g.noFill(); - } - if (children[j].stroke) { - g.stroke(vert[i][R], vert[i][G], vert[i][B]); - } else { - g.noStroke(); - } - } - g.edge(vert[i][EDGE] == 1); - - if (code[i] == VERTEX) { - g.vertex(vert[i]); - - } else if (code[i] == BEZIER_VERTEX) { - float z0 = vert[i+0][Z]; - float z1 = vert[i+1][Z]; - float z2 = vert[i+2][Z]; - if (z0 == 0 && z1 == 0 && z2 == 0) { - g.bezierVertex(vert[i+0][X], vert[i+0][Y], z0, - vert[i+1][X], vert[i+1][Y], z1, - vert[i+2][X], vert[i+2][Y], z2); - } else { - g.bezierVertex(vert[i+0][X], vert[i+0][Y], - vert[i+1][X], vert[i+1][Y], - vert[i+2][X], vert[i+2][Y]); - } - } else if (code[i] == CURVE_VERTEX) { - float z = vert[i][Z]; - if (z == 0) { - g.curveVertex(vert[i][X], vert[i][Y]); - } else { - g.curveVertex(vert[i][X], vert[i][Y], z); - } - } - } - } - g.endShape(); - } - */ - - protected void drawPath(PGraphics g) { - // Paths might be empty (go figure) - // http://dev.processing.org/bugs/show_bug.cgi?id=982 - if (vertices == null) return; - - boolean insideContour = false; - g.beginShape(); - - if (vertexCodeCount == 0) { // each point is a simple vertex - if (vertices[0].length == 2) { // drawing 2D vertices - for (int i = 0; i < vertexCount; i++) { - g.vertex(vertices[i][X], vertices[i][Y]); - } - } else { // drawing 3D vertices - for (int i = 0; i < vertexCount; i++) { - g.vertex(vertices[i][X], vertices[i][Y], vertices[i][Z]); - } - } - - } else { // coded set of vertices - int index = 0; - - if (vertices[0].length == 2) { // drawing a 2D path - for (int j = 0; j < vertexCodeCount; j++) { - switch (vertexCodes[j]) { - - case VERTEX: - g.vertex(vertices[index][X], vertices[index][Y]); - index++; - break; - - case QUADRATIC_VERTEX: - g.quadraticVertex(vertices[index+0][X], vertices[index+0][Y], - vertices[index+1][X], vertices[index+1][Y]); - index += 2; - break; - - case BEZIER_VERTEX: - g.bezierVertex(vertices[index+0][X], vertices[index+0][Y], - vertices[index+1][X], vertices[index+1][Y], - vertices[index+2][X], vertices[index+2][Y]); - index += 3; - break; - - case CURVE_VERTEX: - g.curveVertex(vertices[index][X], vertices[index][Y]); - index++; - break; - - case BREAK: - if (insideContour) { - g.endContour(); - } - g.beginContour(); - insideContour = true; - } - } - } else { // drawing a 3D path - for (int j = 0; j < vertexCodeCount; j++) { - switch (vertexCodes[j]) { - - case VERTEX: - g.vertex(vertices[index][X], vertices[index][Y], vertices[index][Z]); - index++; - break; - - case QUADRATIC_VERTEX: - g.quadraticVertex(vertices[index+0][X], vertices[index+0][Y], vertices[index+0][Z], - vertices[index+1][X], vertices[index+1][Y], vertices[index+0][Z]); - index += 2; - break; - - - case BEZIER_VERTEX: - g.bezierVertex(vertices[index+0][X], vertices[index+0][Y], vertices[index+0][Z], - vertices[index+1][X], vertices[index+1][Y], vertices[index+1][Z], - vertices[index+2][X], vertices[index+2][Y], vertices[index+2][Z]); - index += 3; - break; - - case CURVE_VERTEX: - g.curveVertex(vertices[index][X], vertices[index][Y], vertices[index][Z]); - index++; - break; - - case BREAK: - if (insideContour) { - g.endContour(); - } - g.beginContour(); - insideContour = true; - } - } - } - } - if (insideContour) { - g.endContour(); - } - g.endShape(close ? CLOSE : OPEN); - } - - - private void loadImage(PGraphics g){ - if (this.imagePath.startsWith("data:image")){ - loadBase64Image(); - } - - if (this.imagePath.startsWith("file://")){ - loadFileSystemImage(g); - } - this.imagePath = null; - } - - private void loadFileSystemImage(PGraphics g){ - imagePath = imagePath.substring(7); - PImage loadedImage = g.parent.loadImage(imagePath); - if (loadedImage == null){ - System.err.println("Error loading image file: " + imagePath); - } else{ - setTexture(loadedImage); - } - } - - private void loadBase64Image(){ - String[] parts = this.imagePath.split(";base64,"); - String extension = parts[0].substring(11); - String encodedData = parts[1]; - -// byte[] decodedBytes = DatatypeConverter.parseBase64Binary(encodedData); - byte[] decodedBytes = parseHexBinary(encodedData); - - if(decodedBytes == null){ - System.err.println("Decode Error on image: " + imagePath.substring(0, 20)); - return; - } - -// Image awtImage = new ImageIcon(decodedBytes).getImage(); - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inMutable = true; - Bitmap bmp = BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length, options); - -// if (awtImage instanceof BufferedImage) { -// BufferedImage buffImage = (BufferedImage) awtImage; -// int space = buffImage.getColorModel().getColorSpace().getType(); -// if (space == ColorSpace.TYPE_CMYK) { -// return; -// } -// } - - PImage loadedImage = new PImage(bmp); - if (loadedImage.width == -1) { - // error... - } - - // if it's a .gif image, test to see if it has transparency - if (extension.equals("gif") || extension.equals("png") || - extension.equals("unknown")) { - loadedImage.checkAlpha(); - } - - setTexture(loadedImage); - } - - - // Replacement for DatatypeConverter - // https://github.com/hierynomus/sshj/issues/366#issue-261511648 - private static byte[] parseHexBinary(String s) - throws IllegalArgumentException { - if (s == null) { - return new byte[0]; - } - s = s.trim(); - int length = s.length(); - - if (length % 2 != 0) { - throw new IllegalArgumentException("Invalid hex string length."); - } - - byte[] result = new byte[length / 2]; - for (int i = 0; i < length; i += 2) { - result[i/2] = (byte) Integer.parseInt(s.substring(i, i + 2), 16); - } - return result; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public PShape getParent() { - return parent; - } - - /** - * @webref - * @brief Returns the number of children - */ - public int getChildCount() { - return childCount; - } - - - /** Resize the children[] array to be in line with childCount */ - protected void crop() { - // https://github.com/processing/processing/issues/3347 - if (children.length != childCount) { - children = (PShape[]) PApplet.subset(children, 0, childCount); - } - } - - - public PShape[] getChildren() { - crop(); - return children; - } - - /** - * ( begin auto-generated from PShape_getChild.xml ) - * - * Extracts a child shape from a parent shape. Specify the name of the - * shape with the target parameter. The shape is returned as a - * PShape object, or null is returned if there is an error. - * - * ( end auto-generated ) - * @webref pshape:method - * @usage web_application - * @brief Returns a child element of a shape as a PShape object - * @param index the layer position of the shape to get - * @see PShape#addChild(PShape) - */ - public PShape getChild(int index) { - crop(); - return children[index]; - } - - /** - * @param target the name of the shape to get - */ - public PShape getChild(String target) { - if (name != null && name.equals(target)) { - return this; - } - if (nameTable != null) { - PShape found = nameTable.get(target); - if (found != null) return found; - } - for (int i = 0; i < childCount; i++) { - PShape found = children[i].getChild(target); - if (found != null) return found; - } - return null; - } - - - /** - * Same as getChild(name), except that it first walks all the way up the - * hierarchy to the eldest grandparent, so that children can be found anywhere. - */ - public PShape findChild(String target) { - if (parent == null) { - return getChild(target); - - } else { - return parent.findChild(target); - } - } - - - // can't be just 'add' because that suggests additive geometry - /** - * @webref pshape:method - * @brief Adds a new child - * @param who any variable of type PShape - * @see PShape#getChild(int) - */ - public void addChild(PShape who) { - if (children == null) { - children = new PShape[1]; - } - if (childCount == children.length) { - children = (PShape[]) PApplet.expand(children); - } - children[childCount++] = who; - who.parent = this; - - if (who.getName() != null) { - addName(who.getName(), who); - } - } - - - // adds child who exactly at position idx in the array of children. - /** - * @param idx the layer position in which to insert the new child - */ - public void addChild(PShape who, int idx) { - if (idx < childCount) { - if (childCount == children.length) { - children = (PShape[]) PApplet.expand(children); - } - - // Copy [idx, childCount - 1] to [idx + 1, childCount] - for (int i = childCount - 1; i >= idx; i--) { - children[i + 1] = children[i]; - } - childCount++; - - children[idx] = who; - - who.parent = this; - - if (who.getName() != null) { - addName(who.getName(), who); - } - } - } - - - /** - * Remove the child shape with index idx. - */ - public void removeChild(int idx) { - if (idx < childCount) { - PShape child = children[idx]; - - // Copy [idx + 1, childCount - 1] to [idx, childCount - 2] - for (int i = idx; i < childCount - 1; i++) { - children[i] = children[i + 1]; - } - childCount--; - - if (child.getName() != null && nameTable != null) { - nameTable.remove(child.getName()); - } - } - } - - - /** - * Add a shape to the name lookup table. - */ - public void addName(String nom, PShape shape) { - if (parent != null) { - parent.addName(nom, shape); - } else { - if (nameTable == null) { - nameTable = new HashMap<>(); - } - nameTable.put(nom, shape); - } - } - - - /** - * Returns the index of child who. - */ - public int getChildIndex(PShape who) { - for (int i = 0; i < childCount; i++) { - if (children[i] == who) { - return i; - } - } - return -1; - } - - - public PShape getTessellation() { - return null; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** The shape type, one of GROUP, PRIMITIVE, PATH, or GEOMETRY. */ - public int getFamily() { - return family; - } - - - public int getKind() { - return kind; - } - - - public float[] getParams() { - return getParams(null); - } - - - public float[] getParams(float[] target) { - if (target == null || target.length != params.length) { - target = new float[params.length]; - } - PApplet.arrayCopy(params, target); - return target; - } - - - public float getParam(int index) { - return params[index]; - } - - - protected void setParams(float[] source) { - if (params == null) { - params = new float[source.length]; - } - if (source.length != params.length) { - PGraphics.showWarning("Wrong number of parameters"); - return; - } - PApplet.arrayCopy(source, params); - } - - - public void setPath(int vcount, float[][] verts) { - setPath(vcount, verts, 0, null); - } - - - protected void setPath(int vcount, float[][] verts, int ccount, int[] codes) { - if (verts == null || verts.length < vcount) return; - if (0 < ccount && (codes == null || codes.length < ccount)) return; - - int ndim = verts[0].length; - vertexCount = vcount; - vertices = new float[vertexCount][ndim]; - for (int i = 0; i < vertexCount; i++) { - PApplet.arrayCopy(verts[i], vertices[i]); - } - - vertexCodeCount = ccount; - if (0 < vertexCodeCount) { - vertexCodes = new int[vertexCodeCount]; - PApplet.arrayCopy(codes, vertexCodes, vertexCodeCount); - } - } - - /** - * @webref pshape:method - * @brief Returns the total number of vertices as an int - * @see PShape#getVertex(int) - * @see PShape#setVertex(int, float, float) - */ - public int getVertexCount() { - if (family == GROUP || family == PRIMITIVE) { - PGraphics.showWarning(NO_VERTICES_ERROR); - } - return vertexCount; - } - - - /** - * @webref pshape:method - * @brief Returns the vertex at the index position - * @param index the location of the vertex - * @see PShape#setVertex(int, float, float) - * @see PShape#getVertexCount() - */ - public PVector getVertex(int index) { - return getVertex(index, null); - } - - - /** - * @param vec PVector to assign the data to - */ - public PVector getVertex(int index, PVector vec) { - if (vec == null) { - vec = new PVector(); - } - float[] vert = vertices[index]; - vec.x = vert[X]; - vec.y = vert[Y]; - if (vert.length > 2) { - vec.z = vert[Z]; - } else { - vec.z = 0; // in case this isn't a new vector - } - return vec; - } - - - public float getVertexX(int index) { - return vertices[index][X]; - } - - - public float getVertexY(int index) { - return vertices[index][Y]; - } - - - public float getVertexZ(int index) { - return vertices[index][Z]; - } - - - /** - * @webref pshape:method - * @brief Sets the vertex at the index position - * @param index the location of the vertex - * @param x the x value for the vertex - * @param y the y value for the vertex - * @see PShape#getVertex(int) - * @see PShape#getVertexCount() - */ - public void setVertex(int index, float x, float y) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setVertex()"); - return; - } - - vertices[index][X] = x; - vertices[index][Y] = y; - } - - - /** - * @param z the z value for the vertex - */ - public void setVertex(int index, float x, float y, float z) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setVertex()"); - return; - } - - vertices[index][X] = x; - vertices[index][Y] = y; - vertices[index][Z] = z; - } - - - /** - * @param vec the PVector to define the x, y, z coordinates - */ - public void setVertex(int index, PVector vec) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setVertex()"); - return; - } - - vertices[index][X] = vec.x; - vertices[index][Y] = vec.y; - - if (vertices[index].length > 2) { - vertices[index][Z] = vec.z; - } else if (vec.z != 0 && vec.z == vec.z) { - throw new IllegalArgumentException("Cannot set a z-coordinate on a 2D shape"); - } - } - - - public PVector getNormal(int index) { - return getNormal(index, null); - } - - - public PVector getNormal(int index, PVector vec) { - if (vec == null) { - vec = new PVector(); - } - vec.x = vertices[index][PGraphics.NX]; - vec.y = vertices[index][PGraphics.NY]; - vec.z = vertices[index][PGraphics.NZ]; - return vec; - } - - - public float getNormalX(int index) { - return vertices[index][PGraphics.NX]; - } - - - public float getNormalY(int index) { - return vertices[index][PGraphics.NY]; - } - - - public float getNormalZ(int index) { - return vertices[index][PGraphics.NZ]; - } - - - public void setNormal(int index, float nx, float ny, float nz) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setNormal()"); - return; - } - - vertices[index][PGraphics.NX] = nx; - vertices[index][PGraphics.NY] = ny; - vertices[index][PGraphics.NZ] = nz; - } - - - - public void setAttrib(String name, int index, float... values) { - } - - - public void setAttrib(String name, int index, int... values) { - } - - - public void setAttrib(String name, int index, boolean... values) { - } - - - public float getTextureU(int index) { - return vertices[index][PGraphics.U]; - } - - - public float getTextureV(int index) { - return vertices[index][PGraphics.V]; - } - - - public void setTextureUV(int index, float u, float v) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTextureUV()"); - return; - } - - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || - index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "setTextureUV()"); - return; - } - - - vertices[index][PGraphics.U] = u; - vertices[index][PGraphics.V] = v; - } - - - public void setTextureMode(int mode) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTextureMode()"); - return; - } - - textureMode = mode; - } - - - public void setTexture(PImage tex) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTexture()"); - return; - } - - image = tex; - } - - - public int getFill(int index) { - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || - index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "getFill()"); - return fillColor; - } - - if (image == null) { - int a = (int) (vertices[index][PGraphics.A] * 255); - int r = (int) (vertices[index][PGraphics.R] * 255); - int g = (int) (vertices[index][PGraphics.G] * 255); - int b = (int) (vertices[index][PGraphics.B] * 255); - return (a << 24) | (r << 16) | (g << 8) | b; - } else { - return 0; - } - } - - /** - * @nowebref - */ - public void setFill(boolean fill) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setFill()"); - return; - } - - this.fill = fill; - } - - - /** - * ( begin auto-generated from PShape_setFill.xml ) - * - * The setFill() method defines the fill color of a PShape. - * This method is used after shapes are created or when a shape is defined explicitly - * (e.g. createShape(RECT, 20, 20, 80, 80)) as shown in the above example. - * When a shape is created with beginShape() and endShape(), its - * attributes may be changed with fill() and stroke() within - * beginShape() and endShape(). However, after the shape is - * created, only the setFill() method can define a new fill value for - * the PShape. - * - * ( end auto-generated ) - * - * @webref - * @param fill - * @brief Set the fill value - */ - public void setFill(int fill) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setFill()"); - return; - } - - this.fillColor = fill; - - if (vertices != null && perVertexStyles) { - for (int i = 0; i < vertexCount; i++) { - setFill(i, fill); - } - } - } - - /** - * @nowebref - */ - public void setFill(int index, int fill) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setFill()"); - return; - } - - if (!perVertexStyles) { - PGraphics.showWarning(PER_VERTEX_UNSUPPORTED, "setFill()"); - return; - } - - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "getFill()"); - return; - } - - if (image == null) { - vertices[index][PGraphics.A] = ((fill >> 24) & 0xFF) / 255.0f; - vertices[index][PGraphics.R] = ((fill >> 16) & 0xFF) / 255.0f; - vertices[index][PGraphics.G] = ((fill >> 8) & 0xFF) / 255.0f; - vertices[index][PGraphics.B] = ((fill >> 0) & 0xFF) / 255.0f; - } - } - - - public int getTint(int index) { - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "getTint()"); - return this.tintColor; - } - - if (image != null) { - int a = (int) (vertices[index][PGraphics.A] * 255); - int r = (int) (vertices[index][PGraphics.R] * 255); - int g = (int) (vertices[index][PGraphics.G] * 255); - int b = (int) (vertices[index][PGraphics.B] * 255); - return (a << 24) | (r << 16) | (g << 8) | b; - } else { - return 0; - } - } - - - public void setTint(boolean tint) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTint()"); - return; - } - - this.tint = tint; - } - - - public void setTint(int fill) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTint()"); - return; - } - - tintColor = fill; - - if (vertices != null) { - for (int i = 0; i < vertices.length; i++) { - setFill(i, fill); - } - } - } - - - public void setTint(int index, int tint) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTint()"); - return; - } - - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || - index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "setTint()"); - return; - } - - if (image != null) { - vertices[index][PGraphics.A] = ((tint >> 24) & 0xFF) / 255.0f; - vertices[index][PGraphics.R] = ((tint >> 16) & 0xFF) / 255.0f; - vertices[index][PGraphics.G] = ((tint >> 8) & 0xFF) / 255.0f; - vertices[index][PGraphics.B] = ((tint >> 0) & 0xFF) / 255.0f; - } - } - - - public int getStroke(int index) { - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || - index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "getStroke()"); - return strokeColor; - } - - int a = (int) (vertices[index][PGraphics.SA] * 255); - int r = (int) (vertices[index][PGraphics.SR] * 255); - int g = (int) (vertices[index][PGraphics.SG] * 255); - int b = (int) (vertices[index][PGraphics.SB] * 255); - return (a << 24) | (r << 16) | (g << 8) | b; - } - - - /** - * @nowebref - */ - public void setStroke(boolean stroke) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStroke()"); - return; - } - - this.stroke = stroke; - } - - - /** - * ( begin auto-generated from PShape_setStroke.xml ) - * - * The setStroke() method defines the outline color of a PShape. - * This method is used after shapes are created or when a shape is defined - * explicitly (e.g. createShape(RECT, 20, 20, 80, 80)) as shown in - * the above example. When a shape is created with beginShape() and - * endShape(), its attributes may be changed with fill() and - * stroke() within beginShape() and endShape(). - * However, after the shape is created, only the setStroke() method - * can define a new stroke value for the PShape. - * - * ( end auto-generated ) - * - * @webref - * @param stroke - * @brief Set the stroke value - */ - public void setStroke(int stroke) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStroke()"); - return; - } - - strokeColor = stroke; - - if (vertices != null && perVertexStyles) { - for (int i = 0; i < vertices.length; i++) { - setStroke(i, stroke); - } - } - } - - - /** - * @nowebref - */ - public void setStroke(int index, int stroke) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStroke()"); - return; - } - - if (!perVertexStyles) { - PGraphics.showWarning(PER_VERTEX_UNSUPPORTED, "setStroke()"); - return; - } - - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "setStroke()"); - return; - } - - vertices[index][PGraphics.SA] = ((stroke >> 24) & 0xFF) / 255.0f; - vertices[index][PGraphics.SR] = ((stroke >> 16) & 0xFF) / 255.0f; - vertices[index][PGraphics.SG] = ((stroke >> 8) & 0xFF) / 255.0f; - vertices[index][PGraphics.SB] = ((stroke >> 0) & 0xFF) / 255.0f; - } - - - public float getStrokeWeight(int index) { - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "getStrokeWeight()"); - return strokeWeight; - } - - - return vertices[index][PGraphics.SW]; - } - - - public void setStrokeWeight(float weight) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStrokeWeight()"); - return; - } - - strokeWeight = weight; - - if (vertices != null && perVertexStyles) { - for (int i = 0; i < vertexCount; i++) { - setStrokeWeight(i, weight); - } - } - } - - - public void setStrokeWeight(int index, float weight) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStrokeWeight()"); - return; - } - - if (!perVertexStyles) { - PGraphics.showWarning(PER_VERTEX_UNSUPPORTED, "setStrokeWeight()"); - return; - } - - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "setStrokeWeight()"); - return; - } - - vertices[index][PGraphics.SW] = weight; - } - - - public void setStrokeJoin(int join) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStrokeJoin()"); - return; - } - - strokeJoin = join; - } - - - public void setStrokeCap(int cap) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStrokeCap()"); - return; - } - - strokeCap = cap; - } - - - public int getAmbient(int index) { - - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "getAmbient()"); - return ambientColor; - } - - int r = (int) (vertices[index][PGraphics.AR] * 255); - int g = (int) (vertices[index][PGraphics.AG] * 255); - int b = (int) (vertices[index][PGraphics.AB] * 255); - return 0xff000000 | (r << 16) | (g << 8) | b; - } - - - public void setAmbient(int ambient) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setAmbient()"); - return; - } - - ambientColor = ambient; - - if (vertices != null) { - for (int i = 0; i < vertices.length; i++) { - setAmbient(i, ambient); - } - } - } - - - public void setAmbient(int index, int ambient) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setAmbient()"); - return; - } - - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "setAmbient()"); - return; - } - - vertices[index][PGraphics.AR] = ((ambient >> 16) & 0xFF) / 255.0f; - vertices[index][PGraphics.AG] = ((ambient >> 8) & 0xFF) / 255.0f; - vertices[index][PGraphics.AB] = ((ambient >> 0) & 0xFF) / 255.0f; - } - - - public int getSpecular(int index) { - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "getSpecular()"); - return specularColor; - } - - int r = (int) (vertices[index][PGraphics.SPR] * 255); - int g = (int) (vertices[index][PGraphics.SPG] * 255); - int b = (int) (vertices[index][PGraphics.SPB] * 255); - return 0xff000000 | (r << 16) | (g << 8) | b; - } - - - public void setSpecular(int specular) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setSpecular()"); - return; - } - - specularColor = specular; - - if (vertices != null) { - for (int i = 0; i < vertices.length; i++) { - setSpecular(i, specular); - } - } - } - - - public void setSpecular(int index, int specular) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setSpecular()"); - return; - } - - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "setSpecular()"); - return; - } - - vertices[index][PGraphics.SPR] = ((specular >> 16) & 0xFF) / 255.0f; - vertices[index][PGraphics.SPG] = ((specular >> 8) & 0xFF) / 255.0f; - vertices[index][PGraphics.SPB] = ((specular >> 0) & 0xFF) / 255.0f; - } - - - public int getEmissive(int index) { - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "getEmissive()"); - return emissiveColor; - } - - int r = (int) (vertices[index][PGraphics.ER] * 255); - int g = (int) (vertices[index][PGraphics.EG] * 255); - int b = (int) (vertices[index][PGraphics.EB] * 255); - return 0xff000000 | (r << 16) | (g << 8) | b; - } - - - public void setEmissive(int emissive) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setEmissive()"); - return; - } - - emissiveColor = emissive; - - if (vertices != null) { - for (int i = 0; i < vertices.length; i++) { - setEmissive(i, emissive); - } - } - } - - - public void setEmissive(int index, int emissive) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setEmissive()"); - return; - } - - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || - index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "setEmissive()"); - return; - } - - vertices[index][PGraphics.ER] = ((emissive >> 16) & 0xFF) / 255.0f; - vertices[index][PGraphics.EG] = ((emissive >> 8) & 0xFF) / 255.0f; - vertices[index][PGraphics.EB] = ((emissive >> 0) & 0xFF) / 255.0f; - } - - - public float getShininess(int index) { - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || - index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "getShininess()"); - return shininess; - } - - return vertices[index][PGraphics.SHINE]; - } - - - public void setShininess(float shine) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setShininess()"); - return; - } - - shininess = shine; - - if (vertices != null) { - for (int i = 0; i < vertices.length; i++) { - setShininess(i, shine); - } - } - } - - - public void setShininess(int index, float shine) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setShininess()"); - return; - } - - // make sure we allocated the vertices array and that vertex exists - if (vertices == null || - index >= vertices.length) { - PGraphics.showWarning(NO_SUCH_VERTEX_ERROR + " (" + index + ")", "setShininess()"); - return; - } - - - vertices[index][PGraphics.SHINE] = shine; - } - - - public int[] getVertexCodes() { - if (vertexCodes == null) { - return null; - } - if (vertexCodes.length != vertexCodeCount) { - vertexCodes = PApplet.subset(vertexCodes, 0, vertexCodeCount); - } - return vertexCodes; - } - - - public int getVertexCodeCount() { - return vertexCodeCount; - } - - - /** - * One of VERTEX, BEZIER_VERTEX, CURVE_VERTEX, or BREAK. - */ - public int getVertexCode(int index) { - return vertexCodes[index]; - } - - - public boolean isClosed() { - return close; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Return true if this x, y coordinate is part of this shape. Only works - * with PATH shapes or GROUP shapes that contain other GROUPs or PATHs. - */ - public boolean contains(float x, float y) { - if (family == PATH) { - PVector p = new PVector(x, y); - if (matrix != null) { - // apply the inverse transformation matrix to the point coordinates - PMatrix inverseCoords = matrix.get(); - // TODO why is this called twice? [fry 190724] - // commit was https://github.com/processing/processing/commit/027fc7a4f8e8d0a435366eae754304eea282512a - inverseCoords.invert(); // maybe cache this? - inverseCoords.invert(); // maybe cache this? - inverseCoords.mult(new PVector(x, y), p); - } - - // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html - boolean c = false; - for (int i = 0, j = vertexCount-1; i < vertexCount; j = i++) { - if (((vertices[i][Y] > p.y) != (vertices[j][Y] > p.y)) && - (p.x < - (vertices[j][X]-vertices[i][X]) * - (y-vertices[i][Y]) / - (vertices[j][1]-vertices[i][Y]) + - vertices[i][X])) { - c = !c; - } - } - return c; - - } else if (family == GROUP) { - // If this is a group, loop through children until we find one that - // contains the supplied coordinates. If a child does not support - // contains() throw a warning and continue. - for (int i = 0; i < childCount; i++) { - if (children[i].contains(x, y)) return true; - } - return false; - - } else { - // https://github.com/processing/processing/issues/1280 - throw new IllegalArgumentException("The contains() method is only implemented for paths."); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - // translate, rotate, scale, apply (no push/pop) - // these each call matrix.translate, etc - // if matrix is null when one is called, - // it is created and set to identity - - -/** - * ( begin auto-generated from PShape_translate.xml ) - * - * Specifies an amount to displace the shape. The x parameter - * specifies left/right translation, the y parameter specifies - * up/down translation, and the z parameter specifies translations - * toward/away from the screen. Subsequent calls to the method accumulates - * the effect. For example, calling translate(50, 0) and then - * translate(20, 0) is the same as translate(70, 0). This - * transformation is applied directly to the shape, it's not refreshed each - * time draw() is run. - *

    - * Using this method with the z parameter requires using the P3D - * parameter in combination with size. - * - * ( end auto-generated ) - * @webref pshape:method - * @usage web_application - * @brief Displaces the shape - * @param x left/right translation - * @param y up/down translation - * @see PShape#rotate(float) - * @see PShape#scale(float) - * @see PShape#resetMatrix() - */ - public void translate(float x, float y) { - checkMatrix(2); - matrix.translate(x, y); - } - - /** - * @param z forward/back translation - */ - public void translate(float x, float y, float z) { - checkMatrix(3); - matrix.translate(x, y, z); - } - - /** - * ( begin auto-generated from PShape_rotateX.xml ) - * - * Rotates a shape around the x-axis the amount specified by the - * angle parameter. Angles should be specified in radians (values - * from 0 to TWO_PI) or converted to radians with the radians() method. - *

    - * Shapes are always rotated around the upper-left corner of their bounding - * box. Positive numbers rotate objects in a clockwise direction. - * Subsequent calls to the method accumulates the effect. For example, - * calling rotateX(HALF_PI) and then rotateX(HALF_PI) is the - * same as rotateX(PI). This transformation is applied directly to - * the shape, it's not refreshed each time draw() is run. - *

    - * This method requires a 3D renderer. You need to use P3D as a third - * parameter for the size() function as shown in the example above. - * - * ( end auto-generated ) - * @webref pshape:method - * @usage web_application - * @brief Rotates the shape around the x-axis - * @param angle angle of rotation specified in radians - * @see PShape#rotate(float) - * @see PShape#rotateY(float) - * @see PShape#rotateZ(float) - * @see PShape#scale(float) - * @see PShape#translate(float, float) - * @see PShape#resetMatrix() - */ - public void rotateX(float angle) { - rotate(angle, 1, 0, 0); - } - - /** - * ( begin auto-generated from PShape_rotateY.xml ) - * - * Rotates a shape around the y-axis the amount specified by the - * angle parameter. Angles should be specified in radians (values - * from 0 to TWO_PI) or converted to radians with the radians() method. - *

    - * Shapes are always rotated around the upper-left corner of their bounding - * box. Positive numbers rotate objects in a clockwise direction. - * Subsequent calls to the method accumulates the effect. For example, - * calling rotateY(HALF_PI) and then rotateY(HALF_PI) is the - * same as rotateY(PI). This transformation is applied directly to - * the shape, it's not refreshed each time draw() is run. - *

    - * This method requires a 3D renderer. You need to use P3D as a third - * parameter for the size() function as shown in the example above. - * - * ( end auto-generated ) - * - * @webref pshape:method - * @usage web_application - * @brief Rotates the shape around the y-axis - * @param angle angle of rotation specified in radians - * @see PShape#rotate(float) - * @see PShape#rotateX(float) - * @see PShape#rotateZ(float) - * @see PShape#scale(float) - * @see PShape#translate(float, float) - * @see PShape#resetMatrix() - */ - public void rotateY(float angle) { - rotate(angle, 0, 1, 0); - } - - - /** - * ( begin auto-generated from PShape_rotateZ.xml ) - * - * Rotates a shape around the z-axis the amount specified by the - * angle parameter. Angles should be specified in radians (values - * from 0 to TWO_PI) or converted to radians with the radians() method. - *

    - * Shapes are always rotated around the upper-left corner of their bounding - * box. Positive numbers rotate objects in a clockwise direction. - * Subsequent calls to the method accumulates the effect. For example, - * calling rotateZ(HALF_PI) and then rotateZ(HALF_PI) is the - * same as rotateZ(PI). This transformation is applied directly to - * the shape, it's not refreshed each time draw() is run. - *

    - * This method requires a 3D renderer. You need to use P3D as a third - * parameter for the size() function as shown in the example above. - * - * ( end auto-generated ) - * @webref pshape:method - * @usage web_application - * @brief Rotates the shape around the z-axis - * @param angle angle of rotation specified in radians - * @see PShape#rotate(float) - * @see PShape#rotateX(float) - * @see PShape#rotateY(float) - * @see PShape#scale(float) - * @see PShape#translate(float, float) - * @see PShape#resetMatrix() - */ - public void rotateZ(float angle) { - rotate(angle, 0, 0, 1); - } - - /** - * ( begin auto-generated from PShape_rotate.xml ) - * - * Rotates a shape the amount specified by the angle parameter. - * Angles should be specified in radians (values from 0 to TWO_PI) or - * converted to radians with the radians() method. - *

    - * Shapes are always rotated around the upper-left corner of their bounding - * box. Positive numbers rotate objects in a clockwise direction. - * Transformations apply to everything that happens after and subsequent - * calls to the method accumulates the effect. For example, calling - * rotate(HALF_PI) and then rotate(HALF_PI) is the same as - * rotate(PI). This transformation is applied directly to the shape, - * it's not refreshed each time draw() is run. - * - * ( end auto-generated ) - * @webref pshape:method - * @usage web_application - * @brief Rotates the shape - * @param angle angle of rotation specified in radians - * @see PShape#rotateX(float) - * @see PShape#rotateY(float) - * @see PShape#rotateZ(float) - * @see PShape#scale(float) - * @see PShape#translate(float, float) - * @see PShape#resetMatrix() - */ - public void rotate(float angle) { - checkMatrix(2); // at least 2... - matrix.rotate(angle); - } - -/** - * @nowebref - */ - public void rotate(float angle, float v0, float v1, float v2) { - checkMatrix(3); - float norm2 = v0 * v0 + v1 * v1 + v2 * v2; - if (Math.abs(norm2 - 1) > EPSILON) { - // The rotation vector is not normalized. - float norm = PApplet.sqrt(norm2); - v0 /= norm; - v1 /= norm; - v2 /= norm; - } - matrix.rotate(angle, v0, v1, v2); - } - - - // - - /** - * ( begin auto-generated from PShape_scale.xml ) - * - * Increases or decreases the size of a shape by expanding and contracting - * vertices. Shapes always scale from the relative origin of their bounding - * box. Scale values are specified as decimal percentages. For example, the - * method call scale(2.0) increases the dimension of a shape by - * 200%. Subsequent calls to the method multiply the effect. For example, - * calling scale(2.0) and then scale(1.5) is the same as - * scale(3.0). This transformation is applied directly to the shape, - * it's not refreshed each time draw() is run. - *

    - * Using this method with the z parameter requires using the P3D - * parameter in combination with size. - * - * ( end auto-generated ) - * @webref pshape:method - * @usage web_application - * @brief Increases and decreases the size of a shape - * @param s percentate to scale the object - * @see PShape#rotate(float) - * @see PShape#translate(float, float) - * @see PShape#resetMatrix() - */ - public void scale(float s) { - checkMatrix(2); // at least 2... - matrix.scale(s); - } - - - public void scale(float x, float y) { - checkMatrix(2); - matrix.scale(x, y); - } - -/** - * @param x percentage to scale the object in the x-axis - * @param y percentage to scale the object in the y-axis - * @param z percentage to scale the object in the z-axis - */ - public void scale(float x, float y, float z) { - checkMatrix(3); - matrix.scale(x, y, z); - } - - - // - -/** - * ( begin auto-generated from PShape_resetMatrix.xml ) - * - * Replaces the current matrix of a shape with the identity matrix. The - * equivalent function in OpenGL is glLoadIdentity(). - * - * ( end auto-generated ) - * @webref pshape:method - * @brief Replaces the current matrix of a shape with the identity matrix - * @usage web_application - * @see PShape#rotate(float) - * @see PShape#scale(float) - * @see PShape#translate(float, float) - */ - public void resetMatrix() { - checkMatrix(2); - matrix.reset(); - } - - - public void applyMatrix(PMatrix source) { - if (source instanceof PMatrix2D) { - applyMatrix((PMatrix2D) source); - } else if (source instanceof PMatrix3D) { - applyMatrix((PMatrix3D) source); - } - } - - - public void applyMatrix(PMatrix2D source) { - applyMatrix(source.m00, source.m01, 0, source.m02, - source.m10, source.m11, 0, source.m12, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - public void applyMatrix(float n00, float n01, float n02, - float n10, float n11, float n12) { - checkMatrix(2); - matrix.apply(n00, n01, n02, - n10, n11, n12); - } - - - public void applyMatrix(PMatrix3D source) { - applyMatrix(source.m00, source.m01, source.m02, source.m03, - source.m10, source.m11, source.m12, source.m13, - source.m20, source.m21, source.m22, source.m23, - source.m30, source.m31, source.m32, source.m33); - } - - - public void applyMatrix(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - checkMatrix(3); - matrix.apply(n00, n01, n02, n03, - n10, n11, n12, n13, - n20, n21, n22, n23, - n30, n31, n32, n33); - } - - - // - - - /** - * Make sure that the shape's matrix is 1) not null, and 2) has a matrix - * that can handle at least the specified number of dimensions. - */ - protected void checkMatrix(int dimensions) { - if (matrix == null) { - if (dimensions == 2) { - matrix = new PMatrix2D(); - } else { - matrix = new PMatrix3D(); - } - } else if (dimensions == 3 && (matrix instanceof PMatrix2D)) { - // time for an upgrayedd for a double dose of my pimpin' - matrix = new PMatrix3D(matrix); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Center the shape based on its bounding box. Can't assume - * that the bounding box is 0, 0, width, height. Common case will be - * opening a letter size document in Illustrator, and drawing something - * in the middle, then reading it in as an svg file. - * This will also need to flip the y axis (scale(1, -1)) in cases - * like Adobe Illustrator where the coordinates start at the bottom. - */ -// public void center() { -// } - - - /** - * Set the pivot point for all transformations. - */ -// public void pivot(float x, float y) { -// px = x; -// py = y; -// } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public void colorMode(int mode) { - colorMode(mode, colorModeX, colorModeY, colorModeZ, colorModeA); - } - - /** - * @param max range for all color elements - */ - public void colorMode(int mode, float max) { - colorMode(mode, max, max, max, max); - } - - - /** - * @param maxX range for the red or hue depending on the current color mode - * @param maxY range for the green or saturation depending on the current color mode - * @param maxZ range for the blue or brightness depending on the current color mode - */ - public void colorMode(int mode, float maxX, float maxY, float maxZ) { - colorMode(mode, maxX, maxY, maxZ, colorModeA); - } - -/** - * @param maxA range for the alpha - */ - public void colorMode(int mode, - float maxX, float maxY, float maxZ, float maxA) { - colorMode = mode; - - colorModeX = maxX; // still needs to be set for hsb - colorModeY = maxY; - colorModeZ = maxZ; - colorModeA = maxA; - - // if color max values are all 1, then no need to scale - colorModeScale = - ((maxA != 1) || (maxX != maxY) || (maxY != maxZ) || (maxZ != maxA)); - - // if color is rgb/0..255 this will make it easier for the - // red() green() etc functions - colorModeDefault = (colorMode == RGB) && - (colorModeA == 255) && (colorModeX == 255) && - (colorModeY == 255) && (colorModeZ == 255); - } - - - protected void colorCalc(int rgb) { - if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { - colorCalc((float) rgb); - - } else { - colorCalcARGB(rgb, colorModeA); - } - } - - - protected void colorCalc(int rgb, float alpha) { - if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { // see above - colorCalc((float) rgb, alpha); - - } else { - colorCalcARGB(rgb, alpha); - } - } - - - protected void colorCalc(float gray) { - colorCalc(gray, colorModeA); - } - - - protected void colorCalc(float gray, float alpha) { - if (gray > colorModeX) gray = colorModeX; - if (alpha > colorModeA) alpha = colorModeA; - - if (gray < 0) gray = 0; - if (alpha < 0) alpha = 0; - - calcR = colorModeScale ? (gray / colorModeX) : gray; - calcG = calcR; - calcB = calcR; - calcA = colorModeScale ? (alpha / colorModeA) : alpha; - - calcRi = (int)(calcR*255); calcGi = (int)(calcG*255); - calcBi = (int)(calcB*255); calcAi = (int)(calcA*255); - calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi; - calcAlpha = (calcAi != 255); - } - - - protected void colorCalc(float x, float y, float z) { - colorCalc(x, y, z, colorModeA); - } - - - protected void colorCalc(float x, float y, float z, float a) { - if (x > colorModeX) x = colorModeX; - if (y > colorModeY) y = colorModeY; - if (z > colorModeZ) z = colorModeZ; - if (a > colorModeA) a = colorModeA; - - if (x < 0) x = 0; - if (y < 0) y = 0; - if (z < 0) z = 0; - if (a < 0) a = 0; - - switch (colorMode) { - case RGB: - if (colorModeScale) { - calcR = x / colorModeX; - calcG = y / colorModeY; - calcB = z / colorModeZ; - calcA = a / colorModeA; - } else { - calcR = x; calcG = y; calcB = z; calcA = a; - } - break; - - case HSB: - x /= colorModeX; // h - y /= colorModeY; // s - z /= colorModeZ; // b - - calcA = colorModeScale ? (a/colorModeA) : a; - - if (y == 0) { // saturation == 0 - calcR = calcG = calcB = z; - - } else { - float which = (x - (int)x) * 6.0f; - float f = which - (int)which; - float p = z * (1.0f - y); - float q = z * (1.0f - y * f); - float t = z * (1.0f - (y * (1.0f - f))); - - switch ((int)which) { - case 0: calcR = z; calcG = t; calcB = p; break; - case 1: calcR = q; calcG = z; calcB = p; break; - case 2: calcR = p; calcG = z; calcB = t; break; - case 3: calcR = p; calcG = q; calcB = z; break; - case 4: calcR = t; calcG = p; calcB = z; break; - case 5: calcR = z; calcG = p; calcB = q; break; - } - } - break; - } - calcRi = (int)(255*calcR); calcGi = (int)(255*calcG); - calcBi = (int)(255*calcB); calcAi = (int)(255*calcA); - calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi; - calcAlpha = (calcAi != 255); - } - - - protected void colorCalcARGB(int argb, float alpha) { - if (alpha == colorModeA) { - calcAi = (argb >> 24) & 0xff; - calcColor = argb; - } else { - calcAi = (int) (((argb >> 24) & 0xff) * (alpha / colorModeA)); - calcColor = (calcAi << 24) | (argb & 0xFFFFFF); - } - calcRi = (argb >> 16) & 0xff; - calcGi = (argb >> 8) & 0xff; - calcBi = argb & 0xff; - calcA = calcAi / 255.0f; - calcR = calcRi / 255.0f; - calcG = calcGi / 255.0f; - calcB = calcBi / 255.0f; - calcAlpha = (calcAi != 255); - } - -} diff --git a/core/src/processing/core/PShapeOBJ.java b/core/src/processing/core/PShapeOBJ.java deleted file mode 100644 index 470f3820a..000000000 --- a/core/src/processing/core/PShapeOBJ.java +++ /dev/null @@ -1,468 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - -import java.io.BufferedReader; -import java.io.File; -import java.util.ArrayList; -import java.util.Hashtable; - - -/** - * This class is not part of the Processing API and should not be used - * directly. Instead, use loadShape() and methods like it, which will make - * use of this class. Using this class directly will cause your code to break - * when combined with future versions of Processing. - *

    - * OBJ loading implemented using code from Saito's OBJLoader library: - * http://code.google.com/p/saitoobjloader/ - * and OBJReader from Ahmet Kizilay - * http://www.openprocessing.org/visuals/?visualID=191 - * - */ -public class PShapeOBJ extends PShape { - - /** - * Initializes a new OBJ Object with the given filename. - */ - public PShapeOBJ(PApplet parent, String filename) { - this(parent, parent.createReader(filename), getBasePath(parent, filename)); - } - - public PShapeOBJ(PApplet parent, BufferedReader reader) { - this(parent, reader, ""); - } - - public PShapeOBJ(PApplet parent, BufferedReader reader, String basePath) { - ArrayList faces = new ArrayList(); - ArrayList materials = new ArrayList(); - ArrayList coords = new ArrayList(); - ArrayList normals = new ArrayList(); - ArrayList texcoords = new ArrayList(); - parseOBJ(parent, basePath, - reader, faces, materials, coords, normals, texcoords); - - // The OBJ geometry is stored with each face in a separate child shape. - parent = null; - family = GROUP; - addChildren(faces, materials, coords, normals, texcoords); - } - - - protected PShapeOBJ(OBJFace face, OBJMaterial mtl, - ArrayList coords, - ArrayList normals, - ArrayList texcoords) { - family = GEOMETRY; - if (face.vertIdx.size() == 3) { - kind = TRIANGLES; - } else if (face.vertIdx.size() == 4) { - kind = QUADS; - } else { - kind = POLYGON; - } - - stroke = false; - fill = true; - - // Setting material properties for the new face - fillColor = rgbaValue(mtl.kd); - ambientColor = rgbaValue(mtl.ka); - specularColor = rgbaValue(mtl.ks); - shininess = mtl.ns; - if (mtl.kdMap != null) { - // If current material is textured, then tinting the texture using the - // diffuse color. - tintColor = rgbaValue(mtl.kd, mtl.d); - } - - vertexCount = face.vertIdx.size(); - vertices = new float[vertexCount][12]; - for (int j = 0; j < face.vertIdx.size(); j++){ - int vertIdx, normIdx; - PVector vert, norms; - - vert = norms = null; - - vertIdx = face.vertIdx.get(j).intValue() - 1; - vert = coords.get(vertIdx); - - if (j < face.normIdx.size()) { - normIdx = face.normIdx.get(j).intValue() - 1; - if (-1 < normIdx) { - norms = normals.get(normIdx); - } - } - - vertices[j][X] = vert.x; - vertices[j][Y] = vert.y; - vertices[j][Z] = vert.z; - - vertices[j][PGraphics.R] = mtl.kd.x; - vertices[j][PGraphics.G] = mtl.kd.y; - vertices[j][PGraphics.B] = mtl.kd.z; - vertices[j][PGraphics.A] = 1; - - if (norms != null) { - vertices[j][PGraphics.NX] = norms.x; - vertices[j][PGraphics.NY] = norms.y; - vertices[j][PGraphics.NZ] = norms.z; - } - - if (mtl != null && mtl.kdMap != null) { - // This face is textured. - int texIdx; - PVector tex = null; - - if (j < face.texIdx.size()) { - texIdx = face.texIdx.get(j).intValue() - 1; - if (-1 < texIdx) { - tex = texcoords.get(texIdx); - } - } - - image = mtl.kdMap; - if (tex != null) { - vertices[j][PGraphics.U] = tex.x; - vertices[j][PGraphics.V] = tex.y; - } - } - } - } - - - protected void addChildren(ArrayList faces, - ArrayList materials, - ArrayList coords, - ArrayList normals, - ArrayList texcoords) { - int mtlIdxCur = -1; - OBJMaterial mtl = null; - for (int i = 0; i < faces.size(); i++) { - OBJFace face = faces.get(i); - - // Getting current material. - if (mtlIdxCur != face.matIdx || face.matIdx == -1) { - // To make sure that at least we get the default material - mtlIdxCur = PApplet.max(0, face.matIdx); - mtl = materials.get(mtlIdxCur); - } - - // Creating child shape for current face. - PShape child = new PShapeOBJ(face, mtl, coords, normals, texcoords); - addChild(child); - } - } - - - static protected void parseOBJ(PApplet parent, String path, - BufferedReader reader, - ArrayList faces, - ArrayList materials, - ArrayList coords, - ArrayList normals, - ArrayList texcoords) { - Hashtable mtlTable = new Hashtable(); - int mtlIdxCur = -1; - boolean readv, readvn, readvt; - try { - - readv = readvn = readvt = false; - String line; - String gname = "object"; - while ((line = reader.readLine()) != null) { - // Parse the line. - line = line.trim(); - if (line.equals("") || line.indexOf('#') == 0) { - // Empty line of comment, ignore line - continue; - } - - // The below patch/hack comes from Carlos Tomas Marti and is a - // fix for single backslashes in Rhino obj files - - // BEGINNING OF RHINO OBJ FILES HACK - // Statements can be broken in multiple lines using '\' at the - // end of a line. - // In regular expressions, the backslash is also an escape - // character. - // The regular expression \\ matches a single backslash. This - // regular expression as a Java string, becomes "\\\\". - // That's right: 4 backslashes to match a single one. - while (line.contains("\\")) { - line = line.split("\\\\")[0]; - final String s = reader.readLine(); - if (s != null) - line += s; - } - // END OF RHINO OBJ FILES HACK - - String[] parts = line.split("\\s+"); - // if not a blank line, process the line. - if (parts.length > 0) { - if (parts[0].equals("v")) { - // vertex - PVector tempv = new PVector(Float.valueOf(parts[1]).floatValue(), - Float.valueOf(parts[2]).floatValue(), - Float.valueOf(parts[3]).floatValue()); - coords.add(tempv); - readv = true; - } else if (parts[0].equals("vn")) { - // normal - PVector tempn = new PVector(Float.valueOf(parts[1]).floatValue(), - Float.valueOf(parts[2]).floatValue(), - Float.valueOf(parts[3]).floatValue()); - normals.add(tempn); - readvn = true; - } else if (parts[0].equals("vt")) { - // uv, inverting v to take into account Processing's inverted Y axis - // with respect to OpenGL. - PVector tempv = new PVector(Float.valueOf(parts[1]).floatValue(), - 1 - Float.valueOf(parts[2]).floatValue()); - texcoords.add(tempv); - readvt = true; - } else if (parts[0].equals("o")) { - // Object name is ignored, for now. - } else if (parts[0].equals("mtllib")) { - if (parts[1] != null) { - String fn = parts[1]; - if (fn.indexOf(File.separator) == -1 && !path.equals("")) { - // Relative file name, adding the base path. - fn = path + File.separator + fn; - } - BufferedReader mreader = parent.createReader(fn); - if (mreader != null) { - parseMTL(parent, path, - mreader, materials, mtlTable); - } - } - } else if (parts[0].equals("g")) { - gname = 1 < parts.length ? parts[1] : ""; - } else if (parts[0].equals("usemtl")) { - // Getting index of current active material (will be applied on - // all subsequent faces). - if (parts[1] != null) { - String mtlname = parts[1]; - if (mtlTable.containsKey(mtlname)) { - Integer tempInt = mtlTable.get(mtlname); - mtlIdxCur = tempInt.intValue(); - } else { - mtlIdxCur = -1; - } - } - } else if (parts[0].equals("f")) { - // Face setting - OBJFace face = new OBJFace(); - face.matIdx = mtlIdxCur; - face.name = gname; - - for (int i = 1; i < parts.length; i++) { - String seg = parts[i]; - - if (seg.indexOf("/") > 0) { - String[] forder = seg.split("/"); - - if (forder.length > 2) { - // Getting vertex and texture and normal indexes. - if (forder[0].length() > 0 && readv) { - face.vertIdx.add(Integer.valueOf(forder[0])); - } - - if (forder[1].length() > 0 && readvt) { - face.texIdx.add(Integer.valueOf(forder[1])); - } - - if (forder[2].length() > 0 && readvn) { - face.normIdx.add(Integer.valueOf(forder[2])); - } - } else if (forder.length > 1) { - // Getting vertex and texture/normal indexes. - if (forder[0].length() > 0 && readv) { - face.vertIdx.add(Integer.valueOf(forder[0])); - } - - if (forder[1].length() > 0) { - if (readvt) { - face.texIdx.add(Integer.valueOf(forder[1])); - } else if (readvn) { - face.normIdx.add(Integer.valueOf(forder[1])); - } - - } - - } else if (forder.length > 0) { - // Getting vertex index only. - if (forder[0].length() > 0 && readv) { - face.vertIdx.add(Integer.valueOf(forder[0])); - } - } - } else { - // Getting vertex index only. - if (seg.length() > 0 && readv) { - face.vertIdx.add(Integer.valueOf(seg)); - } - } - } - - faces.add(face); - } - } - } - - if (materials.size() == 0) { - // No materials definition so far. Adding one default material. - OBJMaterial defMtl = new OBJMaterial(); - materials.add(defMtl); - } - - } catch (Exception e) { - e.printStackTrace(); - } - } - - - static protected void parseMTL(PApplet parent, String path, - BufferedReader reader, - ArrayList materials, - Hashtable materialsHash) { - try { - String line; - OBJMaterial currentMtl = null; - while ((line = reader.readLine()) != null) { - // Parse the line - line = line.trim(); - String parts[] = line.split("\\s+"); - if (parts.length > 0) { - // Extract the material data. - if (parts[0].equals("newmtl")) { - // Starting new material. - String mtlname = parts[1]; - currentMtl = new OBJMaterial(mtlname); - materialsHash.put(mtlname, Integer.valueOf(materials.size())); - materials.add(currentMtl); - } else if (parts[0].equals("map_Kd") && parts.length > 1) { - // Loading texture map. - String texname = parts[1]; - if (texname.indexOf(File.separator) == -1 && !path.equals("")) { - // Relative file name, adding the base path. - texname = path + File.separator + texname; - } - currentMtl.kdMap = parent.loadImage(texname); - } else if (parts[0].equals("Ka") && parts.length > 3) { - // The ambient color of the material - currentMtl.ka.x = Float.valueOf(parts[1]).floatValue(); - currentMtl.ka.y = Float.valueOf(parts[2]).floatValue(); - currentMtl.ka.z = Float.valueOf(parts[3]).floatValue(); - } else if (parts[0].equals("Kd") && parts.length > 3) { - // The diffuse color of the material - currentMtl.kd.x = Float.valueOf(parts[1]).floatValue(); - currentMtl.kd.y = Float.valueOf(parts[2]).floatValue(); - currentMtl.kd.z = Float.valueOf(parts[3]).floatValue(); - } else if (parts[0].equals("Ks") && parts.length > 3) { - // The specular color weighted by the specular coefficient - currentMtl.ks.x = Float.valueOf(parts[1]).floatValue(); - currentMtl.ks.y = Float.valueOf(parts[2]).floatValue(); - currentMtl.ks.z = Float.valueOf(parts[3]).floatValue(); - } else if ((parts[0].equals("d") || - parts[0].equals("Tr")) && parts.length > 1) { - // Reading the alpha transparency. - currentMtl.d = Float.valueOf(parts[1]).floatValue(); - } else if (parts[0].equals("Ns") && parts.length > 1) { - // The specular component of the Phong shading model - currentMtl.ns = Float.valueOf(parts[1]).floatValue(); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - - protected static int rgbaValue(PVector color) { - return 0xFF000000 | ((int)(color.x * 255) << 16) | - ((int)(color.y * 255) << 8) | - (int)(color.z * 255); - } - - - protected static int rgbaValue(PVector color, float alpha) { - return ((int)(alpha * 255) << 24) | - ((int)(color.x * 255) << 16) | - ((int)(color.y * 255) << 8) | - (int)(color.z * 255); - } - - - // Stores a face from an OBJ file - static protected class OBJFace { - ArrayList vertIdx; - ArrayList texIdx; - ArrayList normIdx; - int matIdx; - String name; - - OBJFace() { - vertIdx = new ArrayList(); - texIdx = new ArrayList(); - normIdx = new ArrayList(); - matIdx = -1; - name = ""; - } - } - - - static protected String getBasePath(PApplet parent, String filename) { - if (-1 < filename.indexOf(File.separator)) { - return filename.substring(0, filename.lastIndexOf(File.separator)); - } - return ""; - } - - - // Stores a material defined in an MTL file. - static protected class OBJMaterial { - String name; - PVector ka; - PVector kd; - PVector ks; - float d; - float ns; - PImage kdMap; - - OBJMaterial() { - this("default"); - } - - OBJMaterial(String name) { - this.name = name; - ka = new PVector(0.5f, 0.5f, 0.5f); - kd = new PVector(0.5f, 0.5f, 0.5f); - ks = new PVector(0.5f, 0.5f, 0.5f); - d = 1.0f; - ns = 0.0f; - kdMap = null; - } - } -} - diff --git a/core/src/processing/core/PShapeSVG.java b/core/src/processing/core/PShapeSVG.java deleted file mode 100644 index 33bd932b8..000000000 --- a/core/src/processing/core/PShapeSVG.java +++ /dev/null @@ -1,2031 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2006-12 Ben Fry and Casey Reas - Copyright (c) 2004-06 Michael Chang - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - -//import static java.awt.Font.BOLD; -//import static java.awt.Font.ITALIC; -//import static java.awt.Font.PLAIN; -import processing.data.*; - -// TODO replace these with PMatrix2D -import android.graphics.Matrix; -//import java.awt.geom.AffineTransform; -//import java.awt.geom.Point2D; - -import java.util.Map; -import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - -/** - * This class is not part of the Processing API and should not be used - * directly. Instead, use loadShape() and methods like it, which will make - * use of this class. Using this class directly will cause your code to break - * when combined with future versions of Processing. - *

    - * SVG stands for Scalable Vector Graphics, a portable graphics format. - * It is a vector format so it allows for "infinite" resolution and relatively - * small file sizes. Most modern media software can view SVG files, including - * Adobe products, Firefox, etc. Illustrator and Inkscape can edit SVG files. - * View the SVG specification here. - *

    - * We have no intention of turning this into a full-featured SVG library. - * The goal of this project is a basic shape importer that originally was small - * enough to be included with applets, meaning that its download size should be - * in the neighborhood of 25-30 Kb. Though we're far less limited nowadays on - * size constraints, we remain extremely limited in terms of time, and do not - * have volunteers who are available to maintain a larger SVG library. - *

    - * For more sophisticated import/export, consider the - * Batik - * library from the Apache Software Foundation. - *

    - * Batik is used in the SVG Export library in Processing 3, however using it - * for full SVG import is still a considerable amount of work. Wiring it to - * Java2D wouldn't be too bad, but using it with OpenGL, JavaFX, and features - * like begin/endRecord() and begin/endRaw() would be considerable effort. - *

    - * Future improvements to this library may focus on this properly supporting - * a specific subset of SVG, for instance the simpler SVG profiles known as - * SVG Tiny or Basic, - * although we still would not support the interactivity options. - * - *


    - * - * A minimal example program using SVG: - * (assuming a working moo.svg is in your data folder) - * - *

    - * PShape moo;
    - *
    - * void setup() {
    - *   size(400, 400);
    - *   moo = loadShape("moo.svg");
    - * }
    - * void draw() {
    - *   background(255);
    - *   shape(moo, mouseX, mouseY);
    - * }
    - * 
    - */ -public class PShapeSVG extends PShape { - XML element; - - /// Values between 0 and 1. - protected float opacity; - float strokeOpacity; - float fillOpacity; - - /** Width of containing SVG (used for percentages). */ - protected float svgWidth; - - /** Height of containing SVG (used for percentages). */ - protected float svgHeight; - - /** √((w² + h²)/2) of containing SVG (used for percentages). */ - protected float svgSizeXY; - - protected Gradient strokeGradient; - String strokeName; // id of another object, gradients only? - - protected Gradient fillGradient; - String fillName; // id of another object - - - /** - * Initializes a new SVG object from the given XML object. - */ - public PShapeSVG(XML svg) { - this(null, svg, true); - - if (!svg.getName().equals("svg")) { - if (svg.getName().toLowerCase().equals("html")) { - // Common case is that files aren't downloaded properly - throw new RuntimeException("This appears to be a web page, not an SVG file."); - } else { - throw new RuntimeException("The root node is not , it's <" + svg.getName() + ">"); - } - } - } - - - protected PShapeSVG(PShapeSVG parent, XML properties, boolean parseKids) { - setParent(parent); - - // Need to get width/height in early. - if (properties.getName().equals("svg")) { - String unitWidth = properties.getString("width"); - String unitHeight = properties.getString("height"); - - // Can't handle width/height as percentages easily. I'm just going - // to put in 100 as a dummy value, beacuse this means that it will - // come out as a reasonable value. - if (unitWidth != null) width = parseUnitSize(unitWidth, 100); - if (unitHeight != null) height = parseUnitSize(unitHeight, 100); - - String viewBoxStr = properties.getString("viewBox"); - if (viewBoxStr != null) { - float[] viewBox = PApplet.parseFloat(PApplet.splitTokens(viewBoxStr)); - if (unitWidth == null || unitHeight == null) { - // Not proper parsing of the viewBox, but will cover us for cases where - // the width and height of the object is not specified. - width = viewBox[2]; - height = viewBox[3]; - } else { - // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute - // TODO: preserveAspectRatio. - if (matrix == null) matrix = new PMatrix2D(); - matrix.scale(width/viewBox[2], height/viewBox[3]); - matrix.translate(-viewBox[0], -viewBox[1]); - } - } - - // Negative size is illegal. - if (width < 0 || height < 0) - throw new RuntimeException(": width (" + width + - ") and height (" + height + ") must not be negative."); - - // It's technically valid to have width or height == 0. Not specified at - // all is what to test for. - if ((unitWidth == null || unitHeight == null) && viewBoxStr == null) { - //throw new RuntimeException("width/height not specified"); - PGraphics.showWarning("The width and/or height is not " + - "readable in the tag of this file."); - // For the spec, the default is 100% and 100%. For purposes - // here, insert a dummy value because this is prolly just a - // font or something for which the w/h doesn't matter. - width = 1; - height = 1; - } - - svgWidth = width; - svgHeight = height; - svgSizeXY = PApplet.sqrt((svgWidth*svgWidth + svgHeight*svgHeight)/2.0f); - } - - element = properties; - name = properties.getString("id"); - // @#$(* adobe illustrator mangles names of objects when re-saving - if (name != null) { - while (true) { - String[] m = PApplet.match(name, "_x([A-Za-z0-9]{2})_"); - if (m == null) break; - char repair = (char) PApplet.unhex(m[1]); - name = name.replace(m[0], "" + repair); - } - } - - String displayStr = properties.getString("display", "inline"); - visible = !displayStr.equals("none"); - - String transformStr = properties.getString("transform"); - if (transformStr != null) { - if (matrix == null) { - matrix = parseTransform(transformStr); - } else { - matrix.preApply(parseTransform(transformStr)); - } - } - - if (parseKids) { - parseColors(properties); - parseChildren(properties); - } - } - - - // Broken out so that subclasses can copy any additional variables - // (i.e. fillGradientPaint and strokeGradientPaint) - protected void setParent(PShapeSVG parent) { - // Need to set this so that findChild() works. - // Otherwise 'parent' is null until addChild() is called later. - this.parent = parent; - - if (parent == null) { - // set values to their defaults according to the SVG spec - stroke = false; - strokeColor = 0xff000000; - strokeWeight = 1; - strokeCap = PConstants.SQUARE; // equivalent to BUTT in svg spec - strokeJoin = PConstants.MITER; - strokeGradient = null; -// strokeGradientPaint = null; - strokeName = null; - - fill = true; - fillColor = 0xff000000; - fillGradient = null; -// fillGradientPaint = null; - fillName = null; - - //hasTransform = false; - //transformation = null; //new float[] { 1, 0, 0, 1, 0, 0 }; - - // svgWidth, svgHeight, and svgXYSize done below. - - strokeOpacity = 1; - fillOpacity = 1; - opacity = 1; - - } else { - stroke = parent.stroke; - strokeColor = parent.strokeColor; - strokeWeight = parent.strokeWeight; - strokeCap = parent.strokeCap; - strokeJoin = parent.strokeJoin; - strokeGradient = parent.strokeGradient; -// strokeGradientPaint = parent.strokeGradientPaint; - strokeName = parent.strokeName; - - fill = parent.fill; - fillColor = parent.fillColor; - fillGradient = parent.fillGradient; -// fillGradientPaint = parent.fillGradientPaint; - fillName = parent.fillName; - - svgWidth = parent.svgWidth; - svgHeight = parent.svgHeight; - svgSizeXY = parent.svgSizeXY; - - opacity = parent.opacity; - } - - // The rect and ellipse modes are set to CORNER since it is the expected - // mode for svg shapes. - rectMode = CORNER; - ellipseMode = CORNER; - } - - - /** Factory method for subclasses. */ - protected PShapeSVG createShape(PShapeSVG parent, XML properties, boolean parseKids) { - return new PShapeSVG(parent, properties, parseKids); - } - - - protected void parseChildren(XML graphics) { - XML[] elements = graphics.getChildren(); - children = new PShape[elements.length]; - childCount = 0; - - for (XML elem : elements) { - PShape kid = parseChild(elem); - if (kid != null) addChild(kid); - } - children = (PShape[]) PApplet.subset(children, 0, childCount); - } - - - /** - * Parse a child XML element. - * Override this method to add parsing for more SVG elements. - */ - protected PShape parseChild(XML elem) { -// System.err.println("parsing child in pshape " + elem.getName()); - String name = elem.getName(); - PShapeSVG shape = null; - - - if (name == null) { - // just some whitespace that can be ignored (hopefully) - - } else if (name.equals("g")) { - shape = createShape(this, elem, true); - - } else if (name.equals("defs")) { - // generally this will contain gradient info, so may - // as well just throw it into a group element for parsing - shape = createShape(this, elem, true); - - } else if (name.equals("line")) { - shape = createShape(this, elem, true); - shape.parseLine(); - - } else if (name.equals("circle")) { - shape = createShape(this, elem, true); - shape.parseEllipse(true); - - } else if (name.equals("ellipse")) { - shape = createShape(this, elem, true); - shape.parseEllipse(false); - - } else if (name.equals("rect")) { - shape = createShape(this, elem, true); - shape.parseRect(); - - } else if (name.equals("image")) { - shape = createShape(this, elem, true); - shape.parseImage(); - - } else if (name.equals("polygon")) { - shape = createShape(this, elem, true); - shape.parsePoly(true); - - } else if (name.equals("polyline")) { - shape = createShape(this, elem, true); - shape.parsePoly(false); - - } else if (name.equals("path")) { - shape = createShape(this, elem, true); - shape.parsePath(); - - } else if (name.equals("radialGradient")) { - return new RadialGradient(this, elem); - - } else if (name.equals("linearGradient")) { - return new LinearGradient(this, elem); - - } else if (name.equals("font")) { - return new Font(this, elem); - -// } else if (name.equals("font-face")) { -// return new FontFace(this, elem); - -// } else if (name.equals("glyph") || name.equals("missing-glyph")) { -// return new FontGlyph(this, elem); - - } else if (name.equals("text")) { // || name.equals("font")) { - return new Text(this, elem); - - } else if (name.equals("tspan")) { -// return new LineOfText(this, elem); - PGraphics.showWarning("tspan elements are not supported."); - - } else if (name.equals("filter")) { - PGraphics.showWarning("Filters are not supported."); - - } else if (name.equals("mask")) { - PGraphics.showWarning("Masks are not supported."); - - } else if (name.equals("pattern")) { - PGraphics.showWarning("Patterns are not supported."); - - } else if (name.equals("stop")) { - // stop tag is handled by gradient parser, so don't warn about it - - } else if (name.equals("sodipodi:namedview")) { - // these are always in Inkscape files, the warnings get tedious - - } else if (name.equals("metadata") - || name.equals("title") || name.equals("desc")) { - // fontforge just stuffs in as a comment. - // All harmless stuff, irrelevant to rendering. - return null; - - } else if (!name.startsWith("#")) { - PGraphics.showWarning("Ignoring <" + name + "> tag."); -// new Exception().printStackTrace(); - } - return shape; - } - - - protected void parseLine() { - kind = LINE; - family = PRIMITIVE; - params = new float[] { - getFloatWithUnit(element, "x1", svgWidth), - getFloatWithUnit(element, "y1", svgHeight), - getFloatWithUnit(element, "x2", svgWidth), - getFloatWithUnit(element, "y2", svgHeight) - }; - } - - - /** - * Handles parsing ellipse and circle tags. - * @param circle true if this is a circle and not an ellipse - */ - protected void parseEllipse(boolean circle) { - kind = ELLIPSE; - family = PRIMITIVE; - params = new float[4]; - - params[0] = getFloatWithUnit(element, "cx", svgWidth); - params[1] = getFloatWithUnit(element, "cy", svgHeight); - - float rx, ry; - if (circle) { - rx = ry = getFloatWithUnit(element, "r", svgSizeXY); - } else { - rx = getFloatWithUnit(element, "rx", svgWidth); - ry = getFloatWithUnit(element, "ry", svgHeight); - } - params[0] -= rx; - params[1] -= ry; - - params[2] = rx*2; - params[3] = ry*2; - } - - - protected void parseRect() { - kind = RECT; - family = PRIMITIVE; - params = new float[] { - getFloatWithUnit(element, "x", svgWidth), - getFloatWithUnit(element, "y", svgHeight), - getFloatWithUnit(element, "width", svgWidth), - getFloatWithUnit(element, "height", svgHeight) - }; - } - - - protected void parseImage() { - kind = RECT; - textureMode = NORMAL; - - family = PRIMITIVE; - params = new float[] { - getFloatWithUnit(element, "x", svgWidth), - getFloatWithUnit(element, "y", svgHeight), - getFloatWithUnit(element, "width", svgWidth), - getFloatWithUnit(element, "height", svgHeight) - }; - - this.imagePath = element.getString("xlink:href"); - } - - /** - * Parse a polyline or polygon from an SVG file. - * Syntax defined at http://www.w3.org/TR/SVG/shapes.html#PointsBNF - * @param close true if shape is closed (polygon), false if not (polyline) - */ - protected void parsePoly(boolean close) { - family = PATH; - this.close = close; - - String pointsAttr = element.getString("points"); - if (pointsAttr != null) { - Pattern pattern = Pattern.compile("([+-]?[\\d]+(\\.[\\d]+)?([eE][+-][\\d]+)?)(,?\\s*)([+-]?[\\d]+(\\.[\\d]+)?([eE][+-][\\d]+)?)"); - Matcher matcher = pattern.matcher(pointsAttr); - vertexCount = 0; - while (matcher.find()) { - vertexCount++; - } - matcher.reset(); - vertices = new float[vertexCount][2]; - for (int i = 0; i < vertexCount; i++) { - matcher.find(); - vertices[i][X] = Float.parseFloat(matcher.group(1)); - vertices[i][Y] = Float.parseFloat(matcher.group(5)); - } -// String[] pointsBuffer = PApplet.splitTokens(pointsAttr); -// vertexCount = pointsBuffer.length; -// vertices = new float[vertexCount][2]; -// for (int i = 0; i < vertexCount; i++) { -// String pb[] = PApplet.splitTokens(pointsBuffer[i], ", \t\r\n"); -// vertices[i][X] = Float.parseFloat(pb[0]); -// vertices[i][Y] = Float.parseFloat(pb[1]); -// } - } - } - - - protected void parsePath() { - family = PATH; - kind = 0; - - String pathData = element.getString("d"); - if (pathData == null || PApplet.trim(pathData).length() == 0) { - return; - } - char[] pathDataChars = pathData.toCharArray(); - - StringBuilder pathBuffer = new StringBuilder(); - boolean lastSeparate = false; - - for (int i = 0; i < pathDataChars.length; i++) { - char c = pathDataChars[i]; - boolean separate = false; - - if (c == 'M' || c == 'm' || - c == 'L' || c == 'l' || - c == 'H' || c == 'h' || - c == 'V' || c == 'v' || - c == 'C' || c == 'c' || // beziers - c == 'S' || c == 's' || - c == 'Q' || c == 'q' || // quadratic beziers - c == 'T' || c == 't' || - c == 'A' || c == 'a' || // elliptical arc - c == 'Z' || c == 'z' || // closepath - c == ',') { - separate = true; - if (i != 0) { - pathBuffer.append("|"); - } - } - if (c == 'Z' || c == 'z') { - separate = false; - } - if (c == '-' && !lastSeparate) { - // allow for 'e' notation in numbers, e.g. 2.10e-9 - // http://dev.processing.org/bugs/show_bug.cgi?id=1408 - if (i == 0 || pathDataChars[i-1] != 'e') { - pathBuffer.append("|"); - } - } - if (c != ',') { - pathBuffer.append(c); //"" + pathDataBuffer.charAt(i)); - } - if (separate && c != ',' && c != '-') { - pathBuffer.append("|"); - } - lastSeparate = separate; - } - - // use whitespace constant to get rid of extra spaces and CR or LF - String[] pathTokens = - PApplet.splitTokens(pathBuffer.toString(), "|" + WHITESPACE); - vertices = new float[pathTokens.length][2]; - vertexCodes = new int[pathTokens.length]; - - float cx = 0; - float cy = 0; - int i = 0; - - char implicitCommand = '\0'; -// char prevCommand = '\0'; - boolean prevCurve = false; - float ctrlX, ctrlY; - // store values for closepath so that relative coords work properly - float movetoX = 0; - float movetoY = 0; - - while (i < pathTokens.length) { - char c = pathTokens[i].charAt(0); - if (((c >= '0' && c <= '9') || (c == '-')) && implicitCommand != '\0') { - c = implicitCommand; - i--; - } else { - implicitCommand = c; - } - switch (c) { - - case 'M': // M - move to (absolute) - cx = PApplet.parseFloat(pathTokens[i + 1]); - cy = PApplet.parseFloat(pathTokens[i + 2]); - movetoX = cx; - movetoY = cy; - parsePathMoveto(cx, cy); - implicitCommand = 'L'; - i += 3; - break; - - case 'm': // m - move to (relative) - cx = cx + PApplet.parseFloat(pathTokens[i + 1]); - cy = cy + PApplet.parseFloat(pathTokens[i + 2]); - movetoX = cx; - movetoY = cy; - parsePathMoveto(cx, cy); - implicitCommand = 'l'; - i += 3; - break; - - case 'L': - cx = PApplet.parseFloat(pathTokens[i + 1]); - cy = PApplet.parseFloat(pathTokens[i + 2]); - parsePathLineto(cx, cy); - i += 3; - break; - - case 'l': - cx = cx + PApplet.parseFloat(pathTokens[i + 1]); - cy = cy + PApplet.parseFloat(pathTokens[i + 2]); - parsePathLineto(cx, cy); - i += 3; - break; - - // horizontal lineto absolute - case 'H': - cx = PApplet.parseFloat(pathTokens[i + 1]); - parsePathLineto(cx, cy); - i += 2; - break; - - // horizontal lineto relative - case 'h': - cx = cx + PApplet.parseFloat(pathTokens[i + 1]); - parsePathLineto(cx, cy); - i += 2; - break; - - case 'V': - cy = PApplet.parseFloat(pathTokens[i + 1]); - parsePathLineto(cx, cy); - i += 2; - break; - - case 'v': - cy = cy + PApplet.parseFloat(pathTokens[i + 1]); - parsePathLineto(cx, cy); - i += 2; - break; - - // C - curve to (absolute) - case 'C': { - float ctrlX1 = PApplet.parseFloat(pathTokens[i + 1]); - float ctrlY1 = PApplet.parseFloat(pathTokens[i + 2]); - float ctrlX2 = PApplet.parseFloat(pathTokens[i + 3]); - float ctrlY2 = PApplet.parseFloat(pathTokens[i + 4]); - float endX = PApplet.parseFloat(pathTokens[i + 5]); - float endY = PApplet.parseFloat(pathTokens[i + 6]); - parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY); - cx = endX; - cy = endY; - i += 7; - prevCurve = true; - } - break; - - // c - curve to (relative) - case 'c': { - float ctrlX1 = cx + PApplet.parseFloat(pathTokens[i + 1]); - float ctrlY1 = cy + PApplet.parseFloat(pathTokens[i + 2]); - float ctrlX2 = cx + PApplet.parseFloat(pathTokens[i + 3]); - float ctrlY2 = cy + PApplet.parseFloat(pathTokens[i + 4]); - float endX = cx + PApplet.parseFloat(pathTokens[i + 5]); - float endY = cy + PApplet.parseFloat(pathTokens[i + 6]); - parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY); - cx = endX; - cy = endY; - i += 7; - prevCurve = true; - } - break; - - // S - curve to shorthand (absolute) - // Draws a cubic Bézier curve from the current point to (x,y). The first - // control point is assumed to be the reflection of the second control - // point on the previous command relative to the current point. - // (x2,y2) is the second control point (i.e., the control point - // at the end of the curve). S (uppercase) indicates that absolute - // coordinates will follow; s (lowercase) indicates that relative - // coordinates will follow. Multiple sets of coordinates may be specified - // to draw a polybézier. At the end of the command, the new current point - // becomes the final (x,y) coordinate pair used in the polybézier. - case 'S': { - // (If there is no previous command or if the previous command was not - // an C, c, S or s, assume the first control point is coincident with - // the current point.) - if (!prevCurve) { - ctrlX = cx; - ctrlY = cy; - } else { - float ppx = vertices[vertexCount-2][X]; - float ppy = vertices[vertexCount-2][Y]; - float px = vertices[vertexCount-1][X]; - float py = vertices[vertexCount-1][Y]; - ctrlX = px + (px - ppx); - ctrlY = py + (py - ppy); - } - float ctrlX2 = PApplet.parseFloat(pathTokens[i + 1]); - float ctrlY2 = PApplet.parseFloat(pathTokens[i + 2]); - float endX = PApplet.parseFloat(pathTokens[i + 3]); - float endY = PApplet.parseFloat(pathTokens[i + 4]); - parsePathCurveto(ctrlX, ctrlY, ctrlX2, ctrlY2, endX, endY); - cx = endX; - cy = endY; - i += 5; - prevCurve = true; - } - break; - - // s - curve to shorthand (relative) - case 's': { - if (!prevCurve) { - ctrlX = cx; - ctrlY = cy; - } else { - float ppx = vertices[vertexCount-2][X]; - float ppy = vertices[vertexCount-2][Y]; - float px = vertices[vertexCount-1][X]; - float py = vertices[vertexCount-1][Y]; - ctrlX = px + (px - ppx); - ctrlY = py + (py - ppy); - } - float ctrlX2 = cx + PApplet.parseFloat(pathTokens[i + 1]); - float ctrlY2 = cy + PApplet.parseFloat(pathTokens[i + 2]); - float endX = cx + PApplet.parseFloat(pathTokens[i + 3]); - float endY = cy + PApplet.parseFloat(pathTokens[i + 4]); - parsePathCurveto(ctrlX, ctrlY, ctrlX2, ctrlY2, endX, endY); - cx = endX; - cy = endY; - i += 5; - prevCurve = true; - } - break; - - // Q - quadratic curve to (absolute) - // Draws a quadratic Bézier curve from the current point to (x,y) using - // (x1,y1) as the control point. Q (uppercase) indicates that absolute - // coordinates will follow; q (lowercase) indicates that relative - // coordinates will follow. Multiple sets of coordinates may be specified - // to draw a polybézier. At the end of the command, the new current point - // becomes the final (x,y) coordinate pair used in the polybézier. - case 'Q': { - ctrlX = PApplet.parseFloat(pathTokens[i + 1]); - ctrlY = PApplet.parseFloat(pathTokens[i + 2]); - float endX = PApplet.parseFloat(pathTokens[i + 3]); - float endY = PApplet.parseFloat(pathTokens[i + 4]); - //parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); - parsePathQuadto(ctrlX, ctrlY, endX, endY); - cx = endX; - cy = endY; - i += 5; - prevCurve = true; - } - break; - - // q - quadratic curve to (relative) - case 'q': { - ctrlX = cx + PApplet.parseFloat(pathTokens[i + 1]); - ctrlY = cy + PApplet.parseFloat(pathTokens[i + 2]); - float endX = cx + PApplet.parseFloat(pathTokens[i + 3]); - float endY = cy + PApplet.parseFloat(pathTokens[i + 4]); - //parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); - parsePathQuadto(ctrlX, ctrlY, endX, endY); - cx = endX; - cy = endY; - i += 5; - prevCurve = true; - } - break; - - // T - quadratic curveto shorthand (absolute) - // The control point is assumed to be the reflection of the control - // point on the previous command relative to the current point. - case 'T': { - // If there is no previous command or if the previous command was - // not a Q, q, T or t, assume the control point is coincident - // with the current point. - if (!prevCurve) { - ctrlX = cx; - ctrlY = cy; - } else { - float ppx = vertices[vertexCount-2][X]; - float ppy = vertices[vertexCount-2][Y]; - float px = vertices[vertexCount-1][X]; - float py = vertices[vertexCount-1][Y]; - ctrlX = px + (px - ppx); - ctrlY = py + (py - ppy); - } - float endX = PApplet.parseFloat(pathTokens[i + 1]); - float endY = PApplet.parseFloat(pathTokens[i + 2]); - //parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); - parsePathQuadto(ctrlX, ctrlY, endX, endY); - cx = endX; - cy = endY; - i += 3; - prevCurve = true; - } - break; - - // t - quadratic curveto shorthand (relative) - case 't': { - if (!prevCurve) { - ctrlX = cx; - ctrlY = cy; - } else { - float ppx = vertices[vertexCount-2][X]; - float ppy = vertices[vertexCount-2][Y]; - float px = vertices[vertexCount-1][X]; - float py = vertices[vertexCount-1][Y]; - ctrlX = px + (px - ppx); - ctrlY = py + (py - ppy); - } - float endX = cx + PApplet.parseFloat(pathTokens[i + 1]); - float endY = cy + PApplet.parseFloat(pathTokens[i + 2]); - //parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); - parsePathQuadto(ctrlX, ctrlY, endX, endY); - cx = endX; - cy = endY; - i += 3; - prevCurve = true; - } - break; - - // A - elliptical arc to (absolute) - case 'A': { - float rx = PApplet.parseFloat(pathTokens[i + 1]); - float ry = PApplet.parseFloat(pathTokens[i + 2]); - float angle = PApplet.parseFloat(pathTokens[i + 3]); - boolean fa = PApplet.parseFloat(pathTokens[i + 4]) != 0; - boolean fs = PApplet.parseFloat(pathTokens[i + 5]) != 0; - float endX = PApplet.parseFloat(pathTokens[i + 6]); - float endY = PApplet.parseFloat(pathTokens[i + 7]); - parsePathArcto(cx, cy, rx, ry, angle, fa, fs, endX, endY); - cx = endX; - cy = endY; - i += 8; - prevCurve = true; - } - break; - - // a - elliptical arc to (relative) - case 'a': { - float rx = PApplet.parseFloat(pathTokens[i + 1]); - float ry = PApplet.parseFloat(pathTokens[i + 2]); - float angle = PApplet.parseFloat(pathTokens[i + 3]); - boolean fa = PApplet.parseFloat(pathTokens[i + 4]) != 0; - boolean fs = PApplet.parseFloat(pathTokens[i + 5]) != 0; - float endX = cx + PApplet.parseFloat(pathTokens[i + 6]); - float endY = cy + PApplet.parseFloat(pathTokens[i + 7]); - parsePathArcto(cx, cy, rx, ry, angle, fa, fs, endX, endY); - cx = endX; - cy = endY; - i += 8; - prevCurve = true; - } - break; - - case 'Z': - case 'z': - // since closing the path, the 'current' point needs - // to return back to the last moveto location. - // http://code.google.com/p/processing/issues/detail?id=1058 - cx = movetoX; - cy = movetoY; - close = true; - i++; - break; - - default: - String parsed = - PApplet.join(PApplet.subset(pathTokens, 0, i), ","); - String unparsed = - PApplet.join(PApplet.subset(pathTokens, i), ","); - System.err.println("parsed: " + parsed); - System.err.println("unparsed: " + unparsed); - throw new RuntimeException("shape command not handled: " + pathTokens[i]); - } -// prevCommand = c; - } - } - - -// private void parsePathCheck(int num) { -// if (vertexCount + num-1 >= vertices.length) { -// //vertices = (float[][]) PApplet.expand(vertices); -// float[][] temp = new float[vertexCount << 1][2]; -// System.arraycopy(vertices, 0, temp, 0, vertexCount); -// vertices = temp; -// } -// } - - private void parsePathVertex(float x, float y) { - if (vertexCount == vertices.length) { - //vertices = (float[][]) PApplet.expand(vertices); - float[][] temp = new float[vertexCount << 1][2]; - System.arraycopy(vertices, 0, temp, 0, vertexCount); - vertices = temp; - } - vertices[vertexCount][X] = x; - vertices[vertexCount][Y] = y; - vertexCount++; - } - - - private void parsePathCode(int what) { - if (vertexCodeCount == vertexCodes.length) { - vertexCodes = PApplet.expand(vertexCodes); - } - vertexCodes[vertexCodeCount++] = what; - } - - - private void parsePathMoveto(float px, float py) { - if (vertexCount > 0) { - parsePathCode(BREAK); - } - parsePathCode(VERTEX); - parsePathVertex(px, py); - } - - - private void parsePathLineto(float px, float py) { - parsePathCode(VERTEX); - parsePathVertex(px, py); - } - - - private void parsePathCurveto(float x1, float y1, - float x2, float y2, - float x3, float y3) { - parsePathCode(BEZIER_VERTEX); - parsePathVertex(x1, y1); - parsePathVertex(x2, y2); - parsePathVertex(x3, y3); - } - -// private void parsePathQuadto(float x1, float y1, -// float cx, float cy, -// float x2, float y2) { -// //System.out.println("quadto: " + x1 + "," + y1 + " " + cx + "," + cy + " " + x2 + "," + y2); -//// parsePathCode(BEZIER_VERTEX); -// parsePathCode(QUAD_BEZIER_VERTEX); -// // x1/y1 already covered by last moveto, lineto, or curveto -// -// parsePathVertex(x1 + ((cx-x1)*2/3.0f), y1 + ((cy-y1)*2/3.0f)); -// parsePathVertex(x2 + ((cx-x2)*2/3.0f), y2 + ((cy-y2)*2/3.0f)); -// parsePathVertex(x2, y2); -// } - - private void parsePathQuadto(float cx, float cy, - float x2, float y2) { - //System.out.println("quadto: " + x1 + "," + y1 + " " + cx + "," + cy + " " + x2 + "," + y2); -// parsePathCode(BEZIER_VERTEX); - parsePathCode(QUADRATIC_VERTEX); - // x1/y1 already covered by last moveto, lineto, or curveto - parsePathVertex(cx, cy); - parsePathVertex(x2, y2); - } - - - // Approximates elliptical arc by several bezier segments. - // Meets SVG standard requirements from: - // http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands - // http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes - // Based on arc to bezier curve equations from: - // http://www.spaceroots.org/documents/ellipse/node22.html - private void parsePathArcto(float x1, float y1, - float rx, float ry, - float angle, - boolean fa, boolean fs, - float x2, float y2) { - if (x1 == x2 && y1 == y2) return; - if (rx == 0 || ry == 0) { parsePathLineto(x2, y2); return; } - - rx = PApplet.abs(rx); ry = PApplet.abs(ry); - - float phi = PApplet.radians(((angle % 360) + 360) % 360); - float cosPhi = PApplet.cos(phi), sinPhi = PApplet.sin(phi); - - float x1r = ( cosPhi * (x1 - x2) + sinPhi * (y1 - y2)) / 2; - float y1r = (-sinPhi * (x1 - x2) + cosPhi * (y1 - y2)) / 2; - - float cxr, cyr; - { - float A = (x1r*x1r) / (rx*rx) + (y1r*y1r) / (ry*ry); - if (A > 1) { - // No solution, scale ellipse up according to SVG standard - float sqrtA = PApplet.sqrt(A); - rx *= sqrtA; cxr = 0; - ry *= sqrtA; cyr = 0; - } else { - float k = ((fa == fs) ? -1f : 1f) * - PApplet.sqrt((rx*rx * ry*ry) / ((rx*rx * y1r*y1r) + (ry*ry * x1r*x1r)) - 1f); - cxr = k * rx * y1r / ry; - cyr = -k * ry * x1r / rx; - } - } - - float cx = cosPhi * cxr - sinPhi * cyr + (x1 + x2) / 2; - float cy = sinPhi * cxr + cosPhi * cyr + (y1 + y2) / 2; - - float phi1, phiDelta; - { - float sx = ( x1r - cxr) / rx, sy = ( y1r - cyr) / ry; - float tx = (-x1r - cxr) / rx, ty = (-y1r - cyr) / ry; - phi1 = PApplet.atan2(sy, sx); - phiDelta = (((PApplet.atan2(ty, tx) - phi1) % TWO_PI) + TWO_PI) % TWO_PI; - if (!fs) phiDelta -= TWO_PI; - } - - // One segment can not cover more that PI, less than PI/2 is - // recommended to avoid visible inaccuracies caused by rounding errors - int segmentCount = PApplet.ceil(PApplet.abs(phiDelta) / TWO_PI * 4); - - float inc = phiDelta / segmentCount; - float a = PApplet.sin(inc) * - (PApplet.sqrt(4 + 3 * PApplet.sq(PApplet.tan(inc / 2))) - 1) / 3; - - float sinPhi1 = PApplet.sin(phi1), cosPhi1 = PApplet.cos(phi1); - - float p1x = x1; - float p1y = y1; - float relq1x = a * (-rx * cosPhi * sinPhi1 - ry * sinPhi * cosPhi1); - float relq1y = a * (-rx * sinPhi * sinPhi1 + ry * cosPhi * cosPhi1); - - for (int i = 0; i < segmentCount; i++) { - float eta = phi1 + (i + 1) * inc; - float sinEta = PApplet.sin(eta), cosEta = PApplet.cos(eta); - - float p2x = cx + rx * cosPhi * cosEta - ry * sinPhi * sinEta; - float p2y = cy + rx * sinPhi * cosEta + ry * cosPhi * sinEta; - float relq2x = a * (-rx * cosPhi * sinEta - ry * sinPhi * cosEta); - float relq2y = a * (-rx * sinPhi * sinEta + ry * cosPhi * cosEta); - - if (i == segmentCount - 1) { p2x = x2; p2y = y2; } - - parsePathCode(BEZIER_VERTEX); - parsePathVertex(p1x + relq1x, p1y + relq1y); - parsePathVertex(p2x - relq2x, p2y - relq2y); - parsePathVertex(p2x, p2y); - - p1x = p2x; relq1x = relq2x; - p1y = p2y; relq1y = relq2y; - } - } - - - /** - * Parse the specified SVG matrix into a PMatrix2D. Note that PMatrix2D - * is rotated relative to the SVG definition, so parameters are rearranged - * here. More about the transformation matrices in - * this section - * of the SVG documentation. - * @param matrixStr text of the matrix param. - * @return a good old-fashioned PMatrix2D - */ - static protected PMatrix2D parseTransform(String matrixStr) { - matrixStr = matrixStr.trim(); - PMatrix2D outgoing = null; - int start = 0; - int stop = -1; - while ((stop = matrixStr.indexOf(')', start)) != -1) { - PMatrix2D m = parseSingleTransform(matrixStr.substring(start, stop+1)); - if (outgoing == null) { - outgoing = m; - } else { - outgoing.apply(m); - } - start = stop + 1; - } - return outgoing; - } - - - static protected PMatrix2D parseSingleTransform(String matrixStr) { - //String[] pieces = PApplet.match(matrixStr, "^\\s*(\\w+)\\((.*)\\)\\s*$"); - String[] pieces = PApplet.match(matrixStr, "[,\\s]*(\\w+)\\((.*)\\)"); - if (pieces == null) { - System.err.println("Could not parse transform " + matrixStr); - return null; - } - float[] m = PApplet.parseFloat(PApplet.splitTokens(pieces[2], ", ")); - if (pieces[1].equals("matrix")) { - return new PMatrix2D(m[0], m[2], m[4], m[1], m[3], m[5]); - - } else if (pieces[1].equals("translate")) { - float tx = m[0]; - float ty = (m.length == 2) ? m[1] : m[0]; - return new PMatrix2D(1, 0, tx, 0, 1, ty); - - } else if (pieces[1].equals("scale")) { - float sx = m[0]; - float sy = (m.length == 2) ? m[1] : m[0]; - return new PMatrix2D(sx, 0, 0, 0, sy, 0); - - } else if (pieces[1].equals("rotate")) { - float angle = m[0]; - - if (m.length == 1) { - float c = PApplet.cos(angle); - float s = PApplet.sin(angle); - // SVG version is cos(a) sin(a) -sin(a) cos(a) 0 0 - return new PMatrix2D(c, -s, 0, s, c, 0); - - } else if (m.length == 3) { - PMatrix2D mat = new PMatrix2D(0, 1, m[1], 1, 0, m[2]); - mat.rotate(m[0]); - mat.translate(-m[1], -m[2]); - return mat; - } - - } else if (pieces[1].equals("skewX")) { - return new PMatrix2D(1, 0, 1, PApplet.tan(m[0]), 0, 0); - - } else if (pieces[1].equals("skewY")) { - return new PMatrix2D(1, 0, 1, 0, PApplet.tan(m[0]), 0); - } - return null; - } - - - protected void parseColors(XML properties) { - if (properties.hasAttribute("opacity")) { - String opacityText = properties.getString("opacity"); - setOpacity(opacityText); - } - - if (properties.hasAttribute("stroke")) { - String strokeText = properties.getString("stroke"); - setColor(strokeText, false); - } - - if (properties.hasAttribute("stroke-opacity")) { - String strokeOpacityText = properties.getString("stroke-opacity"); - setStrokeOpacity(strokeOpacityText); - } - - if (properties.hasAttribute("stroke-width")) { - // if NaN (i.e. if it's 'inherit') then default back to the inherit setting - String lineweight = properties.getString("stroke-width"); - setStrokeWeight(lineweight); - } - - if (properties.hasAttribute("stroke-linejoin")) { - String linejoin = properties.getString("stroke-linejoin"); - setStrokeJoin(linejoin); - } - - if (properties.hasAttribute("stroke-linecap")) { - String linecap = properties.getString("stroke-linecap"); - setStrokeCap(linecap); - } - - // fill defaults to black (though stroke defaults to "none") - // http://www.w3.org/TR/SVG/painting.html#FillProperties - if (properties.hasAttribute("fill")) { - String fillText = properties.getString("fill"); - setColor(fillText, true); - } - - if (properties.hasAttribute("fill-opacity")) { - String fillOpacityText = properties.getString("fill-opacity"); - setFillOpacity(fillOpacityText); - } - - if (properties.hasAttribute("style")) { - String styleText = properties.getString("style"); - String[] styleTokens = PApplet.splitTokens(styleText, ";"); - - //PApplet.println(styleTokens); - for (int i = 0; i < styleTokens.length; i++) { - String[] tokens = PApplet.splitTokens(styleTokens[i], ":"); - //PApplet.println(tokens); - - tokens[0] = PApplet.trim(tokens[0]); - - if (tokens[0].equals("fill")) { - setColor(tokens[1], true); - - } else if(tokens[0].equals("fill-opacity")) { - setFillOpacity(tokens[1]); - - } else if(tokens[0].equals("stroke")) { - setColor(tokens[1], false); - - } else if(tokens[0].equals("stroke-width")) { - setStrokeWeight(tokens[1]); - - } else if(tokens[0].equals("stroke-linecap")) { - setStrokeCap(tokens[1]); - - } else if(tokens[0].equals("stroke-linejoin")) { - setStrokeJoin(tokens[1]); - - } else if(tokens[0].equals("stroke-opacity")) { - setStrokeOpacity(tokens[1]); - - } else if(tokens[0].equals("opacity")) { - setOpacity(tokens[1]); - - } else { - // Other attributes are not yet implemented - } - } - } - } - - - void setOpacity(String opacityText) { - opacity = PApplet.parseFloat(opacityText); - strokeColor = ((int) (opacity * 255)) << 24 | strokeColor & 0xFFFFFF; - fillColor = ((int) (opacity * 255)) << 24 | fillColor & 0xFFFFFF; - } - - - void setStrokeWeight(String lineweight) { - strokeWeight = parseUnitSize(lineweight, svgSizeXY); - } - - - void setStrokeOpacity(String opacityText) { - strokeOpacity = PApplet.parseFloat(opacityText); - strokeColor = ((int) (strokeOpacity * 255)) << 24 | strokeColor & 0xFFFFFF; - } - - - void setStrokeJoin(String linejoin) { - if (linejoin.equals("inherit")) { - // do nothing, will inherit automatically - - } else if (linejoin.equals("miter")) { - strokeJoin = PConstants.MITER; - - } else if (linejoin.equals("round")) { - strokeJoin = PConstants.ROUND; - - } else if (linejoin.equals("bevel")) { - strokeJoin = PConstants.BEVEL; - } - } - - - void setStrokeCap(String linecap) { - if (linecap.equals("inherit")) { - // do nothing, will inherit automatically - - } else if (linecap.equals("butt")) { - strokeCap = PConstants.SQUARE; - - } else if (linecap.equals("round")) { - strokeCap = PConstants.ROUND; - - } else if (linecap.equals("square")) { - strokeCap = PConstants.PROJECT; - } - } - - - void setFillOpacity(String opacityText) { - fillOpacity = PApplet.parseFloat(opacityText); - fillColor = ((int) (fillOpacity * 255)) << 24 | fillColor & 0xFFFFFF; - } - - - void setColor(String colorText, boolean isFill) { - colorText = colorText.trim(); - int opacityMask = fillColor & 0xFF000000; - boolean visible = true; - int color = 0; - String name = ""; -// String lColorText = colorText.toLowerCase(); - Gradient gradient = null; -// Object paint = null; - if (colorText.equals("none")) { - visible = false; - } else if (colorText.startsWith("url(#")) { - name = colorText.substring(5, colorText.length() - 1); - Object object = findChild(name); - if (object instanceof Gradient) { - gradient = (Gradient) object; - // in 3.0a11, do this on first draw inside PShapeJava2D -// paint = calcGradientPaint(gradient); //, opacity); - } else { -// visible = false; - System.err.println("url " + name + " refers to unexpected data: " + object); - } - } else { - // Prints errors itself. - color = opacityMask | parseSimpleColor(colorText); - } - if (isFill) { - fill = visible; - fillColor = color; - fillName = name; - fillGradient = gradient; -// fillGradientPaint = paint; - } else { - stroke = visible; - strokeColor = color; - strokeName = name; - strokeGradient = gradient; -// strokeGradientPaint = paint; - } - } - - - /** - * Parses the "color" datatype only, and prints an error if it is not of this form. - * http://www.w3.org/TR/SVG/types.html#DataTypeColor - * @return 0xRRGGBB (no alpha). Zero on error. - */ - static protected int parseSimpleColor(String colorText) { - colorText = colorText.toLowerCase().trim(); - //if (colorNames.containsKey(colorText)) { - if (colorNames.hasKey(colorText)) { - return colorNames.get(colorText); - } else if (colorText.startsWith("#")) { - if (colorText.length() == 4) { - // Short form: #ABC, transform to long form #AABBCC - colorText = colorText.replaceAll("^#(.)(.)(.)$", "#$1$1$2$2$3$3"); - } - return (Integer.parseInt(colorText.substring(1), 16)) & 0xFFFFFF; - //System.out.println("hex for fill is " + PApplet.hex(fillColor)); - } else if (colorText.startsWith("rgb")) { - return parseRGB(colorText); - } else { - System.err.println("Cannot parse \"" + colorText + "\"."); - return 0; - } - } - - - /** - * Deliberately conforms to the HTML 4.01 color spec + en-gb grey, rather - * than the (unlikely to be useful) entire 147-color system used in SVG. - */ - static protected IntDict colorNames = new IntDict(new Object[][] { - { "aqua", 0x00ffff }, - { "black", 0x000000 }, - { "blue", 0x0000ff }, - { "fuchsia", 0xff00ff }, - { "gray", 0x808080 }, - { "grey", 0x808080 }, - { "green", 0x008000 }, - { "lime", 0x00ff00 }, - { "maroon", 0x800000 }, - { "navy", 0x000080 }, - { "olive", 0x808000 }, - { "purple", 0x800080 }, - { "red", 0xff0000 }, - { "silver", 0xc0c0c0 }, - { "teal", 0x008080 }, - { "white", 0xffffff }, - { "yellow", 0xffff00 } - }); - - /* - static protected Map colorNames; - static { - colorNames = new HashMap(); - colorNames.put("aqua", 0x00ffff); - colorNames.put("black", 0x000000); - colorNames.put("blue", 0x0000ff); - colorNames.put("fuchsia", 0xff00ff); - colorNames.put("gray", 0x808080); - colorNames.put("grey", 0x808080); - colorNames.put("green", 0x008000); - colorNames.put("lime", 0x00ff00); - colorNames.put("maroon", 0x800000); - colorNames.put("navy", 0x000080); - colorNames.put("olive", 0x808000); - colorNames.put("purple", 0x800080); - colorNames.put("red", 0xff0000); - colorNames.put("silver", 0xc0c0c0); - colorNames.put("teal", 0x008080); - colorNames.put("white", 0xffffff); - colorNames.put("yellow", 0xffff00); - } - */ - - static protected int parseRGB(String what) { - int leftParen = what.indexOf('(') + 1; - int rightParen = what.indexOf(')'); - String sub = what.substring(leftParen, rightParen); - String[] values = PApplet.splitTokens(sub, ", "); - int rgbValue = 0; - if (values.length == 3) { - // Color spec allows for rgb values to be percentages. - for (int i = 0; i < 3; i++) { - rgbValue <<= 8; - if (values[i].endsWith("%")) { - rgbValue |= (int)(PApplet.constrain(255*parseFloatOrPercent(values[i]), 0, 255)); - } else { - rgbValue |= PApplet.constrain(PApplet.parseInt(values[i]), 0, 255); - } - } - } else System.err.println("Could not read color \"" + what + "\"."); - - return rgbValue; - } - - - //static protected Map parseStyleAttributes(String style) { - static protected StringDict parseStyleAttributes(String style) { - //Map table = new HashMap(); - StringDict table = new StringDict(); -// if (style == null) return table; - if (style != null) { - String[] pieces = style.split(";"); - for (int i = 0; i < pieces.length; i++) { - String[] parts = pieces[i].split(":"); - //table.put(parts[0], parts[1]); - table.set(parts[0], parts[1]); - } - } - return table; - } - - - /** - * Used in place of element.getFloatAttribute(a) because we can - * have a unit suffix (length or coordinate). - * @param element what to parse - * @param attribute name of the attribute to get - * @param relativeTo (float) Used for %. When relative to viewbox, should - * be svgWidth for horizontal dimentions, svgHeight for vertical, and - * svgXYSize for anything else. - * @return unit-parsed version of the data - */ - static protected float getFloatWithUnit(XML element, String attribute, float relativeTo) { - String val = element.getString(attribute); - return (val == null) ? 0 : parseUnitSize(val, relativeTo); - } - - - /** - * Parse a size that may have a suffix for its units. - * This assumes 90dpi, which implies, as given in the - * units spec: - *
      - *
    • "1pt" equals "1.25px" (and therefore 1.25 user units) - *
    • "1pc" equals "15px" (and therefore 15 user units) - *
    • "1mm" would be "3.543307px" (3.543307 user units) - *
    • "1cm" equals "35.43307px" (and therefore 35.43307 user units) - *
    • "1in" equals "90px" (and therefore 90 user units) - *
    - * @param relativeTo (float) Used for %. When relative to viewbox, should - * be svgWidth for horizontal dimentions, svgHeight for vertical, and - * svgXYSize for anything else. - */ - static protected float parseUnitSize(String text, float relativeTo) { - int len = text.length() - 2; - - if (text.endsWith("pt")) { - return PApplet.parseFloat(text.substring(0, len)) * 1.25f; - } else if (text.endsWith("pc")) { - return PApplet.parseFloat(text.substring(0, len)) * 15; - } else if (text.endsWith("mm")) { - return PApplet.parseFloat(text.substring(0, len)) * 3.543307f; - } else if (text.endsWith("cm")) { - return PApplet.parseFloat(text.substring(0, len)) * 35.43307f; - } else if (text.endsWith("in")) { - return PApplet.parseFloat(text.substring(0, len)) * 90; - } else if (text.endsWith("px")) { - return PApplet.parseFloat(text.substring(0, len)); - } else if (text.endsWith("%")) { - return relativeTo * parseFloatOrPercent(text); - } else { - return PApplet.parseFloat(text); - } - } - - - static protected float parseFloatOrPercent(String text) { - text = text.trim(); - if (text.endsWith("%")) { - return Float.parseFloat(text.substring(0, text.length() - 1)) / 100.0f; - } else { - return Float.parseFloat(text); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - static public class Gradient extends PShapeSVG { - Matrix transform; - - public float[] offset; - public int[] color; - public int count; - - public Gradient(PShapeSVG parent, XML properties) { - super(parent, properties, true); - - XML elements[] = properties.getChildren(); - offset = new float[elements.length]; - color = new int[elements.length]; - - // - for (int i = 0; i < elements.length; i++) { - XML elem = elements[i]; - String name = elem.getName(); - if (name.equals("stop")) { - String offsetAttr = elem.getString("offset"); - offset[count] = parseFloatOrPercent(offsetAttr); - - String style = elem.getString("style"); - //Map styles = parseStyleAttributes(style); - StringDict styles = parseStyleAttributes(style); - - String colorStr = styles.get("stop-color"); - if (colorStr == null) { - colorStr = elem.getString("stop-color"); - if (colorStr == null) colorStr = "#000000"; - } - String opacityStr = styles.get("stop-opacity"); - if (opacityStr == null) { - opacityStr = elem.getString("stop-opacity"); - if (opacityStr == null) opacityStr = "1"; - } - int tupacity = PApplet.constrain( - (int)(PApplet.parseFloat(opacityStr) * 255), 0, 255); - color[count] = (tupacity << 24) | parseSimpleColor(colorStr); - count++; - } - } - offset = PApplet.subset(offset, 0, count); - color = PApplet.subset(color, 0, count); - } - } - - - public class LinearGradient extends Gradient { - public float x1, y1, x2, y2; - - public LinearGradient(PShapeSVG parent, XML properties) { - super(parent, properties); - - this.x1 = getFloatWithUnit(properties, "x1", svgWidth); - this.y1 = getFloatWithUnit(properties, "y1", svgHeight); - this.x2 = getFloatWithUnit(properties, "x2", svgWidth); - this.y2 = getFloatWithUnit(properties, "y2", svgHeight); - - String transformStr = - properties.getString("gradientTransform"); - - if (transformStr != null) { - float t[] = parseTransform(transformStr).get(null); - //this.transform = new AffineTransform(t[0], t[3], t[1], t[4], t[2], t[5]); - transform = new Matrix(); - transform.setValues(new float[] { // TODO don't create temp floats - t[0], t[1], t[2], - t[3], t[4], t[5], - 0, 0, 1 - }); - -// Point2D t1 = transform.transform(new Point2D.Float(x1, y1), null); -// Point2D t2 = transform.transform(new Point2D.Float(x2, y2), null); - float[] t1 = new float[] { x1, y1 }; - float[] t2 = new float[] { x2, y2 }; - transform.mapPoints(t1); - transform.mapPoints(t2); - -// this.x1 = (float) t1.getX(); -// this.y1 = (float) t1.getY(); -// this.x2 = (float) t2.getX(); -// this.y2 = (float) t2.getY(); - x1 = t1[0]; - y1 = t1[1]; - x2 = t2[0]; - y2 = t2[1]; - } - } - } - - - public class RadialGradient extends Gradient { - public float cx, cy, r; - - public RadialGradient(PShapeSVG parent, XML properties) { - super(parent, properties); - - this.cx = getFloatWithUnit(properties, "cx", svgWidth); - this.cy = getFloatWithUnit(properties, "cy", svgHeight); - this.r = getFloatWithUnit(properties, "r", svgSizeXY); - - String transformStr = - properties.getString("gradientTransform"); - - if (transformStr != null) { - float t[] = parseTransform(transformStr).get(null); -// this.transform = new AffineTransform(t[0], t[3], t[1], t[4], t[2], t[5]); - transform = new Matrix(); - transform.setValues(new float[] { // TODO don't create temp floats - t[0], t[1], t[2], - t[3], t[4], t[5], - 0, 0, 1 - }); - -// Point2D t1 = transform.transform(new Point2D.Float(cx, cy), null); -// Point2D t2 = transform.transform(new Point2D.Float(cx + r, cy), null); - float[] t1 = new float[] { cx, cy }; - float[] t2 = new float[] { cx + r, cy }; - transform.mapPoints(t1); - transform.mapPoints(t2); - -// this.cx = (float) t1.getX(); -// this.cy = (float) t1.getY(); -// this.r = (float) (t2.getX() - t1.getX()); - cx = t1[0]; - cy = t1[1]; - r = t2[0] - t1[0]; - } - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - -// static private float TEXT_QUALITY = 1; - public static final int PLAIN = 0; - public static final int BOLD = 1; - public static final int ITALIC = 2; - - static private PFont parseFont(XML properties) { - String fontFamily = null; - float size = 10; - int weight = PLAIN; // 0 - int italic = 0; - - if (properties.hasAttribute("style")) { - String styleText = properties.getString("style"); - String[] styleTokens = PApplet.splitTokens(styleText, ";"); - - //PApplet.println(styleTokens); - for (int i = 0; i < styleTokens.length; i++) { - String[] tokens = PApplet.splitTokens(styleTokens[i], ":"); - //PApplet.println(tokens); - - tokens[0] = PApplet.trim(tokens[0]); - - if (tokens[0].equals("font-style")) { - // PApplet.println("font-style: " + tokens[1]); - if (tokens[1].contains("italic")) { - italic = ITALIC; - } - } else if (tokens[0].equals("font-variant")) { - // PApplet.println("font-variant: " + tokens[1]); - // setFillOpacity(tokens[1]); - - } else if (tokens[0].equals("font-weight")) { - // PApplet.println("font-weight: " + tokens[1]); - - if (tokens[1].contains("bold")) { - weight = BOLD; - // PApplet.println("Bold weight ! "); - } - - - } else if (tokens[0].equals("font-stretch")) { - // not supported. - - } else if (tokens[0].equals("font-size")) { - // PApplet.println("font-size: " + tokens[1]); - size = Float.parseFloat(tokens[1].split("px")[0]); - // PApplet.println("font-size-parsed: " + size); - } else if (tokens[0].equals("line-height")) { - // not supported - - } else if (tokens[0].equals("font-family")) { - // PApplet.println("Font-family: " + tokens[1]); - fontFamily = tokens[1]; - - } else if (tokens[0].equals("text-align")) { - // not supported - - } else if (tokens[0].equals("letter-spacing")) { - // not supported - - } else if (tokens[0].equals("word-spacing")) { - // not supported - - } else if (tokens[0].equals("writing-mode")) { - // not supported - - } else if (tokens[0].equals("text-anchor")) { - // not supported - - } else { - // Other attributes are not yet implemented - } - } - } - if (fontFamily == null) { - return null; - } -// size = size * TEXT_QUALITY; - - return createFont(fontFamily, weight | italic, size, true); - } - - - static protected PFont createFont(String name, int weight, - float size, boolean smooth) { - //System.out.println("Try to create a font of " + name + " family, " + weight); -// java.awt.Font baseFont = new java.awt.Font(name, weight, (int) size); - - //System.out.println("Resulting family : " + baseFont.getFamily() + " " + baseFont.getStyle()); -// return new PFont(baseFont.deriveFont(size), smooth, null); - return null; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - static public class Text extends PShapeSVG { - protected PFont font; - - public Text(PShapeSVG parent, XML properties) { - super(parent, properties, true); - - // get location - float x = Float.parseFloat(properties.getString("x")); - float y = Float.parseFloat(properties.getString("y")); - - if (matrix == null) { - matrix = new PMatrix2D(); - } - matrix.translate(x, y); - - family = GROUP; - - font = parseFont(properties); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - static public class LineOfText extends PShapeSVG { - String textToDisplay; - PFont font; - - public LineOfText(PShapeSVG parent, XML properties) { - // TODO: child should ideally be parsed too for inline content. - super(parent, properties, false); - - //get location - float x = Float.parseFloat(properties.getString("x")); - float y = Float.parseFloat(properties.getString("y")); - - float parentX = Float.parseFloat(parent.element.getString("x")); - float parentY = Float.parseFloat(parent.element.getString("y")); - - if (matrix == null) matrix = new PMatrix2D(); - matrix.translate(x - parentX, (y - parentY) / 2f); - - // get the first properties - parseColors(properties); - font = parseFont(properties); - - // cleaned up syntax but removing b/c unused [fry 190118] - //boolean isLine = properties.getString("role").equals("line"); - - if (this.childCount > 0) { - // no inline content yet. - } - - String text = properties.getContent(); - textToDisplay = text; - } - - @Override - public void drawImpl(PGraphics g) { - if (font == null) { - font = ((Text) parent).font; - if (font == null) { - return; - } - } - - pre(g); -// g.textFont(font, font.size / TEXT_QUALITY); - g.textFont(font, font.size); - g.text(textToDisplay, 0, 0); - post(g); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - static public class Font extends PShapeSVG { - public FontFace face; - - public Map namedGlyphs; - public Map unicodeGlyphs; - - public int glyphCount; - public FontGlyph[] glyphs; - public FontGlyph missingGlyph; - - int horizAdvX; - - - public Font(PShapeSVG parent, XML properties) { - super(parent, properties, false); -// handle(parent, properties); - - XML[] elements = properties.getChildren(); - - horizAdvX = properties.getInt("horiz-adv-x", 0); - - namedGlyphs = new HashMap<>(); - unicodeGlyphs = new HashMap<>(); - glyphCount = 0; - glyphs = new FontGlyph[elements.length]; - - for (int i = 0; i < elements.length; i++) { - String name = elements[i].getName(); - XML elem = elements[i]; - if (name == null) { - // skip it - } else if (name.equals("glyph")) { - FontGlyph fg = new FontGlyph(this, elem, this); - if (fg.isLegit()) { - if (fg.name != null) { - namedGlyphs.put(fg.name, fg); - } - if (fg.unicode != 0) { - unicodeGlyphs.put(Character.valueOf(fg.unicode), fg); - } - } - glyphs[glyphCount++] = fg; - - } else if (name.equals("missing-glyph")) { -// System.out.println("got missing glyph inside "); - missingGlyph = new FontGlyph(this, elem, this); - } else if (name.equals("font-face")) { - face = new FontFace(this, elem); - } else { - System.err.println("Ignoring " + name + " inside "); - } - } - } - - - protected void drawShape() { - // does nothing for fonts - } - - - public void drawString(PGraphics g, String str, float x, float y, float size) { - // 1) scale by the 1.0/unitsPerEm - // 2) scale up by a font size - g.pushMatrix(); - float s = size / face.unitsPerEm; - //System.out.println("scale is " + s); - // swap y coord at the same time, since fonts have y=0 at baseline - g.translate(x, y); - g.scale(s, -s); - char[] c = str.toCharArray(); - for (int i = 0; i < c.length; i++) { - // call draw on each char (pulling it w/ the unicode table) - FontGlyph fg = unicodeGlyphs.get(Character.valueOf(c[i])); - if (fg != null) { - fg.draw(g); - // add horizAdvX/unitsPerEm to the x coordinate along the way - g.translate(fg.horizAdvX, 0); - } else { - System.err.println("'" + c[i] + "' not available."); - } - } - g.popMatrix(); - } - - - public void drawChar(PGraphics g, char c, float x, float y, float size) { - g.pushMatrix(); - float s = size / face.unitsPerEm; - g.translate(x, y); - g.scale(s, -s); - FontGlyph fg = unicodeGlyphs.get(Character.valueOf(c)); - if (fg != null) g.shape(fg); - g.popMatrix(); - } - - - public float textWidth(String str, float size) { - float w = 0; - char[] c = str.toCharArray(); - for (int i = 0; i < c.length; i++) { - // call draw on each char (pulling it w/ the unicode table) - FontGlyph fg = unicodeGlyphs.get(Character.valueOf(c[i])); - if (fg != null) { - w += (float) fg.horizAdvX / face.unitsPerEm; - } - } - return w * size; - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - static class FontFace extends PShapeSVG { - int horizOriginX; // dflt 0 - int horizOriginY; // dflt 0 - // int horizAdvX; // no dflt? - int vertOriginX; // dflt horizAdvX/2 - int vertOriginY; // dflt ascent - int vertAdvY; // dflt 1em (unitsPerEm value) - - String fontFamily; - int fontWeight; // can also be normal or bold (also comma separated) - String fontStretch; - int unitsPerEm; // dflt 1000 - int[] panose1; // dflt "0 0 0 0 0 0 0 0 0 0" - int ascent; - int descent; - int[] bbox; // spec says comma separated, tho not w/ forge - int underlineThickness; - int underlinePosition; - //String unicodeRange; // gonna ignore for now - - - public FontFace(PShapeSVG parent, XML properties) { - super(parent, properties, true); - - unitsPerEm = properties.getInt("units-per-em", 1000); - } - - - protected void drawShape() { - // nothing to draw in the font face attribute - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - static public class FontGlyph extends PShapeSVG { // extends Path - public String name; - char unicode; - int horizAdvX; - - public FontGlyph(PShapeSVG parent, XML properties, Font font) { - super(parent, properties, true); - super.parsePath(); // ?? - - name = properties.getString("glyph-name"); - String u = properties.getString("unicode"); - unicode = 0; - if (u != null) { - if (u.length() == 1) { - unicode = u.charAt(0); - //System.out.println("unicode for " + name + " is " + u); - } else { - System.err.println("unicode for " + name + - " is more than one char: " + u); - } - } - if (properties.hasAttribute("horiz-adv-x")) { - horizAdvX = properties.getInt("horiz-adv-x"); - } else { - horizAdvX = font.horizAdvX; - } - } - - - protected boolean isLegit() { // TODO need a better way to handle this... - return vertexCount != 0; - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Get a particular element based on its SVG ID. When editing SVG by hand, - * this is the id="" tag on any SVG element. When editing from Illustrator, - * these IDs can be edited by expanding the layers palette. The names used - * in the layers palette, both for the layers or the shapes and groups - * beneath them can be used here. - *
    -   * // This code grabs "Layer 3" and the shapes beneath it.
    -   * PShape layer3 = svg.getChild("Layer 3");
    -   * 
    - */ - @Override - public PShape getChild(String name) { - PShape found = super.getChild(name); - if (found == null) { - // Otherwise try with underscores instead of spaces - // (this is how Illustrator handles spaces in the layer names). - found = super.getChild(name.replace(' ', '_')); - } - // Set bounding box based on the parent bounding box - if (found != null) { -// found.x = this.x; -// found.y = this.y; - found.width = this.width; - found.height = this.height; - } - return found; - } - - - /** - * Prints out the SVG document. Useful for parsing. - */ - public void print() { - PApplet.println(element.toString()); - } -} diff --git a/core/src/processing/core/PStyle.java b/core/src/processing/core/PStyle.java deleted file mode 100644 index f5e1ecffb..000000000 --- a/core/src/processing/core/PStyle.java +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2006-12 Ben Fry and Casey Reas - Copyright (c) 2004-06 Michael Chang - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - - -public class PStyle implements PConstants { - public int imageMode; - public int rectMode; - public int ellipseMode; - public int shapeMode; - - public int blendMode; - - public int colorMode; - public float colorModeX; - public float colorModeY; - public float colorModeZ; - public float colorModeA; - - public boolean tint; - public int tintColor; - public boolean fill; - public int fillColor; - public boolean stroke; - public int strokeColor; - public float strokeWeight; - public int strokeCap; - public int strokeJoin; - - // TODO these fellas are inconsistent, and may need to go elsewhere - public float ambientR, ambientG, ambientB; - public float specularR, specularG, specularB; - public float emissiveR, emissiveG, emissiveB; - public float shininess; - - public PFont textFont; - public int textAlign; - public int textAlignY; - public int textMode; - public float textSize; - public float textLeading; -} diff --git a/core/src/processing/core/PSurface.java b/core/src/processing/core/PSurface.java deleted file mode 100644 index 4a2ec763b..000000000 --- a/core/src/processing/core/PSurface.java +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.res.AssetManager; -import android.graphics.Rect; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.View; -import android.view.ViewGroup; - -import java.io.File; -import java.io.InputStream; - -import processing.android.AppComponent; -import processing.android.ServiceEngine; - -/* - * Holds the surface view associated with the sketch, and the rendering thread - * handling - */ -public interface PSurface { - public static final int REQUEST_PERMISSIONS = 1; - - public AppComponent getComponent(); - public Context getContext(); - public Activity getActivity(); - public ServiceEngine getEngine(); - - public void dispose(); - - public String getName(); - - public View getResource(int id); - - public Rect getVisibleFrame(); - - public SurfaceView getSurfaceView(); - public SurfaceHolder getSurfaceHolder(); - - public View getRootView(); - public void setRootView(View view); - - public void initView(int sketchWidth, int sketchHeight); - public void initView(int sketchWidth, int sketchHeight, boolean parentSize, - LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState); - - public void startActivity(Intent intent); - - public void runOnUiThread(Runnable action); - - public void setOrientation(int which); - - public void setHasOptionsMenu(boolean hasMenu); - - public File getFilesDir(); - - public File getFileStreamPath(String path); - - public InputStream openFileInput(String filename); - - public AssetManager getAssets(); - - public void setSystemUiVisibility(int visibility); - - public void startThread(); - - public void pauseThread(); - - public void resumeThread(); - - public boolean stopThread(); - - public boolean isStopped(); - - public void finish(); - - public void setFrameRate(float fps); - - public boolean hasPermission(String permission); - public void requestPermissions(String[] permissions); -} diff --git a/core/src/processing/core/PSurfaceNone.java b/core/src/processing/core/PSurfaceNone.java deleted file mode 100644 index d6b3ebc70..000000000 --- a/core/src/processing/core/PSurfaceNone.java +++ /dev/null @@ -1,594 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.res.AssetManager; -import android.graphics.Rect; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.view.LayoutInflater; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; -import android.support.v4.os.ResultReceiver; - -import android.service.wallpaper.WallpaperService; -import android.support.wearable.watchface.WatchFaceService; - -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.InputStream; - -import processing.android.AppComponent; -import processing.android.PFragment; -import processing.android.ServiceEngine; -import processing.android.PermissionRequestor; - -/** - * Base surface for Android2D and OpenGL renderers. - * It includes the implementation of the rendering thread. - */ -public class PSurfaceNone implements PSurface, PConstants { - protected PApplet sketch; - protected PGraphics graphics; - protected AppComponent component; - protected Activity activity; - - protected boolean surfaceReady; - protected SurfaceView surfaceView; - protected View view; - - protected WallpaperService wallpaper; - protected WatchFaceService watchface; - - protected boolean requestedThreadStart = false; - protected Thread thread; - protected boolean paused; - protected Object pauseObject = new Object(); - - protected float frameRateTarget = 60; - protected long frameRatePeriod = 1000000000L / 60L; - - - @Override - public AppComponent getComponent() { - return component; - } - - - @Override - public Context getContext() { - if (component.getKind() == AppComponent.FRAGMENT) { - return activity; - } else if (component.getKind() == AppComponent.WALLPAPER) { - return wallpaper; - } else if (component.getKind() == AppComponent.WATCHFACE) { - return watchface; - } - return null; - } - - - @Override - public Activity getActivity() { - return activity; - } - - - @Override - public ServiceEngine getEngine() { - return component.getEngine(); - } - - - @Override - public View getRootView() { - return view; - } - - - @Override - public String getName() { - if (component.getKind() == AppComponent.FRAGMENT) { - return activity.getComponentName().getPackageName(); - } else if (component.getKind() == AppComponent.WALLPAPER) { - return wallpaper.getPackageName(); - } else if (component.getKind() == AppComponent.WATCHFACE) { - return watchface.getPackageName(); - } - return ""; - } - - - @Override - public View getResource(int id) { - return activity.findViewById(id); - } - - - @Override - public Rect getVisibleFrame() { - Rect frame = new Rect(); - if (view != null) { - // According to the docs: - // https://developer.android.com/reference/android/view/View.html#getWindowVisibleDisplayFrame(android.graphics.Rect) - // don't use in performance critical code like drawing. - view.getWindowVisibleDisplayFrame(frame); - } - return frame; - } - - - @Override - public void dispose() { - sketch = null; - graphics = null; - - if (activity != null) { - // In API level 21 you can do - // activity.releaseInstance(); - // to ask the app to free up its memory. - // https://developer.android.com/reference/android/app/Activity.html#releaseInstance() - // but seems redundant to call it here, since dispose() is triggered by - // the onDestroy() handler, which means that the app is already - // being destroyed. - } - - if (view != null) { - view.destroyDrawingCache(); - } - - if (component != null) { - component.dispose(); - } - - if (surfaceView != null) { - surfaceView.getHolder().getSurface().release(); - } - } - - - @Override - public void setRootView(View view) { - this.view = view; - } - - - @Override - public SurfaceView getSurfaceView() { - return surfaceView; - } - - - @Override - // TODO this is only used by A2D, when finishing up a draw. but if the - // surfaceview has changed, then it might belong to an a3d surfaceview. hrm. - public SurfaceHolder getSurfaceHolder() { - SurfaceView view = getSurfaceView(); - if (view == null) { - // Watch faces don't have a surface view associated to them. - return null; - } else { - return view.getHolder(); - } - } - - - @Override - public void initView(int sketchWidth, int sketchHeight) { - if (component.getKind() == AppComponent.FRAGMENT) { - int displayWidth = component.getDisplayWidth(); - int displayHeight = component.getDisplayHeight(); - View rootView; - if (sketchWidth == displayWidth && sketchHeight == displayHeight) { - rootView = getSurfaceView(); - } else { - RelativeLayout overallLayout = new RelativeLayout(activity); - RelativeLayout.LayoutParams lp = - new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - lp.addRule(RelativeLayout.CENTER_IN_PARENT); - - LinearLayout layout = new LinearLayout(activity); - layout.addView(getSurfaceView(), sketchWidth, sketchHeight); - overallLayout.addView(layout, lp); - overallLayout.setBackgroundColor(sketch.sketchWindowColor()); - rootView = overallLayout; - } - setRootView(rootView); - } else if (component.getKind() == AppComponent.WALLPAPER) { - setRootView(getSurfaceView()); - } - } - - - @Override - public void initView(int sketchWidth, int sketchHeight, boolean parentSize, - LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/ - ViewGroup rootView = (ViewGroup)inflater.inflate(sketch.parentLayout, container, false); - - View view = getSurfaceView(); - if (parentSize) { - LinearLayout.LayoutParams lp; - lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.MATCH_PARENT); - lp.weight = 1.0f; - lp.setMargins(0, 0, 0, 0); - view.setPadding(0,0,0,0); - rootView.addView(view, lp); - } else { - RelativeLayout layout = new RelativeLayout(activity); - RelativeLayout.LayoutParams lp = - new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - lp.addRule(RelativeLayout.CENTER_IN_PARENT); - - layout.addView(view, sketchWidth, sketchHeight); - rootView.addView(layout, lp); - } - rootView.setBackgroundColor(sketch.sketchWindowColor()); - setRootView(rootView); - } - - - @Override - public void startActivity(Intent intent) { - component.startActivity(intent); - } - - - @Override - public void runOnUiThread(Runnable action) { - if (component.getKind() == AppComponent.FRAGMENT) { - activity.runOnUiThread(action); - } - } - - - @Override - public void setOrientation(int which) { - if (component.getKind() == AppComponent.FRAGMENT) { - if (which == PORTRAIT) { - activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - } else if (which == LANDSCAPE) { - activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); - } - } - } - - - public void setHasOptionsMenu(boolean hasMenu) { - if (component.getKind() == AppComponent.FRAGMENT) { - ((PFragment)component).setHasOptionsMenu(hasMenu); - } - } - - - - @Override - public File getFilesDir() { - if (component.getKind() == AppComponent.FRAGMENT) { - return activity.getFilesDir(); - } else if (component.getKind() == AppComponent.WALLPAPER) { - return wallpaper.getFilesDir(); - } else if (component.getKind() == AppComponent.WATCHFACE) { - return watchface.getFilesDir(); - } - return null; - } - - - @Override - public File getFileStreamPath(String path) { - if (component.getKind() == AppComponent.FRAGMENT) { - return activity.getFileStreamPath(path); - } else if (component.getKind() == AppComponent.WALLPAPER) { - return wallpaper.getFileStreamPath(path); - } else if (component.getKind() == AppComponent.WATCHFACE) { - return watchface.getFileStreamPath(path); - } - return null; - } - - - @Override - public InputStream openFileInput(String filename) { - if (component.getKind() == AppComponent.FRAGMENT) { - try { - return activity.openFileInput(filename); - } catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return null; - } - - - @Override - public AssetManager getAssets() { - if (component.getKind() == AppComponent.FRAGMENT) { - return activity.getAssets(); - } else if (component.getKind() == AppComponent.WALLPAPER) { - return wallpaper.getBaseContext().getAssets(); - } else if (component.getKind() == AppComponent.WATCHFACE) { - return watchface.getBaseContext().getAssets(); - } - return null; - } - - - @Override - public void setSystemUiVisibility(int visibility) { - int kind = component.getKind(); - if (kind == AppComponent.FRAGMENT || kind == AppComponent.WALLPAPER) { - surfaceView.setSystemUiVisibility(visibility); - } - } - - - @Override - public void finish() { - if (component == null) return; - - if (component.getKind() == AppComponent.FRAGMENT) { - // This is the correct way to stop the sketch programmatically, according to the developer's docs: - // https://developer.android.com/reference/android/app/Activity.html#onDestroy() - // https://developer.android.com/reference/android/app/Activity.html#finish() - // and online discussions: - // http://stackoverflow.com/questions/2033914/quitting-an-application-is-that-frowned-upon/2034238 - // finish() it will trigger an onDestroy() event, which will translate down through the - // activity hierarchy and eventually pausing and stopping Processing's animation thread, etc. - activity.finish(); - } else if (component.getKind() == AppComponent.WALLPAPER) { - // stopSelf() stops a service from within: - // https://developer.android.com/reference/android/app/Service.html#stopSelf() - wallpaper.stopSelf(); - } else if (component.getKind() == AppComponent.WATCHFACE) { - watchface.stopSelf(); - } - } - - /////////////////////////////////////////////////////////// - - // Thread handling - - - public Thread createThread() { - return new AnimationThread(); - } - - - @Override - public void startThread() { - if (!surfaceReady) { - requestedThreadStart = true; - return; - } - - if (thread == null) { - thread = createThread(); - thread.start(); - requestedThreadStart = false; - } else { - throw new IllegalStateException("Thread already started in " + - getClass().getSimpleName()); - } - } - - - @Override - public void pauseThread() { - if (!surfaceReady) return; - - paused = true; - } - - - @Override - public void resumeThread() { - if (!surfaceReady) return; - - if (thread == null) { - thread = createThread(); - thread.start(); - } - - paused = false; - synchronized (pauseObject) { - pauseObject.notifyAll(); // wake up the animation thread - } - } - - - @Override - public boolean stopThread() { - if (!surfaceReady) return true; - - if (thread == null) { - return false; - } - - thread.interrupt(); - thread = null; - - return true; - } - - - @Override - public boolean isStopped() { - return thread == null; - } - - - public void setFrameRate(float fps) { - frameRateTarget = fps; - frameRatePeriod = (long) (1000000000.0 / frameRateTarget); - } - - - protected void checkPause() throws InterruptedException { - synchronized (pauseObject) { - while (paused) { - pauseObject.wait(); - } - } - } - - - protected void callDraw() { - component.requestDraw(); - if (component.canDraw() && sketch != null) { - sketch.handleDraw(); - } - } - - - public class AnimationThread extends Thread { - public AnimationThread() { - super("Animation Thread"); - } - - /** - * Main method for the primary animation thread. - * Painting in AWT and Swing - */ - @Override - public void run() { // not good to make this synchronized, locks things up - long beforeTime = System.nanoTime(); - long overSleepTime = 0L; - - int noDelays = 0; - // Number of frames with a delay of 0 ms before the - // animation thread yields to other running threads. - final int NO_DELAYS_PER_YIELD = 15; - - if (sketch == null) return; - - // un-pause the sketch and get rolling - sketch.start(); - - while ((Thread.currentThread() == thread) && - (sketch != null && !sketch.finished)) { - if (Thread.currentThread().isInterrupted()) { - return; - } - try { - checkPause(); - } catch (InterruptedException e) { - return; - } - - callDraw(); - - // wait for update & paint to happen before drawing next frame - // this is necessary since the drawing is sometimes in a - // separate thread, meaning that the next frame will start - // before the update/paint is completed - - long afterTime = System.nanoTime(); - long timeDiff = afterTime - beforeTime; - //System.out.println("time diff is " + timeDiff); - long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime; - - if (sleepTime > 0) { // some time left in this cycle - try { - Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L)); - noDelays = 0; // Got some sleep, not delaying anymore - } catch (InterruptedException ex) { } - - overSleepTime = (System.nanoTime() - afterTime) - sleepTime; - - } else { // sleepTime <= 0; the frame took longer than the period - overSleepTime = 0L; - noDelays++; - - if (noDelays > NO_DELAYS_PER_YIELD) { - Thread.yield(); // give another thread a chance to run - noDelays = 0; - } - } - - beforeTime = System.nanoTime(); - } - } - } - - - public boolean hasPermission(String permission) { - int res = ContextCompat.checkSelfPermission(getContext(), permission); - return res == PackageManager.PERMISSION_GRANTED; - } - - - public void requestPermissions(String[] permissions) { - if (component.isService()) { - // https://developer.android.com/training/articles/wear-permissions.html - // Inspired by PermissionHelper.java from Michael von Glasow: - // https://github.com/mvglasow/satstat/blob/master/src/com/vonglasow/michael/satstat/utils/PermissionHelper.java - // Example of use: - // https://github.com/mvglasow/satstat/blob/master/src/com/vonglasow/michael/satstat/PasvLocListenerService.java - final ServiceEngine eng = getEngine(); - if (eng != null) { // A valid service should have a non-null engine at this point, but just in case - ResultReceiver resultReceiver = new ResultReceiver(new Handler(Looper.getMainLooper())) { - @Override - protected void onReceiveResult (int resultCode, Bundle resultData) { - String[] outPermissions = resultData.getStringArray(PermissionRequestor.KEY_PERMISSIONS); - int[] grantResults = resultData.getIntArray(PermissionRequestor.KEY_GRANT_RESULTS); - eng.onRequestPermissionsResult(resultCode, outPermissions, grantResults); - } - }; - final Intent permIntent = new Intent(getContext(), PermissionRequestor.class); - permIntent.putExtra(PermissionRequestor.KEY_RESULT_RECEIVER, resultReceiver); - permIntent.putExtra(PermissionRequestor.KEY_PERMISSIONS, permissions); - permIntent.putExtra(PermissionRequestor.KEY_REQUEST_CODE, REQUEST_PERMISSIONS); - // Show the dialog requesting the permissions - permIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(permIntent); - } - } else if (activity != null) { - // Requesting permissions from user when the app resumes. - // Nice example on how to handle user response - // http://stackoverflow.com/a/35495855 - // More on permission in Android 23: - // https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en - ActivityCompat.requestPermissions(activity, permissions, REQUEST_PERMISSIONS); - } - } -} diff --git a/core/src/processing/core/PVector.java b/core/src/processing/core/PVector.java deleted file mode 100644 index d1c074f92..000000000 --- a/core/src/processing/core/PVector.java +++ /dev/null @@ -1,1062 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2008-12 Ben Fry and Casey Reas - Copyright (c) 2008 Dan Shiffman - - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - */ - -package processing.core; - -import java.io.Serializable; - -import processing.core.PApplet; -import processing.core.PConstants; - -/** - * ( begin auto-generated from PVector.xml ) - * - * A class to describe a two or three dimensional vector. This datatype - * stores two or three variables that are commonly used as a position, - * velocity, and/or acceleration. Technically, position is a point - * and velocity and acceleration are vectors, but this is - * often simplified to consider all three as vectors. For example, if you - * consider a rectangle moving across the screen, at any given instant it - * has a position (the object's location, expressed as a point.), a - * velocity (the rate at which the object's position changes per time unit, - * expressed as a vector), and acceleration (the rate at which the object's - * velocity changes per time unit, expressed as a vector). Since vectors - * represent groupings of values, we cannot simply use traditional - * addition/multiplication/etc. Instead, we'll need to do some "vector" - * math, which is made easy by the methods inside the PVector - * class.
    - *
    - * The methods for this class are extensive. For a complete list, visit the - * developer's reference. - * - * ( end auto-generated ) - * - * A class to describe a two or three dimensional vector. - *

    - * The result of all functions are applied to the vector itself, with the - * exception of cross(), which returns a new PVector (or writes to a specified - * 'target' PVector). That is, add() will add the contents of one vector to - * this one. Using add() with additional parameters allows you to put the - * result into a new PVector. Functions that act on multiple vectors also - * include static versions. Because creating new objects can be computationally - * expensive, most functions include an optional 'target' PVector, so that a - * new PVector object is not created with each operation. - *

    - * Initially based on the Vector3D class by Dan Shiffman. - * - * @webref math - */ -public class PVector implements Serializable { - /** - * ( begin auto-generated from PVector_x.xml ) - * - * The x component of the vector. This field (variable) can be used to both - * get and set the value (see above example.) - * - * ( end auto-generated ) - * - * @webref pvector:field - * @usage web_application - * @brief The x component of the vector - */ - public float x; - - /** - * ( begin auto-generated from PVector_y.xml ) - * - * The y component of the vector. This field (variable) can be used to both - * get and set the value (see above example.) - * - * ( end auto-generated ) - * - * @webref pvector:field - * @usage web_application - * @brief The y component of the vector - */ - public float y; - - /** - * ( begin auto-generated from PVector_z.xml ) - * - * The z component of the vector. This field (variable) can be used to both - * get and set the value (see above example.) - * - * ( end auto-generated ) - * - * @webref pvector:field - * @usage web_application - * @brief The z component of the vector - */ - public float z; - - /** Array so that this can be temporarily used in an array context */ - transient protected float[] array; - - - /** - * Constructor for an empty vector: x, y, and z are set to 0. - */ - public PVector() { - } - - - /** - * Constructor for a 3D vector. - * - * @param x the x coordinate. - * @param y the y coordinate. - * @param z the z coordinate. - */ - public PVector(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - } - - - /** - * Constructor for a 2D vector: z coordinate is set to 0. - */ - public PVector(float x, float y) { - this.x = x; - this.y = y; - this.z = 0; - } - - - /** - * ( begin auto-generated from PVector_set.xml ) - * - * Sets the x, y, and z component of the vector using two or three separate - * variables, the data from a PVector, or the values from a float array. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @param x the x component of the vector - * @param y the y component of the vector - * @param z the z component of the vector - * @brief Set the components of the vector - */ - public PVector set(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - return this; - } - - - /** - * @param x the x component of the vector - * @param y the y component of the vector - */ - public PVector set(float x, float y) { - this.x = x; - this.y = y; - return this; - } - - - /** - * @param v any variable of type PVector - */ - public PVector set(PVector v) { - x = v.x; - y = v.y; - z = v.z; - return this; - } - - - /** - * Set the x, y (and maybe z) coordinates using a float[] array as the source. - * @param source array to copy from - */ - public PVector set(float[] source) { - if (source.length >= 2) { - x = source[0]; - y = source[1]; - } - if (source.length >= 3) { - z = source[2]; - } - return this; - } - - - /** - * ( begin auto-generated from PVector_random2D.xml ) - * - * Make a new 2D unit vector with a random direction. If you pass in "this" - * as an argument, it will use the PApplet's random number generator. You can - * also pass in a target PVector to fill. - * - * @webref pvector:method - * @usage web_application - * @return the random PVector - * @brief Make a new 2D unit vector with a random direction. - * @see PVector#random3D() - */ - static public PVector random2D() { - return random2D(null, null); - } - - - /** - * Make a new 2D unit vector with a random direction - * using Processing's current random number generator - * @param parent current PApplet instance - * @return the random PVector - */ - static public PVector random2D(PApplet parent) { - return random2D(null, parent); - } - - /** - * Set a 2D vector to a random unit vector with a random direction - * @param target the target vector (if null, a new vector will be created) - * @return the random PVector - */ - static public PVector random2D(PVector target) { - return random2D(target, null); - } - - - /** - * Make a new 2D unit vector with a random direction. Pass in the parent - * PApplet if you want randomSeed() to work (and be predictable). Or leave - * it null and be... random. - * @return the random PVector - */ - static public PVector random2D(PVector target, PApplet parent) { - return (parent == null) ? - fromAngle((float) (Math.random() * Math.PI*2), target) : - fromAngle(parent.random(PConstants.TAU), target); - } - - - /** - * ( begin auto-generated from PVector_random3D.xml ) - * - * Make a new 3D unit vector with a random direction. If you pass in "this" - * as an argument, it will use the PApplet's random number generator. You can - * also pass in a target PVector to fill. - * - * @webref pvector:method - * @usage web_application - * @return the random PVector - * @brief Make a new 3D unit vector with a random direction. - * @see PVector#random2D() - */ - static public PVector random3D() { - return random3D(null, null); - } - - - /** - * Make a new 3D unit vector with a random direction - * using Processing's current random number generator - * @param parent current PApplet instance - * @return the random PVector - */ - static public PVector random3D(PApplet parent) { - return random3D(null, parent); - } - - - /** - * Set a 3D vector to a random unit vector with a random direction - * @param target the target vector (if null, a new vector will be created) - * @return the random PVector - */ - static public PVector random3D(PVector target) { - return random3D(target, null); - } - - - /** - * Make a new 3D unit vector with a random direction - * @return the random PVector - */ - static public PVector random3D(PVector target, PApplet parent) { - float angle; - float vz; - if (parent == null) { - angle = (float) (Math.random()*Math.PI*2); - vz = (float) (Math.random()*2-1); - } else { - angle = parent.random(PConstants.TWO_PI); - vz = parent.random(-1,1); - } - float vx = (float) (Math.sqrt(1-vz*vz)*Math.cos(angle)); - float vy = (float) (Math.sqrt(1-vz*vz)*Math.sin(angle)); - if (target == null) { - target = new PVector(vx, vy, vz); - //target.normalize(); // Should be unnecessary - } else { - target.set(vx,vy,vz); - } - return target; - } - - - /** - * ( begin auto-generated from PVector_sub.xml ) - * - * Make a new 2D unit vector from an angle. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @brief Make a new 2D unit vector from an angle - * @param angle the angle in radians - * @return the new unit PVector - */ - static public PVector fromAngle(float angle) { - return fromAngle(angle,null); - } - - - /** - * Make a new 2D unit vector from an angle - * - * @param target the target vector (if null, a new vector will be created) - * @return the PVector - */ - static public PVector fromAngle(float angle, PVector target) { - if (target == null) { - target = new PVector((float)Math.cos(angle),(float)Math.sin(angle),0); - } else { - target.set((float)Math.cos(angle),(float)Math.sin(angle),0); - } - return target; - } - - - /** - * ( begin auto-generated from PVector_copy.xml ) - * - * Gets a copy of the vector, returns a PVector object. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @brief Get a copy of the vector - */ - public PVector copy() { - return new PVector(x, y, z); - } - - - @Deprecated - public PVector get() { - return copy(); - } - - - /** - * @param target - */ - public float[] get(float[] target) { - if (target == null) { - return new float[] { x, y, z }; - } - if (target.length >= 2) { - target[0] = x; - target[1] = y; - } - if (target.length >= 3) { - target[2] = z; - } - return target; - } - - - /** - * ( begin auto-generated from PVector_mag.xml ) - * - * Calculates the magnitude (length) of the vector and returns the result - * as a float (this is simply the equation sqrt(x*x + y*y + z*z).) - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @brief Calculate the magnitude of the vector - * @return magnitude (length) of the vector - * @see PVector#magSq() - */ - public float mag() { - return (float) Math.sqrt(x*x + y*y + z*z); - } - - - /** - * ( begin auto-generated from PVector_mag.xml ) - * - * Calculates the squared magnitude of the vector and returns the result - * as a float (this is simply the equation (x*x + y*y + z*z).) - * Faster if the real length is not required in the - * case of comparing vectors, etc. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @brief Calculate the magnitude of the vector, squared - * @return squared magnitude of the vector - * @see PVector#mag() - */ - public float magSq() { - return (x*x + y*y + z*z); - } - - - /** - * ( begin auto-generated from PVector_add.xml ) - * - * Adds x, y, and z components to a vector, adds one vector to another, or - * adds two independent vectors together. The version of the method that - * adds two vectors together is a static method and returns a PVector, the - * others have no return value -- they act directly on the vector. See the - * examples for more context. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @param v the vector to be added - * @brief Adds x, y, and z components to a vector, one vector to another, or two independent vectors - */ - public PVector add(PVector v) { - x += v.x; - y += v.y; - z += v.z; - return this; - } - - - /** - * @param x x component of the vector - * @param y y component of the vector - */ - public PVector add(float x, float y) { - this.x += x; - this.y += y; - return this; - } - - - /** - * @param z z component of the vector - */ - public PVector add(float x, float y, float z) { - this.x += x; - this.y += y; - this.z += z; - return this; - } - - - /** - * Add two vectors - * @param v1 a vector - * @param v2 another vector - */ - static public PVector add(PVector v1, PVector v2) { - return add(v1, v2, null); - } - - - /** - * Add two vectors into a target vector - * @param target the target vector (if null, a new vector will be created) - */ - static public PVector add(PVector v1, PVector v2, PVector target) { - if (target == null) { - target = new PVector(v1.x + v2.x,v1.y + v2.y, v1.z + v2.z); - } else { - target.set(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); - } - return target; - } - - - /** - * ( begin auto-generated from PVector_sub.xml ) - * - * Subtracts x, y, and z components from a vector, subtracts one vector - * from another, or subtracts two independent vectors. The version of the - * method that subtracts two vectors is a static method and returns a - * PVector, the others have no return value -- they act directly on the - * vector. See the examples for more context. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @param v any variable of type PVector - * @brief Subtract x, y, and z components from a vector, one vector from another, or two independent vectors - */ - public PVector sub(PVector v) { - x -= v.x; - y -= v.y; - z -= v.z; - return this; - } - - - /** - * @param x the x component of the vector - * @param y the y component of the vector - */ - public PVector sub(float x, float y) { - this.x -= x; - this.y -= y; - return this; - } - - - /** - * @param z the z component of the vector - */ - public PVector sub(float x, float y, float z) { - this.x -= x; - this.y -= y; - this.z -= z; - return this; - } - - - /** - * Subtract one vector from another - * @param v1 the x, y, and z components of a PVector object - * @param v2 the x, y, and z components of a PVector object - */ - static public PVector sub(PVector v1, PVector v2) { - return sub(v1, v2, null); - } - - - /** - * Subtract one vector from another and store in another vector - * @param target PVector in which to store the result - */ - static public PVector sub(PVector v1, PVector v2, PVector target) { - if (target == null) { - target = new PVector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); - } else { - target.set(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); - } - return target; - } - - - /** - * ( begin auto-generated from PVector_mult.xml ) - * - * Multiplies a vector by a scalar or multiplies one vector by another. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @brief Multiply a vector by a scalar - * @param n the number to multiply with the vector - */ - public PVector mult(float n) { - x *= n; - y *= n; - z *= n; - return this; - } - - - /** - * @param v the vector to multiply by the scalar - */ - static public PVector mult(PVector v, float n) { - return mult(v, n, null); - } - - - /** - * Multiply a vector by a scalar, and write the result into a target PVector. - * @param target PVector in which to store the result - */ - static public PVector mult(PVector v, float n, PVector target) { - if (target == null) { - target = new PVector(v.x*n, v.y*n, v.z*n); - } else { - target.set(v.x*n, v.y*n, v.z*n); - } - return target; - } - - - /** - * ( begin auto-generated from PVector_div.xml ) - * - * Divides a vector by a scalar or divides one vector by another. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @brief Divide a vector by a scalar - * @param n the number by which to divide the vector - */ - public PVector div(float n) { - x /= n; - y /= n; - z /= n; - return this; - } - - - /** - * Divide a vector by a scalar and return the result in a new vector. - * @param v the vector to divide by the scalar - * @return a new vector that is v1 / n - */ - static public PVector div(PVector v, float n) { - return div(v, n, null); - } - - - /** - * Divide a vector by a scalar and store the result in another vector. - * @param target PVector in which to store the result - */ - static public PVector div(PVector v, float n, PVector target) { - if (target == null) { - target = new PVector(v.x/n, v.y/n, v.z/n); - } else { - target.set(v.x/n, v.y/n, v.z/n); - } - return target; - } - - - /** - * ( begin auto-generated from PVector_dist.xml ) - * - * Calculates the Euclidean distance between two points (considering a - * point as a vector object). - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @param v the x, y, and z coordinates of a PVector - * @brief Calculate the distance between two points - */ - public float dist(PVector v) { - float dx = x - v.x; - float dy = y - v.y; - float dz = z - v.z; - return (float) Math.sqrt(dx*dx + dy*dy + dz*dz); - } - - - /** - * @param v1 any variable of type PVector - * @param v2 any variable of type PVector - * @return the Euclidean distance between v1 and v2 - */ - static public float dist(PVector v1, PVector v2) { - float dx = v1.x - v2.x; - float dy = v1.y - v2.y; - float dz = v1.z - v2.z; - return (float) Math.sqrt(dx*dx + dy*dy + dz*dz); - } - - - /** - * ( begin auto-generated from PVector_dot.xml ) - * - * Calculates the dot product of two vectors. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @param v any variable of type PVector - * @return the dot product - * @brief Calculate the dot product of two vectors - */ - public float dot(PVector v) { - return x*v.x + y*v.y + z*v.z; - } - - - /** - * @param x x component of the vector - * @param y y component of the vector - * @param z z component of the vector - */ - public float dot(float x, float y, float z) { - return this.x*x + this.y*y + this.z*z; - } - - - /** - * @param v1 any variable of type PVector - * @param v2 any variable of type PVector - */ - static public float dot(PVector v1, PVector v2) { - return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; - } - - - /** - * ( begin auto-generated from PVector_cross.xml ) - * - * Calculates and returns a vector composed of the cross product between - * two vectors. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @param v the vector to calculate the cross product - * @brief Calculate and return the cross product - */ - public PVector cross(PVector v) { - return cross(v, null); - } - - - /** - * @param v any variable of type PVector - * @param target PVector to store the result - */ - public PVector cross(PVector v, PVector target) { - float crossX = y * v.z - v.y * z; - float crossY = z * v.x - v.z * x; - float crossZ = x * v.y - v.x * y; - - if (target == null) { - target = new PVector(crossX, crossY, crossZ); - } else { - target.set(crossX, crossY, crossZ); - } - return target; - } - - - /** - * @param v1 any variable of type PVector - * @param v2 any variable of type PVector - * @param target PVector to store the result - */ - static public PVector cross(PVector v1, PVector v2, PVector target) { - float crossX = v1.y * v2.z - v2.y * v1.z; - float crossY = v1.z * v2.x - v2.z * v1.x; - float crossZ = v1.x * v2.y - v2.x * v1.y; - - if (target == null) { - target = new PVector(crossX, crossY, crossZ); - } else { - target.set(crossX, crossY, crossZ); - } - return target; - } - - - /** - * ( begin auto-generated from PVector_normalize.xml ) - * - * Normalize the vector to length 1 (make it a unit vector). - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @brief Normalize the vector to a length of 1 - */ - public PVector normalize() { - float m = mag(); - if (m != 0 && m != 1) { - div(m); - } - return this; - } - - - /** - * @param target Set to null to create a new vector - * @return a new vector (if target was null), or target - */ - public PVector normalize(PVector target) { - if (target == null) { - target = new PVector(); - } - float m = mag(); - if (m > 0) { - target.set(x/m, y/m, z/m); - } else { - target.set(x, y, z); - } - return target; - } - - - /** - * ( begin auto-generated from PVector_limit.xml ) - * - * Limit the magnitude of this vector to the value used for the max parameter. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @param max the maximum magnitude for the vector - * @brief Limit the magnitude of the vector - */ - public PVector limit(float max) { - if (magSq() > max*max) { - normalize(); - mult(max); - } - return this; - } - - - /** - * ( begin auto-generated from PVector_setMag.xml ) - * - * Set the magnitude of this vector to the value used for the len parameter. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @param len the new length for this vector - * @brief Set the magnitude of the vector - */ - public PVector setMag(float len) { - normalize(); - mult(len); - return this; - } - - - /** - * Sets the magnitude of this vector, storing the result in another vector. - * @param target Set to null to create a new vector - * @param len the new length for the new vector - * @return a new vector (if target was null), or target - */ - public PVector setMag(PVector target, float len) { - target = normalize(target); - target.mult(len); - return target; - } - - - /** - * ( begin auto-generated from PVector_setMag.xml ) - * - * Calculate the angle of rotation for this vector (only 2D vectors) - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @return the angle of rotation - * @brief Calculate the angle of rotation for this vector - */ - public float heading() { - float angle = (float) Math.atan2(y, x); - return angle; - } - - - @Deprecated - public float heading2D() { - return heading(); - } - - - /** - * ( begin auto-generated from PVector_rotate.xml ) - * - * Rotate the vector by an angle (only 2D vectors), magnitude remains the same - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @brief Rotate the vector by an angle (2D only) - * @param theta the angle of rotation - */ - public PVector rotate(float theta) { - float temp = x; - // Might need to check for rounding errors like with angleBetween function? - x = x*PApplet.cos(theta) - y*PApplet.sin(theta); - y = temp*PApplet.sin(theta) + y*PApplet.cos(theta); - return this; - } - - - /** - * ( begin auto-generated from PVector_rotate.xml ) - * - * Linear interpolate the vector to another vector - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @brief Linear interpolate the vector to another vector - * @param v the vector to lerp to - * @param amt The amount of interpolation; some value between 0.0 (old vector) and 1.0 (new vector). 0.1 is very near the old vector; 0.5 is halfway in between. - * @see PApplet#lerp(float, float, float) - */ - public PVector lerp(PVector v, float amt) { - x = PApplet.lerp(x, v.x, amt); - y = PApplet.lerp(y, v.y, amt); - z = PApplet.lerp(z, v.z, amt); - return this; - } - - - /** - * Linear interpolate between two vectors (returns a new PVector object) - * @param v1 the vector to start from - * @param v2 the vector to lerp to - */ - public static PVector lerp(PVector v1, PVector v2, float amt) { - PVector v = v1.copy(); - v.lerp(v2, amt); - return v; - } - - - /** - * Linear interpolate the vector to x,y,z values - * @param x the x component to lerp to - * @param y the y component to lerp to - * @param z the z component to lerp to - */ - public PVector lerp(float x, float y, float z, float amt) { - this.x = PApplet.lerp(this.x, x, amt); - this.y = PApplet.lerp(this.y, y, amt); - this.z = PApplet.lerp(this.z, z, amt); - return this; - } - - - /** - * ( begin auto-generated from PVector_angleBetween.xml ) - * - * Calculates and returns the angle (in radians) between two vectors. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage web_application - * @param v1 the x, y, and z components of a PVector - * @param v2 the x, y, and z components of a PVector - * @brief Calculate and return the angle between two vectors - */ - static public float angleBetween(PVector v1, PVector v2) { - - // We get NaN if we pass in a zero vector which can cause problems - // Zero seems like a reasonable angle between a (0,0,0) vector and something else - if (v1.x == 0 && v1.y == 0 && v1.z == 0 ) return 0.0f; - if (v2.x == 0 && v2.y == 0 && v2.z == 0 ) return 0.0f; - - double dot = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; - double v1mag = Math.sqrt(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z); - double v2mag = Math.sqrt(v2.x * v2.x + v2.y * v2.y + v2.z * v2.z); - // This should be a number between -1 and 1, since it's "normalized" - double amt = dot / (v1mag * v2mag); - // But if it's not due to rounding error, then we need to fix it - // http://code.google.com/p/processing/issues/detail?id=340 - // Otherwise if outside the range, acos() will return NaN - // http://www.cppreference.com/wiki/c/math/acos - if (amt <= -1) { - return PConstants.PI; - } else if (amt >= 1) { - // http://code.google.com/p/processing/issues/detail?id=435 - return 0; - } - return (float) Math.acos(amt); - } - - - @Override - public String toString() { - return "[ " + x + ", " + y + ", " + z + " ]"; - } - - - /** - * ( begin auto-generated from PVector_array.xml ) - * - * Return a representation of this vector as a float array. This is only - * for temporary use. If used in any other fashion, the contents should be - * copied by using the PVector.get() method to copy into your own array. - * - * ( end auto-generated ) - * - * @webref pvector:method - * @usage: web_application - * @brief Return a representation of the vector as a float array - */ - public float[] array() { - if (array == null) { - array = new float[3]; - } - array[0] = x; - array[1] = y; - array[2] = z; - return array; - } - - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof PVector)) { - return false; - } - final PVector p = (PVector) obj; - return x == p.x && y == p.y && z == p.z; - } - - - @Override - public int hashCode() { - int result = 1; - result = 31 * result + Float.floatToIntBits(x); - result = 31 * result + Float.floatToIntBits(y); - result = 31 * result + Float.floatToIntBits(z); - return result; - } -} diff --git a/core/src/processing/data/DoubleDict.java b/core/src/processing/data/DoubleDict.java deleted file mode 100644 index f2a9adf10..000000000 --- a/core/src/processing/data/DoubleDict.java +++ /dev/null @@ -1,850 +0,0 @@ -package processing.data; - -import java.io.*; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; - -import processing.core.PApplet; - - -/** - * A simple table class to use a String as a lookup for an double value. - * - * @webref data:composite - * @see IntDict - * @see StringDict - */ -public class DoubleDict { - - /** Number of elements in the table */ - protected int count; - - protected String[] keys; - protected double[] values; - - /** Internal implementation for faster lookups */ - private HashMap indices = new HashMap<>(); - - - public DoubleDict() { - count = 0; - keys = new String[10]; - values = new double[10]; - } - - - /** - * Create a new lookup with a specific size. This is more efficient than not - * specifying a size. Use it when you know the rough size of the thing you're creating. - * - * @nowebref - */ - public DoubleDict(int length) { - count = 0; - keys = new String[length]; - values = new double[length]; - } - - - /** - * Read a set of entries from a Reader that has each key/value pair on - * a single line, separated by a tab. - * - * @nowebref - */ - public DoubleDict(BufferedReader reader) { - String[] lines = PApplet.loadStrings(reader); - keys = new String[lines.length]; - values = new double[lines.length]; - - for (int i = 0; i < lines.length; i++) { - String[] pieces = PApplet.split(lines[i], '\t'); - if (pieces.length == 2) { - keys[count] = pieces[0]; - values[count] = PApplet.parseFloat(pieces[1]); - indices.put(pieces[0], count); - count++; - } - } - } - - - /** - * @nowebref - */ - public DoubleDict(String[] keys, double[] values) { - if (keys.length != values.length) { - throw new IllegalArgumentException("key and value arrays must be the same length"); - } - this.keys = keys; - this.values = values; - count = keys.length; - for (int i = 0; i < count; i++) { - indices.put(keys[i], i); - } - } - - - /** - * Constructor to allow (more intuitive) inline initialization, e.g.: - *

    -   * new FloatDict(new Object[][] {
    -   *   { "key1", 1 },
    -   *   { "key2", 2 }
    -   * });
    -   * 
    - */ - public DoubleDict(Object[][] pairs) { - count = pairs.length; - this.keys = new String[count]; - this.values = new double[count]; - for (int i = 0; i < count; i++) { - keys[i] = (String) pairs[i][0]; - values[i] = (Float) pairs[i][1]; - indices.put(keys[i], i); - } - } - - - public DoubleDict(Map incoming) { - count = incoming.size(); - keys = new String[count]; - values = new double[count]; - int index = 0; - for (Map.Entry e : incoming.entrySet()) { - keys[index] = e.getKey(); - values[index] = e.getValue(); - indices.put(keys[index], index); - index++; - } - } - - - /** - * @webref doubledict:method - * @brief Returns the number of key/value pairs - */ - public int size() { - return count; - } - - - /** - * Resize the internal data, this can only be used to shrink the list. - * Helpful for situations like sorting and then grabbing the top 50 entries. - */ - public void resize(int length) { - if (length == count) return; - - if (length > count) { - throw new IllegalArgumentException("resize() can only be used to shrink the dictionary"); - } - if (length < 1) { - throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher"); - } - - String[] newKeys = new String[length]; - double[] newValues = new double[length]; - PApplet.arrayCopy(keys, newKeys, length); - PApplet.arrayCopy(values, newValues, length); - keys = newKeys; - values = newValues; - count = length; - resetIndices(); - } - - - /** - * Remove all entries. - * - * @webref doubledict:method - * @brief Remove all entries - */ - public void clear() { - count = 0; - indices = new HashMap<>(); - } - - - private void resetIndices() { - indices = new HashMap<>(count); - for (int i = 0; i < count; i++) { - indices.put(keys[i], i); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public class Entry { - public String key; - public double value; - - Entry(String key, double value) { - this.key = key; - this.value = value; - } - } - - - public Iterable entries() { - return new Iterable() { - - public Iterator iterator() { - return entryIterator(); - } - }; - } - - - public Iterator entryIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public Entry next() { - ++index; - Entry e = new Entry(keys[index], values[index]); - return e; - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public String key(int index) { - return keys[index]; - } - - - protected void crop() { - if (count != keys.length) { - keys = PApplet.subset(keys, 0, count); - values = PApplet.subset(values, 0, count); - } - } - - - public Iterable keys() { - return new Iterable() { - - @Override - public Iterator iterator() { - return keyIterator(); - } - }; - } - - - // Use this to iterate when you want to be able to remove elements along the way - public Iterator keyIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public String next() { - return key(++index); - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - /** - * Return a copy of the internal keys array. This array can be modified. - * - * @webref doubledict:method - * @brief Return a copy of the internal keys array - */ - public String[] keyArray() { - crop(); - return keyArray(null); - } - - - public String[] keyArray(String[] outgoing) { - if (outgoing == null || outgoing.length != count) { - outgoing = new String[count]; - } - System.arraycopy(keys, 0, outgoing, 0, count); - return outgoing; - } - - - public double value(int index) { - return values[index]; - } - - - /** - * @webref doubledict:method - * @brief Return the internal array being used to store the values - */ - public Iterable values() { - return new Iterable() { - - @Override - public Iterator iterator() { - return valueIterator(); - } - }; - } - - - public Iterator valueIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public Double next() { - return value(++index); - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - /** - * Create a new array and copy each of the values into it. - * - * @webref doubledict:method - * @brief Create a new array and copy each of the values into it - */ - public double[] valueArray() { - crop(); - return valueArray(null); - } - - - /** - * Fill an already-allocated array with the values (more efficient than - * creating a new array each time). If 'array' is null, or not the same - * size as the number of values, a new array will be allocated and returned. - */ - public double[] valueArray(double[] array) { - if (array == null || array.length != size()) { - array = new double[count]; - } - System.arraycopy(values, 0, array, 0, count); - return array; - } - - - /** - * Return a value for the specified key. - * - * @webref doubledict:method - * @brief Return a value for the specified key - */ - public double get(String key) { - int index = index(key); - if (index == -1) { - throw new IllegalArgumentException("No key named '" + key + "'"); - } - return values[index]; - } - - - public double get(String key, double alternate) { - int index = index(key); - if (index == -1) { - return alternate; - } - return values[index]; - } - - - /** - * @webref doubledict:method - * @brief Create a new key/value pair or change the value of one - */ - public void set(String key, double amount) { - int index = index(key); - if (index == -1) { - create(key, amount); - } else { - values[index] = amount; - } - } - - - public void setIndex(int index, String key, double value) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - keys[index] = key; - values[index] = value; - } - - - /** - * @webref doubledict:method - * @brief Check if a key is a part of the data structure - */ - public boolean hasKey(String key) { - return index(key) != -1; - } - - - /** - * @webref doubledict:method - * @brief Add to a value - */ - public void add(String key, double amount) { - int index = index(key); - if (index == -1) { - create(key, amount); - } else { - values[index] += amount; - } - } - - - /** - * @webref doubledict:method - * @brief Subtract from a value - */ - public void sub(String key, double amount) { - add(key, -amount); - } - - - /** - * @webref doubledict:method - * @brief Multiply a value - */ - public void mult(String key, double amount) { - int index = index(key); - if (index != -1) { - values[index] *= amount; - } - } - - - /** - * @webref doubledict:method - * @brief Divide a value - */ - public void div(String key, double amount) { - int index = index(key); - if (index != -1) { - values[index] /= amount; - } - } - - - private void checkMinMax(String functionName) { - if (count == 0) { - String msg = - String.format("Cannot use %s() on an empty %s.", - functionName, getClass().getSimpleName()); - throw new RuntimeException(msg); - } - } - - - /** - * @webref doublelist:method - * @brief Return the smallest value - */ - public int minIndex() { - //checkMinMax("minIndex"); - if (count == 0) return -1; - - // Will still return NaN if there are 1 or more entries, and they're all NaN - double m = Float.NaN; - int mi = -1; - for (int i = 0; i < count; i++) { - // find one good value to start - if (values[i] == values[i]) { - m = values[i]; - mi = i; - - // calculate the rest - for (int j = i+1; j < count; j++) { - double d = values[j]; - if ((d == d) && (d < m)) { - m = values[j]; - mi = j; - } - } - break; - } - } - return mi; - } - - - // return the key for the minimum value - public String minKey() { - checkMinMax("minKey"); - int index = minIndex(); - if (index == -1) { - return null; - } - return keys[index]; - } - - - // return the minimum value, or throw an error if there are no values - public double minValue() { - checkMinMax("minValue"); - int index = minIndex(); - if (index == -1) { - return Float.NaN; - } - return values[index]; - } - - - /** - * @webref doublelist:method - * @brief Return the largest value - */ - // The index of the entry that has the max value. Reference above is incorrect. - public int maxIndex() { - //checkMinMax("maxIndex"); - if (count == 0) { - return -1; - } - // Will still return NaN if there is 1 or more entries, and they're all NaN - double m = Double.NaN; - int mi = -1; - for (int i = 0; i < count; i++) { - // find one good value to start - if (values[i] == values[i]) { - m = values[i]; - mi = i; - - // calculate the rest - for (int j = i+1; j < count; j++) { - double d = values[j]; - if (!Double.isNaN(d) && (d > m)) { - m = values[j]; - mi = j; - } - } - break; - } - } - return mi; - } - - - /** The key for a max value; null if empty or everything is NaN (no max). */ - public String maxKey() { - //checkMinMax("maxKey"); - int index = maxIndex(); - if (index == -1) { - return null; - } - return keys[index]; - } - - - /** The max value. (Or NaN if no entries or they're all NaN.) */ - public double maxValue() { - //checkMinMax("maxValue"); - int index = maxIndex(); - if (index == -1) { - return Float.NaN; - } - return values[index]; - } - - - public double sum() { - double sum = 0; - for (int i = 0; i < count; i++) { - sum += values[i]; - } - return sum; - } - - - public int index(String what) { - Integer found = indices.get(what); - return (found == null) ? -1 : found.intValue(); - } - - - protected void create(String what, double much) { - if (count == keys.length) { - keys = PApplet.expand(keys); - values = PApplet.expand(values); - } - indices.put(what, Integer.valueOf(count)); - keys[count] = what; - values[count] = much; - count++; - } - - - /** - * @webref doubledict:method - * @brief Remove a key/value pair - */ - public double remove(String key) { - int index = index(key); - if (index == -1) { - throw new NoSuchElementException("'" + key + "' not found"); - } - double value = values[index]; - removeIndex(index); - return value; - } - - - public double removeIndex(int index) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - double value = values[index]; - indices.remove(keys[index]); - for (int i = index; i < count-1; i++) { - keys[i] = keys[i+1]; - values[i] = values[i+1]; - indices.put(keys[i], i); - } - count--; - keys[count] = null; - values[count] = 0; - return value; - } - - - public void swap(int a, int b) { - String tkey = keys[a]; - double tvalue = values[a]; - keys[a] = keys[b]; - values[a] = values[b]; - keys[b] = tkey; - values[b] = tvalue; - -// indices.put(keys[a], Integer.valueOf(a)); -// indices.put(keys[b], Integer.valueOf(b)); - } - - - /** - * Sort the keys alphabetically (ignoring case). Uses the value as a - * tie-breaker (only really possible with a key that has a case change). - * - * @webref doubledict:method - * @brief Sort the keys alphabetically - */ - public void sortKeys() { - sortImpl(true, false, true); - } - - - /** - * @webref doubledict:method - * @brief Sort the keys alphabetically in reverse - */ - public void sortKeysReverse() { - sortImpl(true, true, true); - } - - - /** - * Sort by values in descending order (largest value will be at [0]). - * - * @webref doubledict:method - * @brief Sort by values in ascending order - */ - public void sortValues() { - sortValues(true); - } - - - /** - * Set true to ensure that the order returned is identical. Slightly - * slower because the tie-breaker for identical values compares the keys. - * @param stable - */ - public void sortValues(boolean stable) { - sortImpl(false, false, stable); - } - - - /** - * @webref doubledict:method - * @brief Sort by values in descending order - */ - public void sortValuesReverse() { - sortValuesReverse(true); - } - - - public void sortValuesReverse(boolean stable) { - sortImpl(false, true, stable); - } - - - protected void sortImpl(final boolean useKeys, final boolean reverse, - final boolean stable) { - Sort s = new Sort() { - @Override - public int size() { - if (useKeys) { - return count; // don't worry about NaN values - - } else if (count == 0) { // skip the NaN check, it'll AIOOBE - return 0; - - } else { // first move NaN values to the end of the list - int right = count - 1; - while (values[right] != values[right]) { - right--; - if (right == -1) { - return 0; // all values are NaN - } - } - for (int i = right; i >= 0; --i) { - if (Double.isNaN(values[i])) { - swap(i, right); - --right; - } - } - return right + 1; - } - } - - @Override - public int compare(int a, int b) { - double diff = 0; - if (useKeys) { - diff = keys[a].compareToIgnoreCase(keys[b]); - if (diff == 0) { - diff = values[a] - values[b]; - } - } else { // sort values - diff = values[a] - values[b]; - if (diff == 0 && stable) { - diff = keys[a].compareToIgnoreCase(keys[b]); - } - } - if (diff == 0) { - return 0; - } else if (reverse) { - return diff < 0 ? 1 : -1; - } else { - return diff < 0 ? -1 : 1; - } - } - - @Override - public void swap(int a, int b) { - DoubleDict.this.swap(a, b); - } - }; - s.run(); - - // Set the indices after sort/swaps (performance fix 160411) - resetIndices(); - } - - - /** - * Sum all of the values in this dictionary, then return a new FloatDict of - * each key, divided by the total sum. The total for all values will be ~1.0. - * @return a FloatDict with the original keys, mapped to their pct of the total - */ - public DoubleDict getPercent() { - double sum = sum(); - DoubleDict outgoing = new DoubleDict(); - for (int i = 0; i < size(); i++) { - double percent = value(i) / sum; - outgoing.set(key(i), percent); - } - return outgoing; - } - - - /** Returns a duplicate copy of this object. */ - public DoubleDict copy() { - DoubleDict outgoing = new DoubleDict(count); - System.arraycopy(keys, 0, outgoing.keys, 0, count); - System.arraycopy(values, 0, outgoing.values, 0, count); - for (int i = 0; i < count; i++) { - outgoing.indices.put(keys[i], i); - } - outgoing.count = count; - return outgoing; - } - - - public void print() { - for (int i = 0; i < size(); i++) { - System.out.println(keys[i] + " = " + values[i]); - } - } - - - /** - * Save tab-delimited entries to a file (TSV format, UTF-8 encoding) - */ - public void save(File file) { - PrintWriter writer = PApplet.createWriter(file); - write(writer); - writer.close(); - } - - - /** - * Write tab-delimited entries out to - * @param writer - */ - public void write(PrintWriter writer) { - for (int i = 0; i < count; i++) { - writer.println(keys[i] + "\t" + values[i]); - } - writer.flush(); - } - - - /** - * Return this dictionary as a String in JSON format. - */ - public String toJSON() { - StringList items = new StringList(); - for (int i = 0; i < count; i++) { - items.append(JSONObject.quote(keys[i])+ ": " + values[i]); - } - return "{ " + items.join(", ") + " }"; - } - - - @Override - public String toString() { - return getClass().getSimpleName() + " size=" + size() + " " + toJSON(); - } -} diff --git a/core/src/processing/data/DoubleList.java b/core/src/processing/data/DoubleList.java deleted file mode 100644 index ae47a8442..000000000 --- a/core/src/processing/data/DoubleList.java +++ /dev/null @@ -1,928 +0,0 @@ -package processing.data; - -import java.io.File; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Random; - -import processing.core.PApplet; - - -/** - * Helper class for a list of floats. Lists are designed to have some of the - * features of ArrayLists, but to maintain the simplicity and efficiency of - * working with arrays. - * - * Functions like sort() and shuffle() always act on the list itself. To get - * a sorted copy, use list.copy().sort(). - * - * @webref data:composite - * @see IntList - * @see StringList - */ -public class DoubleList implements Iterable { - int count; - double[] data; - - - public DoubleList() { - data = new double[10]; - } - - - /** - * @nowebref - */ - public DoubleList(int length) { - data = new double[length]; - } - - - /** - * @nowebref - */ - public DoubleList(double[] list) { - count = list.length; - data = new double[count]; - System.arraycopy(list, 0, data, 0, count); - } - - - /** - * Construct an FloatList from an iterable pile of objects. - * For instance, a double array, an array of strings, who knows). - * Un-parseable or null values will be set to NaN. - * @nowebref - */ - public DoubleList(Iterable iter) { - this(10); - for (Object o : iter) { - if (o == null) { - append(Double.NaN); - } else if (o instanceof Number) { - append(((Number) o).doubleValue()); - } else { - append(PApplet.parseFloat(o.toString().trim())); - } - } - crop(); - } - - - /** - * Construct an FloatList from a random pile of objects. - * Un-parseable or null values will be set to NaN. - */ - public DoubleList(Object... items) { - // nuts, no good way to pass missingValue to this fn (varargs must be last) - final double missingValue = Double.NaN; - - count = items.length; - data = new double[count]; - int index = 0; - for (Object o : items) { - double value = missingValue; - if (o != null) { - if (o instanceof Number) { - value = ((Number) o).doubleValue(); - } else { - try { - value = Double.parseDouble(o.toString().trim()); - } catch (NumberFormatException nfe) { - value = missingValue; - } - } - } - data[index++] = value; - } - } - - - /** - * Improve efficiency by removing allocated but unused entries from the - * internal array used to store the data. Set to private, though it could - * be useful to have this public if lists are frequently making drastic - * size changes (from very large to very small). - */ - private void crop() { - if (count != data.length) { - data = PApplet.subset(data, 0, count); - } - } - - - /** - * Get the length of the list. - * - * @webref doublelist:method - * @brief Get the length of the list - */ - public int size() { - return count; - } - - - public void resize(int length) { - if (length > data.length) { - double[] temp = new double[length]; - System.arraycopy(data, 0, temp, 0, count); - data = temp; - - } else if (length > count) { - Arrays.fill(data, count, length, 0); - } - count = length; - } - - - /** - * Remove all entries from the list. - * - * @webref doublelist:method - * @brief Remove all entries from the list - */ - public void clear() { - count = 0; - } - - - /** - * Get an entry at a particular index. - * - * @webref doublelist:method - * @brief Get an entry at a particular index - */ - public double get(int index) { - if (index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - return data[index]; - } - - - /** - * Set the entry at a particular index. If the index is past the length of - * the list, it'll expand the list to accommodate, and fill the intermediate - * entries with 0s. - * - * @webref doublelist:method - * @brief Set the entry at a particular index - */ - public void set(int index, double what) { - if (index >= count) { - data = PApplet.expand(data, index+1); - for (int i = count; i < index; i++) { - data[i] = 0; - } - count = index+1; - } - data[index] = what; - } - - - /** Just an alias for append(), but matches pop() */ - public void push(double value) { - append(value); - } - - - public double pop() { - if (count == 0) { - throw new RuntimeException("Can't call pop() on an empty list"); - } - double value = get(count-1); - count--; - return value; - } - - - /** - * Remove an element from the specified index. - * - * @webref doublelist:method - * @brief Remove an element from the specified index - */ - public double remove(int index) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - double entry = data[index]; -// int[] outgoing = new int[count - 1]; -// System.arraycopy(data, 0, outgoing, 0, index); -// count--; -// System.arraycopy(data, index + 1, outgoing, 0, count - index); -// data = outgoing; - // For most cases, this actually appears to be faster - // than arraycopy() on an array copying into itself. - for (int i = index; i < count-1; i++) { - data[i] = data[i+1]; - } - count--; - return entry; - } - - - // Remove the first instance of a particular value, - // and return the index at which it was found. - public int removeValue(int value) { - int index = index(value); - if (index != -1) { - remove(index); - return index; - } - return -1; - } - - - // Remove all instances of a particular value, - // and return the number of values found and removed - public int removeValues(int value) { - int ii = 0; - if (Double.isNaN(value)) { - for (int i = 0; i < count; i++) { - if (!Double.isNaN(data[i])) { - data[ii++] = data[i]; - } - } - } else { - for (int i = 0; i < count; i++) { - if (data[i] != value) { - data[ii++] = data[i]; - } - } - } - int removed = count - ii; - count = ii; - return removed; - } - - - /** Replace the first instance of a particular value */ - public boolean replaceValue(double value, double newValue) { - if (Double.isNaN(value)) { - for (int i = 0; i < count; i++) { - if (Double.isNaN(data[i])) { - data[i] = newValue; - return true; - } - } - } else { - int index = index(value); - if (index != -1) { - data[index] = newValue; - return true; - } - } - return false; - } - - - /** Replace all instances of a particular value */ - public boolean replaceValues(double value, double newValue) { - boolean changed = false; - if (Double.isNaN(value)) { - for (int i = 0; i < count; i++) { - if (Double.isNaN(data[i])) { - data[i] = newValue; - changed = true; - } - } - } else { - for (int i = 0; i < count; i++) { - if (data[i] == value) { - data[i] = newValue; - changed = true; - } - } - } - return changed; - } - - - - /** - * Add a new entry to the list. - * - * @webref doublelist:method - * @brief Add a new entry to the list - */ - public void append(double value) { - if (count == data.length) { - data = PApplet.expand(data); - } - data[count++] = value; - } - - - public void append(double[] values) { - for (double v : values) { - append(v); - } - } - - - public void append(DoubleList list) { - for (double v : list.values()) { // will concat the list... - append(v); - } - } - - - /** Add this value, but only if it's not already in the list. */ - public void appendUnique(double value) { - if (!hasValue(value)) { - append(value); - } - } - - -// public void insert(int index, int value) { -// if (index+1 > count) { -// if (index+1 < data.length) { -// } -// } -// if (index >= data.length) { -// data = PApplet.expand(data, index+1); -// data[index] = value; -// count = index+1; -// -// } else if (count == data.length) { -// if (index >= count) { -// //int[] temp = new int[count << 1]; -// System.arraycopy(data, 0, temp, 0, index); -// temp[index] = value; -// System.arraycopy(data, index, temp, index+1, count - index); -// data = temp; -// -// } else { -// // data[] has room to grow -// // for() loop believed to be faster than System.arraycopy over itself -// for (int i = count; i > index; --i) { -// data[i] = data[i-1]; -// } -// data[index] = value; -// count++; -// } -// } - - - public void insert(int index, double value) { - insert(index, new double[] { value }); - } - - - // same as splice - public void insert(int index, double[] values) { - if (index < 0) { - throw new IllegalArgumentException("insert() index cannot be negative: it was " + index); - } - if (index >= data.length) { - throw new IllegalArgumentException("insert() index " + index + " is past the end of this list"); - } - - double[] temp = new double[count + values.length]; - - // Copy the old values, but not more than already exist - System.arraycopy(data, 0, temp, 0, Math.min(count, index)); - - // Copy the new values into the proper place - System.arraycopy(values, 0, temp, index, values.length); - -// if (index < count) { - // The index was inside count, so it's a true splice/insert - System.arraycopy(data, index, temp, index+values.length, count - index); - count = count + values.length; -// } else { -// // The index was past 'count', so the new count is weirder -// count = index + values.length; -// } - data = temp; - } - - - public void insert(int index, DoubleList list) { - insert(index, list.values()); - } - - - // below are aborted attempts at more optimized versions of the code - // that are harder to read and debug... - -// if (index + values.length >= count) { -// // We're past the current 'count', check to see if we're still allocated -// // index 9, data.length = 10, values.length = 1 -// if (index + values.length < data.length) { -// // There's still room for these entries, even though it's past 'count'. -// // First clear out the entries leading up to it, however. -// for (int i = count; i < index; i++) { -// data[i] = 0; -// } -// data[index] = -// } -// if (index >= data.length) { -// int length = index + values.length; -// int[] temp = new int[length]; -// System.arraycopy(data, 0, temp, 0, count); -// System.arraycopy(values, 0, temp, index, values.length); -// data = temp; -// count = data.length; -// } else { -// -// } -// -// } else if (count == data.length) { -// int[] temp = new int[count << 1]; -// System.arraycopy(data, 0, temp, 0, index); -// temp[index] = value; -// System.arraycopy(data, index, temp, index+1, count - index); -// data = temp; -// -// } else { -// // data[] has room to grow -// // for() loop believed to be faster than System.arraycopy over itself -// for (int i = count; i > index; --i) { -// data[i] = data[i-1]; -// } -// data[index] = value; -// count++; -// } - - - /** Return the first index of a particular value. */ - public int index(double what) { - /* - if (indexCache != null) { - try { - return indexCache.get(what); - } catch (Exception e) { // not there - return -1; - } - } - */ - for (int i = 0; i < count; i++) { - if (data[i] == what) { - return i; - } - } - return -1; - } - - - /** - * @webref doublelist:method - * @brief Check if a number is a part of the list - */ - public boolean hasValue(double value) { - if (Double.isNaN(value)) { - for (int i = 0; i < count; i++) { - if (Double.isNaN(data[i])) { - return true; - } - } - } else { - for (int i = 0; i < count; i++) { - if (data[i] == value) { - return true; - } - } - } - return false; - } - - - private void boundsProblem(int index, String method) { - final String msg = String.format("The list size is %d. " + - "You cannot %s() to element %d.", count, method, index); - throw new ArrayIndexOutOfBoundsException(msg); - } - - - /** - * @webref doublelist:method - * @brief Add to a value - */ - public void add(int index, double amount) { - if (index < count) { - data[index] += amount; - } else { - boundsProblem(index, "add"); - } - } - - - /** - * @webref doublelist:method - * @brief Subtract from a value - */ - public void sub(int index, double amount) { - if (index < count) { - data[index] -= amount; - } else { - boundsProblem(index, "sub"); - } - } - - - /** - * @webref doublelist:method - * @brief Multiply a value - */ - public void mult(int index, double amount) { - if (index < count) { - data[index] *= amount; - } else { - boundsProblem(index, "mult"); - } - } - - - /** - * @webref doublelist:method - * @brief Divide a value - */ - public void div(int index, double amount) { - if (index < count) { - data[index] /= amount; - } else { - boundsProblem(index, "div"); - } - } - - - private void checkMinMax(String functionName) { - if (count == 0) { - String msg = - String.format("Cannot use %s() on an empty %s.", - functionName, getClass().getSimpleName()); - throw new RuntimeException(msg); - } - } - - - /** - * @webref doublelist:method - * @brief Return the smallest value - */ - public double min() { - checkMinMax("min"); - int index = minIndex(); - return index == -1 ? Double.NaN : data[index]; - } - - - public int minIndex() { - checkMinMax("minIndex"); - double m = Double.NaN; - int mi = -1; - for (int i = 0; i < count; i++) { - // find one good value to start - if (data[i] == data[i]) { - m = data[i]; - mi = i; - - // calculate the rest - for (int j = i+1; j < count; j++) { - double d = data[j]; - if (!Double.isNaN(d) && (d < m)) { - m = data[j]; - mi = j; - } - } - break; - } - } - return mi; - } - - - /** - * @webref doublelist:method - * @brief Return the largest value - */ - public double max() { - checkMinMax("max"); - int index = maxIndex(); - return index == -1 ? Double.NaN : data[index]; - } - - - public int maxIndex() { - checkMinMax("maxIndex"); - double m = Double.NaN; - int mi = -1; - for (int i = 0; i < count; i++) { - // find one good value to start - if (data[i] == data[i]) { - m = data[i]; - mi = i; - - // calculate the rest - for (int j = i+1; j < count; j++) { - double d = data[j]; - if (!Double.isNaN(d) && (d > m)) { - m = data[j]; - mi = j; - } - } - break; - } - } - return mi; - } - - - public double sum() { - double sum = 0; - for (int i = 0; i < count; i++) { - sum += data[i]; - } - return sum; - } - - - /** - * Sorts the array in place. - * - * @webref doublelist:method - * @brief Sorts an array, lowest to highest - */ - public void sort() { - Arrays.sort(data, 0, count); - } - - - /** - * Reverse sort, orders values from highest to lowest - * - * @webref doublelist:method - * @brief Reverse sort, orders values from highest to lowest - */ - public void sortReverse() { - new Sort() { - @Override - public int size() { - // if empty, don't even mess with the NaN check, it'll AIOOBE - if (count == 0) { - return 0; - } - // move NaN values to the end of the list and don't sort them - int right = count - 1; - while (data[right] != data[right]) { - right--; - if (right == -1) { // all values are NaN - return 0; - } - } - for (int i = right; i >= 0; --i) { - double v = data[i]; - if (v != v) { - data[i] = data[right]; - data[right] = v; - --right; - } - } - return right + 1; - } - - @Override - public int compare(int a, int b) { - double diff = data[b] - data[a]; - return diff == 0 ? 0 : (diff < 0 ? -1 : 1); - } - - @Override - public void swap(int a, int b) { - double temp = data[a]; - data[a] = data[b]; - data[b] = temp; - } - }.run(); - } - - - // use insert() -// public void splice(int index, int value) { -// } - - -// public void subset(int start) { -// subset(start, count - start); -// } - - -// public void subset(int start, int num) { -// for (int i = 0; i < num; i++) { -// data[i] = data[i+start]; -// } -// count = num; -// } - - - /** - * @webref doublelist:method - * @brief Reverse the order of the list elements - */ - public void reverse() { - int ii = count - 1; - for (int i = 0; i < count/2; i++) { - double t = data[i]; - data[i] = data[ii]; - data[ii] = t; - --ii; - } - } - - - /** - * Randomize the order of the list elements. Note that this does not - * obey the randomSeed() function in PApplet. - * - * @webref doublelist:method - * @brief Randomize the order of the list elements - */ - public void shuffle() { - Random r = new Random(); - int num = count; - while (num > 1) { - int value = r.nextInt(num); - num--; - double temp = data[num]; - data[num] = data[value]; - data[value] = temp; - } - } - - - /** - * Randomize the list order using the random() function from the specified - * sketch, allowing shuffle() to use its current randomSeed() setting. - */ - public void shuffle(PApplet sketch) { - int num = count; - while (num > 1) { - int value = (int) sketch.random(num); - num--; - double temp = data[num]; - data[num] = data[value]; - data[value] = temp; - } - } - - - public DoubleList copy() { - DoubleList outgoing = new DoubleList(data); - outgoing.count = count; - return outgoing; - } - - - /** - * Returns the actual array being used to store the data. For advanced users, - * this is the fastest way to access a large list. Suitable for iterating - * with a for() loop, but modifying the list will have terrible consequences. - */ - public double[] values() { - crop(); - return data; - } - - - /** Implemented this way so that we can use a FloatList in a for loop. */ - @Override - public Iterator iterator() { -// } -// -// -// public Iterator valueIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - DoubleList.this.remove(index); - index--; - } - - public Double next() { - return data[++index]; - } - - public boolean hasNext() { - return index+1 < count; - } - }; - } - - - /** - * Create a new array with a copy of all the values. - * @return an array sized by the length of the list with each of the values. - * @webref doublelist:method - * @brief Create a new array with a copy of all the values - */ - public double[] array() { - return array(null); - } - - - /** - * Copy values into the specified array. If the specified array is null or - * not the same size, a new array will be allocated. - * @param array - */ - public double[] array(double[] array) { - if (array == null || array.length != count) { - array = new double[count]; - } - System.arraycopy(data, 0, array, 0, count); - return array; - } - - - /** - * Returns a normalized version of this array. Called getPercent() for - * consistency with the Dict classes. It's a getter method because it needs - * to returns a new list (because IntList/Dict can't do percentages or - * normalization in place on int values). - */ - public DoubleList getPercent() { - double sum = 0; - for (double value : array()) { - sum += value; - } - DoubleList outgoing = new DoubleList(count); - for (int i = 0; i < count; i++) { - double percent = data[i] / sum; - outgoing.set(i, percent); - } - return outgoing; - } - - - public DoubleList getSubset(int start) { - return getSubset(start, count - start); - } - - - public DoubleList getSubset(int start, int num) { - double[] subset = new double[num]; - System.arraycopy(data, start, subset, 0, num); - return new DoubleList(subset); - } - - - public String join(String separator) { - if (count == 0) { - return ""; - } - StringBuilder sb = new StringBuilder(); - sb.append(data[0]); - for (int i = 1; i < count; i++) { - sb.append(separator); - sb.append(data[i]); - } - return sb.toString(); - } - - - public void print() { - for (int i = 0; i < count; i++) { - System.out.format("[%d] %f%n", i, data[i]); - } - } - - - /** - * Save tab-delimited entries to a file (TSV format, UTF-8 encoding) - */ - public void save(File file) { - PrintWriter writer = PApplet.createWriter(file); - write(writer); - writer.close(); - } - - - /** - * Write entries to a PrintWriter, one per line - */ - public void write(PrintWriter writer) { - for (int i = 0; i < count; i++) { - writer.println(data[i]); - } - writer.flush(); - } - - - /** - * Return this dictionary as a String in JSON format. - */ - public String toJSON() { - return "[ " + join(", ") + " ]"; - } - - - @Override - public String toString() { - return getClass().getSimpleName() + " size=" + size() + " " + toJSON(); - } -} diff --git a/core/src/processing/data/FloatDict.java b/core/src/processing/data/FloatDict.java deleted file mode 100644 index 9495563ad..000000000 --- a/core/src/processing/data/FloatDict.java +++ /dev/null @@ -1,847 +0,0 @@ -package processing.data; - -import java.io.*; -import java.util.HashMap; -import java.util.Iterator; -import java.util.NoSuchElementException; - -import processing.core.PApplet; - - -/** - * A simple table class to use a String as a lookup for an float value. - * - * @webref data:composite - * @see IntDict - * @see StringDict - */ -public class FloatDict { - - /** Number of elements in the table */ - protected int count; - - protected String[] keys; - protected float[] values; - - /** Internal implementation for faster lookups */ - private HashMap indices = new HashMap<>(); - - - public FloatDict() { - count = 0; - keys = new String[10]; - values = new float[10]; - } - - - /** - * Create a new lookup with a specific size. This is more efficient than not - * specifying a size. Use it when you know the rough size of the thing you're creating. - * - * @nowebref - */ - public FloatDict(int length) { - count = 0; - keys = new String[length]; - values = new float[length]; - } - - - /** - * Read a set of entries from a Reader that has each key/value pair on - * a single line, separated by a tab. - * - * @nowebref - */ - public FloatDict(BufferedReader reader) { - String[] lines = PApplet.loadStrings(reader); - keys = new String[lines.length]; - values = new float[lines.length]; - - for (int i = 0; i < lines.length; i++) { - String[] pieces = PApplet.split(lines[i], '\t'); - if (pieces.length == 2) { - keys[count] = pieces[0]; - values[count] = PApplet.parseFloat(pieces[1]); - indices.put(pieces[0], count); - count++; - } - } - } - - - /** - * @nowebref - */ - public FloatDict(String[] keys, float[] values) { - if (keys.length != values.length) { - throw new IllegalArgumentException("key and value arrays must be the same length"); - } - this.keys = keys; - this.values = values; - count = keys.length; - for (int i = 0; i < count; i++) { - indices.put(keys[i], i); - } - } - - - /** - * Constructor to allow (more intuitive) inline initialization, e.g.: - *
    -   * new FloatDict(new Object[][] {
    -   *   { "key1", 1 },
    -   *   { "key2", 2 }
    -   * });
    -   * 
    - */ - public FloatDict(Object[][] pairs) { - count = pairs.length; - this.keys = new String[count]; - this.values = new float[count]; - for (int i = 0; i < count; i++) { - keys[i] = (String) pairs[i][0]; - values[i] = (Float) pairs[i][1]; - indices.put(keys[i], i); - } - } - - - /** - * @webref floatdict:method - * @brief Returns the number of key/value pairs - */ - public int size() { - return count; - } - - - /** - * Resize the internal data, this can only be used to shrink the list. - * Helpful for situations like sorting and then grabbing the top 50 entries. - */ - public void resize(int length) { - if (length == count) return; - - if (length > count) { - throw new IllegalArgumentException("resize() can only be used to shrink the dictionary"); - } - if (length < 1) { - throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher"); - } - - String[] newKeys = new String[length]; - float[] newValues = new float[length]; - PApplet.arrayCopy(keys, newKeys, length); - PApplet.arrayCopy(values, newValues, length); - keys = newKeys; - values = newValues; - count = length; - resetIndices(); - } - - - /** - * Remove all entries. - * - * @webref floatdict:method - * @brief Remove all entries - */ - public void clear() { - count = 0; - indices = new HashMap<>(); - } - - - private void resetIndices() { - indices = new HashMap<>(count); - for (int i = 0; i < count; i++) { - indices.put(keys[i], i); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public class Entry { - public String key; - public float value; - - Entry(String key, float value) { - this.key = key; - this.value = value; - } - } - - - public Iterable entries() { - return new Iterable() { - - public Iterator iterator() { - return entryIterator(); - } - }; - } - - - public Iterator entryIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public Entry next() { - ++index; - Entry e = new Entry(keys[index], values[index]); - return e; - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public String key(int index) { - return keys[index]; - } - - - protected void crop() { - if (count != keys.length) { - keys = PApplet.subset(keys, 0, count); - values = PApplet.subset(values, 0, count); - } - } - - - public Iterable keys() { - return new Iterable() { - - @Override - public Iterator iterator() { - return keyIterator(); - } - }; - } - - - // Use this to iterate when you want to be able to remove elements along the way - public Iterator keyIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public String next() { - return key(++index); - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - /** - * Return a copy of the internal keys array. This array can be modified. - * - * @webref floatdict:method - * @brief Return a copy of the internal keys array - */ - public String[] keyArray() { - crop(); - return keyArray(null); - } - - - public String[] keyArray(String[] outgoing) { - if (outgoing == null || outgoing.length != count) { - outgoing = new String[count]; - } - System.arraycopy(keys, 0, outgoing, 0, count); - return outgoing; - } - - - public float value(int index) { - return values[index]; - } - - - /** - * @webref floatdict:method - * @brief Return the internal array being used to store the values - */ - public Iterable values() { - return new Iterable() { - - @Override - public Iterator iterator() { - return valueIterator(); - } - }; - } - - - public Iterator valueIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public Float next() { - return value(++index); - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - /** - * Create a new array and copy each of the values into it. - * - * @webref floatdict:method - * @brief Create a new array and copy each of the values into it - */ - public float[] valueArray() { - crop(); - return valueArray(null); - } - - - /** - * Fill an already-allocated array with the values (more efficient than - * creating a new array each time). If 'array' is null, or not the same - * size as the number of values, a new array will be allocated and returned. - */ - public float[] valueArray(float[] array) { - if (array == null || array.length != size()) { - array = new float[count]; - } - System.arraycopy(values, 0, array, 0, count); - return array; - } - - - /** - * Return a value for the specified key. - * - * @webref floatdict:method - * @brief Return a value for the specified key - */ - public float get(String key) { - int index = index(key); - if (index == -1) { - throw new IllegalArgumentException("No key named '" + key + "'"); - } - return values[index]; - } - - - public float get(String key, float alternate) { - int index = index(key); - if (index == -1) { - return alternate; - } - return values[index]; - } - - - /** - * @webref floatdict:method - * @brief Create a new key/value pair or change the value of one - */ - public void set(String key, float amount) { - int index = index(key); - if (index == -1) { - create(key, amount); - } else { - values[index] = amount; - } - } - - - public void setIndex(int index, String key, float value) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - keys[index] = key; - values[index] = value; - } - - - /** - * @webref floatdict:method - * @brief Check if a key is a part of the data structure - */ - public boolean hasKey(String key) { - return index(key) != -1; - } - - - /** - * @webref floatdict:method - * @brief Add to a value - */ - public void add(String key, float amount) { - int index = index(key); - if (index == -1) { - create(key, amount); - } else { - values[index] += amount; - } - } - - - /** - * @webref floatdict:method - * @brief Subtract from a value - */ - public void sub(String key, float amount) { - add(key, -amount); - } - - - /** - * @webref floatdict:method - * @brief Multiply a value - */ - public void mult(String key, float amount) { - int index = index(key); - if (index != -1) { - values[index] *= amount; - } - } - - - /** - * @webref floatdict:method - * @brief Divide a value - */ - public void div(String key, float amount) { - int index = index(key); - if (index != -1) { - values[index] /= amount; - } - } - - - private void checkMinMax(String functionName) { - if (count == 0) { - String msg = - String.format("Cannot use %s() on an empty %s.", - functionName, getClass().getSimpleName()); - throw new RuntimeException(msg); - } - } - - - /** - * @webref floatlist:method - * @brief Return the smallest value - */ - public int minIndex() { - //checkMinMax("minIndex"); - if (count == 0) return -1; - - // Will still return NaN if there are 1 or more entries, and they're all NaN - float m = Float.NaN; - int mi = -1; - for (int i = 0; i < count; i++) { - // find one good value to start - if (values[i] == values[i]) { - m = values[i]; - mi = i; - - // calculate the rest - for (int j = i+1; j < count; j++) { - float d = values[j]; - if ((d == d) && (d < m)) { - m = values[j]; - mi = j; - } - } - break; - } - } - return mi; - } - - - // return the key for the minimum value - public String minKey() { - checkMinMax("minKey"); - int index = minIndex(); - if (index == -1) { - return null; - } - return keys[index]; - } - - - // return the minimum value, or throw an error if there are no values - public float minValue() { - checkMinMax("minValue"); - int index = minIndex(); - if (index == -1) { - return Float.NaN; - } - return values[index]; - } - - - /** - * @webref floatlist:method - * @brief Return the largest value - */ - // The index of the entry that has the max value. Reference above is incorrect. - public int maxIndex() { - //checkMinMax("maxIndex"); - if (count == 0) { - return -1; - } - // Will still return NaN if there is 1 or more entries, and they're all NaN - float m = Float.NaN; - int mi = -1; - for (int i = 0; i < count; i++) { - // find one good value to start - if (values[i] == values[i]) { - m = values[i]; - mi = i; - - // calculate the rest - for (int j = i+1; j < count; j++) { - float d = values[j]; - if (!Float.isNaN(d) && (d > m)) { - m = values[j]; - mi = j; - } - } - break; - } - } - return mi; - } - - - /** The key for a max value; null if empty or everything is NaN (no max). */ - public String maxKey() { - //checkMinMax("maxKey"); - int index = maxIndex(); - if (index == -1) { - return null; - } - return keys[index]; - } - - - /** The max value. (Or NaN if no entries or they're all NaN.) */ - public float maxValue() { - //checkMinMax("maxValue"); - int index = maxIndex(); - if (index == -1) { - return Float.NaN; - } - return values[index]; - } - - - public float sum() { - double amount = sumDouble(); - if (amount > Float.MAX_VALUE) { - throw new RuntimeException("sum() exceeds " + Float.MAX_VALUE + ", use sumDouble()"); - } - if (amount < -Float.MAX_VALUE) { - throw new RuntimeException("sum() lower than " + -Float.MAX_VALUE + ", use sumDouble()"); - } - return (float) amount; - } - - - public double sumDouble() { - double sum = 0; - for (int i = 0; i < count; i++) { - sum += values[i]; - } - return sum; - } - - - public int index(String what) { - Integer found = indices.get(what); - return (found == null) ? -1 : found.intValue(); - } - - - protected void create(String what, float much) { - if (count == keys.length) { - keys = PApplet.expand(keys); - values = PApplet.expand(values); - } - indices.put(what, Integer.valueOf(count)); - keys[count] = what; - values[count] = much; - count++; - } - - - /** - * @webref floatdict:method - * @brief Remove a key/value pair - */ - public float remove(String key) { - int index = index(key); - if (index == -1) { - throw new NoSuchElementException("'" + key + "' not found"); - } - float value = values[index]; - removeIndex(index); - return value; - } - - - public float removeIndex(int index) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - float value = values[index]; - indices.remove(keys[index]); - for (int i = index; i < count-1; i++) { - keys[i] = keys[i+1]; - values[i] = values[i+1]; - indices.put(keys[i], i); - } - count--; - keys[count] = null; - values[count] = 0; - return value; - } - - - public void swap(int a, int b) { - String tkey = keys[a]; - float tvalue = values[a]; - keys[a] = keys[b]; - values[a] = values[b]; - keys[b] = tkey; - values[b] = tvalue; - -// indices.put(keys[a], Integer.valueOf(a)); -// indices.put(keys[b], Integer.valueOf(b)); - } - - - /** - * Sort the keys alphabetically (ignoring case). Uses the value as a - * tie-breaker (only really possible with a key that has a case change). - * - * @webref floatdict:method - * @brief Sort the keys alphabetically - */ - public void sortKeys() { - sortImpl(true, false, true); - } - - - /** - * @webref floatdict:method - * @brief Sort the keys alphabetically in reverse - */ - public void sortKeysReverse() { - sortImpl(true, true, true); - } - - - /** - * Sort by values in descending order (largest value will be at [0]). - * - * @webref floatdict:method - * @brief Sort by values in ascending order - */ - public void sortValues() { - sortValues(true); - } - - - /** - * Set true to ensure that the order returned is identical. Slightly - * slower because the tie-breaker for identical values compares the keys. - * @param stable - */ - public void sortValues(boolean stable) { - sortImpl(false, false, stable); - } - - - /** - * @webref floatdict:method - * @brief Sort by values in descending order - */ - public void sortValuesReverse() { - sortValuesReverse(true); - } - - - public void sortValuesReverse(boolean stable) { - sortImpl(false, true, stable); - } - - - protected void sortImpl(final boolean useKeys, final boolean reverse, - final boolean stable) { - Sort s = new Sort() { - @Override - public int size() { - if (useKeys) { - return count; // don't worry about NaN values - - } else if (count == 0) { // skip the NaN check, it'll AIOOBE - return 0; - - } else { // first move NaN values to the end of the list - int right = count - 1; - while (values[right] != values[right]) { - right--; - if (right == -1) { - return 0; // all values are NaN - } - } - for (int i = right; i >= 0; --i) { - if (Float.isNaN(values[i])) { - swap(i, right); - --right; - } - } - return right + 1; - } - } - - @Override - public int compare(int a, int b) { - float diff = 0; - if (useKeys) { - diff = keys[a].compareToIgnoreCase(keys[b]); - if (diff == 0) { - diff = values[a] - values[b]; - } - } else { // sort values - diff = values[a] - values[b]; - if (diff == 0 && stable) { - diff = keys[a].compareToIgnoreCase(keys[b]); - } - } - if (diff == 0) { - return 0; - } else if (reverse) { - return diff < 0 ? 1 : -1; - } else { - return diff < 0 ? -1 : 1; - } - } - - @Override - public void swap(int a, int b) { - FloatDict.this.swap(a, b); - } - }; - s.run(); - - // Set the indices after sort/swaps (performance fix 160411) - resetIndices(); - } - - - /** - * Sum all of the values in this dictionary, then return a new FloatDict of - * each key, divided by the total sum. The total for all values will be ~1.0. - * @return a FloatDict with the original keys, mapped to their pct of the total - */ - public FloatDict getPercent() { - double sum = sum(); - FloatDict outgoing = new FloatDict(); - for (int i = 0; i < size(); i++) { - double percent = value(i) / sum; - outgoing.set(key(i), (float) percent); - } - return outgoing; - } - - - /** Returns a duplicate copy of this object. */ - public FloatDict copy() { - FloatDict outgoing = new FloatDict(count); - System.arraycopy(keys, 0, outgoing.keys, 0, count); - System.arraycopy(values, 0, outgoing.values, 0, count); - for (int i = 0; i < count; i++) { - outgoing.indices.put(keys[i], i); - } - outgoing.count = count; - return outgoing; - } - - - public void print() { - for (int i = 0; i < size(); i++) { - System.out.println(keys[i] + " = " + values[i]); - } - } - - - /** - * Save tab-delimited entries to a file (TSV format, UTF-8 encoding) - */ - public void save(File file) { - PrintWriter writer = PApplet.createWriter(file); - write(writer); - writer.close(); - } - - - /** - * Write tab-delimited entries out to - * @param writer - */ - public void write(PrintWriter writer) { - for (int i = 0; i < count; i++) { - writer.println(keys[i] + "\t" + values[i]); - } - writer.flush(); - } - - - /** - * Return this dictionary as a String in JSON format. - */ - public String toJSON() { - StringList items = new StringList(); - for (int i = 0; i < count; i++) { - items.append(JSONObject.quote(keys[i])+ ": " + values[i]); - } - return "{ " + items.join(", ") + " }"; - } - - - @Override - public String toString() { - return getClass().getSimpleName() + " size=" + size() + " " + toJSON(); - } -} diff --git a/core/src/processing/data/FloatList.java b/core/src/processing/data/FloatList.java deleted file mode 100644 index 863b05658..000000000 --- a/core/src/processing/data/FloatList.java +++ /dev/null @@ -1,936 +0,0 @@ -package processing.data; - -import java.io.File; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Random; - -import processing.core.PApplet; - - -/** - * Helper class for a list of floats. Lists are designed to have some of the - * features of ArrayLists, but to maintain the simplicity and efficiency of - * working with arrays. - * - * Functions like sort() and shuffle() always act on the list itself. To get - * a sorted copy, use list.copy().sort(). - * - * @webref data:composite - * @see IntList - * @see StringList - */ -public class FloatList implements Iterable { - int count; - float[] data; - - - public FloatList() { - data = new float[10]; - } - - - /** - * @nowebref - */ - public FloatList(int length) { - data = new float[length]; - } - - - /** - * @nowebref - */ - public FloatList(float[] list) { - count = list.length; - data = new float[count]; - System.arraycopy(list, 0, data, 0, count); - } - - - /** - * Construct an FloatList from an iterable pile of objects. - * For instance, a float array, an array of strings, who knows). - * Un-parseable or null values will be set to NaN. - * @nowebref - */ - public FloatList(Iterable iter) { - this(10); - for (Object o : iter) { - if (o == null) { - append(Float.NaN); - } else if (o instanceof Number) { - append(((Number) o).floatValue()); - } else { - append(PApplet.parseFloat(o.toString().trim())); - } - } - crop(); - } - - - /** - * Construct an FloatList from a random pile of objects. - * Un-parseable or null values will be set to NaN. - */ - public FloatList(Object... items) { - // nuts, no good way to pass missingValue to this fn (varargs must be last) - final float missingValue = Float.NaN; - - count = items.length; - data = new float[count]; - int index = 0; - for (Object o : items) { - float value = missingValue; - if (o != null) { - if (o instanceof Number) { - value = ((Number) o).floatValue(); - } else { - value = PApplet.parseFloat(o.toString().trim(), missingValue); - } - } - data[index++] = value; - } - } - - - /** - * Improve efficiency by removing allocated but unused entries from the - * internal array used to store the data. Set to private, though it could - * be useful to have this public if lists are frequently making drastic - * size changes (from very large to very small). - */ - private void crop() { - if (count != data.length) { - data = PApplet.subset(data, 0, count); - } - } - - - /** - * Get the length of the list. - * - * @webref floatlist:method - * @brief Get the length of the list - */ - public int size() { - return count; - } - - - public void resize(int length) { - if (length > data.length) { - float[] temp = new float[length]; - System.arraycopy(data, 0, temp, 0, count); - data = temp; - - } else if (length > count) { - Arrays.fill(data, count, length, 0); - } - count = length; - } - - - /** - * Remove all entries from the list. - * - * @webref floatlist:method - * @brief Remove all entries from the list - */ - public void clear() { - count = 0; - } - - - /** - * Get an entry at a particular index. - * - * @webref floatlist:method - * @brief Get an entry at a particular index - */ - public float get(int index) { - if (index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - return data[index]; - } - - - /** - * Set the entry at a particular index. If the index is past the length of - * the list, it'll expand the list to accommodate, and fill the intermediate - * entries with 0s. - * - * @webref floatlist:method - * @brief Set the entry at a particular index - */ - public void set(int index, float what) { - if (index >= count) { - data = PApplet.expand(data, index+1); - for (int i = count; i < index; i++) { - data[i] = 0; - } - count = index+1; - } - data[index] = what; - } - - - /** Just an alias for append(), but matches pop() */ - public void push(float value) { - append(value); - } - - - public float pop() { - if (count == 0) { - throw new RuntimeException("Can't call pop() on an empty list"); - } - float value = get(count-1); - count--; - return value; - } - - - /** - * Remove an element from the specified index. - * - * @webref floatlist:method - * @brief Remove an element from the specified index - */ - public float remove(int index) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - float entry = data[index]; -// int[] outgoing = new int[count - 1]; -// System.arraycopy(data, 0, outgoing, 0, index); -// count--; -// System.arraycopy(data, index + 1, outgoing, 0, count - index); -// data = outgoing; - // For most cases, this actually appears to be faster - // than arraycopy() on an array copying into itself. - for (int i = index; i < count-1; i++) { - data[i] = data[i+1]; - } - count--; - return entry; - } - - - // Remove the first instance of a particular value, - // and return the index at which it was found. - public int removeValue(int value) { - int index = index(value); - if (index != -1) { - remove(index); - return index; - } - return -1; - } - - - // Remove all instances of a particular value, - // and return the number of values found and removed - public int removeValues(int value) { - int ii = 0; - if (Float.isNaN(value)) { - for (int i = 0; i < count; i++) { - if (!Float.isNaN(data[i])) { - data[ii++] = data[i]; - } - } - } else { - for (int i = 0; i < count; i++) { - if (data[i] != value) { - data[ii++] = data[i]; - } - } - } - int removed = count - ii; - count = ii; - return removed; - } - - - /** Replace the first instance of a particular value */ - public boolean replaceValue(float value, float newValue) { - if (Float.isNaN(value)) { - for (int i = 0; i < count; i++) { - if (Float.isNaN(data[i])) { - data[i] = newValue; - return true; - } - } - } else { - int index = index(value); - if (index != -1) { - data[index] = newValue; - return true; - } - } - return false; - } - - - /** Replace all instances of a particular value */ - public boolean replaceValues(float value, float newValue) { - boolean changed = false; - if (Float.isNaN(value)) { - for (int i = 0; i < count; i++) { - if (Float.isNaN(data[i])) { - data[i] = newValue; - changed = true; - } - } - } else { - for (int i = 0; i < count; i++) { - if (data[i] == value) { - data[i] = newValue; - changed = true; - } - } - } - return changed; - } - - - - /** - * Add a new entry to the list. - * - * @webref floatlist:method - * @brief Add a new entry to the list - */ - public void append(float value) { - if (count == data.length) { - data = PApplet.expand(data); - } - data[count++] = value; - } - - - public void append(float[] values) { - for (float v : values) { - append(v); - } - } - - - public void append(FloatList list) { - for (float v : list.values()) { // will concat the list... - append(v); - } - } - - - /** Add this value, but only if it's not already in the list. */ - public void appendUnique(float value) { - if (!hasValue(value)) { - append(value); - } - } - - -// public void insert(int index, int value) { -// if (index+1 > count) { -// if (index+1 < data.length) { -// } -// } -// if (index >= data.length) { -// data = PApplet.expand(data, index+1); -// data[index] = value; -// count = index+1; -// -// } else if (count == data.length) { -// if (index >= count) { -// //int[] temp = new int[count << 1]; -// System.arraycopy(data, 0, temp, 0, index); -// temp[index] = value; -// System.arraycopy(data, index, temp, index+1, count - index); -// data = temp; -// -// } else { -// // data[] has room to grow -// // for() loop believed to be faster than System.arraycopy over itself -// for (int i = count; i > index; --i) { -// data[i] = data[i-1]; -// } -// data[index] = value; -// count++; -// } -// } - - - public void insert(int index, float value) { - insert(index, new float[] { value }); - } - - - // same as splice - public void insert(int index, float[] values) { - if (index < 0) { - throw new IllegalArgumentException("insert() index cannot be negative: it was " + index); - } - if (index >= data.length) { - throw new IllegalArgumentException("insert() index " + index + " is past the end of this list"); - } - - float[] temp = new float[count + values.length]; - - // Copy the old values, but not more than already exist - System.arraycopy(data, 0, temp, 0, Math.min(count, index)); - - // Copy the new values into the proper place - System.arraycopy(values, 0, temp, index, values.length); - -// if (index < count) { - // The index was inside count, so it's a true splice/insert - System.arraycopy(data, index, temp, index+values.length, count - index); - count = count + values.length; -// } else { -// // The index was past 'count', so the new count is weirder -// count = index + values.length; -// } - data = temp; - } - - - public void insert(int index, FloatList list) { - insert(index, list.values()); - } - - - // below are aborted attempts at more optimized versions of the code - // that are harder to read and debug... - -// if (index + values.length >= count) { -// // We're past the current 'count', check to see if we're still allocated -// // index 9, data.length = 10, values.length = 1 -// if (index + values.length < data.length) { -// // There's still room for these entries, even though it's past 'count'. -// // First clear out the entries leading up to it, however. -// for (int i = count; i < index; i++) { -// data[i] = 0; -// } -// data[index] = -// } -// if (index >= data.length) { -// int length = index + values.length; -// int[] temp = new int[length]; -// System.arraycopy(data, 0, temp, 0, count); -// System.arraycopy(values, 0, temp, index, values.length); -// data = temp; -// count = data.length; -// } else { -// -// } -// -// } else if (count == data.length) { -// int[] temp = new int[count << 1]; -// System.arraycopy(data, 0, temp, 0, index); -// temp[index] = value; -// System.arraycopy(data, index, temp, index+1, count - index); -// data = temp; -// -// } else { -// // data[] has room to grow -// // for() loop believed to be faster than System.arraycopy over itself -// for (int i = count; i > index; --i) { -// data[i] = data[i-1]; -// } -// data[index] = value; -// count++; -// } - - - /** Return the first index of a particular value. */ - public int index(float what) { - /* - if (indexCache != null) { - try { - return indexCache.get(what); - } catch (Exception e) { // not there - return -1; - } - } - */ - for (int i = 0; i < count; i++) { - if (data[i] == what) { - return i; - } - } - return -1; - } - - - /** - * @webref floatlist:method - * @brief Check if a number is a part of the list - */ - public boolean hasValue(float value) { - if (Float.isNaN(value)) { - for (int i = 0; i < count; i++) { - if (Float.isNaN(data[i])) { - return true; - } - } - } else { - for (int i = 0; i < count; i++) { - if (data[i] == value) { - return true; - } - } - } - return false; - } - - - private void boundsProblem(int index, String method) { - final String msg = String.format("The list size is %d. " + - "You cannot %s() to element %d.", count, method, index); - throw new ArrayIndexOutOfBoundsException(msg); - } - - - /** - * @webref floatlist:method - * @brief Add to a value - */ - public void add(int index, float amount) { - if (index < count) { - data[index] += amount; - } else { - boundsProblem(index, "add"); - } - } - - - /** - * @webref floatlist:method - * @brief Subtract from a value - */ - public void sub(int index, float amount) { - if (index < count) { - data[index] -= amount; - } else { - boundsProblem(index, "sub"); - } - } - - - /** - * @webref floatlist:method - * @brief Multiply a value - */ - public void mult(int index, float amount) { - if (index < count) { - data[index] *= amount; - } else { - boundsProblem(index, "mult"); - } - } - - - /** - * @webref floatlist:method - * @brief Divide a value - */ - public void div(int index, float amount) { - if (index < count) { - data[index] /= amount; - } else { - boundsProblem(index, "div"); - } - } - - - private void checkMinMax(String functionName) { - if (count == 0) { - String msg = - String.format("Cannot use %s() on an empty %s.", - functionName, getClass().getSimpleName()); - throw new RuntimeException(msg); - } - } - - - /** - * @webref floatlist:method - * @brief Return the smallest value - */ - public float min() { - checkMinMax("min"); - int index = minIndex(); - return index == -1 ? Float.NaN : data[index]; - } - - - public int minIndex() { - checkMinMax("minIndex"); - float m = Float.NaN; - int mi = -1; - for (int i = 0; i < count; i++) { - // find one good value to start - if (data[i] == data[i]) { - m = data[i]; - mi = i; - - // calculate the rest - for (int j = i+1; j < count; j++) { - float d = data[j]; - if (!Float.isNaN(d) && (d < m)) { - m = data[j]; - mi = j; - } - } - break; - } - } - return mi; - } - - - /** - * @webref floatlist:method - * @brief Return the largest value - */ - public float max() { - checkMinMax("max"); - int index = maxIndex(); - return index == -1 ? Float.NaN : data[index]; - } - - - public int maxIndex() { - checkMinMax("maxIndex"); - float m = Float.NaN; - int mi = -1; - for (int i = 0; i < count; i++) { - // find one good value to start - if (data[i] == data[i]) { - m = data[i]; - mi = i; - - // calculate the rest - for (int j = i+1; j < count; j++) { - float d = data[j]; - if (!Float.isNaN(d) && (d > m)) { - m = data[j]; - mi = j; - } - } - break; - } - } - return mi; - } - - - public float sum() { - double amount = sumDouble(); - if (amount > Float.MAX_VALUE) { - throw new RuntimeException("sum() exceeds " + Float.MAX_VALUE + ", use sumDouble()"); - } - if (amount < -Float.MAX_VALUE) { - throw new RuntimeException("sum() lower than " + -Float.MAX_VALUE + ", use sumDouble()"); - } - return (float) amount; - } - - - public double sumDouble() { - double sum = 0; - for (int i = 0; i < count; i++) { - sum += data[i]; - } - return sum; - } - - - /** - * Sorts the array in place. - * - * @webref floatlist:method - * @brief Sorts an array, lowest to highest - */ - public void sort() { - Arrays.sort(data, 0, count); - } - - - /** - * Reverse sort, orders values from highest to lowest - * - * @webref floatlist:method - * @brief Reverse sort, orders values from highest to lowest - */ - public void sortReverse() { - new Sort() { - @Override - public int size() { - // if empty, don't even mess with the NaN check, it'll AIOOBE - if (count == 0) { - return 0; - } - // move NaN values to the end of the list and don't sort them - int right = count - 1; - while (data[right] != data[right]) { - right--; - if (right == -1) { // all values are NaN - return 0; - } - } - for (int i = right; i >= 0; --i) { - float v = data[i]; - if (v != v) { - data[i] = data[right]; - data[right] = v; - --right; - } - } - return right + 1; - } - - @Override - public int compare(int a, int b) { - float diff = data[b] - data[a]; - return diff == 0 ? 0 : (diff < 0 ? -1 : 1); - } - - @Override - public void swap(int a, int b) { - float temp = data[a]; - data[a] = data[b]; - data[b] = temp; - } - }.run(); - } - - - // use insert() -// public void splice(int index, int value) { -// } - - -// public void subset(int start) { -// subset(start, count - start); -// } - - -// public void subset(int start, int num) { -// for (int i = 0; i < num; i++) { -// data[i] = data[i+start]; -// } -// count = num; -// } - - - /** - * @webref floatlist:method - * @brief Reverse the order of the list elements - */ - public void reverse() { - int ii = count - 1; - for (int i = 0; i < count/2; i++) { - float t = data[i]; - data[i] = data[ii]; - data[ii] = t; - --ii; - } - } - - - /** - * Randomize the order of the list elements. Note that this does not - * obey the randomSeed() function in PApplet. - * - * @webref floatlist:method - * @brief Randomize the order of the list elements - */ - public void shuffle() { - Random r = new Random(); - int num = count; - while (num > 1) { - int value = r.nextInt(num); - num--; - float temp = data[num]; - data[num] = data[value]; - data[value] = temp; - } - } - - - /** - * Randomize the list order using the random() function from the specified - * sketch, allowing shuffle() to use its current randomSeed() setting. - */ - public void shuffle(PApplet sketch) { - int num = count; - while (num > 1) { - int value = (int) sketch.random(num); - num--; - float temp = data[num]; - data[num] = data[value]; - data[value] = temp; - } - } - - - public FloatList copy() { - FloatList outgoing = new FloatList(data); - outgoing.count = count; - return outgoing; - } - - - /** - * Returns the actual array being used to store the data. For advanced users, - * this is the fastest way to access a large list. Suitable for iterating - * with a for() loop, but modifying the list will have terrible consequences. - */ - public float[] values() { - crop(); - return data; - } - - - /** Implemented this way so that we can use a FloatList in a for loop. */ - @Override - public Iterator iterator() { -// } -// -// -// public Iterator valueIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - FloatList.this.remove(index); - index--; - } - - public Float next() { - return data[++index]; - } - - public boolean hasNext() { - return index+1 < count; - } - }; - } - - - /** - * Create a new array with a copy of all the values. - * @return an array sized by the length of the list with each of the values. - * @webref floatlist:method - * @brief Create a new array with a copy of all the values - */ - public float[] array() { - return array(null); - } - - - /** - * Copy values into the specified array. If the specified array is null or - * not the same size, a new array will be allocated. - * @param array - */ - public float[] array(float[] array) { - if (array == null || array.length != count) { - array = new float[count]; - } - System.arraycopy(data, 0, array, 0, count); - return array; - } - - - /** - * Returns a normalized version of this array. Called getPercent() for - * consistency with the Dict classes. It's a getter method because it needs - * to returns a new list (because IntList/Dict can't do percentages or - * normalization in place on int values). - */ - public FloatList getPercent() { - double sum = 0; - for (float value : array()) { - sum += value; - } - FloatList outgoing = new FloatList(count); - for (int i = 0; i < count; i++) { - double percent = data[i] / sum; - outgoing.set(i, (float) percent); - } - return outgoing; - } - - - public FloatList getSubset(int start) { - return getSubset(start, count - start); - } - - - public FloatList getSubset(int start, int num) { - float[] subset = new float[num]; - System.arraycopy(data, start, subset, 0, num); - return new FloatList(subset); - } - - - public String join(String separator) { - if (count == 0) { - return ""; - } - StringBuilder sb = new StringBuilder(); - sb.append(data[0]); - for (int i = 1; i < count; i++) { - sb.append(separator); - sb.append(data[i]); - } - return sb.toString(); - } - - - public void print() { - for (int i = 0; i < count; i++) { - System.out.format("[%d] %f%n", i, data[i]); - } - } - - - /** - * Save tab-delimited entries to a file (TSV format, UTF-8 encoding) - */ - public void save(File file) { - PrintWriter writer = PApplet.createWriter(file); - write(writer); - writer.close(); - } - - - /** - * Write entries to a PrintWriter, one per line - */ - public void write(PrintWriter writer) { - for (int i = 0; i < count; i++) { - writer.println(data[i]); - } - writer.flush(); - } - - - /** - * Return this dictionary as a String in JSON format. - */ - public String toJSON() { - return "[ " + join(", ") + " ]"; - } - - - @Override - public String toString() { - return getClass().getSimpleName() + " size=" + size() + " " + toJSON(); - } -} diff --git a/core/src/processing/data/IntDict.java b/core/src/processing/data/IntDict.java deleted file mode 100644 index 96913591f..000000000 --- a/core/src/processing/data/IntDict.java +++ /dev/null @@ -1,807 +0,0 @@ -package processing.data; - -import java.io.*; -import java.util.HashMap; -import java.util.Iterator; -import java.util.NoSuchElementException; - -import processing.core.PApplet; - - -/** - * A simple class to use a String as a lookup for an int value. - * - * @webref data:composite - * @see FloatDict - * @see StringDict - */ -public class IntDict { - - /** Number of elements in the table */ - protected int count; - - protected String[] keys; - protected int[] values; - - /** Internal implementation for faster lookups */ - private HashMap indices = new HashMap<>(); - - - public IntDict() { - count = 0; - keys = new String[10]; - values = new int[10]; - } - - - /** - * Create a new lookup with a specific size. This is more efficient than not - * specifying a size. Use it when you know the rough size of the thing you're creating. - * - * @nowebref - */ - public IntDict(int length) { - count = 0; - keys = new String[length]; - values = new int[length]; - } - - - /** - * Read a set of entries from a Reader that has each key/value pair on - * a single line, separated by a tab. - * - * @nowebref - */ - public IntDict(BufferedReader reader) { - String[] lines = PApplet.loadStrings(reader); - keys = new String[lines.length]; - values = new int[lines.length]; - - for (int i = 0; i < lines.length; i++) { - String[] pieces = PApplet.split(lines[i], '\t'); - if (pieces.length == 2) { - keys[count] = pieces[0]; - values[count] = PApplet.parseInt(pieces[1]); - indices.put(pieces[0], count); - count++; - } - } - } - - /** - * @nowebref - */ - public IntDict(String[] keys, int[] values) { - if (keys.length != values.length) { - throw new IllegalArgumentException("key and value arrays must be the same length"); - } - this.keys = keys; - this.values = values; - count = keys.length; - for (int i = 0; i < count; i++) { - indices.put(keys[i], i); - } - } - - - /** - * Constructor to allow (more intuitive) inline initialization, e.g.: - *
    -   * new FloatDict(new Object[][] {
    -   *   { "key1", 1 },
    -   *   { "key2", 2 }
    -   * });
    -   * 
    - */ - public IntDict(Object[][] pairs) { - count = pairs.length; - this.keys = new String[count]; - this.values = new int[count]; - for (int i = 0; i < count; i++) { - keys[i] = (String) pairs[i][0]; - values[i] = (Integer) pairs[i][1]; - indices.put(keys[i], i); - } - } - - - /** - * Returns the number of key/value pairs - * - * @webref intdict:method - * @brief Returns the number of key/value pairs - */ - public int size() { - return count; - } - - - /** - * Resize the internal data, this can only be used to shrink the list. - * Helpful for situations like sorting and then grabbing the top 50 entries. - */ - public void resize(int length) { - if (length > count) { - throw new IllegalArgumentException("resize() can only be used to shrink the dictionary"); - } - if (length < 1) { - throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher"); - } - - String[] newKeys = new String[length]; - int[] newValues = new int[length]; - PApplet.arrayCopy(keys, newKeys, length); - PApplet.arrayCopy(values, newValues, length); - keys = newKeys; - values = newValues; - count = length; - resetIndices(); - } - - - /** - * Remove all entries. - * - * @webref intdict:method - * @brief Remove all entries - */ - public void clear() { - count = 0; - indices = new HashMap<>(); - } - - - private void resetIndices() { - indices = new HashMap<>(count); - for (int i = 0; i < count; i++) { - indices.put(keys[i], i); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public class Entry { - public String key; - public int value; - - Entry(String key, int value) { - this.key = key; - this.value = value; - } - } - - - public Iterable entries() { - return new Iterable() { - - public Iterator iterator() { - return entryIterator(); - } - }; - } - - - public Iterator entryIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public Entry next() { - ++index; - Entry e = new Entry(keys[index], values[index]); - return e; - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public String key(int index) { - return keys[index]; - } - - - protected void crop() { - if (count != keys.length) { - keys = PApplet.subset(keys, 0, count); - values = PApplet.subset(values, 0, count); - } - } - - - public Iterable keys() { - return new Iterable() { - - @Override - public Iterator iterator() { - return keyIterator(); - } - }; - } - - - // Use this to iterate when you want to be able to remove elements along the way - public Iterator keyIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public String next() { - return key(++index); - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - /** - * Return a copy of the internal keys array. This array can be modified. - * - * @webref intdict:method - * @brief Return a copy of the internal keys array - */ - public String[] keyArray() { - crop(); - return keyArray(null); - } - - - public String[] keyArray(String[] outgoing) { - if (outgoing == null || outgoing.length != count) { - outgoing = new String[count]; - } - System.arraycopy(keys, 0, outgoing, 0, count); - return outgoing; - } - - - public int value(int index) { - return values[index]; - } - - - /** - * @webref intdict:method - * @brief Return the internal array being used to store the values - */ - public Iterable values() { - return new Iterable() { - - @Override - public Iterator iterator() { - return valueIterator(); - } - }; - } - - - public Iterator valueIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public Integer next() { - return value(++index); - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - /** - * Create a new array and copy each of the values into it. - * - * @webref intdict:method - * @brief Create a new array and copy each of the values into it - */ - public int[] valueArray() { - crop(); - return valueArray(null); - } - - - /** - * Fill an already-allocated array with the values (more efficient than - * creating a new array each time). If 'array' is null, or not the same - * size as the number of values, a new array will be allocated and returned. - * - * @param array values to copy into the array - */ - public int[] valueArray(int[] array) { - if (array == null || array.length != size()) { - array = new int[count]; - } - System.arraycopy(values, 0, array, 0, count); - return array; - } - - - /** - * Return a value for the specified key. - * - * @webref intdict:method - * @brief Return a value for the specified key - */ - public int get(String key) { - int index = index(key); - if (index == -1) { - throw new IllegalArgumentException("No key named '" + key + "'"); - } - return values[index]; - } - - - public int get(String key, int alternate) { - int index = index(key); - if (index == -1) return alternate; - return values[index]; - } - - - /** - * Create a new key/value pair or change the value of one. - * - * @webref intdict:method - * @brief Create a new key/value pair or change the value of one - */ - public void set(String key, int amount) { - int index = index(key); - if (index == -1) { - create(key, amount); - } else { - values[index] = amount; - } - } - - - public void setIndex(int index, String key, int value) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - keys[index] = key; - values[index] = value; - } - - - /** - * @webref intdict:method - * @brief Check if a key is a part of the data structure - */ - public boolean hasKey(String key) { - return index(key) != -1; - } - - - /** - * Increase the value associated with a specific key by 1. - * - * @webref intdict:method - * @brief Increase the value of a specific key value by 1 - */ - public void increment(String key) { - add(key, 1); - } - - - /** - * Merge another dictionary into this one. Calling this increment() - * since it doesn't make sense in practice for the other dictionary types, - * even though it's technically an add(). - */ - public void increment(IntDict dict) { - for (int i = 0; i < dict.count; i++) { - add(dict.key(i), dict.value(i)); - } - } - - - /** - * @webref intdict:method - * @brief Add to a value - */ - public void add(String key, int amount) { - int index = index(key); - if (index == -1) { - create(key, amount); - } else { - values[index] += amount; - } - } - - - /** - * @webref intdict:method - * @brief Subtract from a value - */ - public void sub(String key, int amount) { - add(key, -amount); - } - - - /** - * @webref intdict:method - * @brief Multiply a value - */ - public void mult(String key, int amount) { - int index = index(key); - if (index != -1) { - values[index] *= amount; - } - } - - - /** - * @webref intdict:method - * @brief Divide a value - */ - public void div(String key, int amount) { - int index = index(key); - if (index != -1) { - values[index] /= amount; - } - } - - - private void checkMinMax(String functionName) { - if (count == 0) { - String msg = - String.format("Cannot use %s() on an empty %s.", - functionName, getClass().getSimpleName()); - throw new RuntimeException(msg); - } - } - - - // return the index of the minimum value - public int minIndex() { - //checkMinMax("minIndex"); - if (count == 0) return -1; - - int index = 0; - int value = values[0]; - for (int i = 1; i < count; i++) { - if (values[i] < value) { - index = i; - value = values[i]; - } - } - return index; - } - - - // return the key for the minimum value - public String minKey() { - checkMinMax("minKey"); - int index = minIndex(); - if (index == -1) { - return null; - } - return keys[index]; - } - - - // return the minimum value, or throw an error if there are no values - public int minValue() { - checkMinMax("minValue"); - return values[minIndex()]; - } - - - // return the index of the max value - public int maxIndex() { - //checkMinMax("maxIndex"); - if (count == 0) { - return -1; - } - int index = 0; - int value = values[0]; - for (int i = 1; i < count; i++) { - if (values[i] > value) { - index = i; - value = values[i]; - } - } - return index; - } - - - /** return the key corresponding to the maximum value or null if no entries */ - public String maxKey() { - //checkMinMax("maxKey"); - int index = maxIndex(); - if (index == -1) { - return null; - } - return keys[index]; - } - - - // return the maximum value or throw an error if zero length - public int maxValue() { - checkMinMax("maxIndex"); - return values[maxIndex()]; - } - - - public int sum() { - long amount = sumLong(); - if (amount > Integer.MAX_VALUE) { - throw new RuntimeException("sum() exceeds " + Integer.MAX_VALUE + ", use sumLong()"); - } - if (amount < Integer.MIN_VALUE) { - throw new RuntimeException("sum() less than " + Integer.MIN_VALUE + ", use sumLong()"); - } - return (int) amount; - } - - - public long sumLong() { - long sum = 0; - for (int i = 0; i < count; i++) { - sum += values[i]; - } - return sum; - } - - - public int index(String what) { - Integer found = indices.get(what); - return (found == null) ? -1 : found.intValue(); - } - - - protected void create(String what, int much) { - if (count == keys.length) { - keys = PApplet.expand(keys); - values = PApplet.expand(values); - } - indices.put(what, Integer.valueOf(count)); - keys[count] = what; - values[count] = much; - count++; - } - - /** - * @webref intdict:method - * @brief Remove a key/value pair - */ - public int remove(String key) { - int index = index(key); - if (index == -1) { - throw new NoSuchElementException("'" + key + "' not found"); - } - int value = values[index]; - removeIndex(index); - return value; - } - - - public int removeIndex(int index) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - int value = values[index]; - indices.remove(keys[index]); - for (int i = index; i < count-1; i++) { - keys[i] = keys[i+1]; - values[i] = values[i+1]; - indices.put(keys[i], i); - } - count--; - keys[count] = null; - values[count] = 0; - return value; - } - - - public void swap(int a, int b) { - String tkey = keys[a]; - int tvalue = values[a]; - keys[a] = keys[b]; - values[a] = values[b]; - keys[b] = tkey; - values[b] = tvalue; - -// indices.put(keys[a], Integer.valueOf(a)); -// indices.put(keys[b], Integer.valueOf(b)); - } - - - /** - * Sort the keys alphabetically (ignoring case). Uses the value as a - * tie-breaker (only really possible with a key that has a case change). - * - * @webref intdict:method - * @brief Sort the keys alphabetically - */ - public void sortKeys() { - sortImpl(true, false, true); - } - - /** - * Sort the keys alphabetically in reverse (ignoring case). Uses the value as a - * tie-breaker (only really possible with a key that has a case change). - * - * @webref intdict:method - * @brief Sort the keys alphabetically in reverse - */ - public void sortKeysReverse() { - sortImpl(true, true, true); - } - - - /** - * Sort by values in ascending order. The smallest value will be at [0]. - * - * @webref intdict:method - * @brief Sort by values in ascending order - */ - public void sortValues() { - sortValues(true); - } - - - /** - * Set true to ensure that the order returned is identical. Slightly - * slower because the tie-breaker for identical values compares the keys. - * @param stable - */ - public void sortValues(boolean stable) { - sortImpl(false, false, stable); - } - - - /** - * Sort by values in descending order. The largest value will be at [0]. - * - * @webref intdict:method - * @brief Sort by values in descending order - */ - public void sortValuesReverse() { - sortValuesReverse(true); - } - - - public void sortValuesReverse(boolean stable) { - sortImpl(false, true, stable); - } - - - protected void sortImpl(final boolean useKeys, final boolean reverse, - final boolean stable) { - Sort s = new Sort() { - @Override - public int size() { - return count; - } - - @Override - public int compare(int a, int b) { - int diff = 0; - if (useKeys) { - diff = keys[a].compareToIgnoreCase(keys[b]); - if (diff == 0) { - diff = values[a] - values[b]; - } - } else { // sort values - diff = values[a] - values[b]; - if (diff == 0 && stable) { - diff = keys[a].compareToIgnoreCase(keys[b]); - } - } - return reverse ? -diff : diff; - } - - @Override - public void swap(int a, int b) { - IntDict.this.swap(a, b); - } - }; - s.run(); - - // Set the indices after sort/swaps (performance fix 160411) - resetIndices(); - } - - - /** - * Sum all of the values in this dictionary, then return a new FloatDict of - * each key, divided by the total sum. The total for all values will be ~1.0. - * @return an IntDict with the original keys, mapped to their pct of the total - */ - public FloatDict getPercent() { - double sum = sum(); // a little more accuracy - FloatDict outgoing = new FloatDict(); - for (int i = 0; i < size(); i++) { - double percent = value(i) / sum; - outgoing.set(key(i), (float) percent); - } - return outgoing; - } - - - /** Returns a duplicate copy of this object. */ - public IntDict copy() { - IntDict outgoing = new IntDict(count); - System.arraycopy(keys, 0, outgoing.keys, 0, count); - System.arraycopy(values, 0, outgoing.values, 0, count); - for (int i = 0; i < count; i++) { - outgoing.indices.put(keys[i], i); - } - outgoing.count = count; - return outgoing; - } - - - public void print() { - for (int i = 0; i < size(); i++) { - System.out.println(keys[i] + " = " + values[i]); - } - } - - - /** - * Save tab-delimited entries to a file (TSV format, UTF-8 encoding) - */ - public void save(File file) { - PrintWriter writer = PApplet.createWriter(file); - write(writer); - writer.close(); - } - - - /** - * Write tab-delimited entries to a PrintWriter - */ - public void write(PrintWriter writer) { - for (int i = 0; i < count; i++) { - writer.println(keys[i] + "\t" + values[i]); - } - writer.flush(); - } - - - /** - * Return this dictionary as a String in JSON format. - */ - public String toJSON() { - StringList items = new StringList(); - for (int i = 0; i < count; i++) { - items.append(JSONObject.quote(keys[i])+ ": " + values[i]); - } - return "{ " + items.join(", ") + " }"; - } - - - @Override - public String toString() { - return getClass().getSimpleName() + " size=" + size() + " " + toJSON(); - } -} diff --git a/core/src/processing/data/IntList.java b/core/src/processing/data/IntList.java deleted file mode 100644 index dc2c89916..000000000 --- a/core/src/processing/data/IntList.java +++ /dev/null @@ -1,936 +0,0 @@ -package processing.data; - -import java.io.File; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Random; - -import processing.core.PApplet; - - -// splice, slice, subset, concat, reverse - -// trim, join for String versions - - -/** - * Helper class for a list of ints. Lists are designed to have some of the - * features of ArrayLists, but to maintain the simplicity and efficiency of - * working with arrays. - * - * Functions like sort() and shuffle() always act on the list itself. To get - * a sorted copy, use list.copy().sort(). - * - * @webref data:composite - * @see FloatList - * @see StringList - */ -public class IntList implements Iterable { - protected int count; - protected int[] data; - - - public IntList() { - data = new int[10]; - } - - - /** - * @nowebref - */ - public IntList(int length) { - data = new int[length]; - } - - - /** - * @nowebref - */ - public IntList(int[] source) { - count = source.length; - data = new int[count]; - System.arraycopy(source, 0, data, 0, count); - } - - - /** - * Construct an IntList from an iterable pile of objects. - * For instance, a float array, an array of strings, who knows). - * Un-parseable or null values will be set to 0. - * @nowebref - */ - public IntList(Iterable iter) { - this(10); - for (Object o : iter) { - if (o == null) { - append(0); // missing value default - } else if (o instanceof Number) { - append(((Number) o).intValue()); - } else { - append(PApplet.parseInt(o.toString().trim())); - } - } - crop(); - } - - - /** - * Construct an IntList from a random pile of objects. - * Un-parseable or null values will be set to zero. - */ - public IntList(Object... items) { - final int missingValue = 0; // nuts, can't be last/final/second arg - - count = items.length; - data = new int[count]; - int index = 0; - for (Object o : items) { - int value = missingValue; - if (o != null) { - if (o instanceof Number) { - value = ((Number) o).intValue(); - } else { - value = PApplet.parseInt(o.toString().trim(), missingValue); - } - } - data[index++] = value; - } - } - - - static public IntList fromRange(int stop) { - return fromRange(0, stop); - } - - - static public IntList fromRange(int start, int stop) { - int count = stop - start; - IntList newbie = new IntList(count); - for (int i = 0; i < count; i++) { - newbie.set(i, start+i); - } - return newbie; - } - - - /** - * Improve efficiency by removing allocated but unused entries from the - * internal array used to store the data. Set to private, though it could - * be useful to have this public if lists are frequently making drastic - * size changes (from very large to very small). - */ - private void crop() { - if (count != data.length) { - data = PApplet.subset(data, 0, count); - } - } - - - /** - * Get the length of the list. - * - * @webref intlist:method - * @brief Get the length of the list - */ - public int size() { - return count; - } - - - public void resize(int length) { - if (length > data.length) { - int[] temp = new int[length]; - System.arraycopy(data, 0, temp, 0, count); - data = temp; - - } else if (length > count) { - Arrays.fill(data, count, length, 0); - } - count = length; - } - - - /** - * Remove all entries from the list. - * - * @webref intlist:method - * @brief Remove all entries from the list - */ - public void clear() { - count = 0; - } - - - /** - * Get an entry at a particular index. - * - * @webref intlist:method - * @brief Get an entry at a particular index - */ - public int get(int index) { - if (index >= this.count) { - throw new ArrayIndexOutOfBoundsException(index); - } - return data[index]; - } - - - /** - * Set the entry at a particular index. If the index is past the length of - * the list, it'll expand the list to accommodate, and fill the intermediate - * entries with 0s. - * - * @webref intlist:method - * @brief Set the entry at a particular index - */ - public void set(int index, int what) { - if (index >= count) { - data = PApplet.expand(data, index+1); - for (int i = count; i < index; i++) { - data[i] = 0; - } - count = index+1; - } - data[index] = what; - } - - - /** Just an alias for append(), but matches pop() */ - public void push(int value) { - append(value); - } - - - public int pop() { - if (count == 0) { - throw new RuntimeException("Can't call pop() on an empty list"); - } - int value = get(count-1); - count--; - return value; - } - - - /** - * Remove an element from the specified index - * - * @webref intlist:method - * @brief Remove an element from the specified index - */ - public int remove(int index) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - int entry = data[index]; -// int[] outgoing = new int[count - 1]; -// System.arraycopy(data, 0, outgoing, 0, index); -// count--; -// System.arraycopy(data, index + 1, outgoing, 0, count - index); -// data = outgoing; - // For most cases, this actually appears to be faster - // than arraycopy() on an array copying into itself. - for (int i = index; i < count-1; i++) { - data[i] = data[i+1]; - } - count--; - return entry; - } - - - // Remove the first instance of a particular value, - // and return the index at which it was found. - public int removeValue(int value) { - int index = index(value); - if (index != -1) { - remove(index); - return index; - } - return -1; - } - - - // Remove all instances of a particular value, - // and return the number of values found and removed - public int removeValues(int value) { - int ii = 0; - for (int i = 0; i < count; i++) { - if (data[i] != value) { - data[ii++] = data[i]; - } - } - int removed = count - ii; - count = ii; - return removed; - } - - - /** - * Add a new entry to the list. - * - * @webref intlist:method - * @brief Add a new entry to the list - */ - public void append(int value) { - if (count == data.length) { - data = PApplet.expand(data); - } - data[count++] = value; - } - - - public void append(int[] values) { - for (int v : values) { - append(v); - } - } - - - public void append(IntList list) { - for (int v : list.values()) { // will concat the list... - append(v); - } - } - - - /** Add this value, but only if it's not already in the list. */ - public void appendUnique(int value) { - if (!hasValue(value)) { - append(value); - } - } - - -// public void insert(int index, int value) { -// if (index+1 > count) { -// if (index+1 < data.length) { -// } -// } -// if (index >= data.length) { -// data = PApplet.expand(data, index+1); -// data[index] = value; -// count = index+1; -// -// } else if (count == data.length) { -// if (index >= count) { -// //int[] temp = new int[count << 1]; -// System.arraycopy(data, 0, temp, 0, index); -// temp[index] = value; -// System.arraycopy(data, index, temp, index+1, count - index); -// data = temp; -// -// } else { -// // data[] has room to grow -// // for() loop believed to be faster than System.arraycopy over itself -// for (int i = count; i > index; --i) { -// data[i] = data[i-1]; -// } -// data[index] = value; -// count++; -// } -// } - - - public void insert(int index, int value) { - insert(index, new int[] { value }); - } - - - // same as splice - public void insert(int index, int[] values) { - if (index < 0) { - throw new IllegalArgumentException("insert() index cannot be negative: it was " + index); - } - if (index >= data.length) { - throw new IllegalArgumentException("insert() index " + index + " is past the end of this list"); - } - - int[] temp = new int[count + values.length]; - - // Copy the old values, but not more than already exist - System.arraycopy(data, 0, temp, 0, Math.min(count, index)); - - // Copy the new values into the proper place - System.arraycopy(values, 0, temp, index, values.length); - -// if (index < count) { - // The index was inside count, so it's a true splice/insert - System.arraycopy(data, index, temp, index+values.length, count - index); - count = count + values.length; -// } else { -// // The index was past 'count', so the new count is weirder -// count = index + values.length; -// } - data = temp; - } - - - public void insert(int index, IntList list) { - insert(index, list.values()); - } - - - // below are aborted attempts at more optimized versions of the code - // that are harder to read and debug... - -// if (index + values.length >= count) { -// // We're past the current 'count', check to see if we're still allocated -// // index 9, data.length = 10, values.length = 1 -// if (index + values.length < data.length) { -// // There's still room for these entries, even though it's past 'count'. -// // First clear out the entries leading up to it, however. -// for (int i = count; i < index; i++) { -// data[i] = 0; -// } -// data[index] = -// } -// if (index >= data.length) { -// int length = index + values.length; -// int[] temp = new int[length]; -// System.arraycopy(data, 0, temp, 0, count); -// System.arraycopy(values, 0, temp, index, values.length); -// data = temp; -// count = data.length; -// } else { -// -// } -// -// } else if (count == data.length) { -// int[] temp = new int[count << 1]; -// System.arraycopy(data, 0, temp, 0, index); -// temp[index] = value; -// System.arraycopy(data, index, temp, index+1, count - index); -// data = temp; -// -// } else { -// // data[] has room to grow -// // for() loop believed to be faster than System.arraycopy over itself -// for (int i = count; i > index; --i) { -// data[i] = data[i-1]; -// } -// data[index] = value; -// count++; -// } - - - /** Return the first index of a particular value. */ - public int index(int what) { - /* - if (indexCache != null) { - try { - return indexCache.get(what); - } catch (Exception e) { // not there - return -1; - } - } - */ - for (int i = 0; i < count; i++) { - if (data[i] == what) { - return i; - } - } - return -1; - } - - - // !!! TODO this is not yet correct, because it's not being reset when - // the rest of the entries are changed -// protected void cacheIndices() { -// indexCache = new HashMap(); -// for (int i = 0; i < count; i++) { -// indexCache.put(data[i], i); -// } -// } - - /** - * @webref intlist:method - * @brief Check if a number is a part of the list - */ - public boolean hasValue(int value) { -// if (indexCache == null) { -// cacheIndices(); -// } -// return index(what) != -1; - for (int i = 0; i < count; i++) { - if (data[i] == value) { - return true; - } - } - return false; - } - - /** - * @webref intlist:method - * @brief Add one to a value - */ - public void increment(int index) { - if (count <= index) { - resize(index + 1); - } - data[index]++; - } - - - private void boundsProblem(int index, String method) { - final String msg = String.format("The list size is %d. " + - "You cannot %s() to element %d.", count, method, index); - throw new ArrayIndexOutOfBoundsException(msg); - } - - - /** - * @webref intlist:method - * @brief Add to a value - */ - public void add(int index, int amount) { - if (index < count) { - data[index] += amount; - } else { - boundsProblem(index, "add"); - } - } - - /** - * @webref intlist:method - * @brief Subtract from a value - */ - public void sub(int index, int amount) { - if (index < count) { - data[index] -= amount; - } else { - boundsProblem(index, "sub"); - } - } - - /** - * @webref intlist:method - * @brief Multiply a value - */ - public void mult(int index, int amount) { - if (index < count) { - data[index] *= amount; - } else { - boundsProblem(index, "mult"); - } - } - - /** - * @webref intlist:method - * @brief Divide a value - */ - public void div(int index, int amount) { - if (index < count) { - data[index] /= amount; - } else { - boundsProblem(index, "div"); - } - } - - - private void checkMinMax(String functionName) { - if (count == 0) { - String msg = - String.format("Cannot use %s() on an empty %s.", - functionName, getClass().getSimpleName()); - throw new RuntimeException(msg); - } - } - - - /** - * @webref intlist:method - * @brief Return the smallest value - */ - public int min() { - checkMinMax("min"); - int outgoing = data[0]; - for (int i = 1; i < count; i++) { - if (data[i] < outgoing) outgoing = data[i]; - } - return outgoing; - } - - - // returns the index of the minimum value. - // if there are ties, it returns the first one found. - public int minIndex() { - checkMinMax("minIndex"); - int value = data[0]; - int index = 0; - for (int i = 1; i < count; i++) { - if (data[i] < value) { - value = data[i]; - index = i; - } - } - return index; - } - - - /** - * @webref intlist:method - * @brief Return the largest value - */ - public int max() { - checkMinMax("max"); - int outgoing = data[0]; - for (int i = 1; i < count; i++) { - if (data[i] > outgoing) outgoing = data[i]; - } - return outgoing; - } - - - // returns the index of the maximum value. - // if there are ties, it returns the first one found. - public int maxIndex() { - checkMinMax("maxIndex"); - int value = data[0]; - int index = 0; - for (int i = 1; i < count; i++) { - if (data[i] > value) { - value = data[i]; - index = i; - } - } - return index; - } - - - public int sum() { - long amount = sumLong(); - if (amount > Integer.MAX_VALUE) { - throw new RuntimeException("sum() exceeds " + Integer.MAX_VALUE + ", use sumLong()"); - } - if (amount < Integer.MIN_VALUE) { - throw new RuntimeException("sum() less than " + Integer.MIN_VALUE + ", use sumLong()"); - } - return (int) amount; - } - - - public long sumLong() { - long sum = 0; - for (int i = 0; i < count; i++) { - sum += data[i]; - } - return sum; - } - - - /** - * Sorts the array in place. - * - * @webref intlist:method - * @brief Sorts the array, lowest to highest - */ - public void sort() { - Arrays.sort(data, 0, count); - } - - - /** - * Reverse sort, orders values from highest to lowest. - * - * @webref intlist:method - * @brief Reverse sort, orders values from highest to lowest - */ - public void sortReverse() { - new Sort() { - @Override - public int size() { - return count; - } - - @Override - public int compare(int a, int b) { - return data[b] - data[a]; - } - - @Override - public void swap(int a, int b) { - int temp = data[a]; - data[a] = data[b]; - data[b] = temp; - } - }.run(); - } - - - // use insert() -// public void splice(int index, int value) { -// } - - -// public void subset(int start) { -// subset(start, count - start); -// } -// -// -// public void subset(int start, int num) { -// for (int i = 0; i < num; i++) { -// data[i] = data[i+start]; -// } -// count = num; -// } - - /** - * @webref intlist:method - * @brief Reverse the order of the list elements - */ - public void reverse() { - int ii = count - 1; - for (int i = 0; i < count/2; i++) { - int t = data[i]; - data[i] = data[ii]; - data[ii] = t; - --ii; - } - } - - - /** - * Randomize the order of the list elements. Note that this does not - * obey the randomSeed() function in PApplet. - * - * @webref intlist:method - * @brief Randomize the order of the list elements - */ - public void shuffle() { - Random r = new Random(); - int num = count; - while (num > 1) { - int value = r.nextInt(num); - num--; - int temp = data[num]; - data[num] = data[value]; - data[value] = temp; - } - } - - - /** - * Randomize the list order using the random() function from the specified - * sketch, allowing shuffle() to use its current randomSeed() setting. - */ - public void shuffle(PApplet sketch) { - int num = count; - while (num > 1) { - int value = (int) sketch.random(num); - num--; - int temp = data[num]; - data[num] = data[value]; - data[value] = temp; - } - } - - - public IntList copy() { - IntList outgoing = new IntList(data); - outgoing.count = count; - return outgoing; - } - - - /** - * Returns the actual array being used to store the data. For advanced users, - * this is the fastest way to access a large list. Suitable for iterating - * with a for() loop, but modifying the list will have terrible consequences. - */ - public int[] values() { - crop(); - return data; - } - - - @Override - public Iterator iterator() { -// public Iterator valueIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - IntList.this.remove(index); - index--; - } - - public Integer next() { - return data[++index]; - } - - public boolean hasNext() { - return index+1 < count; - } - }; - } - - - /** - * Create a new array with a copy of all the values. - * - * @return an array sized by the length of the list with each of the values. - * @webref intlist:method - * @brief Create a new array with a copy of all the values - */ - public int[] array() { - return array(null); - } - - - /** - * Copy values into the specified array. If the specified array is null or - * not the same size, a new array will be allocated. - * @param array - */ - public int[] array(int[] array) { - if (array == null || array.length != count) { - array = new int[count]; - } - System.arraycopy(data, 0, array, 0, count); - return array; - } - - -// public int[] toIntArray() { -// int[] outgoing = new int[count]; -// for (int i = 0; i < count; i++) { -// outgoing[i] = (int) data[i]; -// } -// return outgoing; -// } - - -// public long[] toLongArray() { -// long[] outgoing = new long[count]; -// for (int i = 0; i < count; i++) { -// outgoing[i] = (long) data[i]; -// } -// return outgoing; -// } - - -// public float[] toFloatArray() { -// float[] outgoing = new float[count]; -// System.arraycopy(data, 0, outgoing, 0, count); -// return outgoing; -// } - - -// public double[] toDoubleArray() { -// double[] outgoing = new double[count]; -// for (int i = 0; i < count; i++) { -// outgoing[i] = data[i]; -// } -// return outgoing; -// } - - -// public String[] toStringArray() { -// String[] outgoing = new String[count]; -// for (int i = 0; i < count; i++) { -// outgoing[i] = String.valueOf(data[i]); -// } -// return outgoing; -// } - - - /** - * Returns a normalized version of this array. Called getPercent() for - * consistency with the Dict classes. It's a getter method because it needs - * to returns a new list (because IntList/Dict can't do percentages or - * normalization in place on int values). - */ - public FloatList getPercent() { - double sum = 0; - for (float value : array()) { - sum += value; - } - FloatList outgoing = new FloatList(count); - for (int i = 0; i < count; i++) { - double percent = data[i] / sum; - outgoing.set(i, (float) percent); - } - return outgoing; - } - - -// /** -// * Count the number of times each entry is found in this list. -// * Converts each entry to a String so it can be used as a key. -// */ -// public IntDict getTally() { -// IntDict outgoing = new IntDict(); -// for (int i = 0; i < count; i++) { -// outgoing.increment(String.valueOf(data[i])); -// } -// return outgoing; -// } - - - public IntList getSubset(int start) { - return getSubset(start, count - start); - } - - - public IntList getSubset(int start, int num) { - int[] subset = new int[num]; - System.arraycopy(data, start, subset, 0, num); - return new IntList(subset); - } - - - public String join(String separator) { - if (count == 0) { - return ""; - } - StringBuilder sb = new StringBuilder(); - sb.append(data[0]); - for (int i = 1; i < count; i++) { - sb.append(separator); - sb.append(data[i]); - } - return sb.toString(); - } - - - public void print() { - for (int i = 0; i < count; i++) { - System.out.format("[%d] %d%n", i, data[i]); - } - } - - - /** - * Save tab-delimited entries to a file (TSV format, UTF-8 encoding) - */ - public void save(File file) { - PrintWriter writer = PApplet.createWriter(file); - write(writer); - writer.close(); - } - - - /** - * Write entries to a PrintWriter, one per line - */ - public void write(PrintWriter writer) { - for (int i = 0; i < count; i++) { - writer.println(data[i]); - } - writer.flush(); - } - - - /** - * Return this dictionary as a String in JSON format. - */ - public String toJSON() { - return "[ " + join(", ") + " ]"; - } - - - @Override - public String toString() { - return getClass().getSimpleName() + " size=" + size() + " " + toJSON(); - } -} diff --git a/core/src/processing/data/JSONArray.java b/core/src/processing/data/JSONArray.java deleted file mode 100644 index ea8276bd8..000000000 --- a/core/src/processing/data/JSONArray.java +++ /dev/null @@ -1,1260 +0,0 @@ -package processing.data; - -// This code has been modified heavily to more closely match the rest of the -// Processing API. In the spirit of the rest of the project, where we try to -// keep the API as simple as possible, we have erred on the side of being -// conservative in choosing which functions to include, since we haven't yet -// decided what's truly necessary. Power users looking for a full-featured -// version can use the original version from json.org, or one of the many -// other APIs that are available. As with all Processing API, if there's a -// function that should be added, please let use know, and have others vote: -// http://code.google.com/p/processing/issues/list - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - */ - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Array; -import java.util.ArrayList; - -import processing.core.PApplet; - -/** - * A JSONArray is an ordered sequence of values. Its external text form is a - * string wrapped in square brackets with commas separating the values. The - * internal form is an object having get and opt - * methods for accessing the values by index, and put methods for - * adding or replacing values. The values can be any of these types: - * Boolean, JSONArray, JSONObject, - * Number, String, or the - * JSONObject.NULL object. - *

    - * The constructor can convert a JSON text into a Java object. The - * toString method converts to JSON text. - *

    - * A get method returns a value if one can be found, and throws an - * exception if one cannot be found. An opt method returns a - * default value instead of throwing an exception, and so is useful for - * obtaining optional values. - *

    - * The generic get() and opt() methods return an - * object which you can cast or query for type. There are also typed - * get and opt methods that do type checking and type - * coercion for you. - *

    - * The texts produced by the toString methods strictly conform to - * JSON syntax rules. The constructors are more forgiving in the texts they will - * accept: - *

      - *
    • An extra , (comma) may appear just - * before the closing bracket.
    • - *
    • The null value will be inserted when there is , - *  (comma) elision.
    • - *
    • Strings may be quoted with ' (single - * quote).
    • - *
    • Strings do not need to be quoted at all if they do not begin with a quote - * or single quote, and if they do not contain leading or trailing spaces, and - * if they do not contain any of these characters: - * { } [ ] / \ : , = ; # and if they do not look like numbers and - * if they are not the reserved words true, false, or - * null.
    • - *
    • Values can be separated by ; (semicolon) as - * well as by , (comma).
    • - *
    - * - * @author JSON.org - * @version 2012-11-13 - * @webref data:composite - * @see JSONObject - * @see PApplet#loadJSONObject(String) - * @see PApplet#loadJSONArray(String) - * @see PApplet#saveJSONObject(JSONObject, String) - * @see PApplet#saveJSONArray(JSONArray, String) - */ -public class JSONArray { - - /** - * The arrayList where the JSONArray's properties are kept. - */ - private final ArrayList myArrayList; - - - /** - * Construct an empty JSONArray. - */ - public JSONArray() { - this.myArrayList = new ArrayList<>(); - } - - - /** - * @nowebref - */ - public JSONArray(Reader reader) { - this(new JSONTokener(reader)); - } - - - /** - * Construct a JSONArray from a JSONTokener. - * - * @param x A JSONTokener - * @throws RuntimeException If there is a syntax error. - * @nowebref - */ - protected JSONArray(JSONTokener x) { - this(); - if (x.nextClean() != '[') { - throw new RuntimeException("A JSONArray text must start with '['"); - } - if (x.nextClean() != ']') { - x.back(); - for (;;) { - if (x.nextClean() == ',') { - x.back(); - myArrayList.add(JSONObject.NULL); - } else { - x.back(); - myArrayList.add(x.nextValue()); - } - switch (x.nextClean()) { - case ';': - case ',': - if (x.nextClean() == ']') { - return; - } - x.back(); - break; - case ']': - return; - default: - throw new RuntimeException("Expected a ',' or ']'"); - } - } - } - } - - - /** - * @nowebref - */ - public JSONArray(IntList list) { - myArrayList = new ArrayList<>(); - for (int item : list.values()) { - myArrayList.add(Integer.valueOf(item)); - } - } - - - /** - * @nowebref - */ - public JSONArray(FloatList list) { - myArrayList = new ArrayList<>(); - for (float item : list.values()) { - myArrayList.add(Float.valueOf(item)); - } - } - - - /** - * @nowebref - */ - public JSONArray(StringList list) { - myArrayList = new ArrayList<>(); - for (String item : list.values()) { - myArrayList.add(item); - } - } - - - /** - * Construct a JSONArray from a source JSON text. - * @param source A string that begins with - * [ (left bracket) - * and ends with ] (right bracket). - * @return {@code null} if there is a syntax error. - */ - static public JSONArray parse(String source) { - try { - return new JSONArray(new JSONTokener(source)); - } catch (Exception e) { - return null; - } - } - - -// /** -// * Construct a JSONArray from a Collection. -// * @param collection A Collection. -// */ -// public JSONArray(Collection collection) { -// myArrayList = new ArrayList(); -// if (collection != null) { -// Iterator iter = collection.iterator(); -// while (iter.hasNext()) { -// myArrayList.add(JSONObject.wrap(iter.next())); -// } -// } -// } - - - // TODO not decided whether we keep this one, but used heavily by JSONObject - /** - * Construct a JSONArray from an array - * @throws RuntimeException If not an array. - */ - protected JSONArray(Object array) { - this(); - if (array.getClass().isArray()) { - int length = Array.getLength(array); - for (int i = 0; i < length; i += 1) { - this.append(JSONObject.wrap(Array.get(array, i))); - } - } else { - throw new RuntimeException("JSONArray initial value should be a string or collection or array."); - } - } - - - /** - * Get the optional object value associated with an index. - * @param index must be between 0 and length() - 1 - * @return An object value, or null if there is no - * object at that index. - */ - private Object opt(int index) { - if (index < 0 || index >= this.size()) { - return null; - } - return myArrayList.get(index); - } - - - /** - * Get the object value associated with an index. - * @param index must be between 0 and length() - 1 - * @return An object value. - * @throws RuntimeException If there is no value for the index. - */ - public Object get(int index) { - Object object = opt(index); - if (object == null) { - throw new RuntimeException("JSONArray[" + index + "] not found."); - } - return object; - } - - - /** - * Get the string associated with an index. - * - * @webref jsonarray:method - * @brief Gets the String value associated with an index - * @param index must be between 0 and length() - 1 - * @return A string value. - * @throws RuntimeException If there is no string value for the index. - * @see JSONArray#getInt(int) - * @see JSONArray#getFloat(int) - * @see JSONArray#getBoolean(int) - */ - public String getString(int index) { - Object object = this.get(index); - if (object instanceof String) { - return (String)object; - } - throw new RuntimeException("JSONArray[" + index + "] not a string."); - } - - - /** - * Get the optional string associated with an index. - * The defaultValue is returned if the key is not found. - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return A String value. - */ - public String getString(int index, String defaultValue) { - Object object = this.opt(index); - return JSONObject.NULL.equals(object) ? defaultValue : object.toString(); - } - - - /** - * Get the int value associated with an index. - * - * @webref jsonarray:method - * @brief Gets the int value associated with an index - * @param index must be between 0 and length() - 1 - * @return The value. - * @throws RuntimeException If the key is not found or if the value is not a number. - * @see JSONArray#getFloat(int) - * @see JSONArray#getString(int) - * @see JSONArray#getBoolean(int) - */ - public int getInt(int index) { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).intValue() - : Integer.parseInt((String)object); - } catch (Exception e) { - throw new RuntimeException("JSONArray[" + index + "] is not a number."); - } - } - - - /** - * Get the optional int value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return The value. - */ - public int getInt(int index, int defaultValue) { - try { - return getInt(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the long value associated with an index. - * - * @param index The index must be between 0 and length() - 1 - * @return The value. - * @throws RuntimeException If the key is not found or if the value cannot - * be converted to a number. - */ - public long getLong(int index) { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).longValue() - : Long.parseLong((String)object); - } catch (Exception e) { - throw new RuntimeException("JSONArray[" + index + "] is not a number."); - } - } - - - /** - * Get the optional long value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return The value. - */ - public long getLong(int index, long defaultValue) { - try { - return this.getLong(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get a value from an index as a float. JSON uses 'double' values - * internally, so this is simply getDouble() cast to a float. - * - * @webref jsonarray:method - * @brief Gets the float value associated with an index - * @param index must be between 0 and length() - 1 - * @see JSONArray#getInt(int) - * @see JSONArray#getString(int) - * @see JSONArray#getBoolean(int) - */ - public float getFloat(int index) { - return (float) getDouble(index); - } - - - public float getFloat(int index, float defaultValue) { - try { - return getFloat(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the double value associated with an index. - * - * @param index must be between 0 and length() - 1 - * @return The value. - * @throws RuntimeException If the key is not found or if the value cannot - * be converted to a number. - */ - public double getDouble(int index) { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).doubleValue() - : Double.parseDouble((String)object); - } catch (Exception e) { - throw new RuntimeException("JSONArray[" + index + "] is not a number."); - } - } - - - /** - * Get the optional double value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index subscript - * @param defaultValue The default value. - * @return The value. - */ - public double getDouble(int index, double defaultValue) { - try { - return this.getDouble(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the boolean value associated with an index. - * The string values "true" and "false" are converted to boolean. - * - * @webref jsonarray:method - * @brief Gets the boolean value associated with an index - * @param index must be between 0 and length() - 1 - * @return The truth. - * @throws RuntimeException If there is no value for the index or if the - * value is not convertible to boolean. - * @see JSONArray#getInt(int) - * @see JSONArray#getFloat(int) - * @see JSONArray#getString(int) - */ - public boolean getBoolean(int index) { - Object object = this.get(index); - if (object.equals(Boolean.FALSE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("true"))) { - return true; - } - throw new RuntimeException("JSONArray[" + index + "] is not a boolean."); - } - - - /** - * Get the optional boolean value associated with an index. - * It returns the defaultValue if there is no value at that index or if - * it is not a Boolean or the String "true" or "false" (case insensitive). - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue A boolean default. - * @return The truth. - */ - public boolean getBoolean(int index, boolean defaultValue) { - try { - return getBoolean(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the JSONArray associated with an index. - * - * @webref jsonobject:method - * @brief Gets the JSONArray associated with an index value - * @param index must be between 0 and length() - 1 - * @return A JSONArray value. - * @throws RuntimeException If there is no value for the index. or if the - * value is not a JSONArray - * @see JSONArray#getJSONObject(int) - * @see JSONArray#setJSONObject(int, JSONObject) - * @see JSONArray#setJSONArray(int, JSONArray) - */ - public JSONArray getJSONArray(int index) { - Object object = this.get(index); - if (object instanceof JSONArray) { - return (JSONArray)object; - } - throw new RuntimeException("JSONArray[" + index + "] is not a JSONArray."); - } - - - public JSONArray getJSONArray(int index, JSONArray defaultValue) { - try { - return getJSONArray(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the JSONObject associated with an index. - * - * @webref jsonobject:method - * @brief Gets the JSONObject associated with an index value - * @param index the index value of the object to get - * @return A JSONObject value. - * @throws RuntimeException If there is no value for the index or if the - * value is not a JSONObject - * @see JSONArray#getJSONArray(int) - * @see JSONArray#setJSONObject(int, JSONObject) - * @see JSONArray#setJSONArray(int, JSONArray) - */ - public JSONObject getJSONObject(int index) { - Object object = this.get(index); - if (object instanceof JSONObject) { - return (JSONObject)object; - } - throw new RuntimeException("JSONArray[" + index + "] is not a JSONObject."); - } - - - public JSONObject getJSONObject(int index, JSONObject defaultValue) { - try { - return getJSONObject(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get this entire array as a String array. - * - * @webref jsonarray:method - * @brief Gets the entire array as an array of Strings - * @see JSONArray#getIntArray() - */ - public String[] getStringArray() { - String[] outgoing = new String[size()]; - for (int i = 0; i < size(); i++) { - outgoing[i] = getString(i); - } - return outgoing; - } - - - /** - * Get this entire array as an int array. Everything must be an int. - * - * @webref jsonarray:method - * @brief Gets the entire array as array of ints - * @see JSONArray#getStringArray() - */ - public int[] getIntArray() { - int[] outgoing = new int[size()]; - for (int i = 0; i < size(); i++) { - outgoing[i] = getInt(i); - } - return outgoing; - } - - - /** Get this entire array as a long array. Everything must be an long. */ - public long[] getLongArray() { - long[] outgoing = new long[size()]; - for (int i = 0; i < size(); i++) { - outgoing[i] = getLong(i); - } - return outgoing; - } - - - /** Get this entire array as a float array. Everything must be an float. */ - public float[] getFloatArray() { - float[] outgoing = new float[size()]; - for (int i = 0; i < size(); i++) { - outgoing[i] = getFloat(i); - } - return outgoing; - } - - - /** Get this entire array as a double array. Everything must be an double. */ - public double[] getDoubleArray() { - double[] outgoing = new double[size()]; - for (int i = 0; i < size(); i++) { - outgoing[i] = getDouble(i); - } - return outgoing; - } - - - /** Get this entire array as a boolean array. Everything must be a boolean. */ - public boolean[] getBooleanArray() { - boolean[] outgoing = new boolean[size()]; - for (int i = 0; i < size(); i++) { - outgoing[i] = getBoolean(i); - } - return outgoing; - } - - -// /** -// * Get the optional boolean value associated with an index. -// * It returns false if there is no value at that index, -// * or if the value is not Boolean.TRUE or the String "true". -// * -// * @param index The index must be between 0 and length() - 1. -// * @return The truth. -// */ -// public boolean optBoolean(int index) { -// return this.optBoolean(index, false); -// } -// -// -// /** -// * Get the optional double value associated with an index. -// * NaN is returned if there is no value for the index, -// * or if the value is not a number and cannot be converted to a number. -// * -// * @param index The index must be between 0 and length() - 1. -// * @return The value. -// */ -// public double optDouble(int index) { -// return this.optDouble(index, Double.NaN); -// } -// -// -// /** -// * Get the optional int value associated with an index. -// * Zero is returned if there is no value for the index, -// * or if the value is not a number and cannot be converted to a number. -// * -// * @param index The index must be between 0 and length() - 1. -// * @return The value. -// */ -// public int optInt(int index) { -// return this.optInt(index, 0); -// } -// -// -// /** -// * Get the optional long value associated with an index. -// * Zero is returned if there is no value for the index, -// * or if the value is not a number and cannot be converted to a number. -// * -// * @param index The index must be between 0 and length() - 1. -// * @return The value. -// */ -// public long optLong(int index) { -// return this.optLong(index, 0); -// } -// -// -// /** -// * Get the optional string value associated with an index. It returns an -// * empty string if there is no value at that index. If the value -// * is not a string and is not null, then it is coverted to a string. -// * -// * @param index The index must be between 0 and length() - 1. -// * @return A String value. -// */ -// public String optString(int index) { -// return this.optString(index, ""); -// } - - - /** - * Append an String value. This increases the array's length by one. - * - * @webref jsonarray:method - * @brief Appends a value, increasing the array's length by one - * @param value a String value - * @return this. - * @see JSONArray#size() - * @see JSONArray#remove(int) - */ - public JSONArray append(String value) { - this.append((Object)value); - return this; - } - - - /** - * Append an int value. This increases the array's length by one. - * - * @param value an int value - * @return this. - */ - public JSONArray append(int value) { - this.append(Integer.valueOf(value)); - return this; - } - - - /** - * Append an long value. This increases the array's length by one. - * - * @nowebref - * @param value A long value. - * @return this. - */ - public JSONArray append(long value) { - this.append(Long.valueOf(value)); - return this; - } - - - /** - * Append a float value. This increases the array's length by one. - * This will store the value as a double, since there are no floats in JSON. - * - * @param value a float value - * @throws RuntimeException if the value is not finite. - * @return this. - */ - public JSONArray append(float value) { - return append((double) value); - } - - - /** - * Append a double value. This increases the array's length by one. - * - * @nowebref - * @param value A double value. - * @throws RuntimeException if the value is not finite. - * @return this. - */ - public JSONArray append(double value) { - Double d = value; - JSONObject.testValidity(d); - this.append(d); - return this; - } - - - /** - * Append a boolean value. This increases the array's length by one. - * - * @param value a boolean value - * @return this. - */ - public JSONArray append(boolean value) { - this.append(value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - -// /** -// * Put a value in the JSONArray, where the value will be a -// * JSONArray which is produced from a Collection. -// * @param value A Collection value. -// * @return this. -// */ -// public JSONArray append(Collection value) { -// this.append(new JSONArray(value)); -// return this; -// } - - -// /** -// * Put a value in the JSONArray, where the value will be a -// * JSONObject which is produced from a Map. -// * @param value A Map value. -// * @return this. -// */ -// public JSONArray append(Map value) { -// this.append(new JSONObject(value)); -// return this; -// } - - - /** - * @param value a JSONArray value - */ - public JSONArray append(JSONArray value) { - myArrayList.add(value); - return this; - } - - - /** - * @param value a JSONObject value - */ - public JSONArray append(JSONObject value) { - myArrayList.add(value); - return this; - } - - - /** - * Append an object value. This increases the array's length by one. - * @param value An object value. The value should be a - * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. - * @return this. - */ - protected JSONArray append(Object value) { - myArrayList.add(value); - return this; - } - - -// /** -// * Put a value in the JSONArray, where the value will be a -// * JSONArray which is produced from a Collection. -// * @param index The subscript. -// * @param value A Collection value. -// * @return this. -// * @throws RuntimeException If the index is negative or if the value is -// * not finite. -// */ -// public JSONArray set(int index, Collection value) { -// this.set(index, new JSONArray(value)); -// return this; -// } - - - /** - * Put or replace a String value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * - * @webref jsonarray:method - * @brief Put a String value in the JSONArray - * @param index an index value - * @param value the value to assign - * @return this. - * @throws RuntimeException If the index is negative. - * @see JSONArray#setInt(int, int) - * @see JSONArray#setFloat(int, float) - * @see JSONArray#setBoolean(int, boolean) - */ - public JSONArray setString(int index, String value) { - this.set(index, value); - return this; - } - - - /** - * Put or replace an int value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * - * @webref jsonarray:method - * @brief Put an int value in the JSONArray - * @param index an index value - * @param value the value to assign - * @return this. - * @throws RuntimeException If the index is negative. - * @see JSONArray#setFloat(int, float) - * @see JSONArray#setString(int, String) - * @see JSONArray#setBoolean(int, boolean) - */ - public JSONArray setInt(int index, int value) { - this.set(index, Integer.valueOf(value)); - return this; - } - - - /** - * Put or replace a long value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * @param index The subscript. - * @param value A long value. - * @return this. - * @throws RuntimeException If the index is negative. - */ - public JSONArray setLong(int index, long value) { - return set(index, Long.valueOf(value)); - } - - - /** - * Put or replace a float value. If the index is greater than the length - * of the JSONArray, then null elements will be added as necessary to pad - * it out. There are no 'double' values in JSON, so this is passed to - * setDouble(value). - * - * @webref jsonarray:method - * @brief Put a float value in the JSONArray - * @param index an index value - * @param value the value to assign - * @return this. - * @throws RuntimeException If the index is negative or if the value is - * not finite. - * @see JSONArray#setInt(int, int) - * @see JSONArray#setString(int, String) - * @see JSONArray#setBoolean(int, boolean) - */ - public JSONArray setFloat(int index, float value) { - return setDouble(index, value); - } - - - /** - * Put or replace a double value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * @param index The subscript. - * @param value A double value. - * @return this. - * @throws RuntimeException If the index is negative or if the value is - * not finite. - */ - public JSONArray setDouble(int index, double value) { - return set(index, Double.valueOf(value)); - } - - - /** - * Put or replace a boolean value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * - * @webref jsonarray:method - * @brief Put a boolean value in the JSONArray - * @param index an index value - * @param value the value to assign - * @return this. - * @throws RuntimeException If the index is negative. - * @see JSONArray#setInt(int, int) - * @see JSONArray#setFloat(int, float) - * @see JSONArray#setString(int, String) - */ - public JSONArray setBoolean(int index, boolean value) { - return set(index, value ? Boolean.TRUE : Boolean.FALSE); - } - - -// /** -// * Put a value in the JSONArray, where the value will be a -// * JSONObject that is produced from a Map. -// * @param index The subscript. -// * @param value The Map value. -// * @return this. -// * @throws RuntimeException If the index is negative or if the the value is -// * an invalid number. -// */ -// public JSONArray set(int index, Map value) { -// this.set(index, new JSONObject(value)); -// return this; -// } - - /** - * @webref jsonarray:method - * @brief Sets the JSONArray value associated with an index value - * @param index the index value to target - * @param value the value to assign - * @see JSONArray#setJSONObject(int, JSONObject) - * @see JSONArray#getJSONObject(int) - * @see JSONArray#getJSONArray(int) - */ - public JSONArray setJSONArray(int index, JSONArray value) { - set(index, value); - return this; - } - - /** - * @webref jsonarray:method - * @brief Sets the JSONObject value associated with an index value - * @param index the index value to target - * @param value the value to assign - * @see JSONArray#setJSONArray(int, JSONArray) - * @see JSONArray#getJSONObject(int) - * @see JSONArray#getJSONArray(int) - */ - public JSONArray setJSONObject(int index, JSONObject value) { - set(index, value); - return this; - } - - - /** - * Put or replace an object value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * @param index The subscript. - * @param value The value to put into the array. The value should be a - * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. - * @return this. - * @throws RuntimeException If the index is negative or if the the value is - * an invalid number. - */ - private JSONArray set(int index, Object value) { - JSONObject.testValidity(value); - if (index < 0) { - throw new RuntimeException("JSONArray[" + index + "] not found."); - } - if (index < this.size()) { - this.myArrayList.set(index, value); - } else { - while (index != this.size()) { - this.append(JSONObject.NULL); - } - this.append(value); - } - return this; - } - - - /** - * Get the number of elements in the JSONArray, included nulls. - * - * @webref jsonarray:method - * @brief Gets the number of elements in the JSONArray - * @return The length (or size). - * @see JSONArray#append(String) - * @see JSONArray#remove(int) - */ - public int size() { - return myArrayList.size(); - } - - - /** - * Determine if the value is null. - * @webref - * @param index must be between 0 and length() - 1 - * @return true if the value at the index is null, or if there is no value. - */ - public boolean isNull(int index) { - return JSONObject.NULL.equals(this.opt(index)); - } - - - /** - * Remove an index and close the hole. - * - * @webref jsonarray:method - * @brief Removes an element - * @param index the index value of the element to be removed - * @return The value that was associated with the index, or null if there was no value. - * @see JSONArray#size() - * @see JSONArray#append(String) - */ - public Object remove(int index) { - Object o = this.opt(index); - this.myArrayList.remove(index); - return o; - } - - -// /** -// * Produce a JSONObject by combining a JSONArray of names with the values -// * of this JSONArray. -// * @param names A JSONArray containing a list of key strings. These will be -// * paired with the values. -// * @return A JSONObject, or null if there are no names or if this JSONArray -// * has no values. -// * @throws JSONException If any of the names are null. -// */ -// public JSON toJSONObject(JSONArray names) { -// if (names == null || names.length() == 0 || this.length() == 0) { -// return null; -// } -// JSON jo = new JSON(); -// for (int i = 0; i < names.length(); i += 1) { -// jo.put(names.getString(i), this.opt(i)); -// } -// return jo; -// } - - -// protected boolean save(OutputStream output) { -// return write(PApplet.createWriter(output), null); -// } - - - public boolean save(File file, String options) { - PrintWriter writer = PApplet.createWriter(file); - boolean success = write(writer, options); - writer.close(); - return success; - } - - - public boolean write(PrintWriter output) { - return write(output, null); - } - - - public boolean write(PrintWriter output, String options) { - int indentFactor = 2; - if (options != null) { - String[] opts = PApplet.split(options, ','); - for (String opt : opts) { - if (opt.equals("compact")) { - indentFactor = -1; - } else if (opt.startsWith("indent=")) { - indentFactor = PApplet.parseInt(opt.substring(7), -2); - if (indentFactor == -2) { - throw new IllegalArgumentException("Could not read a number from " + opt); - } - } else { - System.err.println("Ignoring " + opt); - } - } - } - output.print(format(indentFactor)); - output.flush(); - return true; - } - - - /** - * Return the JSON data formatted with two spaces for indents. - * Chosen to do this since it's the most common case (e.g. with println()). - * Same as format(2). Use the format() function for more options. - */ - @Override - public String toString() { - try { - return format(2); - } catch (Exception e) { - return null; - } - } - - - /** - * Make a pretty-printed JSON text of this JSONArray. - * Warning: This method assumes that the data structure is acyclical. - * @param indentFactor The number of spaces to add to each level of - * indentation. Use -1 to specify no indentation and no newlines. - * @return a printable, displayable, transmittable - * representation of the object, beginning - * with [ (left bracket) and ending - * with ] (right bracket). - */ - public String format(int indentFactor) { - StringWriter sw = new StringWriter(); - synchronized (sw.getBuffer()) { - return this.writeInternal(sw, indentFactor, 0).toString(); - } - } - - -// /** -// * Write the contents of the JSONArray as JSON text to a writer. For -// * compactness, no whitespace is added. -// *

    -// * Warning: This method assumes that the data structure is acyclic. -// * -// * @return The writer. -// */ -// protected Writer write(Writer writer) { -// return this.write(writer, -1, 0); -// } - - - /** - * Write the contents of the JSONArray as JSON text to a writer. - *

    - * Warning: This method assumes that the data structure is acyclic. - * - * @param indentFactor - * The number of spaces to add to each level of indentation. - * Use -1 to specify no indentation and no newlines. - * @param indent - * The indention of the top level. - * @return The writer. - * @throws RuntimeException - */ - protected Writer writeInternal(Writer writer, int indentFactor, int indent) { - try { - boolean commanate = false; - int length = this.size(); - writer.write('['); - - // Use -1 to signify 'no indent' - int thisFactor = (indentFactor == -1) ? 0 : indentFactor; - - if (length == 1) { - JSONObject.writeValue(writer, this.myArrayList.get(0), - indentFactor, indent); -// thisFactor, indent); - } else if (length != 0) { - final int newIndent = indent + thisFactor; - - for (int i = 0; i < length; i += 1) { - if (commanate) { - writer.write(','); - } - if (indentFactor != -1) { - writer.write('\n'); - } - JSONObject.indent(writer, newIndent); -// JSONObject.writeValue(writer, this.myArrayList.get(i), -// thisFactor, newIndent); - JSONObject.writeValue(writer, this.myArrayList.get(i), - indentFactor, newIndent); - commanate = true; - } - if (indentFactor != -1) { - writer.write('\n'); - } - JSONObject.indent(writer, indent); - } - writer.write(']'); - return writer; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - - /** - * Make a string from the contents of this JSONArray. The - * separator string is inserted between each element. - * Warning: This method assumes that the data structure is acyclic. - * @param separator A string that will be inserted between the elements. - * @return a string. - * @throws RuntimeException If the array contains an invalid number. - */ - public String join(String separator) { - int len = this.size(); - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < len; i += 1) { - if (i > 0) { - sb.append(separator); - } - sb.append(JSONObject.valueToString(this.myArrayList.get(i))); - } - return sb.toString(); - } -} diff --git a/core/src/processing/data/JSONObject.java b/core/src/processing/data/JSONObject.java deleted file mode 100644 index cc7a22de0..000000000 --- a/core/src/processing/data/JSONObject.java +++ /dev/null @@ -1,2282 +0,0 @@ -package processing.data; - -// This code has been modified heavily to more closely match the rest of the -// Processing API. In the spirit of the rest of the project, where we try to -// keep the API as simple as possible, we have erred on the side of being -// conservative in choosing which functions to include, since we haven't yet -// decided what's truly necessary. Power users looking for a full-featured -// version can use the original version from json.org, or one of the many -// other APIs that are available. As with all Processing API, if there's a -// function that should be added, please let use know, and have others vote: -// http://code.google.com/p/processing/issues/list - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - */ - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import processing.core.PApplet; - -/** - * A JSONObject is an unordered collection of name/value pairs. Its external - * form is a string wrapped in curly braces with colons between the names and - * values, and commas between the values and names. The internal form is an - * object having get and opt methods for accessing the - * values by name, and put methods for adding or replacing values - * by name. The values can be any of these types: Boolean, - * JSONArray, JSONObject, Number, - * String, or the JSONObject.NULL object. A JSONObject - * constructor can be used to convert an external form JSON text into an - * internal form whose values can be retrieved with the get and - * opt methods, or to convert values into a JSON text using the - * put and toString methods. A get method - * returns a value if one can be found, and throws an exception if one cannot be - * found. An opt method returns a default value instead of throwing - * an exception, and so is useful for obtaining optional values. - *

    - * The generic get() and opt() methods return an - * object, which you can cast or query for type. There are also typed - * get and opt methods that do type checking and type - * coercion for you. The opt methods differ from the get methods in that they do - * not throw. Instead, they return a specified value, such as null. - *

    - * The put methods add or replace values in an object. For example, - * - *

    - * myString = new JSONObject().put("JSON", "Hello, World!").toString();
    - * 
    - * - * produces the string {"JSON": "Hello, World"}. - *

    - * The texts produced by the toString methods strictly conform to - * the JSON syntax rules. The constructors are more forgiving in the texts they - * will accept: - *

      - *
    • An extra , (comma) may appear just - * before the closing brace.
    • - *
    • Strings may be quoted with ' (single - * quote).
    • - *
    • Strings do not need to be quoted at all if they do not begin with a quote - * or single quote, and if they do not contain leading or trailing spaces, and - * if they do not contain any of these characters: - * { } [ ] / \ : , = ; # and if they do not look like numbers and - * if they are not the reserved words true, false, or - * null.
    • - *
    • Keys can be followed by = or {@code =>} as well as by - * :.
    • - *
    • Values can be followed by ; (semicolon) as - * well as by , (comma).
    • - *
    - * - * @author JSON.org - * @version 2012-12-01 - * @webref data:composite - * @see JSONArray - * @see PApplet#loadJSONObject(String) - * @see PApplet#loadJSONArray(String) - * @see PApplet#saveJSONObject(JSONObject, String) - * @see PApplet#saveJSONArray(JSONArray, String) - */ -public class JSONObject { - /** - * The maximum number of keys in the key pool. - */ - private static final int keyPoolSize = 100; - - /** - * Key pooling is like string interning, but without permanently tying up - * memory. To help conserve memory, storage of duplicated key strings in - * JSONObjects will be avoided by using a key pool to manage unique key - * string objects. This is used by JSONObject.put(string, object). - */ - private static HashMap keyPool = - new HashMap<>(keyPoolSize); - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * JSONObject.NULL is equivalent to the value that JavaScript calls null, - * whilst Java's null is equivalent to the value that JavaScript calls - * undefined. - */ - private static final class Null { - /** - * There is only intended to be a single instance of the NULL object, - * so the clone method returns itself. - * @return NULL. - */ - @Override - protected final Object clone() { - return this; - } - - /** - * A Null object is equal to the null value and to itself. - * @param object An object to test for nullness. - * @return true if the object parameter is the JSONObject.NULL object - * or null. - */ - @Override - public boolean equals(Object object) { - return object == null || object == this; - } - - /** - * Get the "null" string value. - * @return The string "null". - */ - @Override - public String toString() { - return "null"; - } - - @Override - public int hashCode() { - // TODO Auto-generated method stub - return super.hashCode(); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * The map where the JSONObject's properties are kept. - */ -// private final Map map; - private final HashMap map; - - - /** - * It is sometimes more convenient and less ambiguous to have a - * NULL object than to use Java's null value. - * JSONObject.NULL.equals(null) returns true. - * JSONObject.NULL.toString() returns "null". - */ - public static final Object NULL = new Null(); - - - /** - * Construct an empty JSONObject. - * @nowebref - */ - public JSONObject() { - this.map = new HashMap<>(); - } - - -// /** -// * Construct a JSONObject from a subset of another JSONObject. -// * An array of strings is used to identify the keys that should be copied. -// * Missing keys are ignored. -// * @param jo A JSONObject. -// * @param names An array of strings. -// */ -// public JSONObject(JSONObject jo, String[] names) { -// this(); -// for (int i = 0; i < names.length; i += 1) { -// try { -// this.putOnce(names[i], jo.opt(names[i])); -// } catch (Exception ignore) { -// } -// } -// } - - - /** - * @nowebref - */ - public JSONObject(Reader reader) { - this(new JSONTokener(reader)); - } - - - /** - * Construct a JSONObject from a JSONTokener. - * @param x A JSONTokener object containing the source string. - * @throws RuntimeException If there is a syntax error in the source string - * or a duplicated key. - */ - protected JSONObject(JSONTokener x) { - this(); - char c; - String key; - - if (x.nextClean() != '{') { - throw new RuntimeException("A JSONObject text must begin with '{'"); - } - for (;;) { - c = x.nextClean(); - switch (c) { - case 0: - throw new RuntimeException("A JSONObject text must end with '}'"); - case '}': - return; - default: - x.back(); - key = x.nextValue().toString(); - } - - // The key is followed by ':'. We will also tolerate '=' or '=>'. - - c = x.nextClean(); - if (c == '=') { - if (x.next() != '>') { - x.back(); - } - } else if (c != ':') { - throw new RuntimeException("Expected a ':' after a key"); - } - this.putOnce(key, x.nextValue()); - - // Pairs are separated by ','. We will also tolerate ';'. - - switch (x.nextClean()) { - case ';': - case ',': - if (x.nextClean() == '}') { - return; - } - x.back(); - break; - case '}': - return; - default: - throw new RuntimeException("Expected a ',' or '}'"); - } - } - } - - - /** - * Construct a JSONObject from a Map. - * - * @param map A map object that can be used to initialize the contents of - * the JSONObject. - */ - protected JSONObject(HashMap map) { - this.map = new HashMap<>(); - if (map != null) { - Iterator i = map.entrySet().iterator(); - while (i.hasNext()) { - Map.Entry e = (Map.Entry) i.next(); - Object value = e.getValue(); - if (value != null) { - map.put((String) e.getKey(), wrap(value)); - } - } - } - } - - - /** - * @nowebref - */ - public JSONObject(IntDict dict) { - map = new HashMap<>(); - for (int i = 0; i < dict.size(); i++) { - setInt(dict.key(i), dict.value(i)); - } - } - - - /** - * @nowebref - */ - public JSONObject(FloatDict dict) { - map = new HashMap<>(); - for (int i = 0; i < dict.size(); i++) { - setFloat(dict.key(i), dict.value(i)); - } - } - - - /** - * @nowebref - */ - public JSONObject(StringDict dict) { - map = new HashMap<>(); - for (int i = 0; i < dict.size(); i++) { - setString(dict.key(i), dict.value(i)); - } - } - - - /** - * Construct a JSONObject from an Object using bean getters. - * It reflects on all of the public methods of the object. - * For each of the methods with no parameters and a name starting - * with "get" or "is" followed by an uppercase letter, - * the method is invoked, and a key and the value returned from the getter method - * are put into the new JSONObject. - * - * The key is formed by removing the "get" or "is" prefix. - * If the second remaining character is not upper case, then the first - * character is converted to lower case. - * - * For example, if an object has a method named "getName", and - * if the result of calling object.getName() is "Larry Fine", - * then the JSONObject will contain "name": "Larry Fine". - * - * @param bean An object that has getter methods that should be used - * to make a JSONObject. - */ - protected JSONObject(Object bean) { - this(); - this.populateMap(bean); - } - - - // holding off on this method until we decide on how to handle reflection -// /** -// * Construct a JSONObject from an Object, using reflection to find the -// * public members. The resulting JSONObject's keys will be the strings -// * from the names array, and the values will be the field values associated -// * with those keys in the object. If a key is not found or not visible, -// * then it will not be copied into the new JSONObject. -// * @param object An object that has fields that should be used to make a -// * JSONObject. -// * @param names An array of strings, the names of the fields to be obtained -// * from the object. -// */ -// public JSONObject(Object object, String names[]) { -// this(); -// Class c = object.getClass(); -// for (int i = 0; i < names.length; i += 1) { -// String name = names[i]; -// try { -// this.putOpt(name, c.getField(name).get(object)); -// } catch (Exception ignore) { -// } -// } -// } - - - /** - * Construct a JSONObject from a source JSON text string. - * This is the most commonly used JSONObject constructor. - * @param source A string beginning - * with { (left brace) and ending - * with } (right brace). - * @exception RuntimeException If there is a syntax error in the source - * string or a duplicated key. - */ - static public JSONObject parse(String source) { - return new JSONObject(new JSONTokener(source)); - } - - -// /** -// * Construct a JSONObject from a ResourceBundle. -// * @param baseName The ResourceBundle base name. -// * @param locale The Locale to load the ResourceBundle for. -// * @throws JSONException If any JSONExceptions are detected. -// */ -// public JSON(String baseName, Locale locale) { -// this(); -// ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, -// Thread.currentThread().getContextClassLoader()); -// -// // Iterate through the keys in the bundle. -// -// Enumeration keys = bundle.getKeys(); -// while (keys.hasMoreElements()) { -// Object key = keys.nextElement(); -// if (key instanceof String) { -// -// // Go through the path, ensuring that there is a nested JSONObject for each -// // segment except the last. Add the value using the last segment's name into -// // the deepest nested JSONObject. -// -// String[] path = ((String)key).split("\\."); -// int last = path.length - 1; -// JSON target = this; -// for (int i = 0; i < last; i += 1) { -// String segment = path[i]; -// JSON nextTarget = target.optJSONObject(segment); -// if (nextTarget == null) { -// nextTarget = new JSON(); -// target.put(segment, nextTarget); -// } -// target = nextTarget; -// } -// target.put(path[last], bundle.getString((String)key)); -// } -// } -// } - - -// /** -// * Accumulate values under a key. It is similar to the put method except -// * that if there is already an object stored under the key then a -// * JSONArray is stored under the key to hold all of the accumulated values. -// * If there is already a JSONArray, then the new value is appended to it. -// * In contrast, the put method replaces the previous value. -// * -// * If only one value is accumulated that is not a JSONArray, then the -// * result will be the same as using put. But if multiple values are -// * accumulated, then the result will be like append. -// * @param key A key string. -// * @param value An object to be accumulated under the key. -// * @return this. -// * @throws JSONException If the value is an invalid number -// * or if the key is null. -// */ -// public JSONObject accumulate( -// String key, -// Object value -// ) throws JSONException { -// testValidity(value); -// Object object = this.opt(key); -// if (object == null) { -// this.put(key, value instanceof JSONArray -// ? new JSONArray().put(value) -// : value); -// } else if (object instanceof JSONArray) { -// ((JSONArray)object).put(value); -// } else { -// this.put(key, new JSONArray().put(object).put(value)); -// } -// return this; -// } - - -// /** -// * Append values to the array under a key. If the key does not exist in the -// * JSONObject, then the key is put in the JSONObject with its value being a -// * JSONArray containing the value parameter. If the key was already -// * associated with a JSONArray, then the value parameter is appended to it. -// * @param key A key string. -// * @param value An object to be accumulated under the key. -// * @return this. -// * @throws JSONException If the key is null or if the current value -// * associated with the key is not a JSONArray. -// */ -// public JSONObject append(String key, Object value) throws JSONException { -// testValidity(value); -// Object object = this.opt(key); -// if (object == null) { -// this.put(key, new JSONArray().put(value)); -// } else if (object instanceof JSONArray) { -// this.put(key, ((JSONArray)object).put(value)); -// } else { -// throw new JSONException("JSONObject[" + key + -// "] is not a JSONArray."); -// } -// return this; -// } - - - /** - * Produce a string from a double. The string "null" will be returned if - * the number is not finite. - * @param d A double. - * @return A String. - */ - static protected String doubleToString(double d) { - if (Double.isInfinite(d) || Double.isNaN(d)) { - return "null"; - } - - // Shave off trailing zeros and decimal point, if possible. - - String string = Double.toString(d); - if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && - string.indexOf('E') < 0) { - while (string.endsWith("0")) { - string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { - string = string.substring(0, string.length() - 1); - } - } - return string; - } - - - /** - * Get the value object associated with a key. - * - * @param key A key string. - * @return The object associated with the key. - * @throws RuntimeException if the key is not found. - */ - public Object get(String key) { - if (key == null) { - throw new RuntimeException("JSONObject.get(null) called"); - } - Object object = this.opt(key); - if (object == null) { - // Adding for rev 0257 in line with other p5 api - return null; - } - if (object == null) { - throw new RuntimeException("JSONObject[" + quote(key) + "] not found"); - } - return object; - } - - - /** - * Gets the String associated with a key - * - * @webref jsonobject:method - * @brief Gets the string value associated with a key - * @param key a key string - * @return A string which is the value. - * @throws RuntimeException if there is no string value for the key. - * @see JSONObject#getInt(String) - * @see JSONObject#getFloat(String) - * @see JSONObject#getBoolean(String) - */ - public String getString(String key) { - Object object = this.get(key); - if (object == null) { - // Adding for rev 0257 in line with other p5 api - return null; - } - if (object instanceof String) { - return (String)object; - } - throw new RuntimeException("JSONObject[" + quote(key) + "] is not a string"); - } - - - /** - * Get an optional string associated with a key. - * It returns the defaultValue if there is no such key. - * - * @param key A key string. - * @param defaultValue The default. - * @return A string which is the value. - */ - public String getString(String key, String defaultValue) { - Object object = this.opt(key); - return NULL.equals(object) ? defaultValue : object.toString(); - } - - - /** - * Gets the int value associated with a key - * - * @webref jsonobject:method - * @brief Gets the int value associated with a key - * @param key A key string. - * @return The integer value. - * @throws RuntimeException if the key is not found or if the value cannot - * be converted to an integer. - * @see JSONObject#getFloat(String) - * @see JSONObject#getString(String) - * @see JSONObject#getBoolean(String) - */ - public int getInt(String key) { - Object object = this.get(key); - if (object == null) { - throw new RuntimeException("JSONObject[" + quote(key) + "] not found"); - } - try { - return object instanceof Number ? - ((Number)object).intValue() : Integer.parseInt((String)object); - } catch (Exception e) { - throw new RuntimeException("JSONObject[" + quote(key) + "] is not an int."); - } - } - - - /** - * Get an optional int value associated with a key, - * or the default if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public int getInt(String key, int defaultValue) { - try { - return this.getInt(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the long value associated with a key. - * - * @param key A key string. - * @return The long value. - * @throws RuntimeException if the key is not found or if the value cannot - * be converted to a long. - */ - public long getLong(String key) { - Object object = this.get(key); - try { - return object instanceof Number - ? ((Number)object).longValue() - : Long.parseLong((String)object); - } catch (Exception e) { - throw new RuntimeException("JSONObject[" + quote(key) + "] is not a long.", e); - } - } - - - /** - * Get an optional long value associated with a key, - * or the default if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public long getLong(String key, long defaultValue) { - try { - return this.getLong(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * @webref jsonobject:method - * @brief Gets the float value associated with a key - * @param key a key string - * @see JSONObject#getInt(String) - * @see JSONObject#getString(String) - * @see JSONObject#getBoolean(String) - */ - public float getFloat(String key) { - return (float) getDouble(key); - } - - - public float getFloat(String key, float defaultValue) { - try { - return getFloat(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the double value associated with a key. - * @param key A key string. - * @return The numeric value. - * @throws RuntimeException if the key is not found or - * if the value is not a Number object and cannot be converted to a number. - */ - public double getDouble(String key) { - Object object = this.get(key); - try { - return object instanceof Number - ? ((Number)object).doubleValue() - : Double.parseDouble((String)object); - } catch (Exception e) { - throw new RuntimeException("JSONObject[" + quote(key) + "] is not a number."); - } - } - - - /** - * Get an optional double associated with a key, or the - * defaultValue if there is no such key or if its value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public double getDouble(String key, double defaultValue) { - try { - return this.getDouble(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the boolean value associated with a key. - * - * @webref jsonobject:method - * @brief Gets the boolean value associated with a key - * @param key a key string - * @return The truth. - * @throws RuntimeException if the value is not a Boolean or the String "true" or "false". - * @see JSONObject#getInt(String) - * @see JSONObject#getFloat(String) - * @see JSONObject#getString(String) - */ - public boolean getBoolean(String key) { - Object object = this.get(key); - if (object.equals(Boolean.FALSE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("true"))) { - return true; - } - throw new RuntimeException("JSONObject[" + quote(key) + "] is not a Boolean."); - } - - - /** - * Get an optional boolean associated with a key. - * It returns the defaultValue if there is no such key, or if it is not - * a Boolean or the String "true" or "false" (case insensitive). - * - * @param key A key string. - * @param defaultValue The default. - * @return The truth. - */ - public boolean getBoolean(String key, boolean defaultValue) { - try { - return this.getBoolean(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the JSONArray value associated with a key. - * - * @webref jsonobject:method - * @brief Gets the JSONArray value associated with a key - * @param key a key string - * @return A JSONArray which is the value, or null if not present - * @throws RuntimeException if the value is not a JSONArray. - * @see JSONObject#getJSONObject(String) - * @see JSONObject#setJSONObject(String, JSONObject) - * @see JSONObject#setJSONArray(String, JSONArray) - */ - public JSONArray getJSONArray(String key) { - Object object = this.get(key); - if (object == null) { - return null; - } - if (object instanceof JSONArray) { - return (JSONArray)object; - } - throw new RuntimeException("JSONObject[" + quote(key) + "] is not a JSONArray."); - } - - - /** - * Get the JSONObject value associated with a key. - * - * @webref jsonobject:method - * @brief Gets the JSONObject value associated with a key - * @param key a key string - * @return A JSONObject which is the value or null if not available. - * @throws RuntimeException if the value is not a JSONObject. - * @see JSONObject#getJSONArray(String) - * @see JSONObject#setJSONObject(String, JSONObject) - * @see JSONObject#setJSONArray(String, JSONArray) - */ - public JSONObject getJSONObject(String key) { - Object object = this.get(key); - if (object == null) { - return null; - } - if (object instanceof JSONObject) { - return (JSONObject)object; - } - throw new RuntimeException("JSONObject[" + quote(key) + "] is not a JSONObject."); - } - - -// /** -// * Get an array of field names from a JSONObject. -// * -// * @return An array of field names, or null if there are no names. -// */ -// public static String[] getNames(JSONObject jo) { -// int length = jo.length(); -// if (length == 0) { -// return null; -// } -// Iterator iterator = jo.keys(); -// String[] names = new String[length]; -// int i = 0; -// while (iterator.hasNext()) { -// names[i] = (String)iterator.next(); -// i += 1; -// } -// return names; -// } -// -// -// /** -// * Get an array of field names from an Object. -// * -// * @return An array of field names, or null if there are no names. -// */ -// public static String[] getNames(Object object) { -// if (object == null) { -// return null; -// } -// Class klass = object.getClass(); -// Field[] fields = klass.getFields(); -// int length = fields.length; -// if (length == 0) { -// return null; -// } -// String[] names = new String[length]; -// for (int i = 0; i < length; i += 1) { -// names[i] = fields[i].getName(); -// } -// return names; -// } - - - /** - * Determine if the JSONObject contains a specific key. - * @param key A key string. - * @return true if the key exists in the JSONObject. - */ - public boolean hasKey(String key) { - return map.containsKey(key); - } - - -// /** -// * Increment a property of a JSONObject. If there is no such property, -// * create one with a value of 1. If there is such a property, and if -// * it is an Integer, Long, Double, or Float, then add one to it. -// * @param key A key string. -// * @return this. -// * @throws JSONException If there is already a property with this name -// * that is not an Integer, Long, Double, or Float. -// */ -// public JSON increment(String key) { -// Object value = this.opt(key); -// if (value == null) { -// this.put(key, 1); -// } else if (value instanceof Integer) { -// this.put(key, ((Integer)value).intValue() + 1); -// } else if (value instanceof Long) { -// this.put(key, ((Long)value).longValue() + 1); -// } else if (value instanceof Double) { -// this.put(key, ((Double)value).doubleValue() + 1); -// } else if (value instanceof Float) { -// this.put(key, ((Float)value).floatValue() + 1); -// } else { -// throw new RuntimeException("Unable to increment [" + quote(key) + "]."); -// } -// return this; -// } - - - /** - * Determine if the value associated with the key is null or if there is - * no value. - * - * @webref - * @param key A key string. - * @return true if there is no value associated with the key or if - * the value is the JSONObject.NULL object. - */ - public boolean isNull(String key) { - return JSONObject.NULL.equals(this.opt(key)); - } - - - /** - * Get an enumeration of the keys of the JSONObject. - * - * @return An iterator of the keys. - */ - public Iterator keyIterator() { -// return this.keySet().iterator(); - return map.keySet().iterator(); - } - - - /** - * Get a set of keys of the JSONObject. - * - * @return A keySet. - */ - public Set keys() { - return this.map.keySet(); - } - - - /** - * Get the number of keys stored in the JSONObject. - * - * @return The number of keys in the JSONObject. - */ - public int size() { - return this.map.size(); - } - - -// /** -// * Produce a JSONArray containing the names of the elements of this -// * JSONObject. -// * @return A JSONArray containing the key strings, or null if the JSONObject -// * is empty. -// */ -// public JSONArray names() { -// JSONArray ja = new JSONArray(); -// Iterator keys = this.keys(); -// while (keys.hasNext()) { -// ja.append(keys.next()); -// } -// return ja.size() == 0 ? null : ja; -// } - - - /** - * Produce a string from a Number. - * @param number A Number - * @return A String. - * @throws RuntimeException If number is null or a non-finite number. - */ - private static String numberToString(Number number) { - if (number == null) { - throw new RuntimeException("Null pointer"); - } - testValidity(number); - - // Shave off trailing zeros and decimal point, if possible. - - String string = number.toString(); - if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && - string.indexOf('E') < 0) { - while (string.endsWith("0")) { - string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { - string = string.substring(0, string.length() - 1); - } - } - return string; - } - - - /** - * Get an optional value associated with a key. - * @param key A key string. - * @return An object which is the value, or null if there is no value. - */ - private Object opt(String key) { - return key == null ? null : this.map.get(key); - } - - -// /** -// * Get an optional boolean associated with a key. -// * It returns false if there is no such key, or if the value is not -// * Boolean.TRUE or the String "true". -// * -// * @param key A key string. -// * @return The truth. -// */ -// private boolean optBoolean(String key) { -// return this.optBoolean(key, false); -// } - - -// /** -// * Get an optional double associated with a key, -// * or NaN if there is no such key or if its value is not a number. -// * If the value is a string, an attempt will be made to evaluate it as -// * a number. -// * -// * @param key A string which is the key. -// * @return An object which is the value. -// */ -// private double optDouble(String key) { -// return this.optDouble(key, Double.NaN); -// } - - -// /** -// * Get an optional int value associated with a key, -// * or zero if there is no such key or if the value is not a number. -// * If the value is a string, an attempt will be made to evaluate it as -// * a number. -// * -// * @param key A key string. -// * @return An object which is the value. -// */ -// private int optInt(String key) { -// return this.optInt(key, 0); -// } - - -// /** -// * Get an optional JSONArray associated with a key. -// * It returns null if there is no such key, or if its value is not a -// * JSONArray. -// * -// * @param key A key string. -// * @return A JSONArray which is the value. -// */ -// private JSONArray optJSONArray(String key) { -// Object o = this.opt(key); -// return o instanceof JSONArray ? (JSONArray)o : null; -// } - - -// /** -// * Get an optional JSONObject associated with a key. -// * It returns null if there is no such key, or if its value is not a -// * JSONObject. -// * -// * @param key A key string. -// * @return A JSONObject which is the value. -// */ -// private JSONObject optJSONObject(String key) { -// Object object = this.opt(key); -// return object instanceof JSONObject ? (JSONObject)object : null; -// } - - -// /** -// * Get an optional long value associated with a key, -// * or zero if there is no such key or if the value is not a number. -// * If the value is a string, an attempt will be made to evaluate it as -// * a number. -// * -// * @param key A key string. -// * @return An object which is the value. -// */ -// public long optLong(String key) { -// return this.optLong(key, 0); -// } - - -// /** -// * Get an optional string associated with a key. -// * It returns an empty string if there is no such key. If the value is not -// * a string and is not null, then it is converted to a string. -// * -// * @param key A key string. -// * @return A string which is the value. -// */ -// public String optString(String key) { -// return this.optString(key, ""); -// } - - - private void populateMap(Object bean) { - Class klass = bean.getClass(); - - // If klass is a System class then set includeSuperClass to false. - - boolean includeSuperClass = klass.getClassLoader() != null; - - Method[] methods = includeSuperClass - ? klass.getMethods() - : klass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i += 1) { - try { - Method method = methods[i]; - if (Modifier.isPublic(method.getModifiers())) { - String name = method.getName(); - String key = ""; - if (name.startsWith("get")) { - if ("getClass".equals(name) || - "getDeclaringClass".equals(name)) { - key = ""; - } else { - key = name.substring(3); - } - } else if (name.startsWith("is")) { - key = name.substring(2); - } - if (key.length() > 0 && - Character.isUpperCase(key.charAt(0)) && - method.getParameterTypes().length == 0) { - if (key.length() == 1) { - key = key.toLowerCase(); - } else if (!Character.isUpperCase(key.charAt(1))) { - key = key.substring(0, 1).toLowerCase() + - key.substring(1); - } - - Object result = method.invoke(bean, (Object[])null); - if (result != null) { - this.map.put(key, wrap(result)); - } - } - } - } catch (Exception ignore) { - } - } - } - - - /** - * @webref jsonobject:method - * @brief Put a key/String pair in the JSONObject - * @param key a key string - * @param value the value to assign - * @see JSONObject#setInt(String, int) - * @see JSONObject#setFloat(String, float) - * @see JSONObject#setBoolean(String, boolean) - */ - public JSONObject setString(String key, String value) { - return put(key, value); - } - - - /** - * Put a key/int pair in the JSONObject. - * - * @webref jsonobject:method - * @brief Put a key/int pair in the JSONObject - * @param key a key string - * @param value the value to assign - * @return this. - * @throws RuntimeException If the key is null. - * @see JSONObject#setFloat(String, float) - * @see JSONObject#setString(String, String) - * @see JSONObject#setBoolean(String, boolean) - */ - public JSONObject setInt(String key, int value) { - this.put(key, Integer.valueOf(value)); - return this; - } - - - /** - * Put a key/long pair in the JSONObject. - * - * @param key A key string. - * @param value A long which is the value. - * @return this. - * @throws RuntimeException If the key is null. - */ - public JSONObject setLong(String key, long value) { - this.put(key, Long.valueOf(value)); - return this; - } - - /** - * @webref jsonobject:method - * @brief Put a key/float pair in the JSONObject - * @param key a key string - * @param value the value to assign - * @throws RuntimeException If the key is null or if the number is NaN or infinite. - * @see JSONObject#setInt(String, int) - * @see JSONObject#setString(String, String) - * @see JSONObject#setBoolean(String, boolean) - */ - public JSONObject setFloat(String key, float value) { - this.put(key, Double.valueOf(value)); - return this; - } - - - /** - * Put a key/double pair in the JSONObject. - * - * @param key A key string. - * @param value A double which is the value. - * @return this. - * @throws RuntimeException If the key is null or if the number is NaN or infinite. - */ - public JSONObject setDouble(String key, double value) { - this.put(key, Double.valueOf(value)); - return this; - } - - - /** - * Put a key/boolean pair in the JSONObject. - * - * @webref jsonobject:method - * @brief Put a key/boolean pair in the JSONObject - * @param key a key string - * @param value the value to assign - * @return this. - * @throws RuntimeException If the key is null. - * @see JSONObject#setInt(String, int) - * @see JSONObject#setFloat(String, float) - * @see JSONObject#setString(String, String) - */ - public JSONObject setBoolean(String key, boolean value) { - this.put(key, value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - /** - * @webref jsonobject:method - * @brief Sets the JSONObject value associated with a key - * @param key a key string - * @param value value to assign - * @see JSONObject#setJSONArray(String, JSONArray) - * @see JSONObject#getJSONObject(String) - * @see JSONObject#getJSONArray(String) - */ - public JSONObject setJSONObject(String key, JSONObject value) { - return put(key, value); - } - - /** - * @webref jsonobject:method - * @brief Sets the JSONArray value associated with a key - * @param key a key string - * @param value value to assign - * @see JSONObject#setJSONObject(String, JSONObject) - * @see JSONObject#getJSONObject(String) - * @see JSONObject#getJSONArray(String) - */ - public JSONObject setJSONArray(String key, JSONArray value) { - return put(key, value); - } - - -// /** -// * Put a key/value pair in the JSONObject, where the value will be a -// * JSONArray which is produced from a Collection. -// * @param key A key string. -// * @param value A Collection value. -// * @return this. -// * @throws JSONException -// */ -// public JSONObject put(String key, Collection value) { -// this.put(key, new JSONArray(value)); -// return this; -// } - - -// /** -// * Put a key/value pair in the JSONObject, where the value will be a -// * JSONObject which is produced from a Map. -// * @param key A key string. -// * @param value A Map value. -// * @return this. -// * @throws JSONException -// */ -// //public JSONObject put(String key, HashMap value) { -// public JSONObject put(String key, Map value) { -// this.put(key, new JSONObject(value)); -// return this; -// } - - - /** - * Put a key/value pair in the JSONObject. If the value is null, - * then the key will be removed from the JSONObject if it is present. - * @param key A key string. - * @param value An object which is the value. It should be of one of these - * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, - * or the JSONObject.NULL object. - * @return this. - * @throws RuntimeException If the value is non-finite number - * or if the key is null. - */ - public JSONObject put(String key, Object value) { - String pooled; - if (key == null) { - throw new RuntimeException("Null key."); - } - if (value != null) { - testValidity(value); - pooled = (String)keyPool.get(key); - if (pooled == null) { - if (keyPool.size() >= keyPoolSize) { - keyPool = new HashMap<>(keyPoolSize); - } - keyPool.put(key, key); - } else { - key = pooled; - } - this.map.put(key, value); - } else { - this.remove(key); - } - return this; - } - - - /** - * Put a key/value pair in the JSONObject, but only if the key and the - * value are both non-null, and only if there is not already a member - * with that name. - * @param key - * @param value - * @return {@code this}. - * @throws RuntimeException if the key is a duplicate, or if - * {@link #put(String,Object)} throws. - */ - private JSONObject putOnce(String key, Object value) { - if (key != null && value != null) { - if (this.opt(key) != null) { - throw new RuntimeException("Duplicate key \"" + key + "\""); - } - this.put(key, value); - } - return this; - } - - -// /** -// * Put a key/value pair in the JSONObject, but only if the -// * key and the value are both non-null. -// * @param key A key string. -// * @param value An object which is the value. It should be of one of these -// * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, -// * or the JSONObject.NULL object. -// * @return this. -// * @throws JSONException If the value is a non-finite number. -// */ -// public JSONObject putOpt(String key, Object value) { -// if (key != null && value != null) { -// this.put(key, value); -// } -// return this; -// } - - - /** - * Produce a string in double quotes with backslash sequences in all the - * right places. A backslash will be inserted within = '\u0080' && c < '\u00a0') - || (c >= '\u2000' && c < '\u2100')) { - w.write("\\u"); - hhhh = Integer.toHexString(c); - w.write("0000", 0, 4 - hhhh.length()); - w.write(hhhh); - } else { - w.write(c); - } - } - } - w.write('"'); - return w; - } - - - /** - * Remove a name and its value, if present. - * @param key The name to be removed. - * @return The value that was associated with the name, - * or null if there was no value. - */ - public Object remove(String key) { - return this.map.remove(key); - } - - - /** - * Try to convert a string into a number, boolean, or null. If the string - * can't be converted, return the string. - * @param string A String. - * @return A simple JSON value. - */ - static protected Object stringToValue(String string) { - Double d; - if (string.equals("")) { - return string; - } - if (string.equalsIgnoreCase("true")) { - return Boolean.TRUE; - } - if (string.equalsIgnoreCase("false")) { - return Boolean.FALSE; - } - if (string.equalsIgnoreCase("null")) { - return JSONObject.NULL; - } - - /* - * If it might be a number, try converting it. - * If a number cannot be produced, then the value will just - * be a string. Note that the plus and implied string - * conventions are non-standard. A JSON parser may accept - * non-JSON forms as long as it accepts all correct JSON forms. - */ - - char b = string.charAt(0); - if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') { - try { - if (string.indexOf('.') > -1 || - string.indexOf('e') > -1 || string.indexOf('E') > -1) { - d = Double.valueOf(string); - if (!d.isInfinite() && !d.isNaN()) { - return d; - } - } else { - Long myLong = Long.valueOf(string); - if (myLong.longValue() == myLong.intValue()) { - return Integer.valueOf(myLong.intValue()); - } else { - return myLong; - } - } - } catch (Exception ignore) { - } - } - return string; - } - - - /** - * Throw an exception if the object is a NaN or infinite number. - * @param o The object to test. If not Float or Double, accepted without - * exceptions. - * @throws RuntimeException If o is infinite or NaN. - */ - static protected void testValidity(Object o) { - if (o != null) { - if (o instanceof Double) { - if (((Double)o).isInfinite() || ((Double)o).isNaN()) { - throw new RuntimeException( - "JSON does not allow non-finite numbers."); - } - } else if (o instanceof Float) { - if (((Float)o).isInfinite() || ((Float)o).isNaN()) { - throw new RuntimeException( - "JSON does not allow non-finite numbers."); - } - } - } - } - - -// /** -// * Produce a JSONArray containing the values of the members of this -// * JSONObject. -// * @param names A JSONArray containing a list of key strings. This -// * determines the sequence of the values in the result. -// * @return A JSONArray of values. -// * @throws JSONException If any of the values are non-finite numbers. -// */ -// public JSONArray toJSONArray(JSONArray names) { -// if (names == null || names.size() == 0) { -// return null; -// } -// JSONArray ja = new JSONArray(); -// for (int i = 0; i < names.size(); i += 1) { -// ja.append(this.opt(names.getString(i))); -// } -// return ja; -// } - - -// protected boolean save(OutputStream output) { -// return save(PApplet.createWriter(output)); -// } - - - public boolean save(File file, String options) { - PrintWriter writer = PApplet.createWriter(file); - boolean success = write(writer, options); - writer.close(); - return success; - } - - - public boolean write(PrintWriter output) { - return write(output, null); - } - - - public boolean write(PrintWriter output, String options) { - int indentFactor = 2; - if (options != null) { - String[] opts = PApplet.split(options, ','); - for (String opt : opts) { - if (opt.equals("compact")) { - indentFactor = -1; - } else if (opt.startsWith("indent=")) { - indentFactor = PApplet.parseInt(opt.substring(7), -2); - if (indentFactor == -2) { - throw new IllegalArgumentException("Could not read a number from " + opt); - } - } else { - System.err.println("Ignoring " + opt); - } - } - } - output.print(format(indentFactor)); - output.flush(); - return true; - } - - - /** - * Return the JSON data formatted with two spaces for indents. - * Chosen to do this since it's the most common case (e.g. with println()). - * Same as format(2). Use the format() function for more options. - */ - @Override - public String toString() { - try { - return format(2); - } catch (Exception e) { - return null; - } - } - - - /** - * Make a prettyprinted JSON text of this JSONObject. - *

    - * Warning: This method assumes that the data structure is acyclical. - * @param indentFactor The number of spaces to add to each level of - * indentation. - * @return a printable, displayable, portable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - * @throws RuntimeException If the object contains an invalid number. - */ - public String format(int indentFactor) { - StringWriter w = new StringWriter(); - synchronized (w.getBuffer()) { - return this.writeInternal(w, indentFactor, 0).toString(); - } - } - - /** - * Make a JSON text of an Object value. If the object has an - * value.toJSONString() method, then that method will be used to produce - * the JSON text. The method is required to produce a strictly - * conforming text. If the object does not contain a toJSONString - * method (which is the most common case), then a text will be - * produced by other means. If the value is an array or Collection, - * then a JSONArray will be made from it and its toJSONString method - * will be called. If the value is a MAP, then a JSONObject will be made - * from it and its toJSONString method will be called. Otherwise, the - * value's toString method will be called, and the result will be quoted. - * - *

    - * Warning: This method assumes that the data structure is acyclical. - * @param value The value to be serialized. - * @return a printable, displayable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - * @throws RuntimeException If the value is or contains an invalid number. - */ - static protected String valueToString(Object value) { - if (value == null || value.equals(null)) { - return "null"; - } -// if (value instanceof JSONString) { -// Object object; -// try { -// object = ((JSONString)value).toJSONString(); -// } catch (Exception e) { -// throw new RuntimeException(e); -// } -// if (object instanceof String) { -// return (String)object; -// } -// throw new RuntimeException("Bad value from toJSONString: " + object); -// } - if (value instanceof Number) { - return numberToString((Number) value); - } - if (value instanceof Boolean || value instanceof JSONObject || - value instanceof JSONArray) { - return value.toString(); - } - if (value instanceof Map) { - return new JSONObject(value).toString(); - } - if (value instanceof Collection) { - return new JSONArray(value).toString(); - } - if (value.getClass().isArray()) { - return new JSONArray(value).toString(); - } - return quote(value.toString()); - } - - /** - * Wrap an object, if necessary. If the object is null, return the NULL - * object. If it is an array or collection, wrap it in a JSONArray. If - * it is a map, wrap it in a JSONObject. If it is a standard property - * (Double, String, et al) then it is already wrapped. Otherwise, if it - * comes from one of the java packages, turn it into a string. And if - * it doesn't, try to wrap it in a JSONObject. If the wrapping fails, - * then null is returned. - * - * @param object The object to wrap - * @return The wrapped value - */ - static protected Object wrap(Object object) { - try { - if (object == null) { - return NULL; - } - if (object instanceof JSONObject || object instanceof JSONArray || - NULL.equals(object) || /*object instanceof JSONString ||*/ - object instanceof Byte || object instanceof Character || - object instanceof Short || object instanceof Integer || - object instanceof Long || object instanceof Boolean || - object instanceof Float || object instanceof Double || - object instanceof String) { - return object; - } - - if (object instanceof Collection) { - return new JSONArray(object); - } - if (object.getClass().isArray()) { - return new JSONArray(object); - } - if (object instanceof Map) { - return new JSONObject(object); - } - Package objectPackage = object.getClass().getPackage(); - String objectPackageName = objectPackage != null - ? objectPackage.getName() - : ""; - if ( - objectPackageName.startsWith("java.") || - objectPackageName.startsWith("javax.") || - object.getClass().getClassLoader() == null - ) { - return object.toString(); - } - return new JSONObject(object); - } catch(Exception exception) { - return null; - } - } - - -// /** -// * Write the contents of the JSONObject as JSON text to a writer. -// * For compactness, no whitespace is added. -// *

    -// * Warning: This method assumes that the data structure is acyclical. -// * -// * @return The writer. -// * @throws JSONException -// */ -// protected Writer write(Writer writer) { -// return this.write(writer, 0, 0); -// } - - - static final Writer writeValue(Writer writer, Object value, - int indentFactor, int indent) throws IOException { - if (value == null || value.equals(null)) { - writer.write("null"); - } else if (value instanceof JSONObject) { - ((JSONObject) value).writeInternal(writer, indentFactor, indent); - } else if (value instanceof JSONArray) { - ((JSONArray) value).writeInternal(writer, indentFactor, indent); - } else if (value instanceof Map) { - new JSONObject(value).writeInternal(writer, indentFactor, indent); - } else if (value instanceof Collection) { - new JSONArray(value).writeInternal(writer, indentFactor, - indent); - } else if (value.getClass().isArray()) { - new JSONArray(value).writeInternal(writer, indentFactor, indent); - } else if (value instanceof Number) { - writer.write(numberToString((Number) value)); - } else if (value instanceof Boolean) { - writer.write(value.toString()); - /* - } else if (value instanceof JSONString) { - Object o; - try { - o = ((JSONString) value).toJSONString(); - } catch (Exception e) { - throw new RuntimeException(e); - } - writer.write(o != null ? o.toString() : quote(value.toString())); - */ - } else { - quote(value.toString(), writer); - } - return writer; - } - - - static final void indent(Writer writer, int indent) throws IOException { - for (int i = 0; i < indent; i += 1) { - writer.write(' '); - } - } - - /** - * Write the contents of the JSONObject as JSON text to a writer. - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws RuntimeException - */ - protected Writer writeInternal(Writer writer, int indentFactor, int indent) { - try { - boolean commanate = false; - final int length = this.size(); - Iterator keys = this.keyIterator(); - writer.write('{'); - - int actualFactor = (indentFactor == -1) ? 0 : indentFactor; - - if (length == 1) { - Object key = keys.next(); - writer.write(quote(key.toString())); - writer.write(':'); - if (actualFactor > 0) { - writer.write(' '); - } - //writeValue(writer, this.map.get(key), actualFactor, indent); - writeValue(writer, this.map.get(key), indentFactor, indent); - } else if (length != 0) { - final int newIndent = indent + actualFactor; - while (keys.hasNext()) { - Object key = keys.next(); - if (commanate) { - writer.write(','); - } - if (indentFactor != -1) { - writer.write('\n'); - } - indent(writer, newIndent); - writer.write(quote(key.toString())); - writer.write(':'); - if (actualFactor > 0) { - writer.write(' '); - } - //writeValue(writer, this.map.get(key), actualFactor, newIndent); - writeValue(writer, this.map.get(key), indentFactor, newIndent); - commanate = true; - } - if (indentFactor != -1) { - writer.write('\n'); - } - indent(writer, indent); - } - writer.write('}'); - return writer; - } catch (IOException exception) { - throw new RuntimeException(exception); - } - } - - -// // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -// -// -// class JSONException extends RuntimeException { -// -// public JSONException(String message) { -// super(message); -// } -// -// public JSONException(Throwable throwable) { -// super(throwable); -// } -// } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - -// /** -// * Get the hex value of a character (base16). -// * @param c A character between '0' and '9' or between 'A' and 'F' or -// * between 'a' and 'f'. -// * @return An int between 0 and 15, or -1 if c was not a hex digit. -// */ -// static protected int dehexchar(char c) { -// if (c >= '0' && c <= '9') { -// return c - '0'; -// } -// if (c >= 'A' && c <= 'F') { -// return c - ('A' - 10); -// } -// if (c >= 'a' && c <= 'f') { -// return c - ('a' - 10); -// } -// return -1; -// } - - -// static class JSONTokener { -// private long character; -// private boolean eof; -// private long index; -// private long line; -// private char previous; -// private Reader reader; -// private boolean usePrevious; -// -// -// /** -// * Construct a JSONTokener from a Reader. -// * -// * @param reader A reader. -// */ -// public JSONTokener(Reader reader) { -// this.reader = reader.markSupported() -// ? reader -// : new BufferedReader(reader); -// this.eof = false; -// this.usePrevious = false; -// this.previous = 0; -// this.index = 0; -// this.character = 1; -// this.line = 1; -// } -// -// -// /** -// * Construct a JSONTokener from an InputStream. -// */ -// public JSONTokener(InputStream inputStream) { -// this(new InputStreamReader(inputStream)); -// } -// -// -// /** -// * Construct a JSONTokener from a string. -// * -// * @param s A source string. -// */ -// public JSONTokener(String s) { -// this(new StringReader(s)); -// } -// -// -// /** -// * Back up one character. This provides a sort of lookahead capability, -// * so that you can test for a digit or letter before attempting to parse -// * the next number or identifier. -// */ -// public void back() { -// if (this.usePrevious || this.index <= 0) { -// throw new RuntimeException("Stepping back two steps is not supported"); -// } -// this.index -= 1; -// this.character -= 1; -// this.usePrevious = true; -// this.eof = false; -// } -// -// -// public boolean end() { -// return this.eof && !this.usePrevious; -// } -// -// -// /** -// * Determine if the source string still contains characters that next() -// * can consume. -// * @return true if not yet at the end of the source. -// */ -// public boolean more() { -// this.next(); -// if (this.end()) { -// return false; -// } -// this.back(); -// return true; -// } -// -// -// /** -// * Get the next character in the source string. -// * -// * @return The next character, or 0 if past the end of the source string. -// */ -// public char next() { -// int c; -// if (this.usePrevious) { -// this.usePrevious = false; -// c = this.previous; -// } else { -// try { -// c = this.reader.read(); -// } catch (IOException exception) { -// throw new RuntimeException(exception); -// } -// -// if (c <= 0) { // End of stream -// this.eof = true; -// c = 0; -// } -// } -// this.index += 1; -// if (this.previous == '\r') { -// this.line += 1; -// this.character = c == '\n' ? 0 : 1; -// } else if (c == '\n') { -// this.line += 1; -// this.character = 0; -// } else { -// this.character += 1; -// } -// this.previous = (char) c; -// return this.previous; -// } -// -// -// /** -// * Consume the next character, and check that it matches a specified -// * character. -// * @param c The character to match. -// * @return The character. -// * @throws JSONException if the character does not match. -// */ -// public char next(char c) { -// char n = this.next(); -// if (n != c) { -// throw new RuntimeException("Expected '" + c + "' and instead saw '" + n + "'"); -// } -// return n; -// } -// -// -// /** -// * Get the next n characters. -// * -// * @param n The number of characters to take. -// * @return A string of n characters. -// * @throws JSONException -// * Substring bounds error if there are not -// * n characters remaining in the source string. -// */ -// public String next(int n) { -// if (n == 0) { -// return ""; -// } -// -// char[] chars = new char[n]; -// int pos = 0; -// -// while (pos < n) { -// chars[pos] = this.next(); -// if (this.end()) { -// throw new RuntimeException("Substring bounds error"); -// } -// pos += 1; -// } -// return new String(chars); -// } -// -// -// /** -// * Get the next char in the string, skipping whitespace. -// * @throws JSONException -// * @return A character, or 0 if there are no more characters. -// */ -// public char nextClean() { -// for (;;) { -// char c = this.next(); -// if (c == 0 || c > ' ') { -// return c; -// } -// } -// } -// -// -// /** -// * Return the characters up to the next close quote character. -// * Backslash processing is done. The formal JSON format does not -// * allow strings in single quotes, but an implementation is allowed to -// * accept them. -// * @param quote The quoting character, either -// * " (double quote) or -// * ' (single quote). -// * @return A String. -// * @throws JSONException Unterminated string. -// */ -// public String nextString(char quote) { -// char c; -// StringBuffer sb = new StringBuffer(); -// for (;;) { -// c = this.next(); -// switch (c) { -// case 0: -// case '\n': -// case '\r': -// throw new RuntimeException("Unterminated string"); -// case '\\': -// c = this.next(); -// switch (c) { -// case 'b': -// sb.append('\b'); -// break; -// case 't': -// sb.append('\t'); -// break; -// case 'n': -// sb.append('\n'); -// break; -// case 'f': -// sb.append('\f'); -// break; -// case 'r': -// sb.append('\r'); -// break; -// case 'u': -// sb.append((char)Integer.parseInt(this.next(4), 16)); -// break; -// case '"': -// case '\'': -// case '\\': -// case '/': -// sb.append(c); -// break; -// default: -// throw new RuntimeException("Illegal escape."); -// } -// break; -// default: -// if (c == quote) { -// return sb.toString(); -// } -// sb.append(c); -// } -// } -// } -// -// -// /** -// * Get the text up but not including the specified character or the -// * end of line, whichever comes first. -// * @param delimiter A delimiter character. -// * @return A string. -// */ -// public String nextTo(char delimiter) { -// StringBuffer sb = new StringBuffer(); -// for (;;) { -// char c = this.next(); -// if (c == delimiter || c == 0 || c == '\n' || c == '\r') { -// if (c != 0) { -// this.back(); -// } -// return sb.toString().trim(); -// } -// sb.append(c); -// } -// } -// -// -// /** -// * Get the text up but not including one of the specified delimiter -// * characters or the end of line, whichever comes first. -// * @param delimiters A set of delimiter characters. -// * @return A string, trimmed. -// */ -// public String nextTo(String delimiters) { -// char c; -// StringBuffer sb = new StringBuffer(); -// for (;;) { -// c = this.next(); -// if (delimiters.indexOf(c) >= 0 || c == 0 || -// c == '\n' || c == '\r') { -// if (c != 0) { -// this.back(); -// } -// return sb.toString().trim(); -// } -// sb.append(c); -// } -// } -// -// -// /** -// * Get the next value. The value can be a Boolean, Double, Integer, -// * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. -// * @throws JSONException If syntax error. -// * -// * @return An object. -// */ -// public Object nextValue() { -// char c = this.nextClean(); -// String string; -// -// switch (c) { -// case '"': -// case '\'': -// return this.nextString(c); -// case '{': -// this.back(); -// return new JSONObject(this); -// case '[': -// this.back(); -// return new JSONArray(this); -// } -// -// /* -// * Handle unquoted text. This could be the values true, false, or -// * null, or it can be a number. An implementation (such as this one) -// * is allowed to also accept non-standard forms. -// * -// * Accumulate characters until we reach the end of the text or a -// * formatting character. -// */ -// -// StringBuffer sb = new StringBuffer(); -// while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { -// sb.append(c); -// c = this.next(); -// } -// this.back(); -// -// string = sb.toString().trim(); -// if ("".equals(string)) { -// throw new RuntimeException("Missing value"); -// } -// return JSONObject.stringToValue(string); -// } -// -// -// /** -// * Skip characters until the next character is the requested character. -// * If the requested character is not found, no characters are skipped. -// * @param to A character to skip to. -// * @return The requested character, or zero if the requested character -// * is not found. -// */ -// public char skipTo(char to) { -// char c; -// try { -// long startIndex = this.index; -// long startCharacter = this.character; -// long startLine = this.line; -// this.reader.mark(1000000); -// do { -// c = this.next(); -// if (c == 0) { -// this.reader.reset(); -// this.index = startIndex; -// this.character = startCharacter; -// this.line = startLine; -// return c; -// } -// } while (c != to); -// } catch (IOException exc) { -// throw new RuntimeException(exc); -// } -// -// this.back(); -// return c; -// } -// -// -// /** -// * Make a printable string of this JSONTokener. -// * -// * @return " at {index} [character {character} line {line}]" -// */ -// @Override -// public String toString() { -// return " at " + this.index + " [character " + this.character + " line " + -// this.line + "]"; -// } -// } -} diff --git a/core/src/processing/data/JSONTokener.java b/core/src/processing/data/JSONTokener.java deleted file mode 100644 index 5301a5e3c..000000000 --- a/core/src/processing/data/JSONTokener.java +++ /dev/null @@ -1,435 +0,0 @@ -package processing.data; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - */ - -/** - * A JSONTokener takes a source string and extracts characters and tokens from - * it. It is used by the JSONObject and JSONArray constructors to parse - * JSON source strings. - * @author JSON.org - * @version 2012-02-16 - */ -class JSONTokener { - - private long character; - private boolean eof; - private long index; - private long line; - private char previous; - private Reader reader; - private boolean usePrevious; - - - /** - * Construct a JSONTokener from a Reader. - * - * @param reader A reader. - */ - public JSONTokener(Reader reader) { - this.reader = reader.markSupported() - ? reader - : new BufferedReader(reader); - this.eof = false; - this.usePrevious = false; - this.previous = 0; - this.index = 0; - this.character = 1; - this.line = 1; - } - - - /** - * Construct a JSONTokener from an InputStream. - */ - public JSONTokener(InputStream inputStream) { - this(new InputStreamReader(inputStream)); - } - - - /** - * Construct a JSONTokener from a string. - * - * @param s A source string. - */ - public JSONTokener(String s) { - this(new StringReader(s)); - } - - - /** - * Back up one character. This provides a sort of lookahead capability, - * so that you can test for a digit or letter before attempting to parse - * the next number or identifier. - */ - public void back() { - if (this.usePrevious || this.index <= 0) { - throw new RuntimeException("Stepping back two steps is not supported"); - } - this.index -= 1; - this.character -= 1; - this.usePrevious = true; - this.eof = false; - } - - - /** - * Get the hex value of a character (base16). - * @param c A character between '0' and '9' or between 'A' and 'F' or - * between 'a' and 'f'. - * @return An int between 0 and 15, or -1 if c was not a hex digit. - */ - public static int dehexchar(char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - if (c >= 'A' && c <= 'F') { - return c - ('A' - 10); - } - if (c >= 'a' && c <= 'f') { - return c - ('a' - 10); - } - return -1; - } - - public boolean end() { - return this.eof && !this.usePrevious; - } - - - /** - * Determine if the source string still contains characters that next() - * can consume. - * @return true if not yet at the end of the source. - */ - public boolean more() { - this.next(); - if (this.end()) { - return false; - } - this.back(); - return true; - } - - - /** - * Get the next character in the source string. - * - * @return The next character, or 0 if past the end of the source string. - */ - public char next() { - int c; - if (this.usePrevious) { - this.usePrevious = false; - c = this.previous; - } else { - try { - c = this.reader.read(); - } catch (IOException exception) { - throw new RuntimeException(exception); - } - - if (c <= 0) { // End of stream - this.eof = true; - c = 0; - } - } - this.index += 1; - if (this.previous == '\r') { - this.line += 1; - this.character = c == '\n' ? 0 : 1; - } else if (c == '\n') { - this.line += 1; - this.character = 0; - } else { - this.character += 1; - } - this.previous = (char) c; - return this.previous; - } - - - /** - * Consume the next character, and check that it matches a specified - * character. - * @param c The character to match. - * @return The character. - * @throws JSONException if the character does not match. - */ - public char next(char c) { - char n = this.next(); - if (n != c) { - throw new RuntimeException("Expected '" + c + "' and instead saw '" + n + "'"); - } - return n; - } - - - /** - * Get the next n characters. - * - * @param n The number of characters to take. - * @return A string of n characters. - * @throws JSONException - * Substring bounds error if there are not - * n characters remaining in the source string. - */ - public String next(int n) { - if (n == 0) { - return ""; - } - - char[] chars = new char[n]; - int pos = 0; - - while (pos < n) { - chars[pos] = this.next(); - if (this.end()) { - throw new RuntimeException("Substring bounds error"); - } - pos += 1; - } - return new String(chars); - } - - - /** - * Get the next char in the string, skipping whitespace. - * @throws JSONException - * @return A character, or 0 if there are no more characters. - */ - public char nextClean() { - for (;;) { - char c = this.next(); - if (c == 0 || c > ' ') { - return c; - } - } - } - - - /** - * Return the characters up to the next close quote character. - * Backslash processing is done. The formal JSON format does not - * allow strings in single quotes, but an implementation is allowed to - * accept them. - * @param quote The quoting character, either - * " (double quote) or - * ' (single quote). - * @return A String. - * @throws JSONException Unterminated string. - */ - public String nextString(char quote) { - char c; - StringBuilder sb = new StringBuilder(); - for (;;) { - c = this.next(); - switch (c) { - case 0: - case '\n': - case '\r': - throw new RuntimeException("Unterminated string"); - case '\\': - c = this.next(); - switch (c) { - case 'b': - sb.append('\b'); - break; - case 't': - sb.append('\t'); - break; - case 'n': - sb.append('\n'); - break; - case 'f': - sb.append('\f'); - break; - case 'r': - sb.append('\r'); - break; - case 'u': - sb.append((char)Integer.parseInt(this.next(4), 16)); - break; - case '"': - case '\'': - case '\\': - case '/': - sb.append(c); - break; - default: - throw new RuntimeException("Illegal escape."); - } - break; - default: - if (c == quote) { - return sb.toString(); - } - sb.append(c); - } - } - } - - - /** - * Get the text up but not including the specified character or the - * end of line, whichever comes first. - * @param delimiter A delimiter character. - * @return A string. - */ - public String nextTo(char delimiter) { - StringBuilder sb = new StringBuilder(); - for (;;) { - char c = this.next(); - if (c == delimiter || c == 0 || c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } - return sb.toString().trim(); - } - sb.append(c); - } - } - - - /** - * Get the text up but not including one of the specified delimiter - * characters or the end of line, whichever comes first. - * @param delimiters A set of delimiter characters. - * @return A string, trimmed. - */ - public String nextTo(String delimiters) { - char c; - StringBuilder sb = new StringBuilder(); - for (;;) { - c = this.next(); - if (delimiters.indexOf(c) >= 0 || c == 0 || - c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } - return sb.toString().trim(); - } - sb.append(c); - } - } - - - /** - * Get the next value. The value can be a Boolean, Double, Integer, - * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. - * @throws JSONException If syntax error. - * - * @return An object. - */ - public Object nextValue() { - char c = this.nextClean(); - String string; - - switch (c) { - case '"': - case '\'': - return this.nextString(c); - case '{': - this.back(); - return new JSONObject(this); - case '[': - this.back(); - return new JSONArray(this); - } - - /* - * Handle unquoted text. This could be the values true, false, or - * null, or it can be a number. An implementation (such as this one) - * is allowed to also accept non-standard forms. - * - * Accumulate characters until we reach the end of the text or a - * formatting character. - */ - - StringBuilder sb = new StringBuilder(); - while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { - sb.append(c); - c = this.next(); - } - this.back(); - - string = sb.toString().trim(); - if ("".equals(string)) { - throw new RuntimeException("Missing value"); - } - return JSONObject.stringToValue(string); - } - - - /** - * Skip characters until the next character is the requested character. - * If the requested character is not found, no characters are skipped. - * @param to A character to skip to. - * @return The requested character, or zero if the requested character - * is not found. - */ - public char skipTo(char to) { - char c; - try { - long startIndex = this.index; - long startCharacter = this.character; - long startLine = this.line; - this.reader.mark(1000000); - do { - c = this.next(); - if (c == 0) { - this.reader.reset(); - this.index = startIndex; - this.character = startCharacter; - this.line = startLine; - return c; - } - } while (c != to); - } catch (IOException exc) { - throw new RuntimeException(exc); - } - - this.back(); - return c; - } - - - /** - * Make a printable string of this JSONTokener. - * - * @return " at {index} [character {character} line {line}]" - */ - @Override - public String toString() { - return " at " + this.index + " [character " + this.character + " line " + - this.line + "]"; - } -} diff --git a/core/src/processing/data/LongDict.java b/core/src/processing/data/LongDict.java deleted file mode 100644 index 529246862..000000000 --- a/core/src/processing/data/LongDict.java +++ /dev/null @@ -1,802 +0,0 @@ -package processing.data; - -import java.io.*; -import java.util.HashMap; -import java.util.Iterator; -import java.util.NoSuchElementException; - -import processing.core.PApplet; - - -/** - * A simple class to use a String as a lookup for an int value. - * - * @webref data:composite - * @see FloatDict - * @see StringDict - */ -public class LongDict { - - /** Number of elements in the table */ - protected int count; - - protected String[] keys; - protected long[] values; - - /** Internal implementation for faster lookups */ - private HashMap indices = new HashMap<>(); - - - public LongDict() { - count = 0; - keys = new String[10]; - values = new long[10]; - } - - - /** - * Create a new lookup with a specific size. This is more efficient than not - * specifying a size. Use it when you know the rough size of the thing you're creating. - * - * @nowebref - */ - public LongDict(int length) { - count = 0; - keys = new String[length]; - values = new long[length]; - } - - - /** - * Read a set of entries from a Reader that has each key/value pair on - * a single line, separated by a tab. - * - * @nowebref - */ - public LongDict(BufferedReader reader) { - String[] lines = PApplet.loadStrings(reader); - keys = new String[lines.length]; - values = new long[lines.length]; - - for (int i = 0; i < lines.length; i++) { - String[] pieces = PApplet.split(lines[i], '\t'); - if (pieces.length == 2) { - keys[count] = pieces[0]; - values[count] = PApplet.parseInt(pieces[1]); - indices.put(pieces[0], count); - count++; - } - } - } - - /** - * @nowebref - */ - public LongDict(String[] keys, long[] values) { - if (keys.length != values.length) { - throw new IllegalArgumentException("key and value arrays must be the same length"); - } - this.keys = keys; - this.values = values; - count = keys.length; - for (int i = 0; i < count; i++) { - indices.put(keys[i], i); - } - } - - - /** - * Constructor to allow (more intuitive) inline initialization, e.g.: - *

    -   * new FloatDict(new Object[][] {
    -   *   { "key1", 1 },
    -   *   { "key2", 2 }
    -   * });
    -   * 
    - */ - public LongDict(Object[][] pairs) { - count = pairs.length; - this.keys = new String[count]; - this.values = new long[count]; - for (int i = 0; i < count; i++) { - keys[i] = (String) pairs[i][0]; - values[i] = (Integer) pairs[i][1]; - indices.put(keys[i], i); - } - } - - - /** - * Returns the number of key/value pairs - * - * @webref intdict:method - * @brief Returns the number of key/value pairs - */ - public int size() { - return count; - } - - - /** - * Resize the internal data, this can only be used to shrink the list. - * Helpful for situations like sorting and then grabbing the top 50 entries. - */ - public void resize(int length) { - if (length > count) { - throw new IllegalArgumentException("resize() can only be used to shrink the dictionary"); - } - if (length < 1) { - throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher"); - } - - String[] newKeys = new String[length]; - long[] newValues = new long[length]; - PApplet.arrayCopy(keys, newKeys, length); - PApplet.arrayCopy(values, newValues, length); - keys = newKeys; - values = newValues; - count = length; - resetIndices(); - } - - - /** - * Remove all entries. - * - * @webref intdict:method - * @brief Remove all entries - */ - public void clear() { - count = 0; - indices = new HashMap<>(); - } - - - private void resetIndices() { - indices = new HashMap<>(count); - for (int i = 0; i < count; i++) { - indices.put(keys[i], i); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public class Entry { - public String key; - public long value; - - Entry(String key, long value) { - this.key = key; - this.value = value; - } - } - - - public Iterable entries() { - return new Iterable() { - - public Iterator iterator() { - return entryIterator(); - } - }; - } - - - public Iterator entryIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public Entry next() { - ++index; - Entry e = new Entry(keys[index], values[index]); - return e; - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public String key(int index) { - return keys[index]; - } - - - protected void crop() { - if (count != keys.length) { - keys = PApplet.subset(keys, 0, count); - values = PApplet.subset(values, 0, count); - } - } - - - public Iterable keys() { - return new Iterable() { - - @Override - public Iterator iterator() { - return keyIterator(); - } - }; - } - - - // Use this to iterate when you want to be able to remove elements along the way - public Iterator keyIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public String next() { - return key(++index); - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - /** - * Return a copy of the internal keys array. This array can be modified. - * - * @webref intdict:method - * @brief Return a copy of the internal keys array - */ - public String[] keyArray() { - crop(); - return keyArray(null); - } - - - public String[] keyArray(String[] outgoing) { - if (outgoing == null || outgoing.length != count) { - outgoing = new String[count]; - } - System.arraycopy(keys, 0, outgoing, 0, count); - return outgoing; - } - - - public long value(int index) { - return values[index]; - } - - - /** - * @webref intdict:method - * @brief Return the internal array being used to store the values - */ - public Iterable values() { - return new Iterable() { - - @Override - public Iterator iterator() { - return valueIterator(); - } - }; - } - - - public Iterator valueIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public Long next() { - return value(++index); - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - /** - * Create a new array and copy each of the values into it. - * - * @webref intdict:method - * @brief Create a new array and copy each of the values into it - */ - public int[] valueArray() { - crop(); - return valueArray(null); - } - - - /** - * Fill an already-allocated array with the values (more efficient than - * creating a new array each time). If 'array' is null, or not the same - * size as the number of values, a new array will be allocated and returned. - * - * @param array values to copy into the array - */ - public int[] valueArray(int[] array) { - if (array == null || array.length != size()) { - array = new int[count]; - } - System.arraycopy(values, 0, array, 0, count); - return array; - } - - - /** - * Return a value for the specified key. - * - * @webref intdict:method - * @brief Return a value for the specified key - */ - public long get(String key) { - int index = index(key); - if (index == -1) { - throw new IllegalArgumentException("No key named '" + key + "'"); - } - return values[index]; - } - - - public long get(String key, long alternate) { - int index = index(key); - if (index == -1) return alternate; - return values[index]; - } - - - /** - * Create a new key/value pair or change the value of one. - * - * @webref intdict:method - * @brief Create a new key/value pair or change the value of one - */ - public void set(String key, long amount) { - int index = index(key); - if (index == -1) { - create(key, amount); - } else { - values[index] = amount; - } - } - - - public void setIndex(int index, String key, long value) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - keys[index] = key; - values[index] = value; - } - - - /** - * @webref intdict:method - * @brief Check if a key is a part of the data structure - */ - public boolean hasKey(String key) { - return index(key) != -1; - } - - - /** - * Increase the value associated with a specific key by 1. - * - * @webref intdict:method - * @brief Increase the value of a specific key value by 1 - */ - public void increment(String key) { - add(key, 1); - } - - - /** - * Merge another dictionary into this one. Calling this increment() - * since it doesn't make sense in practice for the other dictionary types, - * even though it's technically an add(). - */ - public void increment(LongDict dict) { - for (int i = 0; i < dict.count; i++) { - add(dict.key(i), dict.value(i)); - } - } - - - /** - * @webref intdict:method - * @brief Add to a value - */ - public void add(String key, long amount) { - int index = index(key); - if (index == -1) { - create(key, amount); - } else { - values[index] += amount; - } - } - - - /** - * @webref intdict:method - * @brief Subtract from a value - */ - public void sub(String key, long amount) { - add(key, -amount); - } - - - /** - * @webref intdict:method - * @brief Multiply a value - */ - public void mult(String key, long amount) { - int index = index(key); - if (index != -1) { - values[index] *= amount; - } - } - - - /** - * @webref intdict:method - * @brief Divide a value - */ - public void div(String key, long amount) { - int index = index(key); - if (index != -1) { - values[index] /= amount; - } - } - - - private void checkMinMax(String functionName) { - if (count == 0) { - String msg = - String.format("Cannot use %s() on an empty %s.", - functionName, getClass().getSimpleName()); - throw new RuntimeException(msg); - } - } - - - // return the index of the minimum value - public int minIndex() { - //checkMinMax("minIndex"); - if (count == 0) return -1; - - int index = 0; - long value = values[0]; - for (int i = 1; i < count; i++) { - if (values[i] < value) { - index = i; - value = values[i]; - } - } - return index; - } - - - // return the key for the minimum value - public String minKey() { - checkMinMax("minKey"); - int index = minIndex(); - if (index == -1) { - return null; - } - return keys[index]; - } - - - // return the minimum value, or throw an error if there are no values - public long minValue() { - checkMinMax("minValue"); - return values[minIndex()]; - } - - - // return the index of the max value - public int maxIndex() { - //checkMinMax("maxIndex"); - if (count == 0) { - return -1; - } - int index = 0; - long value = values[0]; - for (int i = 1; i < count; i++) { - if (values[i] > value) { - index = i; - value = values[i]; - } - } - return index; - } - - - /** return the key corresponding to the maximum value or null if no entries */ - public String maxKey() { - //checkMinMax("maxKey"); - int index = maxIndex(); - if (index == -1) { - return null; - } - return keys[index]; - } - - - // return the maximum value or throw an error if zero length - public long maxValue() { - checkMinMax("maxIndex"); - return values[maxIndex()]; - } - - - public long sum() { - long sum = 0; - for (int i = 0; i < count; i++) { - sum += values[i]; - } - return sum; - } - - - public int index(String what) { - Integer found = indices.get(what); - return (found == null) ? -1 : found.intValue(); - } - - - protected void create(String what, long much) { - if (count == keys.length) { - keys = PApplet.expand(keys); - values = PApplet.expand(values); - } - indices.put(what, Integer.valueOf(count)); - keys[count] = what; - values[count] = much; - count++; - } - - - /** - * @webref intdict:method - * @brief Remove a key/value pair - */ - public long remove(String key) { - int index = index(key); - if (index == -1) { - throw new NoSuchElementException("'" + key + "' not found"); - } - long value = values[index]; - removeIndex(index); - return value; - } - - - public long removeIndex(int index) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - long value = values[index]; - indices.remove(keys[index]); - for (int i = index; i < count-1; i++) { - keys[i] = keys[i+1]; - values[i] = values[i+1]; - indices.put(keys[i], i); - } - count--; - keys[count] = null; - values[count] = 0; - return value; - } - - - public void swap(int a, int b) { - String tkey = keys[a]; - long tvalue = values[a]; - keys[a] = keys[b]; - values[a] = values[b]; - keys[b] = tkey; - values[b] = tvalue; - -// indices.put(keys[a], Integer.valueOf(a)); -// indices.put(keys[b], Integer.valueOf(b)); - } - - - /** - * Sort the keys alphabetically (ignoring case). Uses the value as a - * tie-breaker (only really possible with a key that has a case change). - * - * @webref intdict:method - * @brief Sort the keys alphabetically - */ - public void sortKeys() { - sortImpl(true, false, true); - } - - /** - * Sort the keys alphabetically in reverse (ignoring case). Uses the value as a - * tie-breaker (only really possible with a key that has a case change). - * - * @webref intdict:method - * @brief Sort the keys alphabetically in reverse - */ - public void sortKeysReverse() { - sortImpl(true, true, true); - } - - - /** - * Sort by values in ascending order. The smallest value will be at [0]. - * - * @webref intdict:method - * @brief Sort by values in ascending order - */ - public void sortValues() { - sortValues(true); - } - - - /** - * Set true to ensure that the order returned is identical. Slightly - * slower because the tie-breaker for identical values compares the keys. - * @param stable - */ - public void sortValues(boolean stable) { - sortImpl(false, false, stable); - } - - - /** - * Sort by values in descending order. The largest value will be at [0]. - * - * @webref intdict:method - * @brief Sort by values in descending order - */ - public void sortValuesReverse() { - sortValuesReverse(true); - } - - - public void sortValuesReverse(boolean stable) { - sortImpl(false, true, stable); - } - - - protected void sortImpl(final boolean useKeys, final boolean reverse, - final boolean stable) { - Sort s = new Sort() { - @Override - public int size() { - return count; - } - - @Override - public int compare(int a, int b) { - long diff = 0; - if (useKeys) { - diff = keys[a].compareToIgnoreCase(keys[b]); - if (diff == 0) { - diff = values[a] - values[b]; - } - } else { // sort values - diff = values[a] - values[b]; - if (diff == 0 && stable) { - diff = keys[a].compareToIgnoreCase(keys[b]); - } - } - if (diff == 0) { - return 0; - } else if (reverse) { - return diff < 0 ? 1 : -1; - } else { - return diff < 0 ? -1 : 1; - } - } - - @Override - public void swap(int a, int b) { - LongDict.this.swap(a, b); - } - }; - s.run(); - - // Set the indices after sort/swaps (performance fix 160411) - resetIndices(); - } - - - /** - * Sum all of the values in this dictionary, then return a new FloatDict of - * each key, divided by the total sum. The total for all values will be ~1.0. - * @return an IntDict with the original keys, mapped to their pct of the total - */ - public FloatDict getPercent() { - double sum = sum(); // a little more accuracy - FloatDict outgoing = new FloatDict(); - for (int i = 0; i < size(); i++) { - double percent = value(i) / sum; - outgoing.set(key(i), (float) percent); - } - return outgoing; - } - - - /** Returns a duplicate copy of this object. */ - public LongDict copy() { - LongDict outgoing = new LongDict(count); - System.arraycopy(keys, 0, outgoing.keys, 0, count); - System.arraycopy(values, 0, outgoing.values, 0, count); - for (int i = 0; i < count; i++) { - outgoing.indices.put(keys[i], i); - } - outgoing.count = count; - return outgoing; - } - - - public void print() { - for (int i = 0; i < size(); i++) { - System.out.println(keys[i] + " = " + values[i]); - } - } - - - /** - * Save tab-delimited entries to a file (TSV format, UTF-8 encoding) - */ - public void save(File file) { - PrintWriter writer = PApplet.createWriter(file); - write(writer); - writer.close(); - } - - - /** - * Write tab-delimited entries to a PrintWriter - */ - public void write(PrintWriter writer) { - for (int i = 0; i < count; i++) { - writer.println(keys[i] + "\t" + values[i]); - } - writer.flush(); - } - - - /** - * Return this dictionary as a String in JSON format. - */ - public String toJSON() { - StringList items = new StringList(); - for (int i = 0; i < count; i++) { - items.append(JSONObject.quote(keys[i])+ ": " + values[i]); - } - return "{ " + items.join(", ") + " }"; - } - - - @Override - public String toString() { - return getClass().getSimpleName() + " size=" + size() + " " + toJSON(); - } -} diff --git a/core/src/processing/data/LongList.java b/core/src/processing/data/LongList.java deleted file mode 100644 index 77bbd8b15..000000000 --- a/core/src/processing/data/LongList.java +++ /dev/null @@ -1,937 +0,0 @@ -package processing.data; - -import java.io.File; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Random; - -import processing.core.PApplet; - - -// splice, slice, subset, concat, reverse - -// trim, join for String versions - - -/** - * Helper class for a list of ints. Lists are designed to have some of the - * features of ArrayLists, but to maintain the simplicity and efficiency of - * working with arrays. - * - * Functions like sort() and shuffle() always act on the list itself. To get - * a sorted copy, use list.copy().sort(). - * - * @webref data:composite - * @see FloatList - * @see StringList - */ -public class LongList implements Iterable { - protected int count; - protected long[] data; - - - public LongList() { - data = new long[10]; - } - - - /** - * @nowebref - */ - public LongList(int length) { - data = new long[length]; - } - - - /** - * @nowebref - */ - public LongList(int[] source) { - count = source.length; - data = new long[count]; - System.arraycopy(source, 0, data, 0, count); - } - - - /** - * Construct an IntList from an iterable pile of objects. - * For instance, a float array, an array of strings, who knows). - * Un-parseable or null values will be set to 0. - * @nowebref - */ - public LongList(Iterable iter) { - this(10); - for (Object o : iter) { - if (o == null) { - append(0); // missing value default - } else if (o instanceof Number) { - append(((Number) o).intValue()); - } else { - append(PApplet.parseInt(o.toString().trim())); - } - } - crop(); - } - - - /** - * Construct an IntList from a random pile of objects. - * Un-parseable or null values will be set to zero. - */ - public LongList(Object... items) { - final int missingValue = 0; // nuts, can't be last/final/second arg - - count = items.length; - data = new long[count]; - int index = 0; - for (Object o : items) { - int value = missingValue; - if (o != null) { - if (o instanceof Number) { - value = ((Number) o).intValue(); - } else { - value = PApplet.parseInt(o.toString().trim(), missingValue); - } - } - data[index++] = value; - } - } - - - static public LongList fromRange(int stop) { - return fromRange(0, stop); - } - - - static public LongList fromRange(int start, int stop) { - int count = stop - start; - LongList newbie = new LongList(count); - for (int i = 0; i < count; i++) { - newbie.set(i, start+i); - } - return newbie; - } - - - /** - * Improve efficiency by removing allocated but unused entries from the - * internal array used to store the data. Set to private, though it could - * be useful to have this public if lists are frequently making drastic - * size changes (from very large to very small). - */ - private void crop() { - if (count != data.length) { - data = PApplet.subset(data, 0, count); - } - } - - - /** - * Get the length of the list. - * - * @webref intlist:method - * @brief Get the length of the list - */ - public int size() { - return count; - } - - - public void resize(int length) { - if (length > data.length) { - long[] temp = new long[length]; - System.arraycopy(data, 0, temp, 0, count); - data = temp; - - } else if (length > count) { - Arrays.fill(data, count, length, 0); - } - count = length; - } - - - /** - * Remove all entries from the list. - * - * @webref intlist:method - * @brief Remove all entries from the list - */ - public void clear() { - count = 0; - } - - - /** - * Get an entry at a particular index. - * - * @webref intlist:method - * @brief Get an entry at a particular index - */ - public long get(int index) { - if (index >= this.count) { - throw new ArrayIndexOutOfBoundsException(index); - } - return data[index]; - } - - - /** - * Set the entry at a particular index. If the index is past the length of - * the list, it'll expand the list to accommodate, and fill the intermediate - * entries with 0s. - * - * @webref intlist:method - * @brief Set the entry at a particular index - */ - public void set(int index, int what) { - if (index >= count) { - data = PApplet.expand(data, index+1); - for (int i = count; i < index; i++) { - data[i] = 0; - } - count = index+1; - } - data[index] = what; - } - - - /** Just an alias for append(), but matches pop() */ - public void push(int value) { - append(value); - } - - - public long pop() { - if (count == 0) { - throw new RuntimeException("Can't call pop() on an empty list"); - } - long value = get(count-1); - count--; - return value; - } - - - /** - * Remove an element from the specified index - * - * @webref intlist:method - * @brief Remove an element from the specified index - */ - public long remove(int index) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - long entry = data[index]; -// int[] outgoing = new int[count - 1]; -// System.arraycopy(data, 0, outgoing, 0, index); -// count--; -// System.arraycopy(data, index + 1, outgoing, 0, count - index); -// data = outgoing; - // For most cases, this actually appears to be faster - // than arraycopy() on an array copying into itself. - for (int i = index; i < count-1; i++) { - data[i] = data[i+1]; - } - count--; - return entry; - } - - - // Remove the first instance of a particular value, - // and return the index at which it was found. - public int removeValue(int value) { - int index = index(value); - if (index != -1) { - remove(index); - return index; - } - return -1; - } - - - // Remove all instances of a particular value, - // and return the number of values found and removed - public int removeValues(int value) { - int ii = 0; - for (int i = 0; i < count; i++) { - if (data[i] != value) { - data[ii++] = data[i]; - } - } - int removed = count - ii; - count = ii; - return removed; - } - - - /** - * Add a new entry to the list. - * - * @webref intlist:method - * @brief Add a new entry to the list - */ - public void append(long value) { - if (count == data.length) { - data = PApplet.expand(data); - } - data[count++] = value; - } - - - public void append(int[] values) { - for (int v : values) { - append(v); - } - } - - - public void append(LongList list) { - for (long v : list.values()) { // will concat the list... - append(v); - } - } - - - /** Add this value, but only if it's not already in the list. */ - public void appendUnique(int value) { - if (!hasValue(value)) { - append(value); - } - } - - -// public void insert(int index, int value) { -// if (index+1 > count) { -// if (index+1 < data.length) { -// } -// } -// if (index >= data.length) { -// data = PApplet.expand(data, index+1); -// data[index] = value; -// count = index+1; -// -// } else if (count == data.length) { -// if (index >= count) { -// //int[] temp = new int[count << 1]; -// System.arraycopy(data, 0, temp, 0, index); -// temp[index] = value; -// System.arraycopy(data, index, temp, index+1, count - index); -// data = temp; -// -// } else { -// // data[] has room to grow -// // for() loop believed to be faster than System.arraycopy over itself -// for (int i = count; i > index; --i) { -// data[i] = data[i-1]; -// } -// data[index] = value; -// count++; -// } -// } - - - public void insert(int index, long value) { - insert(index, new long[] { value }); - } - - - // same as splice - public void insert(int index, long[] values) { - if (index < 0) { - throw new IllegalArgumentException("insert() index cannot be negative: it was " + index); - } - if (index >= data.length) { - throw new IllegalArgumentException("insert() index " + index + " is past the end of this list"); - } - - long[] temp = new long[count + values.length]; - - // Copy the old values, but not more than already exist - System.arraycopy(data, 0, temp, 0, Math.min(count, index)); - - // Copy the new values into the proper place - System.arraycopy(values, 0, temp, index, values.length); - -// if (index < count) { - // The index was inside count, so it's a true splice/insert - System.arraycopy(data, index, temp, index+values.length, count - index); - count = count + values.length; -// } else { -// // The index was past 'count', so the new count is weirder -// count = index + values.length; -// } - data = temp; - } - - - public void insert(int index, LongList list) { - insert(index, list.values()); - } - - - // below are aborted attempts at more optimized versions of the code - // that are harder to read and debug... - -// if (index + values.length >= count) { -// // We're past the current 'count', check to see if we're still allocated -// // index 9, data.length = 10, values.length = 1 -// if (index + values.length < data.length) { -// // There's still room for these entries, even though it's past 'count'. -// // First clear out the entries leading up to it, however. -// for (int i = count; i < index; i++) { -// data[i] = 0; -// } -// data[index] = -// } -// if (index >= data.length) { -// int length = index + values.length; -// int[] temp = new int[length]; -// System.arraycopy(data, 0, temp, 0, count); -// System.arraycopy(values, 0, temp, index, values.length); -// data = temp; -// count = data.length; -// } else { -// -// } -// -// } else if (count == data.length) { -// int[] temp = new int[count << 1]; -// System.arraycopy(data, 0, temp, 0, index); -// temp[index] = value; -// System.arraycopy(data, index, temp, index+1, count - index); -// data = temp; -// -// } else { -// // data[] has room to grow -// // for() loop believed to be faster than System.arraycopy over itself -// for (int i = count; i > index; --i) { -// data[i] = data[i-1]; -// } -// data[index] = value; -// count++; -// } - - - /** Return the first index of a particular value. */ - public int index(int what) { - /* - if (indexCache != null) { - try { - return indexCache.get(what); - } catch (Exception e) { // not there - return -1; - } - } - */ - for (int i = 0; i < count; i++) { - if (data[i] == what) { - return i; - } - } - return -1; - } - - - // !!! TODO this is not yet correct, because it's not being reset when - // the rest of the entries are changed -// protected void cacheIndices() { -// indexCache = new HashMap(); -// for (int i = 0; i < count; i++) { -// indexCache.put(data[i], i); -// } -// } - - /** - * @webref intlist:method - * @brief Check if a number is a part of the list - */ - public boolean hasValue(int value) { -// if (indexCache == null) { -// cacheIndices(); -// } -// return index(what) != -1; - for (int i = 0; i < count; i++) { - if (data[i] == value) { - return true; - } - } - return false; - } - - /** - * @webref intlist:method - * @brief Add one to a value - */ - public void increment(int index) { - if (count <= index) { - resize(index + 1); - } - data[index]++; - } - - - private void boundsProblem(int index, String method) { - final String msg = String.format("The list size is %d. " + - "You cannot %s() to element %d.", count, method, index); - throw new ArrayIndexOutOfBoundsException(msg); - } - - - /** - * @webref intlist:method - * @brief Add to a value - */ - public void add(int index, int amount) { - if (index < count) { - data[index] += amount; - } else { - boundsProblem(index, "add"); - } - } - - /** - * @webref intlist:method - * @brief Subtract from a value - */ - public void sub(int index, int amount) { - if (index < count) { - data[index] -= amount; - } else { - boundsProblem(index, "sub"); - } - } - - /** - * @webref intlist:method - * @brief Multiply a value - */ - public void mult(int index, int amount) { - if (index < count) { - data[index] *= amount; - } else { - boundsProblem(index, "mult"); - } - } - - /** - * @webref intlist:method - * @brief Divide a value - */ - public void div(int index, int amount) { - if (index < count) { - data[index] /= amount; - } else { - boundsProblem(index, "div"); - } - } - - - private void checkMinMax(String functionName) { - if (count == 0) { - String msg = - String.format("Cannot use %s() on an empty %s.", - functionName, getClass().getSimpleName()); - throw new RuntimeException(msg); - } - } - - - /** - * @webref intlist:method - * @brief Return the smallest value - */ - public long min() { - checkMinMax("min"); - long outgoing = data[0]; - for (int i = 1; i < count; i++) { - if (data[i] < outgoing) outgoing = data[i]; - } - return outgoing; - } - - - // returns the index of the minimum value. - // if there are ties, it returns the first one found. - public int minIndex() { - checkMinMax("minIndex"); - long value = data[0]; - int index = 0; - for (int i = 1; i < count; i++) { - if (data[i] < value) { - value = data[i]; - index = i; - } - } - return index; - } - - - /** - * @webref intlist:method - * @brief Return the largest value - */ - public long max() { - checkMinMax("max"); - long outgoing = data[0]; - for (int i = 1; i < count; i++) { - if (data[i] > outgoing) outgoing = data[i]; - } - return outgoing; - } - - - // returns the index of the maximum value. - // if there are ties, it returns the first one found. - public int maxIndex() { - checkMinMax("maxIndex"); - long value = data[0]; - int index = 0; - for (int i = 1; i < count; i++) { - if (data[i] > value) { - value = data[i]; - index = i; - } - } - return index; - } - - - public int sum() { - long amount = sumLong(); - if (amount > Integer.MAX_VALUE) { - throw new RuntimeException("sum() exceeds " + Integer.MAX_VALUE + ", use sumLong()"); - } - if (amount < Integer.MIN_VALUE) { - throw new RuntimeException("sum() less than " + Integer.MIN_VALUE + ", use sumLong()"); - } - return (int) amount; - } - - - public long sumLong() { - long sum = 0; - for (int i = 0; i < count; i++) { - sum += data[i]; - } - return sum; - } - - - /** - * Sorts the array in place. - * - * @webref intlist:method - * @brief Sorts the array, lowest to highest - */ - public void sort() { - Arrays.sort(data, 0, count); - } - - - /** - * Reverse sort, orders values from highest to lowest. - * - * @webref intlist:method - * @brief Reverse sort, orders values from highest to lowest - */ - public void sortReverse() { - new Sort() { - @Override - public int size() { - return count; - } - - @Override - public int compare(int a, int b) { - long diff = data[b] - data[a]; - return diff == 0 ? 0 : (diff < 0 ? -1 : 1); - } - - @Override - public void swap(int a, int b) { - long temp = data[a]; - data[a] = data[b]; - data[b] = temp; - } - }.run(); - } - - - // use insert() -// public void splice(int index, int value) { -// } - - -// public void subset(int start) { -// subset(start, count - start); -// } -// -// -// public void subset(int start, int num) { -// for (int i = 0; i < num; i++) { -// data[i] = data[i+start]; -// } -// count = num; -// } - - /** - * @webref intlist:method - * @brief Reverse the order of the list elements - */ - public void reverse() { - int ii = count - 1; - for (int i = 0; i < count/2; i++) { - long t = data[i]; - data[i] = data[ii]; - data[ii] = t; - --ii; - } - } - - - /** - * Randomize the order of the list elements. Note that this does not - * obey the randomSeed() function in PApplet. - * - * @webref intlist:method - * @brief Randomize the order of the list elements - */ - public void shuffle() { - Random r = new Random(); - int num = count; - while (num > 1) { - int value = r.nextInt(num); - num--; - long temp = data[num]; - data[num] = data[value]; - data[value] = temp; - } - } - - - /** - * Randomize the list order using the random() function from the specified - * sketch, allowing shuffle() to use its current randomSeed() setting. - */ - public void shuffle(PApplet sketch) { - int num = count; - while (num > 1) { - int value = (int) sketch.random(num); - num--; - long temp = data[num]; - data[num] = data[value]; - data[value] = temp; - } - } - - - public LongList copy() { - LongList outgoing = new LongList(data); - outgoing.count = count; - return outgoing; - } - - - /** - * Returns the actual array being used to store the data. For advanced users, - * this is the fastest way to access a large list. Suitable for iterating - * with a for() loop, but modifying the list will have terrible consequences. - */ - public long[] values() { - crop(); - return data; - } - - - @Override - public Iterator iterator() { -// public Iterator valueIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - LongList.this.remove(index); - index--; - } - - public Long next() { - return data[++index]; - } - - public boolean hasNext() { - return index+1 < count; - } - }; - } - - - /** - * Create a new array with a copy of all the values. - * - * @return an array sized by the length of the list with each of the values. - * @webref intlist:method - * @brief Create a new array with a copy of all the values - */ - public int[] array() { - return array(null); - } - - - /** - * Copy values into the specified array. If the specified array is null or - * not the same size, a new array will be allocated. - * @param array - */ - public int[] array(int[] array) { - if (array == null || array.length != count) { - array = new int[count]; - } - System.arraycopy(data, 0, array, 0, count); - return array; - } - - -// public int[] toIntArray() { -// int[] outgoing = new int[count]; -// for (int i = 0; i < count; i++) { -// outgoing[i] = (int) data[i]; -// } -// return outgoing; -// } - - -// public long[] toLongArray() { -// long[] outgoing = new long[count]; -// for (int i = 0; i < count; i++) { -// outgoing[i] = (long) data[i]; -// } -// return outgoing; -// } - - -// public float[] toFloatArray() { -// float[] outgoing = new float[count]; -// System.arraycopy(data, 0, outgoing, 0, count); -// return outgoing; -// } - - -// public double[] toDoubleArray() { -// double[] outgoing = new double[count]; -// for (int i = 0; i < count; i++) { -// outgoing[i] = data[i]; -// } -// return outgoing; -// } - - -// public String[] toStringArray() { -// String[] outgoing = new String[count]; -// for (int i = 0; i < count; i++) { -// outgoing[i] = String.valueOf(data[i]); -// } -// return outgoing; -// } - - - /** - * Returns a normalized version of this array. Called getPercent() for - * consistency with the Dict classes. It's a getter method because it needs - * to returns a new list (because IntList/Dict can't do percentages or - * normalization in place on int values). - */ - public FloatList getPercent() { - double sum = 0; - for (float value : array()) { - sum += value; - } - FloatList outgoing = new FloatList(count); - for (int i = 0; i < count; i++) { - double percent = data[i] / sum; - outgoing.set(i, (float) percent); - } - return outgoing; - } - - -// /** -// * Count the number of times each entry is found in this list. -// * Converts each entry to a String so it can be used as a key. -// */ -// public IntDict getTally() { -// IntDict outgoing = new IntDict(); -// for (int i = 0; i < count; i++) { -// outgoing.increment(String.valueOf(data[i])); -// } -// return outgoing; -// } - - - public LongList getSubset(int start) { - return getSubset(start, count - start); - } - - - public LongList getSubset(int start, int num) { - int[] subset = new int[num]; - System.arraycopy(data, start, subset, 0, num); - return new LongList(subset); - } - - - public String join(String separator) { - if (count == 0) { - return ""; - } - StringBuilder sb = new StringBuilder(); - sb.append(data[0]); - for (int i = 1; i < count; i++) { - sb.append(separator); - sb.append(data[i]); - } - return sb.toString(); - } - - - public void print() { - for (int i = 0; i < count; i++) { - System.out.format("[%d] %d%n", i, data[i]); - } - } - - - /** - * Save tab-delimited entries to a file (TSV format, UTF-8 encoding) - */ - public void save(File file) { - PrintWriter writer = PApplet.createWriter(file); - write(writer); - writer.close(); - } - - - /** - * Write entries to a PrintWriter, one per line - */ - public void write(PrintWriter writer) { - for (int i = 0; i < count; i++) { - writer.println(data[i]); - } - writer.flush(); - } - - - /** - * Return this dictionary as a String in JSON format. - */ - public String toJSON() { - return "[ " + join(", ") + " ]"; - } - - - @Override - public String toString() { - return getClass().getSimpleName() + " size=" + size() + " " + toJSON(); - } -} diff --git a/core/src/processing/data/Sort.java b/core/src/processing/data/Sort.java deleted file mode 100644 index a83fea551..000000000 --- a/core/src/processing/data/Sort.java +++ /dev/null @@ -1,46 +0,0 @@ -package processing.data; - - -/** - * Internal sorter used by several data classes. - * Advanced users only, not official API. - */ -public abstract class Sort implements Runnable { - - public Sort() { } - - - public void run() { - int c = size(); - if (c > 1) { - sort(0, c - 1); - } - } - - - protected void sort(int i, int j) { - int pivotIndex = (i+j)/2; - swap(pivotIndex, j); - int k = partition(i-1, j); - swap(k, j); - if ((k-i) > 1) sort(i, k-1); - if ((j-k) > 1) sort(k+1, j); - } - - - protected int partition(int left, int right) { - int pivot = right; - do { - while (compare(++left, pivot) < 0) { } - while ((right != 0) && (compare(--right, pivot) > 0)) { } - swap(left, right); - } while (left < right); - swap(left, right); - return left; - } - - - abstract public int size(); - abstract public int compare(int a, int b); - abstract public void swap(int a, int b); -} \ No newline at end of file diff --git a/core/src/processing/data/StringDict.java b/core/src/processing/data/StringDict.java deleted file mode 100644 index c66a61e4d..000000000 --- a/core/src/processing/data/StringDict.java +++ /dev/null @@ -1,613 +0,0 @@ -package processing.data; - -import java.io.*; -import java.util.HashMap; -import java.util.Iterator; -import java.util.NoSuchElementException; - -import processing.core.PApplet; - - -/** - * A simple table class to use a String as a lookup for another String value. - * - * @webref data:composite - * @see IntDict - * @see FloatDict - */ -public class StringDict { - - /** Number of elements in the table */ - protected int count; - - protected String[] keys; - protected String[] values; - - /** Internal implementation for faster lookups */ - private HashMap indices = new HashMap<>(); - - - public StringDict() { - count = 0; - keys = new String[10]; - values = new String[10]; - } - - - /** - * Create a new lookup pre-allocated to a specific length. This will not - * change the size(), but is more efficient than not specifying a length. - * Use it when you know the rough size of the thing you're creating. - * - * @nowebref - */ - public StringDict(int length) { - count = 0; - keys = new String[length]; - values = new String[length]; - } - - - /** - * Read a set of entries from a Reader that has each key/value pair on - * a single line, separated by a tab. - * - * @nowebref - */ - public StringDict(BufferedReader reader) { - String[] lines = PApplet.loadStrings(reader); - keys = new String[lines.length]; - values = new String[lines.length]; - - for (int i = 0; i < lines.length; i++) { - String[] pieces = PApplet.split(lines[i], '\t'); - if (pieces.length == 2) { - keys[count] = pieces[0]; - values[count] = pieces[1]; - indices.put(keys[count], count); - count++; - } - } - } - - - /** - * @nowebref - */ - public StringDict(String[] keys, String[] values) { - if (keys.length != values.length) { - throw new IllegalArgumentException("key and value arrays must be the same length"); - } - this.keys = keys; - this.values = values; - count = keys.length; - for (int i = 0; i < count; i++) { - indices.put(keys[i], i); - } - } - - - /** - * Constructor to allow (more intuitive) inline initialization, e.g.: - *
    -   * new StringDict(new String[][] {
    -   *   { "key1", "value1" },
    -   *   { "key2", "value2" }
    -   * });
    -   * 
    - * It's no Python, but beats a static { } block with HashMap.put() statements. - */ - public StringDict(String[][] pairs) { - count = pairs.length; - this.keys = new String[count]; - this.values = new String[count]; - for (int i = 0; i < count; i++) { - keys[i] = pairs[i][0]; - values[i] = pairs[i][1]; - indices.put(keys[i], i); - } - } - - - /** - * Create a dictionary that maps between column titles and cell entries - * in a TableRow. If two columns have the same name, the later column's - * values will override the earlier values. - */ - public StringDict(TableRow row) { - this(row.getColumnCount()); - - String[] titles = row.getColumnTitles(); - if (titles == null) { - titles = new StringList(IntList.fromRange(row.getColumnCount())).array(); - } - for (int col = 0; col < row.getColumnCount(); col++) { - set(titles[col], row.getString(col)); - } - // remove unused and overwritten entries - crop(); - } - - - /** - * @webref stringdict:method - * @brief Returns the number of key/value pairs - */ - public int size() { - return count; - } - - - /** - * Resize the internal data, this can only be used to shrink the list. - * Helpful for situations like sorting and then grabbing the top 50 entries. - */ - public void resize(int length) { - if (length > count) { - throw new IllegalArgumentException("resize() can only be used to shrink the dictionary"); - } - if (length < 1) { - throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher"); - } - - String[] newKeys = new String[length]; - String[] newValues = new String[length]; - PApplet.arrayCopy(keys, newKeys, length); - PApplet.arrayCopy(values, newValues, length); - keys = newKeys; - values = newValues; - count = length; - resetIndices(); - } - - - /** - * Remove all entries. - * - * @webref stringdict:method - * @brief Remove all entries - */ - public void clear() { - count = 0; - indices = new HashMap<>(); - } - - - private void resetIndices() { - indices = new HashMap<>(count); - for (int i = 0; i < count; i++) { - indices.put(keys[i], i); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public class Entry { - public String key; - public String value; - - Entry(String key, String value) { - this.key = key; - this.value = value; - } - } - - - public Iterable entries() { - return new Iterable() { - - public Iterator iterator() { - return entryIterator(); - } - }; - } - - - public Iterator entryIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public Entry next() { - ++index; - Entry e = new Entry(keys[index], values[index]); - return e; - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public String key(int index) { - return keys[index]; - } - - - protected void crop() { - if (count != keys.length) { - keys = PApplet.subset(keys, 0, count); - values = PApplet.subset(values, 0, count); - } - } - - - public Iterable keys() { - return new Iterable() { - - @Override - public Iterator iterator() { - return keyIterator(); - } - }; - } - - - // Use this to iterate when you want to be able to remove elements along the way - public Iterator keyIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public String next() { - return key(++index); - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - /** - * Return a copy of the internal keys array. This array can be modified. - * - * @webref stringdict:method - * @brief Return a copy of the internal keys array - */ - public String[] keyArray() { - crop(); - return keyArray(null); - } - - - public String[] keyArray(String[] outgoing) { - if (outgoing == null || outgoing.length != count) { - outgoing = new String[count]; - } - System.arraycopy(keys, 0, outgoing, 0, count); - return outgoing; - } - - - public String value(int index) { - return values[index]; - } - - /** - * @webref stringdict:method - * @brief Return the internal array being used to store the values - */ - public Iterable values() { - return new Iterable() { - - @Override - public Iterator iterator() { - return valueIterator(); - } - }; - } - - - public Iterator valueIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - removeIndex(index); - index--; - } - - public String next() { - return value(++index); - } - - public boolean hasNext() { - return index+1 < size(); - } - }; - } - - - /** - * Create a new array and copy each of the values into it. - * - * @webref stringdict:method - * @brief Create a new array and copy each of the values into it - */ - public String[] valueArray() { - crop(); - return valueArray(null); - } - - - /** - * Fill an already-allocated array with the values (more efficient than - * creating a new array each time). If 'array' is null, or not the same - * size as the number of values, a new array will be allocated and returned. - */ - public String[] valueArray(String[] array) { - if (array == null || array.length != size()) { - array = new String[count]; - } - System.arraycopy(values, 0, array, 0, count); - return array; - } - - - /** - * Return a value for the specified key. - * - * @webref stringdict:method - * @brief Return a value for the specified key - */ - public String get(String key) { - int index = index(key); - if (index == -1) return null; - return values[index]; - } - - - public String get(String key, String alternate) { - int index = index(key); - if (index == -1) return alternate; - return values[index]; - } - - - /** - * @webref stringdict:method - * @brief Create a new key/value pair or change the value of one - */ - public void set(String key, String value) { - int index = index(key); - if (index == -1) { - create(key, value); - } else { - values[index] = value; - } - } - - - public void setIndex(int index, String key, String value) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - keys[index] = key; - values[index] = value; - } - - - public int index(String what) { - Integer found = indices.get(what); - return (found == null) ? -1 : found.intValue(); - } - - - /** - * @webref stringdict:method - * @brief Check if a key is a part of the data structure - */ - public boolean hasKey(String key) { - return index(key) != -1; - } - - - protected void create(String key, String value) { - if (count == keys.length) { - keys = PApplet.expand(keys); - values = PApplet.expand(values); - } - indices.put(key, Integer.valueOf(count)); - keys[count] = key; - values[count] = value; - count++; - } - - /** - * @webref stringdict:method - * @brief Remove a key/value pair - */ - public String remove(String key) { - int index = index(key); - if (index == -1) { - throw new NoSuchElementException("'" + key + "' not found"); - } - String value = values[index]; - removeIndex(index); - return value; - } - - - public String removeIndex(int index) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - String value = values[index]; - indices.remove(keys[index]); - for (int i = index; i < count-1; i++) { - keys[i] = keys[i+1]; - values[i] = values[i+1]; - indices.put(keys[i], i); - } - count--; - keys[count] = null; - values[count] = null; - return value; - } - - - - public void swap(int a, int b) { - String tkey = keys[a]; - String tvalue = values[a]; - keys[a] = keys[b]; - values[a] = values[b]; - keys[b] = tkey; - values[b] = tvalue; - -// indices.put(keys[a], Integer.valueOf(a)); -// indices.put(keys[b], Integer.valueOf(b)); - } - - - /** - * Sort the keys alphabetically (ignoring case). Uses the value as a - * tie-breaker (only really possible with a key that has a case change). - * - * @webref stringdict:method - * @brief Sort the keys alphabetically - */ - public void sortKeys() { - sortImpl(true, false); - } - - /** - * @webref stringdict:method - * @brief Sort the keys alphabetically in reverse - */ - public void sortKeysReverse() { - sortImpl(true, true); - } - - - /** - * Sort by values in descending order (largest value will be at [0]). - * - * @webref stringdict:method - * @brief Sort by values in ascending order - */ - public void sortValues() { - sortImpl(false, false); - } - - - /** - * @webref stringdict:method - * @brief Sort by values in descending order - */ - public void sortValuesReverse() { - sortImpl(false, true); - } - - - protected void sortImpl(final boolean useKeys, final boolean reverse) { - Sort s = new Sort() { - @Override - public int size() { - return count; - } - - @Override - public int compare(int a, int b) { - int diff = 0; - if (useKeys) { - diff = keys[a].compareToIgnoreCase(keys[b]); - if (diff == 0) { - diff = values[a].compareToIgnoreCase(values[b]); - } - } else { // sort values - diff = values[a].compareToIgnoreCase(values[b]); - if (diff == 0) { - diff = keys[a].compareToIgnoreCase(keys[b]); - } - } - return reverse ? -diff : diff; - } - - @Override - public void swap(int a, int b) { - StringDict.this.swap(a, b); - } - }; - s.run(); - - // Set the indices after sort/swaps (performance fix 160411) - resetIndices(); - } - - - /** Returns a duplicate copy of this object. */ - public StringDict copy() { - StringDict outgoing = new StringDict(count); - System.arraycopy(keys, 0, outgoing.keys, 0, count); - System.arraycopy(values, 0, outgoing.values, 0, count); - for (int i = 0; i < count; i++) { - outgoing.indices.put(keys[i], i); - } - outgoing.count = count; - return outgoing; - } - - - public void print() { - for (int i = 0; i < size(); i++) { - System.out.println(keys[i] + " = " + values[i]); - } - } - - - /** - * Save tab-delimited entries to a file (TSV format, UTF-8 encoding) - */ - public void save(File file) { - PrintWriter writer = PApplet.createWriter(file); - write(writer); - writer.close(); - } - - - /** - * Write tab-delimited entries to a PrintWriter - */ - public void write(PrintWriter writer) { - for (int i = 0; i < count; i++) { - writer.println(keys[i] + "\t" + values[i]); - } - writer.flush(); - } - - - /** - * Return this dictionary as a String in JSON format. - */ - public String toJSON() { - StringList items = new StringList(); - for (int i = 0; i < count; i++) { - items.append(JSONObject.quote(keys[i])+ ": " + JSONObject.quote(values[i])); - } - return "{ " + items.join(", ") + " }"; - } - - - @Override - public String toString() { - return getClass().getSimpleName() + " size=" + size() + " " + toJSON(); - } -} diff --git a/core/src/processing/data/StringList.java b/core/src/processing/data/StringList.java deleted file mode 100644 index c4de6d33c..000000000 --- a/core/src/processing/data/StringList.java +++ /dev/null @@ -1,798 +0,0 @@ -package processing.data; - -import java.io.File; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Random; - -import processing.core.PApplet; - -/** - * Helper class for a list of Strings. Lists are designed to have some of the - * features of ArrayLists, but to maintain the simplicity and efficiency of - * working with arrays. - * - * Functions like sort() and shuffle() always act on the list itself. To get - * a sorted copy, use list.copy().sort(). - * - * @webref data:composite - * @see IntList - * @see FloatList - */ -public class StringList implements Iterable { - int count; - String[] data; - - - public StringList() { - this(10); - } - - /** - * @nowebref - */ - public StringList(int length) { - data = new String[length]; - } - - /** - * @nowebref - */ - public StringList(String[] list) { - count = list.length; - data = new String[count]; - System.arraycopy(list, 0, data, 0, count); - } - - - /** - * Construct a StringList from a random pile of objects. Null values will - * stay null, but all the others will be converted to String values. - */ - public StringList(Object... items) { - count = items.length; - data = new String[count]; - int index = 0; - for (Object o : items) { -// // Not gonna go with null values staying that way because perhaps -// // the most common case here is to immediately call join() or similar. -// data[index++] = String.valueOf(o); - // Keep null values null (because join() will make non-null anyway) - if (o != null) { // leave null values null - data[index] = o.toString(); - } - index++; - } - } - - - /** - * Create from something iterable, for instance: - * StringList list = new StringList(hashMap.keySet()); - * - * @nowebref - */ - public StringList(Iterable iter) { - this(10); - for (String s : iter) { - append(s); - } - } - - - /** - * Improve efficiency by removing allocated but unused entries from the - * internal array used to store the data. Set to private, though it could - * be useful to have this public if lists are frequently making drastic - * size changes (from very large to very small). - */ - private void crop() { - if (count != data.length) { - data = PApplet.subset(data, 0, count); - } - } - - - /** - * Get the length of the list. - * - * @webref stringlist:method - * @brief Get the length of the list - */ - public int size() { - return count; - } - - - public void resize(int length) { - if (length > data.length) { - String[] temp = new String[length]; - System.arraycopy(data, 0, temp, 0, count); - data = temp; - - } else if (length > count) { - Arrays.fill(data, count, length, 0); - } - count = length; - } - - - /** - * Remove all entries from the list. - * - * @webref stringlist:method - * @brief Remove all entries from the list - */ - public void clear() { - count = 0; - } - - - /** - * Get an entry at a particular index. - * - * @webref stringlist:method - * @brief Get an entry at a particular index - */ - public String get(int index) { - if (index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - return data[index]; - } - - - /** - * Set the entry at a particular index. If the index is past the length of - * the list, it'll expand the list to accommodate, and fill the intermediate - * entries with 0s. - * - * @webref stringlist:method - * @brief Set an entry at a particular index - */ - public void set(int index, String what) { - if (index >= count) { - data = PApplet.expand(data, index+1); - for (int i = count; i < index; i++) { - data[i] = null; - } - count = index+1; - } - data[index] = what; - } - - - /** Just an alias for append(), but matches pop() */ - public void push(String value) { - append(value); - } - - - public String pop() { - if (count == 0) { - throw new RuntimeException("Can't call pop() on an empty list"); - } - String value = get(count-1); - data[--count] = null; // avoid leak - return value; - } - - - /** - * Remove an element from the specified index. - * - * @webref stringlist:method - * @brief Remove an element from the specified index - */ - public String remove(int index) { - if (index < 0 || index >= count) { - throw new ArrayIndexOutOfBoundsException(index); - } - String entry = data[index]; -// int[] outgoing = new int[count - 1]; -// System.arraycopy(data, 0, outgoing, 0, index); -// count--; -// System.arraycopy(data, index + 1, outgoing, 0, count - index); -// data = outgoing; - for (int i = index; i < count-1; i++) { - data[i] = data[i+1]; - } - count--; - return entry; - } - - - // Remove the first instance of a particular value and return its index. - public int removeValue(String value) { - if (value == null) { - for (int i = 0; i < count; i++) { - if (data[i] == null) { - remove(i); - return i; - } - } - } else { - int index = index(value); - if (index != -1) { - remove(index); - return index; - } - } - return -1; - } - - - // Remove all instances of a particular value and return the count removed. - public int removeValues(String value) { - int ii = 0; - if (value == null) { - for (int i = 0; i < count; i++) { - if (data[i] != null) { - data[ii++] = data[i]; - } - } - } else { - for (int i = 0; i < count; i++) { - if (!value.equals(data[i])) { - data[ii++] = data[i]; - } - } - } - int removed = count - ii; - count = ii; - return removed; - } - - - // replace the first value that matches, return the index that was replaced - public int replaceValue(String value, String newValue) { - if (value == null) { - for (int i = 0; i < count; i++) { - if (data[i] == null) { - data[i] = newValue; - return i; - } - } - } else { - for (int i = 0; i < count; i++) { - if (value.equals(data[i])) { - data[i] = newValue; - return i; - } - } - } - return -1; - } - - - // replace all values that match, return the count of those replaced - public int replaceValues(String value, String newValue) { - int changed = 0; - if (value == null) { - for (int i = 0; i < count; i++) { - if (data[i] == null) { - data[i] = newValue; - changed++; - } - } - } else { - for (int i = 0; i < count; i++) { - if (value.equals(data[i])) { - data[i] = newValue; - changed++; - } - } - } - return changed; - } - - - /** - * Add a new entry to the list. - * - * @webref stringlist:method - * @brief Add a new entry to the list - */ - public void append(String value) { - if (count == data.length) { - data = PApplet.expand(data); - } - data[count++] = value; - } - - - public void append(String[] values) { - for (String v : values) { - append(v); - } - } - - - public void append(StringList list) { - for (String v : list.values()) { // will concat the list... - append(v); - } - } - - - /** Add this value, but only if it's not already in the list. */ - public void appendUnique(String value) { - if (!hasValue(value)) { - append(value); - } - } - - -// public void insert(int index, int value) { -// if (index+1 > count) { -// if (index+1 < data.length) { -// } -// } -// if (index >= data.length) { -// data = PApplet.expand(data, index+1); -// data[index] = value; -// count = index+1; -// -// } else if (count == data.length) { -// if (index >= count) { -// //int[] temp = new int[count << 1]; -// System.arraycopy(data, 0, temp, 0, index); -// temp[index] = value; -// System.arraycopy(data, index, temp, index+1, count - index); -// data = temp; -// -// } else { -// // data[] has room to grow -// // for() loop believed to be faster than System.arraycopy over itself -// for (int i = count; i > index; --i) { -// data[i] = data[i-1]; -// } -// data[index] = value; -// count++; -// } -// } - - - public void insert(int index, String value) { - insert(index, new String[] { value }); - } - - - // same as splice - public void insert(int index, String[] values) { - if (index < 0) { - throw new IllegalArgumentException("insert() index cannot be negative: it was " + index); - } - if (index >= data.length) { - throw new IllegalArgumentException("insert() index " + index + " is past the end of this list"); - } - - String[] temp = new String[count + values.length]; - - // Copy the old values, but not more than already exist - System.arraycopy(data, 0, temp, 0, Math.min(count, index)); - - // Copy the new values into the proper place - System.arraycopy(values, 0, temp, index, values.length); - -// if (index < count) { - // The index was inside count, so it's a true splice/insert - System.arraycopy(data, index, temp, index+values.length, count - index); - count = count + values.length; -// } else { -// // The index was past 'count', so the new count is weirder -// count = index + values.length; -// } - data = temp; - } - - - public void insert(int index, StringList list) { - insert(index, list.values()); - } - - - // below are aborted attempts at more optimized versions of the code - // that are harder to read and debug... - -// if (index + values.length >= count) { -// // We're past the current 'count', check to see if we're still allocated -// // index 9, data.length = 10, values.length = 1 -// if (index + values.length < data.length) { -// // There's still room for these entries, even though it's past 'count'. -// // First clear out the entries leading up to it, however. -// for (int i = count; i < index; i++) { -// data[i] = 0; -// } -// data[index] = -// } -// if (index >= data.length) { -// int length = index + values.length; -// int[] temp = new int[length]; -// System.arraycopy(data, 0, temp, 0, count); -// System.arraycopy(values, 0, temp, index, values.length); -// data = temp; -// count = data.length; -// } else { -// -// } -// -// } else if (count == data.length) { -// int[] temp = new int[count << 1]; -// System.arraycopy(data, 0, temp, 0, index); -// temp[index] = value; -// System.arraycopy(data, index, temp, index+1, count - index); -// data = temp; -// -// } else { -// // data[] has room to grow -// // for() loop believed to be faster than System.arraycopy over itself -// for (int i = count; i > index; --i) { -// data[i] = data[i-1]; -// } -// data[index] = value; -// count++; -// } - - - /** Return the first index of a particular value. */ - public int index(String what) { - if (what == null) { - for (int i = 0; i < count; i++) { - if (data[i] == null) { - return i; - } - } - } else { - for (int i = 0; i < count; i++) { - if (what.equals(data[i])) { - return i; - } - } - } - return -1; - } - - - // !!! TODO this is not yet correct, because it's not being reset when - // the rest of the entries are changed -// protected void cacheIndices() { -// indexCache = new HashMap(); -// for (int i = 0; i < count; i++) { -// indexCache.put(data[i], i); -// } -// } - - /** - * @webref stringlist:method - * @brief Check if a value is a part of the list - */ - public boolean hasValue(String value) { - if (value == null) { - for (int i = 0; i < count; i++) { - if (data[i] == null) { - return true; - } - } - } else { - for (int i = 0; i < count; i++) { - if (value.equals(data[i])) { - return true; - } - } - } - return false; - } - - - /** - * Sorts the array in place. - * - * @webref stringlist:method - * @brief Sorts the array in place - */ - public void sort() { - sortImpl(false); - } - - - /** - * Reverse sort, orders values from highest to lowest. - * - * @webref stringlist:method - * @brief Reverse sort, orders values from highest to lowest - */ - public void sortReverse() { - sortImpl(true); - } - - - private void sortImpl(final boolean reverse) { - new Sort() { - @Override - public int size() { - return count; - } - - @Override - public int compare(int a, int b) { - int diff = data[a].compareToIgnoreCase(data[b]); - return reverse ? -diff : diff; - } - - @Override - public void swap(int a, int b) { - String temp = data[a]; - data[a] = data[b]; - data[b] = temp; - } - }.run(); - } - - - // use insert() -// public void splice(int index, int value) { -// } - - -// public void subset(int start) { -// subset(start, count - start); -// } -// -// -// public void subset(int start, int num) { -// for (int i = 0; i < num; i++) { -// data[i] = data[i+start]; -// } -// count = num; -// } - - /** - * @webref stringlist:method - * @brief Reverse the order of the list elements - */ - public void reverse() { - int ii = count - 1; - for (int i = 0; i < count/2; i++) { - String t = data[i]; - data[i] = data[ii]; - data[ii] = t; - --ii; - } - } - - - /** - * Randomize the order of the list elements. Note that this does not - * obey the randomSeed() function in PApplet. - * - * @webref stringlist:method - * @brief Randomize the order of the list elements - */ - public void shuffle() { - Random r = new Random(); - int num = count; - while (num > 1) { - int value = r.nextInt(num); - num--; - String temp = data[num]; - data[num] = data[value]; - data[value] = temp; - } - } - - - /** - * Randomize the list order using the random() function from the specified - * sketch, allowing shuffle() to use its current randomSeed() setting. - */ - public void shuffle(PApplet sketch) { - int num = count; - while (num > 1) { - int value = (int) sketch.random(num); - num--; - String temp = data[num]; - data[num] = data[value]; - data[value] = temp; - } - } - - - /** - * Make the entire list lower case. - * - * @webref stringlist:method - * @brief Make the entire list lower case - */ - public void lower() { - for (int i = 0; i < count; i++) { - if (data[i] != null) { - data[i] = data[i].toLowerCase(); - } - } - } - - - /** - * Make the entire list upper case. - * - * @webref stringlist:method - * @brief Make the entire list upper case - */ - public void upper() { - for (int i = 0; i < count; i++) { - if (data[i] != null) { - data[i] = data[i].toUpperCase(); - } - } - } - - - public StringList copy() { - StringList outgoing = new StringList(data); - outgoing.count = count; - return outgoing; - } - - - /** - * Returns the actual array being used to store the data. Suitable for - * iterating with a for() loop, but modifying the list could cause terrible - * things to happen. - */ - public String[] values() { - crop(); - return data; - } - - - @Override - public Iterator iterator() { -// return valueIterator(); -// } -// -// -// public Iterator valueIterator() { - return new Iterator() { - int index = -1; - - public void remove() { - StringList.this.remove(index); - index--; - } - - public String next() { - return data[++index]; - } - - public boolean hasNext() { - return index+1 < count; - } - }; - } - - - /** - * Create a new array with a copy of all the values. - * - * @return an array sized by the length of the list with each of the values. - * @webref stringlist:method - * @brief Create a new array with a copy of all the values - */ - public String[] array() { - return array(null); - } - - - /** - * Copy values into the specified array. If the specified array is null or - * not the same size, a new array will be allocated. - * @param array - */ - public String[] array(String[] array) { - if (array == null || array.length != count) { - array = new String[count]; - } - System.arraycopy(data, 0, array, 0, count); - return array; - } - - - public StringList getSubset(int start) { - return getSubset(start, count - start); - } - - - public StringList getSubset(int start, int num) { - String[] subset = new String[num]; - System.arraycopy(data, start, subset, 0, num); - return new StringList(subset); - } - - - /** Get a list of all unique entries. */ - public String[] getUnique() { - return getTally().keyArray(); - } - - - /** Count the number of times each String entry is found in this list. */ - public IntDict getTally() { - IntDict outgoing = new IntDict(); - for (int i = 0; i < count; i++) { - outgoing.increment(data[i]); - } - return outgoing; - } - - - /** Create a dictionary associating each entry in this list to its index. */ - public IntDict getOrder() { - IntDict outgoing = new IntDict(); - for (int i = 0; i < count; i++) { - outgoing.set(data[i], i); - } - return outgoing; - } - - - public String join(String separator) { - if (count == 0) { - return ""; - } - StringBuilder sb = new StringBuilder(); - sb.append(data[0]); - for (int i = 1; i < count; i++) { - sb.append(separator); - sb.append(data[i]); - } - return sb.toString(); - } - - - public void print() { - for (int i = 0; i < count; i++) { - System.out.format("[%d] %s%n", i, data[i]); - } - } - - - /** - * Save tab-delimited entries to a file (TSV format, UTF-8 encoding) - */ - public void save(File file) { - PrintWriter writer = PApplet.createWriter(file); - write(writer); - writer.close(); - } - - - /** - * Write entries to a PrintWriter, one per line - */ - public void write(PrintWriter writer) { - for (int i = 0; i < count; i++) { - writer.println(data[i]); - } - writer.flush(); - } - - - /** - * Return this dictionary as a String in JSON format. - */ - public String toJSON() { - StringList temp = new StringList(); - for (String item : this) { - temp.append(JSONObject.quote(item)); - } - return "[ " + temp.join(", ") + " ]"; - } - - - @Override - public String toString() { - return getClass().getSimpleName() + " size=" + size() + " " + toJSON(); - } -} diff --git a/core/src/processing/data/Table.java b/core/src/processing/data/Table.java deleted file mode 100644 index 2048376cf..000000000 --- a/core/src/processing/data/Table.java +++ /dev/null @@ -1,4935 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2011-12 Ben Fry and Casey Reas - Copyright (c) 2006-11 Ben Fry - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - */ - -package processing.data; - -import java.io.*; -import java.lang.reflect.*; -import java.nio.charset.Charset; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Types; -import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -import javax.xml.parsers.ParserConfigurationException; - -import org.xml.sax.SAXException; - -import processing.core.PApplet; -import processing.core.PConstants; - - -/** - *

    Generic class for handling tabular data, typically from a CSV, TSV, or - * other sort of spreadsheet file.

    - *

    CSV files are - * comma separated values, - * often with the data in quotes. TSV files use tabs as separators, and usually - * don't bother with the quotes.

    - *

    File names should end with .csv if they're comma separated.

    - *

    A rough "spec" for CSV can be found here.

    - * - * @webref data:composite - * @see PApplet#loadTable(String) - * @see PApplet#saveTable(Table, String) - * @see TableRow - */ -public class Table { - protected int rowCount; - protected int allocCount; - -// protected boolean skipEmptyRows = true; -// protected boolean skipCommentLines = true; -// protected String extension = null; -// protected boolean commaSeparatedValues = false; -// protected boolean awfulCSV = false; - - protected String missingString = null; - protected int missingInt = 0; - protected long missingLong = 0; - protected float missingFloat = Float.NaN; - protected double missingDouble = Double.NaN; - protected int missingCategory = -1; - - String[] columnTitles; - HashMapBlows[] columnCategories; - HashMap columnIndices; - - protected Object[] columns; // [column] - - // accessible for advanced users - static public final int STRING = 0; - static public final int INT = 1; - static public final int LONG = 2; - static public final int FLOAT = 3; - static public final int DOUBLE = 4; - static public final int CATEGORY = 5; - int[] columnTypes; - - protected RowIterator rowIterator; - - // 0 for doubling each time, otherwise the number of rows to increment on - // each expansion. - protected int expandIncrement; - - - /** - * Creates a new, empty table. Use addRow() to add additional rows. - */ - public Table() { - init(); - } - - /** - * @nowebref - */ - public Table(File file) throws IOException { - this(file, null); - } - - - /** - * version that uses a File object; future releases (or data types) - * may include additional optimizations here - * - * @nowebref - */ - public Table(File file, String options) throws IOException { - // uses createInput() to handle .gz (and eventually .bz2) files - init(); - parse(PApplet.createInput(file), - extensionOptions(true, file.getName(), options)); - } - - /** - * @nowebref - */ - public Table(InputStream input) throws IOException { - this(input, null); - } - - - /** - * Read the table from a stream. Possible options include: - *
      - *
    • csv - parse the table as comma-separated values - *
    • tsv - parse the table as tab-separated values - *
    • newlines - this CSV file contains newlines inside individual cells - *
    • header - this table has a header (title) row - *
    - * - * @nowebref - * @param input - * @param options - * @throws IOException - */ - public Table(InputStream input, String options) throws IOException { - init(); - parse(input, options); - } - - - public Table(Iterable rows) { - init(); - - int row = 0; - int alloc = 10; - - for (TableRow incoming : rows) { - if (row == 0) { - setColumnTypes(incoming.getColumnTypes()); - setColumnTitles(incoming.getColumnTitles()); - // Do this after setting types, otherwise it'll attempt to parse the - // allocated but empty rows, and drive CATEGORY columns nutso. - setRowCount(alloc); - // sometimes more columns than titles (and types?) - setColumnCount(incoming.getColumnCount()); - - } else if (row == alloc) { - // Far more efficient than re-allocating all columns and doing a copy - alloc *= 2; - setRowCount(alloc); - } - - //addRow(row); -// try { - setRow(row++, incoming); -// } catch (ArrayIndexOutOfBoundsException aioobe) { -// for (int i = 0; i < incoming.getColumnCount(); i++) { -// System.out.format("[%d] %s%n", i, incoming.getString(i)); -// } -// throw aioobe; -// } - } - // Shrink the table to only the rows that were used - if (row != alloc) { - setRowCount(row); - } - } - - - /** - * @nowebref - */ - public Table(ResultSet rs) { - init(); - try { - ResultSetMetaData rsmd = rs.getMetaData(); - - int columnCount = rsmd.getColumnCount(); - setColumnCount(columnCount); - - for (int col = 0; col < columnCount; col++) { - setColumnTitle(col, rsmd.getColumnName(col + 1)); - - int type = rsmd.getColumnType(col + 1); - switch (type) { // TODO these aren't tested. nor are they complete. - case Types.INTEGER: - case Types.TINYINT: - case Types.SMALLINT: - setColumnType(col, INT); - break; - case Types.BIGINT: - setColumnType(col, LONG); - break; - case Types.FLOAT: - setColumnType(col, FLOAT); - break; - case Types.DECIMAL: - case Types.DOUBLE: - case Types.REAL: - setColumnType(col, DOUBLE); - break; - } - } - - int row = 0; - while (rs.next()) { - for (int col = 0; col < columnCount; col++) { - switch (columnTypes[col]) { - case STRING: setString(row, col, rs.getString(col+1)); break; - case INT: setInt(row, col, rs.getInt(col+1)); break; - case LONG: setLong(row, col, rs.getLong(col+1)); break; - case FLOAT: setFloat(row, col, rs.getFloat(col+1)); break; - case DOUBLE: setDouble(row, col, rs.getDouble(col+1)); break; - default: throw new IllegalArgumentException("column type " + columnTypes[col] + " not supported."); - } - } - row++; -// String[] row = new String[columnCount]; -// for (int col = 0; col < columnCount; col++) { -// row[col] = rs.get(col + 1); -// } -// addRow(row); - } - - } catch (SQLException s) { - throw new RuntimeException(s); - } - } - - - public Table typedParse(InputStream input, String options) throws IOException { - Table table = new Table(); - table.setColumnTypes(this); - table.parse(input, options); - return table; - } - - - protected void init() { - columns = new Object[0]; - columnTypes = new int[0]; - columnCategories = new HashMapBlows[0]; - } - - - /* - protected String checkOptions(File file, String options) throws IOException { - String extension = null; - String filename = file.getName(); - int dotIndex = filename.lastIndexOf('.'); - if (dotIndex != -1) { - extension = filename.substring(dotIndex + 1).toLowerCase(); - if (!extension.equals("csv") && - !extension.equals("tsv") && - !extension.equals("html") && - !extension.equals("bin")) { - // ignore extension - extension = null; - } - } - if (extension == null) { - if (options == null) { - throw new IOException("This table filename has no extension, and no options are set."); - } - } else { // extension is not null - if (options == null) { - options = extension; - } else { - // prepend the extension, it will be overridden if there's an option for it. - options = extension + "," + options; - } - } - return options; - } - */ - - - static final String[] loadExtensions = { "csv", "tsv", "ods", "bin" }; - static final String[] saveExtensions = { "csv", "tsv", "ods", "bin", "html" }; - - static public String extensionOptions(boolean loading, String filename, String options) { - String extension = PApplet.checkExtension(filename); - if (extension != null) { - for (String possible : loading ? loadExtensions : saveExtensions) { - if (extension.equals(possible)) { - if (options == null) { - return extension; - } else { - // prepend the extension to the options (will be replaced by other - // options that override it later in the load loop) - return extension + "," + options; - } - } - } - } - return options; - } - - - protected void parse(InputStream input, String options) throws IOException { -// boolean awfulCSV = false; - boolean header = false; - String extension = null; - boolean binary = false; - String encoding = "UTF-8"; - - String worksheet = null; - final String sheetParam = "worksheet="; - - String[] opts = null; - if (options != null) { - opts = PApplet.trim(PApplet.split(options, ',')); - for (String opt : opts) { - if (opt.equals("tsv")) { - extension = "tsv"; - } else if (opt.equals("csv")) { - extension = "csv"; - } else if (opt.equals("ods")) { - extension = "ods"; - } else if (opt.equals("newlines")) { - //awfulCSV = true; - //extension = "csv"; - throw new IllegalArgumentException("The 'newlines' option is no longer necessary."); - } else if (opt.equals("bin")) { - binary = true; - extension = "bin"; - } else if (opt.equals("header")) { - header = true; - } else if (opt.startsWith(sheetParam)) { - worksheet = opt.substring(sheetParam.length()); - } else if (opt.startsWith("dictionary=")) { - // ignore option, this is only handled by PApplet - } else if (opt.startsWith("encoding=")) { - encoding = opt.substring(9); - } else { - throw new IllegalArgumentException("'" + opt + "' is not a valid option for loading a Table"); - } - } - } - - if (extension == null) { - throw new IllegalArgumentException("No extension specified for this Table"); - } - - if (binary) { - loadBinary(input); - - } else if (extension.equals("ods")) { - odsParse(input, worksheet, header); - - } else { - InputStreamReader isr = new InputStreamReader(input, encoding); - BufferedReader reader = new BufferedReader(isr); - - // strip out the Unicode BOM, if present - reader.mark(1); - int c = reader.read(); - // if not the BOM, back up to the beginning again - if (c != '\uFEFF') { - reader.reset(); - } - - /* - if (awfulCSV) { - parseAwfulCSV(reader, header); - } else if ("tsv".equals(extension)) { - parseBasic(reader, header, true); - } else if ("csv".equals(extension)) { - parseBasic(reader, header, false); - } - */ - parseBasic(reader, header, "tsv".equals(extension)); - } - } - - - protected void parseBasic(BufferedReader reader, - boolean header, boolean tsv) throws IOException { - String line = null; - int row = 0; - if (rowCount == 0) { - setRowCount(10); - } - //int prev = 0; //-1; - try { - while ((line = reader.readLine()) != null) { - if (row == getRowCount()) { - setRowCount(row << 1); - } - if (row == 0 && header) { - setColumnTitles(tsv ? PApplet.split(line, '\t') : splitLineCSV(line, reader)); - header = false; - } else { - setRow(row, tsv ? PApplet.split(line, '\t') : splitLineCSV(line, reader)); - row++; - } - - if (row % 10000 == 0) { - /* - // this is problematic unless we're going to calculate rowCount first - if (row < rowCount) { - int pct = (100 * row) / rowCount; - if (pct != prev) { // also prevents "0%" from showing up - System.out.println(pct + "%"); - prev = pct; - } - } - */ - try { - // Sleep this thread so that the GC can catch up - Thread.sleep(10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } catch (Exception e) { - throw new RuntimeException("Error reading table on line " + row, e); - } - // shorten or lengthen based on what's left - if (row != getRowCount()) { - setRowCount(row); - } - } - - -// public void convertTSV(BufferedReader reader, File outputFile) throws IOException { -// convertBasic(reader, true, outputFile); -// } - - - /* - protected void parseAwfulCSV(BufferedReader reader, - boolean header) throws IOException { - char[] c = new char[100]; - int count = 0; - boolean insideQuote = false; - - int alloc = 100; - setRowCount(100); - - int row = 0; - int col = 0; - int ch; - while ((ch = reader.read()) != -1) { - if (insideQuote) { - if (ch == '\"') { - // this is either the end of a quoted entry, or a quote character - reader.mark(1); - if (reader.read() == '\"') { - // it's "", which means a quote character - if (count == c.length) { - c = PApplet.expand(c); - } - c[count++] = '\"'; - } else { - // nope, just the end of a quoted csv entry - reader.reset(); - insideQuote = false; - // TODO nothing here that prevents bad csv data from showing up - // after the quote and before the comma... -// set(row, col, new String(c, 0, count)); -// count = 0; -// col++; -// insideQuote = false; - } - } else { // inside a quote, but the character isn't a quote - if (count == c.length) { - c = PApplet.expand(c); - } - c[count++] = (char) ch; - } - } else { // not inside a quote - if (ch == '\"') { - insideQuote = true; - - } else if (ch == '\r' || ch == '\n') { - if (ch == '\r') { - // check to see if next is a '\n' - reader.mark(1); - if (reader.read() != '\n') { - reader.reset(); - } - } - setString(row, col, new String(c, 0, count)); - count = 0; - row++; - if (row == 1 && header) { - // Use internal row removal (efficient because only one row). - removeTitleRow(); - // Un-set the header variable so that next time around, we don't - // just get stuck into a loop, removing the 0th row repeatedly. - header = false; - // Reset the number of rows (removeTitleRow() won't reset our local 'row' counter) - row = 0; - } -// if (row % 1000 == 0) { -// PApplet.println(PApplet.nfc(row)); -// } - if (row == alloc) { - alloc *= 2; - setRowCount(alloc); - } - col = 0; - - } else if (ch == ',') { - setString(row, col, new String(c, 0, count)); - count = 0; - // starting a new column, make sure we have room - col++; - ensureColumn(col); - - } else { // just a regular character, add it - if (count == c.length) { - c = PApplet.expand(c); - } - c[count++] = (char) ch; - } - } - } - // catch any leftovers - if (count > 0) { - setString(row, col, new String(c, 0, count)); - } - row++; // set row to row count (the current row index + 1) - if (alloc != row) { - setRowCount(row); // shrink to the actual size - } - } - */ - - - static class CommaSeparatedLine { - char[] c; - String[] pieces; - int pieceCount; - -// int offset; - int start; //, stop; - - String[] handle(String line, BufferedReader reader) throws IOException { -// PApplet.println("handle() called for: " + line); - start = 0; - pieceCount = 0; - c = line.toCharArray(); - - // get tally of number of columns and allocate the array - int cols = 1; // the first comma indicates the second column - boolean quote = false; - for (int i = 0; i < c.length; i++) { - if (!quote && (c[i] == ',')) { - cols++; - } else if (c[i] == '\"') { - // double double quotes (escaped quotes like "") will simply toggle - // this back and forth, so it should remain accurate - quote = !quote; - } - } - pieces = new String[cols]; - -// while (offset < c.length) { -// start = offset; - while (start < c.length) { - boolean enough = ingest(); - while (!enough) { - // found a newline inside the quote, grab another line - String nextLine = reader.readLine(); -// System.out.println("extending to " + nextLine); - if (nextLine == null) { -// System.err.println(line); - throw new IOException("Found a quoted line that wasn't terminated properly."); - } - // for simplicity, not bothering to skip what's already been read - // from c (and reset the offset to 0), opting to make a bigger array - // with both lines. - char[] temp = new char[c.length + 1 + nextLine.length()]; - PApplet.arrayCopy(c, temp, c.length); - // NOTE: we're converting to \n here, which isn't perfect - temp[c.length] = '\n'; - nextLine.getChars(0, nextLine.length(), temp, c.length + 1); -// c = temp; - return handle(new String(temp), reader); - //System.out.println(" full line is now " + new String(c)); - //stop = nextComma(c, offset); - //System.out.println("stop is now " + stop); - //enough = ingest(); - } - } - - // Make any remaining entries blanks instead of nulls. Empty columns from - // CSV are always "" not null, so this handles successive commas in a line - for (int i = pieceCount; i < pieces.length; i++) { - pieces[i] = ""; - } -// PApplet.printArray(pieces); - return pieces; - } - - protected void addPiece(int start, int stop, boolean quotes) { - if (quotes) { - int dest = start; - for (int i = start; i < stop; i++) { - if (c[i] == '\"') { - ++i; // step over the quote - } - if (i != dest) { - c[dest] = c[i]; - } - dest++; - } - pieces[pieceCount++] = new String(c, start, dest - start); - - } else { - pieces[pieceCount++] = new String(c, start, stop - start); - } - } - - /** - * Returns the next comma (not inside a quote) in the specified array. - * @param c array to search - * @param index offset at which to start looking - * @return index of the comma, or -1 if line ended inside an unclosed quote - */ - protected boolean ingest() { - boolean hasEscapedQuotes = false; - // not possible -// if (index == c.length) { // we're already at the end -// return c.length; -// } - boolean quoted = c[start] == '\"'; - if (quoted) { - start++; // step over the quote - } - int i = start; - while (i < c.length) { -// PApplet.println(c[i] + " i=" + i); - if (c[i] == '\"') { - // if this fella started with a quote - if (quoted) { - if (i == c.length-1) { - // closing quote for field; last field on the line - addPiece(start, i, hasEscapedQuotes); - start = c.length; - return true; - - } else if (c[i+1] == '\"') { - // an escaped quote inside a quoted field, step over it - hasEscapedQuotes = true; - i += 2; - - } else if (c[i+1] == ',') { - // that was our closing quote, get outta here - addPiece(start, i, hasEscapedQuotes); - start = i+2; - return true; - - } else { - // This is a lone-wolf quote, occasionally seen in exports. - // It's a single quote in the middle of some other text, - // and not escaped properly. Pray for the best! - i++; - } - - } else { // not a quoted line - if (i == c.length-1) { - // we're at the end of the line, can't have an unescaped quote - throw new RuntimeException("Unterminated quote at end of line"); - - } else if (c[i+1] == '\"') { - // step over this crummy quote escape - hasEscapedQuotes = true; - i += 2; - - } else { - throw new RuntimeException("Unterminated quoted field mid-line"); - } - } - } else if (!quoted && c[i] == ',') { - addPiece(start, i, hasEscapedQuotes); - start = i+1; - return true; - - } else if (!quoted && i == c.length-1) { - addPiece(start, c.length, hasEscapedQuotes); - start = c.length; - return true; - - } else { // nothing all that interesting - i++; - } - } -// if (!quote && (c[i] == ',')) { -// // found a comma, return this location -// return i; -// } else if (c[i] == '\"') { -// // if it's a quote, then either the next char is another quote, -// // or if this is a quoted entry, it better be a comma -// quote = !quote; -// } -// } - - // if still inside a quote, indicate that another line should be read - if (quoted) { - return false; - } - -// // made it to the end of the array with no new comma -// return c.length; - - throw new RuntimeException("not sure how..."); - } - } - - - CommaSeparatedLine csl; - - /** - * Parse a line of text as comma-separated values, returning each value as - * one entry in an array of String objects. Remove quotes from entries that - * begin and end with them, and convert 'escaped' quotes to actual quotes. - * @param line line of text to be parsed - * @return an array of the individual values formerly separated by commas - */ - protected String[] splitLineCSV(String line, BufferedReader reader) throws IOException { - if (csl == null) { - csl = new CommaSeparatedLine(); - } - return csl.handle(line, reader); - } - - - /** - * Returns the next comma (not inside a quote) in the specified array. - * @param c array to search - * @param index offset at which to start looking - * @return index of the comma, or -1 if line ended inside an unclosed quote - */ - /* - static protected int nextComma(char[] c, int index) { - if (index == c.length) { // we're already at the end - return c.length; - } - boolean quoted = c[index] == '\"'; - if (quoted) { - index++; // step over the quote - } - for (int i = index; i < c.length; i++) { - if (c[i] == '\"') { - // if this fella started with a quote - if (quoted) { - if (i == c.length-1) { - //return -1; // ran out of chars - // closing quote for field; last field on the line - return c.length; - } else if (c[i+1] == '\"') { - // an escaped quote inside a quoted field, step over it - i++; - } else if (c[i+1] == ',') { - // that's our closing quote, get outta here - return i+1; - } - - } else { // not a quoted line - if (i == c.length-1) { - // we're at the end of the line, can't have an unescaped quote - //return -1; // ran out of chars - throw new RuntimeException("Unterminated quoted field at end of line"); - } else if (c[i+1] == '\"') { - // step over this crummy quote escape - ++i; - } else { - throw new RuntimeException("Unterminated quoted field mid-line"); - } - } - } else if (!quoted && c[i] == ',') { - return i; - } - if (!quote && (c[i] == ',')) { - // found a comma, return this location - return i; - } else if (c[i] == '\"') { - // if it's a quote, then either the next char is another quote, - // or if this is a quoted entry, it better be a comma - quote = !quote; - } - } - // if still inside a quote, indicate that another line should be read - if (quote) { - return -1; - } - // made it to the end of the array with no new comma - return c.length; - } - */ - - - /** - * Read a .ods (OpenDoc spreadsheet) zip file from an InputStream, and - * return the InputStream for content.xml contained inside. - */ - private InputStream odsFindContentXML(InputStream input) { - ZipInputStream zis = new ZipInputStream(input); - ZipEntry entry = null; - try { - while ((entry = zis.getNextEntry()) != null) { - if (entry.getName().equals("content.xml")) { - return zis; - } - } - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - - protected void odsParse(InputStream input, String worksheet, boolean header) { - try { - InputStream contentStream = odsFindContentXML(input); - XML xml = new XML(contentStream); - - // table files will have multiple sheets.. - // - // - // - XML[] sheets = - xml.getChildren("office:body/office:spreadsheet/table:table"); - - boolean found = false; - for (XML sheet : sheets) { -// System.out.println(sheet.getAttribute("table:name")); - if (worksheet == null || worksheet.equals(sheet.getString("table:name"))) { - odsParseSheet(sheet, header); - found = true; - if (worksheet == null) { - break; // only read the first sheet - } - } - } - if (!found) { - if (worksheet == null) { - throw new RuntimeException("No worksheets found in the ODS file."); - } else { - throw new RuntimeException("No worksheet named " + worksheet + - " found in the ODS file."); - } - } - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } - } - - - /** - * Parses a single sheet of XML from this file. - * @param The XML object for a single worksheet from the ODS file - */ - private void odsParseSheet(XML sheet, boolean header) { - // Extra

    or tags inside the text tag for the cell will be stripped. - // Different from showing formulas, and not quite the same as 'save as - // displayed' option when saving from inside OpenOffice. Only time we - // wouldn't want this would be so that we could parse hyperlinks and - // styling information intact, but that's out of scope for the p5 version. - final boolean ignoreTags = true; - - XML[] rows = sheet.getChildren("table:table-row"); - //xml.getChildren("office:body/office:spreadsheet/table:table/table:table-row"); - - int rowIndex = 0; - for (XML row : rows) { - int rowRepeat = row.getInt("table:number-rows-repeated", 1); -// if (rowRepeat != 1) { -// System.out.println(rowRepeat + " " + rowCount + " " + (rowCount + rowRepeat)); -// } - boolean rowNotNull = false; - XML[] cells = row.getChildren(); - int columnIndex = 0; - - for (XML cell : cells) { - int cellRepeat = cell.getInt("table:number-columns-repeated", 1); - -// -// 4150.00 -// - - String cellData = ignoreTags ? cell.getString("office:value") : null; - - // if there's an office:value in the cell, just roll with that - if (cellData == null) { - int cellKids = cell.getChildCount(); - if (cellKids != 0) { - XML[] paragraphElements = cell.getChildren("text:p"); - if (paragraphElements.length != 1) { - for (XML el : paragraphElements) { - System.err.println(el.toString()); - } - throw new RuntimeException("found more than one text:p element"); - } - XML textp = paragraphElements[0]; - String textpContent = textp.getContent(); - // if there are sub-elements, the content shows up as a child element - // (for which getName() returns null.. which seems wrong) - if (textpContent != null) { - cellData = textpContent; // nothing fancy, the text is in the text:p element - } else { - XML[] textpKids = textp.getChildren(); - StringBuilder cellBuffer = new StringBuilder(); - for (XML kid : textpKids) { - String kidName = kid.getName(); - if (kidName == null) { - odsAppendNotNull(kid, cellBuffer); - - } else if (kidName.equals("text:s")) { - int spaceCount = kid.getInt("text:c", 1); - for (int space = 0; space < spaceCount; space++) { - cellBuffer.append(' '); - } - } else if (kidName.equals("text:span")) { - odsAppendNotNull(kid, cellBuffer); - - } else if (kidName.equals("text:a")) { - // blah.com - if (ignoreTags) { - cellBuffer.append(kid.getString("xlink:href")); - } else { - odsAppendNotNull(kid, cellBuffer); - } - - } else { - odsAppendNotNull(kid, cellBuffer); - System.err.println(getClass().getName() + ": don't understand: " + kid); - //throw new RuntimeException("I'm not used to this."); - } - } - cellData = cellBuffer.toString(); - } - //setString(rowIndex, columnIndex, c); //text[0].getContent()); - //columnIndex++; - } - } - for (int r = 0; r < cellRepeat; r++) { - if (cellData != null) { - //System.out.println("setting " + rowIndex + "," + columnIndex + " to " + cellData); - setString(rowIndex, columnIndex, cellData); - } - columnIndex++; - if (cellData != null) { -// if (columnIndex > columnMax) { -// columnMax = columnIndex; -// } - rowNotNull = true; - } - } - } - if (header) { - removeTitleRow(); // efficient enough on the first row - header = false; // avoid infinite loop - - } else { - if (rowNotNull && rowRepeat > 1) { - String[] rowStrings = getStringRow(rowIndex); - for (int r = 1; r < rowRepeat; r++) { - addRow(rowStrings); - } - } - rowIndex += rowRepeat; - } - } - } - - - private void odsAppendNotNull(XML kid, StringBuilder buffer) { - String content = kid.getContent(); - if (content != null) { - buffer.append(content); - } - } - - - // A 'Class' object is used here, so the syntax for this function is: - // Table t = loadTable("cars3.tsv", "header"); - // Record[] records = (Record[]) t.parse(Record.class); - // While t.parse("Record") might be nicer, the class is likely to be an - // inner class (another tab in a PDE sketch) or even inside a package, - // so additional information would be needed to locate it. The name of the - // inner class would be "SketchName$Record" which isn't acceptable syntax - // to make people use. Better to just introduce the '.class' syntax. - - // Unlike the Table class itself, this accepts char and boolean fields in - // the target class, since they're much more prevalent, and don't require - // a zillion extra methods and special cases in the rest of the class here. - - // since this is likely an inner class, needs a reference to its parent, - // because that's passed to the constructor parameter (inserted by the - // compiler) of an inner class by the runtime. - - /** incomplete, do not use */ - public void parseInto(Object enclosingObject, String fieldName) { - Class target = null; - Object outgoing = null; - Field targetField = null; - try { - // Object targetObject, - // Class target -> get this from the type of fieldName -// Class sketchClass = sketch.getClass(); - Class sketchClass = enclosingObject.getClass(); - targetField = sketchClass.getDeclaredField(fieldName); -// PApplet.println("found " + targetField); - Class targetArray = targetField.getType(); - if (!targetArray.isArray()) { - // fieldName is not an array - } else { - target = targetArray.getComponentType(); - outgoing = Array.newInstance(target, getRowCount()); - } - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - -// Object enclosingObject = sketch; -// PApplet.println("enclosing obj is " + enclosingObject); - Class enclosingClass = target.getEnclosingClass(); - Constructor con = null; - - try { - if (enclosingClass == null) { - con = target.getDeclaredConstructor(); //new Class[] { }); -// PApplet.println("no enclosing class"); - } else { - con = target.getDeclaredConstructor(new Class[] { enclosingClass }); -// PApplet.println("enclosed by " + enclosingClass.getName()); - } - if (!con.isAccessible()) { -// System.out.println("setting constructor to public"); - con.setAccessible(true); - } - } catch (SecurityException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - - Field[] fields = target.getDeclaredFields(); - ArrayList inuse = new ArrayList<>(); - for (Field field : fields) { - String name = field.getName(); - if (getColumnIndex(name, false) != -1) { -// System.out.println("found field " + name); - if (!field.isAccessible()) { -// PApplet.println(" changing field access"); - field.setAccessible(true); - } - inuse.add(field); - } else { -// System.out.println("skipping field " + name); - } - } - - int index = 0; - try { - for (TableRow row : rows()) { - Object item = null; - if (enclosingClass == null) { - //item = target.newInstance(); - item = con.newInstance(); - } else { - item = con.newInstance(new Object[] { enclosingObject }); - } - //Object item = defaultCons.newInstance(new Object[] { }); - for (Field field : inuse) { - String name = field.getName(); - //PApplet.println("gonna set field " + name); - - if (field.getType() == String.class) { - field.set(item, row.getString(name)); - - } else if (field.getType() == Integer.TYPE) { - field.setInt(item, row.getInt(name)); - - } else if (field.getType() == Long.TYPE) { - field.setLong(item, row.getLong(name)); - - } else if (field.getType() == Float.TYPE) { - field.setFloat(item, row.getFloat(name)); - - } else if (field.getType() == Double.TYPE) { - field.setDouble(item, row.getDouble(name)); - - } else if (field.getType() == Boolean.TYPE) { - String content = row.getString(name); - if (content != null) { - // Only bother setting if it's true, - // otherwise false by default anyway. - if (content.toLowerCase().equals("true") || - content.equals("1")) { - field.setBoolean(item, true); - } - } -// if (content == null) { -// field.setBoolean(item, false); // necessary? -// } else if (content.toLowerCase().equals("true")) { -// field.setBoolean(item, true); -// } else if (content.equals("1")) { -// field.setBoolean(item, true); -// } else { -// field.setBoolean(item, false); // necessary? -// } - } else if (field.getType() == Character.TYPE) { - String content = row.getString(name); - if (content != null && content.length() > 0) { - // Otherwise set to \0 anyway - field.setChar(item, content.charAt(0)); - } - } - } -// list.add(item); - Array.set(outgoing, index++, item); - } - if (!targetField.isAccessible()) { -// PApplet.println("setting target field to public"); - targetField.setAccessible(true); - } - // Set the array in the sketch -// targetField.set(sketch, outgoing); - targetField.set(enclosingObject, outgoing); - - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } - - - public boolean save(File file, String options) throws IOException { - return save(PApplet.createOutput(file), - Table.extensionOptions(false, file.getName(), options)); - } - - - public boolean save(OutputStream output, String options) { - PrintWriter writer = PApplet.createWriter(output); - String extension = null; - if (options == null) { - throw new IllegalArgumentException("No extension specified for saving this Table"); - } - - String[] opts = PApplet.trim(PApplet.split(options, ',')); - // Only option for save is the extension, so we can safely grab the last - extension = opts[opts.length - 1]; - boolean found = false; - for (String ext : saveExtensions) { - if (extension.equals(ext)) { - found = true; - break; - } - } - // Not providing a fallback; let's make users specify an extension - if (!found) { - throw new IllegalArgumentException("'" + extension + "' not available for Table"); - } - - if (extension.equals("csv")) { - writeCSV(writer); - } else if (extension.equals("tsv")) { - writeTSV(writer); - } else if (extension.equals("ods")) { - try { - saveODS(output); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } else if (extension.equals("html")) { - writeHTML(writer); - } else if (extension.equals("bin")) { - try { - saveBinary(output); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - writer.flush(); - writer.close(); - return true; - } - - - protected void writeTSV(PrintWriter writer) { - if (columnTitles != null) { - for (int col = 0; col < columns.length; col++) { - if (col != 0) { - writer.print('\t'); - } - if (columnTitles[col] != null) { - writer.print(columnTitles[col]); - } - } - writer.println(); - } - for (int row = 0; row < rowCount; row++) { - for (int col = 0; col < getColumnCount(); col++) { - if (col != 0) { - writer.print('\t'); - } - String entry = getString(row, col); - // just write null entries as blanks, rather than spewing 'null' - // all over the spreadsheet file. - if (entry != null) { - writer.print(entry); - } - } - writer.println(); - } - writer.flush(); - } - - - protected void writeCSV(PrintWriter writer) { - if (columnTitles != null) { - for (int col = 0; col < getColumnCount(); col++) { - if (col != 0) { - writer.print(','); - } - try { - if (columnTitles[col] != null) { // col < columnTitles.length && - writeEntryCSV(writer, columnTitles[col]); - } - } catch (ArrayIndexOutOfBoundsException e) { - PApplet.printArray(columnTitles); - PApplet.printArray(columns); - throw e; - } - } - writer.println(); - } - for (int row = 0; row < rowCount; row++) { - for (int col = 0; col < getColumnCount(); col++) { - if (col != 0) { - writer.print(','); - } - String entry = getString(row, col); - // just write null entries as blanks, rather than spewing 'null' - // all over the spreadsheet file. - if (entry != null) { - writeEntryCSV(writer, entry); - } - } - // Prints the newline for the row, even if it's missing - writer.println(); - } - writer.flush(); - } - - - protected void writeEntryCSV(PrintWriter writer, String entry) { - if (entry != null) { - if (entry.indexOf('\"') != -1) { // convert quotes to double quotes - char[] c = entry.toCharArray(); - writer.print('\"'); - for (int i = 0; i < c.length; i++) { - if (c[i] == '\"') { - writer.print("\"\""); - } else { - writer.print(c[i]); - } - } - writer.print('\"'); - - // add quotes if commas or CR/LF are in the entry - } else if (entry.indexOf(',') != -1 || - entry.indexOf('\n') != -1 || - entry.indexOf('\r') != -1) { - writer.print('\"'); - writer.print(entry); - writer.print('\"'); - - - // add quotes if leading or trailing space - } else if ((entry.length() > 0) && - (entry.charAt(0) == ' ' || - entry.charAt(entry.length() - 1) == ' ')) { - writer.print('\"'); - writer.print(entry); - writer.print('\"'); - - } else { - writer.print(entry); - } - } - } - - - protected void writeHTML(PrintWriter writer) { - writer.println(""); -// writer.println(""); -// writer.println(""); - - writer.println(""); - writer.println(""); - writer.println(" "); - writer.println(""); - - writer.println(""); - writer.println(" "); - - if (hasColumnTitles()) { - writer.println(" "); - for (String entry : getColumnTitles()) { - writer.print(" "); - } - writer.println(" "); - } - - for (int row = 0; row < getRowCount(); row++) { - writer.println(" "); - for (int col = 0; col < getColumnCount(); col++) { - String entry = getString(row, col); - writer.print(" "); - } - writer.println(" "); - } - writer.println("
    "); - if (entry != null) { - writeEntryHTML(writer, entry); - } - writer.println("
    "); - if (entry != null) { - // probably not a great idea to mess w/ the export -// if (entry.startsWith("<") && entry.endsWith(">")) { -// writer.print(entry); -// } else { - writeEntryHTML(writer, entry); -// } - } - writer.println("
    "); - writer.println(""); - - writer.println(""); - writer.flush(); - } - - - protected void writeEntryHTML(PrintWriter writer, String entry) { - //char[] chars = entry.toCharArray(); - for (char c : entry.toCharArray()) { //chars) { - if (c == '<') { - writer.print("<"); - } else if (c == '>') { - writer.print(">"); - } else if (c == '&') { - writer.print("&"); -// } else if (c == '\'') { // only in XML -// writer.print("'"); - } else if (c == '"') { - writer.print("""); - - } else if (c < 32 || c > 127) { // keep in ASCII or Tidy complains - writer.print("&#"); - writer.print((int) c); - writer.print(';'); - - } else { - writer.print(c); - } - } - } - - - protected void saveODS(OutputStream os) throws IOException { - ZipOutputStream zos = new ZipOutputStream(os); - - final String xmlHeader = ""; - - ZipEntry entry = new ZipEntry("META-INF/manifest.xml"); - String[] lines = new String[] { - xmlHeader, - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - zos.putNextEntry(entry); - zos.write(PApplet.join(lines, "\n").getBytes()); - zos.closeEntry(); - - /* - entry = new ZipEntry("meta.xml"); - lines = new String[] { - xmlHeader, - "" - }; - zos.putNextEntry(entry); - zos.write(PApplet.join(lines, "\n").getBytes()); - zos.closeEntry(); - - entry = new ZipEntry("meta.xml"); - lines = new String[] { - xmlHeader, - "" - }; - zos.putNextEntry(entry); - zos.write(PApplet.join(lines, "\n").getBytes()); - zos.closeEntry(); - - entry = new ZipEntry("settings.xml"); - lines = new String[] { - xmlHeader, - "" - }; - zos.putNextEntry(entry); - zos.write(PApplet.join(lines, "\n").getBytes()); - zos.closeEntry(); - - entry = new ZipEntry("styles.xml"); - lines = new String[] { - xmlHeader, - "" - }; - zos.putNextEntry(entry); - zos.write(PApplet.join(lines, "\n").getBytes()); - zos.closeEntry(); - */ - - final String[] dummyFiles = new String[] { - "meta.xml", "settings.xml", "styles.xml" - }; - lines = new String[] { - xmlHeader, - "" - }; - byte[] dummyBytes = PApplet.join(lines, "\n").getBytes(); - for (String filename : dummyFiles) { - entry = new ZipEntry(filename); - zos.putNextEntry(entry); - zos.write(dummyBytes); - zos.closeEntry(); - } - - // - - entry = new ZipEntry("mimetype"); - zos.putNextEntry(entry); - zos.write("application/vnd.oasis.opendocument.spreadsheet".getBytes()); - zos.closeEntry(); - - // - - entry = new ZipEntry("content.xml"); - zos.putNextEntry(entry); - //lines = new String[] { - writeUTF(zos, new String[] { - xmlHeader, - "", - " ", - " ", - " " - }); - //zos.write(PApplet.join(lines, "\n").getBytes()); - - byte[] rowStart = " \n".getBytes(); - byte[] rowStop = " \n".getBytes(); - - if (hasColumnTitles()) { - zos.write(rowStart); - for (int i = 0; i < getColumnCount(); i++) { - saveStringODS(zos, columnTitles[i]); - } - zos.write(rowStop); - } - - for (TableRow row : rows()) { - zos.write(rowStart); - for (int i = 0; i < getColumnCount(); i++) { - if (columnTypes[i] == STRING || columnTypes[i] == CATEGORY) { - saveStringODS(zos, row.getString(i)); - } else { - saveNumberODS(zos, row.getString(i)); - } - } - zos.write(rowStop); - } - - //lines = new String[] { - writeUTF(zos, new String[] { - " ", - " ", - " ", - "" - }); - //zos.write(PApplet.join(lines, "\n").getBytes()); - zos.closeEntry(); - - zos.flush(); - zos.close(); - } - - - void saveStringODS(OutputStream output, String text) throws IOException { - // At this point, I should have just used the XML library. But this does - // save us from having to create the entire document in memory again before - // writing to the file. So while it's dorky, the outcome is still useful. - StringBuilder sanitized = new StringBuilder(); - if (text != null) { - char[] array = text.toCharArray(); - for (char c : array) { - if (c == '&') { - sanitized.append("&"); - } else if (c == '\'') { - sanitized.append("'"); - } else if (c == '"') { - sanitized.append("""); - } else if (c == '<') { - sanitized.append("<"); - } else if (c == '>') { - sanitized.append("&rt;"); - } else if (c < 32 || c > 127) { - sanitized.append("&#" + ((int) c) + ";"); - } else { - sanitized.append(c); - } - } - } - - writeUTF(output, - " ", - " " + sanitized + "", - " "); - } - - - void saveNumberODS(OutputStream output, String text) throws IOException { - writeUTF(output, - " ", - " " + text + "", - " "); - } - - - static Charset utf8; - - static void writeUTF(OutputStream output, String... lines) throws IOException { - if (utf8 == null) { - utf8 = Charset.forName("UTF-8"); - } - for (String str : lines) { - output.write(str.getBytes(utf8)); - output.write('\n'); - } - } - - - protected void saveBinary(OutputStream os) throws IOException { - DataOutputStream output = new DataOutputStream(new BufferedOutputStream(os)); - output.writeInt(0x9007AB1E); // version - output.writeInt(getRowCount()); - output.writeInt(getColumnCount()); - if (columnTitles != null) { - output.writeBoolean(true); - for (String title : columnTitles) { - output.writeUTF(title); - } - } else { - output.writeBoolean(false); - } - for (int i = 0; i < getColumnCount(); i++) { - //System.out.println(i + " is " + columnTypes[i]); - output.writeInt(columnTypes[i]); - } - - for (int i = 0; i < getColumnCount(); i++) { - if (columnTypes[i] == CATEGORY) { - columnCategories[i].write(output); - } - } - if (missingString == null) { - output.writeBoolean(false); - } else { - output.writeBoolean(true); - output.writeUTF(missingString); - } - output.writeInt(missingInt); - output.writeLong(missingLong); - output.writeFloat(missingFloat); - output.writeDouble(missingDouble); - output.writeInt(missingCategory); - - for (TableRow row : rows()) { - for (int col = 0; col < getColumnCount(); col++) { - switch (columnTypes[col]) { - case STRING: - String str = row.getString(col); - if (str == null) { - output.writeBoolean(false); - } else { - output.writeBoolean(true); - output.writeUTF(str); - } - break; - case INT: - output.writeInt(row.getInt(col)); - break; - case LONG: - output.writeLong(row.getLong(col)); - break; - case FLOAT: - output.writeFloat(row.getFloat(col)); - break; - case DOUBLE: - output.writeDouble(row.getDouble(col)); - break; - case CATEGORY: - String peace = row.getString(col); - if (peace.equals(missingString)) { - output.writeInt(missingCategory); - } else { - output.writeInt(columnCategories[col].index(peace)); - } - break; - } - } - } - - output.flush(); - output.close(); - } - - - protected void loadBinary(InputStream is) throws IOException { - DataInputStream input = new DataInputStream(new BufferedInputStream(is)); - - int magic = input.readInt(); - if (magic != 0x9007AB1E) { - throw new IOException("Not a compatible binary table (magic was " + PApplet.hex(magic) + ")"); - } - int rowCount = input.readInt(); - setRowCount(rowCount); - int columnCount = input.readInt(); - setColumnCount(columnCount); - - boolean hasTitles = input.readBoolean(); - if (hasTitles) { - columnTitles = new String[getColumnCount()]; - for (int i = 0; i < columnCount; i++) { - //columnTitles[i] = input.readUTF(); - setColumnTitle(i, input.readUTF()); - } - } - for (int column = 0; column < columnCount; column++) { - int newType = input.readInt(); - columnTypes[column] = newType; - switch (newType) { - case INT: - columns[column] = new int[rowCount]; - break; - case LONG: - columns[column] = new long[rowCount];; - break; - case FLOAT: - columns[column] = new float[rowCount];; - break; - case DOUBLE: - columns[column] = new double[rowCount];; - break; - case STRING: - columns[column] = new String[rowCount];; - break; - case CATEGORY: - columns[column] = new int[rowCount];; - break; - default: - throw new IllegalArgumentException(newType + " is not a valid column type."); - } - } - - for (int i = 0; i < columnCount; i++) { - if (columnTypes[i] == CATEGORY) { - columnCategories[i] = new HashMapBlows(input); - } - } - - if (input.readBoolean()) { - missingString = input.readUTF(); - } else { - missingString = null; - } - missingInt = input.readInt(); - missingLong = input.readLong(); - missingFloat = input.readFloat(); - missingDouble = input.readDouble(); - missingCategory = input.readInt(); - - for (int row = 0; row < rowCount; row++) { - for (int col = 0; col < columnCount; col++) { - switch (columnTypes[col]) { - case STRING: - String str = null; - if (input.readBoolean()) { - str = input.readUTF(); - } - setString(row, col, str); - break; - case INT: - setInt(row, col, input.readInt()); - break; - case LONG: - setLong(row, col, input.readLong()); - break; - case FLOAT: - setFloat(row, col, input.readFloat()); - break; - case DOUBLE: - setDouble(row, col, input.readDouble()); - break; - case CATEGORY: - int index = input.readInt(); - //String name = columnCategories[col].key(index); - setInt(row, col, index); - break; - } - } - } - - input.close(); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * @webref table:method - * @brief Adds a new column to a table - * @see Table#removeColumn(String) - */ - public void addColumn() { - addColumn(null, STRING); - } - - - /** - * @param title the title to be used for the new column - */ - public void addColumn(String title) { - addColumn(title, STRING); - } - - - /** - * @param type the type to be used for the new column: INT, LONG, FLOAT, DOUBLE, or STRING - */ - public void addColumn(String title, int type) { - insertColumn(columns.length, title, type); - } - - - public void insertColumn(int index) { - insertColumn(index, null, STRING); - } - - - public void insertColumn(int index, String title) { - insertColumn(index, title, STRING); - } - - - public void insertColumn(int index, String title, int type) { - if (title != null && columnTitles == null) { - columnTitles = new String[columns.length]; - } - if (columnTitles != null) { - columnTitles = PApplet.splice(columnTitles, title, index); - columnIndices = null; - } - columnTypes = PApplet.splice(columnTypes, type, index); - -// columnCategories = (HashMapBlows[]) -// PApplet.splice(columnCategories, new HashMapBlows(), index); - HashMapBlows[] catTemp = new HashMapBlows[columns.length + 1]; - // Faster than arrayCopy for a dozen or so entries - for (int i = 0; i < index; i++) { - catTemp[i] = columnCategories[i]; - } - catTemp[index] = new HashMapBlows(); - for (int i = index; i < columns.length; i++) { - catTemp[i+1] = columnCategories[i]; - } - columnCategories = catTemp; - - Object[] temp = new Object[columns.length + 1]; - System.arraycopy(columns, 0, temp, 0, index); - System.arraycopy(columns, index, temp, index+1, columns.length - index); - columns = temp; - - switch (type) { - case INT: columns[index] = new int[rowCount]; break; - case LONG: columns[index] = new long[rowCount]; break; - case FLOAT: columns[index] = new float[rowCount]; break; - case DOUBLE: columns[index] = new double[rowCount]; break; - case STRING: columns[index] = new String[rowCount]; break; - case CATEGORY: columns[index] = new int[rowCount]; break; - } - } - - /** - * @webref table:method - * @brief Removes a column from a table - * @param columnName the title of the column to be removed - * @see Table#addColumn() - */ - public void removeColumn(String columnName) { - removeColumn(getColumnIndex(columnName)); - } - - /** - * @param column the index number of the column to be removed - */ - public void removeColumn(int column) { - int newCount = columns.length - 1; - - Object[] columnsTemp = new Object[newCount]; - HashMapBlows[] catTemp = new HashMapBlows[newCount]; - - for (int i = 0; i < column; i++) { - columnsTemp[i] = columns[i]; - catTemp[i] = columnCategories[i]; - } - for (int i = column; i < newCount; i++) { - columnsTemp[i] = columns[i+1]; - catTemp[i] = columnCategories[i+1]; - } - - columns = columnsTemp; - columnCategories = catTemp; - - if (columnTitles != null) { - String[] titlesTemp = new String[newCount]; - for (int i = 0; i < column; i++) { - titlesTemp[i] = columnTitles[i]; - } - for (int i = column; i < newCount; i++) { - titlesTemp[i] = columnTitles[i+1]; - } - columnTitles = titlesTemp; - columnIndices = null; - } - } - - - /** - * @webref table:method - * @brief Gets the number of columns in a table - * @see Table#getRowCount() - */ - public int getColumnCount() { - return columns.length; - } - - - /** - * Change the number of columns in this table. Resizes all rows to ensure - * the same number of columns in each row. Entries in the additional (empty) - * columns will be set to null. - * @param newCount - */ - public void setColumnCount(int newCount) { - int oldCount = columns.length; - if (oldCount != newCount) { - columns = (Object[]) PApplet.expand(columns, newCount); - // create new columns, default to String as the data type - for (int c = oldCount; c < newCount; c++) { - columns[c] = new String[rowCount]; - } - - if (columnTitles != null) { - columnTitles = PApplet.expand(columnTitles, newCount); - } - columnTypes = PApplet.expand(columnTypes, newCount); - columnCategories = (HashMapBlows[]) - PApplet.expand(columnCategories, newCount); - } - } - - - public void setColumnType(String columnName, String columnType) { - setColumnType(checkColumnIndex(columnName), columnType); - } - - - static int parseColumnType(String columnType) { - columnType = columnType.toLowerCase(); - int type = -1; - if (columnType.equals("string")) { - type = STRING; - } else if (columnType.equals("int")) { - type = INT; - } else if (columnType.equals("long")) { - type = LONG; - } else if (columnType.equals("float")) { - type = FLOAT; - } else if (columnType.equals("double")) { - type = DOUBLE; - } else if (columnType.equals("category")) { - type = CATEGORY; - } else { - throw new IllegalArgumentException("'" + columnType + "' is not a valid column type."); - } - return type; - } - - - /** - * Set the data type for a column so that using it is more efficient. - * @param column the column to change - * @param columnType One of int, long, float, double, string, or category. - */ - public void setColumnType(int column, String columnType) { - setColumnType(column, parseColumnType(columnType)); - } - - - public void setColumnType(String columnName, int newType) { - setColumnType(checkColumnIndex(columnName), newType); - } - - - /** - * Sets the column type. If data already exists, then it'll be converted to - * the new type. - * @param column the column whose type should be changed - * @param newType something fresh, maybe try an int or a float for size? - */ - public void setColumnType(int column, int newType) { - switch (newType) { - case INT: { - int[] intData = new int[rowCount]; - for (int row = 0; row < rowCount; row++) { - String s = getString(row, column); - intData[row] = (s == null) ? missingInt : PApplet.parseInt(s, missingInt); - } - columns[column] = intData; - break; - } - case LONG: { - long[] longData = new long[rowCount]; - for (int row = 0; row < rowCount; row++) { - String s = getString(row, column); - try { - longData[row] = (s == null) ? missingLong : Long.parseLong(s); - } catch (NumberFormatException nfe) { - longData[row] = missingLong; - } - } - columns[column] = longData; - break; - } - case FLOAT: { - float[] floatData = new float[rowCount]; - for (int row = 0; row < rowCount; row++) { - String s = getString(row, column); - floatData[row] = (s == null) ? missingFloat : PApplet.parseFloat(s, missingFloat); - } - columns[column] = floatData; - break; - } - case DOUBLE: { - double[] doubleData = new double[rowCount]; - for (int row = 0; row < rowCount; row++) { - String s = getString(row, column); - try { - doubleData[row] = (s == null) ? missingDouble : Double.parseDouble(s); - } catch (NumberFormatException nfe) { - doubleData[row] = missingDouble; - } - } - columns[column] = doubleData; - break; - } - case STRING: { - if (columnTypes[column] != STRING) { - String[] stringData = new String[rowCount]; - for (int row = 0; row < rowCount; row++) { - stringData[row] = getString(row, column); - } - columns[column] = stringData; - } - break; - } - case CATEGORY: { - int[] indexData = new int[rowCount]; - HashMapBlows categories = new HashMapBlows(); - for (int row = 0; row < rowCount; row++) { - String s = getString(row, column); - indexData[row] = categories.index(s); - } - columnCategories[column] = categories; - columns[column] = indexData; - break; - } - default: { - throw new IllegalArgumentException("That's not a valid column type."); - } - } -// System.out.println("new type is " + newType); - columnTypes[column] = newType; - } - - - /** - * Set the entire table to a specific data type. - */ - public void setTableType(String type) { - for (int col = 0; col < getColumnCount(); col++) { - setColumnType(col, type); - } - } - - - public void setColumnTypes(int[] types) { - ensureColumn(types.length - 1); - for (int col = 0; col < types.length; col++) { - setColumnType(col, types[col]); - } - } - - - /** - * Set the titles (and if a second column is present) the data types for - * this table based on a file loaded separately. This will look for the - * title in column 0, and the type in column 1. Better yet, specify a - * column named "title" and another named "type" in the dictionary table - * to future-proof the code. - * @param dictionary - */ - public void setColumnTypes(final Table dictionary) { - ensureColumn(dictionary.getRowCount() - 1); - int titleCol = 0; - int typeCol = 1; - if (dictionary.hasColumnTitles()) { - titleCol = dictionary.getColumnIndex("title", true); - typeCol = dictionary.getColumnIndex("type", true); - } - setColumnTitles(dictionary.getStringColumn(titleCol)); - final String[] typeNames = dictionary.getStringColumn(typeCol); - - if (dictionary.getColumnCount() > 1) { - if (getRowCount() > 1000) { - int proc = Runtime.getRuntime().availableProcessors(); - ExecutorService pool = Executors.newFixedThreadPool(proc/2); - for (int i = 0; i < dictionary.getRowCount(); i++) { - final int col = i; - pool.execute(new Runnable() { - public void run() { - setColumnType(col, typeNames[col]); - } - }); - } - pool.shutdown(); - while (!pool.isTerminated()) { - Thread.yield(); - } - - } else { - for (int col = 0; col < dictionary.getRowCount(); col++) { -// setColumnType(i, dictionary.getString(i, typeCol)); - setColumnType(col, typeNames[col]); - } - } - } - } - - - public int getColumnType(String columnName) { - return getColumnType(getColumnIndex(columnName)); - } - - - /** Returns one of Table.STRING, Table.INT, etc... */ - public int getColumnType(int column) { - return columnTypes[column]; - } - - - public int[] getColumnTypes() { - return columnTypes; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Remove the first row from the data set, and use it as the column titles. - * Use loadTable("table.csv", "header") instead. - */ - @Deprecated - public String[] removeTitleRow() { - String[] titles = getStringRow(0); - removeRow(0); - setColumnTitles(titles); - return titles; - } - - - public void setColumnTitles(String[] titles) { - if (titles != null) { - ensureColumn(titles.length - 1); - } - columnTitles = titles; - columnIndices = null; // remove the cache - } - - - public void setColumnTitle(int column, String title) { - ensureColumn(column); - if (columnTitles == null) { - columnTitles = new String[getColumnCount()]; - } - columnTitles[column] = title; - columnIndices = null; // reset these fellas - } - - - public boolean hasColumnTitles() { - return columnTitles != null; - } - - - public String[] getColumnTitles() { - return columnTitles; - } - - - public String getColumnTitle(int col) { - return (columnTitles == null) ? null : columnTitles[col]; - } - - - public int getColumnIndex(String columnName) { - return getColumnIndex(columnName, true); - } - - - /** - * Get the index of a column. - * @param name Name of the column. - * @param report Whether to throw an exception if the column wasn't found. - * @return index of the found column, or -1 if not found. - */ - protected int getColumnIndex(String name, boolean report) { - if (columnTitles == null) { - if (report) { - throw new IllegalArgumentException("This table has no header, so no column titles are set."); - } - return -1; - } - // only create this on first get(). subsequent calls to set the title will - // also update this array, but only if it exists. - if (columnIndices == null) { - columnIndices = new HashMap<>(); - for (int col = 0; col < columns.length; col++) { - columnIndices.put(columnTitles[col], col); - } - } - Integer index = columnIndices.get(name); - if (index == null) { - if (report) { - // Throws an exception here because the name is known and therefore most useful. - // (Rather than waiting for it to fail inside, say, getInt()) - throw new IllegalArgumentException("This table has no column named '" + name + "'"); - } - return -1; - } - return index.intValue(); - } - - - /** - * Same as getColumnIndex(), but creates the column if it doesn't exist. - * Named this way to not conflict with checkColumn(), an internal function - * used to ensure that a columns exists, and also to denote that it returns - * an int for the column index. - * @param title column title - * @return index of a new or previously existing column - */ - public int checkColumnIndex(String title) { - int index = getColumnIndex(title, false); - if (index != -1) { - return index; - } - addColumn(title); - return getColumnCount() - 1; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - /** - * @webref table:method - * @brief Gets the number of rows in a table - * @see Table#getColumnCount() - */ - public int getRowCount() { - return rowCount; - } - - - public int lastRowIndex() { - return getRowCount() - 1; - } - - - /** - * @webref table:method - * @brief Removes all rows from a table - * @see Table#addRow() - * @see Table#removeRow(int) - */ - public void clearRows() { - setRowCount(0); - } - - - public void setRowCount(int newCount) { - if (newCount != rowCount) { - if (newCount > 1000000) { - System.out.print("Note: setting maximum row count to " + PApplet.nfc(newCount)); - } - long t = System.currentTimeMillis(); - for (int col = 0; col < columns.length; col++) { - switch (columnTypes[col]) { - case INT: columns[col] = PApplet.expand((int[]) columns[col], newCount); break; - case LONG: columns[col] = PApplet.expand((long[]) columns[col], newCount); break; - case FLOAT: columns[col] = PApplet.expand((float[]) columns[col], newCount); break; - case DOUBLE: columns[col] = PApplet.expand((double[]) columns[col], newCount); break; - case STRING: columns[col] = PApplet.expand((String[]) columns[col], newCount); break; - case CATEGORY: columns[col] = PApplet.expand((int[]) columns[col], newCount); break; - } - if (newCount > 1000000) { - try { - Thread.sleep(10); // gc time! - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - if (newCount > 1000000) { - int ms = (int) (System.currentTimeMillis() - t); - System.out.println(" (resize took " + PApplet.nfc(ms) + " ms)"); - } - } - rowCount = newCount; - } - - - /** - * @webref table:method - * @brief Adds a row to a table - * @see Table#removeRow(int) - * @see Table#clearRows() - */ - public TableRow addRow() { - //if (rowIncrement == 0) { - setRowCount(rowCount + 1); - return new RowPointer(this, rowCount - 1); - } - - - /** - * @param source a reference to the original row to be duplicated - */ - public TableRow addRow(TableRow source) { - return setRow(rowCount, source); - } - - - public TableRow setRow(int row, TableRow source) { - // Make sure there are enough columns to add this data - ensureBounds(row, source.getColumnCount() - 1); - - for (int col = 0; col < Math.min(source.getColumnCount(), columns.length); col++) { - switch (columnTypes[col]) { - case INT: - setInt(row, col, source.getInt(col)); - break; - case LONG: - setLong(row, col, source.getLong(col)); - break; - case FLOAT: - setFloat(row, col, source.getFloat(col)); - break; - case DOUBLE: - setDouble(row, col, source.getDouble(col)); - break; - case STRING: - setString(row, col, source.getString(col)); - break; - case CATEGORY: - int index = source.getInt(col); - setInt(row, col, index); - if (!columnCategories[col].hasCategory(index)) { - columnCategories[col].setCategory(index, source.getString(col)); - } - break; - - default: - throw new RuntimeException("no types"); - } - } - return new RowPointer(this, row); - } - - - /** - * @nowebref - */ - public TableRow addRow(Object[] columnData) { - setRow(getRowCount(), columnData); - return new RowPointer(this, rowCount - 1); - } - - - public void addRows(Table source) { - int index = getRowCount(); - setRowCount(index + source.getRowCount()); - for (TableRow row : source.rows()) { - setRow(index++, row); - } - } - - - public void insertRow(int insert, Object[] columnData) { - for (int col = 0; col < columns.length; col++) { - switch (columnTypes[col]) { - case CATEGORY: - case INT: { - int[] intTemp = new int[rowCount+1]; - System.arraycopy(columns[col], 0, intTemp, 0, insert); - System.arraycopy(columns[col], insert, intTemp, insert+1, rowCount - insert); - columns[col] = intTemp; - break; - } - case LONG: { - long[] longTemp = new long[rowCount+1]; - System.arraycopy(columns[col], 0, longTemp, 0, insert); - System.arraycopy(columns[col], insert, longTemp, insert+1, rowCount - insert); - columns[col] = longTemp; - break; - } - case FLOAT: { - float[] floatTemp = new float[rowCount+1]; - System.arraycopy(columns[col], 0, floatTemp, 0, insert); - System.arraycopy(columns[col], insert, floatTemp, insert+1, rowCount - insert); - columns[col] = floatTemp; - break; - } - case DOUBLE: { - double[] doubleTemp = new double[rowCount+1]; - System.arraycopy(columns[col], 0, doubleTemp, 0, insert); - System.arraycopy(columns[col], insert, doubleTemp, insert+1, rowCount - insert); - columns[col] = doubleTemp; - break; - } - case STRING: { - String[] stringTemp = new String[rowCount+1]; - System.arraycopy(columns[col], 0, stringTemp, 0, insert); - System.arraycopy(columns[col], insert, stringTemp, insert+1, rowCount - insert); - columns[col] = stringTemp; - break; - } - } - } - // Need to increment before setRow(), because it calls ensureBounds() - // https://github.com/processing/processing/issues/5406 - ++rowCount; - setRow(insert, columnData); - } - - - /** - * @webref table:method - * @brief Removes a row from a table - * @param row ID number of the row to remove - * @see Table#addRow() - * @see Table#clearRows() - */ - public void removeRow(int row) { - for (int col = 0; col < columns.length; col++) { - switch (columnTypes[col]) { - case CATEGORY: - case INT: { - int[] intTemp = new int[rowCount-1]; -// int[] intData = (int[]) columns[col]; -// System.arraycopy(intData, 0, intTemp, 0, dead); -// System.arraycopy(intData, dead+1, intTemp, dead, (rowCount - dead) + 1); - System.arraycopy(columns[col], 0, intTemp, 0, row); - System.arraycopy(columns[col], row+1, intTemp, row, (rowCount - row) - 1); - columns[col] = intTemp; - break; - } - case LONG: { - long[] longTemp = new long[rowCount-1]; -// long[] longData = (long[]) columns[col]; -// System.arraycopy(longData, 0, longTemp, 0, dead); -// System.arraycopy(longData, dead+1, longTemp, dead, (rowCount - dead) + 1); - System.arraycopy(columns[col], 0, longTemp, 0, row); - System.arraycopy(columns[col], row+1, longTemp, row, (rowCount - row) - 1); - columns[col] = longTemp; - break; - } - case FLOAT: { - float[] floatTemp = new float[rowCount-1]; -// float[] floatData = (float[]) columns[col]; -// System.arraycopy(floatData, 0, floatTemp, 0, dead); -// System.arraycopy(floatData, dead+1, floatTemp, dead, (rowCount - dead) + 1); - System.arraycopy(columns[col], 0, floatTemp, 0, row); - System.arraycopy(columns[col], row+1, floatTemp, row, (rowCount - row) - 1); - columns[col] = floatTemp; - break; - } - case DOUBLE: { - double[] doubleTemp = new double[rowCount-1]; -// double[] doubleData = (double[]) columns[col]; -// System.arraycopy(doubleData, 0, doubleTemp, 0, dead); -// System.arraycopy(doubleData, dead+1, doubleTemp, dead, (rowCount - dead) + 1); - System.arraycopy(columns[col], 0, doubleTemp, 0, row); - System.arraycopy(columns[col], row+1, doubleTemp, row, (rowCount - row) - 1); - columns[col] = doubleTemp; - break; - } - case STRING: { - String[] stringTemp = new String[rowCount-1]; - System.arraycopy(columns[col], 0, stringTemp, 0, row); - System.arraycopy(columns[col], row+1, stringTemp, row, (rowCount - row) - 1); - columns[col] = stringTemp; - } - } - } - rowCount--; - } - - - /* - public void setRow(int row, String[] pieces) { - checkSize(row, pieces.length - 1); - // pieces.length may be less than columns.length, so loop over pieces - for (int col = 0; col < pieces.length; col++) { - setRowCol(row, col, pieces[col]); - } - } - - - protected void setRowCol(int row, int col, String piece) { - switch (columnTypes[col]) { - case STRING: - String[] stringData = (String[]) columns[col]; - stringData[row] = piece; - break; - case INT: - int[] intData = (int[]) columns[col]; - intData[row] = PApplet.parseInt(piece, missingInt); - break; - case LONG: - long[] longData = (long[]) columns[col]; - try { - longData[row] = Long.parseLong(piece); - } catch (NumberFormatException nfe) { - longData[row] = missingLong; - } - break; - case FLOAT: - float[] floatData = (float[]) columns[col]; - floatData[row] = PApplet.parseFloat(piece, missingFloat); - break; - case DOUBLE: - double[] doubleData = (double[]) columns[col]; - try { - doubleData[row] = Double.parseDouble(piece); - } catch (NumberFormatException nfe) { - doubleData[row] = missingDouble; - } - break; - case CATEGORY: - int[] indexData = (int[]) columns[col]; - indexData[row] = columnCategories[col].index(piece); - break; - default: - throw new IllegalArgumentException("That's not a valid column type."); - } - } - */ - - - public void setRow(int row, Object[] pieces) { - ensureBounds(row, pieces.length - 1); - // pieces.length may be less than columns.length, so loop over pieces - for (int col = 0; col < pieces.length; col++) { - setRowCol(row, col, pieces[col]); - } - } - - - protected void setRowCol(int row, int col, Object piece) { - switch (columnTypes[col]) { - case STRING: - String[] stringData = (String[]) columns[col]; - if (piece == null) { - stringData[row] = null; -// } else if (piece instanceof String) { -// stringData[row] = (String) piece; - } else { - // Calls toString() on the object, which is 'return this' for String - stringData[row] = String.valueOf(piece); - } - break; - case INT: - int[] intData = (int[]) columns[col]; - //intData[row] = PApplet.parseInt(piece, missingInt); - if (piece == null) { - intData[row] = missingInt; - } else if (piece instanceof Integer) { - intData[row] = (Integer) piece; - } else { - intData[row] = PApplet.parseInt(String.valueOf(piece), missingInt); - } - break; - case LONG: - long[] longData = (long[]) columns[col]; - if (piece == null) { - longData[row] = missingLong; - } else if (piece instanceof Long) { - longData[row] = (Long) piece; - } else { - try { - longData[row] = Long.parseLong(String.valueOf(piece)); - } catch (NumberFormatException nfe) { - longData[row] = missingLong; - } - } - break; - case FLOAT: - float[] floatData = (float[]) columns[col]; - if (piece == null) { - floatData[row] = missingFloat; - } else if (piece instanceof Float) { - floatData[row] = (Float) piece; - } else { - floatData[row] = PApplet.parseFloat(String.valueOf(piece), missingFloat); - } - break; - case DOUBLE: - double[] doubleData = (double[]) columns[col]; - if (piece == null) { - doubleData[row] = missingDouble; - } else if (piece instanceof Double) { - doubleData[row] = (Double) piece; - } else { - try { - doubleData[row] = Double.parseDouble(String.valueOf(piece)); - } catch (NumberFormatException nfe) { - doubleData[row] = missingDouble; - } - } - break; - case CATEGORY: - int[] indexData = (int[]) columns[col]; - if (piece == null) { - indexData[row] = missingCategory; - } else { - String peace = String.valueOf(piece); - if (peace.equals(missingString)) { // missingString might be null - indexData[row] = missingCategory; - } else { - indexData[row] = columnCategories[col].index(peace); - } - } - break; - default: - throw new IllegalArgumentException("That's not a valid column type."); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - /** - * @webref table:method - * @brief Gets a row from a table - * @param row ID number of the row to get - * @see Table#rows() - * @see Table#findRow(String, int) - * @see Table#findRows(String, int) - * @see Table#matchRow(String, int) - * @see Table#matchRows(String, int) - */ - public TableRow getRow(int row) { - return new RowPointer(this, row); - } - - - /** - * Note that this one iterator instance is shared by any calls to iterate - * the rows of this table. This is very efficient, but not thread-safe. - * If you want to iterate in a multi-threaded manner, don't use the iterator. - * - * @webref table:method - * @brief Gets multiple rows from a table - * @see Table#getRow(int) - * @see Table#findRow(String, int) - * @see Table#findRows(String, int) - * @see Table#matchRow(String, int) - * @see Table#matchRows(String, int) - */ - public Iterable rows() { - return new Iterable() { - public Iterator iterator() { - if (rowIterator == null) { - rowIterator = new RowIterator(Table.this); - } else { - rowIterator.reset(); - } - return rowIterator; - } - }; - } - - /** - * @nowebref - */ - public Iterable rows(final int[] indices) { - return new Iterable() { - public Iterator iterator() { - return new RowIndexIterator(Table.this, indices); - } - }; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - static class RowPointer implements TableRow { - Table table; - int row; - - public RowPointer(Table table, int row) { - this.table = table; - this.row = row; - } - - public void setRow(int row) { - this.row = row; - } - - public String getString(int column) { - return table.getString(row, column); - } - - public String getString(String columnName) { - return table.getString(row, columnName); - } - - public int getInt(int column) { - return table.getInt(row, column); - } - - public int getInt(String columnName) { - return table.getInt(row, columnName); - } - - public long getLong(int column) { - return table.getLong(row, column); - } - - public long getLong(String columnName) { - return table.getLong(row, columnName); - } - - public float getFloat(int column) { - return table.getFloat(row, column); - } - - public float getFloat(String columnName) { - return table.getFloat(row, columnName); - } - - public double getDouble(int column) { - return table.getDouble(row, column); - } - - public double getDouble(String columnName) { - return table.getDouble(row, columnName); - } - - public void setString(int column, String value) { - table.setString(row, column, value); - } - - public void setString(String columnName, String value) { - table.setString(row, columnName, value); - } - - public void setInt(int column, int value) { - table.setInt(row, column, value); - } - - public void setInt(String columnName, int value) { - table.setInt(row, columnName, value); - } - - public void setLong(int column, long value) { - table.setLong(row, column, value); - } - - public void setLong(String columnName, long value) { - table.setLong(row, columnName, value); - } - - public void setFloat(int column, float value) { - table.setFloat(row, column, value); - } - - public void setFloat(String columnName, float value) { - table.setFloat(row, columnName, value); - } - - public void setDouble(int column, double value) { - table.setDouble(row, column, value); - } - - public void setDouble(String columnName, double value) { - table.setDouble(row, columnName, value); - } - - public int getColumnCount() { - return table.getColumnCount(); - } - - public int getColumnType(String columnName) { - return table.getColumnType(columnName); - } - - public int getColumnType(int column) { - return table.getColumnType(column); - } - - public int[] getColumnTypes() { - return table.getColumnTypes(); - } - - public String getColumnTitle(int column) { - return table.getColumnTitle(column); - } - - public String[] getColumnTitles() { - return table.getColumnTitles(); - } - - public void print() { - write(new PrintWriter(System.out)); - } - - public void write(PrintWriter writer) { - for (int i = 0 ; i < getColumnCount(); i++) { - if (i != 0) { - writer.print('\t'); - } - writer.print(getString(i)); - } - } - } - - - static class RowIterator implements Iterator { - Table table; - RowPointer rp; - int row; - - public RowIterator(Table table) { - this.table = table; - row = -1; - rp = new RowPointer(table, row); - } - - public void remove() { - table.removeRow(row); - } - - public TableRow next() { - rp.setRow(++row); - return rp; - } - - public boolean hasNext() { - return row+1 < table.getRowCount(); - } - - public void reset() { - row = -1; - } - } - - - static class RowIndexIterator implements Iterator { - Table table; - RowPointer rp; - int[] indices; - int index; - - public RowIndexIterator(Table table, int[] indices) { - this.table = table; - this.indices = indices; - index = -1; - // just set to something arbitrary - rp = new RowPointer(table, -1); - } - - public void remove() { - table.removeRow(indices[index]); - } - - public TableRow next() { - rp.setRow(indices[++index]); - return rp; - } - - public boolean hasNext() { - //return row+1 < table.getRowCount(); - return index + 1 < indices.length; - } - - public void reset() { - index = -1; - } - } - - - /* - static public Iterator createIterator(final ResultSet rs) { - return new Iterator() { - boolean already; - - public boolean hasNext() { - already = true; - try { - return rs.next(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - - public TableRow next() { - if (!already) { - try { - rs.next(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } else { - already = false; - } - - return new TableRow() { - public double getDouble(int column) { - try { - return rs.getDouble(column); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public double getDouble(String columnName) { - try { - return rs.getDouble(columnName); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public float getFloat(int column) { - try { - return rs.getFloat(column); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public float getFloat(String columnName) { - try { - return rs.getFloat(columnName); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public int getInt(int column) { - try { - return rs.getInt(column); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public int getInt(String columnName) { - try { - return rs.getInt(columnName); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public long getLong(int column) { - try { - return rs.getLong(column); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public long getLong(String columnName) { - try { - return rs.getLong(columnName); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public String getString(int column) { - try { - return rs.getString(column); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public String getString(String columnName) { - try { - return rs.getString(columnName); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public void setString(int column, String value) { immutable(); } - public void setString(String columnName, String value) { immutable(); } - public void setInt(int column, int value) { immutable(); } - public void setInt(String columnName, int value) { immutable(); } - public void setLong(int column, long value) { immutable(); } - public void setLong(String columnName, long value) { immutable(); } - public void setFloat(int column, float value) { immutable(); } - public void setFloat(String columnName, float value) { immutable(); } - public void setDouble(int column, double value) { immutable(); } - public void setDouble(String columnName, double value) { immutable(); } - - private void immutable() { - throw new IllegalArgumentException("This TableRow cannot be modified."); - } - - public int getColumnCount() { - try { - return rs.getMetaData().getColumnCount(); - } catch (SQLException e) { - e.printStackTrace(); - return -1; - } - } - - - public int getColumnType(String columnName) { - // unimplemented - } - - - public int getColumnType(int column) { - // unimplemented - } - - }; - } - - public void remove() { - throw new IllegalArgumentException("remove() not supported"); - } - }; - } - */ - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * @webref table:method - * @brief Get an integer value from the specified row and column - * @param row ID number of the row to reference - * @param column ID number of the column to reference - * @see Table#getFloat(int, int) - * @see Table#getString(int, int) - * @see Table#getStringColumn(String) - * @see Table#setInt(int, int, int) - * @see Table#setFloat(int, int, float) - * @see Table#setString(int, int, String) - */ - public int getInt(int row, int column) { - checkBounds(row, column); - if (columnTypes[column] == INT || - columnTypes[column] == CATEGORY) { - int[] intData = (int[]) columns[column]; - return intData[row]; - } - String str = getString(row, column); - return (str == null || str.equals(missingString)) ? - missingInt : PApplet.parseInt(str, missingInt); - } - - /** - * @param columnName title of the column to reference - */ - public int getInt(int row, String columnName) { - return getInt(row, getColumnIndex(columnName)); - } - - - public void setMissingInt(int value) { - missingInt = value; - } - - - /** - * @webref table:method - * @brief Store an integer value in the specified row and column - * @param row ID number of the target row - * @param column ID number of the target column - * @param value value to assign - * @see Table#setFloat(int, int, float) - * @see Table#setString(int, int, String) - * @see Table#getInt(int, int) - * @see Table#getFloat(int, int) - * @see Table#getString(int, int) - * @see Table#getStringColumn(String) - */ - public void setInt(int row, int column, int value) { - if (columnTypes[column] == STRING) { - setString(row, column, String.valueOf(value)); - - } else { - ensureBounds(row, column); - if (columnTypes[column] != INT && - columnTypes[column] != CATEGORY) { - throw new IllegalArgumentException("Column " + column + " is not an int column."); - } - int[] intData = (int[]) columns[column]; - intData[row] = value; - } - } - - /** - * @param columnName title of the target column - */ - public void setInt(int row, String columnName, int value) { - setInt(row, getColumnIndex(columnName), value); - } - - - - public int[] getIntColumn(String name) { - int col = getColumnIndex(name); - return (col == -1) ? null : getIntColumn(col); - } - - - public int[] getIntColumn(int col) { - int[] outgoing = new int[rowCount]; - for (int row = 0; row < rowCount; row++) { - outgoing[row] = getInt(row, col); - } - return outgoing; - } - - - public int[] getIntRow(int row) { - int[] outgoing = new int[columns.length]; - for (int col = 0; col < columns.length; col++) { - outgoing[col] = getInt(row, col); - } - return outgoing; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public long getLong(int row, int column) { - checkBounds(row, column); - if (columnTypes[column] == LONG) { - long[] longData = (long[]) columns[column]; - return longData[row]; - } - String str = getString(row, column); - if (str == null || str.equals(missingString)) { - return missingLong; - } - try { - return Long.parseLong(str); - } catch (NumberFormatException nfe) { - return missingLong; - } - } - - - public long getLong(int row, String columnName) { - return getLong(row, getColumnIndex(columnName)); - } - - - public void setMissingLong(long value) { - missingLong = value; - } - - - public void setLong(int row, int column, long value) { - if (columnTypes[column] == STRING) { - setString(row, column, String.valueOf(value)); - - } else { - ensureBounds(row, column); - if (columnTypes[column] != LONG) { - throw new IllegalArgumentException("Column " + column + " is not a 'long' column."); - } - long[] longData = (long[]) columns[column]; - longData[row] = value; - } - } - - - public void setLong(int row, String columnName, long value) { - setLong(row, getColumnIndex(columnName), value); - } - - - public long[] getLongColumn(String name) { - int col = getColumnIndex(name); - return (col == -1) ? null : getLongColumn(col); - } - - - public long[] getLongColumn(int col) { - long[] outgoing = new long[rowCount]; - for (int row = 0; row < rowCount; row++) { - outgoing[row] = getLong(row, col); - } - return outgoing; - } - - - public long[] getLongRow(int row) { - long[] outgoing = new long[columns.length]; - for (int col = 0; col < columns.length; col++) { - outgoing[col] = getLong(row, col); - } - return outgoing; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Get a float value from the specified row and column. If the value is null - * or not parseable as a float, the "missing" value is returned. By default, - * this is Float.NaN, but can be controlled with setMissingFloat(). - * - * @webref table:method - * @brief Get a float value from the specified row and column - * @param row ID number of the row to reference - * @param column ID number of the column to reference - * @see Table#getInt(int, int) - * @see Table#getString(int, int) - * @see Table#getStringColumn(String) - * @see Table#setInt(int, int, int) - * @see Table#setFloat(int, int, float) - * @see Table#setString(int, int, String) - */ - public float getFloat(int row, int column) { - checkBounds(row, column); - if (columnTypes[column] == FLOAT) { - float[] floatData = (float[]) columns[column]; - return floatData[row]; - } - String str = getString(row, column); - if (str == null || str.equals(missingString)) { - return missingFloat; - } - return PApplet.parseFloat(str, missingFloat); - } - - /** - * @param columnName title of the column to reference - */ - public float getFloat(int row, String columnName) { - return getFloat(row, getColumnIndex(columnName)); - } - - - public void setMissingFloat(float value) { - missingFloat = value; - } - - - /** - * @webref table:method - * @brief Store a float value in the specified row and column - * @param row ID number of the target row - * @param column ID number of the target column - * @param value value to assign - * @see Table#setInt(int, int, int) - * @see Table#setString(int, int, String) - * @see Table#getInt(int, int) - * @see Table#getFloat(int, int) - * @see Table#getString(int, int) - * @see Table#getStringColumn(String) - */ - public void setFloat(int row, int column, float value) { - if (columnTypes[column] == STRING) { - setString(row, column, String.valueOf(value)); - - } else { - ensureBounds(row, column); - if (columnTypes[column] != FLOAT) { - throw new IllegalArgumentException("Column " + column + " is not a float column."); - } - float[] longData = (float[]) columns[column]; - longData[row] = value; - } - } - - /** - * @param columnName title of the target column - */ - public void setFloat(int row, String columnName, float value) { - setFloat(row, getColumnIndex(columnName), value); - } - - - public float[] getFloatColumn(String name) { - int col = getColumnIndex(name); - return (col == -1) ? null : getFloatColumn(col); - } - - - public float[] getFloatColumn(int col) { - float[] outgoing = new float[rowCount]; - for (int row = 0; row < rowCount; row++) { - outgoing[row] = getFloat(row, col); - } - return outgoing; - } - - - public float[] getFloatRow(int row) { - float[] outgoing = new float[columns.length]; - for (int col = 0; col < columns.length; col++) { - outgoing[col] = getFloat(row, col); - } - return outgoing; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public double getDouble(int row, int column) { - checkBounds(row, column); - if (columnTypes[column] == DOUBLE) { - double[] doubleData = (double[]) columns[column]; - return doubleData[row]; - } - String str = getString(row, column); - if (str == null || str.equals(missingString)) { - return missingDouble; - } - try { - return Double.parseDouble(str); - } catch (NumberFormatException nfe) { - return missingDouble; - } - } - - - public double getDouble(int row, String columnName) { - return getDouble(row, getColumnIndex(columnName)); - } - - - public void setMissingDouble(double value) { - missingDouble = value; - } - - - public void setDouble(int row, int column, double value) { - if (columnTypes[column] == STRING) { - setString(row, column, String.valueOf(value)); - - } else { - ensureBounds(row, column); - if (columnTypes[column] != DOUBLE) { - throw new IllegalArgumentException("Column " + column + " is not a 'double' column."); - } - double[] doubleData = (double[]) columns[column]; - doubleData[row] = value; - } - } - - - public void setDouble(int row, String columnName, double value) { - setDouble(row, getColumnIndex(columnName), value); - } - - - public double[] getDoubleColumn(String name) { - int col = getColumnIndex(name); - return (col == -1) ? null : getDoubleColumn(col); - } - - - public double[] getDoubleColumn(int col) { - double[] outgoing = new double[rowCount]; - for (int row = 0; row < rowCount; row++) { - outgoing[row] = getDouble(row, col); - } - return outgoing; - } - - - public double[] getDoubleRow(int row) { - double[] outgoing = new double[columns.length]; - for (int col = 0; col < columns.length; col++) { - outgoing[col] = getDouble(row, col); - } - return outgoing; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - -//public long getTimestamp(String rowName, int column) { -//return getTimestamp(getRowIndex(rowName), column); -//} - - - /** - * Returns the time in milliseconds by parsing a SQL Timestamp at this cell. - */ -// public long getTimestamp(int row, int column) { -// String str = get(row, column); -// java.sql.Timestamp timestamp = java.sql.Timestamp.valueOf(str); -// return timestamp.getTime(); -// } - - -// public long getExcelTimestamp(int row, int column) { -// return parseExcelTimestamp(get(row, column)); -// } - - -// static protected DateFormat excelDateFormat; - -// static public long parseExcelTimestamp(String timestamp) { -// if (excelDateFormat == null) { -// excelDateFormat = new SimpleDateFormat("MM/dd/yy HH:mm"); -// } -// try { -// return excelDateFormat.parse(timestamp).getTime(); -// } catch (ParseException e) { -// e.printStackTrace(); -// return -1; -// } -// } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - -// public void setObject(int row, int column, Object value) { -// if (value == null) { -// data[row][column] = null; -// } else if (value instanceof String) { -// set(row, column, (String) value); -// } else if (value instanceof Float) { -// setFloat(row, column, ((Float) value).floatValue()); -// } else if (value instanceof Integer) { -// setInt(row, column, ((Integer) value).intValue()); -// } else { -// set(row, column, value.toString()); -// } -// } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Get a String value from the table. If the row is longer than the table - * - * @webref table:method - * @brief Get an String value from the specified row and column - * @param row ID number of the row to reference - * @param column ID number of the column to reference - * @see Table#getInt(int, int) - * @see Table#getFloat(int, int) - * @see Table#getStringColumn(String) - * @see Table#setInt(int, int, int) - * @see Table#setFloat(int, int, float) - * @see Table#setString(int, int, String) - */ - public String getString(int row, int column) { - checkBounds(row, column); - if (columnTypes[column] == STRING) { - String[] stringData = (String[]) columns[column]; - return stringData[row]; - } else if (columnTypes[column] == CATEGORY) { - int cat = getInt(row, column); - if (cat == missingCategory) { - return missingString; - } - return columnCategories[column].key(cat); - } else if (columnTypes[column] == FLOAT) { - if (Float.isNaN(getFloat(row, column))) { - return null; - } - } else if (columnTypes[column] == DOUBLE) { - if (Double.isNaN(getFloat(row, column))) { - return null; - } - } - return String.valueOf(Array.get(columns[column], row)); - } - - - /** - * @param columnName title of the column to reference - */ - public String getString(int row, String columnName) { - return getString(row, getColumnIndex(columnName)); - } - - - /** - * Treat entries with this string as "missing". Also used for categorial. - */ - public void setMissingString(String value) { - missingString = value; - } - - - /** - * @webref table:method - * @brief Store a String value in the specified row and column - * @param row ID number of the target row - * @param column ID number of the target column - * @param value value to assign - * @see Table#setInt(int, int, int) - * @see Table#setFloat(int, int, float) - * @see Table#getInt(int, int) - * @see Table#getFloat(int, int) - * @see Table#getString(int, int) - * @see Table#getStringColumn(String) - */ - public void setString(int row, int column, String value) { - ensureBounds(row, column); - if (columnTypes[column] != STRING) { - throw new IllegalArgumentException("Column " + column + " is not a String column."); - } - String[] stringData = (String[]) columns[column]; - stringData[row] = value; - } - - /** - * @param columnName title of the target column - */ - public void setString(int row, String columnName, String value) { - int column = checkColumnIndex(columnName); - setString(row, column, value); - } - - /** - * @webref table:method - * @brief Gets all values in the specified column - * @param columnName title of the column to search - * @see Table#getInt(int, int) - * @see Table#getFloat(int, int) - * @see Table#getString(int, int) - * @see Table#setInt(int, int, int) - * @see Table#setFloat(int, int, float) - * @see Table#setString(int, int, String) - */ - public String[] getStringColumn(String columnName) { - int col = getColumnIndex(columnName); - return (col == -1) ? null : getStringColumn(col); - } - - - /** - * @param column ID number of the column to search - */ - public String[] getStringColumn(int column) { - String[] outgoing = new String[rowCount]; - for (int i = 0; i < rowCount; i++) { - outgoing[i] = getString(i, column); - } - return outgoing; - } - - - public String[] getStringRow(int row) { - String[] outgoing = new String[columns.length]; - for (int col = 0; col < columns.length; col++) { - outgoing[col] = getString(row, col); - } - return outgoing; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Return the row that contains the first String that matches. - * @param value the String to match - * @param column ID number of the column to search - */ - public int findRowIndex(String value, int column) { - checkColumn(column); - if (columnTypes[column] == STRING) { - String[] stringData = (String[]) columns[column]; - if (value == null) { - for (int row = 0; row < rowCount; row++) { - if (stringData[row] == null) return row; - } - } else { - for (int row = 0; row < rowCount; row++) { - if (stringData[row] != null && stringData[row].equals(value)) { - return row; - } - } - } - } else { // less efficient, includes conversion as necessary - for (int row = 0; row < rowCount; row++) { - String str = getString(row, column); - if (str == null) { - if (value == null) { - return row; - } - } else if (str.equals(value)) { - return row; - } - } - } - return -1; - } - - - /** - * Return the row that contains the first String that matches. - * @param value the String to match - * @param columnName title of the column to search - */ - public int findRowIndex(String value, String columnName) { - return findRowIndex(value, getColumnIndex(columnName)); - } - - - /** - * Return a list of rows that contain the String passed in. If there are no - * matches, a zero length array will be returned (not a null array). - * @param value the String to match - * @param column ID number of the column to search - */ - public int[] findRowIndices(String value, int column) { - int[] outgoing = new int[rowCount]; - int count = 0; - - checkColumn(column); - if (columnTypes[column] == STRING) { - String[] stringData = (String[]) columns[column]; - if (value == null) { - for (int row = 0; row < rowCount; row++) { - if (stringData[row] == null) { - outgoing[count++] = row; - } - } - } else { - for (int row = 0; row < rowCount; row++) { - if (stringData[row] != null && stringData[row].equals(value)) { - outgoing[count++] = row; - } - } - } - } else { // less efficient, includes conversion as necessary - for (int row = 0; row < rowCount; row++) { - String str = getString(row, column); - if (str == null) { - if (value == null) { - outgoing[count++] = row; - } - } else if (str.equals(value)) { - outgoing[count++] = row; - } - } - } - return PApplet.subset(outgoing, 0, count); - } - - - /** - * Return a list of rows that contain the String passed in. If there are no - * matches, a zero length array will be returned (not a null array). - * @param value the String to match - * @param columnName title of the column to search - */ - public int[] findRowIndices(String value, String columnName) { - return findRowIndices(value, getColumnIndex(columnName)); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - /** - * @webref table:method - * @brief Finds a row that contains the given value - * @param value the value to match - * @param column ID number of the column to search - * @see Table#getRow(int) - * @see Table#rows() - * @see Table#findRows(String, int) - * @see Table#matchRow(String, int) - * @see Table#matchRows(String, int) - */ - public TableRow findRow(String value, int column) { - int row = findRowIndex(value, column); - return (row == -1) ? null : new RowPointer(this, row); - } - - - /** - * @param columnName title of the column to search - */ - public TableRow findRow(String value, String columnName) { - return findRow(value, getColumnIndex(columnName)); - } - - - /** - * @webref table:method - * @brief Finds multiple rows that contain the given value - * @param value the value to match - * @param column ID number of the column to search - * @see Table#getRow(int) - * @see Table#rows() - * @see Table#findRow(String, int) - * @see Table#matchRow(String, int) - * @see Table#matchRows(String, int) - */ - public Iterable findRows(final String value, final int column) { - return new Iterable() { - public Iterator iterator() { - return findRowIterator(value, column); - } - }; - } - - - /** - * @param columnName title of the column to search - */ - public Iterable findRows(final String value, final String columnName) { - return findRows(value, getColumnIndex(columnName)); - } - - - /** - * @brief Finds multiple rows that contain the given value - * @param value the value to match - * @param column ID number of the column to search - */ - public Iterator findRowIterator(String value, int column) { - return new RowIndexIterator(this, findRowIndices(value, column)); - } - - - /** - * @param columnName title of the column to search - */ - public Iterator findRowIterator(String value, String columnName) { - return findRowIterator(value, getColumnIndex(columnName)); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Return the row that contains the first String that matches. - * @param regexp the String to match - * @param column ID number of the column to search - */ - public int matchRowIndex(String regexp, int column) { - checkColumn(column); - if (columnTypes[column] == STRING) { - String[] stringData = (String[]) columns[column]; - for (int row = 0; row < rowCount; row++) { - if (stringData[row] != null && - PApplet.match(stringData[row], regexp) != null) { - return row; - } - } - } else { // less efficient, includes conversion as necessary - for (int row = 0; row < rowCount; row++) { - String str = getString(row, column); - if (str != null && - PApplet.match(str, regexp) != null) { - return row; - } - } - } - return -1; - } - - - /** - * Return the row that contains the first String that matches. - * @param what the String to match - * @param columnName title of the column to search - */ - public int matchRowIndex(String what, String columnName) { - return matchRowIndex(what, getColumnIndex(columnName)); - } - - - /** - * Return a list of rows that contain the String passed in. If there are no - * matches, a zero length array will be returned (not a null array). - * @param regexp the String to match - * @param column ID number of the column to search - */ - public int[] matchRowIndices(String regexp, int column) { - int[] outgoing = new int[rowCount]; - int count = 0; - - checkColumn(column); - if (columnTypes[column] == STRING) { - String[] stringData = (String[]) columns[column]; - for (int row = 0; row < rowCount; row++) { - if (stringData[row] != null && - PApplet.match(stringData[row], regexp) != null) { - outgoing[count++] = row; - } - } - } else { // less efficient, includes conversion as necessary - for (int row = 0; row < rowCount; row++) { - String str = getString(row, column); - if (str != null && - PApplet.match(str, regexp) != null) { - outgoing[count++] = row; - } - } - } - return PApplet.subset(outgoing, 0, count); - } - - - /** - * Return a list of rows that match the regex passed in. If there are no - * matches, a zero length array will be returned (not a null array). - * @param what the String to match - * @param columnName title of the column to search - */ - public int[] matchRowIndices(String what, String columnName) { - return matchRowIndices(what, getColumnIndex(columnName)); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - /** - * @webref table:method - * @brief Finds a row that matches the given expression - * @param regexp the regular expression to match - * @param column ID number of the column to search - * @see Table#getRow(int) - * @see Table#rows() - * @see Table#findRow(String, int) - * @see Table#findRows(String, int) - * @see Table#matchRows(String, int) - */ - public TableRow matchRow(String regexp, int column) { - int row = matchRowIndex(regexp, column); - return (row == -1) ? null : new RowPointer(this, row); - } - - - /** - * @param columnName title of the column to search - */ - public TableRow matchRow(String regexp, String columnName) { - return matchRow(regexp, getColumnIndex(columnName)); - } - - - /** - * @webref table:method - * @brief Finds multiple rows that match the given expression - * @param regexp the regular expression to match - * @param column ID number of the column to search - * @see Table#getRow(int) - * @see Table#rows() - * @see Table#findRow(String, int) - * @see Table#findRows(String, int) - * @see Table#matchRow(String, int) - */ - public Iterable matchRows(final String regexp, final int column) { - return new Iterable() { - public Iterator iterator() { - return matchRowIterator(regexp, column); - } - }; - } - - - /** - * @param columnName title of the column to search - */ - public Iterable matchRows(String regexp, String columnName) { - return matchRows(regexp, getColumnIndex(columnName)); - } - - - /** - * @webref table:method - * @brief Finds multiple rows that match the given expression - * @param value the regular expression to match - * @param column ID number of the column to search - */ - public Iterator matchRowIterator(String value, int column) { - return new RowIndexIterator(this, matchRowIndices(value, column)); - } - - - /** - * @param columnName title of the column to search - */ - public Iterator matchRowIterator(String value, String columnName) { - return matchRowIterator(value, getColumnIndex(columnName)); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Replace a String with another. Set empty entries null by using - * replace("", null) or use replace(null, "") to go the other direction. - * If this is a typed table, only String columns will be modified. - * @param orig - * @param replacement - */ - public void replace(String orig, String replacement) { - for (int col = 0; col < columns.length; col++) { - replace(orig, replacement, col); - } - } - - - public void replace(String orig, String replacement, int col) { - if (columnTypes[col] == STRING) { - String[] stringData = (String[]) columns[col]; - - if (orig != null) { - for (int row = 0; row < rowCount; row++) { - if (orig.equals(stringData[row])) { - stringData[row] = replacement; - } - } - } else { // null is a special case (and faster anyway) - for (int row = 0; row < rowCount; row++) { - if (stringData[row] == null) { - stringData[row] = replacement; - } - } - } - } - } - - - public void replace(String orig, String replacement, String colName) { - replace(orig, replacement, getColumnIndex(colName)); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public void replaceAll(String regex, String replacement) { - for (int col = 0; col < columns.length; col++) { - replaceAll(regex, replacement, col); - } - } - - - public void replaceAll(String regex, String replacement, int column) { - checkColumn(column); - if (columnTypes[column] == STRING) { - String[] stringData = (String[]) columns[column]; - for (int row = 0; row < rowCount; row++) { - if (stringData[row] != null) { - stringData[row] = stringData[row].replaceAll(regex, replacement); - } - } - } else { - throw new IllegalArgumentException("replaceAll() can only be used on String columns"); - } - } - - - /** - * Run String.replaceAll() on all entries in a column. - * Only works with columns that are already String values. - * @param regex the String to match - * @param columnName title of the column to search - */ - public void replaceAll(String regex, String replacement, String columnName) { - replaceAll(regex, replacement, getColumnIndex(columnName)); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Remove any of the specified characters from the entire table. - * - * @webref table:method - * @brief Removes characters from the table - * @param tokens a list of individual characters to be removed - * @see Table#trim() - */ - public void removeTokens(String tokens) { - for (int col = 0; col < getColumnCount(); col++) { - removeTokens(tokens, col); - } - } - - - /** - * Removed any of the specified characters from a column. For instance, - * the following code removes dollar signs and commas from column 2: - *

    -   * table.removeTokens(",$", 2);
    -   * 
    - * - * @param column ID number of the column to process - */ - public void removeTokens(String tokens, int column) { - for (int row = 0; row < rowCount; row++) { - String s = getString(row, column); - if (s != null) { - char[] c = s.toCharArray(); - int index = 0; - for (int j = 0; j < c.length; j++) { - if (tokens.indexOf(c[j]) == -1) { - if (index != j) { - c[index] = c[j]; - } - index++; - } - } - if (index != c.length) { - setString(row, column, new String(c, 0, index)); - } - } - } - } - - /** - * @param columnName title of the column to process - */ - public void removeTokens(String tokens, String columnName) { - removeTokens(tokens, getColumnIndex(columnName)); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * @webref table:method - * @brief Trims whitespace from values - * @see Table#removeTokens(String) - */ - public void trim() { - columnTitles = PApplet.trim(columnTitles); - for (int col = 0; col < getColumnCount(); col++) { - trim(col); - } - // remove empty columns - int lastColumn = getColumnCount() - 1; - //while (isEmptyColumn(lastColumn) && lastColumn >= 0) { - while (isEmptyArray(getStringColumn(lastColumn)) && lastColumn >= 0) { - lastColumn--; - } - setColumnCount(lastColumn + 1); - - // trim() works from both sides - while (getColumnCount() > 0 && isEmptyArray(getStringColumn(0))) { - removeColumn(0); - } - - // remove empty rows (starting from the end) - int lastRow = lastRowIndex(); - //while (isEmptyRow(lastRow) && lastRow >= 0) { - while (isEmptyArray(getStringRow(lastRow)) && lastRow >= 0) { - lastRow--; - } - setRowCount(lastRow + 1); - - while (getRowCount() > 0 && isEmptyArray(getStringRow(0))) { - removeRow(0); - } - } - - - protected boolean isEmptyArray(String[] contents) { - for (String entry : contents) { - if (entry != null && entry.length() > 0) { - return false; - } - } - return true; - } - - - /* - protected boolean isEmptyColumn(int column) { - String[] contents = getStringColumn(column); - for (String entry : contents) { - if (entry != null && entry.length() > 0) { - return false; - } - } - return true; - } - - - protected boolean isEmptyRow(int row) { - String[] contents = getStringRow(row); - for (String entry : contents) { - if (entry != null && entry.length() > 0) { - return false; - } - } - return true; - } - */ - - - /** - * @param column ID number of the column to trim - */ - public void trim(int column) { - if (columnTypes[column] == STRING) { - String[] stringData = (String[]) columns[column]; - for (int row = 0; row < rowCount; row++) { - if (stringData[row] != null) { - stringData[row] = PApplet.trim(stringData[row]); - } - } - } - } - - /** - * @param columnName title of the column to trim - */ - public void trim(String columnName) { - trim(getColumnIndex(columnName)); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** Make sure this is a legit column, and if not, expand the table. */ - protected void ensureColumn(int col) { - if (col >= columns.length) { - setColumnCount(col + 1); - } - } - - - /** Make sure this is a legit row, and if not, expand the table. */ - protected void ensureRow(int row) { - if (row >= rowCount) { - setRowCount(row + 1); - } - } - - - /** Make sure this is a legit row and column. If not, expand the table. */ - protected void ensureBounds(int row, int col) { - ensureRow(row); - ensureColumn(col); - } - - - /** Throw an error if this row doesn't exist. */ - protected void checkRow(int row) { - if (row < 0 || row >= rowCount) { - throw new ArrayIndexOutOfBoundsException("Row " + row + " does not exist."); - } - } - - - /** Throw an error if this column doesn't exist. */ - protected void checkColumn(int column) { - if (column < 0 || column >= columns.length) { - throw new ArrayIndexOutOfBoundsException("Column " + column + " does not exist."); - } - } - - - /** Throw an error if this entry is out of bounds. */ - protected void checkBounds(int row, int column) { - checkRow(row); - checkColumn(column); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - static class HashMapBlows { - HashMap dataToIndex = new HashMap<>(); - ArrayList indexToData = new ArrayList<>(); - - HashMapBlows() { } - - HashMapBlows(DataInputStream input) throws IOException { - read(input); - } - - /** gets the index, and creates one if it doesn't already exist. */ - int index(String key) { - Integer value = dataToIndex.get(key); - if (value != null) { - return value; - } - - int v = dataToIndex.size(); - dataToIndex.put(key, v); - indexToData.add(key); - return v; - } - - String key(int index) { - return indexToData.get(index); - } - - boolean hasCategory(int index) { - return index < size() && indexToData.get(index) != null; - } - - void setCategory(int index, String name) { - while (indexToData.size() <= index) { - indexToData.add(null); - } - indexToData.set(index, name); - dataToIndex.put(name, index); - } - - int size() { - return dataToIndex.size(); - } - - void write(DataOutputStream output) throws IOException { - output.writeInt(size()); - for (String str : indexToData) { - output.writeUTF(str); - } - } - - private void writeln(PrintWriter writer) throws IOException { - for (String str : indexToData) { - writer.println(str); - } - writer.flush(); - writer.close(); - } - - void read(DataInputStream input) throws IOException { - int count = input.readInt(); - //System.out.println("found " + count + " entries in category map"); - dataToIndex = new HashMap<>(count); - for (int i = 0; i < count; i++) { - String str = input.readUTF(); - //System.out.println(i + " " + str); - dataToIndex.put(str, i); - indexToData.add(str); - } - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - -// class HashMapSucks extends HashMap { -// -// void increment(String what) { -// Integer value = get(what); -// if (value == null) { -// put(what, 1); -// } else { -// put(what, value + 1); -// } -// } -// -// void check(String what) { -// if (get(what) == null) { -// put(what, 0); -// } -// } -// } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - /** - * Sorts (orders) a table based on the values in a column. - * - * @webref table:method - * @brief Orders a table based on the values in a column - * @param columnName the name of the column to sort - * @see Table#trim() - */ - public void sort(String columnName) { - sort(getColumnIndex(columnName), false); - } - - /** - * @param column the column ID, e.g. 0, 1, 2 - */ - public void sort(int column) { - sort(column, false); - } - - - public void sortReverse(String columnName) { - sort(getColumnIndex(columnName), true); - } - - - public void sortReverse(int column) { - sort(column, true); - } - - - protected void sort(final int column, final boolean reverse) { - final int[] order = IntList.fromRange(getRowCount()).array(); - Sort s = new Sort() { - - @Override - public int size() { - return getRowCount(); - } - - @Override - public int compare(int index1, int index2) { - int a = reverse ? order[index2] : order[index1]; - int b = reverse ? order[index1] : order[index2]; - - switch (getColumnType(column)) { - case INT: - return getInt(a, column) - getInt(b, column); - case LONG: - long diffl = getLong(a, column) - getLong(b, column); - return diffl == 0 ? 0 : (diffl < 0 ? -1 : 1); - case FLOAT: - float difff = getFloat(a, column) - getFloat(b, column); - return difff == 0 ? 0 : (difff < 0 ? -1 : 1); - case DOUBLE: - double diffd = getDouble(a, column) - getDouble(b, column); - return diffd == 0 ? 0 : (diffd < 0 ? -1 : 1); - case STRING: - String string1 = getString(a, column); - if (string1 == null) { - string1 = ""; // avoid NPE when cells are left empty - } - String string2 = getString(b, column); - if (string2 == null) { - string2 = ""; - } - return string1.compareToIgnoreCase(string2); - case CATEGORY: - return getInt(a, column) - getInt(b, column); - default: - throw new IllegalArgumentException("Invalid column type: " + getColumnType(column)); - } - } - - @Override - public void swap(int a, int b) { - int temp = order[a]; - order[a] = order[b]; - order[b] = temp; - } - - }; - s.run(); - - //Object[] newColumns = new Object[getColumnCount()]; - for (int col = 0; col < getColumnCount(); col++) { - switch (getColumnType(col)) { - case INT: - case CATEGORY: - int[] oldInt = (int[]) columns[col]; - int[] newInt = new int[rowCount]; - for (int row = 0; row < getRowCount(); row++) { - newInt[row] = oldInt[order[row]]; - } - columns[col] = newInt; - break; - case LONG: - long[] oldLong = (long[]) columns[col]; - long[] newLong = new long[rowCount]; - for (int row = 0; row < getRowCount(); row++) { - newLong[row] = oldLong[order[row]]; - } - columns[col] = newLong; - break; - case FLOAT: - float[] oldFloat = (float[]) columns[col]; - float[] newFloat = new float[rowCount]; - for (int row = 0; row < getRowCount(); row++) { - newFloat[row] = oldFloat[order[row]]; - } - columns[col] = newFloat; - break; - case DOUBLE: - double[] oldDouble = (double[]) columns[col]; - double[] newDouble = new double[rowCount]; - for (int row = 0; row < getRowCount(); row++) { - newDouble[row] = oldDouble[order[row]]; - } - columns[col] = newDouble; - break; - case STRING: - String[] oldString = (String[]) columns[col]; - String[] newString = new String[rowCount]; - for (int row = 0; row < getRowCount(); row++) { - newString[row] = oldString[order[row]]; - } - columns[col] = newString; - break; - } - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public String[] getUnique(String columnName) { - return getUnique(getColumnIndex(columnName)); - } - - - public String[] getUnique(int column) { - StringList list = new StringList(getStringColumn(column)); - return list.getUnique(); - } - - - public IntDict getTally(String columnName) { - return getTally(getColumnIndex(columnName)); - } - - - public IntDict getTally(int column) { - StringList list = new StringList(getStringColumn(column)); - return list.getTally(); - } - - - public IntDict getOrder(String columnName) { - return getOrder(getColumnIndex(columnName)); - } - - - public IntDict getOrder(int column) { - StringList list = new StringList(getStringColumn(column)); - return list.getOrder(); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public IntList getIntList(String columnName) { - return new IntList(getIntColumn(columnName)); - } - - - public IntList getIntList(int column) { - return new IntList(getIntColumn(column)); - } - - - public FloatList getFloatList(String columnName) { - return new FloatList(getFloatColumn(columnName)); - } - - - public FloatList getFloatList(int column) { - return new FloatList(getFloatColumn(column)); - } - - - public StringList getStringList(String columnName) { - return new StringList(getStringColumn(columnName)); - } - - - public StringList getStringList(int column) { - return new StringList(getStringColumn(column)); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public IntDict getIntDict(String keyColumnName, String valueColumnName) { - return new IntDict(getStringColumn(keyColumnName), - getIntColumn(valueColumnName)); - } - - - public IntDict getIntDict(int keyColumn, int valueColumn) { - return new IntDict(getStringColumn(keyColumn), - getIntColumn(valueColumn)); - } - - - public FloatDict getFloatDict(String keyColumnName, String valueColumnName) { - return new FloatDict(getStringColumn(keyColumnName), - getFloatColumn(valueColumnName)); - } - - - public FloatDict getFloatDict(int keyColumn, int valueColumn) { - return new FloatDict(getStringColumn(keyColumn), - getFloatColumn(valueColumn)); - } - - - public StringDict getStringDict(String keyColumnName, String valueColumnName) { - return new StringDict(getStringColumn(keyColumnName), - getStringColumn(valueColumnName)); - } - - - public StringDict getStringDict(int keyColumn, int valueColumn) { - return new StringDict(getStringColumn(keyColumn), - getStringColumn(valueColumn)); - } - - - public Map getRowMap(String columnName) { - int col = getColumnIndex(columnName); - return (col == -1) ? null : getRowMap(col); - } - - - /** - * Return a mapping that connects the entry from a column back to the row - * from which it came. For instance: - *
    -   * Table t = loadTable("country-data.tsv", "header");
    -   * // use the contents of the 'country' column to index the table
    -   * Map lookup = t.getRowMap("country");
    -   * // get the row that has "us" in the "country" column:
    -   * TableRow usRow = lookup.get("us");
    -   * // get an entry from the 'population' column
    -   * int population = usRow.getInt("population");
    -   * 
    - */ - public Map getRowMap(int column) { - Map outgoing = new HashMap<>(); - for (int row = 0; row < getRowCount(); row++) { - String id = getString(row, column); - outgoing.put(id, new RowPointer(this, row)); - } -// for (TableRow row : rows()) { -// String id = row.getString(column); -// outgoing.put(id, row); -// } - return outgoing; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - -// /** -// * Return an object that maps the String values in one column back to the -// * row from which they came. For instance, if the "name" of each row is -// * found in the first column, getColumnRowLookup(0) would return an object -// * that would map each name back to its row. -// */ -// protected HashMap getRowLookup(int col) { -// HashMap outgoing = new HashMap(); -// for (int row = 0; row < getRowCount(); row++) { -// outgoing.put(getString(row, col), row); -// } -// return outgoing; -// } - - - // incomplete, basically this is silly to write all this repetitive code when - // it can be implemented in ~3 lines of code... -// /** -// * Return an object that maps the data from one column to the data of found -// * in another column. -// */ -// public HashMap getLookup(int col1, int col2) { -// HashMap outgoing = null; -// -// switch (columnTypes[col1]) { -// case INT: { -// if (columnTypes[col2] == INT) { -// outgoing = new HashMap(); -// for (int row = 0; row < getRowCount(); row++) { -// outgoing.put(getInt(row, col1), getInt(row, col2)); -// } -// } else if (columnTypes[col2] == LONG) { -// outgoing = new HashMap(); -// for (int row = 0; row < getRowCount(); row++) { -// outgoing.put(getInt(row, col1), getLong(row, col2)); -// } -// } else if (columnTypes[col2] == FLOAT) { -// outgoing = new HashMap(); -// for (int row = 0; row < getRowCount(); row++) { -// outgoing.put(getInt(row, col1), getFloat(row, col2)); -// } -// } else if (columnTypes[col2] == DOUBLE) { -// outgoing = new HashMap(); -// for (int row = 0; row < getRowCount(); row++) { -// outgoing.put(getInt(row, col1), getDouble(row, col2)); -// } -// } else if (columnTypes[col2] == STRING) { -// outgoing = new HashMap(); -// for (int row = 0; row < getRowCount(); row++) { -// outgoing.put(getInt(row, col1), get(row, col2)); -// } -// } -// break; -// } -// } -// return outgoing; -// } - - - // public StringIntPairs getColumnRowLookup(int col) { -// StringIntPairs sc = new StringIntPairs(); -// String[] column = getStringColumn(col); -// for (int i = 0; i < column.length; i++) { -// sc.set(column[i], i); -// } -// return sc; -// } - - -// public String[] getUniqueEntries(int column) { -//// HashMap indices = new HashMap(); -//// for (int row = 0; row < rowCount; row++) { -//// indices.put(data[row][column], this); // 'this' is a dummy -//// } -// StringIntPairs sc = getStringCount(column); -// return sc.keys(); -// } -// -// -// public StringIntPairs getStringCount(String columnName) { -// return getStringCount(getColumnIndex(columnName)); -// } -// -// -// public StringIntPairs getStringCount(int column) { -// StringIntPairs outgoing = new StringIntPairs(); -// for (int row = 0; row < rowCount; row++) { -// String entry = data[row][column]; -// if (entry != null) { -// outgoing.increment(entry); -// } -// } -// return outgoing; -// } -// -// -// /** -// * Return an object that maps the String values in one column back to the -// * row from which they came. For instance, if the "name" of each row is -// * found in the first column, getColumnRowLookup(0) would return an object -// * that would map each name back to its row. -// */ -// public StringIntPairs getColumnRowLookup(int col) { -// StringIntPairs sc = new StringIntPairs(); -// String[] column = getStringColumn(col); -// for (int i = 0; i < column.length; i++) { -// sc.set(column[i], i); -// } -// return sc; -// } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - // TODO naming/whether to include - protected Table createSubset(int[] rowSubset) { - Table newbie = new Table(); - newbie.setColumnTitles(columnTitles); // also sets columns.length - newbie.columnTypes = columnTypes; - newbie.setRowCount(rowSubset.length); - - for (int i = 0; i < rowSubset.length; i++) { - int row = rowSubset[i]; - for (int col = 0; col < columns.length; col++) { - switch (columnTypes[col]) { - case STRING: newbie.setString(i, col, getString(row, col)); break; - case INT: newbie.setInt(i, col, getInt(row, col)); break; - case LONG: newbie.setLong(i, col, getLong(row, col)); break; - case FLOAT: newbie.setFloat(i, col, getFloat(row, col)); break; - case DOUBLE: newbie.setDouble(i, col, getDouble(row, col)); break; - } - } - } - return newbie; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Searches the entire table for float values. - * Returns missing float (Float.NaN by default) if no valid numbers found. - */ - protected float getMaxFloat() { - boolean found = false; - float max = PConstants.MIN_FLOAT; - for (int row = 0; row < getRowCount(); row++) { - for (int col = 0; col < getColumnCount(); col++) { - float value = getFloat(row, col); - if (!Float.isNaN(value)) { // TODO no, this should be comparing to the missing value - if (!found) { - max = value; - found = true; - } else if (value > max) { - max = value; - } - } - } - } - return found ? max : missingFloat; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - // converts a TSV or CSV file to binary.. do not use - protected void convertBasic(BufferedReader reader, boolean tsv, - File outputFile) throws IOException { - FileOutputStream fos = new FileOutputStream(outputFile); - BufferedOutputStream bos = new BufferedOutputStream(fos, 16384); - DataOutputStream output = new DataOutputStream(bos); - output.writeInt(0); // come back for row count - output.writeInt(getColumnCount()); - if (columnTitles != null) { - output.writeBoolean(true); - for (String title : columnTitles) { - output.writeUTF(title); - } - } else { - output.writeBoolean(false); - } - for (int type : columnTypes) { - output.writeInt(type); - } - - String line = null; - //setRowCount(1); - int prev = -1; - int row = 0; - while ((line = reader.readLine()) != null) { - convertRow(output, tsv ? PApplet.split(line, '\t') : splitLineCSV(line, reader)); - row++; - - if (row % 10000 == 0) { - if (row < rowCount) { - int pct = (100 * row) / rowCount; - if (pct != prev) { - System.out.println(pct + "%"); - prev = pct; - } - } -// try { -// Thread.sleep(5); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// } - } - } - // shorten or lengthen based on what's left -// if (row != getRowCount()) { -// setRowCount(row); -// } - - // has to come afterwards, since these tables get built out during the conversion - int col = 0; - for (HashMapBlows hmb : columnCategories) { - if (hmb == null) { - output.writeInt(0); - } else { - hmb.write(output); - hmb.writeln(PApplet.createWriter(new File(columnTitles[col] + ".categories"))); -// output.writeInt(hmb.size()); -// for (Map.Entry e : hmb.entrySet()) { -// output.writeUTF(e.getKey()); -// output.writeInt(e.getValue()); -// } - } - col++; - } - - output.flush(); - output.close(); - - // come back and write the row count - RandomAccessFile raf = new RandomAccessFile(outputFile, "rw"); - raf.writeInt(rowCount); - raf.close(); - } - - - protected void convertRow(DataOutputStream output, String[] pieces) throws IOException { - if (pieces.length > getColumnCount()) { - throw new IllegalArgumentException("Row with too many columns: " + - PApplet.join(pieces, ",")); - } - // pieces.length may be less than columns.length, so loop over pieces - for (int col = 0; col < pieces.length; col++) { - switch (columnTypes[col]) { - case STRING: - output.writeUTF(pieces[col]); - break; - case INT: - output.writeInt(PApplet.parseInt(pieces[col], missingInt)); - break; - case LONG: - try { - output.writeLong(Long.parseLong(pieces[col])); - } catch (NumberFormatException nfe) { - output.writeLong(missingLong); - } - break; - case FLOAT: - output.writeFloat(PApplet.parseFloat(pieces[col], missingFloat)); - break; - case DOUBLE: - try { - output.writeDouble(Double.parseDouble(pieces[col])); - } catch (NumberFormatException nfe) { - output.writeDouble(missingDouble); - } - break; - case CATEGORY: - String peace = pieces[col]; - if (peace.equals(missingString)) { - output.writeInt(missingCategory); - } else { - output.writeInt(columnCategories[col].index(peace)); - } - break; - } - } - for (int col = pieces.length; col < getColumnCount(); col++) { - switch (columnTypes[col]) { - case STRING: - output.writeUTF(""); - break; - case INT: - output.writeInt(missingInt); - break; - case LONG: - output.writeLong(missingLong); - break; - case FLOAT: - output.writeFloat(missingFloat); - break; - case DOUBLE: - output.writeDouble(missingDouble); - break; - case CATEGORY: - output.writeInt(missingCategory); - break; - - } - } - } - - - /* - private void convertRowCol(DataOutputStream output, int row, int col, String piece) { - switch (columnTypes[col]) { - case STRING: - String[] stringData = (String[]) columns[col]; - stringData[row] = piece; - break; - case INT: - int[] intData = (int[]) columns[col]; - intData[row] = PApplet.parseInt(piece, missingInt); - break; - case LONG: - long[] longData = (long[]) columns[col]; - try { - longData[row] = Long.parseLong(piece); - } catch (NumberFormatException nfe) { - longData[row] = missingLong; - } - break; - case FLOAT: - float[] floatData = (float[]) columns[col]; - floatData[row] = PApplet.parseFloat(piece, missingFloat); - break; - case DOUBLE: - double[] doubleData = (double[]) columns[col]; - try { - doubleData[row] = Double.parseDouble(piece); - } catch (NumberFormatException nfe) { - doubleData[row] = missingDouble; - } - break; - default: - throw new IllegalArgumentException("That's not a valid column type."); - } - } - */ - - - /** Make a copy of the current table */ - public Table copy() { - return new Table(rows()); - } - - - public void write(PrintWriter writer) { - writeTSV(writer); - } - - - public void print() { - writeTSV(new PrintWriter(System.out)); - } -} diff --git a/core/src/processing/data/TableRow.java b/core/src/processing/data/TableRow.java deleted file mode 100644 index 3ac59fe4c..000000000 --- a/core/src/processing/data/TableRow.java +++ /dev/null @@ -1,198 +0,0 @@ -package processing.data; - -import java.io.PrintWriter; - -/** - * @webref data:composite - * @see Table - * @see Table#addRow() - * @see Table#removeRow(int) - * @see Table#clearRows() - * @see Table#getRow(int) - * @see Table#rows() - */ -public interface TableRow { - - /** - * @webref tablerow:method - * @brief Get an String value from the specified column - * @param column ID number of the column to reference - * @see TableRow#getInt(int) - * @see TableRow#getFloat(int) - */ - public String getString(int column); - - /** - * @param columnName title of the column to reference - */ - public String getString(String columnName); - - /** - * @webref tablerow:method - * @brief Get an integer value from the specified column - * @param column ID number of the column to reference - * @see TableRow#getFloat(int) - * @see TableRow#getString(int) - */ - public int getInt(int column); - - /** - * @param columnName title of the column to reference - */ - public int getInt(String columnName); - - /** - * @brief Get a long value from the specified column - * @param column ID number of the column to reference - * @see TableRow#getFloat(int) - * @see TableRow#getString(int) - */ - - public long getLong(int column); - - /** - * @param columnName title of the column to reference - */ - public long getLong(String columnName); - - /** - * @webref tablerow:method - * @brief Get a float value from the specified column - * @param column ID number of the column to reference - * @see TableRow#getInt(int) - * @see TableRow#getString(int) - */ - public float getFloat(int column); - - /** - * @param columnName title of the column to reference - */ - public float getFloat(String columnName); - - /** - * @brief Get a double value from the specified column - * @param column ID number of the column to reference - * @see TableRow#getInt(int) - * @see TableRow#getString(int) - */ - public double getDouble(int column); - - /** - * @param columnName title of the column to reference - */ - public double getDouble(String columnName); - - /** - * @webref tablerow:method - * @brief Store a String value in the specified column - * @param column ID number of the target column - * @param value value to assign - * @see TableRow#setInt(int, int) - * @see TableRow#setFloat(int, float) - */ - public void setString(int column, String value); - /** - * @param columnName title of the target column - */ - public void setString(String columnName, String value); - - /** - * @webref tablerow:method - * @brief Store an integer value in the specified column - * @param column ID number of the target column - * @param value value to assign - * @see TableRow#setFloat(int, float) - * @see TableRow#setString(int, String) - */ - public void setInt(int column, int value); - - /** - * @param columnName title of the target column - */ - public void setInt(String columnName, int value); - - /** - * @brief Store a long value in the specified column - * @param column ID number of the target column - * @param value value to assign - * @see TableRow#setFloat(int, float) - * @see TableRow#setString(int, String) - */ - public void setLong(int column, long value); - - /** - * @param columnName title of the target column - */ - public void setLong(String columnName, long value); - - /** - * @webref tablerow:method - * @brief Store a float value in the specified column - * @param column ID number of the target column - * @param value value to assign - * @see TableRow#setInt(int, int) - * @see TableRow#setString(int, String) - */ - public void setFloat(int column, float value); - - /** - * @param columnName title of the target column - */ - public void setFloat(String columnName, float value); - - /** - * @brief Store a double value in the specified column - * @param column ID number of the target column - * @param value value to assign - * @see TableRow#setFloat(int, float) - * @see TableRow#setString(int, String) - */ - public void setDouble(int column, double value); - - /** - * @param columnName title of the target column - */ - public void setDouble(String columnName, double value); - - /** - * @webref tablerow:method - * @brief Get the column count. - * @return count of all columns - */ - public int getColumnCount(); - - /** - * @brief Get the column type. - * @param columnName title of the target column - * @return type of the column - */ - public int getColumnType(String columnName); - - /** - * @param column ID number of the target column - */ - public int getColumnType(int column); - - /** - * @brief Get the all column types - * @return list of all column types - */ - public int[] getColumnTypes(); - - /** - * @webref tablerow:method - * @brief Get the column title. - * @param column ID number of the target column - * @return title of the column - */ - public String getColumnTitle(int column); - - /** - * @brief Get the all column titles - * @return list of all column titles - */ - public String[] getColumnTitles(); - - public void write(PrintWriter writer); - public void print(); -} diff --git a/core/src/processing/data/XML.java b/core/src/processing/data/XML.java deleted file mode 100644 index f2c2e32cc..000000000 --- a/core/src/processing/data/XML.java +++ /dev/null @@ -1,1156 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2009-12 Ben Fry and Casey Reas - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty - of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.data; - -import java.io.*; - -import javax.xml.parsers.*; - -import org.w3c.dom.*; -import org.xml.sax.*; - -import javax.xml.transform.*; -import javax.xml.transform.dom.*; -import javax.xml.transform.stream.*; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpression; -import javax.xml.xpath.XPathFactory; - -import processing.core.PApplet; - - -/** - * This is the base class used for the Processing XML library, - * representing a single node of an XML tree. - * - * @webref data:composite - * @see PApplet#loadXML(String) - * @see PApplet#parseXML(String) - * @see PApplet#saveXML(XML, String) - */ -public class XML implements Serializable { - - /** The internal representation, a DOM node. */ - protected Node node; - -// /** Cached locally because it's used often. */ -// protected String name; - - /** The parent element. */ - protected XML parent; - - /** Child elements, once loaded. */ - protected XML[] children; - - /** - * @nowebref - */ - protected XML() { } - - -// /** -// * Begin parsing XML data passed in from a PApplet. This code -// * wraps exception handling, for more advanced exception handling, -// * use the constructor that takes a Reader or InputStream. -// * -// * @throws SAXException -// * @throws ParserConfigurationException -// * @throws IOException -// */ -// public XML(PApplet parent, String filename) throws IOException, ParserConfigurationException, SAXException { -// this(parent.createReader(filename)); -// } - - - /** - * Advanced users only; use loadXML() in PApplet. This is not a supported - * function and is subject to change. It is available simply for users that - * would like to handle the exceptions in a particular way. - * - * @nowebref - */ - public XML(File file) throws IOException, ParserConfigurationException, SAXException { - this(file, null); - } - - - /** - * Advanced users only; use loadXML() in PApplet. - * - * @nowebref - */ - public XML(File file, String options) throws IOException, ParserConfigurationException, SAXException { - this(PApplet.createReader(file), options); - } - - /** - * @nowebref - */ - public XML(InputStream input) throws IOException, ParserConfigurationException, SAXException { - this(input, null); - } - - - /** - * Unlike the loadXML() method in PApplet, this version works with files - * that are not in UTF-8 format. - * - * @nowebref - */ - public XML(InputStream input, String options) throws IOException, ParserConfigurationException, SAXException { - //this(PApplet.createReader(input), options); // won't handle non-UTF8 - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - - try { - // Prevent 503 errors from www.w3.org - factory.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); - } catch (IllegalArgumentException e) { - // ignore this; Android doesn't like it - } - - factory.setExpandEntityReferences(false); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document document = builder.parse(new InputSource(input)); - node = document.getDocumentElement(); - } - - - /** - * Advanced users only; use loadXML() in PApplet. - * - * @nowebref - */ - public XML(Reader reader) throws IOException, ParserConfigurationException, SAXException { - this(reader, null); - } - - - /** - * Advanced users only; use loadXML() in PApplet. - * - * Added extra code to handle \u2028 (Unicode NLF), which is sometimes - * inserted by web browsers (Safari?) and not distinguishable from a "real" - * LF (or CRLF) in some text editors (i.e. TextEdit on OS X). Only doing - * this for XML (and not all Reader objects) because LFs are essential. - * https://github.com/processing/processing/issues/2100 - * - * @nowebref - */ - public XML(final Reader reader, String options) throws IOException, ParserConfigurationException, SAXException { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - - // Prevent 503 errors from www.w3.org - try { - factory.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); - } catch (IllegalArgumentException e) { - // ignore this; Android doesn't like it - } - - // without a validating DTD, this doesn't do anything since it doesn't know what is ignorable -// factory.setIgnoringElementContentWhitespace(true); - - factory.setExpandEntityReferences(false); -// factory.setExpandEntityReferences(true); - -// factory.setCoalescing(true); -// builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - DocumentBuilder builder = factory.newDocumentBuilder(); -// builder.setEntityResolver() - -// SAXParserFactory spf = SAXParserFactory.newInstance(); -// spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); -// SAXParser p = spf.newSAXParser(); - - // builder = DocumentBuilderFactory.newDocumentBuilder(); - // builder = new SAXBuilder(); - // builder.setValidation(validating); - - Document document = builder.parse(new InputSource(new Reader() { - @Override - public int read(char[] cbuf, int off, int len) throws IOException { - int count = reader.read(cbuf, off, len); - for (int i = 0; i < count; i++) { - if (cbuf[off+i] == '\u2028') { - cbuf[off+i] = '\n'; - } - } - return count; - } - - @Override - public void close() throws IOException { - reader.close(); - } - })); - node = document.getDocumentElement(); - } - - - /** - * @param name creates a node with this name - * - */ - public XML(String name) { - try { - // TODO is there a more efficient way of doing this? wow. - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document document = builder.newDocument(); - node = document.createElement(name); - this.parent = null; - - } catch (ParserConfigurationException pce) { - throw new RuntimeException(pce); - } - } - - /** - * @nowebref - */ - protected XML(XML parent, Node node) { - this.node = node; - this.parent = parent; - - for (String attr : parent.listAttributes()) { - if (attr.startsWith("xmlns")) { - // Copy namespace attributes to the kids, otherwise this XML - // can no longer be printed (or manipulated in most ways). - // Only do this when it's an Element, otherwise it's trying to set - // attributes on text notes (interstitial content). - if (node instanceof Element) { - setString(attr, parent.getString(attr)); - } - } - } - } - - - /** - * @webref xml:method - * @brief Converts String content to an XML object - * @param data the content to be parsed as XML - * @return an XML object, or null - * @throws SAXException - * @throws ParserConfigurationException - * @throws IOException - * @nowebref - */ - static public XML parse(String data) throws IOException, ParserConfigurationException, SAXException { - return XML.parse(data, null); - } - - /** - * @nowebref - */ - static public XML parse(String data, String options) throws IOException, ParserConfigurationException, SAXException { - return new XML(new StringReader(data), null); - } - - -// protected boolean save(OutputStream output) { -// return write(PApplet.createWriter(output)); -// } - - - public boolean save(File file) { - return save(file, null); - } - - - public boolean save(File file, String options) { - PrintWriter writer = PApplet.createWriter(file); - boolean result = write(writer); - writer.flush(); - writer.close(); - return result; - } - - - // Sends this object and its kids to a Writer with an indent of 2 spaces, - // including the declaration at the top so that the output will be valid XML. - public boolean write(PrintWriter output) { - output.print(format(2)); - output.flush(); - return true; - } - - - /** - * Returns the parent element. This method returns null for the root - * element. - * - * @webref xml:method - * @brief Gets a copy of the element's parent - */ - public XML getParent() { - return this.parent; - } - - /** - * Internal function; not included in reference. - */ - protected Object getNative() { - return node; - } - - - /** - * Returns the full name (i.e. the name including an eventual namespace - * prefix) of the element. - * - * @webref xml:method - * @brief Gets the element's full name - * @return the name, or null if the element only contains #PCDATA. - */ - public String getName() { -// return name; - return node.getNodeName(); - } - - /** - * @webref xml:method - * @brief Sets the element's name - */ - public void setName(String newName) { - Document document = node.getOwnerDocument(); - node = document.renameNode(node, null, newName); -// name = node.getNodeName(); - } - - - /** - * Returns the name of the element (without namespace prefix). - * - * Internal function; not included in reference. - */ - public String getLocalName() { - return node.getLocalName(); - } - - - /** - * Honey, can you just check on the kids? Thanks. - * - * Internal function; not included in reference. - */ - protected void checkChildren() { - if (children == null) { - NodeList kids = node.getChildNodes(); - int childCount = kids.getLength(); - children = new XML[childCount]; - for (int i = 0; i < childCount; i++) { - children[i] = new XML(this, kids.item(i)); - } - } - } - - - /** - * Returns the number of children. - * - * @webref xml:method - * @brief Returns the element's number of children - * @return the count. - */ - public int getChildCount() { - checkChildren(); - return children.length; - } - - - /** - * Returns a boolean of whether or not there are children. - * - * @webref xml:method - * @brief Checks whether or not an element has any children - */ - public boolean hasChildren() { - checkChildren(); - return children.length > 0; - } - - - /** - * Put the names of all children into an array. Same as looping through - * each child and calling getName() on each XMLElement. - * - * @webref xml:method - * @brief Returns the names of all children as an array - */ - public String[] listChildren() { -// NodeList children = node.getChildNodes(); -// int childCount = children.getLength(); -// String[] outgoing = new String[childCount]; -// for (int i = 0; i < childCount; i++) { -// Node kid = children.item(i); -// if (kid.getNodeType() == Node.ELEMENT_NODE) { -// outgoing[i] = kid.getNodeName(); -// } // otherwise just leave him null -// } - checkChildren(); - String[] outgoing = new String[children.length]; - for (int i = 0; i < children.length; i++) { - outgoing[i] = children[i].getName(); - } - return outgoing; - } - - - /** - * Returns an array containing all the child elements. - * - * @webref xml:method - * @brief Returns an array containing all child elements - */ - public XML[] getChildren() { -// NodeList children = node.getChildNodes(); -// int childCount = children.getLength(); -// XMLElement[] kids = new XMLElement[childCount]; -// for (int i = 0; i < childCount; i++) { -// Node kid = children.item(i); -// kids[i] = new XMLElement(this, kid); -// } -// return kids; - checkChildren(); - return children; - } - - - /** - * Quick accessor for an element at a particular index. - * - * @webref xml:method - * @brief Returns the child element with the specified index value or path - */ - public XML getChild(int index) { - checkChildren(); - return children[index]; - } - - - /** - * Get a child by its name or path. - * - * @param name element name or path/to/element - * @return the first matching element or null if no match - */ - public XML getChild(String name) { - if (name.length() > 0 && name.charAt(0) == '/') { - throw new IllegalArgumentException("getChild() should not begin with a slash"); - } - if (name.indexOf('/') != -1) { - return getChildRecursive(PApplet.split(name, '/'), 0); - } - int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - XML kid = getChild(i); - String kidName = kid.getName(); - if (kidName != null && kidName.equals(name)) { - return kid; - } - } - return null; - } - - - /** - * Internal helper function for getChild(String). - * - * @param items result of splitting the query on slashes - * @param offset where in the items[] array we're currently looking - * @return matching element or null if no match - * @author processing.org - */ - protected XML getChildRecursive(String[] items, int offset) { - // if it's a number, do an index instead - if (Character.isDigit(items[offset].charAt(0))) { - XML kid = getChild(Integer.parseInt(items[offset])); - if (offset == items.length-1) { - return kid; - } else { - return kid.getChildRecursive(items, offset+1); - } - } - int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - XML kid = getChild(i); - String kidName = kid.getName(); - if (kidName != null && kidName.equals(items[offset])) { - if (offset == items.length-1) { - return kid; - } else { - return kid.getChildRecursive(items, offset+1); - } - } - } - return null; - } - - - /** - * Get any children that match this name or path. Similar to getChild(), - * but will grab multiple matches rather than only the first. - * - * @param name element name or path/to/element - * @return array of child elements that match - * @author processing.org - */ - public XML[] getChildren(String name) { - if (name.length() > 0 && name.charAt(0) == '/') { - throw new IllegalArgumentException("getChildren() should not begin with a slash"); - } - if (name.indexOf('/') != -1) { - return getChildrenRecursive(PApplet.split(name, '/'), 0); - } - // if it's a number, do an index instead - // (returns a single element array, since this will be a single match - if (Character.isDigit(name.charAt(0))) { - return new XML[] { getChild(Integer.parseInt(name)) }; - } - int childCount = getChildCount(); - XML[] matches = new XML[childCount]; - int matchCount = 0; - for (int i = 0; i < childCount; i++) { - XML kid = getChild(i); - String kidName = kid.getName(); - if (kidName != null && kidName.equals(name)) { - matches[matchCount++] = kid; - } - } - return (XML[]) PApplet.subset(matches, 0, matchCount); - } - - - protected XML[] getChildrenRecursive(String[] items, int offset) { - if (offset == items.length-1) { - return getChildren(items[offset]); - } - XML[] matches = getChildren(items[offset]); - XML[] outgoing = new XML[0]; - for (int i = 0; i < matches.length; i++) { - XML[] kidMatches = matches[i].getChildrenRecursive(items, offset+1); - outgoing = (XML[]) PApplet.concat(outgoing, kidMatches); - } - return outgoing; - } - - - /** - * @webref xml:method - * @brief Appends a new child to the element - */ - public XML addChild(String tag) { - Document document = node.getOwnerDocument(); - Node newChild = document.createElement(tag); - return appendChild(newChild); - } - - - public XML addChild(XML child) { - Document document = node.getOwnerDocument(); - Node newChild = document.importNode((Node) child.getNative(), true); - return appendChild(newChild); - } - - - /** Internal handler to add the node structure. */ - protected XML appendChild(Node newNode) { - node.appendChild(newNode); - XML newbie = new XML(this, newNode); - if (children != null) { - children = (XML[]) PApplet.concat(children, new XML[] { newbie }); - } - return newbie; - } - - - /** - * @webref xml:method - * @brief Removes the specified child - */ - public void removeChild(XML kid) { - node.removeChild(kid.node); - children = null; // TODO not efficient - } - - /** - * Removes whitespace nodes. - * Those whitespace nodes are required to reconstruct the original XML's spacing and indentation. - * If you call this and use saveXML() your original spacing will be gone. - * - * @nowebref - * @brief Removes whitespace nodes - */ - public void trim() { - try { - XPathFactory xpathFactory = XPathFactory.newInstance(); - XPathExpression xpathExp = - xpathFactory.newXPath().compile("//text()[normalize-space(.) = '']"); - NodeList emptyTextNodes = (NodeList) - xpathExp.evaluate(node, XPathConstants.NODESET); - - // Remove each empty text node from document. - for (int i = 0; i < emptyTextNodes.getLength(); i++) { - Node emptyTextNode = emptyTextNodes.item(i); - emptyTextNode.getParentNode().removeChild(emptyTextNode); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - -// /** Remove whitespace nodes. */ -// public void trim() { -////// public static boolean isWhitespace(XML xml) { -////// if (xml.node.getNodeType() != Node.TEXT_NODE) -////// return false; -////// Matcher m = whitespace.matcher(xml.node.getNodeValue()); -////// return m.matches(); -////// } -//// trim(this); -//// } -// -// checkChildren(); -// int index = 0; -// for (int i = 0; i < children.length; i++) { -// if (i != index) { -// children[index] = children[i]; -// } -// Node childNode = (Node) children[i].getNative(); -// if (childNode.getNodeType() != Node.TEXT_NODE || -// children[i].getContent().trim().length() > 0) { -// children[i].trim(); -// index++; -// } -// } -// if (index != children.length) { -// children = (XML[]) PApplet.subset(children, 0, index); -// } -// -// // possibility, but would have to re-parse the object -//// helpdesk.objects.com.au/java/how-do-i-remove-whitespace-from-an-xml-document -//// TransformerFactory factory = TransformerFactory.newInstance(); -//// Transformer transformer = factory.newTransformer(new StreamSource("strip-space.xsl")); -//// DOMSource source = new DOMSource(document); -//// StreamResult result = new StreamResult(System.out); -//// transformer.transform(source, result); -// -//// -//// -//// -//// -//// -//// -//// -//// -//// -// } - - - /** - * Returns the number of attributes. - * - * @webref xml:method - * @brief Counts the specified element's number of attributes - */ - public int getAttributeCount() { - return node.getAttributes().getLength(); - } - - - /** - * Get a list of the names for all of the attributes for this node. - * - * @webref xml:method - * @brief Returns a list of names of all attributes as an array - */ - public String[] listAttributes() { - NamedNodeMap nnm = node.getAttributes(); - String[] outgoing = new String[nnm.getLength()]; - for (int i = 0; i < outgoing.length; i++) { - outgoing[i] = nnm.item(i).getNodeName(); - } - return outgoing; - } - - /** - * Returns whether an attribute exists. - * - * @webref xml:method - * @brief Checks whether or not an element has the specified attribute - */ - public boolean hasAttribute(String name) { - return (node.getAttributes().getNamedItem(name) != null); - } - - - /** - * Returns the value of an attribute. - * - * @param name the non-null name of the attribute. - * @return the value, or null if the attribute does not exist. - */ -// public String getAttribute(String name) { -// return this.getAttribute(name, null); -// } - - - /** - * Returns the value of an attribute. - * - * @param name the non-null full name of the attribute. - * @param defaultValue the default value of the attribute. - * @return the value, or defaultValue if the attribute does not exist. - */ -// public String getAttribute(String name, String defaultValue) { -// Node attr = node.getAttributes().getNamedItem(name); -// return (attr == null) ? defaultValue : attr.getNodeValue(); -// } - - - /** - * @webref xml:method - * @brief Gets the content of an attribute as a String - */ - public String getString(String name) { - return getString(name, null); - } - - - public String getString(String name, String defaultValue) { - NamedNodeMap attrs = node.getAttributes(); - if (attrs != null) { - Node attr = attrs.getNamedItem(name); - if (attr != null) { - return attr.getNodeValue(); - } - } - return defaultValue; - } - - - /** - * @webref xml:method - * @brief Sets the content of an attribute as a String - */ - public void setString(String name, String value) { - ((Element) node).setAttribute(name, value); - } - - - /** - * @webref xml:method - * @brief Gets the content of an attribute as an int - */ - public int getInt(String name) { - return getInt(name, 0); - } - - - /** - * @webref xml:method - * @brief Sets the content of an attribute as an int - */ - public void setInt(String name, int value) { - setString(name, String.valueOf(value)); - } - - - /** - * Returns the value of an attribute. - * - * @param name the non-null full name of the attribute - * @param defaultValue the default value of the attribute - * @return the value, or defaultValue if the attribute does not exist - */ - public int getInt(String name, int defaultValue) { - String value = getString(name); - return (value == null) ? defaultValue : Integer.parseInt(value); - } - - - /** - * @webref xml:method - * @brief Sets the content of an element as an int - */ - public void setLong(String name, long value) { - setString(name, String.valueOf(value)); - } - - - /** - * Returns the value of an attribute. - * - * @param name the non-null full name of the attribute. - * @param defaultValue the default value of the attribute. - * @return the value, or defaultValue if the attribute does not exist. - */ - public long getLong(String name, long defaultValue) { - String value = getString(name); - return (value == null) ? defaultValue : Long.parseLong(value); - } - - - /** - * Returns the value of an attribute, or zero if not present. - * - * @webref xml:method - * @brief Gets the content of an attribute as a float - */ - public float getFloat(String name) { - return getFloat(name, 0); - } - - - /** - * Returns the value of an attribute. - * - * @param name the non-null full name of the attribute. - * @param defaultValue the default value of the attribute. - * @return the value, or defaultValue if the attribute does not exist. - */ - public float getFloat(String name, float defaultValue) { - String value = getString(name); - return (value == null) ? defaultValue : Float.parseFloat(value); - } - - - /** - * @webref xml:method - * @brief Sets the content of an attribute as a float - */ - public void setFloat(String name, float value) { - setString(name, String.valueOf(value)); - } - - - public double getDouble(String name) { - return getDouble(name, 0); - } - - - /** - * Returns the value of an attribute. - * - * @param name the non-null full name of the attribute - * @param defaultValue the default value of the attribute - * @return the value, or defaultValue if the attribute does not exist - */ - public double getDouble(String name, double defaultValue) { - String value = getString(name); - return (value == null) ? defaultValue : Double.parseDouble(value); - } - - - public void setDouble(String name, double value) { - setString(name, String.valueOf(value)); - } - - - /** - * Return the #PCDATA content of the element. If the element has a - * combination of #PCDATA content and child elements, the #PCDATA - * sections can be retrieved as unnamed child objects. In this case, - * this method returns null. - * - * @webref xml:method - * @brief Gets the content of an element - * @return the content. - * @see XML#getIntContent() - * @see XML#getFloatContent() - */ - public String getContent() { - return node.getTextContent(); - } - - - public String getContent(String defaultValue) { - String s = node.getTextContent(); - return (s != null) ? s : defaultValue; - } - - - /** - * @webref xml:method - * @brief Gets the content of an element as an int - * @return the content. - * @see XML#getContent() - * @see XML#getFloatContent() - */ - public int getIntContent() { - return getIntContent(0); - } - - - /** - * @param defaultValue the default value of the attribute - */ - public int getIntContent(int defaultValue) { - return PApplet.parseInt(node.getTextContent(), defaultValue); - } - - - /** - * @webref xml:method - * @brief Gets the content of an element as a float - * @return the content. - * @see XML#getContent() - * @see XML#getIntContent() - */ - public float getFloatContent() { - return getFloatContent(0); - } - - - /** - * @param defaultValue the default value of the attribute - */ - public float getFloatContent(float defaultValue) { - return PApplet.parseFloat(node.getTextContent(), defaultValue); - } - - - public long getLongContent() { - return getLongContent(0); - } - - - public long getLongContent(long defaultValue) { - String c = node.getTextContent(); - if (c != null) { - try { - return Long.parseLong(c); - } catch (NumberFormatException nfe) { } - } - return defaultValue; - } - - - public double getDoubleContent() { - return getDoubleContent(0); - } - - - public double getDoubleContent(double defaultValue) { - String c = node.getTextContent(); - if (c != null) { - try { - return Double.parseDouble(c); - } catch (NumberFormatException nfe) { } - } - return defaultValue; - } - - - /** - * @webref xml:method - * @brief Sets the content of an element - */ - public void setContent(String text) { - node.setTextContent(text); - } - - - public void setIntContent(int value) { - setContent(String.valueOf(value)); - } - - - public void setFloatContent(float value) { - setContent(String.valueOf(value)); - } - - - public void setLongContent(long value) { - setContent(String.valueOf(value)); - } - - - public void setDoubleContent(double value) { - setContent(String.valueOf(value)); - } - - - /** - * Format this XML data as a String. - * - * @webref xml:method - * @brief Formats XML data as a String - * @param indent -1 for a single line (and no declaration), >= 0 for indents and newlines - * @return the content - * @see XML#toString() - */ - public String format(int indent) { - try { - // entities = doctype.getEntities() - boolean useIndentAmount = false; - TransformerFactory factory = TransformerFactory.newInstance(); - if (indent != -1) { - try { - factory.setAttribute("indent-number", indent); - } catch (IllegalArgumentException e) { - useIndentAmount = true; - } - } - Transformer transformer = factory.newTransformer(); - - // Add the XML declaration at the top if this node is the root and we're - // not writing to a single line (indent = -1 means single line). - if (indent == -1 || parent == null) { - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); - } else { - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); - } - -// transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "sample.dtd"); - - transformer.setOutputProperty(OutputKeys.METHOD, "xml"); - -// transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, "yes"); // huh? - -// transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, -// "-//W3C//DTD XHTML 1.0 Transitional//EN"); -// transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, -// "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"); - - // For Android, because (at least 2.3.3) doesn't like indent-number - if (useIndentAmount) { - transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", String.valueOf(indent)); - } - -// transformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1"); -// transformer.setOutputProperty(OutputKeys.ENCODING,"UTF8"); - transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8"); -// transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS - - // Always indent, otherwise the XML declaration will just be jammed - // onto the first line with the XML code as well. - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - -// Properties p = transformer.getOutputProperties(); -// for (Object key : p.keySet()) { -// System.out.println(key + " -> " + p.get(key)); -// } - - // If you smell something, that's because this code stinks. No matter - // the settings of the Transformer object, if the XML document already - // has whitespace elements, it won't bother re-indenting/re-formatting. - // So instead, transform the data once into a single line string. - // If indent is -1, then we're done. Otherwise re-run and the settings - // of the factory will kick in. If you know a better way to do this, - // please contribute. I've wasted too much of my Sunday on it. But at - // least the Giants are getting blown out by the Falcons. - - final String decl = ""; - final String sep = System.getProperty("line.separator"); - - StringWriter tempWriter = new StringWriter(); - StreamResult tempResult = new StreamResult(tempWriter); - transformer.transform(new DOMSource(node), tempResult); - String[] tempLines = PApplet.split(tempWriter.toString(), sep); -// PApplet.println(tempLines); - if (tempLines[0].startsWith("") + 2; - //if (tempLines[0].length() == decl.length()) { - if (tempLines[0].length() == declEnd) { - // If it's all the XML declaration, remove it -// PApplet.println("removing first line"); - tempLines = PApplet.subset(tempLines, 1); - } else { -// PApplet.println("removing part of first line"); - // If the first node has been moved to this line, be more careful - //tempLines[0] = tempLines[0].substring(decl.length()); - tempLines[0] = tempLines[0].substring(declEnd); - } - } - String singleLine = PApplet.join(PApplet.trim(tempLines), ""); - if (indent == -1) { - return singleLine; - } - - // Might just be whitespace, which won't be valid XML for parsing below. - // https://github.com/processing/processing/issues/1796 - // Since indent is not -1, that means they want valid XML, - // so we'll give them the single line plus the decl... Lame? sure. - if (singleLine.trim().length() == 0) { - // You want whitespace? I've got your whitespace right here. - return decl + sep + singleLine; - } - - // Since the indent is not -1, bring back the XML declaration - //transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); - - StringWriter stringWriter = new StringWriter(); - StreamResult xmlOutput = new StreamResult(stringWriter); -// DOMSource source = new DOMSource(node); - Source source = new StreamSource(new StringReader(singleLine)); - transformer.transform(source, xmlOutput); - String outgoing = stringWriter.toString(); - - // Add the XML declaration to the top if it's not there already - if (outgoing.startsWith(decl)) { - int declen = decl.length(); - int seplen = sep.length(); - if (outgoing.length() > declen + seplen && - !outgoing.substring(declen, declen + seplen).equals(sep)) { - // make sure there's a line break between the XML decl and the code - return outgoing.substring(0, decl.length()) + - sep + outgoing.substring(decl.length()); - } - return outgoing; - } else { - return decl + sep + outgoing; - } - - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - - public void print() { - PApplet.println(format(2)); - } - - - /** - * Return the XML document formatted with two spaces for indents. - * Chosen to do this since it's the most common case (e.g. with println()). - * Same as format(2). Use the format() function for more options. - * - * @webref xml:method - * @brief Gets XML data as a String using default formatting - * @return the content - * @see XML#format(int) - */ - @Override - public String toString() { - //return format(2); - return format(-1); - } -} diff --git a/core/src/processing/event/Event.java b/core/src/processing/event/Event.java deleted file mode 100644 index 109dbbee7..000000000 --- a/core/src/processing/event/Event.java +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.event; - - -public class Event { - protected Object nativeObject; - - protected long millis; - protected int action; - - // These correspond to the java.awt.Event modifiers (not to be confused with - // the newer getModifiersEx), though they're not guaranteed to in the future. - static public final int SHIFT = 1 << 0; - static public final int CTRL = 1 << 1; - static public final int META = 1 << 2; - static public final int ALT = 1 << 3; - protected int modifiers; - - // Types of events. As with all constants in Processing, brevity's preferred. - static public final int KEY = 1; - static public final int MOUSE = 2; - static public final int TOUCH = 3; - protected int flavor; - - - public Event(Object nativeObject, long millis, int action, int modifiers) { - this.nativeObject = nativeObject; - this.millis = millis; - this.action = action; - this.modifiers = modifiers; - } - - - public int getFlavor() { - return flavor; - } - - - /** - * Get the platform-native event object. This might be the java.awt event - * on the desktop, though if you're using OpenGL on the desktop it'll be a - * NEWT event that JOGL uses. Android events are something else altogether. - * Bottom line, use this only if you know what you're doing, and don't make - * assumptions about the class type. - */ - public Object getNative() { - return nativeObject; - } - - -// public void setNative(Object nativeObject) { -// this.nativeObject = nativeObject; -// } - - - public long getMillis() { - return millis; - } - - -// public void setMillis(long millis) { -// this.millis = millis; -// } - - - public int getAction() { - return action; - } - - -// public void setAction(int action) { -// this.action = action; -// } - - - public int getModifiers() { - return modifiers; - } - - -// public void setModifiers(int modifiers) { -// this.modifiers = modifiers; -// } - - - public boolean isShiftDown() { - return (modifiers & SHIFT) != 0; - } - - - public boolean isControlDown() { - return (modifiers & CTRL) != 0; - } - - - public boolean isMetaDown() { - return (modifiers & META) != 0; - } - - - public boolean isAltDown() { - return (modifiers & ALT) != 0; - } -} \ No newline at end of file diff --git a/core/src/processing/event/KeyEvent.java b/core/src/processing/event/KeyEvent.java deleted file mode 100644 index 4a9bdf44d..000000000 --- a/core/src/processing/event/KeyEvent.java +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.event; - - -public class KeyEvent extends Event { - static public final int PRESS = 1; - static public final int RELEASE = 2; - static public final int TYPE = 3; - - char key; - int keyCode; - - boolean isAutoRepeat; - - public KeyEvent(Object nativeObject, - long millis, int action, int modifiers, - char key, int keyCode) { - super(nativeObject, millis, action, modifiers); - this.flavor = KEY; - this.key = key; - this.keyCode = keyCode; - } - - - public KeyEvent(Object nativeObject, - long millis, int action, int modifiers, - char key, int keyCode, boolean isAutoRepeat) { - super(nativeObject, millis, action, modifiers); - this.flavor = KEY; - this.key = key; - this.keyCode = keyCode; - this.isAutoRepeat = isAutoRepeat; - } - - - public char getKey() { - return key; - } - - - public int getKeyCode() { - return keyCode; - } - - public boolean isAutoRepeat() { - return isAutoRepeat; - } -} \ No newline at end of file diff --git a/core/src/processing/event/MouseEvent.java b/core/src/processing/event/MouseEvent.java deleted file mode 100644 index 012f4e29e..000000000 --- a/core/src/processing/event/MouseEvent.java +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.event; - -//import processing.core.PConstants; - - -public class MouseEvent extends Event { - static public final int PRESS = 1; - static public final int RELEASE = 2; - static public final int CLICK = 3; - static public final int DRAG = 4; - static public final int MOVE = 5; - static public final int ENTER = 6; - static public final int EXIT = 7; - - protected int x, y; - protected int button; - protected int count; - - -// public MouseEvent(int x, int y) { -// this(null, -// System.currentTimeMillis(), PRESSED, 0, -// x, y, PConstants.LEFT, 1); -// } - - - public MouseEvent(Object nativeObject, - long millis, int action, int modifiers, - int x, int y, int button, int count) { - super(nativeObject, millis, action, modifiers); - this.flavor = MOUSE; - this.x = x; - this.y = y; - this.button = button; - this.count = count; - } - - - public int getX() { - return x; - } - - - public int getY() { - return y; - } - - - /** Which button was pressed, either LEFT, CENTER, or RIGHT. */ - public int getButton() { - return button; - } - - -// public void setButton(int button) { -// this.button = button; -// } - - - @Deprecated - public int getClickCount() { - return count; - } - - - /** - * Number of clicks for mouse button events, or the number of steps (positive - * or negative depending on direction) for a mouse wheel event. - * Wheel events follow Java (see
    here), so - * getAmount() will return "negative values if the mouse wheel was rotated - * up or away from the user" and positive values in the other direction. - * On Mac OS X, this will be reversed when "natural" scrolling is enabled - * in System Preferences &rarr Mouse. - */ - public int getCount() { - return count; - } - - -// public void setClickCount(int clickCount) { -// this.clickCount = clickCount; -// } -} \ No newline at end of file diff --git a/core/src/processing/event/TouchEvent.java b/core/src/processing/event/TouchEvent.java deleted file mode 100644 index 440a7824e..000000000 --- a/core/src/processing/event/TouchEvent.java +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.event; - -/* - * IMPORTANT NOTICE: None of the methods and inner classes in TouchEvent are - * part of the Processing API. Don't use them! They might be changed or removed - * without notice. -*/ -public class TouchEvent extends Event { - static public final int START = 1; - static public final int END = 2; - static public final int CANCEL = 3; - static public final int MOVE = 4; - - protected int action; - - protected int button; - protected int numPointers; - protected int[] pointerId; - protected float[] pointerX; - protected float[] pointerY; - protected float[] pointerArea; - protected float[] pointerPressure; - - public TouchEvent(Object nativeObject, long millis, int action, int modifiers, - int button) { - super(nativeObject, millis, action, modifiers); - this.flavor = TOUCH; - this.button = button; - } - - public void setNumPointers(int n) { - numPointers = n; - pointerId = new int[n]; - pointerX = new float[n]; - pointerY = new float[n]; - pointerArea = new float[n]; - pointerPressure = new float[n]; - } - - - public void setPointer(int idx, int id, float x, float y, float a, float p) { - pointerId[idx] = id; - pointerX[idx] = x; - pointerY[idx] = y; - pointerArea[idx] = a; - pointerPressure[idx] = p; - } - - - public int getNumPointers() { - return numPointers; - } - - - public Pointer getPointer(int idx) { - Pointer pt = new Pointer(); - pt.id = pointerId[idx]; - pt.x = pointerX[idx]; - pt.y = pointerY[idx]; - pt.area = pointerArea[idx]; - pt.pressure = pointerPressure[idx]; - return pt; - } - - - public int getPointerId(int idx) { - return pointerId[idx]; - } - - - public float getPointerX(int idx) { - return pointerX[idx]; - } - - - public float getPointerY(int idx) { - return pointerY[idx]; - } - - - public float getPointerArea(int idx) { - return pointerArea[idx]; - } - - - public float getPointerPressure(int idx) { - return pointerPressure[idx]; - } - - - public int getButton() { - return button; - } - - - public Pointer[] getTouches(Pointer[] touches) { - if (touches == null || touches.length != numPointers) { - touches = new Pointer[numPointers]; - for (int idx = 0; idx < numPointers; idx++) { - touches[idx] = new Pointer(); - } - } - for (int idx = 0; idx < numPointers; idx++) { - touches[idx].id = pointerId[idx]; - touches[idx].x = pointerX[idx]; - touches[idx].y = pointerY[idx]; - touches[idx].area = pointerArea[idx]; - touches[idx].pressure = pointerPressure[idx]; - } - return touches; - } - - - public class Pointer { - public int id; - public float x, y; - public float area; - public float pressure; - } -} \ No newline at end of file diff --git a/core/src/processing/opengl/FontTexture.java b/core/src/processing/opengl/FontTexture.java deleted file mode 100644 index cc67259bb..000000000 --- a/core/src/processing/opengl/FontTexture.java +++ /dev/null @@ -1,379 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import processing.core.PApplet; -import processing.core.PConstants; -import processing.core.PFont; -import processing.core.PGraphics; -import processing.core.PImage; - -import java.util.HashMap; - -/** - * All the infrastructure needed for optimized font rendering - * in OpenGL. Basically, this special class is needed because - * fonts in Processing are handled by a separate PImage for each - * glyph. For performance reasons, all these glyphs should be - * stored in a single OpenGL texture (otherwise, rendering a - * string of text would involve binding and un-binding several - * textures. - * PFontTexture manages the correspondence between individual - * glyphs and the large OpenGL texture containing them. Also, - * in the case that the font size is very large, one single - * OpenGL texture might not be enough to store all the glyphs, - * so PFontTexture also takes care of spreading a single font - * over several textures. - * @author Andres Colubri - */ -class FontTexture implements PConstants { - protected PGL pgl; - protected boolean is3D; - - protected int minSize; - protected int maxSize; - protected int offsetX; - protected int offsetY; - protected int lineHeight; - protected Texture[] textures = null; - protected PImage[] images = null; - protected int lastTex; - protected TextureInfo[] glyphTexinfos; - protected HashMap texinfoMap; - - public FontTexture(PGraphicsOpenGL pg, PFont font, boolean is3D) { - pgl = pg.pgl; - this.is3D = is3D; - - initTexture(pg, font); - } - - - protected void allocate() { - // Nothing to do here: the font textures will allocate - // themselves. - } - - - protected void dispose() { - for (int i = 0; i < textures.length; i++) { - textures[i].dispose(); - } - } - - - protected void initTexture(PGraphicsOpenGL pg, PFont font) { - lastTex = -1; - - int spow = PGL.nextPowerOfTwo(font.getSize()); - minSize = PApplet.min(PGraphicsOpenGL.maxTextureSize, - PApplet.max(PGL.MIN_FONT_TEX_SIZE, spow)); - maxSize = PApplet.min(PGraphicsOpenGL.maxTextureSize, - PApplet.max(PGL.MAX_FONT_TEX_SIZE, 2 * spow)); - - if (maxSize < spow) { - PGraphics.showWarning("The font size is too large to be properly " + - "displayed with OpenGL"); - } - - addTexture(pg); - - offsetX = 0; - offsetY = 0; - lineHeight = 0; - - texinfoMap = new HashMap(); - glyphTexinfos = new TextureInfo[font.getGlyphCount()]; - addAllGlyphsToTexture(pg, font); - } - - - public boolean addTexture(PGraphicsOpenGL pg) { - int w, h; - boolean resize; - - w = maxSize; - if (-1 < lastTex && textures[lastTex].glHeight < maxSize) { - // The height of the current texture is less than the maximum, this - // means we can replace it with a larger texture. - h = PApplet.min(2 * textures[lastTex].glHeight, maxSize); - resize = true; - } else { - h = minSize; - resize = false; - } - - Texture tex; - if (is3D) { - // Bilinear sampling ensures that the texture doesn't look pixelated - // either when it is magnified or minified... - tex = new Texture(pg, w, h, - new Texture.Parameters(ARGB, Texture.BILINEAR, false)); - } else { - // ...however, the effect of bilinear sampling is to add some blurriness - // to the text in its original size. In 2D, we assume that text will be - // shown at its original size, so linear sampling is chosen instead (which - // only affects minimized text). - tex = new Texture(pg, w, h, - new Texture.Parameters(ARGB, Texture.LINEAR, false)); - } - - if (textures == null) { - textures = new Texture[1]; - textures[0] = tex; - images = new PImage[1]; - images[0] = pg.wrapTexture(tex); - lastTex = 0; - } else if (resize) { - // Replacing old smaller texture with larger one. - // But first we must copy the contents of the older - // texture into the new one. - Texture tex0 = textures[lastTex]; - tex.put(tex0); - textures[lastTex] = tex; - - pg.setCache(images[lastTex], tex); - images[lastTex].width = tex.width; - images[lastTex].height = tex.height; - } else { - // Adding new texture to the list. - lastTex = textures.length; - Texture[] tempTex = new Texture[lastTex + 1]; - PApplet.arrayCopy(textures, tempTex, textures.length); - tempTex[lastTex] = tex; - textures = tempTex; - - PImage[] tempImg = new PImage[textures.length]; - PApplet.arrayCopy(images, tempImg, images.length); - tempImg[lastTex] = pg.wrapTexture(tex); - images = tempImg; - } - - // Make sure that the current texture is bound. - tex.bind(); - - return resize; - } - - - public void begin() { - } - - - public void end() { - for (int i = 0; i < textures.length; i++) { - pgl.disableTexturing(textures[i].glTarget); - } - } - - - public PImage getTexture(TextureInfo info) { - return images[info.texIndex]; - } - - - // Add all the current glyphs to opengl texture. - public void addAllGlyphsToTexture(PGraphicsOpenGL pg, PFont font) { - // loop over current glyphs. - for (int i = 0; i < font.getGlyphCount(); i++) { - addToTexture(pg, i, font.getGlyph(i)); - } - } - - - public void updateGlyphsTexCoords() { - // loop over current glyphs. - for (int i = 0; i < glyphTexinfos.length; i++) { - TextureInfo tinfo = glyphTexinfos[i]; - if (tinfo != null && tinfo.texIndex == lastTex) { - tinfo.updateUV(); - } - } - } - - - public TextureInfo getTexInfo(PFont.Glyph glyph) { - TextureInfo info = texinfoMap.get(glyph); - return info; - } - - - public TextureInfo addToTexture(PGraphicsOpenGL pg, PFont.Glyph glyph) { - int n = glyphTexinfos.length; - if (n == 0) { - glyphTexinfos = new TextureInfo[1]; - } - addToTexture(pg, n, glyph); - return glyphTexinfos[n]; - } - - - public boolean contextIsOutdated() { - boolean outdated = false; - for (int i = 0; i < textures.length; i++) { - if (textures[i].contextIsOutdated()) { - outdated = true; - } - } - if (outdated) { - for (int i = 0; i < textures.length; i++) { - textures[i].dispose(); - } - } - return outdated; - } - -// public void draw() { -// Texture tex = textures[lastTex]; -// pgl.drawTexture(tex.glTarget, tex.glName, -// tex.glWidth, tex.glHeight, -// 0, 0, tex.glWidth, tex.glHeight); -// } - - - // Adds this glyph to the opengl texture in PFont. - protected void addToTexture(PGraphicsOpenGL pg, int idx, PFont.Glyph glyph) { - // We add one pixel to avoid issues when sampling the font texture at - // fractional screen positions. I.e.: the pixel on the screen only contains - // half of the font rectangle, so it would sample half of the color from the - // glyph area in the texture, and the other half from the contiguous pixel. - // If the later contains a portion of the neighbor glyph and the former - // doesn't, this would result in a shaded pixel when the correct output is - // blank. This is a consequence of putting all the glyphs in a common - // texture with bilinear sampling. - int w = 1 + glyph.width + 1; - int h = 1 + glyph.height + 1; - - // Converting the pixels array from the PImage into a valid RGBA array for - // OpenGL. - int[] rgba = new int[w * h]; - int t = 0; - int p = 0; - if (PGL.BIG_ENDIAN) { - java.util.Arrays.fill(rgba, 0, w, 0xFFFFFF00); // Set the first row to blank pixels. - t = w; - for (int y = 0; y < glyph.height; y++) { - rgba[t++] = 0xFFFFFF00; // Set the leftmost pixel in this row as blank - for (int x = 0; x < glyph.width; x++) { - rgba[t++] = 0xFFFFFF00 | glyph.image.pixels[p++]; - } - rgba[t++] = 0xFFFFFF00; // Set the rightmost pixel in this row as blank - } - java.util.Arrays.fill(rgba, (h - 1) * w, h * w, 0xFFFFFF00); // Set the last row to blank pixels. - } else { - java.util.Arrays.fill(rgba, 0, w, 0x00FFFFFF); // Set the first row to blank pixels. - t = w; - for (int y = 0; y < glyph.height; y++) { - rgba[t++] = 0x00FFFFFF; // Set the leftmost pixel in this row as blank - for (int x = 0; x < glyph.width; x++) { - rgba[t++] = (glyph.image.pixels[p++] << 24) | 0x00FFFFFF; - } - rgba[t++] = 0x00FFFFFF; // Set the rightmost pixel in this row as blank - } - java.util.Arrays.fill(rgba, (h - 1) * w, h * w, 0x00FFFFFF); // Set the last row to blank pixels. - } - - // Is there room for this glyph in the current line? - if (offsetX + w > textures[lastTex].glWidth) { - // No room, go to the next line: - offsetX = 0; - offsetY += lineHeight; - } - lineHeight = Math.max(lineHeight, h); - - boolean resized = false; - if (offsetY + lineHeight > textures[lastTex].glHeight) { - // We run out of space in the current texture, so we add a new texture: - resized = addTexture(pg); - if (resized) { - // Because the current texture has been resized, we need to - // update the UV coordinates of all the glyphs associated to it: - updateGlyphsTexCoords(); - } else { - // A new texture has been created. Reseting texture coordinates - // and line. - offsetX = 0; - offsetY = 0; - lineHeight = 0; - } - } - - TextureInfo tinfo = new TextureInfo(lastTex, offsetX, offsetY, w, h, rgba); - offsetX += w; - - if (idx == glyphTexinfos.length) { - TextureInfo[] temp = new TextureInfo[glyphTexinfos.length + 1]; - System.arraycopy(glyphTexinfos, 0, temp, 0, glyphTexinfos.length); - glyphTexinfos = temp; - } - - glyphTexinfos[idx] = tinfo; - texinfoMap.put(glyph, tinfo); - } - - - class TextureInfo { - int texIndex; - int width; - int height; - int[] crop; - float u0, u1; - float v0, v1; - int[] pixels; - - TextureInfo(int tidx, int cropX, int cropY, int cropW, int cropH, - int[] pix) { - texIndex = tidx; - crop = new int[4]; - // The region of the texture corresponding to the glyph is surrounded by a - // 1-pixel wide border to avoid artifacts due to bilinear sampling. This - // is why the additions and subtractions to the crop values. - crop[0] = cropX + 1; - crop[1] = cropY + 1 + cropH - 2; - crop[2] = cropW - 2; - crop[3] = -cropH + 2; - pixels = pix; - updateUV(); - updateTex(); - } - - - void updateUV() { - width = textures[texIndex].glWidth; - height = textures[texIndex].glHeight; - - u0 = (float)crop[0] / (float)width; - u1 = u0 + (float)crop[2] / (float)width; - v0 = (float)(crop[1] + crop[3]) / (float)height; - v1 = v0 - (float)crop[3] / (float)height; - } - - - void updateTex() { - textures[texIndex].setNative(pixels, crop[0] - 1, crop[1] + crop[3] - 1, - crop[2] + 2, -crop[3] + 2); - } - } -} diff --git a/core/src/processing/opengl/FrameBuffer.java b/core/src/processing/opengl/FrameBuffer.java deleted file mode 100644 index a5426c52d..000000000 --- a/core/src/processing/opengl/FrameBuffer.java +++ /dev/null @@ -1,503 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import processing.core.PApplet; -import processing.core.PConstants; -import processing.opengl.PGraphicsOpenGL.GLResourceFrameBuffer; - -import java.nio.IntBuffer; - -/** - * Encapsulates a Frame Buffer Object for offscreen rendering. - * When created with onscreen == true, it represents the normal - * framebuffer. Needed by the stack mechanism in OPENGL2 to return - * to onscreen rendering after a sequence of pushFramebuffer calls. - * It transparently handles the situations when the FBO extension is - * not available. - * - * By Andres Colubri. - */ - -public class FrameBuffer implements PConstants { - protected PGraphicsOpenGL pg; - protected PGL pgl; - protected int context; // The context that created this framebuffer. - - public int glFbo; - public int glDepth; - public int glStencil; - public int glDepthStencil; - public int glMultisample; - public int width; - public int height; - private GLResourceFrameBuffer glres; - - protected int depthBits; - protected int stencilBits; - protected boolean packedDepthStencil; - - protected boolean multisample; - protected int nsamples; - - protected int numColorBuffers; - protected Texture[] colorBufferTex; - - protected boolean screenFb; - protected boolean noDepth; - - protected IntBuffer pixelBuffer; - - - FrameBuffer(PGraphicsOpenGL pg) { - this.pg = pg; - pgl = pg.pgl; - context = pgl.createEmptyContext(); - } - - - FrameBuffer(PGraphicsOpenGL pg, int w, int h, int samples, int colorBuffers, - int depthBits, int stencilBits, boolean packedDepthStencil, - boolean screen) { - this(pg); - - glFbo = 0; - glDepth = 0; - glStencil = 0; - glDepthStencil = 0; - glMultisample = 0; - - if (screen) { - // If this framebuffer is used to represent a on-screen buffer, - // then it doesn't make it sense for it to have multisampling, - // color, depth or stencil buffers. - depthBits = stencilBits = samples = colorBuffers = 0; - } - - width = w; - height = h; - - if (1 < samples) { - multisample = true; - nsamples = samples; - } else { - multisample = false; - nsamples = 1; - } - - numColorBuffers = colorBuffers; - colorBufferTex = new Texture[numColorBuffers]; - for (int i = 0; i < numColorBuffers; i++) { - colorBufferTex[i] = null; - } - - if (depthBits < 1 && stencilBits < 1) { - this.depthBits = 0; - this.stencilBits = 0; - this.packedDepthStencil = false; - } else { - if (packedDepthStencil) { - // When combined depth/stencil format is required, the depth and stencil - // bits are overriden and the 24/8 combination for a 32 bits surface is - // used. - this.depthBits = 24; - this.stencilBits = 8; - this.packedDepthStencil = true; - } else { - this.depthBits = depthBits; - this.stencilBits = stencilBits; - this.packedDepthStencil = false; - } - } - - screenFb = screen; - - allocate(); - noDepth = false; - - pixelBuffer = null; - } - - - FrameBuffer(PGraphicsOpenGL pg, int w, int h) { - this(pg, w, h, 1, 1, 0, 0, false, false); - } - - - FrameBuffer(PGraphicsOpenGL pg, int w, int h, boolean screen) { - this(pg, w, h, 1, 1, 0, 0, false, screen); - } - - - public void clear() { - pg.pushFramebuffer(); - pg.setFramebuffer(this); - pgl.clearDepth(1); - pgl.clearStencil(0); - pgl.clearColor(0, 0, 0, 0); - pgl.clear(PGL.DEPTH_BUFFER_BIT | - PGL.STENCIL_BUFFER_BIT | - PGL.COLOR_BUFFER_BIT); - pg.popFramebuffer(); - } - - public void copyColor(FrameBuffer dest) { - copy(dest, PGL.COLOR_BUFFER_BIT); - } - - public void copyDepth(FrameBuffer dest) { - copy(dest, PGL.DEPTH_BUFFER_BIT); - } - - public void copyStencil(FrameBuffer dest) { - copy(dest, PGL.STENCIL_BUFFER_BIT); - } - - public void copy(FrameBuffer dest, int mask) { - pgl.bindFramebufferImpl(PGL.READ_FRAMEBUFFER, this.glFbo); - pgl.bindFramebufferImpl(PGL.DRAW_FRAMEBUFFER, dest.glFbo); - pgl.blitFramebuffer(0, 0, this.width, this.height, - 0, 0, dest.width, dest.height, mask, PGL.NEAREST); - pgl.bindFramebufferImpl(PGL.READ_FRAMEBUFFER, pg.getCurrentFB().glFbo); - pgl.bindFramebufferImpl(PGL.DRAW_FRAMEBUFFER, pg.getCurrentFB().glFbo); - } - - public void bind() { - pgl.bindFramebufferImpl(PGL.FRAMEBUFFER, glFbo); - } - - public void disableDepthTest() { - noDepth = true; - } - - public void finish() { - if (noDepth) { - // No need to clear depth buffer because depth testing was disabled. - if (pg.getHint(ENABLE_DEPTH_TEST)) { - pgl.enable(PGL.DEPTH_TEST); - } else { - pgl.disable(PGL.DEPTH_TEST); - } - } - } - - public void readPixels() { - if (pixelBuffer == null) createPixelBuffer(); - pixelBuffer.rewind(); - pgl.readPixels(0, 0, width, height, PGL.RGBA, PGL.UNSIGNED_BYTE, - pixelBuffer); - } - - public void getPixels(int[] pixels) { - if (pixelBuffer != null) { - pixelBuffer.get(pixels, 0, pixels.length); - pixelBuffer.rewind(); - } - } - - public IntBuffer getPixelBuffer() { - return pixelBuffer; - } - - public boolean hasDepthBuffer() { - return 0 < depthBits; - } - - public boolean hasStencilBuffer() { - return 0 < stencilBits; - } - - public void setFBO(int id) { - if (screenFb) { - glFbo = id; - } - } - - /////////////////////////////////////////////////////////// - - // Color buffer setters. - - - public void setColorBuffer(Texture tex) { - setColorBuffers(new Texture[] { tex }, 1); - } - - - public void setColorBuffers(Texture[] textures) { - setColorBuffers(textures, textures.length); - } - - - public void setColorBuffers(Texture[] textures, int n) { - if (screenFb) return; - - if (numColorBuffers != PApplet.min(n, textures.length)) { - throw new RuntimeException("Wrong number of textures to set the color " + - "buffers."); - } - - for (int i = 0; i < numColorBuffers; i++) { - colorBufferTex[i] = textures[i]; - } - - pg.pushFramebuffer(); - pg.setFramebuffer(this); - - // Making sure nothing is attached. - for (int i = 0; i < numColorBuffers; i++) { - pgl.framebufferTexture2D(PGL.FRAMEBUFFER, PGL.COLOR_ATTACHMENT0 + i, - PGL.TEXTURE_2D, 0, 0); - } - - for (int i = 0; i < numColorBuffers; i++) { - pgl.framebufferTexture2D(PGL.FRAMEBUFFER, PGL.COLOR_ATTACHMENT0 + i, - colorBufferTex[i].glTarget, - colorBufferTex[i].glName, 0); - } - - pgl.validateFramebuffer(); - - pg.popFramebuffer(); - } - - - public void swapColorBuffers() { - for (int i = 0; i < numColorBuffers - 1; i++) { - int i1 = (i + 1); - Texture tmp = colorBufferTex[i]; - colorBufferTex[i] = colorBufferTex[i1]; - colorBufferTex[i1] = tmp; - } - - pg.pushFramebuffer(); - pg.setFramebuffer(this); - for (int i = 0; i < numColorBuffers; i++) { - pgl.framebufferTexture2D(PGL.FRAMEBUFFER, PGL.COLOR_ATTACHMENT0 + i, - colorBufferTex[i].glTarget, - colorBufferTex[i].glName, 0); - } - pgl.validateFramebuffer(); - - pg.popFramebuffer(); - } - - - public int getDefaultReadBuffer() { - if (screenFb) { - return pgl.getDefaultReadBuffer(); - } else { - return PGL.COLOR_ATTACHMENT0; - } - } - - - public int getDefaultDrawBuffer() { - if (screenFb) { - return pgl.getDefaultDrawBuffer(); - } else { - return PGL.COLOR_ATTACHMENT0; - } - } - - - /////////////////////////////////////////////////////////// - - // Allocate/release framebuffer. - - - protected void allocate() { - dispose(); // Just in the case this object is being re-allocated. - - context = pgl.getCurrentContext(); - glres = new GLResourceFrameBuffer(this); // create the FBO resources... - - if (screenFb) { - glFbo = 0; - } else { - if (multisample) { - initColorBufferMultisample(); - } - - if (packedDepthStencil) { - initPackedDepthStencilBuffer(); - } else { - if (0 < depthBits) { - initDepthBuffer(); - } - if (0 < stencilBits) { - initStencilBuffer(); - } - } - } - } - - - protected void dispose() { - if (screenFb) return; - if (glres != null) { - glres.dispose(); - glFbo = 0; - glDepth = 0; - glStencil = 0; - glMultisample = 0; - glDepthStencil = 0; - glres = null; - } - } - - - protected boolean contextIsOutdated() { - if (screenFb) return false; - - boolean outdated = !pgl.contextIsCurrent(context); - if (outdated) { - dispose(); - for (int i = 0; i < numColorBuffers; i++) { - colorBufferTex[i] = null; - } - } - return outdated; - } - - - protected void initColorBufferMultisample() { - if (screenFb) return; - - pg.pushFramebuffer(); - pg.setFramebuffer(this); - - pgl.bindRenderbuffer(PGL.RENDERBUFFER, glMultisample); - pgl.renderbufferStorageMultisample(PGL.RENDERBUFFER, nsamples, - PGL.RGBA8, width, height); - pgl.framebufferRenderbuffer(PGL.FRAMEBUFFER, PGL.COLOR_ATTACHMENT0, - PGL.RENDERBUFFER, glMultisample); - - pg.popFramebuffer(); - } - - - protected void initPackedDepthStencilBuffer() { - if (screenFb) return; - - if (width == 0 || height == 0) { - throw new RuntimeException("PFramebuffer: size undefined."); - } - - pg.pushFramebuffer(); - pg.setFramebuffer(this); - - pgl.bindRenderbuffer(PGL.RENDERBUFFER, glDepthStencil); - - if (multisample) { - pgl.renderbufferStorageMultisample(PGL.RENDERBUFFER, nsamples, - PGL.DEPTH24_STENCIL8, width, height); - } else { - pgl.renderbufferStorage(PGL.RENDERBUFFER, PGL.DEPTH24_STENCIL8, - width, height); - } - - pgl.framebufferRenderbuffer(PGL.FRAMEBUFFER, PGL.DEPTH_ATTACHMENT, - PGL.RENDERBUFFER, glDepthStencil); - pgl.framebufferRenderbuffer(PGL.FRAMEBUFFER, PGL.STENCIL_ATTACHMENT, - PGL.RENDERBUFFER, glDepthStencil); - - pg.popFramebuffer(); - } - - - protected void initDepthBuffer() { - if (screenFb) return; - - if (width == 0 || height == 0) { - throw new RuntimeException("PFramebuffer: size undefined."); - } - - pg.pushFramebuffer(); - pg.setFramebuffer(this); - - pgl.bindRenderbuffer(PGL.RENDERBUFFER, glDepth); - - int glConst = PGL.DEPTH_COMPONENT16; - if (depthBits == 16) { - glConst = PGL.DEPTH_COMPONENT16; - } else if (depthBits == 24) { - glConst = PGL.DEPTH_COMPONENT24; - } else if (depthBits == 32) { - glConst = PGL.DEPTH_COMPONENT32; - } - - if (multisample) { - pgl.renderbufferStorageMultisample(PGL.RENDERBUFFER, nsamples, glConst, - width, height); - } else { - pgl.renderbufferStorage(PGL.RENDERBUFFER, glConst, width, height); - } - - pgl.framebufferRenderbuffer(PGL.FRAMEBUFFER, PGL.DEPTH_ATTACHMENT, - PGL.RENDERBUFFER, glDepth); - - pg.popFramebuffer(); - } - - - protected void initStencilBuffer() { - if (screenFb) return; - - if (width == 0 || height == 0) { - throw new RuntimeException("PFramebuffer: size undefined."); - } - - pg.pushFramebuffer(); - pg.setFramebuffer(this); - - pgl.bindRenderbuffer(PGL.RENDERBUFFER, glStencil); - - int glConst = PGL.STENCIL_INDEX1; - if (stencilBits == 1) { - glConst = PGL.STENCIL_INDEX1; - } else if (stencilBits == 4) { - glConst = PGL.STENCIL_INDEX4; - } else if (stencilBits == 8) { - glConst = PGL.STENCIL_INDEX8; - } - if (multisample) { - pgl.renderbufferStorageMultisample(PGL.RENDERBUFFER, nsamples, glConst, - width, height); - } else { - pgl.renderbufferStorage(PGL.RENDERBUFFER, glConst, width, height); - } - - pgl.framebufferRenderbuffer(PGL.FRAMEBUFFER, PGL.STENCIL_ATTACHMENT, - PGL.RENDERBUFFER, glStencil); - - pg.popFramebuffer(); - } - - - protected void createPixelBuffer() { - pixelBuffer = IntBuffer.allocate(width * height); - pixelBuffer.rewind(); - } -} diff --git a/core/src/processing/opengl/LinePath.java b/core/src/processing/opengl/LinePath.java deleted file mode 100644 index 6e86431a7..000000000 --- a/core/src/processing/opengl/LinePath.java +++ /dev/null @@ -1,623 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package processing.opengl; - -import processing.core.PMatrix2D; - -/** - * The {@code LinePath} class allows to represent polygonal paths, - * potentially composed by several disjoint polygonal segments. - * It can be iterated by the {@link PathIterator} class including all - * of its segment types and winding rules - * - */ -public class LinePath { - /** - * The winding rule constant for specifying an even-odd rule - * for determining the interior of a path. - * The even-odd rule specifies that a point lies inside the - * path if a ray drawn in any direction from that point to - * infinity is crossed by path segments an odd number of times. - */ - public static final int WIND_EVEN_ODD = 0; - - /** - * The winding rule constant for specifying a non-zero rule - * for determining the interior of a path. - * The non-zero rule specifies that a point lies inside the - * path if a ray drawn in any direction from that point to - * infinity is crossed by path segments a different number - * of times in the counter-clockwise direction than the - * clockwise direction. - */ - public static final int WIND_NON_ZERO = 1; - - /** - * Starts segment at a given position. - */ - public static final byte SEG_MOVETO = 0; - - /** - * Extends segment by adding a line to a given position. - */ - public static final byte SEG_LINETO = 1; - - /** - * Closes segment at current position. - */ - public static final byte SEG_CLOSE = 2; - - /** - * Joins path segments by extending their outside edges until they meet. - */ - public final static int JOIN_MITER = 0; - - /** - * Joins path segments by rounding off the corner at a radius of half the line - * width. - */ - public final static int JOIN_ROUND = 1; - - /** - * Joins path segments by connecting the outer corners of their wide outlines - * with a straight segment. - */ - public final static int JOIN_BEVEL = 2; - - /** - * Ends unclosed subpaths and dash segments with no added decoration. - */ - public final static int CAP_BUTT = 0; - - /** - * Ends unclosed subpaths and dash segments with a round decoration that has a - * radius equal to half of the width of the pen. - */ - public final static int CAP_ROUND = 1; - - /** - * Ends unclosed subpaths and dash segments with a square projection that - * extends beyond the end of the segment to a distance equal to half of the - * line width. - */ - public final static int CAP_SQUARE = 2; - - private static PMatrix2D identity = new PMatrix2D(); - - private static float defaultMiterlimit = 10.0f; - - static final int INIT_SIZE = 20; - - static final int EXPAND_MAX = 500; - - protected byte[] pointTypes; - - protected float[] floatCoords; - - protected int[] pointColors; - - protected int numTypes; - - protected int numCoords; - - protected int windingRule; - - - /** - * Constructs a new empty single precision {@code LinePath} object with a - * default winding rule of {@link #WIND_NON_ZERO}. - */ - public LinePath() { - this(WIND_NON_ZERO, INIT_SIZE); - } - - - /** - * Constructs a new empty single precision {@code LinePath} object with the - * specified winding rule to control operations that require the interior of - * the path to be defined. - * - * @param rule - * the winding rule - * @see #WIND_EVEN_ODD - * @see #WIND_NON_ZERO - */ - public LinePath(int rule) { - this(rule, INIT_SIZE); - } - - - /** - * Constructs a new {@code LinePath} object from the given specified initial - * values. This method is only intended for internal use and should not be - * made public if the other constructors for this class are ever exposed. - * - * @param rule - * the winding rule - * @param initialTypes - * the size to make the initial array to store the path segment types - */ - public LinePath(int rule, int initialCapacity) { - setWindingRule(rule); - this.pointTypes = new byte[initialCapacity]; - floatCoords = new float[initialCapacity * 2]; - pointColors = new int[initialCapacity]; - } - - - void needRoom(boolean needMove, int newPoints) { - if (needMove && numTypes == 0) { - throw new RuntimeException("missing initial moveto " - + "in path definition"); - } - int size = pointTypes.length; - if (numTypes >= size) { - int grow = size; - if (grow > EXPAND_MAX) { - grow = EXPAND_MAX; - } - pointTypes = copyOf(pointTypes, size + grow); - } - size = floatCoords.length; - if (numCoords + newPoints * 2 > size) { - int grow = size; - if (grow > EXPAND_MAX * 2) { - grow = EXPAND_MAX * 2; - } - if (grow < newPoints * 2) { - grow = newPoints * 2; - } - floatCoords = copyOf(floatCoords, size + grow); - } - size = pointColors.length; - if (numCoords/2 + newPoints > size) { - int grow = size; - if (grow > EXPAND_MAX) { - grow = EXPAND_MAX; - } - if (grow < newPoints) { - grow = newPoints; - } - pointColors = copyOf(pointColors, size + grow); - } - } - - - /** - * Adds a point to the path by moving to the specified coordinates specified - * in float precision. - *

    - * This method provides a single precision variant of the double precision - * {@code moveTo()} method on the base {@code LinePath} class. - * - * @param x - * the specified X coordinate - * @param y - * the specified Y coordinate - * @see LinePath#moveTo - */ - public final void moveTo(float x, float y, int c) { - if (numTypes > 0 && pointTypes[numTypes - 1] == SEG_MOVETO) { - floatCoords[numCoords - 2] = x; - floatCoords[numCoords - 1] = y; - pointColors[numCoords/2-1] = c; - } else { - needRoom(false, 1); - pointTypes[numTypes++] = SEG_MOVETO; - floatCoords[numCoords++] = x; - floatCoords[numCoords++] = y; - pointColors[numCoords/2-1] = c; - } - } - - - /** - * Adds a point to the path by drawing a straight line from the current - * coordinates to the new specified coordinates specified in float precision. - *

    - * This method provides a single precision variant of the double precision - * {@code lineTo()} method on the base {@code LinePath} class. - * - * @param x - * the specified X coordinate - * @param y - * the specified Y coordinate - * @see LinePath#lineTo - */ - public final void lineTo(float x, float y, int c) { - needRoom(true, 1); - pointTypes[numTypes++] = SEG_LINETO; - floatCoords[numCoords++] = x; - floatCoords[numCoords++] = y; - pointColors[numCoords/2-1] = c; - } - - - /** - * The iterator for this class is not multi-threaded safe, which means that - * the {@code LinePath} class does not guarantee that modifications to the - * geometry of this {@code LinePath} object do not affect any iterations of that - * geometry that are already in process. - */ - public PathIterator getPathIterator() { - return new PathIterator(this); - } - - - /** - * Closes the current subpath by drawing a straight line back to the - * coordinates of the last {@code moveTo}. If the path is already closed then - * this method has no effect. - */ - public final void closePath() { - if (numTypes == 0 || pointTypes[numTypes - 1] != SEG_CLOSE) { - needRoom(false, 0); - pointTypes[numTypes++] = SEG_CLOSE; - } - } - - - /** - * Returns the fill style winding rule. - * - * @return an integer representing the current winding rule. - * @see #WIND_EVEN_ODD - * @see #WIND_NON_ZERO - * @see #setWindingRule - */ - public final int getWindingRule() { - return windingRule; - } - - - /** - * Sets the winding rule for this path to the specified value. - * - * @param rule - * an integer representing the specified winding rule - * @exception IllegalArgumentException - * if {@code rule} is not either {@link #WIND_EVEN_ODD} or - * {@link #WIND_NON_ZERO} - * @see #getWindingRule - */ - public final void setWindingRule(int rule) { - if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) { - throw new IllegalArgumentException("winding rule must be " - + "WIND_EVEN_ODD or " + "WIND_NON_ZERO"); - } - windingRule = rule; - } - - - /** - * Resets the path to empty. The append position is set back to the beginning - * of the path and all coordinates and point types are forgotten. - */ - public final void reset() { - numTypes = numCoords = 0; - } - - - static public class PathIterator { - float floatCoords[]; - - int typeIdx; - - int pointIdx; - - int colorIdx; - - LinePath path; - - static final int curvecoords[] = { 2, 2, 0 }; - - PathIterator(LinePath p2df) { - this.path = p2df; - this.floatCoords = p2df.floatCoords; - pointIdx = 0; - colorIdx = 0; - } - - public int currentSegment(float[] coords) { - int type = path.pointTypes[typeIdx]; - int numCoords = curvecoords[type]; - if (numCoords > 0) { - System.arraycopy(floatCoords, pointIdx, coords, 0, numCoords); - int color = path.pointColors[colorIdx]; - coords[numCoords + 0] = (color >> 24) & 0xFF; - coords[numCoords + 1] = (color >> 16) & 0xFF; - coords[numCoords + 2] = (color >> 8) & 0xFF; - coords[numCoords + 3] = (color >> 0) & 0xFF; - } - return type; - } - - public int currentSegment(double[] coords) { - int type = path.pointTypes[typeIdx]; - int numCoords = curvecoords[type]; - if (numCoords > 0) { - for (int i = 0; i < numCoords; i++) { - coords[i] = floatCoords[pointIdx + i]; - } - int color = path.pointColors[colorIdx]; - coords[numCoords + 0] = (color >> 24) & 0xFF; - coords[numCoords + 1] = (color >> 16) & 0xFF; - coords[numCoords + 2] = (color >> 8) & 0xFF; - coords[numCoords + 3] = (color >> 0) & 0xFF; - } - return type; - } - - public int getWindingRule() { - return path.getWindingRule(); - } - - public boolean isDone() { - return (typeIdx >= path.numTypes); - } - - public void next() { - int type = path.pointTypes[typeIdx++]; - if (0 < curvecoords[type]) { - pointIdx += curvecoords[type]; - colorIdx++; - } - } - } - - - ///////////////////////////////////////////////////////////////////////////// - // - // Stroked path methods - - - static public LinePath createStrokedPath(LinePath src, float weight, - int caps, int join) { - return createStrokedPath(src, weight, caps, join, defaultMiterlimit, null); - } - - - static public LinePath createStrokedPath(LinePath src, float weight, - int caps, int join, float miterlimit) { - return createStrokedPath(src, weight, caps, join, miterlimit, null); - } - - - /** - * Constructs a solid LinePath with the specified attributes. - * - * @param src - * the original path to be stroked - * @param weight - * the weight of the stroked path - * @param cap - * the decoration of the ends of the segments in the path - * @param join - * the decoration applied where path segments meet - * @param miterlimit - * @param transform - * - */ - static public LinePath createStrokedPath(LinePath src, float weight, - int caps, int join, - float miterlimit, PMatrix2D transform) { - final LinePath dest = new LinePath(); - - strokeTo(src, weight, caps, join, miterlimit, transform, new LineStroker() { - @Override - public void moveTo(int x0, int y0, int c0) { - dest.moveTo(S15_16ToFloat(x0), S15_16ToFloat(y0), c0); - } - - @Override - public void lineJoin() { - } - - @Override - public void lineTo(int x1, int y1, int c1) { - dest.lineTo(S15_16ToFloat(x1), S15_16ToFloat(y1), c1); - } - - @Override - public void close() { - dest.closePath(); - } - - @Override - public void end() { - } - }); - - return dest; - } - - - private static void strokeTo(LinePath src, float width, int caps, int join, - float miterlimit, PMatrix2D transform, - LineStroker lsink) { - lsink = new LineStroker(lsink, FloatToS15_16(width), caps, join, - FloatToS15_16(miterlimit), - transform == null ? identity : transform); - - PathIterator pi = src.getPathIterator(); - pathTo(pi, lsink); - } - - - private static void pathTo(PathIterator pi, LineStroker lsink) { - float coords[] = new float[6]; - while (!pi.isDone()) { - int color; - switch (pi.currentSegment(coords)) { - case SEG_MOVETO: - color = ((int)coords[2]<<24) | - ((int)coords[3]<<16) | - ((int)coords[4]<< 8) | - (int)coords[5]; - lsink.moveTo(FloatToS15_16(coords[0]), FloatToS15_16(coords[1]), color); - break; - case SEG_LINETO: - color = ((int)coords[2]<<24) | - ((int)coords[3]<<16) | - ((int)coords[4]<< 8) | - (int)coords[5]; - lsink.lineJoin(); - lsink.lineTo(FloatToS15_16(coords[0]), FloatToS15_16(coords[1]), color); - break; - case SEG_CLOSE: - lsink.lineJoin(); - lsink.close(); - break; - default: - throw new InternalError("unknown flattened segment type"); - } - pi.next(); - } - lsink.end(); - } - - - ///////////////////////////////////////////////////////////////////////////// - // - // Utility methods - - - public static float[] copyOf(float[] source, int length) { - float[] target = new float[length]; - for (int i = 0; i < target.length; i++) { - if (i > source.length - 1) - target[i] = 0f; - else - target[i] = source[i]; - } - return target; - } - - - public static byte[] copyOf(byte[] source, int length) { - byte[] target = new byte[length]; - for (int i = 0; i < target.length; i++) { - if (i > source.length - 1) - target[i] = 0; - else - target[i] = source[i]; - } - return target; - } - - - public static int[] copyOf(int[] source, int length) { - int[] target = new int[length]; - for (int i = 0; i < target.length; i++) { - if (i > source.length - 1) - target[i] = 0; - else - target[i] = source[i]; - } - return target; - } - - - // From Ken Turkowski, _Fixed-Point Square Root_, In Graphics Gems V - public static int isqrt(int x) { - int fracbits = 16; - - int root = 0; - int remHi = 0; - int remLo = x; - int count = 15 + fracbits / 2; - - do { - remHi = (remHi << 2) | (remLo >>> 30); // N.B. - unsigned shift R - remLo <<= 2; - root <<= 1; - int testdiv = (root << 1) + 1; - if (remHi >= testdiv) { - remHi -= testdiv; - root++; - } - } while (count-- != 0); - - return root; - } - - - public static long lsqrt(long x) { - int fracbits = 16; - - long root = 0; - long remHi = 0; - long remLo = x; - int count = 31 + fracbits / 2; - - do { - remHi = (remHi << 2) | (remLo >>> 62); // N.B. - unsigned shift R - remLo <<= 2; - root <<= 1; - long testDiv = (root << 1) + 1; - if (remHi >= testDiv) { - remHi -= testDiv; - root++; - } - } while (count-- != 0); - - return root; - } - - - public static double hypot(double x, double y) { - return Math.sqrt(x * x + y * y); - } - - - public static int hypot(int x, int y) { - return (int) ((lsqrt((long) x * x + (long) y * y) + 128) >> 8); - } - - - public static long hypot(long x, long y) { - return (lsqrt(x * x + y * y) + 128) >> 8; - } - - - static int FloatToS15_16(float flt) { - flt = flt * 65536f + 0.5f; - if (flt <= -(65536f * 65536f)) { - return Integer.MIN_VALUE; - } else if (flt >= (65536f * 65536f)) { - return Integer.MAX_VALUE; - } else { - return (int) Math.floor(flt); - } - } - - - static float S15_16ToFloat(int fix) { - return (fix / 65536f); - } -} diff --git a/core/src/processing/opengl/LineStroker.java b/core/src/processing/opengl/LineStroker.java deleted file mode 100644 index ee6b20910..000000000 --- a/core/src/processing/opengl/LineStroker.java +++ /dev/null @@ -1,685 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package processing.opengl; - -import processing.core.PMatrix2D; - -public class LineStroker { - private LineStroker output; - private int capStyle; - private int joinStyle; - private int m00, m01; - private int m10, m11; - private int lineWidth2; - private long scaledLineWidth2; - - // For any pen offset (pen_dx, pen_dy) that does not depend on - // the line orientation, the pen should be transformed so that: - // - // pen_dx' = m00*pen_dx + m01*pen_dy - // pen_dy' = m10*pen_dx + m11*pen_dy - // - // For a round pen, this means: - // - // pen_dx(r, theta) = r*cos(theta) - // pen_dy(r, theta) = r*sin(theta) - // - // pen_dx'(r, theta) = r*(m00*cos(theta) + m01*sin(theta)) - // pen_dy'(r, theta) = r*(m10*cos(theta) + m11*sin(theta)) - private int numPenSegments; - private int[] pen_dx; - private int[] pen_dy; - - private boolean[] penIncluded; - private int[] join; - private int[] offset = new int[2]; - private int[] reverse = new int[100]; - private int[] miter = new int[2]; - private long miterLimitSq; - private int prev; - private int rindex; - private boolean started; - private boolean lineToOrigin; - private boolean joinToOrigin; - private int sx0, sy0, sx1, sy1, x0, y0; - private int scolor0, pcolor0, color0; - private int mx0, my0, omx, omy; - private int px0, py0; - private double m00_2_m01_2; - private double m10_2_m11_2; - private double m00_m10_m01_m11; - - /** - * Empty constructor. setOutput and setParameters - * must be called prior to calling any other methods. - */ - public LineStroker() { - } - - /** - * Constructs a LineStroker. - * - * @param output - * an output LineStroker. - * @param lineWidth - * the desired line width in pixels, in S15.16 format. - * @param capStyle - * the desired end cap style, one of CAP_BUTT, - * CAP_ROUND or CAP_SQUARE. - * @param joinStyle - * the desired line join style, one of JOIN_MITER, - * JOIN_ROUND or JOIN_BEVEL. - * @param miterLimit - * the desired miter limit, in S15.16 format. - * @param transform - * a Transform4 object indicating the transform that has - * been previously applied to all incoming coordinates. This is - * required in order to produce consistently shaped end caps and - * joins. - */ - public LineStroker(LineStroker output, int lineWidth, int capStyle, int joinStyle, - int miterLimit, PMatrix2D transform) { - setOutput(output); - setParameters(lineWidth, capStyle, joinStyle, miterLimit, transform); - } - - /** - * Sets the output LineStroker of this LineStroker. - * - * @param output - * an output LineStroker. - */ - public void setOutput(LineStroker output) { - this.output = output; - } - - /** - * Sets the parameters of this LineStroker. - * - * @param lineWidth - * the desired line width in pixels, in S15.16 format. - * @param capStyle - * the desired end cap style, one of CAP_BUTT, - * CAP_ROUND or CAP_SQUARE. - * @param joinStyle - * the desired line join style, one of JOIN_MITER, - * JOIN_ROUND or JOIN_BEVEL. - * @param miterLimit - * the desired miter limit, in S15.16 format. - * @param transform - * a Transform4 object indicating the transform that has - * been previously applied to all incoming coordinates. This is - * required in order to produce consistently shaped end caps and - * joins. - */ - public void setParameters(int lineWidth, int capStyle, int joinStyle, - int miterLimit, PMatrix2D transform) { - this.m00 = LinePath.FloatToS15_16(transform.m00); - this.m01 = LinePath.FloatToS15_16(transform.m01); - this.m10 = LinePath.FloatToS15_16(transform.m10); - this.m11 = LinePath.FloatToS15_16(transform.m11); - - this.lineWidth2 = lineWidth >> 1; - this.scaledLineWidth2 = ((long) m00 * lineWidth2) >> 16; - this.capStyle = capStyle; - this.joinStyle = joinStyle; - - this.m00_2_m01_2 = (double) m00 * m00 + (double) m01 * m01; - this.m10_2_m11_2 = (double) m10 * m10 + (double) m11 * m11; - this.m00_m10_m01_m11 = (double) m00 * m10 + (double) m01 * m11; - - double dm00 = m00 / 65536.0; - double dm01 = m01 / 65536.0; - double dm10 = m10 / 65536.0; - double dm11 = m11 / 65536.0; - double determinant = dm00 * dm11 - dm01 * dm10; - - if (joinStyle == LinePath.JOIN_MITER) { - double limit = (miterLimit / 65536.0) * (lineWidth2 / 65536.0) - * determinant; - double limitSq = limit * limit; - this.miterLimitSq = (long) (limitSq * 65536.0 * 65536.0); - } - - this.numPenSegments = (int) (3.14159f * lineWidth / 65536.0f); - if (pen_dx == null || pen_dx.length < numPenSegments) { - this.pen_dx = new int[numPenSegments]; - this.pen_dy = new int[numPenSegments]; - this.penIncluded = new boolean[numPenSegments]; - this.join = new int[2 * numPenSegments]; - } - - for (int i = 0; i < numPenSegments; i++) { - double r = lineWidth / 2.0; - double theta = i * 2 * Math.PI / numPenSegments; - - double cos = Math.cos(theta); - double sin = Math.sin(theta); - pen_dx[i] = (int) (r * (dm00 * cos + dm01 * sin)); - pen_dy[i] = (int) (r * (dm10 * cos + dm11 * sin)); - } - - prev = LinePath.SEG_CLOSE; - rindex = 0; - started = false; - lineToOrigin = false; - } - - private void computeOffset(int x0, int y0, int x1, int y1, int[] m) { - long lx = (long) x1 - (long) x0; - long ly = (long) y1 - (long) y0; - - int dx, dy; - if (m00 > 0 && m00 == m11 && m01 == 0 & m10 == 0) { - long ilen = LinePath.hypot(lx, ly); - if (ilen == 0) { - dx = dy = 0; - } else { - dx = (int) ((ly * scaledLineWidth2) / ilen); - dy = (int) (-(lx * scaledLineWidth2) / ilen); - } - } else { - double dlx = x1 - x0; - double dly = y1 - y0; - double det = (double) m00 * m11 - (double) m01 * m10; - int sdet = (det > 0) ? 1 : -1; - double a = dly * m00 - dlx * m10; - double b = dly * m01 - dlx * m11; - double dh = LinePath.hypot(a, b); - double div = sdet * lineWidth2 / (65536.0 * dh); - double ddx = dly * m00_2_m01_2 - dlx * m00_m10_m01_m11; - double ddy = dly * m00_m10_m01_m11 - dlx * m10_2_m11_2; - dx = (int) (ddx * div); - dy = (int) (ddy * div); - } - - m[0] = dx; - m[1] = dy; - } - - private void ensureCapacity(int newrindex) { - if (reverse.length < newrindex) { - int[] tmp = new int[Math.max(newrindex, 6 * reverse.length / 5)]; - System.arraycopy(reverse, 0, tmp, 0, rindex); - this.reverse = tmp; - } - } - - private boolean isCCW(int x0, int y0, int x1, int y1, int x2, int y2) { - int dx0 = x1 - x0; - int dy0 = y1 - y0; - int dx1 = x2 - x1; - int dy1 = y2 - y1; - return (long) dx0 * dy1 < (long) dy0 * dx1; - } - - private boolean side(int x, int y, int x0, int y0, int x1, int y1) { - long lx = x; - long ly = y; - long lx0 = x0; - long ly0 = y0; - long lx1 = x1; - long ly1 = y1; - - return (ly0 - ly1) * lx + (lx1 - lx0) * ly + (lx0 * ly1 - lx1 * ly0) > 0; - } - - private int computeRoundJoin(int cx, int cy, int xa, int ya, int xb, int yb, - int side, boolean flip, int[] join) { - int px, py; - int ncoords = 0; - - boolean centerSide; - if (side == 0) { - centerSide = side(cx, cy, xa, ya, xb, yb); - } else { - centerSide = (side == 1) ? true : false; - } - for (int i = 0; i < numPenSegments; i++) { - px = cx + pen_dx[i]; - py = cy + pen_dy[i]; - - boolean penSide = side(px, py, xa, ya, xb, yb); - if (penSide != centerSide) { - penIncluded[i] = true; - } else { - penIncluded[i] = false; - } - } - - int start = -1, end = -1; - for (int i = 0; i < numPenSegments; i++) { - if (penIncluded[i] - && !penIncluded[(i + numPenSegments - 1) % numPenSegments]) { - start = i; - } - if (penIncluded[i] && !penIncluded[(i + 1) % numPenSegments]) { - end = i; - } - } - - if (end < start) { - end += numPenSegments; - } - - if (start != -1 && end != -1) { - long dxa = cx + pen_dx[start] - xa; - long dya = cy + pen_dy[start] - ya; - long dxb = cx + pen_dx[start] - xb; - long dyb = cy + pen_dy[start] - yb; - - boolean rev = (dxa * dxa + dya * dya > dxb * dxb + dyb * dyb); - int i = rev ? end : start; - int incr = rev ? -1 : 1; - while (true) { - int idx = i % numPenSegments; - px = cx + pen_dx[idx]; - py = cy + pen_dy[idx]; - join[ncoords++] = px; - join[ncoords++] = py; - if (i == (rev ? start : end)) { - break; - } - i += incr; - } - } - - return ncoords / 2; - } - - //private static final long ROUND_JOIN_THRESHOLD = 1000L; - private static final long ROUND_JOIN_THRESHOLD = 100000000L; - - private static final long ROUND_JOIN_INTERNAL_THRESHOLD = 1000000000L; - - private void drawRoundJoin(int x, int y, int omx, int omy, int mx, int my, - int side, int color, - boolean flip, boolean rev, long threshold) { - if ((omx == 0 && omy == 0) || (mx == 0 && my == 0)) { - return; - } - - long domx = (long) omx - mx; - long domy = (long) omy - my; - long len = domx * domx + domy * domy; - if (len < threshold) { - return; - } - - if (rev) { - omx = -omx; - omy = -omy; - mx = -mx; - my = -my; - } - - int bx0 = x + omx; - int by0 = y + omy; - int bx1 = x + mx; - int by1 = y + my; - - int npoints = computeRoundJoin(x, y, bx0, by0, bx1, by1, side, flip, join); - for (int i = 0; i < npoints; i++) { - emitLineTo(join[2 * i], join[2 * i + 1], color, rev); - } - } - - // Return the intersection point of the lines (ix0, iy0) -> (ix1, iy1) - // and (ix0p, iy0p) -> (ix1p, iy1p) in m[0] and m[1] - private void computeMiter(int ix0, int iy0, int ix1, int iy1, int ix0p, - int iy0p, int ix1p, int iy1p, int[] m) { - long x0 = ix0; - long y0 = iy0; - long x1 = ix1; - long y1 = iy1; - - long x0p = ix0p; - long y0p = iy0p; - long x1p = ix1p; - long y1p = iy1p; - - long x10 = x1 - x0; - long y10 = y1 - y0; - long x10p = x1p - x0p; - long y10p = y1p - y0p; - - long den = (x10 * y10p - x10p * y10) >> 16; - if (den == 0) { - m[0] = ix0; - m[1] = iy0; - return; - } - - long t = (x1p * (y0 - y0p) - x0 * y10p + x0p * (y1p - y0)) >> 16; - m[0] = (int) (x0 + (t * x10) / den); - m[1] = (int) (y0 + (t * y10) / den); - } - - private void drawMiter(int px0, int py0, int x0, int y0, int x1, int y1, - int omx, int omy, int mx, int my, int color, - boolean rev) { - if (mx == omx && my == omy) { - return; - } - if (px0 == x0 && py0 == y0) { - return; - } - if (x0 == x1 && y0 == y1) { - return; - } - - if (rev) { - omx = -omx; - omy = -omy; - mx = -mx; - my = -my; - } - - computeMiter(px0 + omx, py0 + omy, x0 + omx, y0 + omy, x0 + mx, y0 + my, x1 - + mx, y1 + my, miter); - - // Compute miter length in untransformed coordinates - long dx = (long) miter[0] - x0; - long dy = (long) miter[1] - y0; - long a = (dy * m00 - dx * m10) >> 16; - long b = (dy * m01 - dx * m11) >> 16; - long lenSq = a * a + b * b; - - if (lenSq < miterLimitSq) { - emitLineTo(miter[0], miter[1], color, rev); - } - } - - public void moveTo(int x0, int y0, int c0) { - // System.out.println("LineStroker.moveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")"); - - if (lineToOrigin) { - // not closing the path, do the previous lineTo - lineToImpl(sx0, sy0, scolor0, joinToOrigin); - lineToOrigin = false; - } - - if (prev == LinePath.SEG_LINETO) { - finish(); - } - - this.sx0 = this.x0 = x0; - this.sy0 = this.y0 = y0; - this.scolor0 = this.color0 = c0; - this.rindex = 0; - this.started = false; - this.joinSegment = false; - this.prev = LinePath.SEG_MOVETO; - } - - boolean joinSegment = false; - - public void lineJoin() { - // System.out.println("LineStroker.lineJoin()"); - this.joinSegment = true; - } - - public void lineTo(int x1, int y1, int c1) { - // System.out.println("LineStroker.lineTo(" + x1/65536.0 + ", " + y1/65536.0 + ")"); - - if (lineToOrigin) { - if (x1 == sx0 && y1 == sy0) { - // staying in the starting point - return; - } - - // not closing the path, do the previous lineTo - lineToImpl(sx0, sy0, scolor0, joinToOrigin); - lineToOrigin = false; - } else if (x1 == x0 && y1 == y0) { - return; - } else if (x1 == sx0 && y1 == sy0) { - lineToOrigin = true; - joinToOrigin = joinSegment; - joinSegment = false; - return; - } - - lineToImpl(x1, y1, c1, joinSegment); - joinSegment = false; - } - - private void lineToImpl(int x1, int y1, int c1, boolean joinSegment) { - computeOffset(x0, y0, x1, y1, offset); - int mx = offset[0]; - int my = offset[1]; - - if (!started) { - emitMoveTo(x0 + mx, y0 + my, color0); - this.sx1 = x1; - this.sy1 = y1; - this.mx0 = mx; - this.my0 = my; - started = true; - } else { - boolean ccw = isCCW(px0, py0, x0, y0, x1, y1); - if (joinSegment) { - if (joinStyle == LinePath.JOIN_MITER) { - drawMiter(px0, py0, x0, y0, x1, y1, omx, omy, mx, my, color0, ccw); - } else if (joinStyle == LinePath.JOIN_ROUND) { - drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw, - ROUND_JOIN_THRESHOLD); - } - } else { - // Draw internal joins as round - drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw, - ROUND_JOIN_INTERNAL_THRESHOLD); - } - - emitLineTo(x0, y0, color0, !ccw); - } - - emitLineTo(x0 + mx, y0 + my, color0, false); - emitLineTo(x1 + mx, y1 + my, c1, false); - - emitLineTo(x0 - mx, y0 - my, color0, true); - emitLineTo(x1 - mx, y1 - my, c1, true); - - this.omx = mx; - this.omy = my; - this.px0 = x0; - this.py0 = y0; - this.pcolor0 = color0; - this.x0 = x1; - this.y0 = y1; - this.color0 = c1; - this.prev = LinePath.SEG_LINETO; - } - - public void close() { - if (lineToOrigin) { - // ignore the previous lineTo - lineToOrigin = false; - } - - if (!started) { - finish(); - return; - } - - computeOffset(x0, y0, sx0, sy0, offset); - int mx = offset[0]; - int my = offset[1]; - - // Draw penultimate join - boolean ccw = isCCW(px0, py0, x0, y0, sx0, sy0); - if (joinSegment) { - if (joinStyle == LinePath.JOIN_MITER) { - drawMiter(px0, py0, x0, y0, sx0, sy0, omx, omy, mx, my, pcolor0, ccw); - } else if (joinStyle == LinePath.JOIN_ROUND) { - drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw, - ROUND_JOIN_THRESHOLD); - } - } else { - // Draw internal joins as round - drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw, - ROUND_JOIN_INTERNAL_THRESHOLD); - } - - emitLineTo(x0 + mx, y0 + my, color0); - emitLineTo(sx0 + mx, sy0 + my, scolor0); - - ccw = isCCW(x0, y0, sx0, sy0, sx1, sy1); - - // Draw final join on the outside - if (!ccw) { - if (joinStyle == LinePath.JOIN_MITER) { - drawMiter(x0, y0, sx0, sy0, sx1, sy1, mx, my, mx0, my0, color0, false); - } else if (joinStyle == LinePath.JOIN_ROUND) { - drawRoundJoin(sx0, sy0, mx, my, mx0, my0, 0, scolor0, false, false, - ROUND_JOIN_THRESHOLD); - } - } - - emitLineTo(sx0 + mx0, sy0 + my0, scolor0); - emitLineTo(sx0 - mx0, sy0 - my0, scolor0); // same as reverse[0], reverse[1] - - // Draw final join on the inside - if (ccw) { - if (joinStyle == LinePath.JOIN_MITER) { - drawMiter(x0, y0, sx0, sy0, sx1, sy1, -mx, -my, -mx0, -my0, color0, - false); - } else if (joinStyle == LinePath.JOIN_ROUND) { - drawRoundJoin(sx0, sy0, -mx, -my, -mx0, -my0, 0, scolor0, true, false, - ROUND_JOIN_THRESHOLD); - } - } - - emitLineTo(sx0 - mx, sy0 - my, scolor0); - emitLineTo(x0 - mx, y0 - my, color0); - for (int i = rindex - 3; i >= 0; i -= 3) { - emitLineTo(reverse[i], reverse[i + 1], reverse[i + 2]); - } - - this.x0 = this.sx0; - this.y0 = this.sy0; - this.rindex = 0; - this.started = false; - this.joinSegment = false; - this.prev = LinePath.SEG_CLOSE; - emitClose(); - } - - public void end() { - if (lineToOrigin) { - // not closing the path, do the previous lineTo - lineToImpl(sx0, sy0, scolor0, joinToOrigin); - lineToOrigin = false; - } - - if (prev == LinePath.SEG_LINETO) { - finish(); - } - - output.end(); - this.joinSegment = false; - this.prev = LinePath.SEG_MOVETO; - } - - long lineLength(long ldx, long ldy) { - long ldet = ((long) m00 * m11 - (long) m01 * m10) >> 16; - long la = (ldy * m00 - ldx * m10) / ldet; - long lb = (ldy * m01 - ldx * m11) / ldet; - long llen = (int) LinePath.hypot(la, lb); - return llen; - } - - private void finish() { - if (capStyle == LinePath.CAP_ROUND) { - drawRoundJoin(x0, y0, omx, omy, -omx, -omy, 1, color0, false, false, - ROUND_JOIN_THRESHOLD); - } else if (capStyle == LinePath.CAP_SQUARE) { - long ldx = px0 - x0; - long ldy = py0 - y0; - long llen = lineLength(ldx, ldy); - if (0 < llen) { - long s = (long) lineWidth2 * 65536 / llen; - - int capx = x0 - (int) (ldx * s >> 16); - int capy = y0 - (int) (ldy * s >> 16); - - emitLineTo(capx + omx, capy + omy, color0); - emitLineTo(capx - omx, capy - omy, color0); - } - } - - for (int i = rindex - 3; i >= 0; i -= 3) { - emitLineTo(reverse[i], reverse[i + 1], reverse[i + 2]); - } - this.rindex = 0; - - if (capStyle == LinePath.CAP_ROUND) { - drawRoundJoin(sx0, sy0, -mx0, -my0, mx0, my0, 1, scolor0, false, false, - ROUND_JOIN_THRESHOLD); - } else if (capStyle == LinePath.CAP_SQUARE) { - long ldx = sx1 - sx0; - long ldy = sy1 - sy0; - long llen = lineLength(ldx, ldy); - if (0 < llen) { - long s = (long) lineWidth2 * 65536 / llen; - - int capx = sx0 - (int) (ldx * s >> 16); - int capy = sy0 - (int) (ldy * s >> 16); - - emitLineTo(capx - mx0, capy - my0, scolor0); - emitLineTo(capx + mx0, capy + my0, scolor0); - } - } - - emitClose(); - this.joinSegment = false; - } - - private void emitMoveTo(int x0, int y0, int c0) { - output.moveTo(x0, y0, c0); - } - - private void emitLineTo(int x1, int y1, int c1) { - output.lineTo(x1, y1, c1); - } - - private void emitLineTo(int x1, int y1, int c1, boolean rev) { - if (rev) { - ensureCapacity(rindex + 3); - reverse[rindex++] = x1; - reverse[rindex++] = y1; - reverse[rindex++] = c1; - } else { - emitLineTo(x1, y1, c1); - } - } - - private void emitClose() { - output.close(); - } -} diff --git a/core/src/processing/opengl/PGL.java b/core/src/processing/opengl/PGL.java deleted file mode 100644 index 18e4d8bb8..000000000 --- a/core/src/processing/opengl/PGL.java +++ /dev/null @@ -1,3363 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import java.io.IOException; -import java.net.URL; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.nio.ShortBuffer; -import java.util.Arrays; -import java.util.regex.Pattern; - -import processing.core.PApplet; -import processing.core.PConstants; -import processing.core.PGraphics; - - -/** - * Processing-OpenGL abstraction layer. Needs to be implemented by subclasses - * using specific OpenGL-Java bindings. - * - * It includes a full GLES 2.0 interface. - * - */ -public abstract class PGL { - // ........................................................ - - // Basic fields - - /** The PGraphics and PApplet objects using this interface */ - protected PGraphicsOpenGL graphics; - protected PApplet sketch; - - /** OpenGL thread */ - protected Thread glThread; - - /** ID of the GL context associated to the surface **/ - protected int glContext; - - /** true if this is the GL interface for a primary surface PGraphics */ - public boolean primaryPGL; - - // ........................................................ - - // Parameters - - public static int REQUESTED_DEPTH_BITS = 24; - public static int REQUESTED_STENCIL_BITS = 8; - public static int REQUESTED_ALPHA_BITS = 8; - - /** Switches between the use of regular and direct buffers. */ - protected static boolean USE_DIRECT_BUFFERS = true; - protected static int MIN_DIRECT_BUFFER_SIZE = 1; - - /** Enables/disables mipmap use. */ - protected static boolean MIPMAPS_ENABLED = true; - - /** Initial sizes for arrays of input and tessellated data. */ - protected static int DEFAULT_IN_VERTICES = 64; - protected static int DEFAULT_IN_EDGES = 128; - protected static int DEFAULT_IN_TEXTURES = 64; - protected static int DEFAULT_TESS_VERTICES = 64; - protected static int DEFAULT_TESS_INDICES = 128; - - /** Maximum lights by default is 8, the minimum defined by OpenGL. */ - protected static int MAX_LIGHTS = 8; - - /** Maximum index value of a tessellated vertex. GLES restricts the vertex - * indices to be of type unsigned short. Since Java only supports signed - * shorts as primitive type we have 2^15 = 32768 as the maximum number of - * vertices that can be referred to within a single VBO. - */ - protected static int MAX_VERTEX_INDEX = 32767; - protected static int MAX_VERTEX_INDEX1 = MAX_VERTEX_INDEX + 1; - - /** Count of tessellated fill, line or point vertices that will - * trigger a flush in the immediate mode. It doesn't necessarily - * be equal to MAX_VERTEX_INDEX1, since the number of vertices can - * be effectively much large since the renderer uses offsets to - * refer to vertices beyond the MAX_VERTEX_INDEX limit. - */ - protected static int FLUSH_VERTEX_COUNT = MAX_VERTEX_INDEX1; - - /** Minimum/maximum dimensions of a texture used to hold font data. */ - protected static int MIN_FONT_TEX_SIZE = 256; - protected static int MAX_FONT_TEX_SIZE = 1024; - - /** Minimum stroke weight needed to apply the full path stroking - * algorithm that properly generates caps and joins. - */ - protected static float MIN_CAPS_JOINS_WEIGHT = 2f; - - /** Maximum length of linear paths to be stroked with the - * full algorithm that generates accurate caps and joins. - */ - protected static int MAX_CAPS_JOINS_LENGTH = 5000; - - /** Minimum array size to use arrayCopy method(). */ - protected static int MIN_ARRAYCOPY_SIZE = 2; - - /** Factor used to displace the stroke vertices towards the camera in - * order to make sure the lines are always on top of the fill geometry */ - protected static float STROKE_DISPLACEMENT = 0.999f; - - // ........................................................ - - // Variables to handle single-buffered situations (i.e.: Android) - - protected IntBuffer firstFrame; - protected static boolean SINGLE_BUFFERED = false; - - // ........................................................ - - // FBO layer - - protected boolean fboLayerEnabled = false; - protected boolean fboLayerCreated = false; - protected boolean fboLayerEnabledReq = false; - protected boolean fboLayerDisableReq = false; - protected boolean fbolayerResetReq = false; - public int reqNumSamples; - protected int numSamples; - - protected IntBuffer glColorFbo; - protected IntBuffer glColorTex; - protected IntBuffer glDepthStencil; - protected IntBuffer glDepth; - protected IntBuffer glStencil; - - protected IntBuffer glMultiFbo; - protected IntBuffer glMultiColor; - protected IntBuffer glMultiDepthStencil; - protected IntBuffer glMultiDepth; - protected IntBuffer glMultiStencil; - - protected int fboWidth, fboHeight; - protected int backTex, frontTex; - - /** Flags used to handle the creation of a separate front texture */ - protected boolean usingFrontTex = false; - protected boolean needSepFrontTex = false; - - // ........................................................ - - // Texture rendering - - protected boolean loadedTex2DShader = false; - protected int tex2DShaderProgram; - protected int tex2DVertShader; - protected int tex2DFragShader; - protected int tex2DShaderContext; - protected int tex2DVertLoc; - protected int tex2DTCoordLoc; - protected int tex2DSamplerLoc; - protected int tex2DGeoVBO; - - protected boolean loadedTexRectShader = false; - protected int texRectShaderProgram; - protected int texRectVertShader; - protected int texRectFragShader; - protected int texRectShaderContext; - protected int texRectVertLoc; - protected int texRectTCoordLoc; - protected int texRectSamplerLoc; - protected int texRectGeoVBO; - - protected float[] texCoords = { - // X, Y, U, V - -1.0f, -1.0f, 0.0f, 0.0f, - +1.0f, -1.0f, 1.0f, 0.0f, - -1.0f, +1.0f, 0.0f, 1.0f, - +1.0f, +1.0f, 1.0f, 1.0f - }; - protected FloatBuffer texData; - - protected static final String SHADER_PREPROCESSOR_DIRECTIVE = - "#ifdef GL_ES\n" + - "precision mediump float;\n" + - "precision mediump int;\n" + - "#endif\n"; - - protected static String[] texVertShaderSource = { - "attribute vec2 position;", - "attribute vec2 texCoord;", - "varying vec2 vertTexCoord;", - "void main() {", - " gl_Position = vec4(position, 0, 1);", - " vertTexCoord = texCoord;", - "}" - }; - - protected static String[] tex2DFragShaderSource = { - SHADER_PREPROCESSOR_DIRECTIVE, - "uniform sampler2D texMap;", - "varying vec2 vertTexCoord;", - "void main() {", - " gl_FragColor = texture2D(texMap, vertTexCoord.st);", - "}" - }; - - protected static String[] texRectFragShaderSource = { - SHADER_PREPROCESSOR_DIRECTIVE, - "uniform sampler2DRect texMap;", - "varying vec2 vertTexCoord;", - "void main() {", - " gl_FragColor = texture2DRect(texMap, vertTexCoord.st);", - "}" - }; - - /** Which texturing targets are enabled */ - protected boolean[] texturingTargets = { false, false }; - - /** Used to keep track of which textures are bound to each target */ - protected int maxTexUnits; - protected int activeTexUnit = 0; - protected int[][] boundTextures; - - // ........................................................ - - // Framerate handling - - protected float targetFps = 60; - protected float currentFps = 60; - protected boolean setFps = false; - - // ........................................................ - - // Utility buffers - - protected ByteBuffer byteBuffer; - protected IntBuffer intBuffer; - protected IntBuffer viewBuffer; - - protected IntBuffer colorBuffer; - protected FloatBuffer depthBuffer; - protected ByteBuffer stencilBuffer; - - //........................................................ - - // Rendering information - - /** Used to register amount of geometry rendered in each frame. */ - protected int geomCount = 0; - protected int pgeomCount; - - /** Used to register calls to background. */ - protected boolean clearColor = false; - protected boolean pclearColor; - - protected boolean clearDepth = false; - protected boolean pclearDepth; - - protected boolean clearStencil = false; - protected boolean pclearStencil; - - - // ........................................................ - - // Error messages - - public static final String WIKI = - " Read http://wiki.processing.org/w/OpenGL_Issues for help."; - - public static final String FRAMEBUFFER_ERROR = - "Framebuffer error (%1$s), rendering will probably not work as expected" + WIKI; - - public static final String MISSING_FBO_ERROR = - "Framebuffer objects are not supported by this hardware (or driver)" + WIKI; - - public static final String MISSING_GLSL_ERROR = - "GLSL shaders are not supported by this hardware (or driver)" + WIKI; - - public static final String MISSING_GLFUNC_ERROR = - "GL function %1$s is not available on this hardware (or driver)" + WIKI; - - public static final String UNSUPPORTED_GLPROF_ERROR = - "Unsupported OpenGL profile."; - - public static final String TEXUNIT_ERROR = - "Number of texture units not supported by this hardware (or driver)" + WIKI; - - public static final String NONPRIMARY_ERROR = - "The renderer is trying to call a PGL function that can only be called on a primary PGL. " + - "This is most likely due to a bug in the renderer's code, please report it with an " + - "issue on Processing's github page https://github.com/processing/processing/issues?state=open " + - "if using any of the built-in OpenGL renderers. If you are using a contributed " + - "library, contact the library's developers."; - - protected static final String DEPTH_READING_NOT_ENABLED_ERROR = - "Reading depth and stencil values from this multisampled buffer is not enabled. " + - "You can enable it by calling hint(ENABLE_DEPTH_READING) once. " + - "If your sketch becomes too slow, disable multisampling with noSmooth() instead."; - - // ........................................................ - - // Constants - - /** Size of different types in bytes */ - protected static int SIZEOF_SHORT = Short.SIZE / 8; - protected static int SIZEOF_INT = Integer.SIZE / 8; - protected static int SIZEOF_FLOAT = Float.SIZE / 8; - protected static int SIZEOF_BYTE = Byte.SIZE / 8; - protected static int SIZEOF_INDEX = SIZEOF_SHORT; - protected static int INDEX_TYPE = 0x1403; // GL_UNSIGNED_SHORT - - /** Machine Epsilon for float precision. */ - protected static float FLOAT_EPS = Float.MIN_VALUE; - // Calculation of the Machine Epsilon for float precision. From: - // http://en.wikipedia.org/wiki/Machine_epsilon#Approximation_using_Java - static { - float eps = 1.0f; - - do { - eps /= 2.0f; - } while ((float)(1.0 + (eps / 2.0)) != 1.0); - - FLOAT_EPS = eps; - } - - /** - * Set to true if the host system is big endian (PowerPC, MIPS, SPARC), false - * if little endian (x86 Intel for Mac or PC). - */ - protected static boolean BIG_ENDIAN = - ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; - - // ........................................................ - - // Present mode - - // ........................................................ - - // Present mode - - protected boolean presentMode = false; - protected boolean showStopButton = true; - public float presentX; - public float presentY; - protected IntBuffer closeButtonTex; - protected int stopButtonColor; - protected int stopButtonWidth = 28; - protected int stopButtonHeight = 12; - protected int stopButtonX = 21; // The position of the close button is relative to the - protected int closeButtonY = 21; // lower left corner - protected static int[] closeButtonPix = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, -1, -1, -1, -1, -1, 0, 0, 0, -1, - -1, -1, 0, 0, 0, -1, -1, -1, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, - 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, -1, -1, 0, -1, -1, 0, 0, -1, 0, 0, 0, 0, 0, - 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, - -1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, - 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, -1, 0, -1, - -1, 0, 0, -1, -1, 0, -1, -1, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, -1, -1, -1, - 0, 0, 0, -1, -1, -1, 0, 0, 0, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0}; - - - /////////////////////////////////////////////////////////////// - - // Initialization, finalization - - - public PGL() { } - - - public PGL(PGraphicsOpenGL pg) { - this.graphics = pg; - if (glColorTex == null) { - glColorFbo = allocateIntBuffer(1); - glColorTex = allocateIntBuffer(2); - glDepthStencil = allocateIntBuffer(1); - glDepth = allocateIntBuffer(1); - glStencil = allocateIntBuffer(1); - - glMultiFbo = allocateIntBuffer(1); - glMultiColor = allocateIntBuffer(1); - glMultiDepthStencil = allocateIntBuffer(1); - glMultiDepth = allocateIntBuffer(1); - glMultiStencil = allocateIntBuffer(1); - } - - byteBuffer = allocateByteBuffer(1); - intBuffer = allocateIntBuffer(1); - viewBuffer = allocateIntBuffer(4); - } - - - public void dispose() { - destroyFBOLayer(); - graphics = null; - sketch = null; - } - - - public void setPrimary(boolean primary) { - primaryPGL = primary; - } - - - static public int smoothToSamples(int smooth) { - if (smooth == 0) { - // smooth(0) is noSmooth(), which is 1x sampling - return 1; - } else if (smooth == 1) { - // smooth(1) means "default smoothing", which is 2x for OpenGL - return 2; - } else { - // smooth(N) can be used for 4x, 8x, etc - return smooth; - } - } - - - abstract public Object getNative(); - - - public void setFrameRate(float fps) { - targetFps = fps; - currentFps = fps; - setFps = true; - } - - - public float getFrameRate() { - return currentFps; - } - - - abstract protected void initSurface(int antialias); - - - abstract protected void reinitSurface(); - - - abstract protected void registerListeners(); - - - protected int getReadFramebuffer() { - return fboLayerEnabled ? glColorFbo.get(0) : 0; - } - - - protected int getDrawFramebuffer() { - if (fboLayerEnabled) return 1 < numSamples ? glMultiFbo.get(0) : - glColorFbo.get(0); - else return 0; - } - - - protected int getDefaultDrawBuffer() { - return fboLayerEnabled ? COLOR_ATTACHMENT0 : BACK; - } - - - protected int getDefaultReadBuffer() { - return fboLayerEnabled ? COLOR_ATTACHMENT0 : FRONT; - } - - - protected boolean isFBOBacked() {; - return fboLayerEnabled; - } - - - @Deprecated - public void requestFBOLayer() { - enableFBOLayer(); - } - - - public void enableFBOLayer() { - fboLayerEnabledReq = true; - } - - - public void disableFBOLayer() { - fboLayerDisableReq = true; - } - - - public void resetFBOLayer() { - fbolayerResetReq = true; - } - - - abstract public void queueEvent(Runnable runnable); - - protected boolean isMultisampled() { - return 1 < numSamples; - } - - - abstract protected int getDepthBits(); - - - abstract protected int getStencilBits(); - - - protected boolean getDepthTest() { - intBuffer.rewind(); - getBooleanv(DEPTH_TEST, intBuffer); - return intBuffer.get(0) == 0 ? false : true; - } - - - protected boolean getDepthWriteMask() { - intBuffer.rewind(); - getBooleanv(DEPTH_WRITEMASK, intBuffer); - return intBuffer.get(0) == 0 ? false : true; - } - - - protected Texture wrapBackTexture(Texture texture) { - if (texture == null) { - texture = new Texture(graphics); - texture.init(graphics.width, graphics.height, - glColorTex.get(backTex), TEXTURE_2D, RGBA, - fboWidth, fboHeight, NEAREST, NEAREST, - CLAMP_TO_EDGE, CLAMP_TO_EDGE); - texture.invertedY(!graphics.cameraUp); - texture.colorBuffer(true); - graphics.setCache(graphics, texture); - } else { - texture.glName = glColorTex.get(backTex); - } - return texture; - } - - - protected Texture wrapFrontTexture(Texture texture) { - if (texture == null) { - texture = new Texture(graphics); - texture.init(graphics.width, graphics.height, - glColorTex.get(frontTex), TEXTURE_2D, RGBA, - fboWidth, fboHeight, NEAREST, NEAREST, - CLAMP_TO_EDGE, CLAMP_TO_EDGE); - texture.invertedY(!graphics.cameraUp); - texture.colorBuffer(true); - } else { - texture.glName = glColorTex.get(frontTex); - } - return texture; - } - - - protected void bindFrontTexture() { - usingFrontTex = true; - if (!texturingIsEnabled(TEXTURE_2D)) { - enableTexturing(TEXTURE_2D); - } - bindTexture(TEXTURE_2D, glColorTex.get(frontTex)); - } - - - protected void unbindFrontTexture() { - if (textureIsBound(TEXTURE_2D, glColorTex.get(frontTex))) { - // We don't want to unbind another texture - // that might be bound instead of this one. - if (!texturingIsEnabled(TEXTURE_2D)) { - enableTexturing(TEXTURE_2D); - bindTexture(TEXTURE_2D, 0); - disableTexturing(TEXTURE_2D); - } else { - bindTexture(TEXTURE_2D, 0); - } - } - } - - - protected void syncBackTexture() { - if (usingFrontTex) needSepFrontTex = true; - if (1 < numSamples) { - bindFramebufferImpl(READ_FRAMEBUFFER, glMultiFbo.get(0)); - bindFramebufferImpl(DRAW_FRAMEBUFFER, glColorFbo.get(0)); - int mask = COLOR_BUFFER_BIT; - if (graphics.getHint(PConstants.ENABLE_BUFFER_READING)) { - mask |= DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT; - } - blitFramebuffer(0, 0, fboWidth, fboHeight, - 0, 0, fboWidth, fboHeight, - mask, NEAREST); - } - } - - - abstract protected float getPixelScale(); - - /////////////////////////////////////////////////////////// - - // Present mode - - - public void initPresentMode(float x, float y, int stopColor) { - presentMode = true; - showStopButton = stopColor != 0; - stopButtonColor = stopColor; - presentX = x; - presentY = y; - enableFBOLayer(); - } - - - public boolean presentMode() { - return presentMode; - } - - - public float presentX() { - return presentX; - } - - - public float presentY() { - return presentY; - } - - - public boolean insideStopButton(float x, float y) { - if (!showStopButton) return false; - return stopButtonX < x && x < stopButtonX + stopButtonWidth && - -(closeButtonY + stopButtonHeight) < y && y < -closeButtonY; - } - - - /////////////////////////////////////////////////////////// - - // Frame rendering - - - protected void clearDepthStencil() { - if (!pclearDepth && !pclearStencil) { - depthMask(true); - clearDepth(1); - clearStencil(0); - clear(DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT); - } else if (!pclearDepth) { - depthMask(true); - clearDepth(1); - clear(DEPTH_BUFFER_BIT); - } else if (!pclearStencil) { - clearStencil(0); - clear(STENCIL_BUFFER_BIT); - } - } - - - protected void clearBackground(float r, float g, float b, float a, - boolean depth, boolean stencil) { - clearColor(r, g, b, a); - if (depth && stencil) { - clearDepth(1); - clearStencil(0); - clear(DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT | COLOR_BUFFER_BIT); - if (0 < sketch.frameCount) { - clearColor = true; - clearDepth = true; - clearStencil = true; - } - } else if (depth) { - clearDepth(1); - clear(DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT); - if (0 < sketch.frameCount) { - clearColor = true; - clearDepth = true; - } - } else if (stencil) { - clearStencil(0); - clear(STENCIL_BUFFER_BIT | COLOR_BUFFER_BIT); - if (0 < sketch.frameCount) { - clearColor = true; - clearStencil = true; - } - } else { - clear(PGL.COLOR_BUFFER_BIT); - if (0 < sketch.frameCount) { - clearColor = true; - } - } - if (fboLayerEnabled) { - clearFrontColorBuffer(); - } - } - - - protected void beginRender() { - if (sketch == null) { - sketch = graphics.parent; - } - - pgeomCount = geomCount; - geomCount = 0; - - pclearColor = clearColor; - clearColor = false; - - pclearDepth = clearDepth; - clearDepth = false; - - pclearStencil = clearStencil; - clearStencil = false; - - if (fboLayerEnabledReq) { - fboLayerEnabled = true; - fboLayerEnabledReq = false; - } - - if (fboLayerEnabled) { - if (fbolayerResetReq) { - destroyFBOLayer(); - fbolayerResetReq = false; - } - if (!fboLayerCreated) { - createFBOLayer(); - } - - // Draw to the back texture - bindFramebufferImpl(FRAMEBUFFER, glColorFbo.get(0)); - framebufferTexture2D(FRAMEBUFFER, COLOR_ATTACHMENT0, - TEXTURE_2D, glColorTex.get(backTex), 0); - - if (1 < numSamples) { - bindFramebufferImpl(FRAMEBUFFER, glMultiFbo.get(0)); - } - - if (sketch.frameCount == 0) { - // No need to draw back color buffer because we are in the first frame. - int argb = graphics.backgroundColor; - float ba = ((argb >> 24) & 0xff) / 255.0f; - float br = ((argb >> 16) & 0xff) / 255.0f; - float bg = ((argb >> 8) & 0xff) / 255.0f; - float bb = ((argb) & 0xff) / 255.0f; - clearColor(br, bg, bb, ba); - clear(COLOR_BUFFER_BIT); - } else if (!pclearColor || !graphics.isLooping()) { - // Render previous back texture (now is the front) as background, because no background() - // is being used ("incremental drawing") - int x = 0; - int y = 0; - if (presentMode) { - x = (int)presentX; - y = (int)presentY; - } - float scale = getPixelScale(); - drawTexture(TEXTURE_2D, glColorTex.get(frontTex), fboWidth, fboHeight, - x, y, graphics.width, graphics.height, - 0, 0, (int)(scale * graphics.width), (int)(scale * graphics.height), - 0, 0, graphics.width, graphics.height); - } - } else if (SINGLE_BUFFERED && sketch.frameCount == 1) { - restoreFirstFrame(); - } - } - - - protected void endRender(int windowColor) { - if (fboLayerEnabled) { - syncBackTexture(); - - // Draw the contents of the back texture to the screen framebuffer. - bindFramebufferImpl(FRAMEBUFFER, 0); - - if (presentMode) { - float wa = ((windowColor >> 24) & 0xff) / 255.0f; - float wr = ((windowColor >> 16) & 0xff) / 255.0f; - float wg = ((windowColor >> 8) & 0xff) / 255.0f; - float wb = (windowColor & 0xff) / 255.0f; - clearDepth(1); - clearColor(wr, wg, wb, wa); - clear(COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT); - - if (showStopButton) { - if (closeButtonTex == null) { - closeButtonTex = allocateIntBuffer(1); - genTextures(1, closeButtonTex); - bindTexture(TEXTURE_2D, closeButtonTex.get(0)); - texParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, NEAREST); - texParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, NEAREST); - texParameteri(TEXTURE_2D, TEXTURE_WRAP_S, CLAMP_TO_EDGE); - texParameteri(TEXTURE_2D, TEXTURE_WRAP_T, CLAMP_TO_EDGE); - texImage2D(TEXTURE_2D, 0, RGBA, stopButtonWidth, stopButtonHeight, 0, RGBA, UNSIGNED_BYTE, null); - - int[] color = new int[closeButtonPix.length]; - PApplet.arrayCopy(closeButtonPix, color); - - - // Multiply the texture by the button color - float ba = ((stopButtonColor >> 24) & 0xFF) / 255f; - float br = ((stopButtonColor >> 16) & 0xFF) / 255f; - float bg = ((stopButtonColor >> 8) & 0xFF) / 255f; - float bb = ((stopButtonColor >> 0) & 0xFF) / 255f; - for (int i = 0; i < color.length; i++) { - int c = closeButtonPix[i]; - int a = (int)(ba * ((c >> 24) & 0xFF)); - int r = (int)(br * ((c >> 16) & 0xFF)); - int g = (int)(bg * ((c >> 8) & 0xFF)); - int b = (int)(bb * ((c >> 0) & 0xFF)); - color[i] = javaToNativeARGB((a << 24) | (r << 16) | (g << 8) | b); - } - IntBuffer buf = allocateIntBuffer(color); - copyToTexture(TEXTURE_2D, RGBA, closeButtonTex.get(0), 0, 0, stopButtonWidth, stopButtonHeight, buf); - bindTexture(TEXTURE_2D, 0); - } - drawTexture(TEXTURE_2D, closeButtonTex.get(0), stopButtonWidth, stopButtonHeight, - 0, 0, stopButtonX + stopButtonWidth, closeButtonY + stopButtonHeight, - 0, stopButtonHeight, stopButtonWidth, 0, - stopButtonX, closeButtonY, stopButtonX + stopButtonWidth, closeButtonY + stopButtonHeight); - } - } else { - clearDepth(1); - clearColor(0, 0, 0, 0); - clear(COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT); - } - - // Render current back texture to screen, without blending. - disable(BLEND); - int x = 0; - int y = 0; - if (presentMode) { - x = (int)presentX; - y = (int)presentY; - } - float scale = getPixelScale(); - drawTexture(TEXTURE_2D, glColorTex.get(backTex), - fboWidth, fboHeight, - x, y, graphics.width, graphics.height, - 0, 0, (int)(scale * graphics.width), (int)(scale * graphics.height), - 0, 0, graphics.width, graphics.height); - - // Swapping front and back textures. - int temp = frontTex; - frontTex = backTex; - backTex = temp; - - if (fboLayerDisableReq) { - fboLayerEnabled = false; - fboLayerDisableReq = false; - } - } else { - if (SINGLE_BUFFERED && sketch.frameCount == 0) { - saveFirstFrame(); - } - - if (!clearColor && 0 < sketch.frameCount || !graphics.isLooping()) { - enableFBOLayer(); - if (SINGLE_BUFFERED) { - createFBOLayer(); - } - } - } - } - - - protected abstract void getGL(PGL pgl); - - - protected abstract boolean canDraw(); - - - protected abstract void requestFocus(); - - - protected abstract void requestDraw(); - - - protected abstract void swapBuffers(); - - - public boolean threadIsCurrent() { - return Thread.currentThread() == glThread; - } - - - public void setThread(Thread thread) { - glThread = thread; - } - - - protected void beginGL() { } - - - protected void endGL() { } - - - private void createFBOLayer() { - float scale = getPixelScale(); - - if (hasNpotTexSupport()) { - fboWidth = (int)(scale * graphics.width); - fboHeight = (int)(scale * graphics.height); - } else { - fboWidth = nextPowerOfTwo((int)(scale * graphics.width)); - fboHeight = nextPowerOfTwo((int)(scale * graphics.height)); - } - - if (hasFboMultisampleSupport()) { - int maxs = maxSamples(); - numSamples = PApplet.min(reqNumSamples, maxs); - } else { - numSamples = 1; - } - boolean multisample = 1 < numSamples; - - boolean packed = hasPackedDepthStencilSupport(); - int depthBits = PApplet.min(REQUESTED_DEPTH_BITS, getDepthBits()); - int stencilBits = PApplet.min(REQUESTED_STENCIL_BITS, getStencilBits()); - - backTex = 0; - frontTex = 1; - boolean savedFirstFrame = SINGLE_BUFFERED && sketch.frameCount == 0 && firstFrame != null; - - genTextures(2, glColorTex); - for (int i = 0; i < 2; i++) { - bindTexture(TEXTURE_2D, glColorTex.get(i)); - texParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, NEAREST); - texParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, NEAREST); - texParameteri(TEXTURE_2D, TEXTURE_WRAP_S, CLAMP_TO_EDGE); - texParameteri(TEXTURE_2D, TEXTURE_WRAP_T, CLAMP_TO_EDGE); - texImage2D(TEXTURE_2D, 0, RGBA, fboWidth, fboHeight, 0, - RGBA, UNSIGNED_BYTE, null); - if (i == frontTex && savedFirstFrame) { - // Copy first frame to front texture (will be drawn as background in next frame) - texSubImage2D(TEXTURE_2D, 0, 0, 0, graphics.width, graphics.height, - RGBA, UNSIGNED_BYTE, firstFrame); - } else { - // Intitialize texture with background color - initTexture(TEXTURE_2D, RGBA, fboWidth, fboHeight, graphics.backgroundColor); - } - } - bindTexture(TEXTURE_2D, 0); - - genFramebuffers(1, glColorFbo); - bindFramebufferImpl(FRAMEBUFFER, glColorFbo.get(0)); - framebufferTexture2D(FRAMEBUFFER, COLOR_ATTACHMENT0, TEXTURE_2D, - glColorTex.get(backTex), 0); - - if (!multisample || graphics.getHint(PConstants.ENABLE_BUFFER_READING)) { - // If not multisampled, this is the only depth and stencil buffer. - // If multisampled and depth reading enabled, these are going to - // hold downsampled depth and stencil buffers. - createDepthAndStencilBuffer(false, depthBits, stencilBits, packed); - } - - if (multisample) { - // Creating multisampled FBO - genFramebuffers(1, glMultiFbo); - bindFramebufferImpl(FRAMEBUFFER, glMultiFbo.get(0)); - - // color render buffer... - genRenderbuffers(1, glMultiColor); - bindRenderbuffer(RENDERBUFFER, glMultiColor.get(0)); - renderbufferStorageMultisample(RENDERBUFFER, numSamples, - RGBA8, fboWidth, fboHeight); - framebufferRenderbuffer(FRAMEBUFFER, COLOR_ATTACHMENT0, - RENDERBUFFER, glMultiColor.get(0)); - - // Creating multisampled depth and stencil buffers - createDepthAndStencilBuffer(true, depthBits, stencilBits, packed); - } - - validateFramebuffer(); - - // Clear all buffers. - clearDepth(1); - clearStencil(0); - int argb = graphics.backgroundColor; - float ba = ((argb >> 24) & 0xff) / 255.0f; - float br = ((argb >> 16) & 0xff) / 255.0f; - float bg = ((argb >> 8) & 0xff) / 255.0f; - float bb = ((argb) & 0xff) / 255.0f; - clearColor(br, bg, bb, ba); - clear(DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT | COLOR_BUFFER_BIT); - - bindFramebufferImpl(FRAMEBUFFER, 0); - initFBOLayer(); - - fboLayerCreated = true; - } - - protected abstract void initFBOLayer(); - - - protected void saveFirstFrame() { - firstFrame = allocateDirectIntBuffer(graphics.width * graphics.height); - if (hasReadBuffer()) readBuffer(BACK); - readPixelsImpl(0, 0, graphics.width, graphics.height, RGBA, UNSIGNED_BYTE, firstFrame); - } - - - protected void restoreFirstFrame() { - if (firstFrame == null) return; - - IntBuffer tex = allocateIntBuffer(1); - genTextures(1, tex); - - int w, h; - float scale = getPixelScale(); - if (hasNpotTexSupport()) { - w = (int)(scale * graphics.width); - h = (int)(scale * graphics.height); - } else { - w = nextPowerOfTwo((int)(scale * graphics.width)); - h = nextPowerOfTwo((int)(scale * graphics.height)); - } - - bindTexture(TEXTURE_2D, tex.get(0)); - texParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, NEAREST); - texParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, NEAREST); - texParameteri(TEXTURE_2D, TEXTURE_WRAP_S, CLAMP_TO_EDGE); - texParameteri(TEXTURE_2D, TEXTURE_WRAP_T, CLAMP_TO_EDGE); - texImage2D(TEXTURE_2D, 0, RGBA, w, h, 0, RGBA, UNSIGNED_BYTE, null); - texSubImage2D(TEXTURE_2D, 0, 0, 0, graphics.width, graphics.height, RGBA, UNSIGNED_BYTE, firstFrame); - - drawTexture(TEXTURE_2D, tex.get(0), w, h, - 0, 0, graphics.width, graphics.height, - 0, 0, (int)(scale * graphics.width), (int)(scale * graphics.height), - 0, 0, graphics.width, graphics.height); - - deleteTextures(1, tex); - firstFrame.clear(); - firstFrame = null; - } - - protected void destroyFBOLayer() { - if (threadIsCurrent() && fboLayerCreated) { - deleteFramebuffers(1, glColorFbo); - deleteTextures(2, glColorTex); - deleteRenderbuffers(1, glDepthStencil); - deleteRenderbuffers(1, glDepth); - deleteRenderbuffers(1, glStencil); - - deleteFramebuffers(1, glMultiFbo); - deleteRenderbuffers(1, glMultiColor); - deleteRenderbuffers(1, glMultiDepthStencil); - deleteRenderbuffers(1, glMultiDepth); - deleteRenderbuffers(1, glMultiStencil); - } - fboLayerCreated = false; - } - - - private void createDepthAndStencilBuffer(boolean multisample, int depthBits, - int stencilBits, boolean packed) { - // Creating depth and stencil buffers - if (packed && depthBits == 24 && stencilBits == 8) { - // packed depth+stencil buffer - IntBuffer depthStencilBuf = - multisample ? glMultiDepthStencil : glDepthStencil; - genRenderbuffers(1, depthStencilBuf); - bindRenderbuffer(RENDERBUFFER, depthStencilBuf.get(0)); - if (multisample) { - renderbufferStorageMultisample(RENDERBUFFER, numSamples, - DEPTH24_STENCIL8, fboWidth, fboHeight); - } else { - renderbufferStorage(RENDERBUFFER, DEPTH24_STENCIL8, - fboWidth, fboHeight); - } - framebufferRenderbuffer(FRAMEBUFFER, DEPTH_ATTACHMENT, RENDERBUFFER, - depthStencilBuf.get(0)); - framebufferRenderbuffer(FRAMEBUFFER, STENCIL_ATTACHMENT, RENDERBUFFER, - depthStencilBuf.get(0)); - } else { - // separate depth and stencil buffers - if (0 < depthBits) { - int depthComponent = DEPTH_COMPONENT16; - if (depthBits == 32) { - depthComponent = DEPTH_COMPONENT32; - } else if (depthBits == 24) { - depthComponent = DEPTH_COMPONENT24; - } else if (depthBits == 16) { - depthComponent = DEPTH_COMPONENT16; - } - - IntBuffer depthBuf = multisample ? glMultiDepth : glDepth; - genRenderbuffers(1, depthBuf); - bindRenderbuffer(RENDERBUFFER, depthBuf.get(0)); - if (multisample) { - renderbufferStorageMultisample(RENDERBUFFER, numSamples, - depthComponent, fboWidth, fboHeight); - } else { - renderbufferStorage(RENDERBUFFER, depthComponent, - fboWidth, fboHeight); - } - framebufferRenderbuffer(FRAMEBUFFER, DEPTH_ATTACHMENT, - RENDERBUFFER, depthBuf.get(0)); - } - - if (0 < stencilBits) { - int stencilIndex = STENCIL_INDEX1; - if (stencilBits == 8) { - stencilIndex = STENCIL_INDEX8; - } else if (stencilBits == 4) { - stencilIndex = STENCIL_INDEX4; - } else if (stencilBits == 1) { - stencilIndex = STENCIL_INDEX1; - } - - IntBuffer stencilBuf = multisample ? glMultiStencil : glStencil; - genRenderbuffers(1, stencilBuf); - bindRenderbuffer(RENDERBUFFER, stencilBuf.get(0)); - if (multisample) { - renderbufferStorageMultisample(RENDERBUFFER, numSamples, - stencilIndex, fboWidth, fboHeight); - } else { - renderbufferStorage(RENDERBUFFER, stencilIndex, - fboWidth, fboHeight); - } - framebufferRenderbuffer(FRAMEBUFFER, STENCIL_ATTACHMENT, - RENDERBUFFER, stencilBuf.get(0)); - } - } - } - - - protected void clearFrontColorBuffer() { - - } - - - /////////////////////////////////////////////////////////// - - // Context interface - - - protected int createEmptyContext() { - return -1; - } - - - protected int getCurrentContext() { - return glContext; - } - - - /////////////////////////////////////////////////////////// - - // Utility functions - - - protected boolean contextIsCurrent(int other) { - return other == -1 || other == glContext; - } - - - protected void enableTexturing(int target) { - if (target == TEXTURE_2D) { - texturingTargets[0] = true; - } else if (target == TEXTURE_RECTANGLE) { - texturingTargets[1] = true; - } - } - - - protected void disableTexturing(int target) { - if (target == TEXTURE_2D) { - texturingTargets[0] = false; - } else if (target == TEXTURE_RECTANGLE) { - texturingTargets[1] = false; - } - } - - - protected boolean texturingIsEnabled(int target) { - if (target == TEXTURE_2D) { - return texturingTargets[0]; - } else if (target == TEXTURE_RECTANGLE) { - return texturingTargets[1]; - } else { - return false; - } - } - - - protected boolean textureIsBound(int target, int id) { - if (boundTextures == null) return false; - - if (target == TEXTURE_2D) { - return boundTextures[activeTexUnit][0] == id; - } else if (target == TEXTURE_RECTANGLE) { - return boundTextures[activeTexUnit][1] == id; - } else { - return false; - } - } - - - protected void initTexture(int target, int format, int width, int height) { - initTexture(target, format, width, height, 0); - } - - - protected void initTexture(int target, int format, int width, int height, - int initColor) { - int[] glcolor = new int[16 * 16]; - Arrays.fill(glcolor, javaToNativeARGB(initColor)); - IntBuffer texels = allocateDirectIntBuffer(16 * 16); - texels.put(glcolor); - texels.rewind(); - for (int y = 0; y < height; y += 16) { - int h = PApplet.min(16, height - y); - for (int x = 0; x < width; x += 16) { - int w = PApplet.min(16, width - x); - texSubImage2D(target, 0, x, y, w, h, format, UNSIGNED_BYTE, texels); - } - } - } - - - protected void copyToTexture(int target, int format, int id, int x, int y, - int w, int h, int[] buffer) { - copyToTexture(target, format, id, x, y, w, h, IntBuffer.wrap(buffer)); - - } - - protected void copyToTexture(int target, int format, int id, int x, int y, - int w, int h, IntBuffer buffer) { - activeTexture(TEXTURE0); - boolean enabledTex = false; - if (!texturingIsEnabled(target)) { - enableTexturing(target); - enabledTex = true; - } - bindTexture(target, id); - texSubImage2D(target, 0, x, y, w, h, format, UNSIGNED_BYTE, buffer); - bindTexture(target, 0); - if (enabledTex) { - disableTexturing(target); - } - } - - - /** - * Not an approved function, this will change or be removed in the future. - */ - public void drawTexture(int target, int id, int width, int height, - int X0, int Y0, int X1, int Y1) { - // If a texture is drawing on a viewport of the same size as its resolution, - // the pixel factor is 1:1, so we override the surface's pixel factor. - drawTexture(target, id, width, height, - 0, 0, width, height, 1, - X0, Y0, X1, Y1, - X0, Y0, X1, Y1); - } - - - /** - * Not an approved function, this will change or be removed in the future. - */ - public void drawTexture(int target, int id,int texW, int texH, - int viewX, int viewY, int viewW, int viewH, - int texX0, int texY0, int texX1, int texY1, - int scrX0, int scrY0, int scrX1, int scrY1) { - int viewF = (int)getPixelScale(); - drawTexture(target, id, texW, texH, - viewX, viewY, viewW, viewH, viewF, - texX0, texY0, texX1, texY1, - scrX0, scrY0, scrX1, scrY1); - } - - - public void drawTexture(int target, int id,int texW, int texH, - int viewX, int viewY, int viewW, int viewH, int viewF, - int texX0, int texY0, int texX1, int texY1, - int scrX0, int scrY0, int scrX1, int scrY1) { - if (target == TEXTURE_2D) { - drawTexture2D(id, texW, texH, - viewX, viewY, viewW, viewH, viewF, - texX0, texY0, texX1, texY1, - scrX0, scrY0, scrX1, scrY1); - } else if (target == TEXTURE_RECTANGLE) { - drawTextureRect(id, texW, texH, - viewX, viewY, viewW, viewH, viewF, - texX0, texY0, texX1, texY1, - scrX0, scrY0, scrX1, scrY1); - } - } - - - protected PGL initTex2DShader() { - PGL ppgl = primaryPGL ? this : graphics.getPrimaryPGL(); - - if (!ppgl.loadedTex2DShader || ppgl.tex2DShaderContext != ppgl.glContext) { - String[] preprocVertSrc = preprocessVertexSource(texVertShaderSource, getGLSLVersion()); - String vertSource = PApplet.join(preprocVertSrc, "\n"); - String[] preprocFragSrc = preprocessFragmentSource(tex2DFragShaderSource, getGLSLVersion()); - String fragSource = PApplet.join(preprocFragSrc, "\n"); - ppgl.tex2DVertShader = createShader(VERTEX_SHADER, vertSource); - ppgl.tex2DFragShader = createShader(FRAGMENT_SHADER, fragSource); - if (0 < ppgl.tex2DVertShader && 0 < ppgl.tex2DFragShader) { - ppgl.tex2DShaderProgram = createProgram(ppgl.tex2DVertShader, ppgl.tex2DFragShader); - } - if (0 < ppgl.tex2DShaderProgram) { - ppgl.tex2DVertLoc = getAttribLocation(ppgl.tex2DShaderProgram, "position"); - ppgl.tex2DTCoordLoc = getAttribLocation(ppgl.tex2DShaderProgram, "texCoord"); - ppgl.tex2DSamplerLoc = getUniformLocation(ppgl.tex2DShaderProgram, "texMap"); - } - ppgl.loadedTex2DShader = true; - ppgl.tex2DShaderContext = ppgl.glContext; - - genBuffers(1, intBuffer); - ppgl.tex2DGeoVBO = intBuffer.get(0); - bindBuffer(ARRAY_BUFFER, ppgl.tex2DGeoVBO); - bufferData(ARRAY_BUFFER, 16 * SIZEOF_FLOAT, null, STATIC_DRAW); - } - - if (texData == null) { - texData = allocateDirectFloatBuffer(texCoords.length); - } - - return ppgl; - } - - - protected void drawTexture2D(int id, int texW, int texH, - int viewX, int viewY, int viewW, int viewH, int viewF, - int texX0, int texY0, int texX1, int texY1, - int scrX0, int scrY0, int scrX1, int scrY1) { - PGL ppgl = initTex2DShader(); - - if (0 < ppgl.tex2DShaderProgram) { - // The texture overwrites anything drawn earlier. - boolean depthTest = getDepthTest(); - disable(DEPTH_TEST); - - // When drawing the texture we don't write to the - // depth mask, so the texture remains in the background - // and can be occluded by anything drawn later, even if - // if it is behind it. - boolean depthMask = getDepthWriteMask(); - depthMask(false); - - // Making sure that the viewport matches the provided screen dimensions - viewBuffer.rewind(); - getIntegerv(VIEWPORT, viewBuffer); - viewportImpl(viewF * viewX, viewF * viewY, viewF * viewW, viewF * viewH); - - useProgram(ppgl.tex2DShaderProgram); - - enableVertexAttribArray(ppgl.tex2DVertLoc); - enableVertexAttribArray(ppgl.tex2DTCoordLoc); - - // Vertex coordinates of the textured quad are specified - // in normalized screen space (-1, 1): - // Corner 1 - texCoords[ 0] = 2 * (float)scrX0 / viewW - 1; - texCoords[ 1] = 2 * (float)scrY0 / viewH - 1; - texCoords[ 2] = (float)texX0 / texW; - texCoords[ 3] = (float)texY0 / texH; - // Corner 2 - texCoords[ 4] = 2 * (float)scrX1 / viewW - 1; - texCoords[ 5] = 2 * (float)scrY0 / viewH - 1; - texCoords[ 6] = (float)texX1 / texW; - texCoords[ 7] = (float)texY0 / texH; - // Corner 3 - texCoords[ 8] = 2 * (float)scrX0 / viewW - 1; - texCoords[ 9] = 2 * (float)scrY1 / viewH - 1; - texCoords[10] = (float)texX0 / texW; - texCoords[11] = (float)texY1 / texH; - // Corner 4 - texCoords[12] = 2 * (float)scrX1 / viewW - 1; - texCoords[13] = 2 * (float)scrY1 / viewH - 1; - texCoords[14] = (float)texX1 / texW; - texCoords[15] = (float)texY1 / texH; - - texData.rewind(); - texData.put(texCoords); - - activeTexture(TEXTURE0); - boolean enabledTex = false; - if (!texturingIsEnabled(TEXTURE_2D)) { - enableTexturing(TEXTURE_2D); - enabledTex = true; - } - bindTexture(TEXTURE_2D, id); - uniform1i(ppgl.tex2DSamplerLoc, 0); - - texData.position(0); - bindBuffer(ARRAY_BUFFER, ppgl.tex2DGeoVBO); - bufferData(ARRAY_BUFFER, 16 * SIZEOF_FLOAT, texData, STATIC_DRAW); - - vertexAttribPointer(ppgl.tex2DVertLoc, 2, FLOAT, false, 4 * SIZEOF_FLOAT, 0); - vertexAttribPointer(ppgl.tex2DTCoordLoc, 2, FLOAT, false, 4 * SIZEOF_FLOAT, 2 * SIZEOF_FLOAT); - - drawArrays(TRIANGLE_STRIP, 0, 4); - - bindBuffer(ARRAY_BUFFER, 0); // Making sure that no VBO is bound at this point. - - bindTexture(TEXTURE_2D, 0); - if (enabledTex) { - disableTexturing(TEXTURE_2D); - } - - disableVertexAttribArray(ppgl.tex2DVertLoc); - disableVertexAttribArray(ppgl.tex2DTCoordLoc); - - useProgram(0); - - if (depthTest) { - enable(DEPTH_TEST); - } else { - disable(DEPTH_TEST); - } - depthMask(depthMask); - - viewportImpl(viewBuffer.get(0), viewBuffer.get(1), - viewBuffer.get(2), viewBuffer.get(3)); - } - } - - - protected PGL initTexRectShader() { - PGL ppgl = primaryPGL ? this : graphics.getPrimaryPGL(); - - if (!ppgl.loadedTexRectShader || ppgl.texRectShaderContext != ppgl.glContext) { - String[] preprocVertSrc = preprocessVertexSource(texVertShaderSource, getGLSLVersion()); - String vertSource = PApplet.join(preprocVertSrc, "\n"); - String[] preprocFragSrc = preprocessFragmentSource(texRectFragShaderSource, getGLSLVersion()); - String fragSource = PApplet.join(preprocFragSrc, "\n"); - ppgl.texRectVertShader = createShader(VERTEX_SHADER, vertSource); - ppgl.texRectFragShader = createShader(FRAGMENT_SHADER, fragSource); - if (0 < ppgl.texRectVertShader && 0 < ppgl.texRectFragShader) { - ppgl.texRectShaderProgram = createProgram(ppgl.texRectVertShader, - ppgl.texRectFragShader); - } - if (0 < ppgl.texRectShaderProgram) { - ppgl.texRectVertLoc = getAttribLocation(ppgl.texRectShaderProgram, "position"); - ppgl.texRectTCoordLoc = getAttribLocation(ppgl.texRectShaderProgram, "texCoord"); - ppgl.texRectSamplerLoc = getUniformLocation(ppgl.texRectShaderProgram, "texMap"); - } - ppgl.loadedTexRectShader = true; - ppgl.texRectShaderContext = ppgl.glContext; - - genBuffers(1, intBuffer); - ppgl.texRectGeoVBO = intBuffer.get(0); - bindBuffer(ARRAY_BUFFER, ppgl.texRectGeoVBO); - bufferData(ARRAY_BUFFER, 16 * SIZEOF_FLOAT, null, STATIC_DRAW); - } - - return ppgl; - } - - - protected void drawTextureRect(int id, int texW, int texH, - int viewX, int viewY, int viewW, int viewH, int viewF, - int texX0, int texY0, int texX1, int texY1, - int scrX0, int scrY0, int scrX1, int scrY1) { - PGL ppgl = initTexRectShader(); - - if (texData == null) { - texData = allocateDirectFloatBuffer(texCoords.length); - } - - if (0 < ppgl.texRectShaderProgram) { - // The texture overwrites anything drawn earlier. - boolean depthTest = getDepthTest(); - disable(DEPTH_TEST); - - // When drawing the texture we don't write to the - // depth mask, so the texture remains in the background - // and can be occluded by anything drawn later, even if - // if it is behind it. - boolean depthMask = getDepthWriteMask(); - depthMask(false); - - // Making sure that the viewport matches the provided screen dimensions - viewBuffer.rewind(); - getIntegerv(VIEWPORT, viewBuffer); - viewportImpl(viewF * viewX, viewF * viewY, viewF * viewW, viewF * viewH); - - useProgram(ppgl.texRectShaderProgram); - - enableVertexAttribArray(ppgl.texRectVertLoc); - enableVertexAttribArray(ppgl.texRectTCoordLoc); - - // Vertex coordinates of the textured quad are specified - // in normalized screen space (-1, 1): - // Corner 1 - texCoords[ 0] = 2 * (float)scrX0 / viewW - 1; - texCoords[ 1] = 2 * (float)scrY0 / viewH - 1; - texCoords[ 2] = texX0; - texCoords[ 3] = texY0; - // Corner 2 - texCoords[ 4] = 2 * (float)scrX1 / viewW - 1; - texCoords[ 5] = 2 * (float)scrY0 / viewH - 1; - texCoords[ 6] = texX1; - texCoords[ 7] = texY0; - // Corner 3 - texCoords[ 8] = 2 * (float)scrX0 / viewW - 1; - texCoords[ 9] = 2 * (float)scrY1 / viewH - 1; - texCoords[10] = texX0; - texCoords[11] = texY1; - // Corner 4 - texCoords[12] = 2 * (float)scrX1 / viewW - 1; - texCoords[13] = 2 * (float)scrY1 / viewH - 1; - texCoords[14] = texX1; - texCoords[15] = texY1; - - texData.rewind(); - texData.put(texCoords); - - activeTexture(TEXTURE0); - boolean enabledTex = false; - if (!texturingIsEnabled(TEXTURE_RECTANGLE)) { - enableTexturing(TEXTURE_RECTANGLE); - enabledTex = true; - } - bindTexture(TEXTURE_RECTANGLE, id); - uniform1i(ppgl.texRectSamplerLoc, 0); - - texData.position(0); - bindBuffer(ARRAY_BUFFER, ppgl.texRectGeoVBO); - bufferData(ARRAY_BUFFER, 16 * SIZEOF_FLOAT, texData, STATIC_DRAW); - - vertexAttribPointer(ppgl.texRectVertLoc, 2, FLOAT, false, 4 * SIZEOF_FLOAT, 0); - vertexAttribPointer(ppgl.texRectTCoordLoc, 2, FLOAT, false, 4 * SIZEOF_FLOAT, 2 * SIZEOF_FLOAT); - - drawArrays(TRIANGLE_STRIP, 0, 4); - - bindBuffer(ARRAY_BUFFER, 0); // Making sure that no VBO is bound at this point. - - bindTexture(TEXTURE_RECTANGLE, 0); - if (enabledTex) { - disableTexturing(TEXTURE_RECTANGLE); - } - - disableVertexAttribArray(ppgl.texRectVertLoc); - disableVertexAttribArray(ppgl.texRectTCoordLoc); - - useProgram(0); - - if (depthTest) { - enable(DEPTH_TEST); - } else { - disable(DEPTH_TEST); - } - depthMask(depthMask); - - viewportImpl(viewBuffer.get(0), viewBuffer.get(1), - viewBuffer.get(2), viewBuffer.get(3)); - } - } - - - protected int getColorValue(int scrX, int scrY) { - if (colorBuffer == null) { - colorBuffer = IntBuffer.allocate(1); - } - colorBuffer.rewind(); - readPixels(scrX, graphics.height - scrY - 1, 1, 1, RGBA, UNSIGNED_BYTE, - colorBuffer); - return colorBuffer.get(); - } - - - protected float getDepthValue(int scrX, int scrY) { - if (depthBuffer == null) { - depthBuffer = FloatBuffer.allocate(1); - } - depthBuffer.rewind(); - readPixels(scrX, graphics.height - scrY - 1, 1, 1, DEPTH_COMPONENT, FLOAT, - depthBuffer); - return depthBuffer.get(0); - } - - - protected byte getStencilValue(int scrX, int scrY) { - if (stencilBuffer == null) { - stencilBuffer = ByteBuffer.allocate(1); - } - stencilBuffer.rewind(); - readPixels(scrX, graphics.height - scrY - 1, 1, 1, STENCIL_INDEX, - UNSIGNED_BYTE, stencilBuffer); - return stencilBuffer.get(0); - } - - - protected static boolean isPowerOfTwo(int val) { - return (val & (val - 1)) == 0; - } - - - // bit shifting this might be more efficient - protected static int nextPowerOfTwo(int val) { - int ret = 1; - while (ret < val) ret <<= 1; - return ret; - } - - - /** - * Converts input native OpenGL value (RGBA on big endian, ABGR on little - * endian) to Java ARGB. - */ - protected static int nativeToJavaARGB(int color) { - if (BIG_ENDIAN) { // RGBA to ARGB - return (color >>> 8) | (color << 24); - } else { // ABGR to ARGB - int rb = color & 0x00FF00FF; - return (color & 0xFF00FF00) | (rb << 16) | (rb >> 16); - } - } - - - /** - * Converts input array of native OpenGL values (RGBA on big endian, ABGR on - * little endian) representing an image of width x height resolution to Java - * ARGB. It also rearranges the elements in the array so that the image is - * flipped vertically. - */ - protected static void nativeToJavaARGB(int[] pixels, int width, int height) { - int index = 0; - int yindex = (height - 1) * width; - for (int y = 0; y < height / 2; y++) { - for (int x = 0; x < width; x++) { - int pixy = pixels[yindex]; - int pixi = pixels[index]; - if (BIG_ENDIAN) { // RGBA to ARGB - pixels[index] = (pixy >>> 8) | (pixy << 24); - pixels[yindex] = (pixi >>> 8) | (pixi << 24); - } else { // ABGR to ARGB - int rbi = pixi & 0x00FF00FF; - int rby = pixy & 0x00FF00FF; - pixels[index] = (pixy & 0xFF00FF00) | (rby << 16) | (rby >> 16); - pixels[yindex] = (pixi & 0xFF00FF00) | (rbi << 16) | (rbi >> 16); - } - index++; - yindex++; - } - yindex -= width * 2; - } - - if ((height % 2) == 1) { // Converts center row - index = (height / 2) * width; - for (int x = 0; x < width; x++) { - int pixi = pixels[index]; - if (BIG_ENDIAN) { // RGBA to ARGB - pixels[index] = (pixi >>> 8) | (pixi << 24); - } else { // ABGR to ARGB - int rbi = pixi & 0x00FF00FF; - pixels[index] = (pixi & 0xFF00FF00) | (rbi << 16) | (rbi >> 16); - } - index++; - } - } - } - - - /** - * Converts input native OpenGL value (RGBA on big endian, ABGR on little - * endian) to Java RGB, so that the alpha component of the result is set - * to opaque (255). - */ - protected static int nativeToJavaRGB(int color) { - if (BIG_ENDIAN) { // RGBA to ARGB - return (color >>> 8) | 0xFF000000; - } else { // ABGR to ARGB - int rb = color & 0x00FF00FF; - return 0xFF000000 | (rb << 16) | - (color & 0x0000FF00) | (rb >> 16); - } - } - - - /** - * Converts input array of native OpenGL values (RGBA on big endian, ABGR on - * little endian) representing an image of width x height resolution to Java - * RGB, so that the alpha component of all pixels is set to opaque (255). It - * also rearranges the elements in the array so that the image is flipped - * vertically. - */ - protected static void nativeToJavaRGB(int[] pixels, int width, int height) { - int index = 0; - int yindex = (height - 1) * width; - for (int y = 0; y < height / 2; y++) { - for (int x = 0; x < width; x++) { - int pixy = pixels[yindex]; - int pixi = pixels[index]; - if (BIG_ENDIAN) { // RGBA to ARGB - pixels[index] = (pixy >>> 8) | 0xFF000000; - pixels[yindex] = (pixi >>> 8) | 0xFF000000; - } else { // ABGR to ARGB - int rbi = pixi & 0x00FF00FF; - int rby = pixy & 0x00FF00FF; - pixels[index] = 0xFF000000 | (rby << 16) | - (pixy & 0x0000FF00) | (rby >> 16); - pixels[yindex] = 0xFF000000 | (rbi << 16) | - (pixi & 0x0000FF00) | (rbi >> 16); - } - index++; - yindex++; - } - yindex -= width * 2; - } - - if ((height % 2) == 1) { // Converts center row - index = (height / 2) * width; - for (int x = 0; x < width; x++) { - int pixi = pixels[index]; - if (BIG_ENDIAN) { // RGBA to ARGB - pixels[index] = (pixi >>> 8) | 0xFF000000; - } else { // ABGR to ARGB - int rbi = pixi & 0x00FF00FF; - pixels[index] = 0xFF000000 | (rbi << 16) | - (pixi & 0x000FF00) | (rbi >> 16); - } - index++; - } - } - } - - - /** - * Converts input Java ARGB value to native OpenGL format (RGBA on big endian, - * BGRA on little endian). - */ - protected static int javaToNativeARGB(int color) { - if (BIG_ENDIAN) { // ARGB to RGBA - return (color >>> 24) | (color << 8); - } else { // ARGB to ABGR - int rb = color & 0x00FF00FF; - return (color & 0xFF00FF00) | (rb << 16) | (rb >> 16); - } - } - - - /** - * Converts input array of Java ARGB values representing an image of width x - * height resolution to native OpenGL format (RGBA on big endian, BGRA on - * little endian). It also rearranges the elements in the array so that the - * image is flipped vertically. - */ - protected static void javaToNativeARGB(int[] pixels, int width, int height) { - int index = 0; - int yindex = (height - 1) * width; - for (int y = 0; y < height / 2; y++) { - for (int x = 0; x < width; x++) { - int pixy = pixels[yindex]; - int pixi = pixels[index]; - if (BIG_ENDIAN) { // ARGB to RGBA - pixels[index] = (pixy >>> 24) | (pixy << 8); - pixels[yindex] = (pixi >>> 24) | (pixi << 8); - } else { // ARGB to ABGR - int rbi = pixi & 0x00FF00FF; - int rby = pixy & 0x00FF00FF; - pixels[index] = (pixy & 0xFF00FF00) | (rby << 16) | (rby >> 16); - pixels[yindex] = (pixi & 0xFF00FF00) | (rbi << 16) | (rbi >> 16); - } - index++; - yindex++; - } - yindex -= width * 2; - } - - if ((height % 2) == 1) { // Converts center row - index = (height / 2) * width; - for (int x = 0; x < width; x++) { - int pixi = pixels[index]; - if (BIG_ENDIAN) { // ARGB to RGBA - pixels[index] = (pixi >>> 24) | (pixi << 8); - } else { // ARGB to ABGR - int rbi = pixi & 0x00FF00FF; - pixels[index] = (pixi & 0xFF00FF00) | (rbi << 16) | (rbi >> 16); - } - index++; - } - } - } - - - /** - * Converts input Java ARGB value to native OpenGL format (RGBA on big endian, - * BGRA on little endian), setting alpha component to opaque (255). - */ - protected static int javaToNativeRGB(int color) { - if (BIG_ENDIAN) { // ARGB to RGB - return 0xFF | (color << 8); - } else { // ARGB to BGR - int rb = color & 0x00FF00FF; - return 0xFF000000 | (rb << 16) | (color & 0x0000FF00) | (rb >> 16); - } - } - - - /** - * Converts input array of Java ARGB values representing an image of width x - * height resolution to native OpenGL format (RGBA on big endian, BGRA on - * little endian), while setting alpha component of all pixels to opaque - * (255). It also rearranges the elements in the array so that the image is - * flipped vertically. - */ - protected static void javaToNativeRGB(int[] pixels, int width, int height) { - int index = 0; - int yindex = (height - 1) * width; - for (int y = 0; y < height / 2; y++) { - for (int x = 0; x < width; x++) { - int pixy = pixels[yindex]; - int pixi = pixels[index]; - if (BIG_ENDIAN) { // ARGB to RGB - pixels[index] = 0xFF | (pixy << 8); - pixels[yindex] = 0xFF | (pixi << 8); - } else { // ARGB to BGR - int rbi = pixi & 0x00FF00FF; - int rby = pixy & 0x00FF00FF; - pixels[index] = 0xFF000000 | (rby << 16) | - (pixy & 0x0000FF00) | (rby >> 16); - pixels[yindex] = 0xFF000000 | (rbi << 16) | - (pixi & 0x0000FF00) | (rbi >> 16); - } - index++; - yindex++; - } - yindex -= width * 2; - } - - if ((height % 2) == 1) { // Converts center row - index = (height / 2) * width; - for (int x = 0; x < width; x++) { - int pixi = pixels[index]; - if (BIG_ENDIAN) { // ARGB to RGB - pixels[index] = 0xFF | (pixi << 8); - } else { // ARGB to BGR - int rbi = pixi & 0x00FF00FF; - pixels[index] = 0xFF000000 | (rbi << 16) | - (pixi & 0x0000FF00) | (rbi >> 16); - } - index++; - } - } - } - - - protected static int qualityToSamples(int quality) { - if (quality <= 1) { - return 1; - } else { - // Number of samples is always an even number: - int n = 2 * (quality / 2); - return n; - } - } - - - abstract protected int getGLSLVersion(); - - - protected String[] loadVertexShader(String filename) { - return sketch.loadStrings(filename); - } - - - protected String[] loadFragmentShader(String filename) { - return sketch.loadStrings(filename); - } - - - protected String[] loadFragmentShader(URL url) { - try { - return PApplet.loadStrings(url.openStream()); - } catch (IOException e) { - PGraphics.showException("Cannot load fragment shader " + url.getFile()); - } - return null; - } - - - protected String[] loadVertexShader(URL url) { - try { - return PApplet.loadStrings(url.openStream()); - } catch (IOException e) { - PGraphics.showException("Cannot load vertex shader " + url.getFile()); - } - return null; - } - - - protected String[] loadVertexShader(String filename, int version) { - return loadVertexShader(filename); - } - - - protected String[] loadFragmentShader(String filename, int version) { - return loadFragmentShader(filename); - } - - - protected String[] loadFragmentShader(URL url, int version) { - return loadFragmentShader(url); - } - - - protected String[] loadVertexShader(URL url, int version) { - return loadVertexShader(url); - } - - - protected static String[] preprocessFragmentSource(String[] fragSrc0, - int version) { - if (containsVersionDirective(fragSrc0)) { - // The user knows what she or he is doing - return fragSrc0; - } - - String[] fragSrc; - - if (version < 130) { - Pattern[] search = { }; - String[] replace = { }; - int offset = 1; - - fragSrc = preprocessShaderSource(fragSrc0, search, replace, offset); - fragSrc[0] = "#version " + version; - } else { - // We need to replace 'texture' uniform by 'texMap' uniform and - // 'textureXXX()' functions by 'texture()' functions. Order of these - // replacements is important to prevent collisions between these two. - Pattern[] search = new Pattern[] { - Pattern.compile(String.format(GLSL_ID_REGEX, "varying|attribute")), - Pattern.compile(String.format(GLSL_ID_REGEX, "texture")), - Pattern.compile(String.format(GLSL_FN_REGEX, "textureRect|texture2D|texture3D|textureCube")), - Pattern.compile(String.format(GLSL_ID_REGEX, "gl_FragColor")) - }; - String[] replace = new String[] { - "in", "texMap", "texture", "_fragColor" - }; - int offset = 2; - - fragSrc = preprocessShaderSource(fragSrc0, search, replace, offset); - fragSrc[0] = "#version " + version; - fragSrc[1] = "out vec4 _fragColor;"; - } - - return fragSrc; - } - - protected static String[] preprocessVertexSource(String[] vertSrc0, - int version) { - if (containsVersionDirective(vertSrc0)) { - // The user knows what she or he is doing - return vertSrc0; - } - - String[] vertSrc; - - if (version < 130) { - Pattern[] search = { }; - String[] replace = { }; - int offset = 1; - - vertSrc = preprocessShaderSource(vertSrc0, search, replace, offset); - vertSrc[0] = "#version " + version; - } else { - // We need to replace 'texture' uniform by 'texMap' uniform and - // 'textureXXX()' functions by 'texture()' functions. Order of these - // replacements is important to prevent collisions between these two. - Pattern[] search = new Pattern[] { - Pattern.compile(String.format(GLSL_ID_REGEX, "varying")), - Pattern.compile(String.format(GLSL_ID_REGEX, "attribute")), - Pattern.compile(String.format(GLSL_ID_REGEX, "texture")), - Pattern.compile(String.format(GLSL_FN_REGEX, "textureRect|texture2D|texture3D|textureCube")) - }; - String[] replace = new String[] { - "out", "in", "texMap", "texture", - }; - int offset = 1; - - vertSrc = preprocessShaderSource(vertSrc0, search, replace, offset); - vertSrc[0] = "#version " + version; - } - - return vertSrc; - } - - - protected static final String GLSL_ID_REGEX = "(?= 0) { - line = line.substring(0, versionIndex); - } - for (int j = 0; j < search.length; j++) { - line = search[j].matcher(line).replaceAll(replace[j]); - } - src[i+offset] = line; - } - return src; - } - - protected static boolean containsVersionDirective(String[] shSrc) { - for (int i = 0; i < shSrc.length; i++) { - String line = shSrc[i]; - int versionIndex = line.indexOf("#version"); - if (versionIndex >= 0) { - int commentIndex = line.indexOf("//"); - if (commentIndex < 0 || versionIndex < commentIndex) { - return true; - } - } - } - return false; - } - - protected int createShader(int shaderType, String source) { - int shader = createShader(shaderType); - if (shader != 0) { - shaderSource(shader, source); - compileShader(shader); - if (!compiled(shader)) { - System.err.println("Could not compile shader " + shaderType + ":"); - System.err.println(getShaderInfoLog(shader)); - deleteShader(shader); - shader = 0; - } - } - return shader; - } - - - protected int createProgram(int vertexShader, int fragmentShader) { - int program = createProgram(); - if (program != 0) { - attachShader(program, vertexShader); - attachShader(program, fragmentShader); - linkProgram(program); - if (!linked(program)) { - System.err.println("Could not link program: "); - System.err.println(getProgramInfoLog(program)); - deleteProgram(program); - program = 0; - } - } - return program; - } - - - protected boolean compiled(int shader) { - intBuffer.rewind(); - getShaderiv(shader, COMPILE_STATUS, intBuffer); - return intBuffer.get(0) == 0 ? false : true; - } - - - protected boolean linked(int program) { - intBuffer.rewind(); - getProgramiv(program, LINK_STATUS, intBuffer); - return intBuffer.get(0) == 0 ? false : true; - } - - - protected boolean validateFramebuffer() { - int status = checkFramebufferStatus(FRAMEBUFFER); - if (status == FRAMEBUFFER_COMPLETE) { - return true; - } else if (status == FRAMEBUFFER_INCOMPLETE_ATTACHMENT) { - System.err.println(String.format(FRAMEBUFFER_ERROR, - "incomplete attachment")); - } else if (status == FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) { - System.err.println(String.format(FRAMEBUFFER_ERROR, - "incomplete missing attachment")); - } else if (status == FRAMEBUFFER_INCOMPLETE_DIMENSIONS) { - System.err.println(String.format(FRAMEBUFFER_ERROR, - "incomplete dimensions")); - } else if (status == FRAMEBUFFER_INCOMPLETE_FORMATS) { - System.err.println(String.format(FRAMEBUFFER_ERROR, - "incomplete formats")); - } else if (status == FRAMEBUFFER_UNSUPPORTED) { - System.err.println(String.format(FRAMEBUFFER_ERROR, - "framebuffer unsupported")); - } else { - System.err.println(String.format(FRAMEBUFFER_ERROR, - "unknown error")); - } - return false; - } - - protected boolean isES() { - return getString(VERSION).trim().toLowerCase().contains("opengl es"); - } - - protected int[] getGLVersion() { - String version = getString(VERSION).trim().toLowerCase(); - - String ES = "opengl es"; - int esPosition = version.indexOf(ES); - if (esPosition >= 0) { - version = version.substring(esPosition + ES.length()).trim(); - } - - int[] res = {0, 0, 0}; - String[] parts = version.split(" "); - for (int i = 0; i < parts.length; i++) { - if (0 < parts[i].indexOf(".")) { - String nums[] = parts[i].split("\\."); - try { - res[0] = Integer.parseInt(nums[0]); - } catch (NumberFormatException e) { } - if (1 < nums.length) { - try { - res[1] = Integer.parseInt(nums[1]); - } catch (NumberFormatException e) { } - } - if (2 < nums.length) { - try { - res[2] = Integer.parseInt(nums[2]); - } catch (NumberFormatException e) { } - } - break; - } - } - return res; - } - - - protected boolean hasFBOs() { - // FBOs might still be available through extensions. - int major = getGLVersion()[0]; - if (major < 2) { - String ext = getString(EXTENSIONS); - return ext.indexOf("_framebuffer_object") != -1 && - ext.indexOf("_vertex_shader") != -1 && - ext.indexOf("_shader_objects") != -1 && - ext.indexOf("_shading_language") != -1; - } else { - return true; - } - } - - - protected boolean hasShaders() { - // GLSL might still be available through extensions. For instance, - // GLContext.hasGLSL() gives false for older intel integrated chipsets on - // OSX, where OpenGL is 1.4 but shaders are available. - int major = getGLVersion()[0]; - if (major < 2) { - String ext = getString(EXTENSIONS); - return ext.indexOf("_fragment_shader") != -1 && - ext.indexOf("_vertex_shader") != -1 && - ext.indexOf("_shader_objects") != -1 && - ext.indexOf("_shading_language") != -1; - } else { - return true; - } - } - - - protected boolean hasNpotTexSupport() { - int major = getGLVersion()[0]; - if (major < 3) { - String ext = getString(EXTENSIONS); - return -1 < ext.indexOf("_texture_non_power_of_two"); - } else { - return true; - } - } - - - protected boolean hasAutoMipmapGenSupport() { - int major = getGLVersion()[0]; - if (major < 3) { - String ext = getString(EXTENSIONS); - return -1 < ext.indexOf("_generate_mipmap"); - } else { - return true; - } - } - - - protected boolean hasFboMultisampleSupport() { - int major = getGLVersion()[0]; - if (major < 3) { - String ext = getString(EXTENSIONS); - return -1 < ext.indexOf("_framebuffer_multisample"); - } else { - return true; - } - } - - - protected boolean hasPackedDepthStencilSupport() { - int major = getGLVersion()[0]; - if (major < 3) { - String ext = getString(EXTENSIONS); - return -1 < ext.indexOf("_packed_depth_stencil"); - } else { - return true; - } - } - - - protected boolean hasAnisoSamplingSupport() { - int major = getGLVersion()[0]; - if (major < 3) { - String ext = getString(EXTENSIONS); - return -1 < ext.indexOf("_texture_filter_anisotropic"); - } else { - return true; - } - } - - - protected boolean hasSynchronization() { - int[] version = getGLVersion(); - if (isES()) { - return version[0] >= 3; - } - return (version[0] > 3) || (version[0] == 3 && version[1] >= 2); - } - - - protected boolean hasPBOs() { - int[] version = getGLVersion(); - if (isES()) { - return version[0] >= 3; - } - return (version[0] > 2) || (version[0] == 2 && version[1] >= 1); - } - - - protected boolean hasReadBuffer() { - int[] version = getGLVersion(); - if (isES()) { - return version[0] >= 3; - } - return version[0] >= 2; - } - - - protected boolean hasDrawBuffer() { - int[] version = getGLVersion(); - if (isES()) { - return version[0] >= 3; - } - return version[0] >= 2; - } - - - protected int maxSamples() { - intBuffer.rewind(); - getIntegerv(MAX_SAMPLES, intBuffer); - return intBuffer.get(0); - } - - - protected int getMaxTexUnits() { - intBuffer.rewind(); - getIntegerv(MAX_TEXTURE_IMAGE_UNITS, intBuffer); - return intBuffer.get(0); - } - - - protected static ByteBuffer allocateDirectByteBuffer(int size) { - int bytes = PApplet.max(MIN_DIRECT_BUFFER_SIZE, size) * SIZEOF_BYTE; - return ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()); - } - - - protected static ByteBuffer allocateByteBuffer(int size) { - if (USE_DIRECT_BUFFERS) { - return allocateDirectByteBuffer(size); - } else { - return ByteBuffer.allocate(size); - } - } - - - protected static ByteBuffer allocateByteBuffer(byte[] arr) { - if (USE_DIRECT_BUFFERS) { - ByteBuffer buf = allocateDirectByteBuffer(arr.length); - buf.put(arr); - buf.position(0); - return buf; - } else { - return ByteBuffer.wrap(arr); - } - } - - - protected static ByteBuffer updateByteBuffer(ByteBuffer buf, byte[] arr, - boolean wrap) { - if (USE_DIRECT_BUFFERS) { - if (buf == null || buf.capacity() < arr.length) { - buf = allocateDirectByteBuffer(arr.length); - } - buf.position(0); - buf.put(arr); - buf.rewind(); - } else { - if (wrap) { - buf = ByteBuffer.wrap(arr); - } else { - if (buf == null || buf.capacity() < arr.length) { - buf = ByteBuffer.allocate(arr.length); - } - buf.position(0); - buf.put(arr); - buf.rewind(); - } - } - return buf; - } - - - protected static void updateByteBuffer(ByteBuffer buf, byte[] arr, - int offset, int size) { - if (USE_DIRECT_BUFFERS || (buf.hasArray() && buf.array() != arr)) { - buf.position(offset); - buf.put(arr, offset, size); - buf.rewind(); - } - } - - - protected static void getByteArray(ByteBuffer buf, byte[] arr) { - if (!buf.hasArray() || buf.array() != arr) { - buf.position(0); - buf.get(arr); - buf.rewind(); - } - } - - - protected static void putByteArray(ByteBuffer buf, byte[] arr) { - if (!buf.hasArray() || buf.array() != arr) { - buf.position(0); - buf.put(arr); - buf.rewind(); - } - } - - - protected static void fillByteBuffer(ByteBuffer buf, int i0, int i1, - byte val) { - int n = i1 - i0; - byte[] temp = new byte[n]; - Arrays.fill(temp, 0, n, val); - buf.position(i0); - buf.put(temp, 0, n); - buf.rewind(); - } - - - protected static ShortBuffer allocateDirectShortBuffer(int size) { - int bytes = PApplet.max(MIN_DIRECT_BUFFER_SIZE, size) * SIZEOF_SHORT; - return ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()). - asShortBuffer(); - } - - - protected static ShortBuffer allocateShortBuffer(int size) { - if (USE_DIRECT_BUFFERS) { - return allocateDirectShortBuffer(size); - } else { - return ShortBuffer.allocate(size); - } - } - - - protected static ShortBuffer allocateShortBuffer(short[] arr) { - if (USE_DIRECT_BUFFERS) { - ShortBuffer buf = allocateDirectShortBuffer(arr.length); - buf.put(arr); - buf.position(0); - return buf; - } else { - return ShortBuffer.wrap(arr); - } - } - - - protected static ShortBuffer updateShortBuffer(ShortBuffer buf, short[] arr, - boolean wrap) { - if (USE_DIRECT_BUFFERS) { - if (buf == null || buf.capacity() < arr.length) { - buf = allocateDirectShortBuffer(arr.length); - } - buf.position(0); - buf.put(arr); - buf.rewind(); - } else { - if (wrap) { - buf = ShortBuffer.wrap(arr); - } else { - if (buf == null || buf.capacity() < arr.length) { - buf = ShortBuffer.allocate(arr.length); - } - buf.position(0); - buf.put(arr); - buf.rewind(); - } - } - return buf; - } - - - protected static void updateShortBuffer(ShortBuffer buf, short[] arr, - int offset, int size) { - if (USE_DIRECT_BUFFERS || (buf.hasArray() && buf.array() != arr)) { - buf.position(offset); - buf.put(arr, offset, size); - buf.rewind(); - } - } - - - protected static void getShortArray(ShortBuffer buf, short[] arr) { - if (!buf.hasArray() || buf.array() != arr) { - buf.position(0); - buf.get(arr); - buf.rewind(); - } - } - - - protected static void putShortArray(ShortBuffer buf, short[] arr) { - if (!buf.hasArray() || buf.array() != arr) { - buf.position(0); - buf.put(arr); - buf.rewind(); - } - } - - - protected static void fillShortBuffer(ShortBuffer buf, int i0, int i1, - short val) { - int n = i1 - i0; - short[] temp = new short[n]; - Arrays.fill(temp, 0, n, val); - buf.position(i0); - buf.put(temp, 0, n); - buf.rewind(); - } - - - protected static IntBuffer allocateDirectIntBuffer(int size) { - int bytes = PApplet.max(MIN_DIRECT_BUFFER_SIZE, size) * SIZEOF_INT; - return ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()). - asIntBuffer(); - } - - - protected static IntBuffer allocateIntBuffer(int size) { - if (USE_DIRECT_BUFFERS) { - return allocateDirectIntBuffer(size); - } else { - return IntBuffer.allocate(size); - } - } - - - protected static IntBuffer allocateIntBuffer(int[] arr) { - if (USE_DIRECT_BUFFERS) { - IntBuffer buf = allocateDirectIntBuffer(arr.length); - buf.put(arr); - buf.position(0); - return buf; - } else { - return IntBuffer.wrap(arr); - } - } - - - protected static IntBuffer updateIntBuffer(IntBuffer buf, int[] arr, - boolean wrap) { - if (USE_DIRECT_BUFFERS) { - if (buf == null || buf.capacity() < arr.length) { - buf = allocateDirectIntBuffer(arr.length); - } - buf.position(0); - buf.put(arr); - buf.rewind(); - } else { - if (wrap) { - buf = IntBuffer.wrap(arr); - } else { - if (buf == null || buf.capacity() < arr.length) { - buf = IntBuffer.allocate(arr.length); - } - buf.position(0); - buf.put(arr); - buf.rewind(); - } - } - return buf; - } - - - protected static void updateIntBuffer(IntBuffer buf, int[] arr, - int offset, int size) { - if (USE_DIRECT_BUFFERS || (buf.hasArray() && buf.array() != arr)) { - buf.position(offset); - buf.put(arr, offset, size); - buf.rewind(); - } - } - - - protected static void getIntArray(IntBuffer buf, int[] arr) { - if (!buf.hasArray() || buf.array() != arr) { - buf.position(0); - buf.get(arr); - buf.rewind(); - } - } - - - protected static void putIntArray(IntBuffer buf, int[] arr) { - if (!buf.hasArray() || buf.array() != arr) { - buf.position(0); - buf.put(arr); - buf.rewind(); - } - } - - - protected static void fillIntBuffer(IntBuffer buf, int i0, int i1, int val) { - int n = i1 - i0; - int[] temp = new int[n]; - Arrays.fill(temp, 0, n, val); - buf.position(i0); - buf.put(temp, 0, n); - buf.rewind(); - } - - - protected static FloatBuffer allocateDirectFloatBuffer(int size) { - int bytes = PApplet.max(MIN_DIRECT_BUFFER_SIZE, size) * SIZEOF_FLOAT; - return ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()). - asFloatBuffer(); - } - - - protected static FloatBuffer allocateFloatBuffer(int size) { - if (USE_DIRECT_BUFFERS) { - return allocateDirectFloatBuffer(size); - } else { - return FloatBuffer.allocate(size); - } - } - - - protected static FloatBuffer allocateFloatBuffer(float[] arr) { - if (USE_DIRECT_BUFFERS) { - FloatBuffer buf = allocateDirectFloatBuffer(arr.length); - buf.put(arr); - buf.position(0); - return buf; - } else { - return FloatBuffer.wrap(arr); - } - } - - - protected static FloatBuffer updateFloatBuffer(FloatBuffer buf, float[] arr, - boolean wrap) { - if (USE_DIRECT_BUFFERS) { - if (buf == null || buf.capacity() < arr.length) { - buf = allocateDirectFloatBuffer(arr.length); - } - buf.position(0); - buf.put(arr); - buf.rewind(); - } else { - if (wrap) { - buf = FloatBuffer.wrap(arr); - } else { - if (buf == null || buf.capacity() < arr.length) { - buf = FloatBuffer.allocate(arr.length); - } - buf.position(0); - buf.put(arr); - buf.rewind(); - } - } - return buf; - } - - - protected static void updateFloatBuffer(FloatBuffer buf, float[] arr, - int offset, int size) { - if (USE_DIRECT_BUFFERS || (buf.hasArray() && buf.array() != arr)) { - buf.position(offset); - buf.put(arr, offset, size); - buf.rewind(); - } - } - - - protected static void getFloatArray(FloatBuffer buf, float[] arr) { - if (!buf.hasArray() || buf.array() != arr) { - buf.position(0); - buf.get(arr); - buf.rewind(); - } - } - - - protected static void putFloatArray(FloatBuffer buf, float[] arr) { - if (!buf.hasArray() || buf.array() != arr) { - buf.position(0); - buf.put(arr); - buf.rewind(); - } - } - - - protected static void fillFloatBuffer(FloatBuffer buf, int i0, int i1, - float val) { - int n = i1 - i0; - float[] temp = new float[n]; - Arrays.fill(temp, 0, n, val); - buf.position(i0); - buf.put(temp, 0, n); - buf.rewind(); - } - - - // TODO: the next three functions shouldn't be here... - // Uses 'Object' so that the API can be used w/ Android Typeface objects - - abstract protected int getFontAscent(Object font); - - - abstract protected int getFontDescent(Object font); - - - abstract protected int getTextWidth(Object font, char[] buffer, int start, int stop); - - - abstract protected Object getDerivedFont(Object font, float size); - - - /////////////////////////////////////////////////////////// - - // Tessellator interface - - - protected abstract Tessellator createTessellator(TessellatorCallback callback); - - - protected interface Tessellator { - public void setCallback(int flag); - public void setWindingRule(int rule); - public void setProperty(int property, int value); - - public void beginPolygon(); - public void beginPolygon(Object data); - public void endPolygon(); - public void beginContour(); - public void endContour(); - public void addVertex(double[] v); - public void addVertex(double[] v, int n, Object data); - } - - - protected interface TessellatorCallback { - public void begin(int type); - public void end(); - public void vertex(Object data); - public void combine(double[] coords, Object[] data, - float[] weight, Object[] outData); - public void error(int errnum); - } - - - protected String tessError(int err) { - return ""; - } - - - /////////////////////////////////////////////////////////// - - // FontOutline interface - - - protected static boolean SHAPE_TEXT_SUPPORTED; - protected static int SEG_MOVETO; - protected static int SEG_LINETO; - protected static int SEG_QUADTO; - protected static int SEG_CUBICTO; - protected static int SEG_CLOSE; - - - protected abstract FontOutline createFontOutline(char ch, Object font); - - - protected interface FontOutline { - public boolean isDone(); - public int currentSegment(float coords[]); - public void next(); - } - - - ////////////////////////////////////////////////////////////////////////////// - // - // OpenGL ES 2.0 API, with a few additional functions for multisampling and - // and buffer mapping from OpenGL 2.1+. - // - // The functions are organized following the groups in the GLES 2.0 reference - // card: - // http://www.khronos.org/opengles/sdk/docs/reference_cards/OpenGL-ES-2_0-Reference-card.pdf - // - // The entire GLES 2.0 specification is available below: - // http://www.khronos.org/opengles/2_X/ - // - // Implementations of the PGL functions for specific OpenGL bindings (JOGL, - // LWJGL) should simply call the corresponding GL function in the bindings. - // readPixels(), activeTexture() and bindTexture() are special cases, please - // read their comments. - // Also, keep in mind the note about the PGL constants below. - // - ////////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////// - - // Constants - // Very important note: set the GL constants in your PGL subclass by using an - // static initialization block as follows: - // static { - // FALSE = SUPER_DUPER_JAVA_OPENGL_BINDINGS.GL_FALSE; - // TRUE = SUPER_DUPER_JAVA_OPENGL_BINDINGS.GL_TRUE; - // ... - // } - // and not by re-declaring the constants, because doing so will lead to - // errors when the constants are accessed through PGL because they are not - // overridden but hidden by the new declarations, and hence they keep their - // initial values (all zeroes) when accessed through the superclass. - - public static int FALSE; - public static int TRUE; - - public static int INT; - public static int BYTE; - public static int SHORT; - public static int FLOAT; - public static int BOOL; - public static int UNSIGNED_INT; - public static int UNSIGNED_BYTE; - public static int UNSIGNED_SHORT; - - public static int RGB; - public static int RGBA; - public static int ALPHA; - public static int LUMINANCE; - public static int LUMINANCE_ALPHA; - - public static int UNSIGNED_SHORT_5_6_5; - public static int UNSIGNED_SHORT_4_4_4_4; - public static int UNSIGNED_SHORT_5_5_5_1; - - public static int RGBA4; - public static int RGB5_A1; - public static int RGB565; - public static int RGB8; - public static int RGBA8; - public static int ALPHA8; - - public static int READ_ONLY; - public static int WRITE_ONLY; - public static int READ_WRITE; - - public static int TESS_WINDING_NONZERO; - public static int TESS_WINDING_ODD; - public static int TESS_EDGE_FLAG; - - public static int GENERATE_MIPMAP_HINT; - public static int FASTEST; - public static int NICEST; - public static int DONT_CARE; - - public static int VENDOR; - public static int RENDERER; - public static int VERSION; - public static int EXTENSIONS; - public static int SHADING_LANGUAGE_VERSION; - - public static int MAX_SAMPLES; - public static int SAMPLES; - - public static int ALIASED_LINE_WIDTH_RANGE; - public static int ALIASED_POINT_SIZE_RANGE; - - public static int DEPTH_BITS; - public static int STENCIL_BITS; - - public static int CCW; - public static int CW; - - public static int VIEWPORT; - - public static int ARRAY_BUFFER; - public static int ELEMENT_ARRAY_BUFFER; - public static int PIXEL_PACK_BUFFER; - - public static int MAX_VERTEX_ATTRIBS; - - public static int STATIC_DRAW; - public static int DYNAMIC_DRAW; - public static int STREAM_DRAW; - public static int STREAM_READ; - - public static int BUFFER_SIZE; - public static int BUFFER_USAGE; - - public static int POINTS; - public static int LINE_STRIP; - public static int LINE_LOOP; - public static int LINES; - public static int TRIANGLE_FAN; - public static int TRIANGLE_STRIP; - public static int TRIANGLES; - - public static int CULL_FACE; - public static int FRONT; - public static int BACK; - public static int FRONT_AND_BACK; - - public static int POLYGON_OFFSET_FILL; - - public static int UNPACK_ALIGNMENT; - public static int PACK_ALIGNMENT; - - public static int TEXTURE_2D; - public static int TEXTURE_RECTANGLE; - - public static int TEXTURE_BINDING_2D; - public static int TEXTURE_BINDING_RECTANGLE; - - public static int MAX_TEXTURE_SIZE; - public static int TEXTURE_MAX_ANISOTROPY; - public static int MAX_TEXTURE_MAX_ANISOTROPY; - - public static int MAX_VERTEX_TEXTURE_IMAGE_UNITS; - public static int MAX_TEXTURE_IMAGE_UNITS; - public static int MAX_COMBINED_TEXTURE_IMAGE_UNITS; - - public static int NUM_COMPRESSED_TEXTURE_FORMATS; - public static int COMPRESSED_TEXTURE_FORMATS; - - public static int NEAREST; - public static int LINEAR; - public static int LINEAR_MIPMAP_NEAREST; - public static int LINEAR_MIPMAP_LINEAR; - - public static int CLAMP_TO_EDGE; - public static int REPEAT; - - public static int TEXTURE0; - public static int TEXTURE1; - public static int TEXTURE2; - public static int TEXTURE3; - public static int TEXTURE_MIN_FILTER; - public static int TEXTURE_MAG_FILTER; - public static int TEXTURE_WRAP_S; - public static int TEXTURE_WRAP_T; - public static int TEXTURE_WRAP_R; - - public static int TEXTURE_CUBE_MAP; - public static int TEXTURE_CUBE_MAP_POSITIVE_X; - public static int TEXTURE_CUBE_MAP_POSITIVE_Y; - public static int TEXTURE_CUBE_MAP_POSITIVE_Z; - public static int TEXTURE_CUBE_MAP_NEGATIVE_X; - public static int TEXTURE_CUBE_MAP_NEGATIVE_Y; - public static int TEXTURE_CUBE_MAP_NEGATIVE_Z; - - public static int VERTEX_SHADER; - public static int FRAGMENT_SHADER; - public static int INFO_LOG_LENGTH; - public static int SHADER_SOURCE_LENGTH; - public static int COMPILE_STATUS; - public static int LINK_STATUS; - public static int VALIDATE_STATUS; - public static int SHADER_TYPE; - public static int DELETE_STATUS; - - public static int FLOAT_VEC2; - public static int FLOAT_VEC3; - public static int FLOAT_VEC4; - public static int FLOAT_MAT2; - public static int FLOAT_MAT3; - public static int FLOAT_MAT4; - public static int INT_VEC2; - public static int INT_VEC3; - public static int INT_VEC4; - public static int BOOL_VEC2; - public static int BOOL_VEC3; - public static int BOOL_VEC4; - public static int SAMPLER_2D; - public static int SAMPLER_CUBE; - - public static int LOW_FLOAT; - public static int MEDIUM_FLOAT; - public static int HIGH_FLOAT; - public static int LOW_INT; - public static int MEDIUM_INT; - public static int HIGH_INT; - - public static int CURRENT_VERTEX_ATTRIB; - - public static int VERTEX_ATTRIB_ARRAY_BUFFER_BINDING; - public static int VERTEX_ATTRIB_ARRAY_ENABLED; - public static int VERTEX_ATTRIB_ARRAY_SIZE; - public static int VERTEX_ATTRIB_ARRAY_STRIDE; - public static int VERTEX_ATTRIB_ARRAY_TYPE; - public static int VERTEX_ATTRIB_ARRAY_NORMALIZED; - public static int VERTEX_ATTRIB_ARRAY_POINTER; - - public static int BLEND; - public static int ONE; - public static int ZERO; - public static int SRC_ALPHA; - public static int DST_ALPHA; - public static int ONE_MINUS_SRC_ALPHA; - public static int ONE_MINUS_DST_COLOR; - public static int ONE_MINUS_SRC_COLOR; - public static int DST_COLOR; - public static int SRC_COLOR; - - public static int SAMPLE_ALPHA_TO_COVERAGE; - public static int SAMPLE_COVERAGE; - - public static int KEEP; - public static int REPLACE; - public static int INCR; - public static int DECR; - public static int INVERT; - public static int INCR_WRAP; - public static int DECR_WRAP; - public static int NEVER; - public static int ALWAYS; - - public static int EQUAL; - public static int LESS; - public static int LEQUAL; - public static int GREATER; - public static int GEQUAL; - public static int NOTEQUAL; - - public static int FUNC_ADD; - public static int FUNC_MIN; - public static int FUNC_MAX; - public static int FUNC_REVERSE_SUBTRACT; - public static int FUNC_SUBTRACT; - - public static int DITHER; - - public static int CONSTANT_COLOR; - public static int CONSTANT_ALPHA; - public static int ONE_MINUS_CONSTANT_COLOR; - public static int ONE_MINUS_CONSTANT_ALPHA; - public static int SRC_ALPHA_SATURATE; - - public static int SCISSOR_TEST; - public static int STENCIL_TEST; - public static int DEPTH_TEST; - public static int DEPTH_WRITEMASK; - - public static int COLOR_BUFFER_BIT; - public static int DEPTH_BUFFER_BIT; - public static int STENCIL_BUFFER_BIT; - - public static int FRAMEBUFFER; - public static int COLOR_ATTACHMENT0; - public static int COLOR_ATTACHMENT1; - public static int COLOR_ATTACHMENT2; - public static int COLOR_ATTACHMENT3; - public static int RENDERBUFFER; - public static int DEPTH_ATTACHMENT; - public static int STENCIL_ATTACHMENT; - public static int READ_FRAMEBUFFER; - public static int DRAW_FRAMEBUFFER; - - public static int DEPTH24_STENCIL8; - - public static int DEPTH_COMPONENT; - public static int DEPTH_COMPONENT16; - public static int DEPTH_COMPONENT24; - public static int DEPTH_COMPONENT32; - - public static int STENCIL_INDEX; - public static int STENCIL_INDEX1; - public static int STENCIL_INDEX4; - public static int STENCIL_INDEX8; - - public static int DEPTH_STENCIL; - - public static int FRAMEBUFFER_COMPLETE; - public static int FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - public static int FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; - public static int FRAMEBUFFER_INCOMPLETE_DIMENSIONS; - public static int FRAMEBUFFER_INCOMPLETE_FORMATS; - public static int FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER; - public static int FRAMEBUFFER_INCOMPLETE_READ_BUFFER; - public static int FRAMEBUFFER_UNSUPPORTED; - - public static int FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE; - public static int FRAMEBUFFER_ATTACHMENT_OBJECT_NAME; - public static int FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL; - public static int FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE; - - public static int RENDERBUFFER_WIDTH; - public static int RENDERBUFFER_HEIGHT; - public static int RENDERBUFFER_RED_SIZE; - public static int RENDERBUFFER_GREEN_SIZE; - public static int RENDERBUFFER_BLUE_SIZE; - public static int RENDERBUFFER_ALPHA_SIZE; - public static int RENDERBUFFER_DEPTH_SIZE; - public static int RENDERBUFFER_STENCIL_SIZE; - public static int RENDERBUFFER_INTERNAL_FORMAT; - - public static int MULTISAMPLE; - public static int LINE_SMOOTH; - public static int POLYGON_SMOOTH; - - public static int SYNC_GPU_COMMANDS_COMPLETE; - public static int ALREADY_SIGNALED; - public static int CONDITION_SATISFIED; - - /////////////////////////////////////////////////////////// - - // Special Functions - - public abstract void flush(); - public abstract void finish(); - public abstract void hint(int target, int hint); - - /////////////////////////////////////////////////////////// - - // State and State Requests - - public abstract void enable(int value); - public abstract void disable(int value); - public abstract void getBooleanv(int value, IntBuffer data); - public abstract void getIntegerv(int value, IntBuffer data); - public abstract void getFloatv(int value, FloatBuffer data); - public abstract boolean isEnabled(int value); - public abstract String getString(int name); - - /////////////////////////////////////////////////////////// - - // Error Handling - - public abstract int getError(); - public abstract String errorString(int err); - - ////////////////////////////////////////////////////////////////////////////// - - // Buffer Objects - - public abstract void genBuffers(int n, IntBuffer buffers); - public abstract void deleteBuffers(int n, IntBuffer buffers); - public abstract void bindBuffer(int target, int buffer); - public abstract void bufferData(int target, int size, Buffer data, int usage); - public abstract void bufferSubData(int target, int offset, int size, Buffer data); - public abstract void isBuffer(int buffer); - public abstract void getBufferParameteriv(int target, int value, IntBuffer data); - public abstract ByteBuffer mapBuffer(int target, int access); - public abstract ByteBuffer mapBufferRange(int target, int offset, int length, int access); - public abstract void unmapBuffer(int target); - - ////////////////////////////////////////////////////////////////////////////// - - // Synchronization - - public abstract long fenceSync(int condition, int flags); - public abstract void deleteSync(long sync); - public abstract int clientWaitSync(long sync, int flags, long timeout); - - ////////////////////////////////////////////////////////////////////////////// - - // Viewport and Clipping - - public abstract void depthRangef(float n, float f); - public abstract void viewport(int x, int y, int w, int h); - protected abstract void viewportImpl(int x, int y, int w, int h); - - ////////////////////////////////////////////////////////////////////////////// - - // Reading Pixels - // This is a special case: because the renderer might be using an FBO even on - // the main surface, some extra handling might be needed before and after - // reading the pixels. To make this transparent to the user, the actual call - // to glReadPixels() should be done in readPixelsImpl(). - - public void readPixels(int x, int y, int width, int height, int format, int type, Buffer buffer){ - boolean multisampled = isMultisampled() || graphics.offscreenMultisample; - boolean depthReadingEnabled = graphics.getHint(PConstants.ENABLE_BUFFER_READING); - boolean depthRequested = format == STENCIL_INDEX || format == DEPTH_COMPONENT || format == DEPTH_STENCIL; - - if (multisampled && depthRequested && !depthReadingEnabled) { - PGraphics.showWarning(DEPTH_READING_NOT_ENABLED_ERROR); - return; - } - - graphics.beginReadPixels(); - readPixelsImpl(x, y, width, height, format, type, buffer); - graphics.endReadPixels(); - } - - public void readPixels(int x, int y, int width, int height, int format, int type, long offset){ - boolean multisampled = isMultisampled() || graphics.offscreenMultisample; - boolean depthReadingEnabled = graphics.getHint(PConstants.ENABLE_BUFFER_READING); - boolean depthRequested = format == STENCIL_INDEX || format == DEPTH_COMPONENT || format == DEPTH_STENCIL; - - if (multisampled && depthRequested && !depthReadingEnabled) { - PGraphics.showWarning(DEPTH_READING_NOT_ENABLED_ERROR); - return; - } - - graphics.beginReadPixels(); - readPixelsImpl(x, y, width, height, format, type, offset); - graphics.endReadPixels(); - } - - protected abstract void readPixelsImpl(int x, int y, int width, int height, int format, int type, Buffer buffer); - protected abstract void readPixelsImpl(int x, int y, int width, int height, int format, int type, long offset); - - ////////////////////////////////////////////////////////////////////////////// - - // Vertices - - public abstract void vertexAttrib1f(int index, float value); - public abstract void vertexAttrib2f(int index, float value0, float value1); - public abstract void vertexAttrib3f(int index, float value0, float value1, float value2); - public abstract void vertexAttrib4f(int index, float value0, float value1, float value2, float value3); - public abstract void vertexAttrib1fv(int index, FloatBuffer values); - public abstract void vertexAttrib2fv(int index, FloatBuffer values); - public abstract void vertexAttrib3fv(int index, FloatBuffer values); - public abstract void vertexAttrib4fv(int index, FloatBuffer values); - public abstract void vertexAttribPointer(int index, int size, int type, boolean normalized, int stride, int offset); - public abstract void enableVertexAttribArray(int index); - public abstract void disableVertexAttribArray(int index); - - public void drawArrays(int mode, int first, int count) { - geomCount += count; - drawArraysImpl(mode, first, count); - } - - public abstract void drawArraysImpl(int mode, int first, int count); - - public void drawElements(int mode, int count, int type, int offset) { - geomCount += count; - drawElementsImpl(mode, count, type, offset); - } - - public abstract void drawElementsImpl(int mode, int count, int type, int offset); - - ////////////////////////////////////////////////////////////////////////////// - - // Rasterization - - public abstract void lineWidth(float width); - public abstract void frontFace(int dir); - public abstract void cullFace(int mode); - public abstract void polygonOffset(float factor, float units); - - ////////////////////////////////////////////////////////////////////////////// - - // Pixel Rectangles - - public abstract void pixelStorei(int pname, int param); - - /////////////////////////////////////////////////////////// - - // Texturing - - public abstract void texImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, Buffer data); - public abstract void copyTexImage2D(int target, int level, int internalFormat, int x, int y, int width, int height, int border); - public abstract void texSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int type, Buffer data); - public abstract void copyTexSubImage2D(int target, int level, int xOffset, int yOffset, int x, int y, int width, int height); - public abstract void compressedTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int imageSize, Buffer data); - public abstract void compressedTexSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int imageSize, Buffer data); - public abstract void texParameteri(int target, int pname, int param); - public abstract void texParameterf(int target, int pname, float param); - public abstract void texParameteriv(int target, int pname, IntBuffer params); - public abstract void texParameterfv(int target, int pname, FloatBuffer params); - public abstract void generateMipmap(int target); - public abstract void genTextures(int n, IntBuffer textures); - public abstract void deleteTextures(int n, IntBuffer textures); - public abstract void getTexParameteriv(int target, int pname, IntBuffer params); - public abstract void getTexParameterfv(int target, int pname, FloatBuffer params); - public abstract boolean isTexture(int texture); - - // activeTexture() and bindTexture() have some extra logic to keep track of - // the bound textures, so the actual GL call should go in activeTextureImpl() - // and bindTextureImpl(). - public void activeTexture(int texture) { - activeTexUnit = texture - TEXTURE0; - activeTextureImpl(texture); - } - - protected abstract void activeTextureImpl(int texture); - - public void bindTexture(int target, int texture) { - bindTextureImpl(target, texture); - - if (boundTextures == null) { - maxTexUnits = getMaxTexUnits(); - boundTextures = new int[maxTexUnits][2]; - } - - if (maxTexUnits <= activeTexUnit) { - throw new RuntimeException(TEXUNIT_ERROR); - } - - if (target == TEXTURE_2D) { - boundTextures[activeTexUnit][0] = texture; - } else if (target == TEXTURE_RECTANGLE) { - boundTextures[activeTexUnit][1] = texture; - } - } - protected abstract void bindTextureImpl(int target, int texture); - - /////////////////////////////////////////////////////////// - - // Shaders and Programs - - public abstract int createShader(int type); - public abstract void shaderSource(int shader, String source); - public abstract void compileShader(int shader); - public abstract void releaseShaderCompiler(); - public abstract void deleteShader(int shader); - public abstract void shaderBinary(int count, IntBuffer shaders, int binaryFormat, Buffer binary, int length); - public abstract int createProgram(); - public abstract void attachShader(int program, int shader); - public abstract void detachShader(int program, int shader); - public abstract void linkProgram(int program); - public abstract void useProgram(int program); - public abstract void deleteProgram(int program); - public abstract String getActiveAttrib(int program, int index, IntBuffer size, IntBuffer type); - public abstract int getAttribLocation(int program, String name); - public abstract void bindAttribLocation(int program, int index, String name); - public abstract int getUniformLocation(int program, String name); - public abstract String getActiveUniform(int program, int index, IntBuffer size, IntBuffer type); - public abstract void uniform1i(int location, int value); - public abstract void uniform2i(int location, int value0, int value1); - public abstract void uniform3i(int location, int value0, int value1, int value2); - public abstract void uniform4i(int location, int value0, int value1, int value2, int value3); - public abstract void uniform1f(int location, float value); - public abstract void uniform2f(int location, float value0, float value1); - public abstract void uniform3f(int location, float value0, float value1, float value2); - public abstract void uniform4f(int location, float value0, float value1, float value2, float value3); - public abstract void uniform1iv(int location, int count, IntBuffer v); - public abstract void uniform2iv(int location, int count, IntBuffer v); - public abstract void uniform3iv(int location, int count, IntBuffer v); - public abstract void uniform4iv(int location, int count, IntBuffer v); - public abstract void uniform1fv(int location, int count, FloatBuffer v); - public abstract void uniform2fv(int location, int count, FloatBuffer v); - public abstract void uniform3fv(int location, int count, FloatBuffer v); - public abstract void uniform4fv(int location, int count, FloatBuffer v); - public abstract void uniformMatrix2fv(int location, int count, boolean transpose, FloatBuffer mat); - public abstract void uniformMatrix3fv(int location, int count, boolean transpose, FloatBuffer mat); - public abstract void uniformMatrix4fv(int location, int count, boolean transpose, FloatBuffer mat); - public abstract void validateProgram(int program); - public abstract boolean isShader(int shader); - public abstract void getShaderiv(int shader, int pname, IntBuffer params); - public abstract void getAttachedShaders(int program, int maxCount, IntBuffer count, IntBuffer shaders); - public abstract String getShaderInfoLog(int shader); - public abstract String getShaderSource(int shader); - public abstract void getShaderPrecisionFormat(int shaderType, int precisionType, IntBuffer range, IntBuffer precision); - public abstract void getVertexAttribfv(int index, int pname, FloatBuffer params); - public abstract void getVertexAttribiv(int index, int pname, IntBuffer params); - public abstract void getVertexAttribPointerv(int index, int pname, ByteBuffer data); - public abstract void getUniformfv(int program, int location, FloatBuffer params); - public abstract void getUniformiv(int program, int location, IntBuffer params); - public abstract boolean isProgram(int program); - public abstract void getProgramiv(int program, int pname, IntBuffer params); - public abstract String getProgramInfoLog(int program); - - /////////////////////////////////////////////////////////// - - // Per-Fragment Operations - - public abstract void scissor(int x, int y, int w, int h); - public abstract void sampleCoverage(float value, boolean invert); - public abstract void stencilFunc(int func, int ref, int mask); - public abstract void stencilFuncSeparate(int face, int func, int ref, int mask); - public abstract void stencilOp(int sfail, int dpfail, int dppass); - public abstract void stencilOpSeparate(int face, int sfail, int dpfail, int dppass); - public abstract void depthFunc(int func); - public abstract void blendEquation(int mode); - public abstract void blendEquationSeparate(int modeRGB, int modeAlpha); - public abstract void blendFunc(int src, int dst); - public abstract void blendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha); - public abstract void blendColor(float red, float green, float blue, float alpha); - - /////////////////////////////////////////////////////////// - - // Whole Framebuffer Operations - - public abstract void colorMask(boolean r, boolean g, boolean b, boolean a); - public abstract void depthMask(boolean mask); - public abstract void stencilMask(int mask); - public abstract void stencilMaskSeparate(int face, int mask); - public abstract void clearColor(float r, float g, float b, float a); - public abstract void clearDepth(float d); - public abstract void clearStencil(int s); - public abstract void clear(int buf); - - /////////////////////////////////////////////////////////// - - // Framebuffers Objects - - public void bindFramebuffer(int target, int framebuffer) { - graphics.beginBindFramebuffer(target, framebuffer); - bindFramebufferImpl(target, framebuffer); - graphics.endBindFramebuffer(target, framebuffer); - } - protected abstract void bindFramebufferImpl(int target, int framebuffer); - - public abstract void deleteFramebuffers(int n, IntBuffer framebuffers); - public abstract void genFramebuffers(int n, IntBuffer framebuffers); - public abstract void bindRenderbuffer(int target, int renderbuffer); - public abstract void deleteRenderbuffers(int n, IntBuffer renderbuffers); - public abstract void genRenderbuffers(int n, IntBuffer renderbuffers); - public abstract void renderbufferStorage(int target, int internalFormat, int width, int height); - public abstract void framebufferRenderbuffer(int target, int attachment, int rendbuferfTarget, int renderbuffer); - public abstract void framebufferTexture2D(int target, int attachment, int texTarget, int texture, int level); - public abstract int checkFramebufferStatus(int target); - public abstract boolean isFramebuffer(int framebuffer); - public abstract void getFramebufferAttachmentParameteriv(int target, int attachment, int pname, IntBuffer params); - public abstract boolean isRenderbuffer(int renderbuffer); - public abstract void getRenderbufferParameteriv(int target, int pname, IntBuffer params); - public abstract void blitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter); - public abstract void renderbufferStorageMultisample(int target, int samples, int format, int width, int height); - public abstract void readBuffer(int buf); - public abstract void drawBuffer(int buf); -} diff --git a/core/src/processing/opengl/PGLES.java b/core/src/processing/opengl/PGLES.java deleted file mode 100644 index e31799170..000000000 --- a/core/src/processing/opengl/PGLES.java +++ /dev/null @@ -1,1609 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.opengles.GL10; - -import android.opengl.GLES20; -import android.opengl.GLSurfaceView; -import android.opengl.GLU; -import android.view.SurfaceView; - -import processing.opengl.tess.PGLU; -import processing.opengl.tess.PGLUtessellator; -import processing.opengl.tess.PGLUtessellatorCallbackAdapter; - -public class PGLES extends PGL { - // ........................................................ - - // Public members to access the underlying GL objects and glview - - /** Basic GLES 1.0 interface */ - public GL10 gl; - - /** GLU interface **/ - public PGLU glu; - - /** The current opengl context */ - public EGLContext context; - - /** The current surface view */ - public GLSurfaceView glview; - - - /** Requested major version of the OpenGL ES context */ - static public int version = 2; - - // ........................................................ - - // Static initialization for some parameters that need to be different for - // GLES - - static { - SINGLE_BUFFERED = true; - - MIN_DIRECT_BUFFER_SIZE = 1; - INDEX_TYPE = GLES20.GL_UNSIGNED_SHORT; - - MIPMAPS_ENABLED = false; - - DEFAULT_IN_VERTICES = 16; - DEFAULT_IN_EDGES = 32; - DEFAULT_IN_TEXTURES = 16; - DEFAULT_TESS_VERTICES = 16; - DEFAULT_TESS_INDICES = 32; - - MIN_FONT_TEX_SIZE = 128; - MAX_FONT_TEX_SIZE = 512; - - MAX_CAPS_JOINS_LENGTH = 1000; - } - - // Some EGL constants needed to initialize a GLES2 context. - public static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; - public static final int EGL_OPENGL_ES2_BIT = 0x0004; - - // Coverage multisampling identifiers for nVidia Tegra2 - public static final int EGL_COVERAGE_BUFFERS_NV = 0x30E0; - public static final int EGL_COVERAGE_SAMPLES_NV = 0x30E1; - public static final int GL_COVERAGE_BUFFER_BIT_NV = 0x8000; - - public static boolean usingMultisampling = false; - public static boolean usingCoverageMultisampling = false; - public static int multisampleCount = 1; - - /////////////////////////////////////////////////////////// - - // Initialization, finalization - - - public PGLES(PGraphicsOpenGL pg) { - super(pg); - glu = new PGLU(); - } - - - @Override - public GLSurfaceView getNative() { - return glview; - } - - - @Override - public void queueEvent(Runnable runnable) { - if (glview != null) { - glview.queueEvent(runnable); - } - } - - - @Override - protected void initSurface(int antialias) { - SurfaceView surf = sketch.getSurface().getSurfaceView(); - if (surf != null) { - glview = (GLSurfaceView)surf; - } - reqNumSamples = qualityToSamples(antialias); - registerListeners(); - } - - - @Override - protected void reinitSurface() { } - - - @Override - protected void registerListeners() { } - - - @Override - protected int getDepthBits() { - intBuffer.rewind(); - getIntegerv(DEPTH_BITS, intBuffer); - return intBuffer.get(0); - } - - - @Override - protected int getStencilBits() { - intBuffer.rewind(); - getIntegerv(STENCIL_BITS, intBuffer); - return intBuffer.get(0); - } - - - @Override - protected int getDefaultDrawBuffer() { - return fboLayerEnabled ? COLOR_ATTACHMENT0 : FRONT; - } - - - @Override - protected int getDefaultReadBuffer() { - return fboLayerEnabled ? COLOR_ATTACHMENT0 : FRONT; - } - - - public void init(GL10 igl) { - gl = igl; - context = ((EGL10)EGLContext.getEGL()).eglGetCurrentContext(); - glContext = context.hashCode(); - glThread = Thread.currentThread(); - - if (!hasFBOs()) { - throw new RuntimeException(PGL.MISSING_FBO_ERROR); - } - if (!hasShaders()) { - throw new RuntimeException(PGL.MISSING_GLSL_ERROR); - } - } - - - /////////////////////////////////////////////////////////// - - // Frame rendering - - - @Override - protected float getPixelScale() { - return 1; - } - - - @Override - protected void getGL(PGL pgl) { - PGLES pgles = (PGLES)pgl; - this.gl = pgles.gl; - setThread(pgles.glThread); - } - - public void getGL(GL10 igl) { - gl = igl; - glThread = Thread.currentThread(); - } - - - @Override - protected boolean canDraw() { return true; } - - - @Override - protected void requestFocus() { } - - - @Override - protected void requestDraw() { } - - - @Override - protected void swapBuffers() { } - - - @Override - protected int getGLSLVersion() { - return 100; - } - - - @Override - protected void initFBOLayer() { - if (0 < sketch.frameCount) { - IntBuffer buf = allocateDirectIntBuffer(fboWidth * fboHeight); - - if (hasReadBuffer()) readBuffer(BACK); - readPixelsImpl(0, 0, fboWidth, fboHeight, RGBA, UNSIGNED_BYTE, buf); - bindTexture(TEXTURE_2D, glColorTex.get(frontTex)); - texSubImage2D(TEXTURE_2D, 0, 0, 0, fboWidth, fboHeight, RGBA, UNSIGNED_BYTE, buf); - - bindTexture(TEXTURE_2D, glColorTex.get(backTex)); - texSubImage2D(TEXTURE_2D, 0, 0, 0, fboWidth, fboHeight, RGBA, UNSIGNED_BYTE, buf); - - bindTexture(TEXTURE_2D, 0); - bindFramebufferImpl(FRAMEBUFFER, 0); - } - } - - - @Override - protected void clearFrontColorBuffer() { - // Need to front clear color buffer, otherwise one can lead to the screen not clearning - // properly in sketches that do not call background() continously in draw() but only at - // specific events. - framebufferTexture2D(FRAMEBUFFER, COLOR_ATTACHMENT0, - TEXTURE_2D, glColorTex.get(frontTex), 0); - clear(COLOR_BUFFER_BIT); - framebufferTexture2D(FRAMEBUFFER, COLOR_ATTACHMENT0, - TEXTURE_2D, glColorTex.get(backTex), 0); - } - - - /////////////////////////////////////////////////////////// - - // Tessellator interface - - - @Override - protected Tessellator createTessellator(TessellatorCallback callback) { - return new Tessellator(callback); - } - - - protected class Tessellator implements PGL.Tessellator { - protected PGLUtessellator tess; - protected TessellatorCallback callback; - protected GLUCallback gluCallback; - - public Tessellator(TessellatorCallback callback) { - this.callback = callback; - tess = PGLU.gluNewTess(); - gluCallback = new GLUCallback(); - - PGLU.gluTessCallback(tess, PGLU.GLU_TESS_BEGIN, gluCallback); - PGLU.gluTessCallback(tess, PGLU.GLU_TESS_END, gluCallback); - PGLU.gluTessCallback(tess, PGLU.GLU_TESS_VERTEX, gluCallback); - PGLU.gluTessCallback(tess, PGLU.GLU_TESS_COMBINE, gluCallback); - PGLU.gluTessCallback(tess, PGLU.GLU_TESS_ERROR, gluCallback); - } - - @Override - public void setCallback(int flag) { - PGLU.gluTessCallback(tess, flag, gluCallback); - } - - @Override - public void setWindingRule(int rule) { - setProperty(PGLU.GLU_TESS_WINDING_RULE, rule); - } - - public void setProperty(int property, int value) { - PGLU.gluTessProperty(tess, property, value); - } - - @Override - public void beginPolygon() { - beginPolygon(null); - } - - @Override - public void beginPolygon(Object data) { - PGLU.gluTessBeginPolygon(tess, data); - } - - @Override - public void endPolygon() { - PGLU.gluTessEndPolygon(tess); - } - - @Override - public void beginContour() { - PGLU.gluTessBeginContour(tess); - } - - @Override - public void endContour() { - PGLU.gluTessEndContour(tess); - } - - @Override - public void addVertex(double[] v) { - addVertex(v, 0, v); - } - - @Override - public void addVertex(double[] v, int n, Object data) { - PGLU.gluTessVertex(tess, v, n, data); - } - - protected class GLUCallback extends PGLUtessellatorCallbackAdapter { - @Override - public void begin(int type) { - callback.begin(type); - } - - @Override - public void end() { - callback.end(); - } - - @Override - public void vertex(Object data) { - callback.vertex(data); - } - - @Override - public void combine(double[] coords, Object[] data, - float[] weight, Object[] outData) { - callback.combine(coords, data, weight, outData); - } - - @Override - public void error(int errnum) { - callback.error(errnum); - } - } - } - - - @Override - protected String tessError(int err) { - return PGLU.gluErrorString(err); - } - - - /////////////////////////////////////////////////////////// - - // Font outline - - - static { - SHAPE_TEXT_SUPPORTED = false; - } - - - @Override - protected FontOutline createFontOutline(char ch, Object font) { - return null; - } - - - /////////////////////////////////////////////////////////// - - // Constants - // - // The values for constants not defined in the GLES20 interface can be found - // in this file: - // http://code.metager.de/source/xref/android/4.0.3/development/tools/glesv2debugger/src/com/android/glesv2debugger/GLEnum.java - - - static { - FALSE = GLES20.GL_FALSE; - TRUE = GLES20.GL_TRUE; - - INT = GLES20.GL_INT; - BYTE = GLES20.GL_BYTE; - SHORT = GLES20.GL_SHORT; - FLOAT = GLES20.GL_FLOAT; - BOOL = GLES20.GL_BOOL; - UNSIGNED_INT = GLES20.GL_UNSIGNED_INT; - UNSIGNED_BYTE = GLES20.GL_UNSIGNED_BYTE; - UNSIGNED_SHORT = GLES20.GL_UNSIGNED_SHORT; - - RGB = GLES20.GL_RGB; - RGBA = GLES20.GL_RGBA; - ALPHA = GLES20.GL_ALPHA; - LUMINANCE = GLES20.GL_LUMINANCE; - LUMINANCE_ALPHA = GLES20.GL_LUMINANCE_ALPHA; - - UNSIGNED_SHORT_5_6_5 = GLES20.GL_UNSIGNED_SHORT_5_6_5; - UNSIGNED_SHORT_4_4_4_4 = GLES20.GL_UNSIGNED_SHORT_4_4_4_4; - UNSIGNED_SHORT_5_5_5_1 = GLES20.GL_UNSIGNED_SHORT_5_5_5_1; - - RGBA4 = GLES20.GL_RGBA4; - RGB5_A1 = GLES20.GL_RGB5_A1; - RGB565 = GLES20.GL_RGB565; - RGB8 = 0x8051; - RGBA8 = 0x8058; - ALPHA8 = -1; - - READ_ONLY = -1; - WRITE_ONLY = 0x88B9; - READ_WRITE = -1; - - TESS_WINDING_NONZERO = PGLU.GLU_TESS_WINDING_NONZERO; - TESS_WINDING_ODD = PGLU.GLU_TESS_WINDING_ODD; - TESS_EDGE_FLAG = PGLU.GLU_TESS_EDGE_FLAG; - - GENERATE_MIPMAP_HINT = GLES20.GL_GENERATE_MIPMAP_HINT; - FASTEST = GLES20.GL_FASTEST; - NICEST = GLES20.GL_NICEST; - DONT_CARE = GLES20.GL_DONT_CARE; - - VENDOR = GLES20.GL_VENDOR; - RENDERER = GLES20.GL_RENDERER; - VERSION = GLES20.GL_VERSION; - EXTENSIONS = GLES20.GL_EXTENSIONS; - SHADING_LANGUAGE_VERSION = GLES20.GL_SHADING_LANGUAGE_VERSION; - - MAX_SAMPLES = -1; - SAMPLES = GLES20.GL_SAMPLES; - - ALIASED_LINE_WIDTH_RANGE = GLES20.GL_ALIASED_LINE_WIDTH_RANGE; - ALIASED_POINT_SIZE_RANGE = GLES20.GL_ALIASED_POINT_SIZE_RANGE; - - DEPTH_BITS = GLES20.GL_DEPTH_BITS; - STENCIL_BITS = GLES20.GL_STENCIL_BITS; - - CCW = GLES20.GL_CCW; - CW = GLES20.GL_CW; - - VIEWPORT = GLES20.GL_VIEWPORT; - - ARRAY_BUFFER = GLES20.GL_ARRAY_BUFFER; - ELEMENT_ARRAY_BUFFER = GLES20.GL_ELEMENT_ARRAY_BUFFER; - - MAX_VERTEX_ATTRIBS = GLES20.GL_MAX_VERTEX_ATTRIBS; - - STATIC_DRAW = GLES20.GL_STATIC_DRAW; - DYNAMIC_DRAW = GLES20.GL_DYNAMIC_DRAW; - STREAM_DRAW = GLES20.GL_STREAM_DRAW; - - BUFFER_SIZE = GLES20.GL_BUFFER_SIZE; - BUFFER_USAGE = GLES20.GL_BUFFER_USAGE; - - POINTS = GLES20.GL_POINTS; - LINE_STRIP = GLES20.GL_LINE_STRIP; - LINE_LOOP = GLES20.GL_LINE_LOOP; - LINES = GLES20.GL_LINES; - TRIANGLE_FAN = GLES20.GL_TRIANGLE_FAN; - TRIANGLE_STRIP = GLES20.GL_TRIANGLE_STRIP; - TRIANGLES = GLES20.GL_TRIANGLES; - - CULL_FACE = GLES20.GL_CULL_FACE; - FRONT = GLES20.GL_FRONT; - BACK = GLES20.GL_BACK; - FRONT_AND_BACK = GLES20.GL_FRONT_AND_BACK; - - POLYGON_OFFSET_FILL = GLES20.GL_POLYGON_OFFSET_FILL; - - UNPACK_ALIGNMENT = GLES20.GL_UNPACK_ALIGNMENT; - PACK_ALIGNMENT = GLES20.GL_PACK_ALIGNMENT; - - TEXTURE_2D = GLES20.GL_TEXTURE_2D; - TEXTURE_RECTANGLE = -1; - - TEXTURE_BINDING_2D = GLES20.GL_TEXTURE_BINDING_2D; - TEXTURE_BINDING_RECTANGLE = -1; - - MAX_TEXTURE_SIZE = GLES20.GL_MAX_TEXTURE_SIZE; - TEXTURE_MAX_ANISOTROPY = 0x84FE; - MAX_TEXTURE_MAX_ANISOTROPY = 0x84FF; - - MAX_VERTEX_TEXTURE_IMAGE_UNITS = GLES20.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS; - MAX_TEXTURE_IMAGE_UNITS = GLES20.GL_MAX_TEXTURE_IMAGE_UNITS; - MAX_COMBINED_TEXTURE_IMAGE_UNITS = GLES20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS; - - NUM_COMPRESSED_TEXTURE_FORMATS = GLES20.GL_NUM_COMPRESSED_TEXTURE_FORMATS; - COMPRESSED_TEXTURE_FORMATS = GLES20.GL_COMPRESSED_TEXTURE_FORMATS; - - NEAREST = GLES20.GL_NEAREST; - LINEAR = GLES20.GL_LINEAR; - LINEAR_MIPMAP_NEAREST = GLES20.GL_LINEAR_MIPMAP_NEAREST; - LINEAR_MIPMAP_LINEAR = GLES20.GL_LINEAR_MIPMAP_LINEAR; - - CLAMP_TO_EDGE = GLES20.GL_CLAMP_TO_EDGE; - REPEAT = GLES20.GL_REPEAT; - - TEXTURE0 = GLES20.GL_TEXTURE0; - TEXTURE1 = GLES20.GL_TEXTURE1; - TEXTURE2 = GLES20.GL_TEXTURE2; - TEXTURE3 = GLES20.GL_TEXTURE3; - TEXTURE_MIN_FILTER = GLES20.GL_TEXTURE_MIN_FILTER; - TEXTURE_MAG_FILTER = GLES20.GL_TEXTURE_MAG_FILTER; - TEXTURE_WRAP_S = GLES20.GL_TEXTURE_WRAP_S; - TEXTURE_WRAP_T = GLES20.GL_TEXTURE_WRAP_T; - TEXTURE_WRAP_R = 0x8072; - - TEXTURE_CUBE_MAP = GLES20.GL_TEXTURE_CUBE_MAP; - TEXTURE_CUBE_MAP_POSITIVE_X = GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X; - TEXTURE_CUBE_MAP_POSITIVE_Y = GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_Y; - TEXTURE_CUBE_MAP_POSITIVE_Z = GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_Z; - TEXTURE_CUBE_MAP_NEGATIVE_X = GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_X; - TEXTURE_CUBE_MAP_NEGATIVE_Y = GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; - TEXTURE_CUBE_MAP_NEGATIVE_Z = GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; - - VERTEX_SHADER = GLES20.GL_VERTEX_SHADER; - FRAGMENT_SHADER = GLES20.GL_FRAGMENT_SHADER; - INFO_LOG_LENGTH = GLES20.GL_INFO_LOG_LENGTH; - SHADER_SOURCE_LENGTH = GLES20.GL_SHADER_SOURCE_LENGTH; - COMPILE_STATUS = GLES20.GL_COMPILE_STATUS; - LINK_STATUS = GLES20.GL_LINK_STATUS; - VALIDATE_STATUS = GLES20.GL_VALIDATE_STATUS; - SHADER_TYPE = GLES20.GL_SHADER_TYPE; - DELETE_STATUS = GLES20.GL_DELETE_STATUS; - - FLOAT_VEC2 = GLES20.GL_FLOAT_VEC2; - FLOAT_VEC3 = GLES20.GL_FLOAT_VEC3; - FLOAT_VEC4 = GLES20.GL_FLOAT_VEC4; - FLOAT_MAT2 = GLES20.GL_FLOAT_MAT2; - FLOAT_MAT3 = GLES20.GL_FLOAT_MAT3; - FLOAT_MAT4 = GLES20.GL_FLOAT_MAT4; - INT_VEC2 = GLES20.GL_INT_VEC2; - INT_VEC3 = GLES20.GL_INT_VEC3; - INT_VEC4 = GLES20.GL_INT_VEC4; - BOOL_VEC2 = GLES20.GL_BOOL_VEC2; - BOOL_VEC3 = GLES20.GL_BOOL_VEC3; - BOOL_VEC4 = GLES20.GL_BOOL_VEC4; - SAMPLER_2D = GLES20.GL_SAMPLER_2D; - SAMPLER_CUBE = GLES20.GL_SAMPLER_CUBE; - - LOW_FLOAT = GLES20.GL_LOW_FLOAT; - MEDIUM_FLOAT = GLES20.GL_MEDIUM_FLOAT; - HIGH_FLOAT = GLES20.GL_HIGH_FLOAT; - LOW_INT = GLES20.GL_LOW_INT; - MEDIUM_INT = GLES20.GL_MEDIUM_INT; - HIGH_INT = GLES20.GL_HIGH_INT; - - CURRENT_VERTEX_ATTRIB = GLES20.GL_CURRENT_VERTEX_ATTRIB; - - VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = GLES20.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING; - VERTEX_ATTRIB_ARRAY_ENABLED = GLES20.GL_VERTEX_ATTRIB_ARRAY_ENABLED; - VERTEX_ATTRIB_ARRAY_SIZE = GLES20.GL_VERTEX_ATTRIB_ARRAY_SIZE; - VERTEX_ATTRIB_ARRAY_STRIDE = GLES20.GL_VERTEX_ATTRIB_ARRAY_STRIDE; - VERTEX_ATTRIB_ARRAY_TYPE = GLES20.GL_VERTEX_ATTRIB_ARRAY_TYPE; - VERTEX_ATTRIB_ARRAY_NORMALIZED = GLES20.GL_VERTEX_ATTRIB_ARRAY_NORMALIZED; - VERTEX_ATTRIB_ARRAY_POINTER = GLES20.GL_VERTEX_ATTRIB_ARRAY_POINTER; - - BLEND = GLES20.GL_BLEND; - ONE = GLES20.GL_ONE; - ZERO = GLES20.GL_ZERO; - SRC_ALPHA = GLES20.GL_SRC_ALPHA; - DST_ALPHA = GLES20.GL_DST_ALPHA; - ONE_MINUS_SRC_ALPHA = GLES20.GL_ONE_MINUS_SRC_ALPHA; - ONE_MINUS_DST_COLOR = GLES20.GL_ONE_MINUS_DST_COLOR; - ONE_MINUS_SRC_COLOR = GLES20.GL_ONE_MINUS_SRC_COLOR; - DST_COLOR = GLES20.GL_DST_COLOR; - SRC_COLOR = GLES20.GL_SRC_COLOR; - - SAMPLE_ALPHA_TO_COVERAGE = GLES20.GL_SAMPLE_ALPHA_TO_COVERAGE; - SAMPLE_COVERAGE = GLES20.GL_SAMPLE_COVERAGE; - - KEEP = GLES20.GL_KEEP; - REPLACE = GLES20.GL_REPLACE; - INCR = GLES20.GL_INCR; - DECR = GLES20.GL_DECR; - INVERT = GLES20.GL_INVERT; - INCR_WRAP = GLES20.GL_INCR_WRAP; - DECR_WRAP = GLES20.GL_DECR_WRAP; - NEVER = GLES20.GL_NEVER; - ALWAYS = GLES20.GL_ALWAYS; - - EQUAL = GLES20.GL_EQUAL; - LESS = GLES20.GL_LESS; - LEQUAL = GLES20.GL_LEQUAL; - GREATER = GLES20.GL_GREATER; - GEQUAL = GLES20.GL_GEQUAL; - NOTEQUAL = GLES20.GL_NOTEQUAL; - - FUNC_ADD = GLES20.GL_FUNC_ADD; - FUNC_MIN = 0x8007; - FUNC_MAX = 0x8008; - FUNC_REVERSE_SUBTRACT = GLES20.GL_FUNC_REVERSE_SUBTRACT; - FUNC_SUBTRACT = GLES20.GL_FUNC_SUBTRACT; - - DITHER = GLES20.GL_DITHER; - - CONSTANT_COLOR = GLES20.GL_CONSTANT_COLOR; - CONSTANT_ALPHA = GLES20.GL_CONSTANT_ALPHA; - ONE_MINUS_CONSTANT_COLOR = GLES20.GL_ONE_MINUS_CONSTANT_COLOR; - ONE_MINUS_CONSTANT_ALPHA = GLES20.GL_ONE_MINUS_CONSTANT_ALPHA; - SRC_ALPHA_SATURATE = GLES20.GL_SRC_ALPHA_SATURATE; - - SCISSOR_TEST = GLES20.GL_SCISSOR_TEST; - STENCIL_TEST = GLES20.GL_STENCIL_TEST; - DEPTH_TEST = GLES20.GL_DEPTH_TEST; - DEPTH_WRITEMASK = GLES20.GL_DEPTH_WRITEMASK; - - COLOR_BUFFER_BIT = GLES20.GL_COLOR_BUFFER_BIT; - DEPTH_BUFFER_BIT = GLES20.GL_DEPTH_BUFFER_BIT; - STENCIL_BUFFER_BIT = GLES20.GL_STENCIL_BUFFER_BIT; - - FRAMEBUFFER = GLES20.GL_FRAMEBUFFER; - COLOR_ATTACHMENT0 = GLES20.GL_COLOR_ATTACHMENT0; - COLOR_ATTACHMENT1 = -1; - COLOR_ATTACHMENT2 = -1; - COLOR_ATTACHMENT3 = -1; - RENDERBUFFER = GLES20.GL_RENDERBUFFER; - DEPTH_ATTACHMENT = GLES20.GL_DEPTH_ATTACHMENT; - STENCIL_ATTACHMENT = GLES20.GL_STENCIL_ATTACHMENT; - READ_FRAMEBUFFER = -1; - DRAW_FRAMEBUFFER = -1; - - DEPTH24_STENCIL8 = 0x88F0; - - DEPTH_COMPONENT = GLES20.GL_DEPTH_COMPONENT; - DEPTH_COMPONENT16 = GLES20.GL_DEPTH_COMPONENT16; - DEPTH_COMPONENT24 = 0x81A6; - DEPTH_COMPONENT32 = 0x81A7; - - STENCIL_INDEX = 6401; // GLES20.GL_STENCIL_INDEX is marked as deprecated - STENCIL_INDEX1 = 0x8D46; - STENCIL_INDEX4 = 0x8D47; - STENCIL_INDEX8 = GLES20.GL_STENCIL_INDEX8; - - DEPTH_STENCIL = 0x84F9; - - FRAMEBUFFER_COMPLETE = GLES20.GL_FRAMEBUFFER_COMPLETE; - FRAMEBUFFER_INCOMPLETE_ATTACHMENT = GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; - FRAMEBUFFER_INCOMPLETE_DIMENSIONS = GLES20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; - FRAMEBUFFER_INCOMPLETE_FORMATS = 0x8CDA; - FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER = -1; - FRAMEBUFFER_INCOMPLETE_READ_BUFFER = -1; - FRAMEBUFFER_UNSUPPORTED = GLES20.GL_FRAMEBUFFER_UNSUPPORTED; - - FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = GLES20.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE; - FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = GLES20.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME; - FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = GLES20.GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL; - FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = GLES20.GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE; - - RENDERBUFFER_WIDTH = GLES20.GL_RENDERBUFFER_WIDTH; - RENDERBUFFER_HEIGHT = GLES20.GL_RENDERBUFFER_HEIGHT; - RENDERBUFFER_RED_SIZE = GLES20.GL_RENDERBUFFER_RED_SIZE; - RENDERBUFFER_GREEN_SIZE = GLES20.GL_RENDERBUFFER_GREEN_SIZE; - RENDERBUFFER_BLUE_SIZE = GLES20.GL_RENDERBUFFER_BLUE_SIZE; - RENDERBUFFER_ALPHA_SIZE = GLES20.GL_RENDERBUFFER_ALPHA_SIZE; - RENDERBUFFER_DEPTH_SIZE = GLES20.GL_RENDERBUFFER_DEPTH_SIZE; - RENDERBUFFER_STENCIL_SIZE = GLES20.GL_RENDERBUFFER_STENCIL_SIZE; - RENDERBUFFER_INTERNAL_FORMAT = GLES20.GL_RENDERBUFFER_INTERNAL_FORMAT; - - MULTISAMPLE = -1; - LINE_SMOOTH = -1; - POLYGON_SMOOTH = -1; - } - - /////////////////////////////////////////////////////////// - - // Special Functions - - @Override - public void flush() { - GLES20.glFlush(); - } - - @Override - public void finish() { - GLES20.glFinish(); - } - - @Override - public void hint(int target, int hint) { - GLES20.glHint(target, hint); - } - - /////////////////////////////////////////////////////////// - - // State and State Requests - - @Override - public void enable(int value) { - if (-1 < value) { - GLES20.glEnable(value); - } - } - - @Override - public void disable(int value) { - if (-1 < value) { - GLES20.glDisable(value); - } - } - - @Override - public void getBooleanv(int name, IntBuffer values) { - if (-1 < name) { - GLES20.glGetBooleanv(name, values); - } else { - fillIntBuffer(values, 0, values.capacity(), 0); - } - } - - @Override - public void getIntegerv(int value, IntBuffer data) { - if (-1 < value) { - GLES20.glGetIntegerv(value, data); - } else { - fillIntBuffer(data, 0, data.capacity() - 1, 0); - } - } - - @Override - public void getFloatv(int value, FloatBuffer data) { - if (-1 < value) { - GLES20.glGetFloatv(value, data); - } else { - fillFloatBuffer(data, 0, data.capacity() - 1, 0); - } - } - - @Override - public boolean isEnabled(int value) { - return GLES20.glIsEnabled(value); - } - - @Override - public String getString(int name) { - return GLES20.glGetString(name); - } - - /////////////////////////////////////////////////////////// - - // Error Handling - - @Override - public int getError() { - return GLES20.glGetError(); - } - - @Override - public String errorString(int err) { - return GLU.gluErrorString(err); - } - - ////////////////////////////////////////////////////////////////////////////// - - // Buffer Objects - - @Override - public void genBuffers(int n, IntBuffer buffers) { - GLES20.glGenBuffers(n, buffers); - } - - @Override - public void deleteBuffers(int n, IntBuffer buffers) { - GLES20.glDeleteBuffers(n, buffers); - } - - @Override - public void bindBuffer(int target, int buffer) { - GLES20.glBindBuffer(target, buffer); - } - - @Override - public void bufferData(int target, int size, Buffer data, int usage) { - GLES20.glBufferData(target, size, data, usage); - } - - @Override - public void bufferSubData(int target, int offset, int size, Buffer data) { - GLES20.glBufferSubData(target, offset, size, data); - } - - @Override - public void isBuffer(int buffer) { - GLES20.glIsBuffer(buffer); - } - - @Override - public void getBufferParameteriv(int target, int value, IntBuffer data) { - GLES20.glGetBufferParameteriv(target, value, data); - } - - @Override - public ByteBuffer mapBuffer(int target, int access) { - throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glMapBuffer")); - } - - @Override - public ByteBuffer mapBufferRange(int target, int offset, int length, int access) { - throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glMapBufferRange")); - } - - @Override - public void unmapBuffer(int target) { - throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glUnmapBuffer")); - } - - ////////////////////////////////////////////////////////////////////////////// - - // Viewport and Clipping - - @Override - public void depthRangef(float n, float f) { - GLES20.glDepthRangef(n, f); - } - - @Override - public void viewport(int x, int y, int w, int h) { - float scale = getPixelScale(); - viewportImpl((int)scale * x, (int)(scale * y), (int)(scale * w), (int)(scale * h)); - } - - @Override - protected void viewportImpl(int x, int y, int w, int h) { - GLES20.glViewport(x, y, w, h); - } - - - ////////////////////////////////////////////////////////////////////////////// - - // Reading Pixels - - @Override - public void readPixelsImpl(int x, int y, int width, int height, int format, int type, Buffer buffer) { - GLES20.glReadPixels(x, y, width, height, format, type, buffer); - } - - - @Override - protected void readPixelsImpl(int x, int y, int width, int height, int format, - int type, long offset) { - // TODO Auto-generated method stub - } - - - ////////////////////////////////////////////////////////////////////////////// - - // Vertices - - @Override - public void vertexAttrib1f(int index, float value) { - GLES20.glVertexAttrib1f(index, value); - } - - @Override - public void vertexAttrib2f(int index, float value0, float value1) { - GLES20.glVertexAttrib2f(index, value0, value1); - } - - @Override - public void vertexAttrib3f(int index, float value0, float value1, float value2) { - GLES20.glVertexAttrib3f(index, value0, value1, value2); - } - - @Override - public void vertexAttrib4f(int index, float value0, float value1, float value2, float value3) { - GLES20.glVertexAttrib4f(index, value0, value1, value2, value3); - } - - @Override - public void vertexAttrib1fv(int index, FloatBuffer values) { - GLES20.glVertexAttrib1fv(index, values); - } - - @Override - public void vertexAttrib2fv(int index, FloatBuffer values) { - GLES20.glVertexAttrib2fv(index, values); - } - - @Override - public void vertexAttrib3fv(int index, FloatBuffer values) { - GLES20.glVertexAttrib3fv(index, values); - } - - @Override - public void vertexAttrib4fv(int index, FloatBuffer values) { - GLES20.glVertexAttrib4fv(index, values); - } - - @Override - public void vertexAttribPointer(int index, int size, int type, boolean normalized, int stride, int offset) { - GLES20.glVertexAttribPointer(index, size, type, normalized, stride, offset); - } - - @Override - public void enableVertexAttribArray(int index) { - GLES20.glEnableVertexAttribArray(index); - } - - @Override - public void disableVertexAttribArray(int index) { - GLES20.glDisableVertexAttribArray(index); - } - - @Override - public void drawArraysImpl(int mode, int first, int count) { - GLES20.glDrawArrays(mode, first, count); - } - - @Override - public void drawElementsImpl(int mode, int count, int type, int offset) { - GLES20.glDrawElements(mode, count, type, offset); - } - - ////////////////////////////////////////////////////////////////////////////// - - // Rasterization - - @Override - public void lineWidth(float width) { - GLES20.glLineWidth(width); - } - - @Override - public void frontFace(int dir) { - GLES20.glFrontFace(dir); - } - - @Override - public void cullFace(int mode) { - GLES20.glCullFace(mode); - } - - @Override - public void polygonOffset(float factor, float units) { - GLES20.glPolygonOffset(factor, units); - } - - ////////////////////////////////////////////////////////////////////////////// - - // Pixel Rectangles - - @Override - public void pixelStorei(int pname, int param) { - GLES20.glPixelStorei(pname, param); - } - - /////////////////////////////////////////////////////////// - - // Texturing - - @Override - public void texImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, Buffer data) { - GLES20.glTexImage2D(target, level, internalFormat, width, height, border, format, type, data); - } - - @Override - public void copyTexImage2D(int target, int level, int internalFormat, int x, int y, int width, int height, int border) { - GLES20.glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border); - } - - @Override - public void texSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int type, Buffer data) { - GLES20.glTexSubImage2D(target, level, xOffset, yOffset, width, height, format, type, data); - } - - @Override - public void copyTexSubImage2D(int target, int level, int xOffset, int yOffset, int x, int y, int width, int height) { - GLES20.glCopyTexSubImage2D(target, level, x, y, xOffset, yOffset, width, height); - } - - @Override - public void compressedTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int imageSize, Buffer data) { - GLES20.glCompressedTexImage2D(target, level, internalFormat, width, height, border, imageSize, data); - } - - @Override - public void compressedTexSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int imageSize, Buffer data) { - GLES20.glCompressedTexSubImage2D(target, level, xOffset, yOffset, width, height, format, imageSize, data); - } - - @Override - public void texParameteri(int target, int pname, int param) { - GLES20.glTexParameteri(target, pname, param); - } - - @Override - public void texParameterf(int target, int pname, float param) { - GLES20.glTexParameterf(target, pname, param); - } - - @Override - public void texParameteriv(int target, int pname, IntBuffer params) { - GLES20.glTexParameteriv(target, pname, params); - } - - @Override - public void texParameterfv(int target, int pname, FloatBuffer params) { - GLES20.glTexParameterfv(target, pname, params); - } - - @Override - public void generateMipmap(int target) { - GLES20.glGenerateMipmap(target); - } - - @Override - public void genTextures(int n, IntBuffer textures) { - GLES20.glGenTextures(n, textures); - } - - @Override - public void deleteTextures(int n, IntBuffer textures) { - GLES20.glDeleteTextures(n, textures); - } - - @Override - public void getTexParameteriv(int target, int pname, IntBuffer params) { - GLES20.glGetTexParameteriv(target, pname, params); - } - - @Override - public void getTexParameterfv(int target, int pname, FloatBuffer params) { - GLES20.glGetTexParameterfv(target, pname, params); - } - - @Override - public boolean isTexture(int texture) { - return GLES20.glIsTexture(texture); - } - - @Override - protected void activeTextureImpl(int texture) { - GLES20.glActiveTexture(texture); - } - - @Override - protected void bindTextureImpl(int target, int texture) { - GLES20.glBindTexture(target, texture); - } - - /////////////////////////////////////////////////////////// - - // Shaders and Programs - - @Override - public int createShader(int type) { - return GLES20.glCreateShader(type); - } - - @Override - public void shaderSource(int shader, String source) { - GLES20.glShaderSource(shader, source); - } - - @Override - public void compileShader(int shader) { - GLES20.glCompileShader(shader); - } - - @Override - public void releaseShaderCompiler() { - GLES20.glReleaseShaderCompiler(); - } - - @Override - public void deleteShader(int shader) { - GLES20.glDeleteShader(shader); - } - - @Override - public void shaderBinary(int count, IntBuffer shaders, int binaryFormat, Buffer binary, int length) { - GLES20.glShaderBinary(count, shaders, binaryFormat, binary, length); - } - - @Override - public int createProgram() { - return GLES20.glCreateProgram(); - } - - @Override - public void attachShader(int program, int shader) { - GLES20.glAttachShader(program, shader); - } - - @Override - public void detachShader(int program, int shader) { - GLES20.glDetachShader(program, shader); - } - - @Override - public void linkProgram(int program) { - GLES20.glLinkProgram(program); - } - - @Override - public void useProgram(int program) { - GLES20.glUseProgram(program); - } - - @Override - public void deleteProgram(int program) { - GLES20.glDeleteProgram(program); - } - - @Override - public String getActiveAttrib(int program, int index, IntBuffer size, IntBuffer type) { - int[] tmp = {0, 0, 0}; - byte[] namebuf = new byte[1024]; - GLES20.glGetActiveAttrib(program, index, 1024, tmp, 0, tmp, 1, tmp, 2, namebuf, 0); - size.put(tmp[1]); - type.put(tmp[2]); - String name = new String(namebuf, 0, tmp[0]); - return name; - } - - @Override - public int getAttribLocation(int program, String name) { - return GLES20.glGetAttribLocation(program, name); - } - - @Override - public void bindAttribLocation(int program, int index, String name) { - GLES20.glBindAttribLocation(program, index, name); - } - - @Override - public int getUniformLocation(int program, String name) { - return GLES20.glGetUniformLocation(program, name); - } - - @Override - public String getActiveUniform(int program, int index, IntBuffer size, IntBuffer type) { - int[] tmp= {0, 0, 0}; - byte[] namebuf = new byte[1024]; - GLES20.glGetActiveUniform(program, index, 1024, tmp, 0, tmp, 1, tmp, 2, namebuf, 0); - size.put(tmp[1]); - type.put(tmp[2]); - String name = new String(namebuf, 0, tmp[0]); - return name; - } - - @Override - public void uniform1i(int location, int value) { - GLES20.glUniform1i(location, value); - } - - @Override - public void uniform2i(int location, int value0, int value1) { - GLES20.glUniform2i(location, value0, value1); - } - - @Override - public void uniform3i(int location, int value0, int value1, int value2) { - GLES20.glUniform3i(location, value0, value1, value2); - } - - @Override - public void uniform4i(int location, int value0, int value1, int value2, int value3) { - GLES20.glUniform4i(location, value0, value1, value2, value3); - } - - @Override - public void uniform1f(int location, float value) { - GLES20.glUniform1f(location, value); - } - - @Override - public void uniform2f(int location, float value0, float value1) { - GLES20.glUniform2f(location, value0, value1); - } - - @Override - public void uniform3f(int location, float value0, float value1, float value2) { - GLES20.glUniform3f(location, value0, value1, value2); - } - - @Override - public void uniform4f(int location, float value0, float value1, float value2, float value3) { - GLES20.glUniform4f(location, value0, value1, value2, value3); - } - - @Override - public void uniform1iv(int location, int count, IntBuffer v) { - GLES20.glUniform1iv(location, count, v); - } - - @Override - public void uniform2iv(int location, int count, IntBuffer v) { - GLES20.glUniform2iv(location, count, v); - } - - @Override - public void uniform3iv(int location, int count, IntBuffer v) { - GLES20.glUniform3iv(location, count, v); - } - - @Override - public void uniform4iv(int location, int count, IntBuffer v) { - GLES20.glUniform4iv(location, count, v); - } - - @Override - public void uniform1fv(int location, int count, FloatBuffer v) { - GLES20.glUniform1fv(location, count, v); - } - - @Override - public void uniform2fv(int location, int count, FloatBuffer v) { - GLES20.glUniform2fv(location, count, v); - } - - @Override - public void uniform3fv(int location, int count, FloatBuffer v) { - GLES20.glUniform3fv(location, count, v); - } - - @Override - public void uniform4fv(int location, int count, FloatBuffer v) { - GLES20.glUniform4fv(location, count, v); - } - - @Override - public void uniformMatrix2fv(int location, int count, boolean transpose, FloatBuffer mat) { - GLES20.glUniformMatrix2fv(location, count, transpose, mat); - } - - @Override - public void uniformMatrix3fv(int location, int count, boolean transpose, FloatBuffer mat) { - GLES20.glUniformMatrix3fv(location, count, transpose, mat); - } - - @Override - public void uniformMatrix4fv(int location, int count, boolean transpose, FloatBuffer mat) { - GLES20.glUniformMatrix4fv(location, count, transpose, mat); - } - - @Override - public void validateProgram(int program) { - GLES20.glValidateProgram(program); - } - - @Override - public boolean isShader(int shader) { - return GLES20.glIsShader(shader); - } - - @Override - public void getShaderiv(int shader, int pname, IntBuffer params) { - GLES20.glGetShaderiv(shader, pname, params); - } - - @Override - public void getAttachedShaders(int program, int maxCount, IntBuffer count, IntBuffer shaders) { - GLES20.glGetAttachedShaders(program, maxCount, count, shaders); - } - - @Override - public String getShaderInfoLog(int shader) { - return GLES20.glGetShaderInfoLog(shader); - } - - @Override - public String getShaderSource(int shader) { - int[] len = {0}; - byte[] buf = new byte[1024]; - GLES20.glGetShaderSource(shader, 1024, len, 0, buf, 0); - return new String(buf, 0, len[0]); - } - - @Override - public void getShaderPrecisionFormat(int shaderType, int precisionType, IntBuffer range, IntBuffer precision) { - GLES20.glGetShaderPrecisionFormat(shaderType, precisionType, range, precision); - } - - @Override - public void getVertexAttribfv(int index, int pname, FloatBuffer params) { - GLES20.glGetVertexAttribfv(index, pname, params); - } - - @Override - public void getVertexAttribiv(int index, int pname, IntBuffer params) { - GLES20.glGetVertexAttribiv(index, pname, params); - } - - @Override - public void getVertexAttribPointerv(int index, int pname, ByteBuffer data) { - throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glGetVertexAttribPointerv()")); - } - - @Override - public void getUniformfv(int program, int location, FloatBuffer params) { - GLES20.glGetUniformfv(program, location, params); - } - - @Override - public void getUniformiv(int program, int location, IntBuffer params) { - GLES20.glGetUniformiv(program, location, params); - } - - @Override - public boolean isProgram(int program) { - return GLES20.glIsProgram(program); - } - - @Override - public void getProgramiv(int program, int pname, IntBuffer params) { - GLES20.glGetProgramiv(program, pname, params); - } - - @Override - public String getProgramInfoLog(int program) { - return GLES20.glGetProgramInfoLog(program); - } - - /////////////////////////////////////////////////////////// - - // Per-Fragment Operations - - @Override - public void scissor(int x, int y, int w, int h) { - GLES20.glScissor(x, y, w, h); - } - - @Override - public void sampleCoverage(float value, boolean invert) { - GLES20.glSampleCoverage(value, invert); - } - - @Override - public void stencilFunc(int func, int ref, int mask) { - GLES20.glStencilFunc(func, ref, mask); - } - - @Override - public void stencilFuncSeparate(int face, int func, int ref, int mask) { - GLES20.glStencilFuncSeparate(face, func, ref, mask); - } - - @Override - public void stencilOp(int sfail, int dpfail, int dppass) { - GLES20.glStencilOp(sfail, dpfail, dppass); - } - - @Override - public void stencilOpSeparate(int face, int sfail, int dpfail, int dppass) { - GLES20.glStencilOpSeparate(face, sfail, dpfail, dppass); - } - - @Override - public void depthFunc(int func) { - GLES20.glDepthFunc(func); - } - - @Override - public void blendEquation(int mode) { - GLES20.glBlendEquation(mode); - } - - @Override - public void blendEquationSeparate(int modeRGB, int modeAlpha) { - GLES20.glBlendEquationSeparate(modeRGB, modeAlpha); - } - - @Override - public void blendFunc(int src, int dst) { - GLES20.glBlendFunc(src, dst); - } - - @Override - public void blendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) { - GLES20.glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); - } - - @Override - public void blendColor(float red, float green, float blue, float alpha) { - GLES20.glBlendColor(red, green, blue, alpha); - } - - /////////////////////////////////////////////////////////// - - // Whole Framebuffer Operations - - @Override - public void colorMask(boolean r, boolean g, boolean b, boolean a) { - GLES20.glColorMask(r, g, b, a); - } - - @Override - public void depthMask(boolean mask) { - GLES20.glDepthMask(mask); - } - - @Override - public void stencilMask(int mask) { - GLES20.glStencilMask(mask); - } - - @Override - public void stencilMaskSeparate(int face, int mask) { - GLES20.glStencilMaskSeparate(face, mask); - } - - @Override - public void clear(int buf) { - if (usingMultisampling && usingCoverageMultisampling) { - buf |= GL_COVERAGE_BUFFER_BIT_NV; - } - GLES20.glClear(buf); - } - - @Override - public void clearColor(float r, float g, float b, float a) { - GLES20.glClearColor(r, g, b, a); - } - - @Override - public void clearDepth(float d) { - GLES20.glClearDepthf(d); - } - - @Override - public void clearStencil(int s) { - GLES20.glClearStencil(s); - } - - /////////////////////////////////////////////////////////// - - // Framebuffers Objects - - @Override - protected void bindFramebufferImpl(int target, int framebuffer) { - GLES20.glBindFramebuffer(target, framebuffer); - } - - @Override - public void deleteFramebuffers(int n, IntBuffer framebuffers) { - GLES20.glDeleteFramebuffers(n, framebuffers); - } - - @Override - public void genFramebuffers(int n, IntBuffer framebuffers) { - GLES20.glGenFramebuffers(n, framebuffers); - } - - @Override - public void bindRenderbuffer(int target, int renderbuffer) { - GLES20.glBindRenderbuffer(target, renderbuffer); - } - - @Override - public void deleteRenderbuffers(int n, IntBuffer renderbuffers) { - GLES20.glDeleteRenderbuffers(n, renderbuffers); - } - - @Override - public void genRenderbuffers(int n, IntBuffer renderbuffers) { - GLES20.glGenRenderbuffers(n, renderbuffers); - } - - @Override - public void renderbufferStorage(int target, int internalFormat, int width, int height) { - GLES20.glRenderbufferStorage(target, internalFormat, width, height); - } - - @Override - public void framebufferRenderbuffer(int target, int attachment, int rendbuferfTarget, int renderbuffer) { - GLES20.glFramebufferRenderbuffer(target, attachment, rendbuferfTarget, renderbuffer); - } - - @Override - public void framebufferTexture2D(int target, int attachment, int texTarget, int texture, int level) { - GLES20.glFramebufferTexture2D(target, attachment, texTarget, texture, level); - } - - @Override - public int checkFramebufferStatus(int target) { - return GLES20.glCheckFramebufferStatus(target); - } - - @Override - public boolean isFramebuffer(int framebuffer) { - return GLES20.glIsFramebuffer(framebuffer); - } - - @Override - public void getFramebufferAttachmentParameteriv(int target, int attachment, int pname, IntBuffer params) { - GLES20.glGetFramebufferAttachmentParameteriv(target, attachment, pname, params); - } - - @Override - public boolean isRenderbuffer(int renderbuffer) { - return GLES20.glIsRenderbuffer(renderbuffer); - } - - @Override - public void getRenderbufferParameteriv(int target, int pname, IntBuffer params) { - GLES20.glGetRenderbufferParameteriv(target, pname, params); - } - - @Override - public void blitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) { -// throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glBlitFramebuffer()")); - } - - @Override - public void renderbufferStorageMultisample(int target, int samples, int format, int width, int height) { -// throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glRenderbufferStorageMultisample()")); - } - - @Override - public void readBuffer(int buf) { -// throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glReadBuffer()")); - } - - @Override - public void drawBuffer(int buf) { -// throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glDrawBuffer()")); - } - - - @Override - protected int getFontAscent(Object font) { - // TODO Auto-generated method stub - return 0; - } - - - @Override - protected int getFontDescent(Object font) { - // TODO Auto-generated method stub - return 0; - } - - - @Override - protected int getTextWidth(Object font, char[] buffer, int start, int stop) { - // TODO Auto-generated method stub - return 0; - } - - - @Override - protected Object getDerivedFont(Object font, float size) { - // TODO Auto-generated method stub - return null; - } - - ////////////////////////////////////////////////////////////////////////////// - - // Synchronization - - @Override - public long fenceSync(int condition, int flags) { - return 0; -// if (gl3es3 != null) { -// return gl3es3.glFenceSync(condition, flags); -// } else { -// throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "fenceSync()")); -// } - } - - @Override - public void deleteSync(long sync) { -// if (gl3es3 != null) { -// gl3es3.glDeleteSync(sync); -// } else { -// throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "deleteSync()")); -// } - } - - @Override - public int clientWaitSync(long sync, int flags, long timeout) { - return 0; -// if (gl3es3 != null) { -// return gl3es3.glClientWaitSync(sync, flags, timeout); -// } else { -// throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "clientWaitSync()")); -// } - } - -} diff --git a/core/src/processing/opengl/PGraphics2D.java b/core/src/processing/opengl/PGraphics2D.java deleted file mode 100644 index 2fdd47543..000000000 --- a/core/src/processing/opengl/PGraphics2D.java +++ /dev/null @@ -1,629 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import processing.core.PGraphics; -import processing.core.PMatrix2D; -import processing.core.PMatrix3D; -import processing.core.PShape; -import processing.core.PShapeSVG; - - -public class PGraphics2D extends PGraphicsOpenGL { - - public PGraphics2D() { - super(); - } - - - ////////////////////////////////////////////////////////////// - - // RENDERER SUPPORT QUERIES - - - @Override - public boolean is2D() { - return true; - } - - - @Override - public boolean is3D() { - return false; - } - - - ////////////////////////////////////////////////////////////// - - // HINTS - - - @Override - public void hint(int which) { - if (which == ENABLE_STROKE_PERSPECTIVE) { - showWarning("Strokes cannot be perspective-corrected in 2D."); - return; - } - super.hint(which); - } - - - ////////////////////////////////////////////////////////////// - - // PROJECTION - - - @Override - public void ortho() { - showMethodWarning("ortho"); - } - - - @Override - public void ortho(float left, float right, - float bottom, float top) { - showMethodWarning("ortho"); - } - - - @Override - public void ortho(float left, float right, - float bottom, float top, - float near, float far) { - showMethodWarning("ortho"); - } - - - @Override - public void perspective() { - showMethodWarning("perspective"); - } - - - @Override - public void perspective(float fov, float aspect, float zNear, float zFar) { - showMethodWarning("perspective"); - } - - - @Override - public void frustum(float left, float right, float bottom, float top, - float znear, float zfar) { - showMethodWarning("frustum"); - } - - - @Override - protected void defaultPerspective() { - super.ortho(0, width, -height, 0, -1, +1); - } - - - ////////////////////////////////////////////////////////////// - - // CAMERA - - - @Override - public void beginCamera() { - showMethodWarning("beginCamera"); - } - - - @Override - public void endCamera() { - showMethodWarning("endCamera"); - } - - - @Override - public void camera() { - showMethodWarning("camera"); - } - - - @Override - public void camera(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - showMethodWarning("camera"); - } - - - @Override - protected void defaultCamera() { - eyeDist = 1; - resetMatrix(); - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX MORE! - - - @Override - protected void begin2D() { - pushProjection(); - defaultPerspective(); - pushMatrix(); - defaultCamera(); - } - - - @Override - protected void end2D() { - popMatrix(); - popProjection(); - } - - - ////////////////////////////////////////////////////////////// - - // SHAPE - - - @Override - public void shape(PShape shape) { - if (shape.is2D()) { - super.shape(shape); - } else { - showWarning("The shape object is not 2D, cannot be displayed with " + - "this renderer"); - } - } - - - @Override - public void shape(PShape shape, float x, float y) { - if (shape.is2D()) { - super.shape(shape, x, y); - } else { - showWarning("The shape object is not 2D, cannot be displayed with " + - "this renderer"); - } - } - - - @Override - public void shape(PShape shape, float a, float b, float c, float d) { - if (shape.is2D()) { - super.shape(shape, a, b, c, d); - } else { - showWarning("The shape object is not 2D, cannot be displayed with " + - "this renderer"); - } - } - - - @Override - public void shape(PShape shape, float x, float y, float z) { - showDepthWarningXYZ("shape"); - } - - - @Override - public void shape(PShape shape, float x, float y, float z, - float c, float d, float e) { - showDepthWarningXYZ("shape"); - } - - - - ////////////////////////////////////////////////////////////// - - // SHAPE I/O - - - static protected boolean isSupportedExtension(String extension) { - return extension.equals("svg") || extension.equals("svgz"); - } - - - static protected PShape loadShapeImpl(PGraphics pg, - String filename, String extension) { - if (extension.equals("svg") || extension.equals("svgz")) { - PShapeSVG svg = new PShapeSVG(pg.parent.loadXML(filename)); - return PShapeOpenGL.createShape((PGraphicsOpenGL) pg, svg); - } - return null; - } - - - ////////////////////////////////////////////////////////////// - - // SCREEN TRANSFORMS - - - @Override - public float modelX(float x, float y, float z) { - showDepthWarning("modelX"); - return 0; - } - - - @Override - public float modelY(float x, float y, float z) { - showDepthWarning("modelY"); - return 0; - } - - - @Override - public float modelZ(float x, float y, float z) { - showDepthWarning("modelZ"); - return 0; - } - - - ////////////////////////////////////////////////////////////// - - // SHAPE CREATION - - -// @Override -// protected PShape createShapeFamily(int type) { -// return new PShapeOpenGL(this, type); -// } -// -// -// @Override -// protected PShape createShapePrimitive(int kind, float... p) { -// return new PShapeOpenGL(this, kind, p); -// } - - - /* - @Override - public PShape createShape(PShape source) { - return PShapeOpenGL.createShape2D(this, source); - } - - - @Override - public PShape createShape() { - return createShape(PShape.GEOMETRY); - } - - - @Override - public PShape createShape(int type) { - return createShapeImpl(this, type); - } - - - @Override - public PShape createShape(int kind, float... p) { - return createShapeImpl(this, kind, p); - } - - - static protected PShapeOpenGL createShapeImpl(PGraphicsOpenGL pg, int type) { - PShapeOpenGL shape = null; - if (type == PConstants.GROUP) { - shape = new PShapeOpenGL(pg, PConstants.GROUP); - } else if (type == PShape.PATH) { - shape = new PShapeOpenGL(pg, PShape.PATH); - } else if (type == PShape.GEOMETRY) { - shape = new PShapeOpenGL(pg, PShape.GEOMETRY); - } - shape.set3D(false); - return shape; - } - - - static protected PShapeOpenGL createShapeImpl(PGraphicsOpenGL pg, - int kind, float... p) { - PShapeOpenGL shape = null; - int len = p.length; - - if (kind == POINT) { - if (len != 2) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(POINT); - } else if (kind == LINE) { - if (len != 4) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(LINE); - } else if (kind == TRIANGLE) { - if (len != 6) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(TRIANGLE); - } else if (kind == QUAD) { - if (len != 8) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(QUAD); - } else if (kind == RECT) { - if (len != 4 && len != 5 && len != 8 && len != 9) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(RECT); - } else if (kind == ELLIPSE) { - if (len != 4 && len != 5) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(ELLIPSE); - } else if (kind == ARC) { - if (len != 6 && len != 7) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(ARC); - } else if (kind == BOX) { - showWarning("Primitive not supported in 2D"); - } else if (kind == SPHERE) { - showWarning("Primitive not supported in 2D"); - } else { - showWarning("Unrecognized primitive type"); - } - - if (shape != null) { - shape.setParams(p); - } - - shape.set3D(false); - return shape; - } - */ - - - ////////////////////////////////////////////////////////////// - - // BEZIER VERTICES - - - @Override - public void bezierVertex(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - showDepthWarningXYZ("bezierVertex"); - } - - - ////////////////////////////////////////////////////////////// - - // QUADRATIC BEZIER VERTICES - - - @Override - public void quadraticVertex(float x2, float y2, float z2, - float x4, float y4, float z4) { - showDepthWarningXYZ("quadVertex"); - } - - - ////////////////////////////////////////////////////////////// - - // CURVE VERTICES - - - @Override - public void curveVertex(float x, float y, float z) { - showDepthWarningXYZ("curveVertex"); - } - - - ////////////////////////////////////////////////////////////// - - // BOX - - - @Override - public void box(float w, float h, float d) { - showMethodWarning("box"); - } - - - ////////////////////////////////////////////////////////////// - - // SPHERE - - - @Override - public void sphere(float r) { - showMethodWarning("sphere"); - } - - - ////////////////////////////////////////////////////////////// - - // VERTEX SHAPES - - - @Override - public void vertex(float x, float y, float z) { - showDepthWarningXYZ("vertex"); - } - - @Override - public void vertex(float x, float y, float z, float u, float v) { - showDepthWarningXYZ("vertex"); - } - - ////////////////////////////////////////////////////////////// - - // MATRIX TRANSFORMATIONS - - @Override - public void translate(float tx, float ty, float tz) { - showDepthWarningXYZ("translate"); - } - - @Override - public void rotateX(float angle) { - showDepthWarning("rotateX"); - } - - @Override - public void rotateY(float angle) { - showDepthWarning("rotateY"); - } - - @Override - public void rotateZ(float angle) { - showDepthWarning("rotateZ"); - } - - @Override - public void rotate(float angle, float vx, float vy, float vz) { - showVariationWarning("rotate"); - } - - @Override - public void applyMatrix(PMatrix3D source) { - showVariationWarning("applyMatrix"); - } - - @Override - public void applyMatrix(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - showVariationWarning("applyMatrix"); - } - - @Override - public void scale(float sx, float sy, float sz) { - showDepthWarningXYZ("scale"); - } - - ////////////////////////////////////////////////////////////// - - // SCREEN AND MODEL COORDS - - @Override - public float screenX(float x, float y, float z) { - showDepthWarningXYZ("screenX"); - return 0; - } - - @Override - public float screenY(float x, float y, float z) { - showDepthWarningXYZ("screenY"); - return 0; - } - - @Override - public float screenZ(float x, float y, float z) { - showDepthWarningXYZ("screenZ"); - return 0; - } - - @Override - public PMatrix2D getMatrix(PMatrix2D target) { - if (target == null) { - target = new PMatrix2D(); - } - // This set operation is well defined, since modelview is a 2D-only - // transformation matrix in the P2D renderer. - target.set(modelview.m00, modelview.m01, modelview.m03, - modelview.m10, modelview.m11, modelview.m13); - return target; - - } - - @Override - public PMatrix3D getMatrix(PMatrix3D target) { - showVariationWarning("getMatrix"); - return target; - } - - @Override - public void setMatrix(PMatrix3D source) { - showVariationWarning("setMatrix"); - } - - ////////////////////////////////////////////////////////////// - - // LIGHTS - - @Override - public void lights() { - showMethodWarning("lights"); - } - - @Override - public void noLights() { - showMethodWarning("noLights"); - } - - @Override - public void ambientLight(float red, float green, float blue) { - showMethodWarning("ambientLight"); - } - - @Override - public void ambientLight(float red, float green, float blue, - float x, float y, float z) { - showMethodWarning("ambientLight"); - } - - @Override - public void directionalLight(float red, float green, float blue, - float nx, float ny, float nz) { - showMethodWarning("directionalLight"); - } - - @Override - public void pointLight(float red, float green, float blue, - float x, float y, float z) { - showMethodWarning("pointLight"); - } - - @Override - public void spotLight(float red, float green, float blue, - float x, float y, float z, - float nx, float ny, float nz, - float angle, float concentration) { - showMethodWarning("spotLight"); - } - - @Override - public void lightFalloff(float constant, float linear, float quadratic) { - showMethodWarning("lightFalloff"); - } - - @Override - public void lightSpecular(float v1, float v2, float v3) { - showMethodWarning("lightSpecular"); - } -} \ No newline at end of file diff --git a/core/src/processing/opengl/PGraphics2DX.java b/core/src/processing/opengl/PGraphics2DX.java deleted file mode 100755 index 60fee8e16..000000000 --- a/core/src/processing/opengl/PGraphics2DX.java +++ /dev/null @@ -1,2055 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2019-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import static processing.core.PApplet.println; - -import java.net.URL; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import processing.core.PApplet; -import processing.core.PGraphics; -import processing.core.PImage; -import processing.core.PMatrix3D; -import processing.core.PShape; -import processing.core.PShapeSVG; - -/** - * Super fast OpenGL 2D renderer originally contributed by Miles Fogle: - * https://github.com/hazmatsuitor - * - * It speeds-up rendering of 2D geometry by essentially two key optimizations: packing all the - * vertex data in a single VBO, and using a custom stroke tessellator (see StrokeRenderer class - * at the end). There are a number of other, less critical optimizations, for example using a single - * shader for textured and non-textured geometry and a depth algorithm that allows stacking a large - * number of 2D shapes without z-fighting (so occlusion is based on drawing order). - * - * Some notes from Miles: - * - * for testing purposes, I found it easier to create a separate class and avoid - * touching existing code for now, rather than directly editing PGraphics2D/PGraphicsOpenGL - * if this code becomes the new P2D implementation, then it will be properly migrated/integrated - - * NOTE: this implementation doesn't use some of Processing's OpenGL wrappers - * (e.g. PShader, Texture) because I found it more convenient to handle them manually - * it could probably be made to use those classes with a bit of elbow grease and a spot of guidance - * but it may not be worth it - I doubt it would reduce complexity much, if at all - * (if there are reasons we need to use those classes, let me know) - * - */ - -//TODO: track debug performance stats -public final class PGraphics2DX extends PGraphicsOpenGL { - static final String NON_2D_SHAPE_ERROR = "The shape object is not 2D, cannot be displayed with this renderer"; - static final String STROKE_PERSPECTIVE_ERROR = "Strokes cannot be perspective-corrected in 2D"; - - static final String NON_2D_SHADER_ERROR = "This shader cannot be used for 2D rendering"; - static final String WRONG_SHADER_PARAMS = "The P2D renderer does not accept shaders of different tyes"; - - static protected final int SHADER2D = 7; - - // Uses the implementations in the parent PGraphicsOpenGL class, which is needed to to draw obj files - // and apply shader filters. - protected boolean useParentImpl = false; - - protected boolean initialized; - - protected PGL.Tessellator tess; - - protected PShader twoShader; - protected PShader defTwoShader; - - protected int positionLoc; - protected int colorLoc; - protected int texCoordLoc; - protected int texFactorLoc; - - protected int transformLoc; - protected int texScaleLoc; - - static protected URL defP2DShaderVertURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/P2DVert.glsl"); - static protected URL defP2DShaderFragURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/P2DFrag.glsl"); - - - public PGraphics2DX() { - super(); - initTess(); - initVerts(); - } - - - ////////////////////////////////////////////////////////////// - - // RENDERER SUPPORT QUERIES - - - @Override - public boolean is2D() { - return true; - } - - - @Override - public boolean is3D() { - return false; - } - - - ////////////////////////////////////////////////////////////// - - // RENDERING - - - @Override - public void beginDraw() { - super.beginDraw(); - if (!useParentImpl) { - pgl.depthFunc(PGL.LESS); - depth = 1.0f; - } - } - - - @Override - public void flush() { - // If no vertices where created with the base implementation, then flush() will do nothing. - super.flush(); - flushBuffer(); - } - - - // These two methods are meant for debugging (comparing the new and old P2D renderers) - // and will go away. - - - public void useOldP2D() { - useParentImpl = true; - pgl.depthFunc(PGL.LEQUAL); - } - - - public void useNewP2D() { - useParentImpl = false; - pgl.depthFunc(PGL.LESS); - } - - - ////////////////////////////////////////////////////////////// - - // HINTS - - - @Override - public void hint(int which) { - if (which == ENABLE_STROKE_PERSPECTIVE) { - showWarning(STROKE_PERSPECTIVE_ERROR); - return; - } - super.hint(which); - } - - - ////////////////////////////////////////////////////////////// - - // PROJECTION - - - @Override - public void ortho() { - showMethodWarning("ortho"); - } - - - @Override - public void ortho(float left, float right, - float bottom, float top) { - showMethodWarning("ortho"); - } - - - @Override - public void ortho(float left, float right, - float bottom, float top, - float near, float far) { - showMethodWarning("ortho"); - } - - - @Override - public void perspective() { - showMethodWarning("perspective"); - } - - - @Override - public void perspective(float fov, float aspect, float zNear, float zFar) { - showMethodWarning("perspective"); - } - - - @Override - public void frustum(float left, float right, float bottom, float top, - float znear, float zfar) { - showMethodWarning("frustum"); - } - - - @Override - protected void defaultPerspective() { - super.ortho(0, width, -height, 0, -1, +1); - } - - - ////////////////////////////////////////////////////////////// - - // CAMERA - - - @Override - public void beginCamera() { - showMethodWarning("beginCamera"); - } - - - @Override - public void endCamera() { - showMethodWarning("endCamera"); - } - - - @Override - public void camera() { - showMethodWarning("camera"); - } - - - @Override - public void camera(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - showMethodWarning("camera"); - } - - - @Override - protected void defaultCamera() { - eyeDist = 1; - resetMatrix(); - } - - - ////////////////////////////////////////////////////////////// - - // SHAPE - - - @Override - public void shape(PShape shape) { - if (shape.is2D()) { - if (!useParentImpl) { - useOldP2D(); - super.shape(shape); - useNewP2D(); - } else { - super.shape(shape); - } - } else { - showWarning(NON_2D_SHAPE_ERROR); - } - } - - - @Override - public void shape(PShape shape, float x, float y) { - if (shape.is2D()) { - if (!useParentImpl) { - useOldP2D(); - super.shape(shape, x, y); - useNewP2D(); - } else { - super.shape(shape, x, y); - } - } else { - showWarning(NON_2D_SHAPE_ERROR); - } - } - - - @Override - public void shape(PShape shape, float a, float b, float c, float d) { - if (shape.is2D()) { - if (!useParentImpl) { - useOldP2D(); - super.shape(shape, a, b, c, d); - useNewP2D(); - } else { - super.shape(shape, a, b, c, d); - } - } else { - showWarning(NON_2D_SHAPE_ERROR); - } - } - - - @Override - public void shape(PShape shape, float x, float y, float z) { - showDepthWarningXYZ("shape"); - } - - - @Override - public void shape(PShape shape, float x, float y, float z, - float c, float d, float e) { - showDepthWarningXYZ("shape"); - } - - - - ////////////////////////////////////////////////////////////// - - // SHAPE I/O - - - static protected boolean isSupportedExtension(String extension) { - return extension.equals("svg") || extension.equals("svgz"); - } - - - static protected PShape loadShapeImpl(PGraphics pg, - String filename, String extension) { - if (extension.equals("svg") || extension.equals("svgz")) { - PShapeSVG svg = new PShapeSVG(pg.parent.loadXML(filename)); - return PShapeOpenGL.createShape((PGraphicsOpenGL) pg, svg); - } - return null; - } - - - ////////////////////////////////////////////////////////////// - - // SCREEN TRANSFORMS - - - @Override - public float modelX(float x, float y, float z) { - showDepthWarning("modelX"); - return 0; - } - - - @Override - public float modelY(float x, float y, float z) { - showDepthWarning("modelY"); - return 0; - } - - - @Override - public float modelZ(float x, float y, float z) { - showDepthWarning("modelZ"); - return 0; - } - - - ////////////////////////////////////////////////////////////// - - // VERTEX SHAPES - - - @Override - public void texture(PImage image) { - super.texture(image); - - if (image == null) { - return; - } - - Texture t = currentPG.getTexture(image); - texWidth = t.width; - texHeight = t.height; - imageTex = t.glName; - textureImpl(imageTex); - } - - - @Override - public void beginShape(int kind) { - if (useParentImpl) { - super.beginShape(kind); - return; - } - - shapeType = kind; - vertCount = 0; - contourCount = 0; - } - - - @Override - public void endShape(int mode) { - if (useParentImpl) { - super.endShape(mode); - return; - } - - //end the current contour - appendContour(vertCount); - - if (fill) { - incrementDepth(); - - if (shapeType == POLYGON) { - if (knownConvexPolygon) { - for (int i = 2; i < vertCount; ++i) { - check(3); - vertexImpl(shapeVerts[0]); - vertexImpl(shapeVerts[i - 1]); - vertexImpl(shapeVerts[i]); - } - - knownConvexPolygon = false; - } else { - tess.beginPolygon(this); - tess.beginContour(); - - int c = 0; - for (int i = 0; i < vertCount; ++i) { - if (contours[c] == i) { - tess.endContour(); - tess.beginContour(); - c++; //lol no, this is java - } - - tempDoubles[0] = shapeVerts[i].x; - tempDoubles[1] = shapeVerts[i].y; - tess.addVertex(tempDoubles, 0, shapeVerts[i]); - } - tess.endContour(); - tess.endPolygon(); - } - } else if (shapeType == QUAD_STRIP) { - for (int i = 0; i <= vertCount - 4; i += 2) { - check(6); - vertexImpl(shapeVerts[i + 0]); - vertexImpl(shapeVerts[i + 1]); - vertexImpl(shapeVerts[i + 2]); - vertexImpl(shapeVerts[i + 1]); - vertexImpl(shapeVerts[i + 2]); - vertexImpl(shapeVerts[i + 3]); - } - } else if (shapeType == QUADS) { - for (int i = 0; i <= vertCount - 4; i += 4) { - check(6); - vertexImpl(shapeVerts[i + 0]); - vertexImpl(shapeVerts[i + 1]); - vertexImpl(shapeVerts[i + 2]); - vertexImpl(shapeVerts[i + 0]); - vertexImpl(shapeVerts[i + 2]); - vertexImpl(shapeVerts[i + 3]); - } - } else if (shapeType == TRIANGLE_STRIP) { - for (int i = 0; i <= vertCount - 3; i += 1) { - check(3); - vertexImpl(shapeVerts[i + 0]); - vertexImpl(shapeVerts[i + 1]); - vertexImpl(shapeVerts[i + 2]); - } - } else if (shapeType == TRIANGLE_FAN) { - for (int i = 0; i <= vertCount - 3; i += 1) { - check(3); - vertexImpl(shapeVerts[0 + 0]); - vertexImpl(shapeVerts[i + 1]); - vertexImpl(shapeVerts[i + 2]); - } - - //close the fan - if (vertCount >= 3) { - check(3); - vertexImpl(shapeVerts[0]); - vertexImpl(shapeVerts[vertCount - 1]); - vertexImpl(shapeVerts[1]); - } - } else if (shapeType == TRIANGLES) { - for (int i = 0; i <= vertCount - 3; i += 3) { - check(3); - vertexImpl(shapeVerts[i + 0]); - vertexImpl(shapeVerts[i + 1]); - vertexImpl(shapeVerts[i + 2]); - } - } - } - - if (stroke) { - incrementDepth(); - - if (shapeType == POLYGON) { - if (vertCount < 3) { - return; - } - - int c = 0; - sr.beginLine(); - for (int i = 0; i < vertCount; ++i) { - if (contours[c] == i) { - sr.endLine(mode == CLOSE); - sr.beginLine(); - c++; - } - - sr.lineVertex(shapeVerts[i].x, shapeVerts[i].y); - } - sr.endLine(mode == CLOSE); - } else if (shapeType == QUAD_STRIP) { - for (int i = 0; i <= vertCount - 4; i += 2) { - sr.beginLine(); - sr.lineVertex(shapeVerts[i + 0].x, shapeVerts[i + 0].y); - sr.lineVertex(shapeVerts[i + 1].x, shapeVerts[i + 1].y); - sr.lineVertex(shapeVerts[i + 3].x, shapeVerts[i + 3].y); - sr.lineVertex(shapeVerts[i + 2].x, shapeVerts[i + 2].y); - sr.endLine(true); - } - } else if (shapeType == QUADS) { - for (int i = 0; i <= vertCount - 4; i += 4) { - sr.beginLine(); - sr.lineVertex(shapeVerts[i + 0].x, shapeVerts[i + 0].y); - sr.lineVertex(shapeVerts[i + 1].x, shapeVerts[i + 1].y); - sr.lineVertex(shapeVerts[i + 2].x, shapeVerts[i + 2].y); - sr.lineVertex(shapeVerts[i + 3].x, shapeVerts[i + 3].y); - sr.endLine(true); - } - } else if (shapeType == TRIANGLE_STRIP) { - for (int i = 0; i <= vertCount - 3; i += 1) { - sr.beginLine(); - sr.lineVertex(shapeVerts[i + 0].x, shapeVerts[i + 0].y); - sr.lineVertex(shapeVerts[i + 1].x, shapeVerts[i + 1].y); - sr.lineVertex(shapeVerts[i + 2].x, shapeVerts[i + 2].y); - sr.endLine(true); - } - } else if (shapeType == TRIANGLE_FAN) { - for (int i = 0; i <= vertCount - 3; i += 1) { - sr.beginLine(); - sr.lineVertex(shapeVerts[0 + 0].x, shapeVerts[0 + 0].y); - sr.lineVertex(shapeVerts[i + 1].x, shapeVerts[i + 1].y); - sr.lineVertex(shapeVerts[i + 2].x, shapeVerts[i + 2].y); - sr.endLine(true); - } - - //close the fan - if (vertCount >= 3) { - sr.beginLine(); - sr.lineVertex(shapeVerts[0].x, shapeVerts[0].y); - sr.lineVertex(shapeVerts[vertCount - 1].x, shapeVerts[vertCount - 1].y); - sr.lineVertex(shapeVerts[1].x, shapeVerts[1].y); - sr.endLine(true); - } - } else if (shapeType == TRIANGLES) { - for (int i = 0; i <= vertCount - 3; i += 3) { - sr.beginLine(); - sr.lineVertex(shapeVerts[i + 0].x, shapeVerts[i + 0].y); - sr.lineVertex(shapeVerts[i + 1].x, shapeVerts[i + 1].y); - sr.lineVertex(shapeVerts[i + 2].x, shapeVerts[i + 2].y); - sr.endLine(true); - } - } else if (shapeType == LINES) { - for (int i = 0; i <= vertCount - 2; i += 2) { - TessVertex s1 = shapeVerts[i + 0]; - TessVertex s2 = shapeVerts[i + 1]; - singleLine(s1.x, s1.y, s2.x, s2.y, strokeColor); - } - } else if (shapeType == POINTS) { - for (int i = 0; i <= vertCount - 1; i += 1) { - singlePoint(shapeVerts[i].x, shapeVerts[i].y, strokeColor); - } - } - } - } - - - @Override - public void beginContour() { - super.beginContour(); - if (useParentImpl) { - return; - } - - //XXX: not sure what the exact behavior should be for invalid calls to begin/endContour() - //but this should work for valid cases for now - appendContour(vertCount); - } - - - @Override - public void vertex(float x, float y) { - if (useParentImpl) { - super.vertex(x, y); - return; - } - - curveVerts = 0; - shapeVertex(x, y, 0, 0, fillColor, 0); - } - - - @Override - public void vertex(float x, float y, float u, float v) { - if (useParentImpl) { - super.vertex(x, y, u, v); - return; - } - - curveVerts = 0; - textureImpl(imageTex); - shapeVertex(x, y, u, v, tint? tintColor : 0xFFFFFFFF, 1); - } - - - @Override - public void vertex(float x, float y, float z) { - showDepthWarningXYZ("vertex"); - } - - - @Override - public void vertex(float x, float y, float z, float u, float v) { - showDepthWarningXYZ("vertex"); - } - - - ////////////////////////////////////////////////////////////// - - // BEZIER VERTICES - - - //this method is almost wholesale copied from PGraphics.bezierVertex() - //TODO: de-duplicate this code if there is a convenient way to do so - @Override - public void bezierVertex(float x2, float y2, float x3, float y3, float x4, float y4) { - if (useParentImpl) { - super.bezierVertex(x2, y2, x3, y3, x4, y4); - return; - } - - bezierInitCheck(); -// bezierVertexCheck(); //TODO: re-implement this (and other run-time sanity checks) - PMatrix3D draw = bezierDrawMatrix; - - //(these are the only lines that are different) - float x1 = shapeVerts[vertCount - 1].x; - float y1 = shapeVerts[vertCount - 1].y; - - float xplot1 = draw.m10*x1 + draw.m11*x2 + draw.m12*x3 + draw.m13*x4; - float xplot2 = draw.m20*x1 + draw.m21*x2 + draw.m22*x3 + draw.m23*x4; - float xplot3 = draw.m30*x1 + draw.m31*x2 + draw.m32*x3 + draw.m33*x4; - - float yplot1 = draw.m10*y1 + draw.m11*y2 + draw.m12*y3 + draw.m13*y4; - float yplot2 = draw.m20*y1 + draw.m21*y2 + draw.m22*y3 + draw.m23*y4; - float yplot3 = draw.m30*y1 + draw.m31*y2 + draw.m32*y3 + draw.m33*y4; - - for (int j = 0; j < bezierDetail; j++) { - x1 += xplot1; xplot1 += xplot2; xplot2 += xplot3; - y1 += yplot1; yplot1 += yplot2; yplot2 += yplot3; - shapeVertex(x1, y1, 0, 0, fillColor, 0); - } - } - - - @Override - public void bezierVertex(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - showDepthWarningXYZ("bezierVertex"); - } - - - ////////////////////////////////////////////////////////////// - - // QUADRATIC BEZIER VERTICES - - - //this method is almost wholesale copied from PGraphics.quadraticVertex() - //TODO: de-duplicate this code if there is a convenient way to do so - @Override - public void quadraticVertex(float cx, float cy, - float x3, float y3) { - if (useParentImpl) { - super.quadraticVertex(cx, cy, x3, y3); - return; - } - - //(these are the only lines that are different) - float x1 = shapeVerts[vertCount - 1].x; - float y1 = shapeVerts[vertCount - 1].y; - - //TODO: optimize this? - bezierVertex(x1 + ((cx-x1)*2/3.0f), y1 + ((cy-y1)*2/3.0f), - x3 + ((cx-x3)*2/3.0f), y3 + ((cy-y3)*2/3.0f), - x3, y3); - } - - - @Override - public void quadraticVertex(float x2, float y2, float z2, - float x4, float y4, float z4) { - showDepthWarningXYZ("quadVertex"); - } - - - ////////////////////////////////////////////////////////////// - - // CURVE VERTICES - - - //curve vertices - private float cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4; - private int curveVerts; - - - @Override - public void curveVertex(float x, float y) { - if (useParentImpl) { - super.curveVertex(x, y); - return; - } - -// curveVertexCheck(); //TODO: re-implement this (and other runtime checks) - - curveInitCheck(); - - cx1 = cx2; - cx2 = cx3; - cx3 = cx4; - - cy1 = cy2; - cy2 = cy3; - cy3 = cy4; - - cx4 = x; - cy4 = y; - - curveVerts += 1; - - if (curveVerts > 3) { - println("drawing curve..."); - - PMatrix3D draw = curveDrawMatrix; - - float xplot1 = draw.m10*cx1 + draw.m11*cx2 + draw.m12*cx3 + draw.m13*cx4; - float xplot2 = draw.m20*cx1 + draw.m21*cx2 + draw.m22*cx3 + draw.m23*cx4; - float xplot3 = draw.m30*cx1 + draw.m31*cx2 + draw.m32*cx3 + draw.m33*cx4; - - float yplot1 = draw.m10*cy1 + draw.m11*cy2 + draw.m12*cy3 + draw.m13*cy4; - float yplot2 = draw.m20*cy1 + draw.m21*cy2 + draw.m22*cy3 + draw.m23*cy4; - float yplot3 = draw.m30*cy1 + draw.m31*cy2 + draw.m32*cy3 + draw.m33*cy4; - - float x0 = cx2; - float y0 = cy2; - - if (curveVerts == 4) { - shapeVertex(x0, y0, 0, 0, fillColor, 0); - } - - for (int j = 0; j < curveDetail; j++) { - x0 += xplot1; xplot1 += xplot2; xplot2 += xplot3; - y0 += yplot1; yplot1 += yplot2; yplot2 += yplot3; - shapeVertex(x0, y0, 0, 0, fillColor, 0); - } - } - } - - - @Override - public void curveVertex(float x, float y, float z) { - showDepthWarningXYZ("curveVertex"); - } - - - ////////////////////////////////////////////////////////////// - - // PRIMITIVES - - - /* - * Re-implementations of the various shape drawing methods. - * - * Ideally we could just call the versions in PGraphics, - * since most of those will work correctly without modification, - * but there's no good way to do that in Java, - * so as long as we're inheriting from PGraphicsOpenGL, - * we need to re-implement them. - */ - - - @Override - public void quad(float x1, float y1, float x2, float y2, - float x3, float y3, float x4, float y4) { - if (useParentImpl) { - super.quad(x1, y1, x2, y2, x3, y3, x4, y4); - return; - } - - beginShape(QUADS); - vertex(x1, y1); - vertex(x2, y2); - vertex(x3, y3); - vertex(x4, y4); - endShape(); - } - - - @Override - public void triangle(float x1, float y1, float x2, float y2, - float x3, float y3) { - if (useParentImpl) { - super.triangle(x1, y1, x2, y2, x3, y3); - return; - } - - beginShape(TRIANGLES); - vertex(x1, y1); - vertex(x2, y2); - vertex(x3, y3); - endShape(); - } - - - @Override - public void ellipseImpl(float a, float b, float c, float d) { - if (useParentImpl) { - super.ellipseImpl(a, b, c, d); - return; - } - - beginShape(POLYGON); - - //convert corner/diameter to center/radius - float rx = c * 0.5f; - float ry = d * 0.5f; - float x = a + rx; - float y = b + ry; - - //since very wide stroke and/or very small radius might cause the - //stroke to account for a significant portion of the overall radius, - //we take it into account when calculating detail, just to be safe - int segments = circleDetail(PApplet.max(rx, ry) + (stroke? strokeWeight : 0), TWO_PI); - float step = TWO_PI / segments; - - float cos = PApplet.cos(step); - float sin = PApplet.sin(step); - float dx = 0, dy = 1; - for (int i = 0; i < segments; ++i) { - shapeVertex(x + dx * rx, y + dy * ry, 0, 0, fillColor, 0); - //this is the equivalent of multiplying the vector by the 2x2 rotation matrix [[cos -sin] [sin cos]] - float tempx = dx * cos - dy * sin; - dy = dx * sin + dy * cos; - dx = tempx; - } - - knownConvexPolygon = true; - endShape(CLOSE); - } - - - @Override - public void line(float x1, float y1, float x2, float y2) { - if (useParentImpl) { - super.line(x1, y1, x2, y2); - return; - } - - incrementDepth(); - singleLine(x1, y1, x2, y2, strokeColor); - } - - - @Override - public void point(float x, float y) { - if (useParentImpl) { - super.point(x, y); - return; - } - - incrementDepth(); - singlePoint(x, y, strokeColor); - } - - - @Override - protected void arcImpl(float x, float y, float w, float h, float start, float stop, int mode) { - if (useParentImpl) { - super.arcImpl(x, y, w, h, start, stop, mode); - return; - } - - //INVARIANT: stop > start - //INVARIANT: stop - start <= TWO_PI - - //convert corner/diameter to center/radius - w *= 0.5f; - h *= 0.5f; - x += w; - y += h; - - float diff = stop - start; - int segments = circleDetail(PApplet.max(w, h), diff); - float step = diff / segments; - - beginShape(POLYGON); - - //no constant is defined for the default arc mode, so we just use a literal 0 - //(this is consistent with code elsewhere) - if (mode == 0 || mode == PIE) { - vertex(x, y); - } - - if (mode == 0) { - //kinda hacky way to disable drawing a stroke along the first edge - appendContour(vertCount); - } - - float dx = PApplet.cos(start); - float dy = PApplet.sin(start); - float c = PApplet.cos(step); - float s = PApplet.sin(step); - for (int i = 0; i <= segments; ++i) { - shapeVertex(x + dx * w, y + dy * h, 0, 0, fillColor, 0); - //this is the equivalent of multiplying the vector by the 2x2 rotation matrix [[c -s] [s c]] - float tempx = dx * c - dy * s; - dy = dx * s + dy * c; - dx = tempx; - } - - //for the case `(mode == PIE || mode == 0) && diff > HALF_PI`, the polygon - //will not actually be convex, but due to known vertex order, we can still safely tessellate as if it is - knownConvexPolygon = true; - if (mode == CHORD || mode == PIE) { - endShape(CLOSE); - } else { - endShape(); - } - } - - - @Override - protected void rectImpl(float x1, float y1, float x2, float y2, - float tl, float tr, float br, float bl) { - if (useParentImpl) { - super.rectImpl(x1, y1, x2, y2, tl, tr, br, bl); - return; - } - - beginShape(); - if (tr != 0) { - vertex(x2-tr, y1); - quadraticVertex(x2, y1, x2, y1+tr); - } else { - vertex(x2, y1); - } - if (br != 0) { - vertex(x2, y2-br); - quadraticVertex(x2, y2, x2-br, y2); - } else { - vertex(x2, y2); - } - if (bl != 0) { - vertex(x1+bl, y2); - quadraticVertex(x1, y2, x1, y2-bl); - } else { - vertex(x1, y2); - } - if (tl != 0) { - vertex(x1, y1+tl); - quadraticVertex(x1, y1, x1+tl, y1); - } else { - vertex(x1, y1); - } - knownConvexPolygon = true; - endShape(CLOSE); - } - - - ////////////////////////////////////////////////////////////// - - // BOX - - - @Override - public void box(float w, float h, float d) { - showMethodWarning("box"); - } - - - ////////////////////////////////////////////////////////////// - - // SPHERE - - - @Override - public void sphere(float r) { - showMethodWarning("sphere"); - } - - - ////////////////////////////////////////////////////////////// - - // PIXELS - - - @Override - public void loadPixels() { - super.loadPixels(); - - allocatePixels(); - readPixels(); - } - - - @Override - public void updatePixels() { - super.updatePixels(); - image(this, 0, 0, width * 2, height * 2, 0, 0, pixelWidth, pixelHeight); - flushBuffer(); - } - - - ////////////////////////////////////////////////////////////// - - // CLIPPING - - /* - @Override - public void clipImpl(float x1, float y1, float x2, float y2) { - //XXX: exactly the same as the implementation in PGraphicsOpenGL, - //but calls flushBuffer() instead of flush() - flushBuffer(); - pgl.enable(PGL.SCISSOR_TEST); - - float h = y2 - y1; - clipRect[0] = (int)x1; - clipRect[1] = (int)(height - y1 - h); - clipRect[2] = (int)(x2 - x1); - clipRect[3] = (int)h; - pgl.scissor(clipRect[0], clipRect[1], clipRect[2], clipRect[3]); - - clip = true; - } - - @Override - public void noClip() { - //XXX: exactly the same as the implementation in PGraphicsOpenGL, - //but calls flushBuffer() instead of flush() - if (clip) { - flushBuffer(); - pgl.disable(PGL.SCISSOR_TEST); - clip = false; - } - } -*/ - - - ////////////////////////////////////////////////////////////// - - // TEXT - - - //NOTE: a possible improvement to text rendering performance is to batch all glyphs - //from the same texture page together instead of rendering each char strictly in sequence. - //it remains to be seen whether this would improve performance in practice - //(I don't know how common it is for a font to occupy multiple texture pages) - - @Override - protected void textCharModelImpl(FontTexture.TextureInfo info, - float x0, float y0, float x1, float y1) { - incrementDepth(); - check(6); - textureImpl(textTex.textures[info.texIndex].glName); - vertexImpl(x0, y0, info.u0, info.v0, fillColor, 1); - vertexImpl(x1, y0, info.u1, info.v0, fillColor, 1); - vertexImpl(x0, y1, info.u0, info.v1, fillColor, 1); - vertexImpl(x1, y0, info.u1, info.v0, fillColor, 1); - vertexImpl(x0, y1, info.u0, info.v1, fillColor, 1); - vertexImpl(x1, y1, info.u1, info.v1, fillColor, 1); - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX MORE! - - - @Override - protected void begin2D() { - pushProjection(); - defaultPerspective(); - pushMatrix(); - defaultCamera(); - } - - - @Override - protected void end2D() { - popMatrix(); - popProjection(); - } - - - ////////////////////////////////////////////////////////////// - - // SHADER FILTER - - - - @Override - public void filter(PShader shader) { - // TODO: not working... the loadShader() method uses the P2 vertex stage - // The filter method needs to use the geometry-generation in the base class. - // We could re-implement it here, but this is easier. - if (!useParentImpl) { - useOldP2D(); - super.filter(shader); - useNewP2D(); - } else { - super.filter(shader); - } - } - - - - ////////////////////////////////////////////////////////////// - - // SHADER API - - - @Override - public PShader loadShader(String fragFilename) { - if (fragFilename == null || fragFilename.equals("")) { - PGraphics.showWarning(MISSING_FRAGMENT_SHADER); - return null; - } - - PShader shader = new PShader(parent); - - shader.setFragmentShader(fragFilename); - String[] vertSource = pgl.loadVertexShader(defP2DShaderVertURL); - shader.setVertexShader(vertSource); - - return shader; - } - - - @Override - public void shader(PShader shader) { - if (useParentImpl) { - super.shader(shader); - return; - } - flushBuffer(); // Flushing geometry drawn with a different shader. - - if (shader != null) shader.init(); - boolean res = checkShaderLocs(shader); - if (res) { - twoShader = shader; - shader.type = SHADER2D; - } else { - PGraphics.showWarning(NON_2D_SHADER_ERROR); - } - } - - - @Override - public void shader(PShader shader, int kind) { - if (useParentImpl) { - super.shader(shader, kind); - return; - } - PGraphics.showWarning(WRONG_SHADER_PARAMS); - } - - - @Override - public void resetShader() { - if (useParentImpl) { - super.resetShader(); - return; - } - flushBuffer(); - twoShader = null; - } - - - @Override - public void resetShader(int kind) { - if (useParentImpl) { - super.resetShader(kind); - return; - } - PGraphics.showWarning(WRONG_SHADER_PARAMS); - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX TRANSFORMATIONS - - - @Override - public void translate(float tx, float ty, float tz) { - showDepthWarningXYZ("translate"); - } - - @Override - public void rotateX(float angle) { - showDepthWarning("rotateX"); - } - - @Override - public void rotateY(float angle) { - showDepthWarning("rotateY"); - } - - @Override - public void rotateZ(float angle) { - showDepthWarning("rotateZ"); - } - - @Override - public void rotate(float angle, float vx, float vy, float vz) { - showVariationWarning("rotate"); - } - - @Override - public void applyMatrix(PMatrix3D source) { - showVariationWarning("applyMatrix"); - } - - @Override - public void applyMatrix(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - showVariationWarning("applyMatrix"); - } - - @Override - public void scale(float sx, float sy, float sz) { - showDepthWarningXYZ("scale"); - } - - ////////////////////////////////////////////////////////////// - - // SCREEN AND MODEL COORDS - - - @Override - public float screenX(float x, float y, float z) { - showDepthWarningXYZ("screenX"); - return 0; - } - - @Override - public float screenY(float x, float y, float z) { - showDepthWarningXYZ("screenY"); - return 0; - } - - @Override - public float screenZ(float x, float y, float z) { - showDepthWarningXYZ("screenZ"); - return 0; - } - - @Override - public PMatrix3D getMatrix(PMatrix3D target) { - showVariationWarning("getMatrix"); - return target; - } - - @Override - public void setMatrix(PMatrix3D source) { - showVariationWarning("setMatrix"); - } - - ////////////////////////////////////////////////////////////// - - // LIGHTS - - - @Override - public void lights() { - showMethodWarning("lights"); - } - - @Override - public void noLights() { - showMethodWarning("noLights"); - } - - @Override - public void ambientLight(float red, float green, float blue) { - showMethodWarning("ambientLight"); - } - - @Override - public void ambientLight(float red, float green, float blue, - float x, float y, float z) { - showMethodWarning("ambientLight"); - } - - @Override - public void directionalLight(float red, float green, float blue, - float nx, float ny, float nz) { - showMethodWarning("directionalLight"); - } - - @Override - public void pointLight(float red, float green, float blue, - float x, float y, float z) { - showMethodWarning("pointLight"); - } - - @Override - public void spotLight(float red, float green, float blue, - float x, float y, float z, - float nx, float ny, float nz, - float angle, float concentration) { - showMethodWarning("spotLight"); - } - - @Override - public void lightFalloff(float constant, float linear, float quadratic) { - showMethodWarning("lightFalloff"); - } - - @Override - public void lightSpecular(float v1, float v2, float v3) { - showMethodWarning("lightSpecular"); - } - - - ////////////////////////////////////////////////////////////// - - // PRIVATE IMPLEMENTATION - - - //maxVerts can be tweaked for memory/performance trade-off - //in my testing, performance seems to plateau after around 6000 (= 2000*3) - //memory usage should be around ~165kb for 6000 verts - final private int maxVerts = 2000*3; - final private int vertSize = 7*Float.BYTES; //xyzuvcf - private float[] vertexData = new float[maxVerts*7]; - private int usedVerts = 0; - - private float depth = 1.0f; - - private int imageTex; - private int tex; - private int vbo; - private int texWidth, texHeight; - - // Determination of the smallest increments and largest-greater-than-minus-one - // https://en.wikipedia.org/wiki/Half-precision_floating-point_format - - // Using the smallest positive normal number in half (16-bit) precision, which is how the depth - // buffer is initialized in mobile - private float smallestDepthIncrement = (float)Math.pow(2, -14); - - // As the limit for the depth increase, we take the minus the largest number less than one in - // half (16-bit) precision - private float largestNumberLessThanOne = 1 - (float)Math.pow(2, -11); - - private void incrementDepth() { - // By resetting the depth buffer when needed, we are able to have arbitrarily many - // layers, unlimited by depth buffer precision. In practice, the precision of this - // algorithm seems to be acceptable (exactly (1 + 1 - pow(2, -11))/pow(2, -14) = 32,760 layers) - // for mobile. - if (depth < -largestNumberLessThanOne) { - flushBuffer(); - pgl.clear(PGL.DEPTH_BUFFER_BIT); - // Depth test will fail at depth = 1.0 after clearing the depth buffer, - // But since we always increment before drawing anything, this should be okay - depth = 1.0f; - } - - depth -= smallestDepthIncrement; - } - - - private void initTess() { - PGL.TessellatorCallback callback = new PGL.TessellatorCallback() { - - public void begin(int type) { - // TODO Auto-generated method stub - - } - - public void end() { - // TODO Auto-generated method stub - - } - - public void vertex(Object data) { - if (usedVerts % 3 == 0) { - check(3); - } - - TessVertex vert = (TessVertex)data; - vertexImpl(vert.x, vert.y, vert.u, vert.v, vert.c, vert.f); - } - - public void combine(double[] coords, Object[] data, float[] weights, Object[] outData) { - //here we do some horrible things to blend the colors - float r = 0, g = 0, b = 0, a = 0; - for (int i = 0; i < data.length; ++i) { - int c = ((TessVertex)data[i]).c; - a += weights[i] * ((c >> 24) & 0xFF); - r += weights[i] * ((c >> 16) & 0xFF); - g += weights[i] * ((c >> 8) & 0xFF); - b += weights[i] * (c & 0xFF); - } - int c = ((int)a << 24) + ((int)r << 16) + ((int)g << 8) + (int)b; - - float u = 0, v = 0, f = 0; - for (int i = 0; i < data.length; ++i) { - u += weights[i] * ((TessVertex)data[i]).u; - v += weights[i] * ((TessVertex)data[i]).v; - f += weights[i] * ((TessVertex)data[i]).f; - } - - outData[0] = new TessVertex((float)coords[0], (float)coords[1], u, v, c, f); - } - - public void error(int err) { - println("glu error: " + err); - } - }; - tess = pgl.createTessellator(callback); - - // We specify the edge flag callback as a no-op to force the tesselator to only pass us - // triangle primitives (no triangle fans or triangle strips), for simplicity - tess.setCallback(PGL.TESS_EDGE_FLAG); - tess.setWindingRule(PGL.TESS_WINDING_NONZERO); - } - - - private void initVerts() { - for (int i = 0; i < shapeVerts.length; ++i) { - shapeVerts[i] = new TessVertex(); - } - } - - - private void flushBuffer() { - if (usedVerts == 0) { - return; - } - - if (vbo == 0) { - // Generate vbo - IntBuffer vboBuff = IntBuffer.allocate(1); - pgl.genBuffers(1, vboBuff); - vbo = vboBuff.get(0); - } - - // Upload vertex data - pgl.bindBuffer(PGL.ARRAY_BUFFER, vbo); - pgl.bufferData(PGL.ARRAY_BUFFER, usedVerts * vertSize, - FloatBuffer.wrap(vertexData), PGL.DYNAMIC_DRAW); - - PShader shader = getShader(); - shader.bind(); - setAttribs(); - loadUniforms(); - - pgl.drawArrays(PGL.TRIANGLES, 0, usedVerts); - - usedVerts = 0; - shader.unbind(); - - //XXX: DEBUG -// println("flushed: " + tex + ", " + imageTex); - } - - - private boolean checkShaderLocs(PShader shader) { - int positionLoc = shader.getAttributeLoc("position"); - if (positionLoc == -1) { - positionLoc = shader.getAttributeLoc("vertex"); - } -// int colorLoc = shader.getAttributeLoc("color"); - int transformLoc = shader.getUniformLoc("transform"); - if (transformLoc == -1) { - transformLoc = shader.getUniformLoc("transformMatrix"); - } - - /* - // Became less demanding and 2D shaders do not need to have texture uniforms/attribs - int texScaleLoc = shader.getUniformLoc("texScale"); - if (texScaleLoc == -1) { - texScaleLoc = shader.getUniformLoc("texOffset"); - } - int texCoordLoc = shader.getAttributeLoc("texCoord"); - int texFactorLoc = shader.getAttributeLoc("texFactor"); - */ - - return positionLoc != -1 && transformLoc != -1; -// colorLoc != -1 && texCoordLoc != -1 && texFactorLoc != -1 && texScaleLoc != -1; - } - - - private void loadShaderLocs(PShader shader) { - positionLoc = shader.getAttributeLoc("position"); - if (positionLoc == -1) { - positionLoc = shader.getAttributeLoc("vertex"); - } - colorLoc = shader.getAttributeLoc("color"); - texCoordLoc = shader.getAttributeLoc("texCoord"); - texFactorLoc = shader.getAttributeLoc("texFactor"); - transformLoc = shader.getUniformLoc("transform"); - if (transformLoc == -1) { - transformLoc = shader.getUniformLoc("transformMatrix"); - } - texScaleLoc = shader.getUniformLoc("texScale"); - if (texScaleLoc == -1) { - texScaleLoc = shader.getUniformLoc("texOffset"); - } - } - - - private PShader getShader() { - // TODO: Perhaps a better way to handle the new 2D rendering would be to define a PShader2D - // subclass of PShader... - PShader shader; - if (twoShader == null) { - if (defTwoShader == null) { - String[] vertSource = pgl.loadVertexShader(defP2DShaderVertURL); - String[] fragSource = pgl.loadFragmentShader(defP2DShaderFragURL); - defTwoShader = new PShader(parent, vertSource, fragSource); - } - shader = defTwoShader; - } else { - shader = twoShader; - } -// if (shader != defTwoShader) { - loadShaderLocs(shader); -// } - return shader; - } - - @Override - protected PShader getPolyShader(boolean lit, boolean tex) { - return super.getPolyShader(lit, tex); - } - - private void setAttribs() { - pgl.vertexAttribPointer(positionLoc, 3, PGL.FLOAT, false, vertSize, 0); - pgl.enableVertexAttribArray(positionLoc); - if (-1 < texCoordLoc) { - pgl.vertexAttribPointer(texCoordLoc, 2, PGL.FLOAT, false, vertSize, 3*Float.BYTES); - pgl.enableVertexAttribArray(texCoordLoc); - } - pgl.vertexAttribPointer(colorLoc, 4, PGL.UNSIGNED_BYTE, true, vertSize, 5*Float.BYTES); - pgl.enableVertexAttribArray(colorLoc); - if (-1 < texFactorLoc) { - pgl.vertexAttribPointer(texFactorLoc, 1, PGL.FLOAT, false, vertSize, 6*Float.BYTES); - pgl.enableVertexAttribArray(texFactorLoc); - } - } - - - private void loadUniforms() { - //set matrix uniform - pgl.uniformMatrix4fv(transformLoc, 1, true, FloatBuffer.wrap(new PMatrix3D().get(null))); - - //set texture info - pgl.activeTexture(PGL.TEXTURE0); - pgl.bindTexture(PGL.TEXTURE_2D, tex); - if (-1 < texScaleLoc) { - //enable uv scaling only for use-defined images, not for fonts - if (tex == imageTex) { - pgl.uniform2f(texScaleLoc, 1f/texWidth, 1f/texHeight); - } else { - pgl.uniform2f(texScaleLoc, 1, 1); - } - } - } - - - private void textureImpl(int glId) { - if (glId == tex) { - return; //texture is already bound; no work to be done - } - - flushBuffer(); - tex = glId; - } - - - private void check(int newVerts) { - if (usedVerts + newVerts > maxVerts) { - flushBuffer(); - } - } - - - private void vertexImpl(float x, float y, float u, float v, int c, float f) { - int idx = usedVerts * 7; - //inline multiply only x and y to avoid an allocation and a few flops - vertexData[idx + 0] = projmodelview.m00*x + projmodelview.m01*y + projmodelview.m03; - vertexData[idx + 1] = projmodelview.m10*x + projmodelview.m11*y + projmodelview.m13; - vertexData[idx + 2] = depth; - vertexData[idx + 3] = u; - vertexData[idx + 4] = v; - vertexData[idx + 5] = Float.intBitsToFloat(c); - vertexData[idx + 6] = f; - usedVerts++; - } - - - private void vertexImpl(TessVertex vert) { - vertexImpl(vert.x, vert.y, vert.u, vert.v, vert.c, vert.f); - } - - - //one of POINTS, LINES, TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, QUAD_STRIP, POLYGON - private int shapeType; - private int vertCount; - private TessVertex[] shapeVerts = new TessVertex[16]; //initial size is arbitrary - - //list of indices (into shapeVerts array) at which a new contour begins - private int[] contours = new int[2]; //initial size is arbitrary - private int contourCount; - - - private void appendContour(int vertIndex) { - //dynamically expand contour array as needed - if (contourCount >= contours.length) { - contours = PApplet.expand(contours, contours.length * 2); - } - - contours[contourCount] = vertIndex; - contourCount += 1; - } - - - //used by endShape() as a temporary to avoid unnecessary allocations - private double[] tempDoubles = new double[3]; - - //If this flag is set, then the next call to endShape() with shape type of POLYGON - //will triangulate blindly instead of going through the GLU tessellator (for performance). - //This is useful for shapes (like ellipse(), rect(), etc.) that we know will always be convex. - //TODO: Make this an optional argument to endShape() - //once we start integrating PGraphics4D into the rest of the codebase. - private boolean knownConvexPolygon = false; - - - private void shapeVertex(float x, float y, float u, float v, int c, float f) { - //avoid adding a duplicate because it will cause the GLU tess to fail spectacularly - //by spitting out-of-memory errors and passing null parameters to the combine() callback - //TODO: figure out why that happens and how to stop it - //(P2D renderer doesn't appear to have such a problem, so presumably there must be a way) - for (int i = 0; i < vertCount; ++i) { - if (shapeVerts[i].x == x && shapeVerts[i].y == y) { - return; - } - } - - //dynamically expand input vertex array as needed - if (vertCount >= shapeVerts.length) { - shapeVerts = (TessVertex[]) PApplet.expand(shapeVerts, shapeVerts.length * 2); - - //allocate objects for the new half of the array so we don't NPE ourselves - for (int i = shapeVerts.length/2; i < shapeVerts.length; ++i) { - shapeVerts[i] = new TessVertex(); - } - } - - shapeVerts[vertCount].set(x, y, u, v, c, f); - vertCount += 1; - } - - - private void triangle(float x1, float y1, float x2, float y2, float x3, float y3, int color) { - check(3); - vertexImpl(x1, y1, 0, 0, color, 0); - vertexImpl(x2, y2, 0, 0, color, 0); - vertexImpl(x3, y3, 0, 0, color, 0); - } - - - //below r == LINE_DETAIL_LIMIT, all lines will be drawn as plain rectangles - //instead of using fancy stroke rendering algorithms, since the result is visually indistinguishable - static final private float LINE_DETAIL_LIMIT = 1.0f; - - - private void singleLine(float x1, float y1, float x2, float y2, int color) { - float r = strokeWeight * 0.5f; - - float dx = x2 - x1; - float dy = y2 - y1; - float d = PApplet.sqrt(dx*dx + dy*dy); - float tx = dy / d * r; - float ty = dx / d * r; - - if (strokeCap == PROJECT) { - x1 -= ty; - x2 += ty; - y1 -= tx; - y2 += tx; - } - - triangle(x1 - tx, y1 + ty, x1 + tx, y1 - ty, x2 - tx, y2 + ty, color); - triangle(x2 + tx, y2 - ty, x2 - tx, y2 + ty, x1 + tx, y1 - ty, color); - - if (r >= LINE_DETAIL_LIMIT && strokeCap == ROUND) { - int segments = circleDetail(r, HALF_PI); - float step = HALF_PI / segments; - float c = PApplet.cos(step); - float s = PApplet.sin(step); - for (int i = 0; i < segments; ++i) { - //this is the equivalent of multiplying the vector by the 2x2 rotation matrix [[c -s] [s c]] - float nx = c * tx - s * ty; - float ny = s * tx + c * ty; - - triangle(x2, y2, x2 + ty, y2 + tx, x2 + ny, y2 + nx, color); - triangle(x2, y2, x2 - tx, y2 + ty, x2 - nx, y2 + ny, color); - triangle(x1, y1, x1 - ty, y1 - tx, x1 - ny, y1 - nx, color); - triangle(x1, y1, x1 + tx, y1 - ty, x1 + nx, y1 - ny, color); - - tx = nx; - ty = ny; - } - } - } - - - private void singlePoint(float x, float y, int color) { - float r = strokeWeight * 0.5f; - if (r >= LINE_DETAIL_LIMIT && strokeCap == ROUND) { - int segments = circleDetail(r); - float step = QUARTER_PI / segments; - - float x1 = 0, y1 = r; - float c = PApplet.cos(step); - float s = PApplet.sin(step); - for (int i = 0; i < segments; ++i) { - //this is the equivalent of multiplying the vector by the 2x2 rotation matrix [[c -s] [s c]] - float x2 = c * x1 - s * y1; - float y2 = s * x1 + c * y1; - - triangle(x, y, x + x1, y + y1, x + x2, y + y2, strokeColor); - triangle(x, y, x + x1, y - y1, x + x2, y - y2, strokeColor); - triangle(x, y, x - x1, y + y1, x - x2, y + y2, strokeColor); - triangle(x, y, x - x1, y - y1, x - x2, y - y2, strokeColor); - - triangle(x, y, x + y1, y + x1, x + y2, y + x2, strokeColor); - triangle(x, y, x + y1, y - x1, x + y2, y - x2, strokeColor); - triangle(x, y, x - y1, y + x1, x - y2, y + x2, strokeColor); - triangle(x, y, x - y1, y - x1, x - y2, y - x2, strokeColor); - - x1 = x2; - y1 = y2; - } - } else { - triangle(x - r, y - r, x + r, y - r, x - r, y + r, color); - triangle(x + r, y - r, x - r, y + r, x + r, y + r, color); - } - } - - - private StrokeRenderer sr = new StrokeRenderer(); - - - private class StrokeRenderer { - int lineVertexCount; - float fx, fy; - float sx, sy, sdx, sdy; - float px, py, pdx, pdy; - float lx, ly; - float r; - - - void arcJoin(float x, float y, float dx1, float dy1, float dx2, float dy2) { - //we don't need to normalize before doing these products - //since the vectors are the same length and only used as arguments to atan2() - float cross = dx1 * dy2 - dy1 * dx2; - float dot = dx1 * dx2 + dy1 * dy2; - float theta = PApplet.atan2(cross, dot); - int segments = circleDetail(r, theta); - float px = x + dx1, py = y + dy1; - if (segments > 1) { - float c = PApplet.cos(theta / segments); - float s = PApplet.sin(theta / segments); - for (int i = 1; i < segments; ++i) { - //this is the equivalent of multiplying the vector by the 2x2 rotation matrix [[c -s] [s c]] - float tempx = c * dx1 - s * dy1; - dy1 = s * dx1 + c * dy1; - dx1 = tempx; - - float nx = x + dx1; - float ny = y + dy1; - triangle(x, y, px, py, nx, ny, strokeColor); - px = nx; - py = ny; - } - } - triangle(x, y, px, py, x + dx2, y + dy2, strokeColor); - } - - void beginLine() { - lineVertexCount = 0; - r = strokeWeight * 0.5f; - } - - void lineVertex(float x, float y) { - //disallow adding consecutive duplicate vertices, - //as it is pointless and just creates an extra edge case - if (lineVertexCount > 0 && x == lx && y == ly) { - return; - } - - if (lineVertexCount == 0) { - fx = x; - fy = y; - } else if (r < LINE_DETAIL_LIMIT) { - singleLine(lx, ly, x, y, strokeColor); - } else if (lineVertexCount == 1) { - sx = x; - sy = y; - } else { - //calculate normalized direction vectors for each leg - float leg1x = lx - px; - float leg1y = ly - py; - float leg2x = x - lx; - float leg2y = y - ly; - float len1 = PApplet.sqrt(leg1x * leg1x + leg1y * leg1y); - float len2 = PApplet.sqrt(leg2x * leg2x + leg2y * leg2y); - leg1x /= len1; - leg1y /= len1; - leg2x /= len2; - leg2y /= len2; - - float legDot = -leg1x * leg2x - leg1y * leg2y; - float cosPiOver15 = 0.97815f; - if (strokeJoin == BEVEL || strokeJoin == ROUND || legDot > cosPiOver15 || legDot < -0.999) { - float tx = leg1y * r; - float ty = -leg1x * r; - - if (lineVertexCount == 2) { - sdx = tx; - sdy = ty; - } else { - triangle(px - pdx, py - pdy, px + pdx, py + pdy, lx - tx, ly - ty, strokeColor); - triangle(px + pdx, py + pdy, lx - tx, ly - ty, lx + tx, ly + ty, strokeColor); - } - - float nx = leg2y * r; - float ny = -leg2x * r; - - float legCross = leg1x * leg2y - leg1y * leg2x; - if (strokeJoin == ROUND) { - if (legCross > 0) { - arcJoin(lx, ly, tx, ty, nx, ny); - } else { - arcJoin(lx, ly, -tx, -ty, -nx, -ny); - } - } else if (legCross > 0) { - triangle(lx, ly, lx + tx, ly + ty, lx + nx, ly + ny, strokeColor); - } else { - triangle(lx, ly, lx - tx, ly - ty, lx - nx, ly - ny, strokeColor); - } - - pdx = nx; - pdy = ny; - } else { //miter joint - //find the bisecting vector - float x1 = leg2x - leg1x; - float y1 = leg2y - leg1y; - //find a (normalized) vector perpendicular to one of the legs - float x2 = leg1y; - float y2 = -leg1x; - //scale the bisecting vector to the correct length using magic (not sure how to explain this one) - float dot = x1 * x2 + y1 * y2; - float bx = x1 * (r / dot); - float by = y1 * (r / dot); - - if (lineVertexCount == 2) { - sdx = bx; - sdy = by; - } else { - triangle(px - pdx, py - pdy, px + pdx, py + pdy, lx - bx, ly - by, strokeColor); - triangle(px + pdx, py + pdy, lx - bx, ly - by, lx + bx, ly + by, strokeColor); - } - - pdx = bx; - pdy = by; - } - } - - px = lx; - py = ly; - lx = x; - ly = y; - - lineVertexCount += 1; - } - - void lineCap(float x, float y, float dx, float dy) { - int segments = circleDetail(r, HALF_PI); - float px = dy, py = -dx; - if (segments > 1) { - float c = PApplet.cos(HALF_PI / segments); - float s = PApplet.sin(HALF_PI / segments); - for (int i = 1; i < segments; ++i) { - //this is the equivalent of multiplying the vector by the 2x2 rotation matrix [[c -s] [s c]] - float nx = c * px - s * py; - float ny = s * px + c * py; - triangle(x, y, x + px, y + py, x + nx, y + ny, strokeColor); - triangle(x, y, x - py, y + px, x - ny, y + nx, strokeColor); - px = nx; - py = ny; - } - } - triangle(x, y, x + px, y + py, x + dx, y + dy, strokeColor); - triangle(x, y, x - py, y + px, x - dy, y + dx, strokeColor); - } - - void endLine(boolean closed) { - if (lineVertexCount < 2) { - return; - } - - if (lineVertexCount == 2) { - singleLine(px, py, lx, ly, strokeColor); - return; - } - - if (r < LINE_DETAIL_LIMIT) { - if (closed) { - singleLine(lx, ly, fx, fy, strokeColor); - } - return; - } - - if (closed) { - //draw the last two legs - lineVertex(fx, fy); - lineVertex(sx, sy); - - //connect first and second vertices - triangle(px - pdx, py - pdy, px + pdx, py + pdy, sx - sdx, sy - sdy, strokeColor); - triangle(px + pdx, py + pdy, sx - sdx, sy - sdy, sx + sdx, sy + sdy, strokeColor); - } else { - //draw last line (with cap) - float dx = lx - px; - float dy = ly - py; - float d = PApplet.sqrt(dx*dx + dy*dy); - float tx = dy / d * r; - float ty = -dx / d * r; - - if (strokeCap == PROJECT) { - lx -= ty; - ly += tx; - } - - triangle(px - pdx, py - pdy, px + pdx, py + pdy, lx - tx, ly - ty, strokeColor); - triangle(px + pdx, py + pdy, lx - tx, ly - ty, lx + tx, ly + ty, strokeColor); - - if (strokeCap == ROUND) { - lineCap(lx, ly, -ty, tx); - } - - //draw first line (with cap) - dx = fx - sx; - dy = fy - sy; - d = PApplet.sqrt(dx*dx + dy*dy); - tx = dy / d * r; - ty = -dx / d * r; - - if (strokeCap == PROJECT) { - fx -= ty; - fy += tx; - } - - triangle(sx - sdx, sy - sdy, sx + sdx, sy + sdy, fx + tx, fy + ty, strokeColor); - triangle(sx + sdx, sy + sdy, fx + tx, fy + ty, fx - tx, fy - ty, strokeColor); - - if (strokeCap == ROUND) { - lineCap(fx, fy, -ty, tx); - } - } - } - } - - - //returns the total number of points needed to approximate an arc of a given radius and extent - int circleDetail(float radius, float delta) { - //this serves as a rough approximation of how much the longest axis - //of an ellipse will be scaled by a given matrix - //(in other words, the amount by which its on-screen size changes) - float sxi = projmodelview.m00 * width / 2; - float syi = projmodelview.m10 * height / 2; - float sxj = projmodelview.m01 * width / 2; - float syj = projmodelview.m11 * height / 2; - float Imag2 = sxi * sxi + syi * syi; - float Jmag2 = sxj * sxj + syj * syj; - float ellipseDetailMultiplier = PApplet.sqrt(PApplet.max(Imag2, Jmag2)); - radius *= ellipseDetailMultiplier; - return (int)(PApplet.min(127, PApplet.sqrt(radius) / QUARTER_PI * PApplet.abs(delta) * 0.75f) + 1); - } - - - //returns the number of points per quadrant needed to approximate a circle of a given radius - int circleDetail(float radius) { - return circleDetail(radius, QUARTER_PI); - } - - - private class TessVertex { - float x, y, u, v; - int c; - float f; //1.0 if textured, 0.0 if flat - - public TessVertex() { - //no-op - } - - public TessVertex(float x, float y, float u, float v, int c, float f) { - set(x, y, u, v, c, f); - } - - public void set(float x, float y, float u, float v, int c, float f) { - this.x = x; - this.y = y; - this.u = u; - this.v = v; - this.c = c; - this.f = f; - } - - @Override - public String toString() { - return x + ", " + y; - } - } -} diff --git a/core/src/processing/opengl/PGraphics3D.java b/core/src/processing/opengl/PGraphics3D.java deleted file mode 100644 index 5a5e1c3b3..000000000 --- a/core/src/processing/opengl/PGraphics3D.java +++ /dev/null @@ -1,281 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import processing.core.PGraphics; -import processing.core.PShape; -import processing.core.PShapeOBJ; - - -public class PGraphics3D extends PGraphicsOpenGL { - - public PGraphics3D() { - super(); - } - - - ////////////////////////////////////////////////////////////// - - // RENDERER SUPPORT QUERIES - - - @Override - public boolean is2D() { - return false; - } - - - @Override - public boolean is3D() { - return true; - } - - - ////////////////////////////////////////////////////////////// - - // PROJECTION - - - @Override - protected void defaultPerspective() { - perspective(); - } - - - ////////////////////////////////////////////////////////////// - - // CAMERA - - - @Override - protected void defaultCamera() { - camera(); - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX MORE! - - - @Override - protected void begin2D() { - pushProjection(); - ortho(-width/2f, width/2f, -height/2f, height/2f); - pushMatrix(); - - // Set camera for 2D rendering, it simply centers at (width/2, height/2) - float centerX = width/2f; - float centerY = height/2f; - modelview.reset(); - modelview.translate(-centerX, -centerY); - - modelviewInv.set(modelview); - modelviewInv.invert(); - - camera.set(modelview); - cameraInv.set(modelviewInv); - - updateProjmodelview(); - } - - - @Override - protected void end2D() { - popMatrix(); - popProjection(); - } - - - - ////////////////////////////////////////////////////////////// - - // SHAPE I/O - - - static protected boolean isSupportedExtension(String extension) { - return extension.equals("obj"); - } - - - static protected PShape loadShapeImpl(PGraphics pg, String filename, - String extension) { - PShapeOBJ obj = null; - - if (extension.equals("obj")) { - obj = new PShapeOBJ(pg.parent, filename); - int prevTextureMode = pg.textureMode; - pg.textureMode = NORMAL; - PShapeOpenGL p3d = PShapeOpenGL.createShape((PGraphicsOpenGL)pg, obj); - pg.textureMode = prevTextureMode; - return p3d; - } - return null; - } - - - - ////////////////////////////////////////////////////////////// - - // SHAPE CREATION - - -// @Override -// protected PShape createShapeFamily(int type) { -// PShape shape = new PShapeOpenGL(this, type); -// shape.set3D(true); -// return shape; -// } -// -// -// @Override -// protected PShape createShapePrimitive(int kind, float... p) { -// PShape shape = new PShapeOpenGL(this, kind, p); -// shape.set3D(true); -// return shape; -// } - - - /* - @Override - public PShape createShape(PShape source) { - return PShapeOpenGL.createShape3D(this, source); - } - - - @Override - public PShape createShape() { - return createShape(PShape.GEOMETRY); - } - - - @Override - public PShape createShape(int type) { - return createShapeImpl(this, type); - } - - - @Override - public PShape createShape(int kind, float... p) { - return createShapeImpl(this, kind, p); - } - - - static protected PShapeOpenGL createShapeImpl(PGraphicsOpenGL pg, int type) { - PShapeOpenGL shape = null; - if (type == PConstants.GROUP) { - shape = new PShapeOpenGL(pg, PConstants.GROUP); - } else if (type == PShape.PATH) { - shape = new PShapeOpenGL(pg, PShape.PATH); - } else if (type == PShape.GEOMETRY) { - shape = new PShapeOpenGL(pg, PShape.GEOMETRY); - } - shape.set3D(true); - return shape; - } - - - static protected PShapeOpenGL createShapeImpl(PGraphicsOpenGL pg, - int kind, float... p) { - PShapeOpenGL shape = null; - int len = p.length; - - if (kind == POINT) { - if (len != 2 && len != 3) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(POINT); - } else if (kind == LINE) { - if (len != 4 && len != 6) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(LINE); - } else if (kind == TRIANGLE) { - if (len != 6) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(TRIANGLE); - } else if (kind == QUAD) { - if (len != 8) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(QUAD); - } else if (kind == RECT) { - if (len != 4 && len != 5 && len != 8 && len != 9) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(RECT); - } else if (kind == ELLIPSE) { - if (len != 4 && len != 5) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(ELLIPSE); - } else if (kind == ARC) { - if (len != 6 && len != 7) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(ARC); - - } else if (kind == BOX) { - if (len != 1 && len != 3) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(BOX); - } else if (kind == SPHERE) { - if (len < 1 || 3 < len) { - showWarning("Wrong number of parameters"); - return null; - } - shape = new PShapeOpenGL(pg, PShape.PRIMITIVE); - shape.setKind(SPHERE); - } else { - showWarning("Unrecognized primitive type"); - } - - if (shape != null) { - shape.setParams(p); - } - - shape.set3D(true); - return shape; - } - */ -} \ No newline at end of file diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java deleted file mode 100644 index 478a2f13b..000000000 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ /dev/null @@ -1,14280 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import processing.android.AppComponent; -import processing.core.*; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.net.URL; -import java.nio.*; -import java.util.*; - -import android.content.Context; -import android.os.Environment; -import android.view.SurfaceHolder; - -import static android.os.Environment.isExternalStorageRemovable; - -/** - * OpenGL renderer. - */ -public class PGraphicsOpenGL extends PGraphics { - /** Interface between Processing and OpenGL */ - public PGL pgl; - - /** The renderer currently in use. */ - public PGraphicsOpenGL currentPG; - - /** Font cache for texture objects. */ - protected WeakHashMap fontMap; - - // ........................................................ - - // Disposal of native resources - // Using the technique alternative to finalization described in: - // http://www.oracle.com/technetwork/articles/java/finalization-137655.html - private static ReferenceQueue refQueue = new ReferenceQueue<>(); - private static List> reachableWeakReferences = - new LinkedList<>(); - - static final private int MAX_DRAIN_GLRES_ITERATIONS = 10; - - static void drainRefQueueBounded() { - int iterations = 0; - while (iterations < MAX_DRAIN_GLRES_ITERATIONS) { - Disposable res = - (Disposable) refQueue.poll(); - if (res == null) { - break; - } - res.dispose(); - ++iterations; - } - } - - private static abstract class Disposable extends WeakReference { - protected Disposable(T obj) { - super(obj, refQueue); - drainRefQueueBounded(); - reachableWeakReferences.add(this); - } - - public void dispose() { - reachableWeakReferences.remove(this); - disposeNative(); - } - - abstract public void disposeNative(); - } - - // Basic rendering parameters: - - /** Whether the PGraphics object is ready to render or not. */ - public boolean initialized; - - /** Flush modes: continuously (geometry is flushed after each call to - * endShape) when-full (geometry is accumulated until a maximum size is - * reached. */ - static protected final int FLUSH_CONTINUOUSLY = 0; - static protected final int FLUSH_WHEN_FULL = 1; - - /** Type of geometry: immediate is that generated with beginShape/vertex/ - * endShape, retained is the result of creating a PShapeOpenGL object with - * createShape. */ - static protected final int IMMEDIATE = 0; - static protected final int RETAINED = 1; - - /** Current flush mode. */ - protected int flushMode = FLUSH_WHEN_FULL; - - - // ........................................................ - - // VBOs for immediate rendering: - - protected VertexBuffer bufPolyVertex; - protected VertexBuffer bufPolyColor; - protected VertexBuffer bufPolyNormal; - protected VertexBuffer bufPolyTexcoord; - protected VertexBuffer bufPolyAmbient; - protected VertexBuffer bufPolySpecular; - protected VertexBuffer bufPolyEmissive; - protected VertexBuffer bufPolyShininess; - protected VertexBuffer bufPolyIndex; - protected boolean polyBuffersCreated = false; - protected int polyBuffersContext; - - protected VertexBuffer bufLineVertex; - protected VertexBuffer bufLineColor; - protected VertexBuffer bufLineAttrib; - protected VertexBuffer bufLineIndex; - protected boolean lineBuffersCreated = false; - protected int lineBuffersContext; - - protected VertexBuffer bufPointVertex; - protected VertexBuffer bufPointColor; - protected VertexBuffer bufPointAttrib; - protected VertexBuffer bufPointIndex; - protected boolean pointBuffersCreated = false; - protected int pointBuffersContext; - - // Generic vertex attributes (only for polys) - protected AttributeMap polyAttribs; - - static protected final int INIT_VERTEX_BUFFER_SIZE = 256; - static protected final int INIT_INDEX_BUFFER_SIZE = 512; - - // ........................................................ - - // GL parameters - - static protected boolean glParamsRead = false; - - /** Extensions used by Processing */ - static public boolean npotTexSupported; - static public boolean autoMipmapGenSupported; - static public boolean fboMultisampleSupported; - static public boolean packedDepthStencilSupported; - static public boolean anisoSamplingSupported; - static public boolean blendEqSupported; - static public boolean readBufferSupported; - static public boolean drawBufferSupported; - - /** Some hardware limits */ - static public int maxTextureSize; - static public int maxSamples; - static public float maxAnisoAmount; - static public int depthBits; - static public int stencilBits; - - /** OpenGL information strings */ - static public String OPENGL_VENDOR; - static public String OPENGL_RENDERER; - static public String OPENGL_VERSION; - static public String OPENGL_EXTENSIONS; - static public String GLSL_VERSION; - - // ........................................................ - - // Shaders - - static protected URL defColorShaderVertURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/ColorVert.glsl"); - static protected URL defTextureShaderVertURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/TexVert.glsl"); - static protected URL defLightShaderVertURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/LightVert.glsl"); - static protected URL defTexlightShaderVertURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/TexLightVert.glsl"); - static protected URL defColorShaderFragURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/ColorFrag.glsl"); - static protected URL defTextureShaderFragURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/TexFrag.glsl"); - static protected URL defLightShaderFragURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/LightFrag.glsl"); - static protected URL defTexlightShaderFragURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/TexLightFrag.glsl"); - - static protected URL defLineShaderVertURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/LineVert.glsl"); - static protected URL defLineShaderFragURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/LineFrag.glsl"); - static protected URL defPointShaderVertURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/PointVert.glsl"); - static protected URL defPointShaderFragURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/PointFrag.glsl"); - static protected URL maskShaderFragURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/MaskFrag.glsl"); - - protected PShader defColorShader; - protected PShader defTextureShader; - protected PShader defLightShader; - protected PShader defTexlightShader; - protected PShader defLineShader; - protected PShader defPointShader; - protected PShader maskShader; - - protected PShader polyShader; - protected PShader lineShader; - protected PShader pointShader; - - // ........................................................ - - // Tessellator, geometry - - protected InGeometry inGeo; - protected TessGeometry tessGeo; - protected TexCache texCache; - protected Tessellator tessellator; - - // ........................................................ - - // Depth sorter - - protected DepthSorter sorter; - protected boolean isDepthSortingEnabled; - - // ........................................................ - - // Async pixel reader - - protected AsyncPixelReader asyncPixelReader; - protected boolean asyncPixelReaderInitialized; - - // Keeps track of ongoing transfers so they can be finished. - // Set is copied to the List when we need to iterate it - // so that readers can remove themselves from the Set during - // iteration if they don't have any ongoing transfers. - protected static final Set - ongoingPixelTransfers = new HashSet<>(); - protected static final List - ongoingPixelTransfersIterable = new ArrayList<>(); - - // ........................................................ - - // Camera: - - /** Camera field of view. */ - public float cameraFOV; - - /** Default position of the camera. */ - public float cameraX, cameraY, cameraZ; - /** Distance of the near and far planes. */ - public float cameraNear, cameraFar; - /** Aspect ratio of camera's view. */ - public float cameraAspect; - - /** Default camera properties. */ - public float defCameraFOV; - public float defCameraX, defCameraY, defCameraZ; - public float defCameraNear, defCameraFar; - public float defCameraAspect; - - /** Distance between camera eye and center. */ - protected float eyeDist; - - /** Flag to indicate that we are inside beginCamera/endCamera block. */ - protected boolean manipulatingCamera; - - /** - * Sets the coordinates to "first person" setting: Y axis up, origin at - * screen center - */ - protected boolean cameraUp = false; - - // ........................................................ - - // All the matrices required for camera and geometry transformations. - public PMatrix3D projection; - public PMatrix3D camera; - public PMatrix3D cameraInv; - public PMatrix3D modelview; - public PMatrix3D modelviewInv; - public PMatrix3D projmodelview; - - // To pass to shaders - protected float[] glProjection; - protected float[] glModelview; - protected float[] glProjmodelview; - protected float[] glNormal; - - // Useful to have around. - static protected PMatrix3D identity = new PMatrix3D(); - - /** - * Marks when changes to the size have occurred, so that the camera - * will be reset in beginDraw(). - */ - protected boolean sized; - - /** - * Marks when some changes have occurred, to the surface view. - */ - protected boolean changed; - - static protected final int MATRIX_STACK_DEPTH = 32; - - protected int modelviewStackDepth; - protected int projectionStackDepth; - - /** Modelview matrix stack **/ - protected float[][] modelviewStack = new float[MATRIX_STACK_DEPTH][16]; - - /** Inverse modelview matrix stack **/ - protected float[][] modelviewInvStack = new float[MATRIX_STACK_DEPTH][16]; - - /** Camera matrix stack **/ - protected float[][] cameraStack = new float[MATRIX_STACK_DEPTH][16]; - - /** Inverse camera matrix stack **/ - protected float[][] cameraInvStack = new float[MATRIX_STACK_DEPTH][16]; - - /** Projection matrix stack **/ - protected float[][] projectionStack = new float[MATRIX_STACK_DEPTH][16]; - - - /** Matrix that transform coordinates to the eye coordinate system **/ - protected PMatrix3D eyeMatrix; - - /** Matrix that transform coordinates to the system that results from appling the modelview transformation **/ - protected PMatrix3D objMatrix; - - /** Vectors defining the eye axes **/ - public float forwardX, forwardY, forwardZ; - public float rightX, rightY, rightZ; - public float upX, upY, upZ; - - // ........................................................ - - // Lights: - - public boolean lights; - public int lightCount = 0; - - /** Light types */ - public int[] lightType; - - /** Light positions */ - public float[] lightPosition; - - /** Light direction (normalized vector) */ - public float[] lightNormal; - - /** - * Ambient colors for lights. - */ - public float[] lightAmbient; - - /** - * Diffuse colors for lights. - */ - public float[] lightDiffuse; - - /** - * Specular colors for lights. Internally these are stored as numbers between - * 0 and 1. - */ - public float[] lightSpecular; - - /** Light falloff */ - public float[] lightFalloffCoefficients; - - /** Light spot parameters: Cosine of light spot angle - * and concentration */ - public float[] lightSpotParameters; - - /** Current specular color for lighting */ - public float[] currentLightSpecular; - - /** Current light falloff */ - public float currentLightFalloffConstant; - public float currentLightFalloffLinear; - public float currentLightFalloffQuadratic; - - // ........................................................ - - // Texturing: - - protected int textureWrap = CLAMP; - protected int textureSampling = Texture.TRILINEAR; - - // ........................................................ - - // Clipping - - protected boolean clip = false; - - /** Clipping rectangle. */ - protected int[] clipRect = {0, 0, 0, 0}; - - - // ........................................................ - - // Text: - - /** Font texture of currently selected font. */ - FontTexture textTex; - - // ....................................................... - - // Framebuffer stack: - - static protected final int FB_STACK_DEPTH = 16; - - protected int fbStackDepth; - protected FrameBuffer[] fbStack; - protected FrameBuffer drawFramebuffer; - protected FrameBuffer readFramebuffer; - protected FrameBuffer currentFramebuffer; - - // ....................................................... - - // Offscreen rendering: - - protected FrameBuffer offscreenFramebuffer; - protected FrameBuffer multisampleFramebuffer; - protected boolean offscreenMultisample; - - protected boolean pixOpChangedFB; - - // ........................................................ - - // Screen surface: - - /** Texture containing the current frame */ - protected Texture texture = null; - - /** Texture containing the previous frame */ - protected Texture ptexture = null; - - /** IntBuffer wrapping the pixels array. */ - protected IntBuffer pixelBuffer; - - /** Array to store pixels in OpenGL format. */ - protected int[] nativePixels; - - /** IntBuffer wrapping the native pixels array. */ - protected IntBuffer nativePixelBuffer; - - /** texture used to apply a filter on the screen image. */ - protected Texture filterTexture = null; - - /** PImage that wraps filterTexture. */ - protected PImage filterImage; - - // ........................................................ - - // Utility variables: - - /** True if we are inside a beginDraw()/endDraw() block. */ - protected boolean drawing = false; - - /** Used to detect continuous use of the smooth/noSmooth functions */ - protected boolean smoothDisabled = false; - protected int smoothCallCount = 0; - protected int lastSmoothCall = -10; - - /** Used to avoid flushing the geometry when blendMode() is called with the - * same blend mode as the last */ - protected int lastBlendMode = -1; - - /** Type of pixels operation. */ - static protected final int OP_NONE = 0; - static protected final int OP_READ = 1; - static protected final int OP_WRITE = 2; - protected int pixelsOp = OP_NONE; - - /** Viewport dimensions. */ - protected IntBuffer viewport; - - protected boolean openContour = false; - protected boolean breakShape = false; - protected boolean defaultEdges = false; - - static protected final int EDGE_MIDDLE = 0; - static protected final int EDGE_START = 1; - static protected final int EDGE_STOP = 2; - static protected final int EDGE_SINGLE = 3; - static protected final int EDGE_CLOSE = -1; - - /** Used in round point and ellipse tessellation. The - * number of subdivisions per round point or ellipse is - * calculated with the following formula: - * n = min(M, max(N, (TWO_PI * size / F))) - * where size is a measure of the dimensions of the circle - * when projected on screen coordinates. F just sets the - * minimum number of subdivisions, while a smaller F - * would allow to have more detailed circles. - * N = MIN_POINT_ACCURACY - * M = MAX_POINT_ACCURACY - * F = POINT_ACCURACY_FACTOR - */ - final static protected int MIN_POINT_ACCURACY = 20; - final static protected int MAX_POINT_ACCURACY = 200; - final static protected float POINT_ACCURACY_FACTOR = 10.0f; - - /** Used in quad point tessellation. */ - final static protected float[][] QUAD_POINT_SIGNS = - { {-1, +1}, {-1, -1}, {+1, -1}, {+1, +1} }; - - /** To get data from OpenGL. */ - static protected IntBuffer intBuffer; - static protected FloatBuffer floatBuffer; - - // ........................................................ - - // Variables used in ray casting: - - protected PVector[] ray; - protected PVector hit = new PVector(); - protected PVector screen = new PVector(); - - protected PVector origInObjCoord = new PVector(); - protected PVector hitInObjCoord = new PVector(); - protected PVector dirInObjCoord = new PVector(); - - protected PVector origInWorldCoord = new PVector(); - protected PVector dirInWorldCoord = new PVector(); - - // ........................................................ - - // Error strings: - - static final String OPENGL_THREAD_ERROR = - "Cannot run the OpenGL renderer outside the main thread, change your code" + - "\nso the drawing calls are all inside the main thread, " + - "\nor use the default renderer instead."; - static final String BLEND_DRIVER_ERROR = - "blendMode(%1$s) is not supported by this hardware (or driver)"; - static final String BLEND_RENDERER_ERROR = - "blendMode(%1$s) is not supported by this renderer"; - static final String ALREADY_BEGAN_CONTOUR_ERROR = - "Already called beginContour()"; - static final String NO_BEGIN_CONTOUR_ERROR = - "Need to call beginContour() first"; - static final String UNSUPPORTED_SMOOTH_LEVEL_ERROR = - "Smooth level %1$s is not available. Using %2$s instead"; - static final String UNSUPPORTED_SMOOTH_ERROR = - "Smooth is not supported by this hardware (or driver)"; - static final String TOO_MANY_SMOOTH_CALLS_ERROR = - "The smooth/noSmooth functions are being called too often.\n" + - "This results in screen flickering, so they will be disabled\n" + - "for the rest of the sketch's execution"; - static final String UNSUPPORTED_SHAPE_FORMAT_ERROR = - "Unsupported shape format"; - static final String MISSING_UV_TEXCOORDS_ERROR = - "No uv texture coordinates supplied with vertex() call"; - static final String INVALID_FILTER_SHADER_ERROR = - "Your shader cannot be used as a filter because is of type POINT or LINES"; - static final String INCONSISTENT_SHADER_TYPES = - "The vertex and fragment shaders have different types"; - static final String WRONG_SHADER_TYPE_ERROR = - "shader() called with a wrong shader"; - static final String SHADER_NEED_LIGHT_ATTRIBS = - "The provided shader needs light attributes (ambient, diffuse, etc.), but " + - "the current scene is unlit, so the default shader will be used instead"; - static final String MISSING_FRAGMENT_SHADER = - "The fragment shader is missing, cannot create shader object"; - static final String MISSING_VERTEX_SHADER = - "The vertex shader is missing, cannot create shader object"; - static final String UNKNOWN_SHADER_KIND_ERROR = - "Unknown shader kind"; - static final String NO_TEXLIGHT_SHADER_ERROR = - "Your shader needs to be of TEXLIGHT type " + - "to render this geometry properly, using default shader instead."; - static final String NO_LIGHT_SHADER_ERROR = - "Your shader needs to be of LIGHT type " + - "to render this geometry properly, using default shader instead."; - static final String NO_TEXTURE_SHADER_ERROR = - "Your shader needs to be of TEXTURE type " + - "to render this geometry properly, using default shader instead."; - static final String NO_COLOR_SHADER_ERROR = - "Your shader needs to be of COLOR type " + - "to render this geometry properly, using default shader instead."; - static final String TESSELLATION_ERROR = - "Tessellation Error: %1$s"; - static final String GL_THREAD_NOT_CURRENT = - "You are trying to draw outside OpenGL's animation thread.\n" + - "Place all drawing commands in the draw() function, or inside\n" + - "your own functions as long as they are called from draw(),\n" + - "but not in event handling functions such as keyPressed()\n" + - "or mousePressed()."; - - ////////////////////////////////////////////////////////////// - - // INIT/ALLOCATE/FINISH - - - public PGraphicsOpenGL() { - pgl = createPGL(this); - - if (intBuffer == null) { - intBuffer = PGL.allocateIntBuffer(2); - floatBuffer = PGL.allocateFloatBuffer(2); - } - - viewport = PGL.allocateIntBuffer(4); - - polyAttribs = newAttributeMap(); - inGeo = newInGeometry(this, polyAttribs, IMMEDIATE); - tessGeo = newTessGeometry(this, polyAttribs, IMMEDIATE); - texCache = newTexCache(this); - - projection = new PMatrix3D(); - camera = new PMatrix3D(); - cameraInv = new PMatrix3D(); - modelview = new PMatrix3D(); - modelviewInv = new PMatrix3D(); - projmodelview = new PMatrix3D(); - - lightType = new int[PGL.MAX_LIGHTS]; - lightPosition = new float[4 * PGL.MAX_LIGHTS]; - lightNormal = new float[3 * PGL.MAX_LIGHTS]; - lightAmbient = new float[3 * PGL.MAX_LIGHTS]; - lightDiffuse = new float[3 * PGL.MAX_LIGHTS]; - lightSpecular = new float[3 * PGL.MAX_LIGHTS]; - lightFalloffCoefficients = new float[3 * PGL.MAX_LIGHTS]; - lightSpotParameters = new float[2 * PGL.MAX_LIGHTS]; - currentLightSpecular = new float[3]; - - initialized = false; - } - - - @Override - public void setParent(PApplet parent) { - super.setParent(parent); - if (pgl != null) { - pgl.sketch = parent; - } - } - - - @Override - public void setPrimary(boolean primary) { - super.setPrimary(primary); - pgl.setPrimary(primary); - format = ARGB; - if (primary) { - fbStack = new FrameBuffer[FB_STACK_DEPTH]; - fontMap = new WeakHashMap(); - tessellator = new Tessellator(); - } else { - tessellator = getPrimaryPG().tessellator; - } - } - - - //public void setPath(String path) // PGraphics - - - //public void setAntiAlias(int samples) // PGraphics - - - @Override - public void surfaceChanged() { - changed = true; - } - - - @Override - public void reset() { - pgl.resetFBOLayer(); - restartPGL(); - } - - - @Override - public void setSize(int iwidth, int iheight) { - sized = iwidth != width || iheight != height; - super.setSize(iwidth, iheight); - - updatePixelSize(); - - // init perspective projection based on new dimensions - defCameraFOV = 60 * DEG_TO_RAD; // at least for now - defCameraX = width / 2.0f; - defCameraY = height / 2.0f; - defCameraZ = defCameraY / ((float) Math.tan(defCameraFOV / 2.0f)); - defCameraNear = defCameraZ / 10.0f; - defCameraFar = defCameraZ * 10.0f; - defCameraAspect = (float) width / (float) height; - - cameraFOV = defCameraFOV; - cameraX = defCameraX; - cameraY = defCameraY; - cameraZ = defCameraZ; - cameraNear = defCameraNear; - cameraFar = defCameraFar; - cameraAspect = defCameraAspect; - } - - - @Override - public void dispose() { // PGraphics - if (asyncPixelReader != null) { - asyncPixelReader.dispose(); - asyncPixelReader = null; - } - - if (!primaryGraphics) { - deleteSurfaceTextures(); - FrameBuffer ofb = offscreenFramebuffer; - FrameBuffer mfb = multisampleFramebuffer; - if (ofb != null) { - ofb.dispose(); - } - if (mfb != null) { - mfb.dispose(); - } - } - - pgl.dispose(); - - super.dispose(); - } - - - protected void setFlushMode(int mode) { - flushMode = mode; - } - - - protected void updatePixelSize() { - float f = pgl.getPixelScale(); - pixelWidth = (int)(width * f); - pixelHeight = (int)(height * f); - } - - - ////////////////////////////////////////////////////////////// - - // PLATFORM-SPECIFIC CODE (Java, Android, etc.). Needs to be manually edited. - - - // Factory method - protected PGL createPGL(PGraphicsOpenGL pg) { // ignore -// return new PJOGL(pg); - return new PGLES(pg); - } - - - /* - @Override - // Java only - public PSurface createSurface() { // ignore - return surface = new PSurfaceJOGL(this); - } -*/ - - @Override - // Android only - public PSurface createSurface(AppComponent component, SurfaceHolder holder, boolean reset) { // ignore - if (reset) pgl.resetFBOLayer(); - return new PSurfaceGLES(this, component, holder); - } - - - @Override - // Android only - public void setFrameRate(float frameRate) { - pgl.setFrameRate(frameRate); - } - - - @Override - protected boolean isLooping() { // ignore - return super.isLooping(); - } - - - public boolean saveImpl(String filename) { - return super.save(filename); // ASYNC save frame using PBOs not yet available on Android - - /* - if (getHint(DISABLE_ASYNC_SAVEFRAME)) { - // Act as an opaque surface for the purposes of saving. - if (primaryGraphics) { - int prevFormat = format; - format = RGB; - boolean result = super.save(filename); - format = prevFormat; - return result; - } - - return super.save(filename); - } - - if (asyncImageSaver == null) { - asyncImageSaver = new AsyncImageSaver(); - } - - if (!asyncPixelReaderInitialized) { - // First call! Get this guy initialized - if (pgl.hasPBOs() && pgl.hasSynchronization()) { - asyncPixelReader = new AsyncPixelReader(); - } - asyncPixelReaderInitialized = true; - } - - if (asyncPixelReader != null && !loaded) { - boolean needEndDraw = false; - if (!drawing) { - beginDraw(); - needEndDraw = true; - } - flush(); - updatePixelSize(); - - // get the whole async package - asyncPixelReader.readAndSaveAsync(filename); - - if (needEndDraw) endDraw(); - } else { - // async transfer is not supported or - // pixels are already in memory, just do async save - if (!loaded) loadPixels(); - int format = primaryGraphics ? RGB : ARGB; - PImage target = asyncImageSaver.getAvailableTarget(pixelWidth, pixelHeight, - format); - if (target == null) return false; - int count = PApplet.min(pixels.length, target.pixels.length); - System.arraycopy(pixels, 0, target.pixels, 0, count); - asyncImageSaver.saveTargetAsync(this, target, filename); - } - - return true; - */ - } - - - ////////////////////////////////////////////////////////////// - - // EYE/OBJECT MATRICES - - - @Override - public PMatrix3D getEyeMatrix() { - return getEyeMatrix(null); - } - - - @Override - public PMatrix3D getEyeMatrix(PMatrix3D target) { - if (target == null) { - target = new PMatrix3D(); - } - float sign = cameraUp ? +1 : -1; - target.set(rightX, sign * upX, forwardX, cameraX, - rightY, sign * upY, forwardY, cameraY, - rightZ, sign * upZ, forwardZ, cameraZ, - 0, 0, 0, 1); - return target; - } - - - @Override - public PMatrix3D getObjectMatrix() { - PMatrix3D mat = new PMatrix3D(); - mat.set(modelviewInv); - mat.apply(camera); - return mat; - } - - - @Override - public PMatrix3D getObjectMatrix(PMatrix3D target) { - if (target == null) { - target = new PMatrix3D(); - } - target.set(modelviewInv); - target.apply(camera); - return target; - } - - - @Override - public void eye() { - eyeMatrix = getEyeMatrix(eyeMatrix); - - // Erasing any previous transformation in modelview - modelview.set(camera); - modelview.apply(eyeMatrix); - - // The 3x3 block of eyeMatrix is orthogonal, so taking the transpose inverts it... - eyeMatrix.transpose(); - // ...and then invert the translation separately: - eyeMatrix.m03 = -cameraX; - eyeMatrix.m13 = -cameraY; - eyeMatrix.m23 = -cameraZ; - eyeMatrix.m30 = 0; - eyeMatrix.m31 = 0; - eyeMatrix.m32 = 0; - - // Applying the inverse of the previous transformations in the opposite order - // to compute the modelview inverse - modelviewInv.set(eyeMatrix); - modelviewInv.preApply(cameraInv); - - updateProjmodelview(); - } - - - ////////////////////////////////////////////////////////////// - - // RAY CASTING - - @Override - public PVector[] getRayFromScreen(float screenX, float screenY, PVector[] ray) { - if (ray == null || ray.length < 2) { - ray = new PVector[2]; - ray[0] = new PVector(); - ray[1] = new PVector(); - } - getRayFromScreen(screenX, screenY, ray[0], ray[1]); - return ray; - } - - - @Override - public void getRayFromScreen(float screenX, float screenY, PVector origin, PVector direction) { - eyeMatrix = getEyeMatrix(eyeMatrix); - - // Transforming screen coordinates to world coordinates - screen.x = screenX; - screen.y = screenY; - screen.z = 0; - eyeMatrix.mult(screen, origin); - - // The direction of the ray is simply extracted from the third column of the eye matrix (the - // forward vector). - direction.set(eyeMatrix.m02, eyeMatrix.m12, eyeMatrix.m22); - } - - - @Override - public boolean intersectsSphere(float r, float screenX, float screenY) { - ray = getRayFromScreen(screenX, screenY, ray); - return intersectsSphere(r, ray[0], ray[1]); - } - - - @Override - public boolean intersectsSphere(float r, PVector origin, PVector direction) { - objMatrix = getObjectMatrix(objMatrix); - objMatrix.mult(origin, origInObjCoord); - PVector.add(origin, direction, hit); - objMatrix.mult(hit, hitInObjCoord); - PVector.sub(hitInObjCoord, origInObjCoord, dirInObjCoord); - - return rayIntersectsSphere(origInObjCoord, dirInObjCoord, r); - } - - - // Ray-sphere intersecton algorithm as described in: - // http://paulbourke.net/geometry/circlesphere/ - private boolean rayIntersectsSphere(PVector orig, PVector dir, float r) { - float d = orig.mag(); - - // The eye is inside the sphere - if (d <= r) return true; - - float p = PVector.dot(orig, dir); - - // Check if sphere is in front of ray - if (p > 0) return false; - - // Check intersection of ray with sphere - float b = 2 * p; - float c = d * d - r * r; - float det = b * b - 4 * c; - return det >= 0; - } - - - @Override - public boolean intersectsBox(float size, float screenX, float screenY) { - ray = getRayFromScreen(screenX, screenY, ray); - return intersectsBox(size, size, size, ray[0], ray[1]); - } - - - @Override - public boolean intersectsBox(float w, float h, float d, float screenX, float screenY) { - ray = getRayFromScreen(screenX, screenY, ray); - return intersectsBox(w, h, d, ray[0], ray[1]); - } - - - @Override - public boolean intersectsBox(float size, PVector origin, PVector direction) { - return intersectsBox(size, size, size, origin, direction); - } - - - @Override - public boolean intersectsBox(float w, float h, float d, PVector origin, PVector direction) { - objMatrix = getObjectMatrix(objMatrix); - objMatrix.mult(origin, origInObjCoord); - PVector.add(origin, direction, hit); - objMatrix.mult(hit, hitInObjCoord); - PVector.sub(hitInObjCoord, origInObjCoord, dirInObjCoord); - - return lineIntersectsAABB(origInObjCoord, dirInObjCoord, w, h, d); - } - - - // Line intersection with an axis-aligned bounding box (AABB), calculated using the algorithm - // from Amy William et al: http:// dl.acm.org/citation.cfm?id=1198748 - private boolean lineIntersectsAABB(PVector orig, PVector dir, float w, float h, float d) { - float minx = -w/2; - float miny = -h/2; - float minz = -d/2; - - float maxx = +w/2; - float maxy = +h/2; - float maxz = +d/2; - - float idx = 1/dir.x; - float idy = 1/dir.y; - float idz = 1/dir.z; - - boolean sdx = idx < 0; - boolean sdy = idy < 0; - boolean sdz = idz < 0; - - float bbx = sdx ? maxx : minx; - float txmin = (bbx - orig.x) * idx; - bbx = sdx ? minx : maxx; - float txmax = (bbx - orig.x) * idx; - float bby = sdy ? maxy : miny; - float tymin = (bby - orig.y) * idy; - bby = sdy ? miny : maxy; - float tymax = (bby - orig.y) * idy; - - if ((txmin > tymax) || (tymin > txmax)) { - return false; - } - if (tymin > txmin) { - txmin = tymin; - } - if (tymax < txmax) { - txmax = tymax; - } - - float bbz = sdz ? maxz : minz; - float tzmin = (bbz - orig.z) * idz; - bbz = sdz ? minz : maxz; - float tzmax = (bbz - orig.z) * idz; - - if ((txmin > tzmax) || (tzmin > txmax)) { - return false; - } - if (tzmin > txmin) { - txmin = tzmin; - } - if (tzmax < txmax) { - txmax = tzmax; - } - - if ((txmin < defCameraFar) && (txmax > 0)) { - // The intersection coordinates: - // x = orig.x + txmin * dir.x; - // y = orig.y + txmin * dir.y; - // z = orig.z + txmin * dir.z; - return true; - } - - return false; - } - - - @Override - public PVector intersectsPlane(float screenX, float screenY) { - ray = getRayFromScreen(screenX, screenY, ray); - return intersectsPlane(ray[0], ray[1]); - } - - - @Override - public PVector intersectsPlane(PVector origin, PVector direction) { - modelview.mult(origin, origInWorldCoord); - modelview.mult(direction, dirInWorldCoord); - dirInWorldCoord.normalize(); - - // Plane representation - PVector point = new PVector(0, 0, 0); - PVector normal = new PVector(0, 0, 1); - - // Ray-plane intersection algorithm - float d = PApplet.abs(PVector.dot(normal, dirInWorldCoord)); - if (d == 0) return null; - - PVector w = PVector.sub(point, origInWorldCoord); - float k = PApplet.abs(PVector.dot(normal, w)/d); - PVector p = PVector.add(origInWorldCoord, dirInWorldCoord).setMag(k); - - return p; - } - - - ////////////////////////////////////////////////////////////// - - // IMAGE METADATA FOR THIS RENDERER - - - @Override - public void setCache(PImage image, Object storage) { - if (image instanceof PGraphicsOpenGL) { - // Prevent strong reference to the key from the value by wrapping - // the Texture into WeakReference (proposed solution by WeakHashMap docs) - getPrimaryPG().cacheMap.put(image, new WeakReference<>(storage)); - return; - } - getPrimaryPG().cacheMap.put(image, storage); - } - - - @Override - @SuppressWarnings("rawtypes") - public Object getCache(PImage image) { - Object storage = getPrimaryPG().cacheMap.get(image); - if (storage != null && storage.getClass() == WeakReference.class) { - // Unwrap the value, use getClass() for fast check - return ((WeakReference) storage).get(); - } - return storage; - } - - - @Override - public void removeCache(PImage image) { - getPrimaryPG().cacheMap.remove(image); - } - - - ////////////////////////////////////////////////////////////// - - - protected void setFontTexture(PFont font, FontTexture fontTexture) { - getPrimaryPG().fontMap.put(font, fontTexture); - } - - - protected FontTexture getFontTexture(PFont font) { - return getPrimaryPG().fontMap.get(font); - } - - - protected void removeFontTexture(PFont font) { - getPrimaryPG().fontMap.remove(font); - } - - - ////////////////////////////////////////////////////////////// - - - protected static class GLResourceTexture extends Disposable { - int glName; - - private PGL pgl; - private int context; - - public GLResourceTexture(Texture tex) { - super(tex); - - - pgl = tex.pg.getPrimaryPGL(); - pgl.genTextures(1, intBuffer); - tex.glName = intBuffer.get(0); - - this.glName = tex.glName; - this.context = tex.context; - } - - @Override - public void disposeNative() { - if (pgl != null) { - if (glName != 0) { - intBuffer.put(0, glName); - pgl.deleteTextures(1, intBuffer); - glName = 0; - } - pgl = null; - } - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof GLResourceTexture)) { - return false; - } - GLResourceTexture other = (GLResourceTexture)obj; - return other.glName == glName && - other.context == context; - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + glName; - result = 31 * result + context; - return result; - } - } - - - protected static class GLResourceVertexBuffer extends Disposable { - int glId; - - private PGL pgl; - private int context; - - public GLResourceVertexBuffer(VertexBuffer vbo) { - super(vbo); - - pgl = vbo.pgl.graphics.getPrimaryPGL(); - pgl.genBuffers(1, intBuffer); - vbo.glId = intBuffer.get(0); - - this.glId = vbo.glId; - this.context = vbo.context; - } - - @Override - public void disposeNative() { - if (pgl != null) { - if (glId != 0) { - intBuffer.put(0, glId); - pgl.deleteBuffers(1, intBuffer); - glId = 0; - } - pgl = null; - } - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof GLResourceVertexBuffer)) { - return false; - } - GLResourceVertexBuffer other = (GLResourceVertexBuffer)obj; - return other.glId == glId && - other.context == context; - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + glId; - result = 31 * result + context; - return result; - } - } - - - protected static class GLResourceShader extends Disposable { - int glProgram; - int glVertex; - int glFragment; - - private PGL pgl; - private int context; - - public GLResourceShader(PShader sh) { - super(sh); - - this.pgl = sh.pgl.graphics.getPrimaryPGL(); - sh.glProgram = pgl.createProgram(); - sh.glVertex = pgl.createShader(PGL.VERTEX_SHADER); - sh.glFragment = pgl.createShader(PGL.FRAGMENT_SHADER); - - this.glProgram = sh.glProgram; - this.glVertex = sh.glVertex; - this.glFragment = sh.glFragment; - - this.context = sh.context; - } - - @Override - public void disposeNative() { - if (pgl != null) { - if (glFragment != 0) { - pgl.deleteShader(glFragment); - glFragment = 0; - } - if (glVertex != 0) { - pgl.deleteShader(glVertex); - glVertex = 0; - } - if (glProgram != 0) { - pgl.deleteProgram(glProgram); - glProgram = 0; - } - pgl = null; - } - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof GLResourceShader)) { - return false; - } - GLResourceShader other = (GLResourceShader)obj; - return other.glProgram == glProgram && - other.glVertex == glVertex && - other.glFragment == glFragment && - other.context == context; - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + glProgram; - result = 31 * result + glVertex; - result = 31 * result + glFragment; - result = 31 * result + context; - return result; - } - } - - - protected static class GLResourceFrameBuffer extends Disposable { - int glFbo; - int glDepth; - int glStencil; - int glDepthStencil; - int glMultisample; - - private PGL pgl; - private int context; - - public GLResourceFrameBuffer(FrameBuffer fb) { - super(fb); - - pgl = fb.pg.getPrimaryPGL(); - if (!fb.screenFb) { - pgl.genFramebuffers(1, intBuffer); - fb.glFbo = intBuffer.get(0); - - if (fb.multisample) { - pgl.genRenderbuffers(1, intBuffer); - fb.glMultisample = intBuffer.get(0); - } - - if (fb.packedDepthStencil) { - pgl.genRenderbuffers(1, intBuffer); - fb.glDepthStencil = intBuffer.get(0); - } else { - if (0 < fb.depthBits) { - pgl.genRenderbuffers(1, intBuffer); - fb.glDepth = intBuffer.get(0); - } - if (0 < fb.stencilBits) { - pgl.genRenderbuffers(1, intBuffer); - fb.glStencil = intBuffer.get(0); - } - } - - this.glFbo = fb.glFbo; - this.glDepth = fb.glDepth; - this.glStencil = fb.glStencil; - this.glDepthStencil = fb.glDepthStencil; - this.glMultisample = fb.glMultisample; - } - - this.context = fb.context; - } - - @Override - public void disposeNative() { - if (pgl != null) { - if (glFbo != 0) { - intBuffer.put(0, glFbo); - pgl.deleteFramebuffers(1, intBuffer); - glFbo = 0; - } - if (glDepth != 0) { - intBuffer.put(0, glDepth); - pgl.deleteRenderbuffers(1, intBuffer); - glDepth = 0; - } - if (glStencil != 0) { - intBuffer.put(0, glStencil); - pgl.deleteRenderbuffers(1, intBuffer); - glStencil = 0; - } - if (glDepthStencil != 0) { - intBuffer.put(0, glDepthStencil); - pgl.deleteRenderbuffers(1, intBuffer); - glDepthStencil = 0; - } - if (glMultisample != 0) { - intBuffer.put(0, glMultisample); - pgl.deleteRenderbuffers(1, intBuffer); - glMultisample = 0; - } - pgl = null; - } - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof GLResourceFrameBuffer)) { - return false; - } - GLResourceFrameBuffer other = (GLResourceFrameBuffer)obj; - return other.glFbo == glFbo && - other.glDepth == glDepth && - other.glStencil == glStencil && - other.glDepthStencil == glDepthStencil && - other.glMultisample == glMultisample && - other.context == context; - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + glFbo; - result = 31 * result + glDepth; - result = 31 * result + glStencil; - result = 31 * result + glDepthStencil; - result = 31 * result + glMultisample; - result = 31 * result + context; - return result; - } - } - - - ////////////////////////////////////////////////////////////// - - // FRAMEBUFFERS - - - protected void pushFramebuffer() { - PGraphicsOpenGL ppg = getPrimaryPG(); - if (ppg.fbStackDepth == FB_STACK_DEPTH) { - throw new RuntimeException("Too many pushFramebuffer calls"); - } - ppg.fbStack[ppg.fbStackDepth] = ppg.currentFramebuffer; - ppg.fbStackDepth++; - } - - - protected void setFramebuffer(FrameBuffer fbo) { - PGraphicsOpenGL ppg = getPrimaryPG(); - if (ppg.currentFramebuffer != fbo) { - ppg.currentFramebuffer = fbo; - if (ppg.currentFramebuffer != null) ppg.currentFramebuffer.bind(); - } - } - - - protected void popFramebuffer() { - PGraphicsOpenGL ppg = getPrimaryPG(); - if (ppg.fbStackDepth == 0) { - throw new RuntimeException("popFramebuffer call is unbalanced."); - } - ppg.fbStackDepth--; - FrameBuffer fbo = ppg.fbStack[ppg.fbStackDepth]; - if (ppg.currentFramebuffer != fbo) { - ppg.currentFramebuffer.finish(); - ppg.currentFramebuffer = fbo; - if (ppg.currentFramebuffer != null) ppg.currentFramebuffer.bind(); - } - } - - - protected FrameBuffer getCurrentFB() { - return getPrimaryPG().currentFramebuffer; - } - - - ////////////////////////////////////////////////////////////// - - // FRAME RENDERING - - - protected void createPolyBuffers() { - if (!polyBuffersCreated || polyBuffersContextIsOutdated()) { - polyBuffersContext = pgl.getCurrentContext(); - - bufPolyVertex = new VertexBuffer(this, PGL.ARRAY_BUFFER, 3, PGL.SIZEOF_FLOAT); - bufPolyColor = new VertexBuffer(this, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - bufPolyNormal = new VertexBuffer(this, PGL.ARRAY_BUFFER, 3, PGL.SIZEOF_FLOAT); - bufPolyTexcoord = new VertexBuffer(this, PGL.ARRAY_BUFFER, 2, PGL.SIZEOF_FLOAT); - bufPolyAmbient = new VertexBuffer(this, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - bufPolySpecular = new VertexBuffer(this, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - bufPolyEmissive = new VertexBuffer(this, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - bufPolyShininess = new VertexBuffer(this, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_FLOAT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - bufPolyIndex = new VertexBuffer(this, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); - - polyBuffersCreated = true; - } - - boolean created = false; - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (!attrib.bufferCreated() || polyBuffersContextIsOutdated()) { - attrib.createBuffer(pgl); - created = true; - } - } - if (created) pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void updatePolyBuffers(boolean lit, boolean tex, - boolean needNormals, boolean needTexCoords) { - createPolyBuffers(); - - int size = tessGeo.polyVertexCount; - int sizef = size * PGL.SIZEOF_FLOAT; - int sizei = size * PGL.SIZEOF_INT; - - tessGeo.updatePolyVerticesBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyVertex.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, - tessGeo.polyVerticesBuffer, PGL.STATIC_DRAW); - - tessGeo.updatePolyColorsBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyColor.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.polyColorsBuffer, PGL.STATIC_DRAW); - - if (lit) { - tessGeo.updatePolyAmbientBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyAmbient.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.polyAmbientBuffer, PGL.STATIC_DRAW); - - tessGeo.updatePolySpecularBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolySpecular.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.polySpecularBuffer, PGL.STATIC_DRAW); - - tessGeo.updatePolyEmissiveBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyEmissive.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.polyEmissiveBuffer, PGL.STATIC_DRAW); - - tessGeo.updatePolyShininessBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyShininess.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizef, - tessGeo.polyShininessBuffer, PGL.STATIC_DRAW); - } - - if (lit || needNormals) { - tessGeo.updatePolyNormalsBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyNormal.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 3 * sizef, - tessGeo.polyNormalsBuffer, PGL.STATIC_DRAW); - } - - if (tex || needTexCoords) { - tessGeo.updatePolyTexCoordsBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyTexcoord.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 2 * sizef, - tessGeo.polyTexCoordsBuffer, PGL.STATIC_DRAW); - } - - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - tessGeo.updateAttribBuffer(name); - pgl.bindBuffer(PGL.ARRAY_BUFFER, attrib.buf.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, attrib.sizeInBytes(size), - tessGeo.polyAttribBuffers.get(name), PGL.STATIC_DRAW); - } - - tessGeo.updatePolyIndicesBuffer(); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, bufPolyIndex.glId); - pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, - tessGeo.polyIndexCount * PGL.SIZEOF_INDEX, tessGeo.polyIndicesBuffer, - PGL.STATIC_DRAW); - } - - - protected void unbindPolyBuffers() { - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); - } - - - protected boolean polyBuffersContextIsOutdated() { - return !pgl.contextIsCurrent(polyBuffersContext); - } - - - protected void createLineBuffers() { - if (!lineBuffersCreated || lineBufferContextIsOutdated()) { - lineBuffersContext = pgl.getCurrentContext(); - - bufLineVertex = new VertexBuffer(this, PGL.ARRAY_BUFFER, 3, PGL.SIZEOF_FLOAT); - bufLineColor = new VertexBuffer(this, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - bufLineAttrib = new VertexBuffer(this, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - bufLineIndex = new VertexBuffer(this, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); - - lineBuffersCreated = true; - } - } - - - protected void updateLineBuffers() { - createLineBuffers(); - - int size = tessGeo.lineVertexCount; - int sizef = size * PGL.SIZEOF_FLOAT; - int sizei = size * PGL.SIZEOF_INT; - - - - tessGeo.updateLineVerticesBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineVertex.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, tessGeo.lineVerticesBuffer, - PGL.STATIC_DRAW); - - tessGeo.updateLineColorsBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineColor.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.lineColorsBuffer, PGL.STATIC_DRAW); - - tessGeo.updateLineDirectionsBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineAttrib.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, - tessGeo.lineDirectionsBuffer, PGL.STATIC_DRAW); - - tessGeo.updateLineIndicesBuffer(); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, bufLineIndex.glId); - pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, - tessGeo.lineIndexCount * PGL.SIZEOF_INDEX, - tessGeo.lineIndicesBuffer, PGL.STATIC_DRAW); - } - - - protected void unbindLineBuffers() { - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); - } - - - protected boolean lineBufferContextIsOutdated() { - return !pgl.contextIsCurrent(lineBuffersContext); - } - - - protected void createPointBuffers() { - if (!pointBuffersCreated || pointBuffersContextIsOutdated()) { - pointBuffersContext = pgl.getCurrentContext(); - - bufPointVertex = new VertexBuffer(this, PGL.ARRAY_BUFFER, 3, PGL.SIZEOF_FLOAT); - bufPointColor = new VertexBuffer(this, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - bufPointAttrib = new VertexBuffer(this, PGL.ARRAY_BUFFER, 2, PGL.SIZEOF_FLOAT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - bufPointIndex = new VertexBuffer(this, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); - - pointBuffersCreated = true; - } - } - - - protected void updatePointBuffers() { - createPointBuffers(); - - int size = tessGeo.pointVertexCount; - int sizef = size * PGL.SIZEOF_FLOAT; - int sizei = size * PGL.SIZEOF_INT; - - tessGeo.updatePointVerticesBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointVertex.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, - tessGeo.pointVerticesBuffer, PGL.STATIC_DRAW); - - tessGeo.updatePointColorsBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointColor.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.pointColorsBuffer, PGL.STATIC_DRAW); - - tessGeo.updatePointOffsetsBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointAttrib.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 2 * sizef, - tessGeo.pointOffsetsBuffer, PGL.STATIC_DRAW); - - tessGeo.updatePointIndicesBuffer(); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, bufPointIndex.glId); - pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, - tessGeo.pointIndexCount * PGL.SIZEOF_INDEX, - tessGeo.pointIndicesBuffer, PGL.STATIC_DRAW); - } - - - protected void unbindPointBuffers() { - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); - } - - - protected boolean pointBuffersContextIsOutdated() { - return !pgl.contextIsCurrent(pointBuffersContext); - } - - - @Override - public void beginDraw() { - if (primaryGraphics) { - initPrimary(); - setCurrentPG(this); - } else { - pgl.getGL(getPrimaryPGL()); - getPrimaryPG().setCurrentPG(this); - } - -// if (!pgl.threadIsCurrent()) { -// PGraphics.showWarning(GL_THREAD_NOT_CURRENT); -// return; -// } - - // This has to go after the surface initialization, otherwise offscreen - // surfaces will have a null gl object. - report("top beginDraw()"); - - if (!checkGLThread()) { - return; - } - - if (drawing) { - return; - } - - if (!primaryGraphics && getPrimaryPG().texCache.containsTexture(this)) { - // This offscreen surface is being used as a texture earlier in draw, - // so we should update the rendering up to this point since it will be - // modified. - getPrimaryPG().flush(); - } - - if (!glParamsRead) { - getGLParameters(); - } - - setViewport(); - if (primaryGraphics) { - beginOnscreenDraw(); - } else { - beginOffscreenDraw(); - } - checkSettings(); - - drawing = true; - - report("bot beginDraw()"); - } - - - @Override - public void endDraw() { - report("top endDraw()"); - - if (!drawing) { - return; - } - - // Flushing any remaining geometry. - flush(); - - if (primaryGraphics) { - endOnscreenDraw(); - } else { - endOffscreenDraw(); - } - - if (primaryGraphics) { - setCurrentPG(null); - } else { - getPrimaryPG().setCurrentPG(); - } - drawing = false; - - report("bot endDraw()"); - } - - - protected PGraphicsOpenGL getPrimaryPG() { - if (primaryGraphics) { - return this; - } else { - return (PGraphicsOpenGL)parent.g; - } - } - - protected void setCurrentPG(PGraphicsOpenGL pg) { - currentPG = pg; - } - - protected void setCurrentPG() { - currentPG = this; - } - - protected PGraphicsOpenGL getCurrentPG() { - return currentPG; - } - - protected PGL getPrimaryPGL() { - if (primaryGraphics) { - return pgl; - } else { - return ((PGraphicsOpenGL)parent.g).pgl; - } - } - - - @Override - public PGL beginPGL() { - flush(); - pgl.beginGL(); - return pgl; - } - - - @Override - public void endPGL() { - pgl.endGL(); - restoreGL(); - } - - - public void updateProjmodelview() { - projmodelview.set(projection); - projmodelview.apply(modelview); - } - - - protected void restartPGL() { - initialized = false; - } - - - protected void restoreGL() { - blendMode(blendMode); // this should be set by reapplySettings... - - if (hints[DISABLE_DEPTH_TEST]) { - pgl.disable(PGL.DEPTH_TEST); - } else { - pgl.enable(PGL.DEPTH_TEST); - } - pgl.depthFunc(PGL.LEQUAL); - - if (smooth < 1) { - pgl.disable(PGL.MULTISAMPLE); - } else { - pgl.enable(PGL.MULTISAMPLE); - pgl.disable(PGL.POLYGON_SMOOTH); - } - - pgl.viewport(viewport.get(0), viewport.get(1), - viewport.get(2), viewport.get(3)); - if (clip) { - pgl.enable(PGL.SCISSOR_TEST); - pgl.scissor(clipRect[0], clipRect[1], clipRect[2], clipRect[3]); - } else { - pgl.disable(PGL.SCISSOR_TEST); - } - - pgl.frontFace(cameraUp ? PGL.CCW : PGL.CW); - pgl.disable(PGL.CULL_FACE); - - pgl.activeTexture(PGL.TEXTURE0); - - if (hints[DISABLE_DEPTH_MASK]) { - pgl.depthMask(false); - } else { - pgl.depthMask(true); - } - - FrameBuffer fb = getCurrentFB(); - if (fb != null) { - fb.bind(); - if (drawBufferSupported) pgl.drawBuffer(fb.getDefaultDrawBuffer()); - } - } - - protected void beginBindFramebuffer(int target, int framebuffer) { - // Actually, nothing to do here. - } - - protected void endBindFramebuffer(int target, int framebuffer) { - FrameBuffer fb = getCurrentFB(); - if (framebuffer == 0 && fb != null && fb.glFbo != 0) { - // The user is setting the framebuffer to 0 (screen buffer), but the - // renderer is drawing into an offscreen buffer. - fb.bind(); - } - } - - protected void beginReadPixels() { - beginPixelsOp(OP_READ); - } - - protected void endReadPixels() { - endPixelsOp(); - } - - protected void beginPixelsOp(int op) { - FrameBuffer pixfb = null; - FrameBuffer currfb = getCurrentFB(); - if (primaryGraphics) { - FrameBuffer rfb = readFramebuffer; - FrameBuffer dfb = drawFramebuffer; - if ((currfb == rfb) || (currfb == dfb)) { - // Not user-provided FB, need to check if the correct FB is current. - if (op == OP_READ) { - if (pgl.isFBOBacked() && pgl.isMultisampled()) { - // Making sure the back texture is up-to-date... - pgl.syncBackTexture(); - // ...because the read framebuffer uses it as the color buffer (the - // draw framebuffer is MSAA so it cannot be read from it). - pixfb = rfb; - } else { - pixfb = dfb; - } - } else if (op == OP_WRITE) { - // We can write to the draw framebuffer irrespective of whether is - // FBO-baked or multisampled. - pixfb = dfb; - } - } - } else { - FrameBuffer ofb = offscreenFramebuffer; - FrameBuffer mfb = multisampleFramebuffer; - if ((currfb == ofb) || (currfb == mfb)) { - // Not user-provided FB, need to check if the correct FB is current. - if (op == OP_READ) { - if (offscreenMultisample) { - // Making sure the offscreen FBO is up-to-date - int mask = PGL.COLOR_BUFFER_BIT; - if (hints[ENABLE_BUFFER_READING]) { - mask |= PGL.DEPTH_BUFFER_BIT | PGL.STENCIL_BUFFER_BIT; - } - if (ofb != null && mfb != null) { - mfb.copy(ofb, mask); - } - } - // We always read the screen pixels from the color FBO. - pixfb = ofb; - } else if (op == OP_WRITE) { - // We can write directly to the color FBO, or to the multisample FBO - // if multisampling is enabled. - pixfb = offscreenMultisample ? mfb : ofb; - } - } - } - - // Set the framebuffer where the pixel operation shall be carried out. - if (pixfb != null && pixfb != getCurrentFB()) { - pushFramebuffer(); - setFramebuffer(pixfb); - pixOpChangedFB = true; - } - - // We read from/write to the draw buffer. - if (op == OP_READ) { - if (readBufferSupported) pgl.readBuffer(getCurrentFB().getDefaultDrawBuffer()); - } else if (op == OP_WRITE) { - if (drawBufferSupported) pgl.drawBuffer(getCurrentFB().getDefaultDrawBuffer()); - } - - pixelsOp = op; - } - - - protected void endPixelsOp() { - // Restoring current framebuffer prior to the pixel operation - if (pixOpChangedFB) { - popFramebuffer(); - pixOpChangedFB = false; - } - - // Restoring default read/draw buffer configuration. - if (readBufferSupported) pgl.readBuffer(getCurrentFB().getDefaultReadBuffer()); - if (drawBufferSupported) pgl.drawBuffer(getCurrentFB().getDefaultDrawBuffer()); - - pixelsOp = OP_NONE; - } - - - protected void updateGLProjection() { - if (glProjection == null) { - glProjection = new float[16]; - } - - glProjection[0] = projection.m00; - glProjection[1] = projection.m10; - glProjection[2] = projection.m20; - glProjection[3] = projection.m30; - - glProjection[4] = projection.m01; - glProjection[5] = projection.m11; - glProjection[6] = projection.m21; - glProjection[7] = projection.m31; - - glProjection[8] = projection.m02; - glProjection[9] = projection.m12; - glProjection[10] = projection.m22; - glProjection[11] = projection.m32; - - glProjection[12] = projection.m03; - glProjection[13] = projection.m13; - glProjection[14] = projection.m23; - glProjection[15] = projection.m33; - } - - - protected void updateGLModelview() { - if (glModelview == null) { - glModelview = new float[16]; - } - - glModelview[0] = modelview.m00; - glModelview[1] = modelview.m10; - glModelview[2] = modelview.m20; - glModelview[3] = modelview.m30; - - glModelview[4] = modelview.m01; - glModelview[5] = modelview.m11; - glModelview[6] = modelview.m21; - glModelview[7] = modelview.m31; - - glModelview[8] = modelview.m02; - glModelview[9] = modelview.m12; - glModelview[10] = modelview.m22; - glModelview[11] = modelview.m32; - - glModelview[12] = modelview.m03; - glModelview[13] = modelview.m13; - glModelview[14] = modelview.m23; - glModelview[15] = modelview.m33; - } - - - protected void updateGLProjmodelview() { - if (glProjmodelview == null) { - glProjmodelview = new float[16]; - } - - glProjmodelview[0] = projmodelview.m00; - glProjmodelview[1] = projmodelview.m10; - glProjmodelview[2] = projmodelview.m20; - glProjmodelview[3] = projmodelview.m30; - - glProjmodelview[4] = projmodelview.m01; - glProjmodelview[5] = projmodelview.m11; - glProjmodelview[6] = projmodelview.m21; - glProjmodelview[7] = projmodelview.m31; - - glProjmodelview[8] = projmodelview.m02; - glProjmodelview[9] = projmodelview.m12; - glProjmodelview[10] = projmodelview.m22; - glProjmodelview[11] = projmodelview.m32; - - glProjmodelview[12] = projmodelview.m03; - glProjmodelview[13] = projmodelview.m13; - glProjmodelview[14] = projmodelview.m23; - glProjmodelview[15] = projmodelview.m33; - } - - - protected void updateGLNormal() { - if (glNormal == null) { - glNormal = new float[9]; - } - - // The normal matrix is the transpose of the inverse of the - // modelview (remember that gl matrices are column-major, - // meaning that elements 0, 1, 2 are the first column, - // 3, 4, 5 the second, etc.): - glNormal[0] = modelviewInv.m00; - glNormal[1] = modelviewInv.m01; - glNormal[2] = modelviewInv.m02; - - glNormal[3] = modelviewInv.m10; - glNormal[4] = modelviewInv.m11; - glNormal[5] = modelviewInv.m12; - - glNormal[6] = modelviewInv.m20; - glNormal[7] = modelviewInv.m21; - glNormal[8] = modelviewInv.m22; - } - - - ////////////////////////////////////////////////////////////// - - // SETTINGS - - // protected void checkSettings() - - - @Override - protected void defaultSettings() { - super.defaultSettings(); - - manipulatingCamera = false; - - // easiest for beginners - textureMode(IMAGE); - - // Default material properties - ambient(255); - specular(125); - emissive(0); - shininess(1); - - // To indicate that the user hasn't set ambient - setAmbient = false; - } - - - // reapplySettings - - ////////////////////////////////////////////////////////////// - - // HINTS - - - @Override - public void hint(int which) { - boolean oldValue = hints[PApplet.abs(which)]; - super.hint(which); - boolean newValue = hints[PApplet.abs(which)]; - - if (oldValue == newValue) { - return; - } - - if (which == DISABLE_DEPTH_TEST) { - flush(); - pgl.disable(PGL.DEPTH_TEST); - } else if (which == ENABLE_DEPTH_TEST) { - flush(); - pgl.enable(PGL.DEPTH_TEST); - } else if (which == DISABLE_DEPTH_MASK) { - flush(); - pgl.depthMask(false); - } else if (which == ENABLE_DEPTH_MASK) { - flush(); - pgl.depthMask(true); - } else if (which == ENABLE_OPTIMIZED_STROKE) { - flush(); - setFlushMode(FLUSH_WHEN_FULL); - } else if (which == DISABLE_OPTIMIZED_STROKE) { - if (is2D()) { - PGraphics.showWarning("Optimized strokes can only be disabled in 3D"); - } else { - flush(); - setFlushMode(FLUSH_CONTINUOUSLY); - } - } else if (which == DISABLE_STROKE_PERSPECTIVE) { - if (0 < tessGeo.lineVertexCount && 0 < tessGeo.lineIndexCount) { - // We flush the geometry using the previous line setting. - flush(); - } - } else if (which == ENABLE_STROKE_PERSPECTIVE) { - if (0 < tessGeo.lineVertexCount && 0 < tessGeo.lineIndexCount) { - // We flush the geometry using the previous line setting. - flush(); - } - } else if (which == ENABLE_DEPTH_SORT) { - if (is3D()) { - flush(); - if (sorter == null) sorter = new DepthSorter(this); - isDepthSortingEnabled = true; - } else { - PGraphics.showWarning("Depth sorting can only be enabled in 3D"); - } - } else if (which == DISABLE_DEPTH_SORT) { - if (is3D()) { - flush(); - isDepthSortingEnabled = false; - } - } else if (which == ENABLE_BUFFER_READING) { - restartPGL(); - } else if (which == DISABLE_BUFFER_READING) { - restartPGL(); - } - } - - - protected boolean getHint(int which) { - if (which > 0) { - return hints[which]; - } else { - return !hints[-which]; - } - } - - - ////////////////////////////////////////////////////////////// - - // CREATE SHAPE - - - @Override - protected PShape createShapeFamily(int type) { - PShape shape = new PShapeOpenGL(this, type); - if (is3D()) { - shape.set3D(true); - } - return shape; - } - - - @Override - protected PShape createShapePrimitive(int kind, float... p) { - PShape shape = new PShapeOpenGL(this, kind, p); - if (is3D()) { - shape.set3D(true); - } - return shape; - } - - - - ////////////////////////////////////////////////////////////// - - // VERTEX SHAPES - - - @Override - public void beginShape(int kind) { - shape = kind; - inGeo.clear(); - - curveVertexCount = 0; - breakShape = false; - defaultEdges = true; - - // The superclass method is called to avoid an early flush. - super.noTexture(); - - normalMode = NORMAL_MODE_AUTO; - } - - - @Override - public void endShape(int mode) { - tessellate(mode); - - if ((flushMode == FLUSH_CONTINUOUSLY) || - (flushMode == FLUSH_WHEN_FULL && tessGeo.isFull())) { - flush(); - } else { - // pixels array is not up-to-date anymore - loaded = false; - } - } - - - protected void endShape(int[] indices) { - if (shape != TRIANGLE && shape != TRIANGLES) { - throw new RuntimeException("Indices and edges can only be set for " + - "TRIANGLE shapes"); - } - - tessellate(indices); - - if (flushMode == FLUSH_CONTINUOUSLY || - (flushMode == FLUSH_WHEN_FULL && tessGeo.isFull())) { - flush(); - } else { - // pixels array is not up-to-date anymore - loaded = false; - } - } - - - @Override - public void textureWrap(int wrap) { - this.textureWrap = wrap; - } - - - public void textureSampling(int sampling) { - this.textureSampling = sampling; - } - - - @Override - public void beginContour() { - if (openContour) { - PGraphics.showWarning(ALREADY_BEGAN_CONTOUR_ERROR); - return; - } - openContour = true; - breakShape = true; - } - - - @Override - public void endContour() { - if (!openContour) { - PGraphics.showWarning(NO_BEGIN_CONTOUR_ERROR); - return; - } - openContour = false; - } - - - @Override - public void vertex(float x, float y) { - vertexImpl(x, y, 0, 0, 0); - if (textureImage != null) PGraphics.showWarning(MISSING_UV_TEXCOORDS_ERROR); - } - - - @Override - public void vertex(float x, float y, float u, float v) { - vertexImpl(x, y, 0, u, v); - } - - - @Override - public void vertex(float x, float y, float z) { - vertexImpl(x, y, z, 0, 0); - if (textureImage != null) PGraphics.showWarning(MISSING_UV_TEXCOORDS_ERROR); - } - - - @Override - public void vertex(float x, float y, float z, float u, float v) { - vertexImpl(x, y, z, u, v); - } - - - @Override - public void attribPosition(String name, float x, float y, float z) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.POSITION, - PGL.FLOAT, 3); - if (attrib != null) attrib.set(x, y, z); - } - - - @Override - public void attribNormal(String name, float nx, float ny, float nz) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.NORMAL, - PGL.FLOAT, 3); - if (attrib != null) attrib.set(nx, ny, nz); - } - - - @Override - public void attribColor(String name, int color) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.COLOR, PGL.INT, 1); - if (attrib != null) attrib.set(new int[] {color}); - } - - - @Override - public void attrib(String name, float... values) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.OTHER, - PGL.FLOAT, values.length); - if (attrib != null) attrib.set(values); - } - - - @Override - public void attrib(String name, int... values) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.OTHER, - PGL.INT, values.length); - if (attrib != null) attrib.set(values); - } - - - @Override - public void attrib(String name, boolean... values) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.OTHER, - PGL.BOOL, values.length); - if (attrib != null) attrib.set(values); - } - - - protected VertexAttribute attribImpl(String name, int kind, int type, int size) { - if (4 < size) { - PGraphics.showWarning("Vertex attributes cannot have more than 4 values"); - return null; - } - VertexAttribute attrib = polyAttribs.get(name); - if (attrib == null) { - attrib = new VertexAttribute(this, name, kind, type, size); - polyAttribs.put(name, attrib); - inGeo.initAttrib(attrib); - tessGeo.initAttrib(attrib); - } - if (attrib.kind != kind) { - PGraphics.showWarning("The attribute kind cannot be changed after creation"); - return null; - } - if (attrib.type != type) { - PGraphics.showWarning("The attribute type cannot be changed after creation"); - return null; - } - if (attrib.size != size) { - PGraphics.showWarning("New value for vertex attribute has wrong number of values"); - return null; - } - return attrib; - } - - - protected void vertexImpl(float x, float y, float z, float u, float v) { - boolean textured = textureImage != null; - int fcolor = 0x00; - if (fill || textured) { - if (!textured) { - fcolor = fillColor; - } else { - if (tint) { - fcolor = tintColor; - } else { - fcolor = 0xffFFFFFF; - } - } - } - - int scolor = 0x00; - float sweight = 0; - if (stroke) { - scolor = strokeColor; - sweight = strokeWeight; - } - - if (textured && textureMode == IMAGE) { - u /= textureImage.width; - v /= textureImage.height; - } - - inGeo.addVertex(x, y, z, - fcolor, - normalX, normalY, normalZ, - u, v, - scolor, sweight, - ambientColor, specularColor, emissiveColor, shininess, - VERTEX, vertexBreak()); - } - - - protected boolean vertexBreak() { - if (breakShape) { - breakShape = false; - return true; - } - return false; - } - - - @Override - protected void clipImpl(float x1, float y1, float x2, float y2) { - flush(); - pgl.enable(PGL.SCISSOR_TEST); - - float h = y2 - y1; - clipRect[0] = (int)x1; - clipRect[1] = (int)(height - y1 - h); - clipRect[2] = (int)(x2 - x1); - clipRect[3] = (int)h; - pgl.scissor(clipRect[0], clipRect[1], clipRect[2], clipRect[3]); - - clip = true; - } - - - @Override - public void noClip() { - if (clip) { - flush(); - pgl.disable(PGL.SCISSOR_TEST); - clip = false; - } - } - - - ////////////////////////////////////////////////////////////// - - // RENDERING - - // protected void render() - - // protected void sort() - - - protected void tessellate(int mode) { - tessellator.setInGeometry(inGeo); - tessellator.setTessGeometry(tessGeo); - tessellator.setFill(fill || textureImage != null); - tessellator.setTexCache(texCache, textureImage); - tessellator.setStroke(stroke); - tessellator.setStrokeColor(strokeColor); - tessellator.setStrokeWeight(strokeWeight); - tessellator.setStrokeCap(strokeCap); - tessellator.setStrokeJoin(strokeJoin); - tessellator.setRenderer(this); - tessellator.setTransform(modelview); - tessellator.set3D(is3D()); - - if (shape == POINTS) { - tessellator.tessellatePoints(); - } else if (shape == LINES) { - tessellator.tessellateLines(); - } else if (shape == LINE_STRIP) { - tessellator.tessellateLineStrip(); - } else if (shape == LINE_LOOP) { - tessellator.tessellateLineLoop(); - } else if (shape == TRIANGLE || shape == TRIANGLES) { - if (stroke && defaultEdges) inGeo.addTrianglesEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcTrianglesNormals(); - tessellator.tessellateTriangles(); - } else if (shape == TRIANGLE_FAN) { - if (stroke && defaultEdges) inGeo.addTriangleFanEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcTriangleFanNormals(); - tessellator.tessellateTriangleFan(); - } else if (shape == TRIANGLE_STRIP) { - if (stroke && defaultEdges) inGeo.addTriangleStripEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcTriangleStripNormals(); - tessellator.tessellateTriangleStrip(); - } else if (shape == QUAD || shape == QUADS) { - if (stroke && defaultEdges) inGeo.addQuadsEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcQuadsNormals(); - tessellator.tessellateQuads(); - } else if (shape == QUAD_STRIP) { - if (stroke && defaultEdges) inGeo.addQuadStripEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcQuadStripNormals(); - tessellator.tessellateQuadStrip(); - } else if (shape == POLYGON) { - tessellator.tessellatePolygon(true, mode == CLOSE, - normalMode == NORMAL_MODE_AUTO); - } - } - - - protected void tessellate(int[] indices) { - tessellator.setInGeometry(inGeo); - tessellator.setTessGeometry(tessGeo); - tessellator.setFill(fill || textureImage != null); - tessellator.setStroke(stroke); - tessellator.setStrokeColor(strokeColor); - tessellator.setStrokeWeight(strokeWeight); - tessellator.setStrokeCap(strokeCap); - tessellator.setStrokeJoin(strokeJoin); - tessellator.setTexCache(texCache, textureImage); - tessellator.setTransform(modelview); - tessellator.set3D(is3D()); - - if (stroke && defaultEdges) inGeo.addTrianglesEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcTrianglesNormals(); - tessellator.tessellateTriangles(indices); - } - - - @Override - public void flush() { - boolean hasPolys = 0 < tessGeo.polyVertexCount && - 0 < tessGeo.polyIndexCount; - boolean hasLines = 0 < tessGeo.lineVertexCount && - 0 < tessGeo.lineIndexCount; - boolean hasPoints = 0 < tessGeo.pointVertexCount && - 0 < tessGeo.pointIndexCount; - - boolean hasPixels = modified && pixels != null; - - if (hasPixels) { - // If the user has been manipulating individual pixels, - // the changes need to be copied to the screen before - // drawing any new geometry. - flushPixels(); - } - - if (hasPoints || hasLines || hasPolys) { - PMatrix3D modelview0 = null; - PMatrix3D modelviewInv0 = null; - if (flushMode == FLUSH_WHEN_FULL) { - // The modelview transformation has been applied already to the - // tessellated vertices, so we set the OpenGL modelview matrix as - // the identity to avoid applying the model transformations twice. - // We save the modelview objects and temporarily use the identity - // static matrix to avoid calling pushMatrix(), resetMatrix(), - // popMatrix(). - modelview0 = modelview; - modelviewInv0 = modelviewInv; - modelview = modelviewInv = identity; - projmodelview.set(projection); - } - - if (hasPolys && !isDepthSortingEnabled) { - flushPolys(); - if (raw != null) { - rawPolys(); - } - } - - if (is3D()) { - if (hasLines) { - flushLines(); - if (raw != null) { - rawLines(); - } - } - - if (hasPoints) { - flushPoints(); - if (raw != null) { - rawPoints(); - } - } - } - - if (hasPolys && isDepthSortingEnabled) { - // We flush after lines so they are visible - // under transparent polygons - flushSortedPolys(); - if (raw != null) { - rawSortedPolys(); - } - } - - if (flushMode == FLUSH_WHEN_FULL) { - modelview = modelview0; - modelviewInv = modelviewInv0; - updateProjmodelview(); - } - - loaded = false; - } - - tessGeo.clear(); - texCache.clear(); - } - - - protected void flushPixels() { - drawPixels(mx1, my1, mx2 - mx1, my2 - my1); - modified = false; - } - - - protected void flushPolys() { - boolean customShader = polyShader != null; - boolean needNormals = customShader ? polyShader.accessNormals() : false; - boolean needTexCoords = customShader ? polyShader.accessTexCoords() : false; - - updatePolyBuffers(lights, texCache.hasTextures, needNormals, needTexCoords); - - for (int i = 0; i < texCache.size; i++) { - Texture tex = texCache.getTexture(i); - - // If the renderer is 2D, then lights should always be false, - // so no need to worry about that. - PShader shader = getPolyShader(lights, tex != null); - shader.bind(); - - int first = texCache.firstCache[i]; - int last = texCache.lastCache[i]; - IndexCache cache = tessGeo.polyIndexCache; - - for (int n = first; n <= last; n++) { - int ioffset = n == first ? texCache.firstIndex[i] : cache.indexOffset[n]; - int icount = n == last ? texCache.lastIndex[i] - ioffset + 1 : - cache.indexOffset[n] + cache.indexCount[n] - ioffset; - int voffset = cache.vertexOffset[n]; - - shader.setVertexAttribute(bufPolyVertex.glId, 4, PGL.FLOAT, 0, - 4 * voffset * PGL.SIZEOF_FLOAT); - shader.setColorAttribute(bufPolyColor.glId, 4, PGL.UNSIGNED_BYTE, 0, - 4 * voffset * PGL.SIZEOF_BYTE); - - if (lights) { - shader.setNormalAttribute(bufPolyNormal.glId, 3, PGL.FLOAT, 0, - 3 * voffset * PGL.SIZEOF_FLOAT); - shader.setAmbientAttribute(bufPolyAmbient.glId, 4, PGL.UNSIGNED_BYTE, 0, - 4 * voffset * PGL.SIZEOF_BYTE); - shader.setSpecularAttribute(bufPolySpecular.glId, 4, PGL.UNSIGNED_BYTE, 0, - 4 * voffset * PGL.SIZEOF_BYTE); - shader.setEmissiveAttribute(bufPolyEmissive.glId, 4, PGL.UNSIGNED_BYTE, 0, - 4 * voffset * PGL.SIZEOF_BYTE); - shader.setShininessAttribute(bufPolyShininess.glId, 1, PGL.FLOAT, 0, - voffset * PGL.SIZEOF_FLOAT); - } - - if (lights || needNormals) { - shader.setNormalAttribute(bufPolyNormal.glId, 3, PGL.FLOAT, 0, - 3 * voffset * PGL.SIZEOF_FLOAT); - } - - if (tex != null || needTexCoords) { - shader.setTexcoordAttribute(bufPolyTexcoord.glId, 2, PGL.FLOAT, 0, - 2 * voffset * PGL.SIZEOF_FLOAT); - shader.setTexture(tex); - } - - for (VertexAttribute attrib: polyAttribs.values()) { - if (!attrib.active(shader)) continue; - attrib.bind(pgl); - shader.setAttributeVBO(attrib.glLoc, attrib.buf.glId, - attrib.tessSize, attrib.type, - attrib.isColor(), 0, attrib.sizeInBytes(voffset)); - } - - shader.draw(bufPolyIndex.glId, icount, ioffset); - } - - for (VertexAttribute attrib: polyAttribs.values()) { - if (attrib.active(shader)) attrib.unbind(pgl); - } - shader.unbind(); - } - unbindPolyBuffers(); - } - - protected void flushSortedPolys() { - boolean customShader = polyShader != null; - boolean needNormals = customShader ? polyShader.accessNormals() : false; - boolean needTexCoords = customShader ? polyShader.accessTexCoords() : false; - - sorter.sort(tessGeo); - - int triangleCount = tessGeo.polyIndexCount / 3; - int[] texMap = sorter.texMap; - int[] voffsetMap = sorter.voffsetMap; - - int[] vertexOffset = tessGeo.polyIndexCache.vertexOffset; - - updatePolyBuffers(lights, texCache.hasTextures, needNormals, needTexCoords); - - int ti = 0; - - while (ti < triangleCount) { - - int startTi = ti; - int texId = texMap[ti]; - int voffsetId = voffsetMap[ti]; - - do { - ++ti; - } while (ti < triangleCount && - texId == texMap[ti] && - voffsetId == voffsetMap[ti]); - - int endTi = ti; - - Texture tex = texCache.getTexture(texId); - - int voffset = vertexOffset[voffsetId]; - - int ioffset = 3 * startTi; - int icount = 3 * (endTi - startTi); - - // If the renderer is 2D, then lights should always be false, - // so no need to worry about that. - PShader shader = getPolyShader(lights, tex != null); - shader.bind(); - - shader.setVertexAttribute(bufPolyVertex.glId, 4, PGL.FLOAT, 0, - 4 * voffset * PGL.SIZEOF_FLOAT); - shader.setColorAttribute(bufPolyColor.glId, 4, PGL.UNSIGNED_BYTE, 0, - 4 * voffset * PGL.SIZEOF_BYTE); - - if (lights) { - shader.setNormalAttribute(bufPolyNormal.glId, 3, PGL.FLOAT, 0, - 3 * voffset * PGL.SIZEOF_FLOAT); - shader.setAmbientAttribute(bufPolyAmbient.glId, 4, PGL.UNSIGNED_BYTE, 0, - 4 * voffset * PGL.SIZEOF_BYTE); - shader.setSpecularAttribute(bufPolySpecular.glId, 4, PGL.UNSIGNED_BYTE, 0, - 4 * voffset * PGL.SIZEOF_BYTE); - shader.setEmissiveAttribute(bufPolyEmissive.glId, 4, PGL.UNSIGNED_BYTE, 0, - 4 * voffset * PGL.SIZEOF_BYTE); - shader.setShininessAttribute(bufPolyShininess.glId, 1, PGL.FLOAT, 0, - voffset * PGL.SIZEOF_FLOAT); - } - - if (lights || needNormals) { - shader.setNormalAttribute(bufPolyNormal.glId, 3, PGL.FLOAT, 0, - 3 * voffset * PGL.SIZEOF_FLOAT); - } - - if (tex != null || needTexCoords) { - shader.setTexcoordAttribute(bufPolyTexcoord.glId, 2, PGL.FLOAT, 0, - 2 * voffset * PGL.SIZEOF_FLOAT); - shader.setTexture(tex); - } - - for (VertexAttribute attrib: polyAttribs.values()) { - if (!attrib.active(shader)) continue; - attrib.bind(pgl); - shader.setAttributeVBO(attrib.glLoc, attrib.buf.glId, - attrib.tessSize, attrib.type, - attrib.isColor(), 0, attrib.sizeInBytes(voffset)); - } - - shader.draw(bufPolyIndex.glId, icount, ioffset); - - for (VertexAttribute attrib: polyAttribs.values()) { - if (attrib.active(shader)) attrib.unbind(pgl); - } - shader.unbind(); - } - unbindPolyBuffers(); - } - - - void rawPolys() { - raw.colorMode(RGB); - raw.noStroke(); - raw.beginShape(TRIANGLES); - - float[] vertices = tessGeo.polyVertices; - int[] color = tessGeo.polyColors; - float[] uv = tessGeo.polyTexCoords; - short[] indices = tessGeo.polyIndices; - - for (int i = 0; i < texCache.size; i++) { - PImage textureImage = texCache.getTextureImage(i); - - int first = texCache.firstCache[i]; - int last = texCache.lastCache[i]; - IndexCache cache = tessGeo.polyIndexCache; - for (int n = first; n <= last; n++) { - int ioffset = n == first ? texCache.firstIndex[i] : - cache.indexOffset[n]; - int icount = n == last ? texCache.lastIndex[i] - ioffset + 1 : - cache.indexOffset[n] + cache.indexCount[n] - - ioffset; - int voffset = cache.vertexOffset[n]; - - for (int tr = ioffset / 3; tr < (ioffset + icount) / 3; tr++) { - int i0 = voffset + indices[3 * tr + 0]; - int i1 = voffset + indices[3 * tr + 1]; - int i2 = voffset + indices[3 * tr + 2]; - - float[] pt0 = {0, 0, 0, 0}; - float[] pt1 = {0, 0, 0, 0}; - float[] pt2 = {0, 0, 0, 0}; - int argb0 = PGL.nativeToJavaARGB(color[i0]); - int argb1 = PGL.nativeToJavaARGB(color[i1]); - int argb2 = PGL.nativeToJavaARGB(color[i2]); - - if (flushMode == FLUSH_CONTINUOUSLY) { - float[] src0 = {0, 0, 0, 0}; - float[] src1 = {0, 0, 0, 0}; - float[] src2 = {0, 0, 0, 0}; - PApplet.arrayCopy(vertices, 4 * i0, src0, 0, 4); - PApplet.arrayCopy(vertices, 4 * i1, src1, 0, 4); - PApplet.arrayCopy(vertices, 4 * i2, src2, 0, 4); - modelview.mult(src0, pt0); - modelview.mult(src1, pt1); - modelview.mult(src2, pt2); - } else { - PApplet.arrayCopy(vertices, 4 * i0, pt0, 0, 4); - PApplet.arrayCopy(vertices, 4 * i1, pt1, 0, 4); - PApplet.arrayCopy(vertices, 4 * i2, pt2, 0, 4); - } - - if (textureImage != null) { - raw.texture(textureImage); - if (raw.is3D()) { - raw.fill(argb0); - raw.vertex(pt0[X], pt0[Y], pt0[Z], uv[2 * i0 + 0], uv[2 * i0 + 1]); - raw.fill(argb1); - raw.vertex(pt1[X], pt1[Y], pt1[Z], uv[2 * i1 + 0], uv[2 * i1 + 1]); - raw.fill(argb2); - raw.vertex(pt2[X], pt2[Y], pt2[Z], uv[2 * i2 + 0], uv[2 * i2 + 1]); - } else if (raw.is2D()) { - float sx0 = screenXImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sy0 = screenYImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sx1 = screenXImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sy1 = screenYImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sx2 = screenXImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - float sy2 = screenYImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - raw.fill(argb0); - raw.vertex(sx0, sy0, uv[2 * i0 + 0], uv[2 * i0 + 1]); - raw.fill(argb1); - raw.vertex(sx1, sy1, uv[2 * i1 + 0], uv[2 * i1 + 1]); - raw.fill(argb1); - raw.vertex(sx2, sy2, uv[2 * i2 + 0], uv[2 * i2 + 1]); - } - } else { - if (raw.is3D()) { - raw.fill(argb0); - raw.vertex(pt0[X], pt0[Y], pt0[Z]); - raw.fill(argb1); - raw.vertex(pt1[X], pt1[Y], pt1[Z]); - raw.fill(argb2); - raw.vertex(pt2[X], pt2[Y], pt2[Z]); - } else if (raw.is2D()) { - float sx0 = screenXImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sy0 = screenYImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sx1 = screenXImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sy1 = screenYImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sx2 = screenXImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - float sy2 = screenYImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - raw.fill(argb0); - raw.vertex(sx0, sy0); - raw.fill(argb1); - raw.vertex(sx1, sy1); - raw.fill(argb2); - raw.vertex(sx2, sy2); - } - } - } - } - } - - - raw.endShape(); - } - - - void rawSortedPolys() { - raw.colorMode(RGB); - raw.noStroke(); - raw.beginShape(TRIANGLES); - - float[] vertices = tessGeo.polyVertices; - int[] color = tessGeo.polyColors; - float[] uv = tessGeo.polyTexCoords; - short[] indices = tessGeo.polyIndices; - - sorter.sort(tessGeo); - int[] triangleIndices = sorter.triangleIndices; - int[] texMap = sorter.texMap; - int[] voffsetMap = sorter.voffsetMap; - - int[] vertexOffset = tessGeo.polyIndexCache.vertexOffset; - - for (int i = 0; i < tessGeo.polyIndexCount/3; i++) { - int ti = triangleIndices[i]; - PImage tex = texCache.getTextureImage(texMap[ti]); - int voffset = vertexOffset[voffsetMap[ti]]; - - int i0 = voffset + indices[3*ti+0]; - int i1 = voffset + indices[3*ti+1]; - int i2 = voffset + indices[3*ti+2]; - - float[] pt0 = {0, 0, 0, 0}; - float[] pt1 = {0, 0, 0, 0}; - float[] pt2 = {0, 0, 0, 0}; - int argb0 = PGL.nativeToJavaARGB(color[i0]); - int argb1 = PGL.nativeToJavaARGB(color[i1]); - int argb2 = PGL.nativeToJavaARGB(color[i2]); - - if (flushMode == FLUSH_CONTINUOUSLY) { - float[] src0 = {0, 0, 0, 0}; - float[] src1 = {0, 0, 0, 0}; - float[] src2 = {0, 0, 0, 0}; - PApplet.arrayCopy(vertices, 4 * i0, src0, 0, 4); - PApplet.arrayCopy(vertices, 4 * i1, src1, 0, 4); - PApplet.arrayCopy(vertices, 4 * i2, src2, 0, 4); - modelview.mult(src0, pt0); - modelview.mult(src1, pt1); - modelview.mult(src2, pt2); - } else { - PApplet.arrayCopy(vertices, 4 * i0, pt0, 0, 4); - PApplet.arrayCopy(vertices, 4 * i1, pt1, 0, 4); - PApplet.arrayCopy(vertices, 4 * i2, pt2, 0, 4); - } - - if (tex != null) { - raw.texture(tex); - if (raw.is3D()) { - raw.fill(argb0); - raw.vertex(pt0[X], pt0[Y], pt0[Z], uv[2 * i0 + 0], uv[2 * i0 + 1]); - raw.fill(argb1); - raw.vertex(pt1[X], pt1[Y], pt1[Z], uv[2 * i1 + 0], uv[2 * i1 + 1]); - raw.fill(argb2); - raw.vertex(pt2[X], pt2[Y], pt2[Z], uv[2 * i2 + 0], uv[2 * i2 + 1]); - } else if (raw.is2D()) { - float sx0 = screenXImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sy0 = screenYImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sx1 = screenXImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sy1 = screenYImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sx2 = screenXImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - float sy2 = screenYImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - raw.fill(argb0); - raw.vertex(sx0, sy0, uv[2 * i0 + 0], uv[2 * i0 + 1]); - raw.fill(argb1); - raw.vertex(sx1, sy1, uv[2 * i1 + 0], uv[2 * i1 + 1]); - raw.fill(argb1); - raw.vertex(sx2, sy2, uv[2 * i2 + 0], uv[2 * i2 + 1]); - } - } else { - if (raw.is3D()) { - raw.fill(argb0); - raw.vertex(pt0[X], pt0[Y], pt0[Z]); - raw.fill(argb1); - raw.vertex(pt1[X], pt1[Y], pt1[Z]); - raw.fill(argb2); - raw.vertex(pt2[X], pt2[Y], pt2[Z]); - } else if (raw.is2D()) { - float sx0 = screenXImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sy0 = screenYImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sx1 = screenXImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sy1 = screenYImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sx2 = screenXImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - float sy2 = screenYImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - raw.fill(argb0); - raw.vertex(sx0, sy0); - raw.fill(argb1); - raw.vertex(sx1, sy1); - raw.fill(argb2); - raw.vertex(sx2, sy2); - } - } - } - - raw.endShape(); - } - - - protected void flushLines() { - updateLineBuffers(); - - PShader shader = getLineShader(); - shader.bind(); - - IndexCache cache = tessGeo.lineIndexCache; - for (int n = 0; n < cache.size; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int voffset = cache.vertexOffset[n]; - - shader.setVertexAttribute(bufLineVertex.glId, 4, PGL.FLOAT, 0, - 4 * voffset * PGL.SIZEOF_FLOAT); - shader.setColorAttribute(bufLineColor.glId, 4, PGL.UNSIGNED_BYTE, 0, - 4 * voffset * PGL.SIZEOF_BYTE); - shader.setLineAttribute(bufLineAttrib.glId, 4, PGL.FLOAT, 0, - 4 * voffset * PGL.SIZEOF_FLOAT); - - shader.draw(bufLineIndex.glId, icount, ioffset); - } - - shader.unbind(); - unbindLineBuffers(); - } - - - void rawLines() { - raw.colorMode(RGB); - raw.noFill(); - raw.strokeCap(strokeCap); - raw.strokeJoin(strokeJoin); - raw.beginShape(LINES); - - float[] vertices = tessGeo.lineVertices; - int[] color = tessGeo.lineColors; - float[] attribs = tessGeo.lineDirections; - short[] indices = tessGeo.lineIndices; - - IndexCache cache = tessGeo.lineIndexCache; - for (int n = 0; n < cache.size; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int voffset = cache.vertexOffset[n]; - - for (int ln = ioffset / 6; ln < (ioffset + icount) / 6; ln++) { - // Each line segment is defined by six indices since its - // formed by two triangles. We only need the first and last - // vertices. - // This bunch of vertices could also be the bevel triangles, - // with we detect this situation by looking at the line weight. - int i0 = voffset + indices[6 * ln + 0]; - int i1 = voffset + indices[6 * ln + 5]; - float sw0 = 2 * attribs[4 * i0 + 3]; - float sw1 = 2 * attribs[4 * i1 + 3]; - - if (zero(sw0)) continue; // Bevel triangles, skip. - - float[] pt0 = {0, 0, 0, 0}; - float[] pt1 = {0, 0, 0, 0}; - int argb0 = PGL.nativeToJavaARGB(color[i0]); - int argb1 = PGL.nativeToJavaARGB(color[i1]); - - if (flushMode == FLUSH_CONTINUOUSLY) { - float[] src0 = {0, 0, 0, 0}; - float[] src1 = {0, 0, 0, 0}; - PApplet.arrayCopy(vertices, 4 * i0, src0, 0, 4); - PApplet.arrayCopy(vertices, 4 * i1, src1, 0, 4); - modelview.mult(src0, pt0); - modelview.mult(src1, pt1); - } else { - PApplet.arrayCopy(vertices, 4 * i0, pt0, 0, 4); - PApplet.arrayCopy(vertices, 4 * i1, pt1, 0, 4); - } - - if (raw.is3D()) { - raw.strokeWeight(sw0); - raw.stroke(argb0); - raw.vertex(pt0[X], pt0[Y], pt0[Z]); - raw.strokeWeight(sw1); - raw.stroke(argb1); - raw.vertex(pt1[X], pt1[Y], pt1[Z]); - } else if (raw.is2D()) { - float sx0 = screenXImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sy0 = screenYImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sx1 = screenXImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sy1 = screenYImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - raw.strokeWeight(sw0); - raw.stroke(argb0); - raw.vertex(sx0, sy0); - raw.strokeWeight(sw1); - raw.stroke(argb1); - raw.vertex(sx1, sy1); - } - } - } - - raw.endShape(); - } - - - protected void flushPoints() { - updatePointBuffers(); - - PShader shader = getPointShader(); - shader.bind(); - - IndexCache cache = tessGeo.pointIndexCache; - for (int n = 0; n < cache.size; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int voffset = cache.vertexOffset[n]; - - shader.setVertexAttribute(bufPointVertex.glId, 4, PGL.FLOAT, 0, - 4 * voffset * PGL.SIZEOF_FLOAT); - shader.setColorAttribute(bufPointColor.glId, 4, PGL.UNSIGNED_BYTE, 0, - 4 * voffset * PGL.SIZEOF_BYTE); - shader.setPointAttribute(bufPointAttrib.glId, 2, PGL.FLOAT, 0, - 2 * voffset * PGL.SIZEOF_FLOAT); - - shader.draw(bufPointIndex.glId, icount, ioffset); - } - - shader.unbind(); - unbindPointBuffers(); - } - - - void rawPoints() { - raw.colorMode(RGB); - raw.noFill(); - raw.strokeCap(strokeCap); - raw.beginShape(POINTS); - - float[] vertices = tessGeo.pointVertices; - int[] color = tessGeo.pointColors; - float[] attribs = tessGeo.pointOffsets; - short[] indices = tessGeo.pointIndices; - - IndexCache cache = tessGeo.pointIndexCache; - for (int n = 0; n < cache.size; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int voffset = cache.vertexOffset[n]; - - int pt = ioffset; - while (pt < (ioffset + icount) / 3) { - float size = attribs[2 * pt + 2]; - float weight; - int perim; - if (0 < size) { // round point - weight = +size / 0.5f; - perim = PApplet.min(MAX_POINT_ACCURACY, PApplet.max(MIN_POINT_ACCURACY, - (int) (TWO_PI * weight / POINT_ACCURACY_FACTOR))) + 1; - } else { // Square point - weight = -size / 0.5f; - perim = 5; - } - - int i0 = voffset + indices[3 * pt]; - int argb0 = PGL.nativeToJavaARGB(color[i0]); - float[] pt0 = {0, 0, 0, 0}; - - if (flushMode == FLUSH_CONTINUOUSLY) { - float[] src0 = {0, 0, 0, 0}; - PApplet.arrayCopy(vertices, 4 * i0, src0, 0, 4); - modelview.mult(src0, pt0); - } else { - PApplet.arrayCopy(vertices, 4 * i0, pt0, 0, 4); - } - - if (raw.is3D()) { - raw.strokeWeight(weight); - raw.stroke(argb0); - raw.vertex(pt0[X], pt0[Y], pt0[Z]); - } else if (raw.is2D()) { - float sx0 = screenXImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sy0 = screenYImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - raw.strokeWeight(weight); - raw.stroke(argb0); - raw.vertex(sx0, sy0); - } - - pt += perim; - } - } - - raw.endShape(); - } - - - ////////////////////////////////////////////////////////////// - - // BEZIER CURVE VERTICES - - - @Override - public void bezierVertex(float x2, float y2, - float x3, float y3, - float x4, float y4) { - bezierVertexImpl(x2, y2, 0, - x3, y3, 0, - x4, y4, 0); - } - - - @Override - public void bezierVertex(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - bezierVertexImpl(x2, y2, z2, - x3, y3, z3, - x4, y4, z4); - } - - - protected void bezierVertexImpl(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - bezierVertexCheck(shape, inGeo.vertexCount); - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addBezierVertex(x2, y2, z2, - x3, y3, z3, - x4, y4, z4, vertexBreak()); - } - - - @Override - public void quadraticVertex(float cx, float cy, - float x3, float y3) { - quadraticVertexImpl(cx, cy, 0, - x3, y3, 0); - } - - - @Override - public void quadraticVertex(float cx, float cy, float cz, - float x3, float y3, float z3) { - quadraticVertexImpl(cx, cy, cz, - x3, y3, z3); - } - - - protected void quadraticVertexImpl(float cx, float cy, float cz, - float x3, float y3, float z3) { - bezierVertexCheck(shape, inGeo.vertexCount); - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addQuadraticVertex(cx, cy, cz, - x3, y3, z3, vertexBreak()); - } - - - ////////////////////////////////////////////////////////////// - - // CATMULL-ROM CURVE VERTICES - - - @Override - public void curveVertex(float x, float y) { - curveVertexImpl(x, y, 0); - } - - - @Override - public void curveVertex(float x, float y, float z) { - curveVertexImpl(x, y, z); - } - - - protected void curveVertexImpl(float x, float y, float z) { - curveVertexCheck(shape); - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addCurveVertex(x, y, z, vertexBreak()); - } - - - ////////////////////////////////////////////////////////////// - - // POINT, LINE, TRIANGLE, QUAD - - - @Override - public void point(float x, float y) { - pointImpl(x, y, 0); - } - - - @Override - public void point(float x, float y, float z) { - pointImpl(x, y, z); - } - - - protected void pointImpl(float x, float y, float z) { - beginShape(POINTS); - defaultEdges = false; - normalMode = NORMAL_MODE_SHAPE; - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addPoint(x, y, z, fill, stroke); - endShape(); - } - - - @Override - public void line(float x1, float y1, float x2, float y2) { - lineImpl(x1, y1, 0, x2, y2, 0); - } - - - @Override - public void line(float x1, float y1, float z1, - float x2, float y2, float z2) { - lineImpl(x1, y1, z1, x2, y2, z2); - } - - - protected void lineImpl(float x1, float y1, float z1, - float x2, float y2, float z2) { - beginShape(LINES); - defaultEdges = false; - normalMode = NORMAL_MODE_SHAPE; - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addLine(x1, y1, z1, - x2, y2, z2, - fill, stroke); - endShape(); - } - - - @Override - public void triangle(float x1, float y1, float x2, float y2, - float x3, float y3) { - beginShape(TRIANGLES); - defaultEdges = false; - normalMode = NORMAL_MODE_SHAPE; - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addTriangle(x1, y1, 0, - x2, y2, 0, - x3, y3, 0, - fill, stroke); - endShape(); - } - - - @Override - public void quad(float x1, float y1, float x2, float y2, - float x3, float y3, float x4, float y4) { - beginShape(QUADS); - defaultEdges = false; - normalMode = NORMAL_MODE_SHAPE; - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addQuad(x1, y1, 0, - x2, y2, 0, - x3, y3, 0, - x4, y4, 0, - stroke); - endShape(); - } - - - @Override - protected void rectImpl(float x1, float y1, float x2, float y2, - float tl, float tr, float br, float bl) { - beginShape(POLYGON); - defaultEdges = false; - normalMode = NORMAL_MODE_SHAPE; - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addRect(x1, y1, x2, y2, tl, tr, br, bl, stroke); - endShape(CLOSE); - } - - - ////////////////////////////////////////////////////////////// - - // ELLIPSE - - - @Override - public void ellipseImpl(float a, float b, float c, float d) { - beginShape(TRIANGLE_FAN); - defaultEdges = false; - normalMode = NORMAL_MODE_SHAPE; - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addEllipse(a, b, c, d, fill, stroke); - endShape(); - } - - - @Override - protected void arcImpl(float x, float y, float w, float h, - float start, float stop, int mode) { - beginShape(TRIANGLE_FAN); - defaultEdges = false; - normalMode = NORMAL_MODE_SHAPE; - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addArc(x, y, w, h, start, stop, fill, stroke, mode); - endShape(); - } - - - ////////////////////////////////////////////////////////////// - - // BOX - - // public void box(float size) - - @Override - public void box(float w, float h, float d) { - beginShape(QUADS); - defaultEdges = false; - normalMode = NORMAL_MODE_VERTEX; - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.addBox(w, h, d, fill, stroke); - endShape(); - } - - ////////////////////////////////////////////////////////////// - - // SPHERE - - // public void sphereDetail(int res) - - // public void sphereDetail(int ures, int vres) - - @Override - public void sphere(float r) { - if ((sphereDetailU < 3) || (sphereDetailV < 2)) { - sphereDetail(30); - } - - beginShape(TRIANGLES); - defaultEdges = false; - normalMode = NORMAL_MODE_VERTEX; - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - int[] indices = inGeo.addSphere(r, sphereDetailU, sphereDetailV, - fill, stroke); - endShape(indices); - } - - ////////////////////////////////////////////////////////////// - - // BEZIER - - // public float bezierPoint(float a, float b, float c, float d, float t) - - // public float bezierTangent(float a, float b, float c, float d, float t) - - // public void bezierDetail(int detail) - - // public void bezier(float x1, float y1, - // float x2, float y2, - // float x3, float y3, - // float x4, float y4) - - // public void bezier(float x1, float y1, float z1, - // float x2, float y2, float z2, - // float x3, float y3, float z3, - // float x4, float y4, float z4) - - ////////////////////////////////////////////////////////////// - - // CATMULL-ROM CURVES - - // public float curvePoint(float a, float b, float c, float d, float t) - - // public float curveTangent(float a, float b, float c, float d, float t) - - // public void curveDetail(int detail) - - // public void curveTightness(float tightness) - - // public void curve(float x1, float y1, - // float x2, float y2, - // float x3, float y3, - // float x4, float y4) - - // public void curve(float x1, float y1, float z1, - // float x2, float y2, float z2, - // float x3, float y3, float z3, - // float x4, float y4, float z4) - - ////////////////////////////////////////////////////////////// - - // IMAGES - - // public void imageMode(int mode) - - // public void image(PImage image, float x, float y) - - // public void image(PImage image, float x, float y, float c, float d) - - // public void image(PImage image, - // float a, float b, float c, float d, - // int u1, int v1, int u2, int v2) - - // protected void imageImpl(PImage image, - // float x1, float y1, float x2, float y2, - // int u1, int v1, int u2, int v2) - - ////////////////////////////////////////////////////////////// - - // SMOOTH - -/* - @Override - public void smooth() { - if (quality < 2) { - smooth(2); - } else { - smooth(quality); - } - } - - - @Override - public void smooth(int level) { - if (smoothDisabled || PGL.MAX_SAMPLES == -1) return; - - smooth = true; - - if (maxSamples < level) { - if (0 < maxSamples) { - PGraphics.showWarning(UNSUPPORTED_SMOOTH_LEVEL_ERROR, level, maxSamples); - } else{ - PGraphics.showWarning(UNSUPPORTED_SMOOTH_ERROR); - } - level = maxSamples; - } - - if (quality != level) { - smoothCallCount++; - if (parent.frameCount - lastSmoothCall < 30 && 5 < smoothCallCount) { - smoothDisabled = true; - PGraphics.showWarning(TOO_MANY_SMOOTH_CALLS_ERROR); - } - lastSmoothCall = parent.frameCount; - - quality = level; - - if (quality <= 1) { - quality = 0; - textureSampling = Texture.POINT; - } else { - textureSampling = Texture.TRILINEAR; - } - - // This will trigger a surface restart next time - // requestDraw() is called. -// restartPGL(); - } - } - - - @Override - public void noSmooth() { - if (smoothDisabled) return; - - smooth = false; - textureSampling = Texture.POINT; - - if (1 < quality) { - smoothCallCount++; - if (parent.frameCount - lastSmoothCall < 30 && 5 < smoothCallCount) { - smoothDisabled = true; - PGraphics.showWarning(TOO_MANY_SMOOTH_CALLS_ERROR); - } - lastSmoothCall = parent.frameCount; - - quality = 0; - - // This will trigger a surface restart next time - // requestDraw() is called. - restartPGL(); - } - } - */ - - - ////////////////////////////////////////////////////////////// - - // SHAPE - - // public void shapeMode(int mode) - - - // TODO unapproved - @Override - protected void shape(PShape shape, float x, float y, float z) { - if (shape.isVisible()) { // don't do expensive matrix ops if invisible - flush(); - - pushMatrix(); - - if (shapeMode == CENTER) { - translate(x - shape.getWidth() / 2, y - shape.getHeight() / 2, - z - shape.getDepth() / 2); - - } else if ((shapeMode == CORNER) || (shapeMode == CORNERS)) { - translate(x, y, z); - } - shape.draw(this); - - popMatrix(); - } - } - - - // TODO unapproved - @Override - protected void shape(PShape shape, float x, float y, float z, - float c, float d, float e) { - if (shape.isVisible()) { // don't do expensive matrix ops if invisible - flush(); - - pushMatrix(); - - if (shapeMode == CENTER) { - // x, y and z are center, c, d and e refer to a diameter - translate(x - c / 2f, y - d / 2f, z - e / 2f); - scale(c / shape.getWidth(), - d / shape.getHeight(), - e / shape.getDepth()); - - } else if (shapeMode == CORNER) { - translate(x, y, z); - scale(c / shape.getWidth(), - d / shape.getHeight(), - e / shape.getDepth()); - - } else if (shapeMode == CORNERS) { - // c, d, e are x2/y2/z2, make them into width/height/depth - c -= x; - d -= y; - e -= z; - // then same as above - translate(x, y, z); - scale(c / shape.getWidth(), - d / shape.getHeight(), - e / shape.getDepth()); - } - shape.draw(this); - - popMatrix(); - } - } - - - ////////////////////////////////////////////////////////////// - - // SHAPE I/O - - - @Override - public PShape loadShape(String filename) { - String ext = PApplet.getExtension(filename); - if (PGraphics2D.isSupportedExtension(ext)) { - return PGraphics2D.loadShapeImpl(this, filename, ext); - } if (PGraphics3D.isSupportedExtension(ext)) { - return PGraphics3D.loadShapeImpl(this, filename, ext); - } else { - PGraphics.showWarning(UNSUPPORTED_SHAPE_FORMAT_ERROR); - return null; - } - } - - - ////////////////////////////////////////////////////////////// - - // TEXT SETTINGS - - // public void textAlign(int align) - - // public void textAlign(int alignX, int alignY) - - // public float textAscent() - - // public float textDescent() - - // public void textFont(PFont which) - - // public void textFont(PFont which, float size) - - // public void textLeading(float leading) - - // public void textMode(int mode) - - @Override - protected boolean textModeCheck(int mode) { - return mode == MODEL || (mode == SHAPE && PGL.SHAPE_TEXT_SUPPORTED); - } - - // public void textSize(float size) - - // public float textWidth(char c) - - // public float textWidth(String str) - - // protected float textWidthImpl(char buffer[], int start, int stop) - - - ////////////////////////////////////////////////////////////// - - // TEXT IMPL - - - @Override - public void text(char c, float x, float y) { - if (textFont == null) { - defaultFontOrDeath("text"); - } - - int sign = cameraUp ? -1 : +1; - - if (textAlignY == CENTER) { - y += sign * textAscent() / 2; - } else if (textAlignY == TOP) { - y += sign * textAscent(); - } else if (textAlignY == BOTTOM) { - y -= sign * textDescent(); - //} else if (textAlignY == BASELINE) { - // do nothing - } - - textBuffer[0] = c; - textLineAlignImpl(textBuffer, 0, 1, x, y); - } - - - @Override - public void text(String str, float x, float y) { - if (textFont == null) { - defaultFontOrDeath("text"); - } - - int sign = cameraUp ? -1 : +1; - - int length = str.length(); - if (length > textBuffer.length) { - textBuffer = new char[length + 10]; - } - str.getChars(0, length, textBuffer, 0); - - // If multiple lines, sum the height of the additional lines - float high = 0; //-textAscent(); - for (int i = 0; i < length; i++) { - if (textBuffer[i] == '\n') { - high += sign * textLeading; - } - } - if (textAlignY == CENTER) { - // for a single line, this adds half the textAscent to y - // for multiple lines, subtract half the additional height - //y += (textAscent() - textDescent() - high)/2; - y += sign * (textAscent() - high)/2; - } else if (textAlignY == TOP) { - // for a single line, need to add textAscent to y - // for multiple lines, no different - y += sign * textAscent(); - } else if (textAlignY == BOTTOM) { - // for a single line, this is just offset by the descent - // for multiple lines, subtract leading for each line - y -= sign * textDescent() + high; - } - - int start = 0; - int index = 0; - while (index < length) { - if (textBuffer[index] == '\n') { - textLineAlignImpl(textBuffer, start, index, x, y); - start = index + 1; - y += sign * textLeading; - } - index++; - } - if (start < length) { - textLineAlignImpl(textBuffer, start, index, x, y); - } - } - - - @Override - public void text(String str, float x1, float y1, float x2, float y2) { - if (textFont == null) { - defaultFontOrDeath("text"); - } - - int sign = cameraUp ? -1 : +1; - - float hradius, vradius; - switch (rectMode) { - case CORNER: - x2 += x1; y2 += y1; - break; - case RADIUS: - hradius = x2; - vradius = y2; - x2 = x1 + hradius; - y2 = y1 + vradius; - x1 -= hradius; - y1 -= vradius; - break; - case CENTER: - hradius = x2 / 2.0f; - vradius = y2 / 2.0f; - x2 = x1 + hradius; - y2 = y1 + vradius; - x1 -= hradius; - y1 -= vradius; - } - if (x2 < x1) { - float temp = x1; x1 = x2; x2 = temp; - } - if (y2 < y1) { - float temp = y1; y1 = y2; y2 = temp; - } - - float boxWidth = x2 - x1; - - float spaceWidth = textWidth(' '); - - if (textBreakStart == null) { - textBreakStart = new int[20]; - textBreakStop = new int[20]; - } - textBreakCount = 0; - - int length = str.length(); - if (length + 1 > textBuffer.length) { - textBuffer = new char[length + 1]; - } - str.getChars(0, length, textBuffer, 0); - // add a fake newline to simplify calculations - textBuffer[length++] = '\n'; - - int sentenceStart = 0; - for (int i = 0; i < length; i++) { - if (textBuffer[i] == '\n') { - boolean legit = - textSentence(textBuffer, sentenceStart, i, boxWidth, spaceWidth); - if (!legit) break; - sentenceStart = i + 1; - } - } - - // lineX is the position where the text starts, which is adjusted - // to left/center/right based on the current textAlign - float lineX = x1; //boxX1; - if (textAlign == CENTER) { - lineX = lineX + boxWidth/2f; - } else if (textAlign == RIGHT) { - lineX = x2; //boxX2; - } - - float boxHeight = y2 - y1; - // incorporate textAscent() for the top (baseline will be y1 + ascent) - // and textDescent() for the bottom, so that lower parts of letters aren't - // outside the box. [0151] - float topAndBottom = textAscent() + textDescent(); - int lineFitCount = 1 + PApplet.floor((boxHeight - topAndBottom) / textLeading); - int lineCount = Math.min(textBreakCount, lineFitCount); - - if (textAlignY == CENTER) { - float lineHigh = textAscent() + textLeading * (lineCount - 1); - float y = cameraUp ? y2 - textAscent() - (boxHeight - lineHigh) / 2 : - y1 + textAscent() + (boxHeight - lineHigh) / 2; - for (int i = 0; i < lineCount; i++) { - textLineAlignImpl(textBuffer, textBreakStart[i], textBreakStop[i], lineX, y); - y += sign * textLeading; - } - - } else if (textAlignY == BOTTOM) { - float y = cameraUp ? y1 + textDescent() + textLeading * (lineCount - 1) : - y2 - textDescent() - textLeading * (lineCount - 1); - for (int i = 0; i < lineCount; i++) { - textLineAlignImpl(textBuffer, textBreakStart[i], textBreakStop[i], lineX, y); - y += sign * textLeading; - } - - } else { // TOP or BASELINE just go to the default - float y = cameraUp ? y2 - textAscent() : y1 + textAscent(); - for (int i = 0; i < lineCount; i++) { - textLineAlignImpl(textBuffer, textBreakStart[i], textBreakStop[i], lineX, y); - y += sign * textLeading; - } - } - } - - - @Override - public float textAscent() { - if (textFont == null) defaultFontOrDeath("textAscent"); - Object font = textFont.getNative(); - float ascent = 0; - if (font != null) ascent = pgl.getFontAscent(font); - if (ascent == 0) ascent = super.textAscent(); - return ascent; - } - - - @Override - public float textDescent() { - if (textFont == null) defaultFontOrDeath("textDescent"); - Object font = textFont.getNative(); - float descent = 0; - if (font != null) descent = pgl.getFontDescent(font); - if (descent == 0) descent = super.textDescent(); - return descent; - } - - - @Override - protected float textWidthImpl(char buffer[], int start, int stop) { - Object font = textFont.getNative(); - float twidth = 0; - if (font != null) twidth = pgl.getTextWidth(font, buffer, start, stop); - if (twidth == 0) twidth = super.textWidthImpl(buffer, start, stop); - return twidth; - } - - - @Override - protected void handleTextSize(float size) { - Object font = textFont.getNative(); - if (font != null) { - Object dfont = pgl.getDerivedFont(font, size); - if (dfont != null) textFont.setNative(dfont); - } - super.handleTextSize(size); - } - - - /** - * Implementation of actual drawing for a line of text. - */ - @Override - protected void textLineImpl(char buffer[], int start, int stop, - float x, float y) { - if (textMode == MODEL) { - textTex = getFontTexture(textFont); - - if (textTex == null || textTex.contextIsOutdated()) { - textTex = new FontTexture(this, textFont, is3D()); - setFontTexture(textFont, textTex); - } - - textTex.begin(); - - // Saving style parameters modified by text rendering. - int savedTextureMode = textureMode; - boolean savedStroke = stroke; - float savedNormalX = normalX; - float savedNormalY = normalY; - float savedNormalZ = normalZ; - boolean savedTint = tint; - int savedTintColor = tintColor; - int savedBlendMode = blendMode; - - // Setting style used in text rendering. - textureMode = NORMAL; - stroke = false; - normalX = 0; - normalY = 0; - normalZ = 1; - tint = true; - tintColor = fillColor; - - blendMode(BLEND); - - super.textLineImpl(buffer, start, stop, x, y); - - // Restoring original style. - textureMode = savedTextureMode; - stroke = savedStroke; - normalX = savedNormalX; - normalY = savedNormalY; - normalZ = savedNormalZ; - tint = savedTint; - tintColor = savedTintColor; - - // Note that if the user is using a blending mode different from - // BLEND, and has a bunch of continuous text rendering, the performance - // won't be optimal because at the end of each text() call the geometry - // will be flushed when restoring the user's blend. - blendMode(savedBlendMode); - - textTex.end(); - } else if (textMode == SHAPE) { - super.textLineImpl(buffer, start, stop, x, y); - } - } - - - @Override - protected void textCharImpl(char ch, float x, float y) { - PFont.Glyph glyph = textFont.getGlyph(ch); - if (glyph != null) { - if (textMode == MODEL) { - FontTexture.TextureInfo tinfo = textTex.getTexInfo(glyph); - - if (tinfo == null) { - // Adding new glyph to the font texture. - tinfo = textTex.addToTexture(this, glyph); - } - - float high = glyph.height / (float) textFont.getSize(); - float bwidth = glyph.width / (float) textFont.getSize(); - float lextent = glyph.leftExtent / (float) textFont.getSize(); - float textent = glyph.topExtent / (float) textFont.getSize(); - - // The default text setting assumes an Y axis pointing down, so - // inverting in the the case Y points up - int sign = cameraUp ? -1 : +1; - - float x1 = x + lextent * textSize; - float y1 = y - sign * textent * textSize; - float x2 = x1 + bwidth * textSize; - float y2 = y1 + sign * high * textSize; - - textCharModelImpl(tinfo, x1, y1, x2, y2); - } else if (textMode == SHAPE) { - textCharShapeImpl(ch, x, y); - } - } - } - - - protected void textCharModelImpl(FontTexture.TextureInfo info, - float x0, float y0, - float x1, float y1) { - beginShape(QUADS); - texture(textTex.getTexture(info)); - vertex(x0, y0, info.u0, info.v0); - vertex(x1, y0, info.u1, info.v0); - vertex(x1, y1, info.u1, info.v1); - vertex(x0, y1, info.u0, info.v1); - endShape(); - } - - - /** - * Ported from the implementation of textCharShapeImpl() in 1.5.1 - * - * No attempt has been made to optimize this code - *

    - * TODO: Implement a FontShape class where each glyph is tessellated and - * stored inside a larger PShapeOpenGL object (which needs to be expanded as - * new glyphs are added and exceed the initial capacity in a similar way as - * the textures in FontTexture work). When a string of text is to be rendered - * in shape mode, then the correct sequences of vertex indices are computed - * (akin to the texcoords in the texture case) and used to draw only those - * parts of the PShape object that are required for the text. - *

    - * - * Some issues of the original implementation probably remain, so they are - * reproduced below: - *

    - * Also a problem where some fonts seem to be a bit slight, as if the - * control points aren't being mapped quite correctly. Probably doing - * something dumb that the control points don't map to P5's control - * points. Perhaps it's returning b-spline data from the TrueType font? - * Though it seems like that would make a lot of garbage rather than - * just a little flattening. - *

    - * There also seems to be a bug that is causing a line (but not a filled - * triangle) back to the origin on some letters (i.e. a capital L when - * tested with Akzidenz Grotesk Light). But this won't be visible - * with the stroke shut off, so tabling that bug for now. - */ - protected void textCharShapeImpl(char ch, float x, float y) { - // save the current stroke because it needs to be disabled - // while the text is being drawn - boolean strokeSaved = stroke; - stroke = false; - - PGL.FontOutline outline = pgl.createFontOutline(ch, textFont.getNative()); - - // six element array received from the Java2D path iterator - float textPoints[] = new float[6]; - float lastX = 0; - float lastY = 0; - - boolean open = false; - beginShape(); - while (!outline.isDone()) { - int type = outline.currentSegment(textPoints); - if (!open) { - beginContour(); - open = true; - } - if (type == PGL.SEG_MOVETO || type == PGL.SEG_LINETO) { // 1 point - vertex(x + textPoints[0], y + textPoints[1]); - lastX = textPoints[0]; - lastY = textPoints[1]; - } else if (type == PGL.SEG_QUADTO) { // 2 points - for (int i = 1; i < bezierDetail; i++) { - float t = (float)i / (float)bezierDetail; - vertex(x + bezierPoint(lastX, - lastX + (float) ((textPoints[0] - lastX) * 2/3.0), - textPoints[2] + (float) ((textPoints[0] - textPoints[2]) * 2/3.0), - textPoints[2], t), - y + bezierPoint(lastY, - lastY + (float) ((textPoints[1] - lastY) * 2/3.0), - textPoints[3] + (float) ((textPoints[1] - textPoints[3]) * 2/3.0), - textPoints[3], t)); - } - lastX = textPoints[2]; - lastY = textPoints[3]; - } else if (type == PGL.SEG_CUBICTO) { // 3 points - for (int i = 1; i < bezierDetail; i++) { - float t = (float)i / (float)bezierDetail; - vertex(x + bezierPoint(lastX, textPoints[0], - textPoints[2], textPoints[4], t), - y + bezierPoint(lastY, textPoints[1], - textPoints[3], textPoints[5], t)); - } - lastX = textPoints[4]; - lastY = textPoints[5]; - } else if (type == PGL.SEG_CLOSE) { - endContour(); - open = false; - } - outline.next(); - } - endShape(); - - // re-enable stroke if it was in use before - stroke = strokeSaved; - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX STACK - - - @Override - public void pushMatrix() { - if (modelviewStackDepth == MATRIX_STACK_DEPTH) { - throw new RuntimeException(ERROR_PUSHMATRIX_OVERFLOW); - } - modelview.get(modelviewStack[modelviewStackDepth]); - modelviewInv.get(modelviewInvStack[modelviewStackDepth]); - camera.get(cameraStack[modelviewStackDepth]); - cameraInv.get(cameraInvStack[modelviewStackDepth]); - modelviewStackDepth++; - } - - - @Override - public void popMatrix() { - if (modelviewStackDepth == 0) { - throw new RuntimeException(ERROR_PUSHMATRIX_UNDERFLOW); - } - modelviewStackDepth--; - modelview.set(modelviewStack[modelviewStackDepth]); - modelviewInv.set(modelviewInvStack[modelviewStackDepth]); - camera.set(cameraStack[modelviewStackDepth]); - cameraInv.set(cameraInvStack[modelviewStackDepth]); - updateProjmodelview(); - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX TRANSFORMATIONS - - - @Override - public void translate(float tx, float ty) { - translateImpl(tx, ty, 0); - } - - - @Override - public void translate(float tx, float ty, float tz) { - translateImpl(tx, ty, tz); - } - - - protected void translateImpl(float tx, float ty, float tz) { - modelview.translate(tx, ty, tz); - invTranslate(modelviewInv, tx, ty, tz); - projmodelview.translate(tx, ty, tz); - } - - - static protected void invTranslate(PMatrix3D matrix, - float tx, float ty, float tz) { - matrix.preApply(1, 0, 0, -tx, - 0, 1, 0, -ty, - 0, 0, 1, -tz, - 0, 0, 0, 1); - } - - - static protected void invTranslate(PMatrix2D matrix, - float tx, float ty) { - matrix.preApply(1, 0, -tx, - 0, 1, -ty); - } - - - static protected float matrixScale(PMatrix matrix) { - // Volumetric scaling factor that is associated to the given - // transformation matrix, which is given by the absolute value of its - // determinant: - float factor = 1; - - if (matrix != null) { - if (matrix instanceof PMatrix2D) { - PMatrix2D tr = (PMatrix2D)matrix; - float areaScaleFactor = Math.abs(tr.m00 * tr.m11 - tr.m01 * tr.m10); - factor = (float) Math.sqrt(areaScaleFactor); - } else if (matrix instanceof PMatrix3D) { - PMatrix3D tr = (PMatrix3D)matrix; - float volumeScaleFactor = - Math.abs(tr.m00 * (tr.m11 * tr.m22 - tr.m12 * tr.m21) + - tr.m01 * (tr.m12 * tr.m20 - tr.m10 * tr.m22) + - tr.m02 * (tr.m10 * tr.m21 - tr.m11 * tr.m20)); - factor = (float) Math.pow(volumeScaleFactor, 1.0f / 3.0f); - } - } - return factor; - } - - - /** - * Two dimensional rotation. Same as rotateZ (this is identical to a 3D - * rotation along the z-axis) but included for clarity -- it'd be weird for - * people drawing 2D graphics to be using rotateZ. And they might kick our a-- - * for the confusion. - */ - @Override - public void rotate(float angle) { - rotateImpl(angle, 0, 0, 1); - } - - - @Override - public void rotateX(float angle) { - rotateImpl(angle, 1, 0, 0); - } - - - @Override - public void rotateY(float angle) { - rotateImpl(angle, 0, 1, 0); - } - - - @Override - public void rotateZ(float angle) { - rotateImpl(angle, 0, 0, 1); - } - - - /** - * Rotate around an arbitrary vector, similar to glRotate(), except that it - * takes radians (instead of degrees). - */ - @Override - public void rotate(float angle, float v0, float v1, float v2) { - rotateImpl(angle, v0, v1, v2); - } - - - protected void rotateImpl(float angle, float v0, float v1, float v2) { - float norm2 = v0 * v0 + v1 * v1 + v2 * v2; - if (zero(norm2)) { - // The vector is zero, cannot apply rotation. - return; - } - - if (diff(norm2, 1)) { - // The rotation vector is not normalized. - float norm = PApplet.sqrt(norm2); - v0 /= norm; - v1 /= norm; - v2 /= norm; - } - - modelview.rotate(angle, v0, v1, v2); - invRotate(modelviewInv, angle, v0, v1, v2); - updateProjmodelview(); // Possibly cheaper than doing projmodelview.rotate() - } - - - static protected void invRotate(PMatrix3D matrix, float angle, - float v0, float v1, float v2) { - float c = PApplet.cos(-angle); - float s = PApplet.sin(-angle); - float t = 1.0f - c; - - matrix.preApply((t*v0*v0) + c, (t*v0*v1) - (s*v2), (t*v0*v2) + (s*v1), 0, - (t*v0*v1) + (s*v2), (t*v1*v1) + c, (t*v1*v2) - (s*v0), 0, - (t*v0*v2) - (s*v1), (t*v1*v2) + (s*v0), (t*v2*v2) + c, 0, - 0, 0, 0, 1); - } - - - static protected void invRotate(PMatrix2D matrix, float angle) { - matrix.rotate(-angle); - } - - - /** - * Same as scale(s, s, s). - */ - @Override - public void scale(float s) { - scaleImpl(s, s, s); - } - - - /** - * Same as scale(sx, sy, 1). - */ - @Override - public void scale(float sx, float sy) { - scaleImpl(sx, sy, 1); - } - - - /** - * Scale in three dimensions. - */ - @Override - public void scale(float sx, float sy, float sz) { - scaleImpl(sx, sy, sz); - } - - /** - * Scale in three dimensions. - */ - protected void scaleImpl(float sx, float sy, float sz) { - modelview.scale(sx, sy, sz); - invScale(modelviewInv, sx, sy, sz); - projmodelview.scale(sx, sy, sz); - } - - - static protected void invScale(PMatrix3D matrix, float x, float y, float z) { - matrix.preApply(1/x, 0, 0, 0, 0, 1/y, 0, 0, 0, 0, 1/z, 0, 0, 0, 0, 1); - } - - - static protected void invScale(PMatrix2D matrix, float x, float y) { - matrix.preApply(1/x, 0, 0, 0, 1/y, 0); - } - - - @Override - public void shearX(float angle) { - float t = (float) Math.tan(angle); - applyMatrixImpl(1, t, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - @Override - public void shearY(float angle) { - float t = (float) Math.tan(angle); - applyMatrixImpl(1, 0, 0, 0, - t, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX MORE! - - - @Override - public void resetMatrix() { - modelview.reset(); - modelviewInv.reset(); - projmodelview.set(projection); - - // For consistency, since modelview = camera * [all other transformations] - // the camera matrix should be set to the identity as well: - camera.reset(); - cameraInv.reset(); - } - - - @Override - public void applyMatrix(PMatrix2D source) { - applyMatrixImpl(source.m00, source.m01, 0, source.m02, - source.m10, source.m11, 0, source.m12, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - @Override - public void applyMatrix(float n00, float n01, float n02, - float n10, float n11, float n12) { - applyMatrixImpl(n00, n01, 0, n02, - n10, n11, 0, n12, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - - @Override - public void applyMatrix(PMatrix3D source) { - applyMatrixImpl(source.m00, source.m01, source.m02, source.m03, - source.m10, source.m11, source.m12, source.m13, - source.m20, source.m21, source.m22, source.m23, - source.m30, source.m31, source.m32, source.m33); - } - - - /** - * Apply a 4x4 transformation matrix to the modelview stack. - */ - @Override - public void applyMatrix(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - applyMatrixImpl(n00, n01, n02, n03, - n10, n11, n12, n13, - n20, n21, n22, n23, - n30, n31, n32, n33); - } - - - protected void applyMatrixImpl(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - modelview.apply(n00, n01, n02, n03, - n10, n11, n12, n13, - n20, n21, n22, n23, - n30, n31, n32, n33); - modelviewInv.set(modelview); - modelviewInv.invert(); - - projmodelview.apply(n00, n01, n02, n03, - n10, n11, n12, n13, - n20, n21, n22, n23, - n30, n31, n32, n33); - } - - - protected void begin2D() { - } - - - protected void end2D() { - } - - - ////////////////////////////////////////////////////////////// - - // MATRIX GET/SET/PRINT - - - @Override - public PMatrix getMatrix() { - return modelview.get(); - } - - - // public PMatrix2D getMatrix(PMatrix2D target) - - - @Override - public PMatrix3D getMatrix(PMatrix3D target) { - if (target == null) { - target = new PMatrix3D(); - } - target.set(modelview); - return target; - } - - - // public void setMatrix(PMatrix source) - - - @Override - public void setMatrix(PMatrix2D source) { - resetMatrix(); - applyMatrix(source); - } - - - /** - * Set the current transformation to the contents of the specified source. - */ - @Override - public void setMatrix(PMatrix3D source) { - resetMatrix(); - applyMatrix(source); - } - - - /** - * Print the current model (or "transformation") matrix. - */ - @Override - public void printMatrix() { - modelview.print(); - } - - - ////////////////////////////////////////////////////////////// - - // PROJECTION - - - public void pushProjection() { - if (projectionStackDepth == MATRIX_STACK_DEPTH) { - throw new RuntimeException(ERROR_PUSHMATRIX_OVERFLOW); - } - projection.get(projectionStack[projectionStackDepth]); - projectionStackDepth++; - } - - - public void popProjection() { - flush(); // The geometry with the old projection matrix needs to be drawn now - - if (projectionStackDepth == 0) { - throw new RuntimeException(ERROR_PUSHMATRIX_UNDERFLOW); - } - projectionStackDepth--; - projection.set(projectionStack[projectionStackDepth]); - updateProjmodelview(); - } - - - public void resetProjection() { - flush(); - projection.reset(); - updateProjmodelview(); - } - - - public void applyProjection(PMatrix3D mat) { - flush(); - projection.apply(mat); - updateProjmodelview(); - } - - - public void applyProjection(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - flush(); - projection.apply(n00, n01, n02, n03, - n10, n11, n12, n13, - n20, n21, n22, n23, - n30, n31, n32, n33); - updateProjmodelview(); - } - - - public void setProjection(PMatrix3D mat) { - flush(); - projection.set(mat); - updateProjmodelview(); - } - - - // Returns true if the matrix is of the form: - // x, 0, 0, a, - // 0, y, 0, b, - // 0, 0, z, c, - // 0, 0, 0, 1 - protected boolean orthoProjection() { - return zero(projection.m01) && zero(projection.m02) && - zero(projection.m10) && zero(projection.m12) && - zero(projection.m20) && zero(projection.m21) && - zero(projection.m30) && zero(projection.m31) && - zero(projection.m32) && same(projection.m33, 1); - } - - - protected boolean nonOrthoProjection() { - return nonZero(projection.m01) || nonZero(projection.m02) || - nonZero(projection.m10) || nonZero(projection.m12) || - nonZero(projection.m20) || nonZero(projection.m21) || - nonZero(projection.m30) || nonZero(projection.m31) || - nonZero(projection.m32) || diff(projection.m33, 1); - } - - - ////////////////////////////////////////////////////////////// - - // Some float math utilities - - - protected static boolean same(float a, float b) { - return Math.abs(a - b) < PGL.FLOAT_EPS; - } - - - protected static boolean diff(float a, float b) { - return PGL.FLOAT_EPS <= Math.abs(a - b); - } - - - protected static boolean zero(float a) { - return Math.abs(a) < PGL.FLOAT_EPS; - } - - - protected static boolean nonZero(float a) { - return PGL.FLOAT_EPS <= Math.abs(a); - } - - - ////////////////////////////////////////////////////////////// - - // CAMERA - - /** - * Set matrix mode to the camera matrix (instead of the current transformation - * matrix). This means applyMatrix, resetMatrix, etc. will affect the camera. - *

    - * Note that the camera matrix is *not* the perspective matrix, it contains - * the values of the modelview matrix immediatly after the latter was - * initialized with ortho() or camera(), or the modelview matrix as result of - * the operations applied between beginCamera()/endCamera(). - *

    - * beginCamera() specifies that all coordinate transforms until endCamera() - * should be pre-applied in inverse to the camera transform matrix. Note that - * this is only challenging when a user specifies an arbitrary matrix with - * applyMatrix(). Then that matrix will need to be inverted, which may not be - * possible. But take heart, if a user is applying a non-invertible matrix to - * the camera transform, then he is clearly up to no good, and we can wash our - * hands of those bad intentions. - *

    - * begin/endCamera clauses do not automatically reset the camera transform - * matrix. That's because we set up a nice default camera transform in - * setup(), and we expect it to hold through draw(). So we don't reset the - * camera transform matrix at the top of draw(). That means that an - * innocuous-looking clause like - * - *

    -   * beginCamera();
    -   * translate(0, 0, 10);
    -   * endCamera();
    -   * 
    - * - * at the top of draw(), will result in a runaway camera that shoots - * infinitely out of the screen over time. In order to prevent this, it is - * necessary to call some function that does a hard reset of the camera - * transform matrix inside of begin/endCamera. Two options are - * - *
    -   * camera(); // sets up the nice default camera transform
    -   * resetMatrix(); // sets up the identity camera transform
    -   * 
    - * - * So to rotate a camera a constant amount, you might try - * - *
    -   * beginCamera();
    -   * camera();
    -   * rotateY(PI / 8);
    -   * endCamera();
    -   * 
    - */ - @Override - public void beginCamera() { - if (manipulatingCamera) { - throw new RuntimeException("beginCamera() cannot be called again " - + "before endCamera()"); - } else { - manipulatingCamera = true; - } - } - - - /** - * Record the current settings into the camera matrix, and set the matrix mode - * back to the current transformation matrix. - *

    - * Note that this will destroy any settings to scale(), translate(), or - * whatever, because the final camera matrix will be copied (not multiplied) - * into the modelview. - */ - @Override - public void endCamera() { - if (!manipulatingCamera) { - throw new RuntimeException("Cannot call endCamera() " - + "without first calling beginCamera()"); - } - - camera.set(modelview); - cameraInv.set(modelviewInv); - - // all done - manipulatingCamera = false; - } - - - /** - * Set camera to the default settings. - *

    - * Processing camera behavior: - *

    - * Camera behavior can be split into two separate components, camera - * transformation, and projection. The transformation corresponds to the - * physical location, orientation, and scale of the camera. In a physical - * camera metaphor, this is what can manipulated by handling the camera body - * (with the exception of scale, which doesn't really have a physcial analog). - * The projection corresponds to what can be changed by manipulating the lens. - *

    - * We maintain separate matrices to represent the camera transform and - * projection. An important distinction between the two is that the camera - * transform should be invertible, where the projection matrix should not, - * since it serves to map three dimensions to two. It is possible to bake the - * two matrices into a single one just by multiplying them together, but it - * isn't a good idea, since lighting, z-ordering, and z-buffering all demand a - * true camera z coordinate after modelview and camera transforms have been - * applied but before projection. If the camera transform and projection are - * combined there is no way to recover a good camera-space z-coordinate from a - * model coordinate. - *

    - * Fortunately, there are no functions that manipulate both camera - * transformation and projection. - *

    - * camera() sets the camera position, orientation, and center of the scene. It - * replaces the camera transform with a new one. - *

    - * The transformation functions are the same ones used to manipulate the - * modelview matrix (scale, translate, rotate, etc.). But they are bracketed - * with beginCamera(), endCamera() to indicate that they should apply (in - * inverse), to the camera transformation matrix. - */ - @Override - public void camera() { - camera(defCameraX, defCameraY, defCameraZ, defCameraX, defCameraY, - 0, 0, 1, 0); - } - - - /** - * More flexible method for dealing with camera(). - *

    - * The actual call is like gluLookat. Here's the real skinny on what does - * what: - * - *

    -   * camera(); or
    -   * camera(ex, ey, ez, cx, cy, cz, ux, uy, uz);
    -   * 
    - * - * do not need to be called from with beginCamera();/endCamera(); That's - * because they always apply to the camera transformation, and they always - * totally replace it. That means that any coordinate transforms done before - * camera(); in draw() will be wiped out. It also means that camera() always - * operates in untransformed world coordinates. Therefore it is always - * redundant to call resetMatrix(); before camera(); This isn't technically - * true of gluLookat, but it's pretty much how it's used. - *

    - * Now, beginCamera(); and endCamera(); are useful if you want to move the - * camera around using transforms like translate(), etc. They will wipe out - * any coordinate system transforms that occur before them in draw(), but they - * will not automatically wipe out the camera transform. This means that they - * should be at the top of draw(). It also means that the following: - * - *

    -   * beginCamera();
    -   * rotateY(PI / 8);
    -   * endCamera();
    -   * 
    - * - * will result in a camera that spins without stopping. If you want to just - * rotate a small constant amount, try this: - * - *
    -   * beginCamera();
    -   * camera(); // sets up the default view
    -   * rotateY(PI / 8);
    -   * endCamera();
    -   * 
    - * - * That will rotate a little off of the default view. Note that this is - * entirely equivalent to - * - *
    -   * camera(); // sets up the default view
    -   * beginCamera();
    -   * rotateY(PI / 8);
    -   * endCamera();
    -   * 
    - * - * because camera() doesn't care whether or not it's inside a begin/end - * clause. Basically it's safe to use camera() or camera(ex, ey, ez, cx, cy, - * cz, ux, uy, uz) as naked calls because they do all the matrix resetting - * automatically. - */ - @Override - public void camera(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - cameraX = eyeX; - cameraY = eyeY; - cameraZ = eyeZ; - - // Calculating Z vector - float z0 = eyeX - centerX; - float z1 = eyeY - centerY; - float z2 = eyeZ - centerZ; - eyeDist = PApplet.sqrt(z0 * z0 + z1 * z1 + z2 * z2); - if (nonZero(eyeDist)) { - z0 /= eyeDist; - z1 /= eyeDist; - z2 /= eyeDist; - } - - forwardX = z0; - forwardY = z1; - forwardZ = z2; - - // Calculating Y vector - float y0 = upX; - float y1 = upY; - float y2 = upZ; - - this.upX = upX; - this.upY = upY; - this.upZ = upZ; - - // Computing X vector as Y cross Z - float x0 = y1 * z2 - y2 * z1; - float x1 = -y0 * z2 + y2 * z0; - float x2 = y0 * z1 - y1 * z0; - - rightX = x0; - rightY = x1; - rightZ = x2; - - // Recompute Y = Z cross X - y0 = z1 * x2 - z2 * x1; - y1 = -z0 * x2 + z2 * x0; - y2 = z0 * x1 - z1 * x0; - - // Cross product gives area of parallelogram, which is < 1.0 for - // non-perpendicular unit-length vectors; so normalize x, y here: - float xmag = PApplet.sqrt(x0 * x0 + x1 * x1 + x2 * x2); - if (nonZero(xmag)) { - x0 /= xmag; - x1 /= xmag; - x2 /= xmag; - } - - float ymag = PApplet.sqrt(y0 * y0 + y1 * y1 + y2 * y2); - if (nonZero(ymag)) { - y0 /= ymag; - y1 /= ymag; - y2 /= ymag; - } - - modelview.set(x0, x1, x2, 0, - y0, y1, y2, 0, - z0, z1, z2, 0, - 0, 0, 0, 1); - - float tx = -eyeX; - float ty = -eyeY; - float tz = -eyeZ; - modelview.translate(tx, ty, tz); - - // The initial modelview transformation can be decomposed in a orthogonal - // matrix (with the inverse simply being the transpose), and a translation. - // The modelview inverse can then be calculated as follows, without need of - // employing the more general, slower, inverse() calculation. - modelviewInv.set(x0, y0, z0, 0, - x1, y1, z1, 0, - x2, y2, z2, 0, - 0, 0, 0, 1); - modelviewInv.translate(-tx, -ty, -tz); - - camera.set(modelview); - cameraInv.set(modelviewInv); - - updateProjmodelview(); - } - - - /** - * Print the current camera matrix. - */ - @Override - public void printCamera() { - camera.print(); - } - - - @Override - public void cameraUp() { - cameraUp = true; - } - - - protected void defaultCamera() { - camera(); - } - - - ////////////////////////////////////////////////////////////// - - // PROJECTION - - - /** - * Calls ortho() with the proper parameters for Processing's standard - * orthographic projection. - */ - @Override - public void ortho() { - ortho(-width/2f, width/2f, -height/2f, height/2f, 0, eyeDist * 10); - } - - - /** - * Calls ortho() with the specified size of the viewing volume along - * the X and Z directions. - */ - @Override - public void ortho(float left, float right, - float bottom, float top) { - ortho(left, right, bottom, top, 0, eyeDist * 10); - } - - - /** - * Sets an orthographic projection. - * - */ - @Override - public void ortho(float left, float right, - float bottom, float top, - float near, float far) { - float w = right - left; - float h = top - bottom; - float d = far - near; - - // Flushing geometry with a different perspective configuration. - flush(); - - float x = +2.0f / w; - float y = +2.0f / h; - float z = -2.0f / d; - - float tx = -(right + left) / w; - float ty = -(top + bottom) / h; - float tz = -(far + near) / d; - - // The minus sign is needed to invert the Y axis. - projection.set(x, 0, 0, tx, - 0, -y, 0, ty, - 0, 0, z, tz, - 0, 0, 0, 1); - - updateProjmodelview(); - } - - - /** - * Calls perspective() with Processing's standard coordinate projection. - *

    - * Projection functions: - *

      - *
    • frustrum() - *
    • ortho() - *
    • perspective() - *
    - * Each of these three functions completely replaces the projection matrix - * with a new one. They can be called inside setup(), and their effects will - * be felt inside draw(). At the top of draw(), the projection matrix is not - * reset. Therefore the last projection function to be called always - * dominates. On resize, the default projection is always established, which - * has perspective. - *

    - * This behavior is pretty much familiar from OpenGL, except where functions - * replace matrices, rather than multiplying against the previous. - *

    - */ - @Override - public void perspective() { - perspective(defCameraFOV, defCameraAspect, defCameraNear, defCameraFar); - } - - - /** - * Similar to gluPerspective(). Implementation based on Mesa's glu.c - */ - @Override - public void perspective(float fov, float aspect, float zNear, float zFar) { - float ymax = zNear * (float) Math.tan(fov / 2); - float ymin = -ymax; - float xmin = ymin * aspect; - float xmax = ymax * aspect; - frustum(xmin, xmax, ymin, ymax, zNear, zFar); - } - - - /** - * Same as glFrustum(), except that it wipes out (rather than multiplies - * against) the current perspective matrix. - *

    - * Implementation based on the explanation in the OpenGL blue book. - */ - @Override - public void frustum(float left, float right, float bottom, float top, - float znear, float zfar) { - // Flushing geometry with a different perspective configuration. - flush(); - - cameraFOV = 2 * (float) Math.atan2(top, znear); - cameraAspect = left / bottom; - cameraNear = znear; - cameraFar = zfar; - - float n2 = 2 * znear; - float w = right - left; - float h = top - bottom; - float d = zfar - znear; - - projection.set(n2 / w, 0, (right + left) / w, 0, - 0, -n2 / h, (top + bottom) / h, 0, - 0, 0, -(zfar + znear) / d, -(n2 * zfar) / d, - 0, 0, -1, 0); - - updateProjmodelview(); - } - - - /** - * Print the current projection matrix. - */ - @Override - public void printProjection() { - projection.print(); - } - - - protected void defaultPerspective() { - perspective(); - } - - - ////////////////////////////////////////////////////////////// - - // SCREEN AND MODEL COORDS - - - @Override - public float screenX(float x, float y) { - return screenXImpl(x, y, 0); - } - - - @Override - public float screenY(float x, float y) { - return screenYImpl(x, y, 0); - } - - - @Override - public float screenX(float x, float y, float z) { - return screenXImpl(x, y, z); - } - - - @Override - public float screenY(float x, float y, float z) { - return screenYImpl(x, y, z); - } - - - @Override - public float screenZ(float x, float y, float z) { - return screenZImpl(x, y, z); - } - - - protected float screenXImpl(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - return screenXImpl(ax, ay, az, aw); - } - - - protected float screenXImpl(float x, float y, float z, float w) { - float ox = - projection.m00*x + projection.m01*y + projection.m02*z + projection.m03*w; - float ow = - projection.m30*x + projection.m31*y + projection.m32*z + projection.m33*w; - - if (nonZero(ow)) { - ox /= ow; - } - float sx = width * (1 + ox) / 2.0f; - return sx; - } - - - protected float screenYImpl(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - return screenYImpl(ax, ay, az, aw); - } - - - protected float screenYImpl(float x, float y, float z, float w) { - float oy = - projection.m10*x + projection.m11*y + projection.m12*z + projection.m13*w; - float ow = - projection.m30*x + projection.m31*y + projection.m32*z + projection.m33*w; - - if (nonZero(ow)) { - oy /= ow; - } - float sy = height * (1 + oy) / 2.0f; - // Turning value upside down because of Processing's inverted Y axis. - sy = height - sy; - return sy; - } - - - protected float screenZImpl(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - return screenZImpl(ax, ay, az, aw); - } - - - protected float screenZImpl(float x, float y, float z, float w) { - float oz = - projection.m20*x + projection.m21*y + projection.m22*z + projection.m23*w; - float ow = - projection.m30*x + projection.m31*y + projection.m32*z + projection.m33*w; - - if (nonZero(ow)) { - oz /= ow; - } - float sz = (oz + 1) / 2.0f; - return sz; - } - - - @Override - public float modelX(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - - float ox = - cameraInv.m00*ax + cameraInv.m01*ay + cameraInv.m02*az + cameraInv.m03*aw; - float ow = - cameraInv.m30*ax + cameraInv.m31*ay + cameraInv.m32*az + cameraInv.m33*aw; - - return nonZero(ow) ? ox / ow : ox; - } - - - @Override - public float modelY(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - - float oy = - cameraInv.m10*ax + cameraInv.m11*ay + cameraInv.m12*az + cameraInv.m13*aw; - float ow = - cameraInv.m30*ax + cameraInv.m31*ay + cameraInv.m32*az + cameraInv.m33*aw; - - return nonZero(ow) ? oy / ow : oy; - } - - - @Override - public float modelZ(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - - float oz = - cameraInv.m20*ax + cameraInv.m21*ay + cameraInv.m22*az + cameraInv.m23*aw; - float ow = - cameraInv.m30*ax + cameraInv.m31*ay + cameraInv.m32*az + cameraInv.m33*aw; - - return nonZero(ow) ? oz / ow : oz; - } - - ////////////////////////////////////////////////////////////// - - // STYLES - - @Override - public void popStyle() { - // popStyle() sets ambient to true (because it calls ambient() in style()) - // and so setting the setAmbient flag to true, even if the user didn't call - // ambient, so need to revert to false. - boolean savedSetAmbient = setAmbient; - super.popStyle(); - if (!savedSetAmbient) setAmbient = false; - } - - // public void pushStyle() - // public void popStyle() - // public void style(PStyle) - // public PStyle getStyle() - // public void getStyle(PStyle) - - ////////////////////////////////////////////////////////////// - - // COLOR MODE - - // public void colorMode(int mode) - // public void colorMode(int mode, float max) - // public void colorMode(int mode, float mx, float my, float mz); - // public void colorMode(int mode, float mx, float my, float mz, float ma); - - ////////////////////////////////////////////////////////////// - - // COLOR CALC - - // protected void colorCalc(int rgb) - // protected void colorCalc(int rgb, float alpha) - // protected void colorCalc(float gray) - // protected void colorCalc(float gray, float alpha) - // protected void colorCalc(float x, float y, float z) - // protected void colorCalc(float x, float y, float z, float a) - // protected void colorCalcARGB(int argb, float alpha) - - ////////////////////////////////////////////////////////////// - - // STROKE CAP/JOIN/WEIGHT - - - @Override - public void strokeWeight(float weight) { - this.strokeWeight = weight; - } - - - @Override - public void strokeJoin(int join) { - this.strokeJoin = join; - } - - - @Override - public void strokeCap(int cap) { - this.strokeCap = cap; - } - - - ////////////////////////////////////////////////////////////// - - // FILL COLOR - - - @Override - protected void fillFromCalc() { - super.fillFromCalc(); - - if (!setAmbient) { - // Setting the ambient color from the current fill - // is what the old P3D did and allows to have an - // default ambient color when the user doesn't specify - // it explicitly. - ambientFromCalc(); - // ambientFromCalc sets setAmbient to true, but it hasn't been - // set by the user so put back to false. - setAmbient = false; - } - } - - - ////////////////////////////////////////////////////////////// - - // LIGHTING - - /** - * Sets up an ambient and directional light using OpenGL. API taken from - * PGraphics3D. - * - *

    -   * The Lighting Skinny:
    -   * The way lighting works is complicated enough that it's worth
    -   * producing a document to describe it. Lighting calculations proceed
    -   * pretty much exactly as described in the OpenGL red book.
    -   * Light-affecting material properties:
    -   *   AMBIENT COLOR
    -   *   - multiplies by light's ambient component
    -   *   - for believability this should match diffuse color
    -   *   DIFFUSE COLOR
    -   *   - multiplies by light's diffuse component
    -   *   SPECULAR COLOR
    -   *   - multiplies by light's specular component
    -   *   - usually less colored than diffuse/ambient
    -   *   SHININESS
    -   *   - the concentration of specular effect
    -   *   - this should be set pretty high (20-50) to see really
    -   *     noticeable specularity
    -   *   EMISSIVE COLOR
    -   *   - constant additive color effect
    -   * Light types:
    -   *   AMBIENT
    -   *   - one color
    -   *   - no specular color
    -   *   - no direction
    -   *   - may have falloff (constant, linear, and quadratic)
    -   *   - may have position (which matters in non-constant falloff case)
    -   *   - multiplies by a material's ambient reflection
    -   *   DIRECTIONAL
    -   *   - has diffuse color
    -   *   - has specular color
    -   *   - has direction
    -   *   - no position
    -   *   - no falloff
    -   *   - multiplies by a material's diffuse and specular reflections
    -   *   POINT
    -   *   - has diffuse color
    -   *   - has specular color
    -   *   - has position
    -   *   - no direction
    -   *   - may have falloff (constant, linear, and quadratic)
    -   *   - multiplies by a material's diffuse and specular reflections
    -   *   SPOT
    -   *   - has diffuse color
    -   *   - has specular color
    -   *   - has position
    -   *   - has direction
    -   *   - has cone angle (set to half the total cone angle)
    -   *   - has concentration value
    -   *   - may have falloff (constant, linear, and quadratic)
    -   *   - multiplies by a material's diffuse and specular reflections
    -   * Normal modes:
    -   * All of the primitives (rect, box, sphere, etc.) have their normals
    -   * set nicely. During beginShape/endShape normals can be set by the user.
    -   *   AUTO-NORMAL
    -   *   - if no normal is set during the shape, we are in auto-normal mode
    -   *   - auto-normal calculates one normal per triangle (face-normal mode)
    -   *   SHAPE-NORMAL
    -   *   - if one normal is set during the shape, it will be used for
    -   *     all vertices
    -   *   VERTEX-NORMAL
    -   *   - if multiple normals are set, each normal applies to
    -   *     subsequent vertices
    -   *   - (except for the first one, which applies to previous
    -   *     and subsequent vertices)
    -   * Efficiency consequences:
    -   *   There is a major efficiency consequence of position-dependent
    -   *   lighting calculations per vertex. (See below for determining
    -   *   whether lighting is vertex position-dependent.) If there is no
    -   *   position dependency then the only factors that affect the lighting
    -   *   contribution per vertex are its colors and its normal.
    -   *   There is a major efficiency win if
    -   *   1) lighting is not position dependent
    -   *   2) we are in AUTO-NORMAL or SHAPE-NORMAL mode
    -   *   because then we can calculate one lighting contribution per shape
    -   *   (SHAPE-NORMAL) or per triangle (AUTO-NORMAL) and simply multiply it
    -   *   into the vertex colors. The converse is our worst-case performance when
    -   *   1) lighting is position dependent
    -   *   2) we are in AUTO-NORMAL mode
    -   *   because then we must calculate lighting per-face * per-vertex.
    -   *   Each vertex has a different lighting contribution per face in
    -   *   which it appears. Yuck.
    -   * Determining vertex position dependency:
    -   *   If any of the following factors are TRUE then lighting is
    -   *   vertex position dependent:
    -   *   1) Any lights uses non-constant falloff
    -   *   2) There are any point or spot lights
    -   *   3) There is a light with specular color AND there is a
    -   *      material with specular color
    -   * So worth noting is that default lighting (a no-falloff ambient
    -   * and a directional without specularity) is not position-dependent.
    -   * We should capitalize.
    -   * Simon Greenwold, April 2005
    -   * 
    - */ - @Override - public void lights() { - enableLighting(); - - // reset number of lights - lightCount = 0; - - // need to make sure colorMode is RGB 255 here - int colorModeSaved = colorMode; - colorMode = RGB; - - lightFalloff(1, 0, 0); - lightSpecular(0, 0, 0); - - ambientLight(colorModeX * 0.5f, colorModeY * 0.5f, colorModeZ * 0.5f); - directionalLight(colorModeX * 0.5f, colorModeY * 0.5f, colorModeZ * 0.5f, - 0, 0, -1); - - colorMode = colorModeSaved; - } - - - /** - * Disables lighting. - */ - @Override - public void noLights() { - disableLighting(); - lightCount = 0; - } - - - /** - * Add an ambient light based on the current color mode. - */ - @Override - public void ambientLight(float r, float g, float b) { - ambientLight(r, g, b, 0, 0, 0); - } - - - /** - * Add an ambient light based on the current color mode. This version includes - * an (x, y, z) position for situations where the falloff distance is used. - */ - @Override - public void ambientLight(float r, float g, float b, - float x, float y, float z) { - enableLighting(); - if (lightCount == PGL.MAX_LIGHTS) { - throw new RuntimeException("can only create " + PGL.MAX_LIGHTS + - " lights"); - } - - lightType[lightCount] = AMBIENT; - - lightPosition(lightCount, x, y, z, false); - lightNormal(lightCount, 0, 0, 0); - - lightAmbient(lightCount, r, g, b); - noLightDiffuse(lightCount); - noLightSpecular(lightCount); - noLightSpot(lightCount); - lightFalloff(lightCount, currentLightFalloffConstant, - currentLightFalloffLinear, - currentLightFalloffQuadratic); - - lightCount++; - } - - - @Override - public void directionalLight(float r, float g, float b, - float dx, float dy, float dz) { - enableLighting(); - if (lightCount == PGL.MAX_LIGHTS) { - throw new RuntimeException("can only create " + PGL.MAX_LIGHTS + - " lights"); - } - - lightType[lightCount] = DIRECTIONAL; - - lightPosition(lightCount, 0, 0, 0, true); - lightNormal(lightCount, dx, dy, dz); - - noLightAmbient(lightCount); - lightDiffuse(lightCount, r, g, b); - lightSpecular(lightCount, currentLightSpecular[0], - currentLightSpecular[1], - currentLightSpecular[2]); - noLightSpot(lightCount); - noLightFalloff(lightCount); - - lightCount++; - } - - - @Override - public void pointLight(float r, float g, float b, - float x, float y, float z) { - enableLighting(); - if (lightCount == PGL.MAX_LIGHTS) { - throw new RuntimeException("can only create " + PGL.MAX_LIGHTS + - " lights"); - } - - lightType[lightCount] = POINT; - - lightPosition(lightCount, x, y, z, false); - lightNormal(lightCount, 0, 0, 0); - - noLightAmbient(lightCount); - lightDiffuse(lightCount, r, g, b); - lightSpecular(lightCount, currentLightSpecular[0], - currentLightSpecular[1], - currentLightSpecular[2]); - noLightSpot(lightCount); - lightFalloff(lightCount, currentLightFalloffConstant, - currentLightFalloffLinear, - currentLightFalloffQuadratic); - - lightCount++; - } - - - @Override - public void spotLight(float r, float g, float b, - float x, float y, float z, - float dx, float dy, float dz, - float angle, float concentration) { - enableLighting(); - if (lightCount == PGL.MAX_LIGHTS) { - throw new RuntimeException("can only create " + PGL.MAX_LIGHTS + - " lights"); - } - - lightType[lightCount] = SPOT; - - lightPosition(lightCount, x, y, z, false); - lightNormal(lightCount, dx, dy, dz); - - noLightAmbient(lightCount); - lightDiffuse(lightCount, r, g, b); - lightSpecular(lightCount, currentLightSpecular[0], - currentLightSpecular[1], - currentLightSpecular[2]); - lightSpot(lightCount, angle, concentration); - lightFalloff(lightCount, currentLightFalloffConstant, - currentLightFalloffLinear, - currentLightFalloffQuadratic); - - lightCount++; - } - - - /** - * Set the light falloff rates for the last light that was created. Default is - * lightFalloff(1, 0, 0). - */ - @Override - public void lightFalloff(float constant, float linear, float quadratic) { - currentLightFalloffConstant = constant; - currentLightFalloffLinear = linear; - currentLightFalloffQuadratic = quadratic; - } - - - /** - * Set the specular color of the last light created. - */ - @Override - public void lightSpecular(float x, float y, float z) { - colorCalc(x, y, z); - currentLightSpecular[0] = calcR; - currentLightSpecular[1] = calcG; - currentLightSpecular[2] = calcB; - } - - - protected void enableLighting() { - flush(); - lights = true; - } - - - protected void disableLighting() { - flush(); - lights = false; - } - - - protected void lightPosition(int num, float x, float y, float z, - boolean dir) { - lightPosition[4 * num + 0] = - x*modelview.m00 + y*modelview.m01 + z*modelview.m02 + modelview.m03; - lightPosition[4 * num + 1] = - x*modelview.m10 + y*modelview.m11 + z*modelview.m12 + modelview.m13; - lightPosition[4 * num + 2] = - x*modelview.m20 + y*modelview.m21 + z*modelview.m22 + modelview.m23; - - // Used to indicate if the light is directional or not. - lightPosition[4 * num + 3] = dir ? 0 : 1; - } - - - protected void lightNormal(int num, float dx, float dy, float dz) { - // Applying normal matrix to the light direction vector, which is the - // transpose of the inverse of the modelview. - float nx = - dx*modelviewInv.m00 + dy*modelviewInv.m10 + dz*modelviewInv.m20; - float ny = - dx*modelviewInv.m01 + dy*modelviewInv.m11 + dz*modelviewInv.m21; - float nz = - dx*modelviewInv.m02 + dy*modelviewInv.m12 + dz*modelviewInv.m22; - - float d = PApplet.dist(0, 0, 0, nx, ny, nz); - if (0 < d) { - float invn = 1.0f / d; - lightNormal[3 * num + 0] = invn * nx; - lightNormal[3 * num + 1] = invn * ny; - lightNormal[3 * num + 2] = invn * nz; - } else { - lightNormal[3 * num + 0] = 0; - lightNormal[3 * num + 1] = 0; - lightNormal[3 * num + 2] = 0; - } - } - - - protected void lightAmbient(int num, float r, float g, float b) { - colorCalc(r, g, b); - lightAmbient[3 * num + 0] = calcR; - lightAmbient[3 * num + 1] = calcG; - lightAmbient[3 * num + 2] = calcB; - } - - - protected void noLightAmbient(int num) { - lightAmbient[3 * num + 0] = 0; - lightAmbient[3 * num + 1] = 0; - lightAmbient[3 * num + 2] = 0; - } - - - protected void lightDiffuse(int num, float r, float g, float b) { - colorCalc(r, g, b); - lightDiffuse[3 * num + 0] = calcR; - lightDiffuse[3 * num + 1] = calcG; - lightDiffuse[3 * num + 2] = calcB; - } - - - protected void noLightDiffuse(int num) { - lightDiffuse[3 * num + 0] = 0; - lightDiffuse[3 * num + 1] = 0; - lightDiffuse[3 * num + 2] = 0; - } - - - protected void lightSpecular(int num, float r, float g, float b) { - lightSpecular[3 * num + 0] = r; - lightSpecular[3 * num + 1] = g; - lightSpecular[3 * num + 2] = b; - } - - - protected void noLightSpecular(int num) { - lightSpecular[3 * num + 0] = 0; - lightSpecular[3 * num + 1] = 0; - lightSpecular[3 * num + 2] = 0; - } - - - protected void lightFalloff(int num, float c0, float c1, float c2) { - lightFalloffCoefficients[3 * num + 0] = c0; - lightFalloffCoefficients[3 * num + 1] = c1; - lightFalloffCoefficients[3 * num + 2] = c2; - } - - - protected void noLightFalloff(int num) { - lightFalloffCoefficients[3 * num + 0] = 1; - lightFalloffCoefficients[3 * num + 1] = 0; - lightFalloffCoefficients[3 * num + 2] = 0; - } - - - protected void lightSpot(int num, float angle, float exponent) { - lightSpotParameters[2 * num + 0] = Math.max(0, PApplet.cos(angle)); - lightSpotParameters[2 * num + 1] = exponent; - } - - - protected void noLightSpot(int num) { - lightSpotParameters[2 * num + 0] = 0; - lightSpotParameters[2 * num + 1] = 0; - } - - - ////////////////////////////////////////////////////////////// - - // BACKGROUND - - - @Override - protected void backgroundImpl(PImage image) { - backgroundImpl(); - set(0, 0, image); - // Setting the background as opaque. If this an offscreen surface, the - // alpha channel will be set to 1 in endOffscreenDraw(), even if - // blending operations during draw create translucent areas in the - // color buffer. - backgroundA = 1; - loaded = false; - } - - - @Override - protected void backgroundImpl() { - flush(); - pgl.clearBackground(backgroundR, backgroundG, backgroundB, backgroundA, - !hints[DISABLE_DEPTH_MASK], true); - loaded = false; - } - - - ////////////////////////////////////////////////////////////// - - // COLOR MODE - - // colorMode() is inherited from PGraphics. - - - ////////////////////////////////////////////////////////////// - - // COLOR METHODS - - // public final int color(int gray) - // public final int color(int gray, int alpha) - // public final int color(int rgb, float alpha) - // public final int color(int x, int y, int z) - - // public final float alpha(int what) - // public final float red(int what) - // public final float green(int what) - // public final float blue(int what) - // public final float hue(int what) - // public final float saturation(int what) - // public final float brightness(int what) - - // public int lerpColor(int c1, int c2, float amt) - // static public int lerpColor(int c1, int c2, float amt, int mode) - - ////////////////////////////////////////////////////////////// - - // BEGINRAW/ENDRAW - - // beginRaw, endRaw() both inherited. - - ////////////////////////////////////////////////////////////// - - // WARNINGS and EXCEPTIONS - - // showWarning() and showException() available from PGraphics. - - /** - * Report on anything from glError(). - * Don't use this inside glBegin/glEnd otherwise it'll - * throw an GL_INVALID_OPERATION error. - */ - protected void report(String where) { - if (!hints[DISABLE_OPENGL_ERRORS]) { - int err = pgl.getError(); - if (err != 0) { - String errString = pgl.errorString(err); - String msg = "OpenGL error " + err + " at " + where + ": " + errString; - PGraphics.showWarning(msg); - } - } - } - - - - ////////////////////////////////////////////////////////////// - - // RENDERER SUPPORT QUERIES - - // public boolean displayable() - - - @Override - public boolean isGL() { - return true; - } - - - ////////////////////////////////////////////////////////////// - - // LOAD/UPDATE PIXELS - - - // Initializes the pixels array, copying the current contents of the - // color buffer into it. - @Override - public void loadPixels() { - if (primaryGraphics && sized) { - // Something wrong going on with threading, sized can never be true if - // all the steps in a resize happen inside the Animation thread. - return; - } - - boolean needEndDraw = false; - if (!drawing) { - beginDraw(); - needEndDraw = true; - } - - if (!loaded) { - // Draws any remaining geometry in case the user is still not - // setting/getting new pixels. - flush(); - } - - allocatePixels(); - - if (!loaded) { - readPixels(); - } - - // Pixels are now up-to-date, set the flag. - loaded = true; - - - if (needEndDraw) { - endDraw(); - } - } - - - protected void allocatePixels() { - updatePixelSize(); - if ((pixels == null) || (pixels.length != pixelWidth * pixelHeight)) { - pixels = new int[pixelWidth * pixelHeight]; - pixelBuffer = PGL.allocateIntBuffer(pixels); - loaded = false; - } - } - - - protected void readPixels() { - updatePixelSize(); - beginPixelsOp(OP_READ); - try { - // The readPixelsImpl() call in inside a try/catch block because it appears - // that (only sometimes) JOGL will run beginDraw/endDraw on the EDT - // thread instead of the Animation thread right after a resize. Because - // of this the width and height might have a different size than the - // one of the pixels arrays. - pgl.readPixelsImpl(0, 0, pixelWidth, pixelHeight, PGL.RGBA, PGL.UNSIGNED_BYTE, - pixelBuffer); - } catch (IndexOutOfBoundsException e) { - // Silently catch the exception. - } - endPixelsOp(); - try { - // Idem... - PGL.getIntArray(pixelBuffer, pixels); - PGL.nativeToJavaARGB(pixels, pixelWidth, pixelHeight); - } catch (ArrayIndexOutOfBoundsException e) { - } - } - - - protected void drawPixels(int x, int y, int w, int h) { - drawPixels(pixels, x, y, w, h); - } - - - protected void drawPixels(int[] pixBuffer, int x, int y, int w, int h) { - int f = (int)pgl.getPixelScale(); - int len = f * w * f * h; - if (nativePixels == null || nativePixels.length < len) { - nativePixels = new int[len]; - nativePixelBuffer = PGL.allocateIntBuffer(nativePixels); - } - - try { - if (0 < x || 0 < y || w < width || h < height) { - // The pixels to be copied to the texture need to be consecutive, and - // they are not in the pixels array, so putting each row one after - // another in nativePixels. - int offset0 = f * (y * width + x); - int offset1 = 0; - - for (int yc = f * y; yc < f * (y + h); yc++) { - System.arraycopy(pixBuffer, offset0, nativePixels, offset1, f * w); - offset0 += f * width; - offset1 += f * w; - } - } else { - PApplet.arrayCopy(pixBuffer, 0, nativePixels, 0, len); - } - PGL.javaToNativeARGB(nativePixels, f * w, f * h); - } catch (ArrayIndexOutOfBoundsException e) { - } - PGL.putIntArray(nativePixelBuffer, nativePixels); - // Copying pixel buffer to screen texture... - if (primaryGraphics && !pgl.isFBOBacked()) { - // First making sure that the screen texture is valid. Only in the case - // of non-FBO-backed primary surface we might need to create the texture. - loadTextureImpl(POINT, false); - } - - boolean needToDrawTex = primaryGraphics && (!pgl.isFBOBacked() || - (pgl.isFBOBacked() && pgl.isMultisampled())) || - offscreenMultisample; - if (texture == null) return; - if (needToDrawTex) { - // The texture to screen needs to be drawn only if we are on the primary - // surface w/out FBO-layer, or with FBO-layer and multisampling. Or, we - // are doing multisampled offscreen. Why? Because in the case of - // non-multisampled FBO, texture is actually the color buffer used by the - // color FBO, so with the copy operation we should be done updating the - // (off)screen buffer. - // First, copy the pixels to the texture. We don't need to invert the - // pixel copy because the texture will be drawn inverted. - int tw = PApplet.min(texture.glWidth - f * x, f * w); - int th = PApplet.min(texture.glHeight - f * y, f * h); - pgl.copyToTexture(texture.glTarget, texture.glFormat, texture.glName, - f * x, f * y, tw, th, nativePixelBuffer); - beginPixelsOp(OP_WRITE); - drawTexture(x, y, w, h); - endPixelsOp(); - } else { - // We only need to copy the pixels to the back texture where we are - // currently drawing to. Because the texture is inverted along Y, we - // need to reflect that in the vertical arguments. - pgl.copyToTexture(texture.glTarget, texture.glFormat, texture.glName, - f * x, f * (height - (y + h)), f * w, f * h, nativePixelBuffer); - } - } - - - @Override - protected void clearState() { - super.clearState(); - if (restoreFilename != null) { - File cacheFile = new File(restoreFilename); - cacheFile.delete(); - } - } - - - @Override - protected void saveState() { - super.saveState(); - - // Queue the pixel read operation so it is performed when the surface is ready - pgl.queueEvent(new Runnable() { - @Override - public void run() { - Context context = parent.getContext(); - if (context == null || parent.getSurface().getComponent().isService()) return; - try { - restoreWidth = pixelWidth; - restoreHeight = pixelHeight; - - int[] restorePixels = new int[restoreWidth * restoreHeight]; - IntBuffer buf = IntBuffer.wrap(restorePixels); - buf.position(0); - beginPixelsOp(OP_READ); - pgl.readPixelsImpl(0, 0, pixelWidth, pixelHeight, PGL.RGBA, PGL.UNSIGNED_BYTE, buf); - endPixelsOp(); - - // Tries to use external but if not mounted, falls back on internal storage, as shown in - // https://developer.android.com/topic/performance/graphics/cache-bitmap#java - File cacheDir = Environment.MEDIA_MOUNTED == Environment.getExternalStorageState() || !isExternalStorageRemovable() ? - context.getExternalCacheDir() : context.getCacheDir(); - File cacheFile = new File(cacheDir + File.separator + "restore_pixels"); - restoreFilename = cacheFile.getAbsolutePath(); - - FileOutputStream stream = new FileOutputStream(cacheFile); - ObjectOutputStream dout = new ObjectOutputStream(stream); - dout.writeObject(restorePixels); - dout.flush(); - stream.getFD().sync(); - stream.close(); - } catch (Exception ex) { - PGraphics.showWarning("Could not save screen contents to cache"); - ex.printStackTrace(); - } - } - }); - } - - - @Override - protected void restoreSurface() { - if (changed) { - changed = false; - if (restoreFilename != null && restoreWidth == pixelWidth && restoreHeight == pixelHeight) { - // Set restore count to 2 so it draws the bitmap two frames after surface change, otherwise - // the restoration does not work because the OpenGL renderer sometimes resizes the surface - // twice after restoring the app to the foreground... this may be due to broken graphics - // drivers, hacks in the GLSurfaceView class from the Replica Island game point to that, - // although those seem to be quite old: - // https://gamedev.stackexchange.com/questions/12629/workaround-to-losing-the-opengl-context-when-android-pauses - // "It fails in a very specific case: when the EGL context is lost due to resource constraints, - // and then recreated, if GL commands are sent within two frames of the surface being created - // then eglSwapBuffers() will hang." - // However, the same number showing up makes me thing this issue continue to exist to this day. - restoreCount = 2; - } - } else if (restoreCount > 0) { - restoreCount--; - if (restoreCount == 0) { - Context context = parent.getContext(); - if (context == null) return; - try { - // Load cached pixels and draw - File cacheFile = new File(restoreFilename); - FileInputStream inStream = new FileInputStream(cacheFile); - ObjectInputStream din = new ObjectInputStream(inStream); - int[] restorePixels = (int[]) din.readObject(); - if (restorePixels.length == pixelWidth * pixelHeight) { - PGL.nativeToJavaARGB(restorePixels, pixelWidth, pixelHeight); - drawPixels(restorePixels, 0, 0, pixelWidth, pixelHeight); - } - inStream.close(); - cacheFile.delete(); - } catch (Exception ex) { - PGraphics.showWarning("Could not restore screen contents from cache"); - ex.printStackTrace(); - } finally { - restoreFilename = null; - restoreWidth = -1; - restoreHeight = -1; - restoredSurface = true; - } - } - } - super.restoreSurface(); - } - - - @Override - protected boolean requestNoLoop() { - return true; - } - - ////////////////////////////////////////////////////////////// - - // GET/SET PIXELS - - - @Override - public int get(int x, int y) { - loadPixels(); - return super.get(x, y); - } - - - @Override - protected void getImpl(int sourceX, int sourceY, - int sourceWidth, int sourceHeight, - PImage target, int targetX, int targetY) { - loadPixels(); - super.getImpl(sourceX, sourceY, sourceWidth, sourceHeight, - target, targetX, targetY); - } - - - @Override - public void set(int x, int y, int argb) { - loadPixels(); - super.set(x, y, argb); - } - - - @Override - protected void setImpl(PImage sourceImage, - int sourceX, int sourceY, - int sourceWidth, int sourceHeight, - int targetX, int targetY) { - updatePixelSize(); - - if (sourceImage.pixels == null) { - // Copies the pixels - loadPixels(); - sourceImage.loadPixels(); - int sourceOffset = sourceY * sourceImage.pixelWidth + sourceX; - int targetOffset = targetY * pixelWidth + targetX; - for (int y = sourceY; y < sourceY + sourceHeight; y++) { - System.arraycopy(sourceImage.pixels, sourceOffset, pixels, targetOffset, sourceWidth); - sourceOffset += sourceImage.pixelWidth; - targetOffset += pixelWidth; - } - } - - // Draws the texture, copy() is very efficient because it simply renders - // the texture cache of sourceImage using OpenGL. - copy(sourceImage, - sourceX, sourceY, sourceWidth, sourceHeight, - targetX, targetY, sourceWidth, sourceHeight); - } - - - ////////////////////////////////////////////////////////////// - - // SAVE - - - @Override - public boolean save(String filename) { - return saveImpl(filename); - } - - - @Override - protected void processImageBeforeAsyncSave(PImage image) { - if (image.format == AsyncPixelReader.OPENGL_NATIVE) { - PGL.nativeToJavaARGB(image.pixels, image.width, image.height); - image.format = ARGB; - } else if (image.format == AsyncPixelReader.OPENGL_NATIVE_OPAQUE) { - PGL.nativeToJavaRGB(image.pixels, image.width, image.height); - image.format = RGB; - } - } - - - protected static void completeFinishedPixelTransfers() { - ongoingPixelTransfersIterable.addAll(ongoingPixelTransfers); - for (PGraphicsOpenGL.AsyncPixelReader pixelReader : - ongoingPixelTransfersIterable) { - // if the getter was not called this frame, - // tell it to check for completed transfers now - if (!pixelReader.calledThisFrame) { - pixelReader.completeFinishedTransfers(); - } - pixelReader.calledThisFrame = false; - } - ongoingPixelTransfersIterable.clear(); - } - - protected static void completeAllPixelTransfers() { - ongoingPixelTransfersIterable.addAll(ongoingPixelTransfers); - for (PGraphicsOpenGL.AsyncPixelReader pixelReader : - ongoingPixelTransfersIterable) { - pixelReader.completeAllTransfers(); - } - ongoingPixelTransfersIterable.clear(); - } - - - protected class AsyncPixelReader { - - // PImage formats used internally to offload - // color format conversion to save threads - static final int OPENGL_NATIVE = -1; - static final int OPENGL_NATIVE_OPAQUE = -2; - - static final int BUFFER_COUNT = 3; - - int[] pbos; - long[] fences; - String[] filenames; - int[] widths; - int[] heights; - - int head; - int tail; - int size; - - boolean supportsAsyncTransfers; - - boolean calledThisFrame; - - - /// PGRAPHICS API ////////////////////////////////////////////////////////// - - public AsyncPixelReader() { - supportsAsyncTransfers = pgl.hasPBOs() && pgl.hasSynchronization(); - if (supportsAsyncTransfers) { - pbos = new int[BUFFER_COUNT]; - fences = new long[BUFFER_COUNT]; - filenames = new String[BUFFER_COUNT]; - widths = new int[BUFFER_COUNT]; - heights = new int[BUFFER_COUNT]; - - IntBuffer intBuffer = PGL.allocateIntBuffer(BUFFER_COUNT); - intBuffer.rewind(); - pgl.genBuffers(BUFFER_COUNT, intBuffer); - for (int i = 0; i < BUFFER_COUNT; i++) { - pbos[i] = intBuffer.get(i); - } - } - } - - - public void dispose() { - if (fences != null) { - while (size > 0) { - pgl.deleteSync(fences[tail]); - size--; - tail = (tail + 1) % BUFFER_COUNT; - } - fences = null; - } - if (pbos != null) { - for (int i = 0; i < BUFFER_COUNT; i++) { - IntBuffer intBuffer = PGL.allocateIntBuffer(pbos); - pgl.deleteBuffers(BUFFER_COUNT, intBuffer); - } - pbos = null; - } - filenames = null; - widths = null; - heights = null; - size = 0; - head = 0; - tail = 0; - calledThisFrame = false; - ongoingPixelTransfers.remove(this); - } - - - public void readAndSaveAsync(final String filename) { - if (size > 0) { - boolean shouldRead = (size == BUFFER_COUNT); - if (!shouldRead) shouldRead = isLastTransferComplete(); - if (shouldRead) endTransfer(); - } else { - ongoingPixelTransfers.add(this); - } - beginTransfer(filename); - calledThisFrame = true; - } - - - public void completeFinishedTransfers() { - if (size <= 0 || !asyncImageSaver.hasAvailableTarget()) return; - - boolean needEndDraw = false; - if (!drawing) { - beginDraw(); - needEndDraw = true; - } - - while (asyncImageSaver.hasAvailableTarget() && - isLastTransferComplete()) { - endTransfer(); - } - - // make sure to always unregister if there are no ongoing transfers - // so that PGraphics can be GC'd if needed - if (size <= 0) ongoingPixelTransfers.remove(this); - - if (needEndDraw) endDraw(); - } - - - protected void completeAllTransfers() { - if (size <= 0) return; - - boolean needEndDraw = false; - if (!drawing) { - beginDraw(); - needEndDraw = true; - } - - while (size > 0) { - endTransfer(); - } - - // make sure to always unregister if there are no ongoing transfers - // so that PGraphics can be GC'd if needed - ongoingPixelTransfers.remove(this); - - if (needEndDraw) endDraw(); - } - - - /// TRANSFERS ////////////////////////////////////////////////////////////// - - public boolean isLastTransferComplete() { - if (size <= 0) return false; - int status = pgl.clientWaitSync(fences[tail], 0, 0); - return (status == PGL.ALREADY_SIGNALED) || - (status == PGL.CONDITION_SATISFIED); - } - - - public void beginTransfer(String filename) { - // check the size of the buffer - if (widths[head] != pixelWidth || heights[head] != pixelHeight) { - if (widths[head] * heights[head] != pixelWidth * pixelHeight) { - pgl.bindBuffer(PGL.PIXEL_PACK_BUFFER, pbos[head]); - pgl.bufferData(PGL.PIXEL_PACK_BUFFER, - Integer.SIZE/8 * pixelWidth * pixelHeight, - null, PGL.STREAM_READ); - } - widths[head] = pixelWidth; - heights[head] = pixelHeight; - pgl.bindBuffer(PGL.PIXEL_PACK_BUFFER, 0); - } - - pgl.bindBuffer(PGL.PIXEL_PACK_BUFFER, pbos[head]); - pgl.readPixels(0, 0, pixelWidth, pixelHeight, PGL.RGBA, PGL.UNSIGNED_BYTE, 0); - pgl.bindBuffer(PGL.PIXEL_PACK_BUFFER, 0); - - fences[head] = pgl.fenceSync(PGL.SYNC_GPU_COMMANDS_COMPLETE, 0); - filenames[head] = filename; - - head = (head + 1) % BUFFER_COUNT; - size++; - } - - - public void endTransfer() { - pgl.deleteSync(fences[tail]); - pgl.bindBuffer(PGL.PIXEL_PACK_BUFFER, pbos[tail]); - ByteBuffer readBuffer = pgl.mapBuffer(PGL.PIXEL_PACK_BUFFER, - PGL.READ_ONLY); - if (readBuffer != null) { - int format = primaryGraphics ? OPENGL_NATIVE_OPAQUE : OPENGL_NATIVE; - PImage target = asyncImageSaver.getAvailableTarget(widths[tail], - heights[tail], - format); - if (target == null) return; - readBuffer.rewind(); - readBuffer.asIntBuffer().get(target.pixels); - pgl.unmapBuffer(PGL.PIXEL_PACK_BUFFER); - asyncImageSaver.saveTargetAsync(PGraphicsOpenGL.this, target, - filenames[tail]); - } - - pgl.bindBuffer(PGL.PIXEL_PACK_BUFFER, 0); - - size--; - tail = (tail + 1) % BUFFER_COUNT; - } - - } - - - ////////////////////////////////////////////////////////////// - - // LOAD/UPDATE TEXTURE - - - // Loads the current contents of the renderer's drawing surface into the - // its texture. - public void loadTexture() { - boolean needEndDraw = false; - if (!drawing) { - beginDraw(); - needEndDraw = true; - } - - flush(); // To make sure the color buffer is updated. - - if (primaryGraphics) { - updatePixelSize(); - - if (pgl.isFBOBacked()) { - // In the case of MSAA, this is needed so the back buffer is in sync - // with the rendering. - pgl.syncBackTexture(); - } else { - loadTextureImpl(Texture.POINT, false); - - // Here we go the slow route: we first copy the contents of the color - // buffer into a pixels array (but we keep it in native format) and - // then copy this array into the texture. - if (nativePixels == null || nativePixels.length < pixelWidth * pixelHeight) { - nativePixels = new int[pixelWidth * pixelHeight]; - nativePixelBuffer = PGL.allocateIntBuffer(nativePixels); - } - - beginPixelsOp(OP_READ); - try { - // See comments in readPixels() for the reason for this try/catch. - pgl.readPixelsImpl(0, 0, pixelWidth, pixelHeight, PGL.RGBA, PGL.UNSIGNED_BYTE, - nativePixelBuffer); - } catch (IndexOutOfBoundsException e) { - } - endPixelsOp(); - - if (texture != null) { - texture.setNative(nativePixelBuffer, 0, 0, pixelWidth, pixelHeight); - } - } - } else if (offscreenMultisample) { - // We need to copy the contents of the multisampled buffer to the color - // buffer, so the later is up-to-date with the last drawing. - FrameBuffer ofb = offscreenFramebuffer; - FrameBuffer mfb = multisampleFramebuffer; - if (ofb != null && mfb != null) { - mfb.copyColor(ofb); - } - } - - if (needEndDraw) { - endDraw(); - } - } - - - // Just marks the whole texture as updated - public void updateTexture() { - if (texture != null) { - texture.updateTexels(); - } - } - - - // Marks the specified rectanglular subregion in the texture as - // updated. - public void updateTexture(int x, int y, int w, int h) { - if (texture != null) { - texture.updateTexels(x, y, w, h); - } - } - - - // Draws wherever it is in the screen texture right now to the display. - public void updateDisplay() { - flush(); - beginPixelsOp(OP_WRITE); - drawTexture(); - endPixelsOp(); - } - - - protected void loadTextureImpl(int sampling, boolean mipmap) { - updatePixelSize(); - if (pixelWidth == 0 || pixelHeight == 0) return; - if (texture == null || texture.contextIsOutdated()) { - Texture.Parameters params = new Texture.Parameters(ARGB, - sampling, mipmap); - texture = new Texture(this, pixelWidth, pixelHeight, params); - texture.invertedY(!cameraUp); - texture.colorBuffer(true); - setCache(this, texture); - } - } - - - protected void createPTexture() { - updatePixelSize(); - if (texture != null) { - ptexture = new Texture(this, pixelWidth, pixelHeight, texture.getParameters()); - ptexture.invertedY(!cameraUp); - ptexture.colorBuffer(true); - } - } - - - protected void swapOffscreenTextures() { - FrameBuffer ofb = offscreenFramebuffer; - if (texture != null && ptexture != null && ofb != null) { - int temp = texture.glName; - texture.glName = ptexture.glName; - ptexture.glName = temp; - ofb.setColorBuffer(texture); - } - } - - - protected void drawTexture() { - if (texture != null) { - // No blend so the texure replaces wherever is on the screen, - // irrespective of the alpha - pgl.disable(PGL.BLEND); - pgl.drawTexture(texture.glTarget, texture.glName, - texture.glWidth, texture.glHeight, - 0, 0, width, height); - pgl.enable(PGL.BLEND); - } - } - - - protected void drawTexture(int x, int y, int w, int h) { - if (texture != null) { - // Processing Y axis is inverted with respect to OpenGL, so we need to - // invert the y coordinates of the screen rectangle. - pgl.disable(PGL.BLEND); - pgl.drawTexture(texture.glTarget, texture.glName, - texture.glWidth, texture.glHeight, - 0, 0, width, height, - x, y, x + w, y + h, - x, height - (y + h), x + w, height - y); - pgl.enable(PGL.BLEND); - } - } - - - protected void drawPTexture() { - if (ptexture != null) { - // No blend so the texure replaces wherever is on the screen, - // irrespective of the alpha - pgl.disable(PGL.BLEND); - pgl.drawTexture(ptexture.glTarget, ptexture.glName, - ptexture.glWidth, ptexture.glHeight, - 0, 0, width, height); - pgl.enable(PGL.BLEND); - } - } - - - ////////////////////////////////////////////////////////////// - - // MASK - - -// @Override -// public void mask(int alpha[]) { -// PImage temp = get(); -// temp.mask(alpha); -// set(0, 0, temp); -// } - - - @Override - public void mask(PImage alpha) { - updatePixelSize(); - if (alpha.width != pixelWidth || alpha.height != pixelHeight) { - throw new RuntimeException("The PImage used with mask() must be " + - "the same size as the applet."); - } - - PGraphicsOpenGL ppg = getPrimaryPG(); - if (ppg.maskShader == null) { - ppg.maskShader = new PShader(parent, defTextureShaderVertURL, - maskShaderFragURL); - } - ppg.maskShader.set("mask", alpha); - filter(ppg.maskShader); - } - - - - ////////////////////////////////////////////////////////////// - - // FILTER - - - /** - * This is really inefficient and not a good idea in OpenGL. Use get() and - * set() with a smaller image area, or call the filter on an image instead, - * and then draw that. - */ - @Override - public void filter(int kind) { - PImage temp = get(); - temp.filter(kind); - set(0, 0, temp); - } - - - /** - * This is really inefficient and not a good idea in OpenGL. Use get() and - * set() with a smaller image area, or call the filter on an image instead, - * and then draw that. - */ - @Override - public void filter(int kind, float param) { - PImage temp = get(); - temp.filter(kind, param); - set(0, 0, temp); - } - - - @Override - public void filter(PShader shader) { - if (!shader.isPolyShader()) { - PGraphics.showWarning(INVALID_FILTER_SHADER_ERROR); - return; - } - - boolean needEndDraw = false; - if (primaryGraphics) { - pgl.enableFBOLayer(); - } else if (!drawing) { - beginDraw(); - needEndDraw = true; - } - loadTexture(); - - if (filterTexture == null || filterTexture.contextIsOutdated()) { - filterTexture = new Texture(this, texture.width, texture.height, - texture.getParameters()); - filterTexture.invertedY(!cameraUp); - filterImage = wrapTexture(filterTexture); - } - filterTexture.set(texture); - - // Disable writing to the depth buffer, so that after applying the filter we - // can still use the depth information to keep adding geometry to the scene. - pgl.depthMask(false); - // Also disabling depth testing so the texture is drawn on top of everything - // that has been drawn before. - pgl.disable(PGL.DEPTH_TEST); - - // Drawing a textured quad in 2D, covering the entire screen, - // with the filter shader applied to it: - begin2D(); - - // Changing light configuration and shader after begin2D() - // because it calls flush(). - boolean prevLights = lights; - lights = false; - int prevTextureMode = textureMode; - textureMode = NORMAL; - boolean prevStroke = stroke; - stroke = false; - int prevBlendMode = blendMode; - blendMode(REPLACE); - PShader prevShader = polyShader; - polyShader = shader; - - beginShape(QUADS); - texture(filterImage); - vertex(0, 0, 0, 0); - vertex(width, 0, 1, 0); - vertex(width, height, 1, 1); - vertex(0, height, 0, 1); - endShape(); - end2D(); - - // Restoring previous configuration. - polyShader = prevShader; - stroke = prevStroke; - lights = prevLights; - textureMode = prevTextureMode; - blendMode(prevBlendMode); - - if (!hints[DISABLE_DEPTH_TEST]) { - pgl.enable(PGL.DEPTH_TEST); - } - if (!hints[DISABLE_DEPTH_MASK]) { - pgl.depthMask(true); - } - - if (needEndDraw) { - endDraw(); - } - } - - - ////////////////////////////////////////////////////////////// - - // COPY - - - @Override - public void copy(int sx, int sy, int sw, int sh, - int dx, int dy, int dw, int dh) { - if (primaryGraphics) pgl.enableFBOLayer(); - loadTexture(); - if (filterTexture == null || filterTexture.contextIsOutdated()) { - filterTexture = new Texture(this, texture.width, texture.height, texture.getParameters()); - filterTexture.invertedY(!cameraUp); - filterImage = wrapTexture(filterTexture); - } - filterTexture.put(texture, sx, height - (sy + sh), sw, height - sy); - copy(filterImage, sx, sy, sw, sh, dx, dy, dw, dh); - } - - - @Override - public void copy(PImage src, - int sx, int sy, int sw, int sh, - int dx, int dy, int dw, int dh) { - boolean needEndDraw = false; - if (!drawing) { - beginDraw(); - needEndDraw = true; - } - - flush(); // make sure that the screen contents are up to date. - - Texture tex = getTexture(src); - boolean invX = tex.invertedX(); - boolean invY = tex.invertedY(); - int scrX0, scrX1; - int scrY0, scrY1; - if (invX) { - scrX0 = (dx + dw) / src.pixelDensity; - scrX1 = dx / src.pixelDensity; - } else { - scrX0 = dx / src.pixelDensity; - scrX1 = (dx + dw) / src.pixelDensity; - } - - int texX0 = sx; - int texX1 = sx + sw; - int texY0, texY1; - if (invY) { - scrY0 = height - (dy + dh) / src.pixelDensity; - scrY1 = height - dy / src.pixelDensity; - texY0 = tex.height - (sy + sh); - texY1 = tex.height - sy; - } else { - // Because drawTexture uses bottom-to-top orientation of Y axis. - scrY0 = height - dy / src.pixelDensity; - scrY1 = height - (dy + dh) / src.pixelDensity; - texY0 = sy; - texY1 = sy + sh; - } - - pgl.drawTexture(tex.glTarget, tex.glName, tex.glWidth, tex.glHeight, - 0, 0, width, height, - texX0, texY0, texX1, texY1, - scrX0, scrY0, scrX1, scrY1); - - - if (needEndDraw) { - endDraw(); - } - } - - - ////////////////////////////////////////////////////////////// - - // BLEND - - - /** - * Allows to set custom blend modes for the entire scene, using openGL. - * Reference article about blending modes: - * http://www.pegtop.net/delphi/articles/blendmodes/ - * DIFFERENCE, HARD_LIGHT, SOFT_LIGHT, OVERLAY, DODGE, BURN modes cannot be - * implemented in fixed-function pipeline because they require - * conditional blending and non-linear blending equations. - */ - @Override - protected void blendModeImpl() { - if (blendMode != lastBlendMode) { - // Flush any geometry that uses a different blending mode. - flush(); - } - - pgl.enable(PGL.BLEND); - - if (blendMode == REPLACE) { - if (blendEqSupported) { - pgl.blendEquation(PGL.FUNC_ADD); - } - pgl.blendFunc(PGL.ONE, PGL.ZERO); - - } else if (blendMode == BLEND) { - if (blendEqSupported) { - pgl.blendEquationSeparate(PGL.FUNC_ADD, - PGL.FUNC_ADD); - } - pgl.blendFuncSeparate(PGL.SRC_ALPHA, PGL.ONE_MINUS_SRC_ALPHA, - PGL.ONE, PGL.ONE); - - } else if (blendMode == ADD) { - if (blendEqSupported) { - pgl.blendEquationSeparate(PGL.FUNC_ADD, - PGL.FUNC_ADD); - } - pgl.blendFuncSeparate(PGL.SRC_ALPHA, PGL.ONE, - PGL.ONE, PGL.ONE); - - } else if (blendMode == SUBTRACT) { - if (blendEqSupported) { - pgl.blendEquationSeparate(PGL.FUNC_REVERSE_SUBTRACT, - PGL.FUNC_ADD); - pgl.blendFuncSeparate(PGL.SRC_ALPHA, PGL.ONE, - PGL.ONE, PGL.ONE); - } else { - PGraphics.showWarning(BLEND_DRIVER_ERROR, "SUBTRACT"); - } - - } else if (blendMode == LIGHTEST) { - if (blendEqSupported) { - pgl.blendEquationSeparate(PGL.FUNC_MAX, - PGL.FUNC_ADD); - pgl.blendFuncSeparate(PGL.ONE, PGL.ONE, - PGL.ONE, PGL.ONE); - } else { - PGraphics.showWarning(BLEND_DRIVER_ERROR, "LIGHTEST"); - } - - } else if (blendMode == DARKEST) { - if (blendEqSupported) { - pgl.blendEquationSeparate(PGL.FUNC_MIN, - PGL.FUNC_ADD); - pgl.blendFuncSeparate(PGL.ONE, PGL.ONE, - PGL.ONE, PGL.ONE); - } else { - PGraphics.showWarning(BLEND_DRIVER_ERROR, "DARKEST"); - } - - } else if (blendMode == EXCLUSION) { - if (blendEqSupported) { - pgl.blendEquationSeparate(PGL.FUNC_ADD, - PGL.FUNC_ADD); - } - pgl.blendFuncSeparate(PGL.ONE_MINUS_DST_COLOR, PGL.ONE_MINUS_SRC_COLOR, - PGL.ONE, PGL.ONE); - - } else if (blendMode == MULTIPLY) { - if (blendEqSupported) { - pgl.blendEquationSeparate(PGL.FUNC_ADD, - PGL.FUNC_ADD); - } - pgl.blendFuncSeparate(PGL.ZERO, PGL.SRC_COLOR, - PGL.ONE, PGL.ONE); - - } else if (blendMode == SCREEN) { - if (blendEqSupported) { - pgl.blendEquationSeparate(PGL.FUNC_ADD, - PGL.FUNC_ADD); - } - pgl.blendFuncSeparate(PGL.ONE_MINUS_DST_COLOR, PGL.ONE, - PGL.ONE, PGL.ONE); - - } else if (blendMode == DIFFERENCE) { - PGraphics.showWarning(BLEND_RENDERER_ERROR, "DIFFERENCE"); - - } else if (blendMode == OVERLAY) { - PGraphics.showWarning(BLEND_RENDERER_ERROR, "OVERLAY"); - - } else if (blendMode == HARD_LIGHT) { - PGraphics.showWarning(BLEND_RENDERER_ERROR, "HARD_LIGHT"); - - } else if (blendMode == SOFT_LIGHT) { - PGraphics.showWarning(BLEND_RENDERER_ERROR, "SOFT_LIGHT"); - - } else if (blendMode == DODGE) { - PGraphics.showWarning(BLEND_RENDERER_ERROR, "DODGE"); - - } else if (blendMode == BURN) { - PGraphics.showWarning(BLEND_RENDERER_ERROR, "BURN"); - } - lastBlendMode = blendMode; - } - - - ////////////////////////////////////////////////////////////// - - // SAVE - - // public void save(String filename) // PImage calls loadPixels() - - - ////////////////////////////////////////////////////////////// - - // TEXTURE UTILS - - - /** - * Not an approved function, this will change or be removed in the future. - * This utility method returns the texture associated to the renderer's. - * drawing surface, making sure is updated to reflect the current contents - * off the screen (or offscreen drawing surface). - */ - public Texture getTexture() { - return getTexture(true); - } - - - /** - * Not an approved function either, don't use it. - */ - public Texture getTexture(boolean load) { - if (load) loadTexture(); - return texture; - } - - - /** - * Not an approved function, this will change or be removed in the future. - * This utility method returns the texture associated to the image. - * creating and/or updating it if needed. - * - * @param img the image to have a texture metadata associated to it - */ - public Texture getTexture(PImage img) { - Texture tex = (Texture)initCache(img); - if (tex == null) return null; - - if (img.isModified()) { - if (img.width != tex.width || img.height != tex.height) { - tex.init(img.width, img.height); - } - updateTexture(img, tex); - } - - if (tex.hasBuffers()) { - tex.bufferUpdate(); - } - - checkTexture(tex); - - return tex; - } - - - /** - * Not an approved function, test its use in libraries to grab the FB objects - * for offscreen PGraphics. - */ - public FrameBuffer getFrameBuffer() { - return getFrameBuffer(false); - } - - - public FrameBuffer getFrameBuffer(boolean multi) { - if (multi) { - return multisampleFramebuffer; - } else { - return offscreenFramebuffer; - } - } - - - protected Object initCache(PImage img) { - if (!checkGLThread()) { - return null; - } - - Texture tex = (Texture)getCache(img); - if (tex == null || tex.contextIsOutdated()) { - tex = addTexture(img); - if (tex != null) { - boolean dispose = img.pixels == null; - img.loadPixels(); - tex.set(img.pixels, img.format); - img.setModified(); - if (dispose) { - // We only used the pixels to load the image into the texture and the user did not request - // to load the pixels, so we should dispose the pixels array to avoid wasting memory - img.pixels = null; - img.loaded = false; - } - } - } - return tex; - } - - - protected void bindFrontTexture() { - if (primaryGraphics) { - pgl.bindFrontTexture(); - } else { - if (ptexture == null) { - createPTexture(); - } - ptexture.bind(); - } - } - - - protected void unbindFrontTexture() { - if (primaryGraphics) { - pgl.unbindFrontTexture(); - } else { - ptexture.unbind(); - } - } - - - /** - * This utility method creates a texture for the provided image, and adds it - * to the metadata cache of the image. - * @param img the image to have a texture metadata associated to it - */ - protected Texture addTexture(PImage img) { - Texture.Parameters params = - new Texture.Parameters(ARGB, textureSampling, - getHint(ENABLE_TEXTURE_MIPMAPS), textureWrap); - return addTexture(img, params); - } - - - protected Texture addTexture(PImage img, Texture.Parameters params) { - if (img.width == 0 || img.height == 0) { - // Cannot add textures of size 0 - return null; - } - if (img.parent == null) { - img.parent = parent; - } - Texture tex = new Texture(this, img.pixelWidth, img.pixelHeight, params); - tex.invertedY(cameraUp); // Pixels are read upside down if camera us pointing up - setCache(img, tex); - return tex; - } - - - protected void checkTexture(Texture tex) { - if (!tex.colorBuffer() && - (tex.usingMipmaps == hints[DISABLE_TEXTURE_MIPMAPS] || - tex.currentSampling() != textureSampling)) { - if (hints[DISABLE_TEXTURE_MIPMAPS]) { - tex.usingMipmaps(false, textureSampling); - } else { - tex.usingMipmaps(true, textureSampling); - } - } - - if ((tex.usingRepeat && textureWrap == CLAMP) || - (!tex.usingRepeat && textureWrap == REPEAT)) { - if (textureWrap == CLAMP) { - tex.usingRepeat(false); - } else { - tex.usingRepeat(true); - } - } - } - - - protected PImage wrapTexture(Texture tex) { - // We don't use the PImage(int width, int height, int mode) constructor to - // avoid initializing the pixels array. - PImage img = new PImage(); - img.parent = parent; - img.width = tex.width; - img.height = tex.height; - img.format = ARGB; - setCache(img, tex); - return img; - } - - - protected void updateTexture(PImage img, Texture tex) { - if (tex != null) { - if (img.isModified()) { - int x = img.getModifiedX1(); - int y = img.getModifiedY1(); - int w = img.getModifiedX2() - x; - int h = img.getModifiedY2() - y; - tex.set(img.pixels, x, y, w, h, img.format); - } - } - img.setModified(false); - } - - - protected void deleteSurfaceTextures() { - if (texture != null) { - texture.dispose(); - } - - if (ptexture != null) { - ptexture.dispose(); - } - - if (filterTexture != null) { - filterTexture.dispose(); - } - } - - - protected boolean checkGLThread() { -// if (pgl.threadIsCurrent()) { -// return true; -// } else { -// PGraphics.showWarning(OPENGL_THREAD_ERROR); -// return false; -// } - return true; - } - - - ////////////////////////////////////////////////////////////// - - // RESIZE - - - @Override - public void resize(int wide, int high) { - PGraphics.showMethodWarning("resize"); - } - - - ////////////////////////////////////////////////////////////// - - // INITIALIZATION ROUTINES - - - protected void initPrimary() { - if (initialized) return; - pgl.initSurface(smooth); - if (texture != null) { - removeCache(this); - texture = null; - ptexture = null; - } - initialized = true; - } - - - protected void beginOnscreenDraw() { - updatePixelSize(); - restoreSurface(); - pgl.beginRender(); - - if (drawFramebuffer == null) { - drawFramebuffer = new FrameBuffer(this, pixelWidth, pixelHeight, true); - } - drawFramebuffer.setFBO(pgl.getDrawFramebuffer()); - if (readFramebuffer == null) { - readFramebuffer = new FrameBuffer(this, pixelWidth, pixelHeight, true); - } - readFramebuffer.setFBO(pgl.getReadFramebuffer()); - if (currentFramebuffer == null) { - setFramebuffer(drawFramebuffer); - } - - if (pgl.isFBOBacked()) { - texture = pgl.wrapBackTexture(texture); - ptexture = pgl.wrapFrontTexture(ptexture); - } - } - - - protected void endOnscreenDraw() { - pgl.endRender(parent.sketchWindowColor()); - } - - - protected void initOffscreen() { - // Getting the context and capabilities from the main renderer. - loadTextureImpl(textureSampling, false); - - FrameBuffer ofb = offscreenFramebuffer; - FrameBuffer mfb = multisampleFramebuffer; - - // In case of re-initialization (for example, when the smooth level - // is changed), we make sure that all the OpenGL resources associated - // to the surface are released by calling delete(). - if (ofb != null) { - ofb.dispose(); - ofb = null; - } - if (mfb != null) { - mfb.dispose(); - mfb = null; - } - - boolean packed = depthBits == 24 && stencilBits == 8 && - packedDepthStencilSupported; - if (PGraphicsOpenGL.fboMultisampleSupported && 1 < PGL.smoothToSamples(smooth)) { - mfb = new FrameBuffer(this, texture.glWidth, texture.glHeight, PGL.smoothToSamples(smooth), 0, - depthBits, stencilBits, packed, false); - mfb.clear(); - multisampleFramebuffer = mfb; - offscreenMultisample = true; - - // The offscreen framebuffer where the multisampled image is finally drawn - // to. If depth reading is disabled it doesn't need depth and stencil buffers - // since they are part of the multisampled framebuffer. - if (hints[ENABLE_BUFFER_READING]) { - ofb = new FrameBuffer(this, texture.glWidth, texture.glHeight, 1, 1, - depthBits, stencilBits, packed, false); - } else { - ofb = new FrameBuffer(this, texture.glWidth, texture.glHeight, 1, 1, - 0, 0, false, false); - } - } else { - smooth = 0; - ofb = new FrameBuffer(this, texture.glWidth, texture.glHeight, 1, 1, - depthBits, stencilBits, packed, false); - offscreenMultisample = false; - } - ofb.setColorBuffer(texture); - ofb.clear(); - offscreenFramebuffer = ofb; - - initialized = true; - } - - - protected void beginOffscreenDraw() { - if (!initialized) { - initOffscreen(); - } else { - FrameBuffer ofb = offscreenFramebuffer; - FrameBuffer mfb = multisampleFramebuffer; - boolean outdated = ofb != null && ofb.contextIsOutdated(); - boolean outdatedMulti = mfb != null && mfb.contextIsOutdated(); - if (outdated || outdatedMulti) { - restartPGL(); - initOffscreen(); - } else { - // The back texture of the past frame becomes the front, - // and the front texture becomes the new back texture where the - // new frame is drawn to. - swapOffscreenTextures(); - } - } - - pushFramebuffer(); - if (offscreenMultisample) { - FrameBuffer mfb = multisampleFramebuffer; - if (mfb != null) { - setFramebuffer(mfb); - } - } else { - FrameBuffer ofb = offscreenFramebuffer; - if (ofb != null) { - setFramebuffer(ofb); - } - } - - // Render previous back texture (now is the front) as background - drawPTexture(); - - // Restoring the clipping configuration of the offscreen surface. - if (clip) { - pgl.enable(PGL.SCISSOR_TEST); - pgl.scissor(clipRect[0], clipRect[1], clipRect[2], clipRect[3]); - } else { - pgl.disable(PGL.SCISSOR_TEST); - } - } - - - protected void endOffscreenDraw() { - if (offscreenMultisample) { - FrameBuffer ofb = offscreenFramebuffer; - FrameBuffer mfb = multisampleFramebuffer; - if (ofb != null && mfb != null) { - mfb.copyColor(ofb); - } - } - - popFramebuffer(); - - if (backgroundA == 1) { - // Set alpha channel to opaque in order to match behavior of JAVA2D, not - // on the multisampled FBO because it leads to wrong background color - // on some Macbooks with AMD graphics. - pgl.colorMask(false, false, false, true); - pgl.clearColor(0, 0, 0, backgroundA); - pgl.clear(PGL.COLOR_BUFFER_BIT); - pgl.colorMask(true, true, true, true); - } - - if (texture != null) { - texture.updateTexels(); // Mark all texels in screen texture as modified. - } - - getPrimaryPG().restoreGL(); - } - - - protected void setViewport() { - viewport.put(0, 0); viewport.put(1, 0); - viewport.put(2, width); viewport.put(3, height); - pgl.viewport(viewport.get(0), viewport.get(1), - viewport.get(2), viewport.get(3)); - } - - - @Override - protected void checkSettings() { - super.checkSettings(); - setGLSettings(); - } - - - protected void setGLSettings() { - inGeo.clear(); - tessGeo.clear(); - texCache.clear(); - - // Each frame starts with textures disabled. - super.noTexture(); - - // Making sure that OpenGL is using the last blend mode set by the user. - blendModeImpl(); - - // this is necessary for 3D drawing - if (hints[DISABLE_DEPTH_TEST]) { - pgl.disable(PGL.DEPTH_TEST); - } else { - pgl.enable(PGL.DEPTH_TEST); - } - // use <= since that's what processing.core does - pgl.depthFunc(PGL.LEQUAL); - - if (hints[DISABLE_OPTIMIZED_STROKE]) { - flushMode = FLUSH_CONTINUOUSLY; - } else { - flushMode = FLUSH_WHEN_FULL; - } - - if (primaryGraphics) { -// pgl.getIntegerv(PGL.SAMPLES, intBuffer); -// int temp = intBuffer.get(0); -// if (smooth != temp && 1 < temp && 1 < smooth) { - // TODO check why the samples is higher that initialized smooth level. -// quality = temp; -// } - } - if (smooth < 1) { - pgl.disable(PGL.MULTISAMPLE); - } else { - // work around runtime exceptions in Broadcom's VC IV driver - if (false == OPENGL_RENDERER.equals("VideoCore IV HW")) { - pgl.enable(PGL.MULTISAMPLE); - } - } - // work around runtime exceptions in Broadcom's VC IV driver - if (false == OPENGL_RENDERER.equals("VideoCore IV HW")) { - pgl.disable(PGL.POLYGON_SMOOTH); - } - - if (sized || parent.frameCount == 0) { -// reapplySettings(); - - // To avoid having garbage in the screen after a resize, - // in the case background is not called in draw(). - if (primaryGraphics) { - background(backgroundColor); - } else { - // offscreen surfaces are transparent by default. - background(0x00 << 24 | (backgroundColor & 0xFFFFFF)); - } - - // Sets the default projection and camera (initializes modelview). - // If the user has setup up their own projection, they'll need - // to fix it after resize anyway. This helps the people who haven't - // set up their own projection. - defaultPerspective(); - defaultCamera(); - - // clear the flag - sized = false; - } else { - // Eliminating any user's transformations by going back to the - // original camera setup. - modelview.set(camera); - modelviewInv.set(cameraInv); - updateProjmodelview(); - } - - if (is3D()) { - noLights(); - lightFalloff(1, 0, 0); - lightSpecular(0, 0, 0); - } - - // The GL coordinate system is right-handed, so that facing - // polygons are CCW in window coordinates, whereas are CW - // in the left-handed system that is Processing's default (with - // its Y axis pointing down) - pgl.frontFace(cameraUp ? PGL.CCW : PGL.CW); - pgl.disable(PGL.CULL_FACE); - - // Processing uses only one texture unit. - pgl.activeTexture(PGL.TEXTURE0); - - // The current normal vector is set to be parallel to the Z axis. - normalX = normalY = 0; - normalZ = 1; - - pgl.clearDepthStencil(); - - if (hints[DISABLE_DEPTH_MASK]) { - pgl.depthMask(false); - } else { - pgl.depthMask(true); - } - - pixelsOp = OP_NONE; - - modified = false; - loaded = false; - } - - - protected void getGLParameters() { - OPENGL_VENDOR = pgl.getString(PGL.VENDOR); - OPENGL_RENDERER = pgl.getString(PGL.RENDERER); - OPENGL_VERSION = pgl.getString(PGL.VERSION); - OPENGL_EXTENSIONS = pgl.getString(PGL.EXTENSIONS); - GLSL_VERSION = pgl.getString(PGL.SHADING_LANGUAGE_VERSION); - - npotTexSupported = pgl.hasNpotTexSupport(); - autoMipmapGenSupported = pgl.hasAutoMipmapGenSupport(); - fboMultisampleSupported = pgl.hasFboMultisampleSupport(); - packedDepthStencilSupported = pgl.hasPackedDepthStencilSupport(); - anisoSamplingSupported = pgl.hasAnisoSamplingSupport(); - readBufferSupported = pgl.hasReadBuffer(); - drawBufferSupported = pgl.hasDrawBuffer(); - - try { - pgl.blendEquation(PGL.FUNC_ADD); - blendEqSupported = true; - } catch (Exception e) { - blendEqSupported = false; - } - - depthBits = pgl.getDepthBits(); - stencilBits = pgl.getStencilBits(); - - pgl.getIntegerv(PGL.MAX_TEXTURE_SIZE, intBuffer); - maxTextureSize = intBuffer.get(0); - - // work around runtime exceptions in Broadcom's VC IV driver - if (false == OPENGL_RENDERER.equals("VideoCore IV HW")) { - pgl.getIntegerv(PGL.MAX_SAMPLES, intBuffer); - maxSamples = intBuffer.get(0); - } - - if (anisoSamplingSupported) { - pgl.getFloatv(PGL.MAX_TEXTURE_MAX_ANISOTROPY, floatBuffer); - maxAnisoAmount = floatBuffer.get(0); - } - - // overwrite the default shaders with vendor specific versions - // if needed - if (OPENGL_RENDERER.equals("VideoCore IV HW") || // Broadcom's binary driver for Raspberry Pi - OPENGL_RENDERER.equals("Gallium 0.4 on VC4")) { // Mesa driver for same hardware - defLightShaderVertURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/LightVert-vc4.glsl"); - defTexlightShaderVertURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/TexLightVert-vc4.glsl"); - } - - glParamsRead = true; - } - - - ////////////////////////////////////////////////////////////// - - // SHADER HANDLING - - - @Override - public PShader loadShader(String fragFilename) { - if (fragFilename == null || fragFilename.equals("")) { - PGraphics.showWarning(MISSING_FRAGMENT_SHADER); - return null; - } - - int type = PShader.getShaderType(parent.loadStrings(fragFilename), - PShader.POLY); - PShader shader = new PShader(parent); - shader.setType(type); - shader.setFragmentShader(fragFilename); - if (type == PShader.POINT) { - String[] vertSource = pgl.loadVertexShader(defPointShaderVertURL); - shader.setVertexShader(vertSource); - } else if (type == PShader.LINE) { - String[] vertSource = pgl.loadVertexShader(defLineShaderVertURL); - shader.setVertexShader(vertSource); - } else if (type == PShader.TEXLIGHT) { - String[] vertSource = pgl.loadVertexShader(defTexlightShaderVertURL); - shader.setVertexShader(vertSource); - } else if (type == PShader.LIGHT) { - String[] vertSource = pgl.loadVertexShader(defLightShaderVertURL); - shader.setVertexShader(vertSource); - } else if (type == PShader.TEXTURE) { - String[] vertSource = pgl.loadVertexShader(defTextureShaderVertURL); - shader.setVertexShader(vertSource); - } else if (type == PShader.COLOR) { - String[] vertSource = pgl.loadVertexShader(defColorShaderVertURL); - shader.setVertexShader(vertSource); - } else { - String[] vertSource = pgl.loadVertexShader(defTextureShaderVertURL); - shader.setVertexShader(vertSource); - } - return shader; - } - - - @Override - public PShader loadShader(String fragFilename, String vertFilename) { - PShader shader = null; - if (fragFilename == null || fragFilename.equals("")) { - PGraphics.showWarning(MISSING_FRAGMENT_SHADER); - } else if (vertFilename == null || vertFilename.equals("")) { - PGraphics.showWarning(MISSING_VERTEX_SHADER); - } else { - shader = new PShader(parent, vertFilename, fragFilename); - } - return shader; - } - - - @Override - public void shader(PShader shader) { - flush(); // Flushing geometry drawn with a different shader. - - if (shader != null) shader.init(); - if (shader.isPolyShader()) polyShader = shader; - else if (shader.isLineShader()) lineShader = shader; - else if (shader.isPointShader()) pointShader = shader; - else PGraphics.showWarning(UNKNOWN_SHADER_KIND_ERROR); - } - - - @Override - public void shader(PShader shader, int kind) { - flush(); // Flushing geometry drawn with a different shader. - - if (shader != null) shader.init(); - if (kind == TRIANGLES) polyShader = shader; - else if (kind == LINES) lineShader = shader; - else if (kind == POINTS) pointShader = shader; - else PGraphics.showWarning(UNKNOWN_SHADER_KIND_ERROR); - } - - - @Override - public void resetShader() { - resetShader(TRIANGLES); - } - - - @Override - public void resetShader(int kind) { - flush(); // Flushing geometry drawn with a different shader. - - if (kind == TRIANGLES || kind == QUADS || kind == POLYGON) { - polyShader = null; - } else if (kind == LINES) { - lineShader = null; - } else if (kind == POINTS) { - pointShader = null; - } else { - PGraphics.showWarning(UNKNOWN_SHADER_KIND_ERROR); - } - } - - - protected PShader getPolyShader(boolean lit, boolean tex) { - PShader shader; - PGraphicsOpenGL ppg = getPrimaryPG(); - boolean useDefault = polyShader == null; - if (polyShader != null) { - updateShader(polyShader); -// polyShader.setRenderer(this); -// polyShader.loadAttributes(); -// polyShader.loadUniforms(); - } - if (lit) { - if (tex) { - if (useDefault || !isPolyShaderTexLight(polyShader)) { - if (ppg.defTexlightShader == null) { - ppg.defTexlightShader = loadShaderFromURL(defTexlightShaderFragURL, - defTexlightShaderVertURL); - } - shader = ppg.defTexlightShader; - } else { - shader = polyShader; - } - } else { - if (useDefault || !isPolyShaderLight(polyShader)) { - if (ppg.defLightShader == null) { - ppg.defLightShader = loadShaderFromURL(defLightShaderFragURL, - defLightShaderVertURL); - } - shader = ppg.defLightShader; - } else { - shader = polyShader; - } - } - } else { - if (isPolyShaderUsingLights(polyShader)) { - PGraphics.showWarning(SHADER_NEED_LIGHT_ATTRIBS); - useDefault = true; - } - - if (tex) { - if (useDefault || !isPolyShaderTex(polyShader)) { - if (ppg.defTextureShader == null) { - ppg.defTextureShader = loadShaderFromURL(defTextureShaderFragURL, - defTextureShaderVertURL); - } - shader = ppg.defTextureShader; - } else { - shader = polyShader; - } - } else { - if (useDefault || !isPolyShaderColor(polyShader)) { - if (ppg.defColorShader == null) { - ppg.defColorShader = loadShaderFromURL(defColorShaderFragURL, - defColorShaderVertURL); - } - shader = ppg.defColorShader; - } else { - shader = polyShader; - } - } - } - if (shader != polyShader) { - updateShader(shader); - } - updateShader(shader); - return shader; - } - - - protected void updateShader(PShader shader) { - shader.setRenderer(this); - shader.loadAttributes(); - shader.loadUniforms(); - } - - - protected PShader loadShaderFromURL(URL fragURL, URL vertURL) { - String[] vertSource = pgl.loadVertexShader(vertURL); - String[] fragSource = pgl.loadFragmentShader(fragURL); - return new PShader(parent, vertSource, fragSource); - } - - - protected boolean isPolyShaderTexLight(PShader shader) { - return shader.checkPolyType(PShader.TEXLIGHT); - } - - - protected boolean isPolyShaderLight(PShader shader) { - return shader.checkPolyType(PShader.LIGHT); - } - - - protected boolean isPolyShaderTex(PShader shader) { - return shader.checkPolyType(PShader.TEXTURE); - } - - - protected boolean isPolyShaderColor(PShader shader) { - return shader.checkPolyType(PShader.COLOR); - } - - - protected boolean isPolyShaderUsingLights(PShader shader) { - return shader != null && shader.accessLightAttribs(); - } - - - protected PShader getLineShader() { - PShader shader; - PGraphicsOpenGL ppg = getPrimaryPG(); - if (lineShader == null) { - if (ppg.defLineShader == null) { - String[] vertSource = pgl.loadVertexShader(defLineShaderVertURL); - String[] fragSource = pgl.loadFragmentShader(defLineShaderFragURL); - ppg.defLineShader = new PShader(parent, vertSource, fragSource); - } - shader = ppg.defLineShader; - } else { - shader = lineShader; - } - shader.setRenderer(this); - shader.loadAttributes(); - shader.loadUniforms(); - return shader; - } - - - protected PShader getPointShader() { - PShader shader; - PGraphicsOpenGL ppg = getPrimaryPG(); - if (pointShader == null) { - if (ppg.defPointShader == null) { - String[] vertSource = pgl.loadVertexShader(defPointShaderVertURL); - String[] fragSource = pgl.loadFragmentShader(defPointShaderFragURL); - ppg.defPointShader = new PShader(parent, vertSource, fragSource); - } - shader = ppg.defPointShader; - } else { - shader = pointShader; - } - shader.setRenderer(this); - shader.loadAttributes(); - shader.loadUniforms(); - return shader; - } - - - ////////////////////////////////////////////////////////////// - - // Utils - - static protected int expandArraySize(int currSize, int newMinSize) { - int newSize = currSize; - while (newSize < newMinSize) { - newSize <<= 1; - } - return newSize; - } - - ////////////////////////////////////////////////////////////// - - // Generic vertex attributes. - - - static protected AttributeMap newAttributeMap() { - return new AttributeMap(); - } - - - static protected class AttributeMap extends HashMap { - public ArrayList names = new ArrayList(); - public int numComp = 0; // number of components for a single vertex - - @Override - public VertexAttribute put(String key, VertexAttribute value) { - VertexAttribute prev = super.put(key, value); - names.add(key); - if (value.kind == VertexAttribute.COLOR) numComp += 4; - else numComp += value.size; - return prev; - } - - public VertexAttribute get(int i) { - return super.get(names.get(i)); - } - } - - - static protected class VertexAttribute { - static final int POSITION = 0; - static final int NORMAL = 1; - static final int COLOR = 2; - static final int OTHER = 3; - - PGraphicsOpenGL pg; - String name; - int kind; // POSITION, NORMAL, COLOR, OTHER - int type; // GL_INT, GL_FLOAT, GL_BOOL - int size; // number of elements (1, 2, 3, or 4) - int tessSize; - int elementSize; - VertexBuffer buf; - int glLoc; - - float[] fvalues; - int[] ivalues; - byte[] bvalues; - - // For use in PShape - boolean modified; - int firstModified; - int lastModified; - boolean active; - - VertexAttribute(PGraphicsOpenGL pg, String name, int kind, int type, int size) { - this.pg = pg; - this.name = name; - this.kind = kind; - this.type = type; - this.size = size; - - if (kind == POSITION) { - tessSize = 4; // for w - } else { - tessSize = size; - } - - if (type == PGL.FLOAT) { - elementSize = PGL.SIZEOF_FLOAT; - fvalues = new float[size]; - } else if (type == PGL.INT) { - elementSize = PGL.SIZEOF_INT; - ivalues = new int[size]; - } else if (type == PGL.BOOL) { - elementSize = PGL.SIZEOF_INT; - bvalues = new byte[size]; - } - - buf = null; - glLoc = -1; - - modified = false; - firstModified = PConstants.MAX_INT; - lastModified = PConstants.MIN_INT; - - active = true; - } - - public boolean diff(VertexAttribute attr) { - return !name.equals(attr.name) || - kind != attr.kind || - type != attr.type || - size != attr.size || - tessSize != attr.tessSize || - elementSize != attr.elementSize; - } - - boolean isPosition() { - return kind == POSITION; - } - - boolean isNormal() { - return kind == NORMAL; - } - - boolean isColor() { - return kind == COLOR; - } - - boolean isOther() { - return kind == OTHER; - } - - boolean isFloat() { - return type == PGL.FLOAT; - } - - boolean isInt() { - return type == PGL.INT; - } - - boolean isBool() { - return type == PGL.BOOL; - } - - boolean bufferCreated() { - return buf != null && 0 < buf.glId; - } - - void createBuffer(PGL pgl) { - buf = new VertexBuffer(pg, PGL.ARRAY_BUFFER, size, elementSize, false); - } - - void deleteBuffer(PGL pgl) { - if (buf.glId != 0) { - intBuffer.put(0, buf.glId); - if (pgl.threadIsCurrent()) pgl.deleteBuffers(1, intBuffer); - } - } - - void bind(PGL pgl) { - pgl.enableVertexAttribArray(glLoc); - } - - void unbind(PGL pgl) { - pgl.disableVertexAttribArray(glLoc); - } - - boolean active(PShader shader) { - if (active) { - if (glLoc == -1) { - glLoc = shader.getAttributeLoc(name); - if (glLoc == -1) active = false; - } - } - return active; - } - - int sizeInBytes(int length) { - return length * tessSize * elementSize; - } - - void set(float x, float y, float z) { - fvalues[0] = x; - fvalues[1] = y; - fvalues[2] = z; - } - - void set(int c) { - ivalues[0] = c; - } - - void set(float[] values) { - PApplet.arrayCopy(values, 0, fvalues, 0, size); - } - - void set(int[] values) { - PApplet.arrayCopy(values, 0, ivalues, 0, size); - } - - void set(boolean[] values) { - for (int i = 0; i < values.length; i++) { - bvalues[i] = (byte)(values[i] ? 1 : 0); - } - } - - void add(float[] dstValues, int dstIdx) { - PApplet.arrayCopy(fvalues, 0, dstValues, dstIdx, size); - } - - void add(int[] dstValues, int dstIdx) { - PApplet.arrayCopy(ivalues, 0, dstValues, dstIdx, size); - } - - void add(byte[] dstValues, int dstIdx) { - PApplet.arrayCopy(bvalues, 0, dstValues, dstIdx, size); - } - } - - - ////////////////////////////////////////////////////////////// - - // Input (raw) and Tessellated geometry, tessellator. - - - static protected InGeometry newInGeometry(PGraphicsOpenGL pg, AttributeMap attr, - int mode) { - return new InGeometry(pg, attr, mode); - } - - - static protected TessGeometry newTessGeometry(PGraphicsOpenGL pg, - AttributeMap attr, int mode) { - return new TessGeometry(pg, attr, mode); - } - - - static protected TexCache newTexCache(PGraphicsOpenGL pg) { - return new TexCache(pg); - } - - - // Holds an array of textures and the range of vertex - // indices each texture applies to. - static protected class TexCache { - PGraphicsOpenGL pg; - int size; - PImage[] textures; - int[] firstIndex; - int[] lastIndex; - int[] firstCache; - int[] lastCache; - boolean hasTextures; - - TexCache(PGraphicsOpenGL pg) { - this.pg = pg; - allocate(); - } - - void allocate() { - textures = new PImage[PGL.DEFAULT_IN_TEXTURES]; - firstIndex = new int[PGL.DEFAULT_IN_TEXTURES]; - lastIndex = new int[PGL.DEFAULT_IN_TEXTURES]; - firstCache = new int[PGL.DEFAULT_IN_TEXTURES]; - lastCache = new int[PGL.DEFAULT_IN_TEXTURES]; - size = 0; - hasTextures = false; - } - - void clear() { - java.util.Arrays.fill(textures, 0, size, null); - size = 0; - hasTextures = false; - } - - boolean containsTexture(PImage img) { - for (int i = 0; i < size; i++) { - if (textures[i] == img) return true; - } - return false; - } - - PImage getTextureImage(int i) { - return textures[i]; - } - - Texture getTexture(int i) { - PImage img = textures[i]; - Texture tex = null; - - if (img != null) { - tex = pg.getTexture(img); - } - - return tex; - } - - void addTexture(PImage img, int firsti, int firstb, int lasti, int lastb) { - arrayCheck(); - - textures[size] = img; - firstIndex[size] = firsti; - lastIndex[size] = lasti; - firstCache[size] = firstb; - lastCache[size] = lastb; - - // At least one non-null texture since last reset. - hasTextures |= img != null; - - size++; - } - - void setLastIndex(int lasti, int lastb) { - lastIndex[size - 1] = lasti; - lastCache[size - 1] = lastb; - } - - void arrayCheck() { - if (size == textures.length) { - int newSize = size << 1; - - expandTextures(newSize); - expandFirstIndex(newSize); - expandLastIndex(newSize); - expandFirstCache(newSize); - expandLastCache(newSize); - } - } - - void expandTextures(int n) { - PImage[] temp = new PImage[n]; - PApplet.arrayCopy(textures, 0, temp, 0, size); - textures = temp; - } - - void expandFirstIndex(int n) { - int[] temp = new int[n]; - PApplet.arrayCopy(firstIndex, 0, temp, 0, size); - firstIndex = temp; - } - - void expandLastIndex(int n) { - int[] temp = new int[n]; - PApplet.arrayCopy(lastIndex, 0, temp, 0, size); - lastIndex = temp; - } - - void expandFirstCache(int n) { - int[] temp = new int[n]; - PApplet.arrayCopy(firstCache, 0, temp, 0, size); - firstCache = temp; - } - - void expandLastCache(int n) { - int[] temp = new int[n]; - PApplet.arrayCopy(lastCache, 0, temp, 0, size); - lastCache = temp; - } - } - - - // Stores the offsets and counts of indices and vertices - // to render a piece of geometry that doesn't fit in a single - // glDrawElements() call. - static protected class IndexCache { - int size; - int[] indexCount; - int[] indexOffset; - int[] vertexCount; - int[] vertexOffset; - int[] counter; - - IndexCache() { - allocate(); - } - - void allocate() { - size = 0; - indexCount = new int[2]; - indexOffset = new int[2]; - vertexCount = new int[2]; - vertexOffset = new int[2]; - counter = null; - } - - void clear() { - size = 0; - } - - int addNew() { - arrayCheck(); - init(size); - size++; - return size - 1; - } - - int addNew(int index) { - arrayCheck(); - indexCount[size] = indexCount[index]; - indexOffset[size] = indexOffset[index]; - vertexCount[size] = vertexCount[index]; - vertexOffset[size] = vertexOffset[index]; - size++; - return size - 1; - } - - int getLast() { - if (size == 0) { - arrayCheck(); - init(0); - size = 1; - } - return size - 1; - } - - void setCounter(int[] counter) { - this.counter = counter; - } - - void incCounts(int index, int icount, int vcount) { - indexCount[index] += icount; - vertexCount[index] += vcount; - if (counter != null) { - counter[0] += icount; - counter[1] += vcount; - } - } - - void init(int n) { - if (0 < n) { - indexOffset[n] = indexOffset[n - 1] + indexCount[n - 1]; - vertexOffset[n] = vertexOffset[n - 1] + vertexCount[n - 1]; - } else { - indexOffset[n] = 0; - vertexOffset[n] = 0; - } - indexCount[n] = 0; - vertexCount[n] = 0; - } - - void arrayCheck() { - if (size == indexCount.length) { - int newSize = size << 1; - - expandIndexCount(newSize); - expandIndexOffset(newSize); - expandVertexCount(newSize); - expandVertexOffset(newSize); - } - } - - void expandIndexCount(int n) { - int[] temp = new int[n]; - PApplet.arrayCopy(indexCount, 0, temp, 0, size); - indexCount = temp; - } - - void expandIndexOffset(int n) { - int[] temp = new int[n]; - PApplet.arrayCopy(indexOffset, 0, temp, 0, size); - indexOffset = temp; - } - - void expandVertexCount(int n) { - int[] temp = new int[n]; - PApplet.arrayCopy(vertexCount, 0, temp, 0, size); - vertexCount = temp; - } - - void expandVertexOffset(int n) { - int[] temp = new int[n]; - PApplet.arrayCopy(vertexOffset, 0, temp, 0, size); - vertexOffset = temp; - } - } - - - // Holds the input vertices: xyz coordinates, fill/tint color, - // normal, texture coordinates and stroke color and weight. - static protected class InGeometry { - PGraphicsOpenGL pg; - int renderMode; - AttributeMap attribs; - - int vertexCount; - int codeCount; - int edgeCount; - - float[] vertices; - int[] colors; - float[] normals; - float[] texcoords; - int[] strokeColors; - float[] strokeWeights; - - // vertex codes - int[] codes; - - // Stroke edges - int[][] edges; - - // Material properties - int[] ambient; - int[] specular; - int[] emissive; - float[] shininess; - - // Generic attributes - HashMap fattribs; - HashMap iattribs; - HashMap battribs; - - // Internally used by the addVertex() methods. - int fillColor; - int strokeColor; - float strokeWeight; - int ambientColor; - int specularColor; - int emissiveColor; - float shininessFactor; - float normalX, normalY, normalZ; - - InGeometry(PGraphicsOpenGL pg, AttributeMap attr, int mode) { - this.pg = pg; - this.attribs = attr; - renderMode = mode; - allocate(); - } - - // ----------------------------------------------------------------- - // - // Allocate/dispose - - void clear() { - vertexCount = 0; - codeCount = 0; - edgeCount = 0; - } - - void clearEdges() { - edgeCount = 0; - } - - void allocate() { - vertices = new float[3 * PGL.DEFAULT_IN_VERTICES]; - colors = new int[PGL.DEFAULT_IN_VERTICES]; - normals = new float[3 * PGL.DEFAULT_IN_VERTICES]; - texcoords = new float[2 * PGL.DEFAULT_IN_VERTICES]; - strokeColors = new int[PGL.DEFAULT_IN_VERTICES]; - strokeWeights = new float[PGL.DEFAULT_IN_VERTICES]; - ambient = new int[PGL.DEFAULT_IN_VERTICES]; - specular = new int[PGL.DEFAULT_IN_VERTICES]; - emissive = new int[PGL.DEFAULT_IN_VERTICES]; - shininess = new float[PGL.DEFAULT_IN_VERTICES]; - edges = new int[PGL.DEFAULT_IN_EDGES][3]; - - fattribs = new HashMap(); - iattribs = new HashMap(); - battribs = new HashMap(); - - clear(); - } - - void initAttrib(VertexAttribute attrib) { - if (attrib.type == PGL.FLOAT) { - float[] temp = new float[attrib.size * PGL.DEFAULT_IN_VERTICES]; - fattribs.put(attrib.name, temp); - } else if (attrib.type == PGL.INT) { - int[] temp = new int[attrib.size * PGL.DEFAULT_IN_VERTICES]; - iattribs.put(attrib.name, temp); - } else if (attrib.type == PGL.BOOL) { - byte[] temp = new byte[attrib.size * PGL.DEFAULT_IN_VERTICES]; - battribs.put(attrib.name, temp); - } - } - - void vertexCheck() { - if (vertexCount == vertices.length / 3) { - int newSize = vertexCount << 1; - - expandVertices(newSize); - expandColors(newSize); - expandNormals(newSize); - expandTexCoords(newSize); - expandStrokeColors(newSize); - expandStrokeWeights(newSize); - expandAmbient(newSize); - expandSpecular(newSize); - expandEmissive(newSize); - expandShininess(newSize); - expandAttribs(newSize); - } - } - - void codeCheck() { - if (codeCount == codes.length) { - int newLen = codeCount << 1; - - expandCodes(newLen); - } - } - - void edgeCheck() { - if (edgeCount == edges.length) { - int newLen = edgeCount << 1; - - expandEdges(newLen); - } - } - - // ----------------------------------------------------------------- - // - // Query - - float getVertexX(int idx) { - return vertices[3 * idx + 0]; - } - - float getVertexY(int idx) { - return vertices[3 * idx + 1]; - } - - float getVertexZ(int idx) { - return vertices[3 * idx + 2]; - } - - float getLastVertexX() { - return vertices[3 * (vertexCount - 1) + 0]; - } - - float getLastVertexY() { - return vertices[3 * (vertexCount - 1) + 1]; - } - - float getLastVertexZ() { - return vertices[3 * (vertexCount - 1) + 2]; - } - - int getNumEdgeClosures() { - int count = 0; - for (int i = 0; i < edgeCount; i++) { - if (edges[i][2] == EDGE_CLOSE) count++; - } - return count; - } - - int getNumEdgeVertices(boolean bevel) { - int segVert = edgeCount; - int bevVert = 0; - if (bevel) { - for (int i = 0; i < edgeCount; i++) { - int[] edge = edges[i]; - if (edge[2] == EDGE_MIDDLE || edge[2] == EDGE_START) bevVert += 3; - if (edge[2] == EDGE_CLOSE) { - bevVert += 5; - segVert--; - } - } - } else { - segVert -= getNumEdgeClosures(); - } - return 4 * segVert + bevVert; - } - - int getNumEdgeIndices(boolean bevel) { - int segInd = edgeCount; - int bevInd = 0; - if (bevel) { - for (int i = 0; i < edgeCount; i++) { - int[] edge = edges[i]; - if (edge[2] == EDGE_MIDDLE || edge[2] == EDGE_START) bevInd++; - if (edge[2] == EDGE_CLOSE) { - bevInd++; - segInd--; - } - } - } else { - segInd -= getNumEdgeClosures(); - } - return 6 * (segInd + bevInd); - } - - void getVertexMin(PVector v) { - int index; - for (int i = 0; i < vertexCount; i++) { - index = 4 * i; - v.x = PApplet.min(v.x, vertices[index++]); - v.y = PApplet.min(v.y, vertices[index++]); - v.z = PApplet.min(v.z, vertices[index ]); - } - } - - void getVertexMax(PVector v) { - int index; - for (int i = 0; i < vertexCount; i++) { - index = 4 * i; - v.x = PApplet.max(v.x, vertices[index++]); - v.y = PApplet.max(v.y, vertices[index++]); - v.z = PApplet.max(v.z, vertices[index ]); - } - } - - int getVertexSum(PVector v) { - int index; - for (int i = 0; i < vertexCount; i++) { - index = 4 * i; - v.x += vertices[index++]; - v.y += vertices[index++]; - v.z += vertices[index ]; - } - return vertexCount; - } - - double[] getAttribVector(int idx) { - double[] vector = new double[attribs.numComp]; - int vidx = 0; - for (int i = 0; i < attribs.size(); i++) { - VertexAttribute attrib = attribs.get(i); - String name = attrib.name; - int aidx = attrib.size * idx; - if (attrib.isColor()) { - int[] iarray = iattribs.get(name); - int col = iarray[aidx]; - vector[vidx++] = (col >> 24) & 0xFF; - vector[vidx++] = (col >> 16) & 0xFF; - vector[vidx++] = (col >> 8) & 0xFF; - vector[vidx++] = (col >> 0) & 0xFF; - } else { - if (attrib.isFloat()) { - float[] farray = fattribs.get(name); - for (int n = 0; n < attrib.size; n++) { - vector[vidx++] = farray[aidx++]; - } - } else if (attrib.isInt()) { - int[] iarray = iattribs.get(name); - for (int n = 0; n < attrib.size; n++) { - vector[vidx++] = iarray[aidx++]; - } - } else if (attrib.isBool()) { - byte[] barray = battribs.get(name); - for (int n = 0; n < attrib.size; n++) { - vector[vidx++] = barray[aidx++]; - } - } - } - } - return vector; - } - - // ----------------------------------------------------------------- - // - // Expand arrays - - void expandVertices(int n) { - float temp[] = new float[3 * n]; - PApplet.arrayCopy(vertices, 0, temp, 0, 3 * vertexCount); - vertices = temp; - } - - void expandColors(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(colors, 0, temp, 0, vertexCount); - colors = temp; - } - - void expandNormals(int n) { - float temp[] = new float[3 * n]; - PApplet.arrayCopy(normals, 0, temp, 0, 3 * vertexCount); - normals = temp; - } - - void expandTexCoords(int n) { - float temp[] = new float[2 * n]; - PApplet.arrayCopy(texcoords, 0, temp, 0, 2 * vertexCount); - texcoords = temp; - } - - void expandStrokeColors(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(strokeColors, 0, temp, 0, vertexCount); - strokeColors = temp; - } - - void expandStrokeWeights(int n) { - float temp[] = new float[n]; - PApplet.arrayCopy(strokeWeights, 0, temp, 0, vertexCount); - strokeWeights = temp; - } - - void expandAmbient(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(ambient, 0, temp, 0, vertexCount); - ambient = temp; - } - - void expandSpecular(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(specular, 0, temp, 0, vertexCount); - specular = temp; - } - - void expandEmissive(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(emissive, 0, temp, 0, vertexCount); - emissive = temp; - } - - void expandShininess(int n) { - float temp[] = new float[n]; - PApplet.arrayCopy(shininess, 0, temp, 0, vertexCount); - shininess = temp; - } - - void expandAttribs(int n) { - for (String name: attribs.keySet()) { - VertexAttribute attrib = attribs.get(name); - if (attrib.type == PGL.FLOAT) { - expandFloatAttrib(attrib, n); - } else if (attrib.type == PGL.INT) { - expandIntAttrib(attrib, n); - } else if (attrib.type == PGL.BOOL) { - expandBoolAttrib(attrib, n); - } - } - } - - void expandFloatAttrib(VertexAttribute attrib, int n) { - float[] values = fattribs.get(attrib.name); - float temp[] = new float[attrib.size * n]; - PApplet.arrayCopy(values, 0, temp, 0, attrib.size * vertexCount); - fattribs.put(attrib.name, temp); - } - - void expandIntAttrib(VertexAttribute attrib, int n) { - int[] values = iattribs.get(attrib.name); - int temp[] = new int[attrib.size * n]; - PApplet.arrayCopy(values, 0, temp, 0, attrib.size * vertexCount); - iattribs.put(attrib.name, temp); - } - - void expandBoolAttrib(VertexAttribute attrib, int n) { - byte[] values = battribs.get(attrib.name); - byte temp[] = new byte[attrib.size * n]; - PApplet.arrayCopy(values, 0, temp, 0, attrib.size * vertexCount); - battribs.put(attrib.name, temp); - } - - void expandCodes(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(codes, 0, temp, 0, codeCount); - codes = temp; - } - - void expandEdges(int n) { - int temp[][] = new int[n][3]; - PApplet.arrayCopy(edges, 0, temp, 0, edgeCount); - edges = temp; - } - - // ----------------------------------------------------------------- - // - // Trim arrays - - void trim() { - if (0 < vertexCount && vertexCount < vertices.length / 3) { - trimVertices(); - trimColors(); - trimNormals(); - trimTexCoords(); - trimStrokeColors(); - trimStrokeWeights(); - trimAmbient(); - trimSpecular(); - trimEmissive(); - trimShininess(); - trimAttribs(); - } - - if (0 < codeCount && codeCount < codes.length) { - trimCodes(); - } - - if (0 < edgeCount && edgeCount < edges.length) { - trimEdges(); - } - } - - void trimVertices() { - float temp[] = new float[3 * vertexCount]; - PApplet.arrayCopy(vertices, 0, temp, 0, 3 * vertexCount); - vertices = temp; - } - - void trimColors() { - int temp[] = new int[vertexCount]; - PApplet.arrayCopy(colors, 0, temp, 0, vertexCount); - colors = temp; - } - - void trimNormals() { - float temp[] = new float[3 * vertexCount]; - PApplet.arrayCopy(normals, 0, temp, 0, 3 * vertexCount); - normals = temp; - } - - void trimTexCoords() { - float temp[] = new float[2 * vertexCount]; - PApplet.arrayCopy(texcoords, 0, temp, 0, 2 * vertexCount); - texcoords = temp; - } - - void trimStrokeColors() { - int temp[] = new int[vertexCount]; - PApplet.arrayCopy(strokeColors, 0, temp, 0, vertexCount); - strokeColors = temp; - } - - void trimStrokeWeights() { - float temp[] = new float[vertexCount]; - PApplet.arrayCopy(strokeWeights, 0, temp, 0, vertexCount); - strokeWeights = temp; - } - - void trimAmbient() { - int temp[] = new int[vertexCount]; - PApplet.arrayCopy(ambient, 0, temp, 0, vertexCount); - ambient = temp; - } - - void trimSpecular() { - int temp[] = new int[vertexCount]; - PApplet.arrayCopy(specular, 0, temp, 0, vertexCount); - specular = temp; - } - - void trimEmissive() { - int temp[] = new int[vertexCount]; - PApplet.arrayCopy(emissive, 0, temp, 0, vertexCount); - emissive = temp; - } - - void trimShininess() { - float temp[] = new float[vertexCount]; - PApplet.arrayCopy(shininess, 0, temp, 0, vertexCount); - shininess = temp; - } - - void trimCodes() { - int temp[] = new int[codeCount]; - PApplet.arrayCopy(codes, 0, temp, 0, codeCount); - codes = temp; - } - - void trimEdges() { - int temp[][] = new int[edgeCount][3]; - PApplet.arrayCopy(edges, 0, temp, 0, edgeCount); - edges = temp; - } - - void trimAttribs() { - for (String name: attribs.keySet()) { - VertexAttribute attrib = attribs.get(name); - if (attrib.type == PGL.FLOAT) { - trimFloatAttrib(attrib); - } else if (attrib.type == PGL.INT) { - trimIntAttrib(attrib); - } else if (attrib.type == PGL.BOOL) { - trimBoolAttrib(attrib); - } - } - } - - void trimFloatAttrib(VertexAttribute attrib) { - float[] values = fattribs.get(attrib.name); - float temp[] = new float[attrib.size * vertexCount]; - PApplet.arrayCopy(values, 0, temp, 0, attrib.size * vertexCount); - fattribs.put(attrib.name, temp); - } - - void trimIntAttrib(VertexAttribute attrib) { - int[] values = iattribs.get(attrib.name); - int temp[] = new int[attrib.size * vertexCount]; - PApplet.arrayCopy(values, 0, temp, 0, attrib.size * vertexCount); - iattribs.put(attrib.name, temp); - } - - void trimBoolAttrib(VertexAttribute attrib) { - byte[] values = battribs.get(attrib.name); - byte temp[] = new byte[attrib.size * vertexCount]; - PApplet.arrayCopy(values, 0, temp, 0, attrib.size * vertexCount); - battribs.put(attrib.name, temp); - } - - // ----------------------------------------------------------------- - // - // Vertices - - int addVertex(float x, float y, boolean brk) { - return addVertex(x, y, 0, - fillColor, - normalX, normalY, normalZ, - 0, 0, - strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininessFactor, - VERTEX, brk); - } - - int addVertex(float x, float y, - int code, boolean brk) { - return addVertex(x, y, 0, - fillColor, - normalX, normalY, normalZ, - 0, 0, - strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininessFactor, - code, brk); - } - - int addVertex(float x, float y, - float u, float v, - boolean brk) { - return addVertex(x, y, 0, - fillColor, - normalX, normalY, normalZ, - u, v, - strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininessFactor, - VERTEX, brk); - } - - int addVertex(float x, float y, - float u, float v, - int code, boolean brk) { - return addVertex(x, y, 0, - fillColor, - normalX, normalY, normalZ, - u, v, - strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininessFactor, - code, brk); - } - - int addVertex(float x, float y, float z, boolean brk) { - return addVertex(x, y, z, - fillColor, - normalX, normalY, normalZ, - 0, 0, - strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininessFactor, - VERTEX, brk); - } - - int addVertex(float x, float y, float z, int code, boolean brk) { - return addVertex(x, y, z, - fillColor, - normalX, normalY, normalZ, - 0, 0, - strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininessFactor, - code, brk); - } - - int addVertex(float x, float y, float z, - float u, float v, - boolean brk) { - return addVertex(x, y, z, - fillColor, - normalX, normalY, normalZ, - u, v, - strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininessFactor, - VERTEX, brk); - } - - int addVertex(float x, float y, float z, - float u, float v, - int code, boolean brk) { - return addVertex(x, y, z, - fillColor, - normalX, normalY, normalZ, - u, v, - strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininessFactor, - code, brk); - } - - int addVertex(float x, float y, float z, - int fcolor, - float nx, float ny, float nz, - float u, float v, - int scolor, float sweight, - int am, int sp, int em, float shine, - int code, boolean brk) { - vertexCheck(); - int index; - - index = 3 * vertexCount; - vertices[index++] = x; - vertices[index++] = y; - vertices[index ] = z; - - colors[vertexCount] = PGL.javaToNativeARGB(fcolor); - - index = 3 * vertexCount; - normals[index++] = nx; - normals[index++] = ny; - normals[index ] = nz; - - index = 2 * vertexCount; - texcoords[index++] = u; - texcoords[index ] = v; - - strokeColors[vertexCount] = PGL.javaToNativeARGB(scolor); - strokeWeights[vertexCount] = sweight; - - ambient[vertexCount] = PGL.javaToNativeARGB(am); - specular[vertexCount] = PGL.javaToNativeARGB(sp); - emissive[vertexCount] = PGL.javaToNativeARGB(em); - shininess[vertexCount] = shine; - - for (String name: attribs.keySet()) { - VertexAttribute attrib = attribs.get(name); - index = attrib.size * vertexCount; - if (attrib.type == PGL.FLOAT) { - float[] values = fattribs.get(name); - attrib.add(values, index); - } else if (attrib.type == PGL.INT) { - int[] values = iattribs.get(name); - attrib.add(values, index); - } else if (attrib.type == PGL.BOOL) { - byte[] values = battribs.get(name); - attrib.add(values, index); - } - } - - if (brk || (code == VERTEX && codes != null) || - code == BEZIER_VERTEX || - code == QUADRATIC_VERTEX || - code == CURVE_VERTEX) { - if (codes == null) { - codes = new int[PApplet.max(PGL.DEFAULT_IN_VERTICES, vertexCount)]; - Arrays.fill(codes, 0, vertexCount, VERTEX); - codeCount = vertexCount; - } - - if (brk) { - codeCheck(); - codes[codeCount] = BREAK; - codeCount++; - } - - if (code != -1) { - codeCheck(); - codes[codeCount] = code; - codeCount++; - } - } - - vertexCount++; - - return vertexCount - 1; - } - - public void addBezierVertex(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4, - boolean brk) { - addVertex(x2, y2, z2, BEZIER_VERTEX, brk); - addVertex(x3, y3, z3, -1, false); - addVertex(x4, y4, z4, -1, false); - } - - public void addQuadraticVertex(float cx, float cy, float cz, - float x3, float y3, float z3, - boolean brk) { - addVertex(cx, cy, cz, QUADRATIC_VERTEX, brk); - addVertex(x3, y3, z3, -1, false); - } - - public void addCurveVertex(float x, float y, float z, boolean brk) { - addVertex(x, y, z, CURVE_VERTEX, brk); - } - - // Returns the vertex data in the PGraphics double array format. - float[][] getVertexData() { - float[][] data = new float[vertexCount][VERTEX_FIELD_COUNT]; - for (int i = 0; i < vertexCount; i++) { - float[] vert = data[i]; - - vert[X] = vertices[3 * i + 0]; - vert[Y] = vertices[3 * i + 1]; - vert[Z] = vertices[3 * i + 2]; - - vert[R] = ((colors[i] >> 16) & 0xFF) / 255.0f; - vert[G] = ((colors[i] >> 8) & 0xFF) / 255.0f; - vert[B] = ((colors[i] >> 0) & 0xFF) / 255.0f; - vert[A] = ((colors[i] >> 24) & 0xFF) / 255.0f; - - vert[U] = texcoords[2 * i + 0]; - vert[V] = texcoords[2 * i + 1]; - - vert[NX] = normals[3 * i + 0]; - vert[NY] = normals[3 * i + 1]; - vert[NZ] = normals[3 * i + 2]; - - vert[SR] = ((strokeColors[i] >> 16) & 0xFF) / 255.0f; - vert[SG] = ((strokeColors[i] >> 8) & 0xFF) / 255.0f; - vert[SB] = ((strokeColors[i] >> 0) & 0xFF) / 255.0f; - vert[SA] = ((strokeColors[i] >> 24) & 0xFF) / 255.0f; - - vert[SW] = strokeWeights[i]; - } - - return data; - } - - boolean hasBezierVertex() { - for (int i = 0; i < codeCount; i++) { - if (codes[i] == BEZIER_VERTEX) return true; - } - return false; - } - - boolean hasQuadraticVertex() { - for (int i = 0; i < codeCount; i++) { - if (codes[i] == QUADRATIC_VERTEX) return true; - } - return false; - } - - boolean hasCurveVertex() { - for (int i = 0; i < codeCount; i++) { - if (codes[i] == CURVE_VERTEX) return true; - } - return false; - } - - // ----------------------------------------------------------------- - // - // Edges - - int addEdge(int i, int j, boolean start, boolean end) { - edgeCheck(); - - int[] edge = edges[edgeCount]; - edge[0] = i; - edge[1] = j; - - // Possible values for state: - // 0 = middle edge (not start, not end) - // 1 = start edge (start, not end) - // 2 = end edge (not start, end) - // 3 = isolated edge (start, end) - edge[2] = (start ? 1 : 0) + 2 * (end ? 1 : 0); - - edgeCount++; - - return edgeCount - 1; - } - - int closeEdge(int i, int j) { - edgeCheck(); - - int[] edge = edges[edgeCount]; - edge[0] = i; - edge[1] = j; - edge[2] = EDGE_CLOSE; - - edgeCount++; - - return edgeCount - 1; - } - - void addTrianglesEdges() { - for (int i = 0; i < vertexCount / 3; i++) { - int i0 = 3 * i + 0; - int i1 = 3 * i + 1; - int i2 = 3 * i + 2; - - addEdge(i0, i1, true, false); - addEdge(i1, i2, false, false); - addEdge(i2, i0, false, false); - closeEdge(i2, i0); - } - } - - void addTriangleFanEdges() { - for (int i = 1; i < vertexCount - 1; i++) { - int i0 = 0; - int i1 = i; - int i2 = i + 1; - - addEdge(i0, i1, true, false); - addEdge(i1, i2, false, false); - addEdge(i2, i0, false, false); - closeEdge(i2, i0); - } - } - - void addTriangleStripEdges() { - for (int i = 1; i < vertexCount - 1; i++) { - int i0 = i; - int i1, i2; - if (i % 2 == 0) { - i1 = i - 1; - i2 = i + 1; - } else { - i1 = i + 1; - i2 = i - 1; - } - - addEdge(i0, i1, true, false); - addEdge(i1, i2, false, false); - addEdge(i2, i0, false, false); - closeEdge(i2, i0); - } - } - - void addQuadsEdges() { - for (int i = 0; i < vertexCount / 4; i++) { - int i0 = 4 * i + 0; - int i1 = 4 * i + 1; - int i2 = 4 * i + 2; - int i3 = 4 * i + 3; - - addEdge(i0, i1, true, false); - addEdge(i1, i2, false, false); - addEdge(i2, i3, false, false); - addEdge(i3, i0, false, false); - closeEdge(i3, i0); - } - } - - void addQuadStripEdges() { - for (int qd = 1; qd < vertexCount / 2; qd++) { - int i0 = 2 * (qd - 1); - int i1 = 2 * (qd - 1) + 1; - int i2 = 2 * qd + 1; - int i3 = 2 * qd; - - addEdge(i0, i1, true, false); - addEdge(i1, i2, false, false); - addEdge(i2, i3, false, false); - addEdge(i3, i0, false, false); - closeEdge(i3, i0); - } - } - - // ----------------------------------------------------------------- - // - // Normal calculation - - // Expects vertices in CW (left-handed) order. - void calcTriangleNormal(int i0, int i1, int i2) { - int index; - - index = 3 * i0; - float x0 = vertices[index++]; - float y0 = vertices[index++]; - float z0 = vertices[index ]; - - index = 3 * i1; - float x1 = vertices[index++]; - float y1 = vertices[index++]; - float z1 = vertices[index ]; - - index = 3 * i2; - float x2 = vertices[index++]; - float y2 = vertices[index++]; - float z2 = vertices[index ]; - - float v12x = x2 - x1; - float v12y = y2 - y1; - float v12z = z2 - z1; - - float v10x = x0 - x1; - float v10y = y0 - y1; - float v10z = z0 - z1; - - // The automatic normal calculation in Processing assumes - // that vertices as given in CCW order (right-handed) so: - // n = v12 x v10 - // so that the normal extends from the front face. - float nx = v12y * v10z - v10y * v12z; - float ny = v12z * v10x - v10z * v12x; - float nz = v12x * v10y - v10x * v12y; - float d = PApplet.sqrt(nx * nx + ny * ny + nz * nz); - nx /= d; - ny /= d; - nz /= d; - - index = 3 * i0; - normals[index++] = nx; - normals[index++] = ny; - normals[index ] = nz; - - index = 3 * i1; - normals[index++] = nx; - normals[index++] = ny; - normals[index ] = nz; - - index = 3 * i2; - normals[index++] = nx; - normals[index++] = ny; - normals[index ] = nz; - } - - void calcTrianglesNormals() { - for (int i = 0; i < vertexCount / 3; i++) { - int i0 = 3 * i + 0; - int i1 = 3 * i + 1; - int i2 = 3 * i + 2; - - calcTriangleNormal(i0, i1, i2); - } - } - - void calcTriangleFanNormals() { - for (int i = 1; i < vertexCount - 1; i++) { - int i0 = 0; - int i1 = i; - int i2 = i + 1; - - calcTriangleNormal(i0, i1, i2); - } - } - - void calcTriangleStripNormals() { - for (int i = 1; i < vertexCount - 1; i++) { - int i1 = i; - int i0, i2; - // Vertices are specified by user as: - // 1-3 ... - // |\|\ ... - // 0-2-4 ... - if (i % 2 == 1) { - // The odd triangles (1, 3, 5...) should be CW (left-handed) - i0 = i - 1; - i2 = i + 1; - } else { - // The even triangles (2, 4, 6...) should be CCW (left-handed) - i0 = i + 1; - i2 = i - 1; - } - calcTriangleNormal(i0, i1, i2); - } - } - - void calcQuadsNormals() { - for (int i = 0; i < vertexCount / 4; i++) { - int i0 = 4 * i + 0; - int i1 = 4 * i + 1; - int i2 = 4 * i + 2; - int i3 = 4 * i + 3; - - calcTriangleNormal(i0, i1, i2); - calcTriangleNormal(i2, i3, i0); - } - } - - void calcQuadStripNormals() { - for (int qd = 1; qd < vertexCount / 2; qd++) { - int i0 = 2 * (qd - 1); - int i1 = 2 * (qd - 1) + 1; - int i2 = 2 * qd; - int i3 = 2 * qd + 1; - - // Vertices are specified by user as: - // 1-3-5 ... - // |\|\| ... - // 0-2-4 ... - // thus (0, 1, 2) and (2, 1, 3) are triangles - // in CW order (left-handed). - calcTriangleNormal(i0, i1, i2); - calcTriangleNormal(i2, i1, i3); - } - } - - // ----------------------------------------------------------------- - // - // Primitives - - void setMaterial(int fillColor, int strokeColor, float strokeWeight, - int ambientColor, int specularColor, int emissiveColor, - float shininessFactor) { - this.fillColor = fillColor; - this.strokeColor = strokeColor; - this.strokeWeight = strokeWeight; - this.ambientColor = ambientColor; - this.specularColor = specularColor; - this.emissiveColor = emissiveColor; - this.shininessFactor = shininessFactor; - } - - void setNormal(float normalX, float normalY, float normalZ) { - this.normalX = normalX; - this.normalY = normalY; - this.normalZ = normalZ; - } - - void addPoint(float x, float y, float z, boolean fill, boolean stroke) { - addVertex(x, y, z, VERTEX, true); - } - - void addLine(float x1, float y1, float z1, - float x2, float y2, float z2, - boolean fill, boolean stroke) { - int idx1 = addVertex(x1, y1, z1, VERTEX, true); - int idx2 = addVertex(x2, y2, z2, VERTEX, false); - if (stroke) addEdge(idx1, idx2, true, true); - } - - void addTriangle(float x1, float y1, float z1, - float x2, float y2, float z2, - float x3, float y3, float z3, - boolean fill, boolean stroke) { - int idx1 = addVertex(x1, y1, z1, VERTEX, true); - int idx2 = addVertex(x2, y2, z2, VERTEX, false); - int idx3 = addVertex(x3, y3, z3, VERTEX, false); - if (stroke) { - addEdge(idx1, idx2, true, false); - addEdge(idx2, idx3, false, false); - addEdge(idx3, idx1, false, false); - closeEdge(idx3, idx1); - } - } - - void addQuad(float x1, float y1, float z1, - float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4, - boolean stroke) { - int idx1 = addVertex(x1, y1, z1, 0, 0, VERTEX, true); - int idx2 = addVertex(x2, y2, z2, 1, 0, VERTEX, false); - int idx3 = addVertex(x3, y3, z3, 1, 1, VERTEX, false); - int idx4 = addVertex(x4, y4, z4, 0, 1, VERTEX, false); - if (stroke) { - addEdge(idx1, idx2, true, false); - addEdge(idx2, idx3, false, false); - addEdge(idx3, idx4, false, false); - addEdge(idx4, idx1, false, false); - closeEdge(idx4, idx1); - } - } - - void addRect(float a, float b, float c, float d, - boolean stroke) { - addQuad(a, b, 0, - c, b, 0, - c, d, 0, - a, d, 0, - stroke); - } - - void addRect(float a, float b, float c, float d, - float tl, float tr, float br, float bl, - boolean stroke) { - if (nonZero(tr)) { - addVertex(c-tr, b, VERTEX, true); - addQuadraticVertex(c, b, 0, c, b+tr, 0, false); - } else { - addVertex(c, b, VERTEX, true); - } - if (nonZero(br)) { - addVertex(c, d-br, VERTEX, false); - addQuadraticVertex(c, d, 0, c-br, d, 0, false); - } else { - addVertex(c, d, VERTEX, false); - } - if (nonZero(bl)) { - addVertex(a+bl, d, VERTEX, false); - addQuadraticVertex(a, d, 0, a, d-bl, 0, false); - } else { - addVertex(a, d, VERTEX, false); - } - if (nonZero(tl)) { - addVertex(a, b+tl, VERTEX, false); - addQuadraticVertex(a, b, 0, a+tl, b, 0, false); - } else { - addVertex(a, b, VERTEX, false); - } - } - - void addEllipse(float x, float y, float w, float h, - boolean fill, boolean stroke) { - float radiusH = w / 2; - float radiusV = h / 2; - - float centerX = x + radiusH; - float centerY = y + radiusV; - - // should call screenX/Y using current renderer. - float sx1 = pg.screenX(x, y); - float sy1 = pg.screenY(x, y); - float sx2 = pg.screenX(x + w, y + h); - float sy2 = pg.screenY(x + w, y + h); - - int accuracy = - PApplet.min(MAX_POINT_ACCURACY, PApplet.max(MIN_POINT_ACCURACY, - (int) (TWO_PI * PApplet.dist(sx1, sy1, sx2, sy2) / - POINT_ACCURACY_FACTOR))); - float inc = (float) SINCOS_LENGTH / accuracy; - - if (fill) { - addVertex(centerX, centerY, VERTEX, true); - } - int idx0, pidx, idx; - idx0 = pidx = idx = 0; - float val = 0; - for (int i = 0; i < accuracy; i++) { - idx = addVertex(centerX + cosLUT[(int) val] * radiusH, - centerY + sinLUT[(int) val] * radiusV, - VERTEX, i == 0 && !fill); - val = (val + inc) % SINCOS_LENGTH; - - if (0 < i) { - if (stroke) addEdge(pidx, idx, i == 1, false); - } else { - idx0 = idx; - } - - pidx = idx; - } - // Back to the beginning - addVertex(centerX + cosLUT[0] * radiusH, - centerY + sinLUT[0] * radiusV, - VERTEX, false); - if (stroke) { - addEdge(idx, idx0, false, false); - closeEdge(idx, idx0); - } - } - - // arcMode can be 0, OPEN, CHORD, or PIE - void addArc(float x, float y, float w, float h, - float start, float stop, - boolean fill, boolean stroke, int arcMode) { - float hr = w / 2f; - float vr = h / 2f; - - float centerX = x + hr; - float centerY = y + vr; - - int startLUT = (int) (0.5f + (start / TWO_PI) * SINCOS_LENGTH); - int stopLUT = (int) (0.5f + (stop / TWO_PI) * SINCOS_LENGTH); - - // get length before wrapping indexes so (startLUT <= stopLUT); - int length = PApplet.constrain(stopLUT - startLUT, 0, SINCOS_LENGTH); - - boolean fullCircle = length == SINCOS_LENGTH; - - if (fullCircle && arcMode == CHORD) { - // get rid of overlapping vertices, - // solves problem with closing edge in P3D - length -= 1; - stopLUT -= 1; - } - - { // wrap indexes so they are safe to use in LUT - startLUT %= SINCOS_LENGTH; - if (startLUT < 0) startLUT += SINCOS_LENGTH; - - stopLUT %= SINCOS_LENGTH; - if (stopLUT < 0) stopLUT += SINCOS_LENGTH; - } - - int idx0; - if (arcMode == CHORD || arcMode == OPEN) { - // move center to the middle of flat side - // to properly display arcs smaller than PI - float relX = (cosLUT[startLUT] + cosLUT[stopLUT]) * 0.5f * hr; - float relY = (sinLUT[startLUT] + sinLUT[stopLUT]) * 0.5f * vr; - idx0 = addVertex(centerX + relX, centerY + relY, VERTEX, true); - } else { - idx0 = addVertex(centerX, centerY, VERTEX, true); - } - - int inc; - { // initializes inc the same way ellipse does - float sx1 = pg.screenX(x, y); - float sy1 = pg.screenY(x, y); - float sx2 = pg.screenX(x + w, y + h); - float sy2 = pg.screenY(x + w, y + h); - - int accuracy = - PApplet.min(MAX_POINT_ACCURACY, PApplet.max(MIN_POINT_ACCURACY, - (int) (TWO_PI * PApplet.dist(sx1, sy1, sx2, sy2) / - POINT_ACCURACY_FACTOR))); - inc = PApplet.max(1, SINCOS_LENGTH / accuracy); - } - - int idx = idx0; - int pidx; - - int i = -inc; - int ii; - - // i: (0 -> length) inclusive - // ii: (startLUT -> stopLUT) inclusive, going CW (left-handed), - // wrapping around end of LUT - do { - i += inc; - i = PApplet.min(i, length); // clamp so last vertex won't go over - - ii = startLUT + i; // ii from 0 to (2 * SINCOS_LENGTH - 1) - if (ii >= SINCOS_LENGTH) ii -= SINCOS_LENGTH; - - pidx = idx; - idx = addVertex(centerX + cosLUT[ii] * hr, - centerY + sinLUT[ii] * vr, - VERTEX, i == 0 && !fill); - - if (stroke) { - if (arcMode == CHORD || arcMode == PIE) { - addEdge(pidx, idx, i == 0, false); - } else if (0 < i) { - // when drawing full circle, the edge is closed later - addEdge(pidx, idx, i == PApplet.min(inc, length), - i == length && !fullCircle); - } - } - } while (i < length); - - // keeping last vertex as idx and second last vertex as pidx - - if (stroke) { - if (arcMode == CHORD || arcMode == PIE) { - addEdge(idx, idx0, false, false); - closeEdge(idx, idx0); - } else if (fullCircle) { - closeEdge(pidx, idx); - } - } - } - - void addBox(float w, float h, float d, - boolean fill, boolean stroke) { - - // Correct normals if some dimensions are negative so they always - // extend from front face. We could just take absolute value - // of dimensions, but that would affect texturing. - boolean invertNormX = (h > 0) != (d > 0); - boolean invertNormY = (w > 0) != (d > 0); - boolean invertNormZ = (w > 0) != (h > 0); - - int normX = invertNormX ? -1 : 1; - int normY = invertNormY ? -1 : 1; - int normZ = invertNormZ ? -1 : 1; - - float x1 = -w/2f; float x2 = w/2f; - float y1 = -h/2f; float y2 = h/2f; - float z1 = -d/2f; float z2 = d/2f; - - int idx1 = 0, idx2 = 0, idx3 = 0, idx4 = 0; - if (fill || stroke) { - // back face - setNormal(0, 0, -normZ); - idx1 = addVertex(x1, y1, z1, 0, 0, VERTEX, true); - idx2 = addVertex(x1, y2, z1, 0, 1, VERTEX, false); - idx3 = addVertex(x2, y2, z1, 1, 1, VERTEX, false); - idx4 = addVertex(x2, y1, z1, 1, 0, VERTEX, false); - if (stroke) { - addEdge(idx1, idx2, true, false); - addEdge(idx2, idx3, false, false); - addEdge(idx3, idx4, false, false); - addEdge(idx4, idx1, false, false); - closeEdge(idx4, idx1); - } - - // front face - setNormal(0, 0, normZ); - idx1 = addVertex(x1, y2, z2, 1, 1, VERTEX, false); - idx2 = addVertex(x1, y1, z2, 1, 0, VERTEX, false); - idx3 = addVertex(x2, y1, z2, 0, 0, VERTEX, false); - idx4 = addVertex(x2, y2, z2, 0, 1, VERTEX, false); - if (stroke) { - addEdge(idx1, idx2, true, false); - addEdge(idx2, idx3, false, false); - addEdge(idx3, idx4, false, false); - addEdge(idx4, idx1, false, false); - closeEdge(idx4, idx1); - } - - // right face - setNormal(normX, 0, 0); - idx1 = addVertex(x2, y1, z1, 0, 0, VERTEX, false); - idx2 = addVertex(x2, y2, z1, 0, 1, VERTEX, false); - idx3 = addVertex(x2, y2, z2, 1, 1, VERTEX, false); - idx4 = addVertex(x2, y1, z2, 1, 0, VERTEX, false); - if (stroke) { - addEdge(idx1, idx2, true, false); - addEdge(idx2, idx3, false, false); - addEdge(idx3, idx4, false, false); - addEdge(idx4, idx1, false, false); - closeEdge(idx4, idx1); - } - - // left face - setNormal(-normX, 0, 0); - idx1 = addVertex(x1, y2, z1, 1, 1, VERTEX, false); - idx2 = addVertex(x1, y1, z1, 1, 0, VERTEX, false); - idx3 = addVertex(x1, y1, z2, 0, 0, VERTEX, false); - idx4 = addVertex(x1, y2, z2, 0, 1, VERTEX, false); - if (stroke) { - addEdge(idx1, idx2, true, false); - addEdge(idx2, idx3, false, false); - addEdge(idx3, idx4, false, false); - addEdge(idx4, idx1, false, false); - closeEdge(idx4, idx1); - } - - // top face - setNormal(0, -normY, 0); - idx1 = addVertex(x2, y1, z1, 1, 1, VERTEX, false); - idx2 = addVertex(x2, y1, z2, 1, 0, VERTEX, false); - idx3 = addVertex(x1, y1, z2, 0, 0, VERTEX, false); - idx4 = addVertex(x1, y1, z1, 0, 1, VERTEX, false); - if (stroke) { - addEdge(idx1, idx2, true, false); - addEdge(idx2, idx3, false, false); - addEdge(idx3, idx4, false, false); - addEdge(idx4, idx1, false, false); - closeEdge(idx4, idx1); - } - - // bottom face - setNormal(0, normY, 0); - idx1 = addVertex(x1, y2, z1, 0, 0, VERTEX, false); - idx2 = addVertex(x1, y2, z2, 0, 1, VERTEX, false); - idx3 = addVertex(x2, y2, z2, 1, 1, VERTEX, false); - idx4 = addVertex(x2, y2, z1, 1, 0, VERTEX, false); - if (stroke) { - addEdge(idx1, idx2, true, false); - addEdge(idx2, idx3, false, false); - addEdge(idx3, idx4, false, false); - addEdge(idx4, idx1, false, false); - closeEdge(idx4, idx1); - } - } - } - - // Adds the vertices that define an sphere, without duplicating - // any vertex or edge. - int[] addSphere(float r, int detailU, int detailV, - boolean fill, boolean stroke) { - int nind = 3 * detailU + (6 * detailU + 3) * (detailV - 2) + 3 * detailU; - int[] indices = new int[nind]; - - int vertCount = 0; - int indCount = 0; - int vert0, vert1; - - float u, v; - float du = 1.0f / (detailU); - float dv = 1.0f / (detailV); - - // Southern cap ------------------------------------------------------- - - // Adding multiple copies of the south pole vertex, each one with a - // different u coordinate, so the texture mapping is correct when - // making the first strip of triangles. - u = 1; v = 1; - for (int i = 0; i < detailU; i++) { - setNormal(0, 1, 0); - addVertex(0, r, 0, u , v, VERTEX, true); - u -= du; - } - vertCount = detailU; - vert0 = vertCount; - u = 1; v -= dv; - for (int i = 0; i < detailU; i++) { - setNormal(pg.sphereX[i], pg.sphereY[i], pg.sphereZ[i]); - addVertex(r*pg.sphereX[i], r*pg.sphereY[i], r*pg.sphereZ[i], u , v, - VERTEX, false); - u -= du; - } - vertCount += detailU; - vert1 = vertCount; - setNormal(pg.sphereX[0], pg.sphereY[0], pg.sphereZ[0]); - addVertex(r*pg.sphereX[0], r*pg.sphereY[0], r*pg.sphereZ[0], u, v, - VERTEX, false); - vertCount++; - - for (int i = 0; i < detailU; i++) { - int i1 = vert0 + i; - int i0 = vert0 + i - detailU; - - indices[3 * i + 0] = i1; - indices[3 * i + 1] = i0; - indices[3 * i + 2] = i1 + 1; - - addEdge(i0, i1, true, true); - addEdge(i1, i1 + 1, true, true); - } - indCount += 3 * detailU; - - // Middle rings ------------------------------------------------------- - - int offset = 0; - for (int j = 2; j < detailV; j++) { - offset += detailU; - vert0 = vertCount; - u = 1; v -= dv; - for (int i = 0; i < detailU; i++) { - int ioff = offset + i; - setNormal(pg.sphereX[ioff], pg.sphereY[ioff], pg.sphereZ[ioff]); - addVertex(r*pg.sphereX[ioff], r*pg.sphereY[ioff], r*pg.sphereZ[ioff], - u , v, VERTEX, false); - u -= du; - } - vertCount += detailU; - vert1 = vertCount; - setNormal(pg.sphereX[offset], pg.sphereY[offset], pg.sphereZ[offset]); - addVertex(r*pg.sphereX[offset], r*pg.sphereY[offset], r*pg.sphereZ[offset], - u, v, VERTEX, false); - vertCount++; - - for (int i = 0; i < detailU; i++) { - int i1 = vert0 + i; - int i0 = vert0 + i - detailU - 1; - - indices[indCount + 6 * i + 0] = i1; - indices[indCount + 6 * i + 1] = i0; - indices[indCount + 6 * i + 2] = i0 + 1; - - indices[indCount + 6 * i + 3] = i1; - indices[indCount + 6 * i + 4] = i0 + 1; - indices[indCount + 6 * i + 5] = i1 + 1; - - addEdge(i0, i1, true, true); - addEdge(i1, i1 + 1, true, true); - addEdge(i0 + 1, i1, true, true); - } - indCount += 6 * detailU; - indices[indCount + 0] = vert1; - indices[indCount + 1] = vert1 - detailU; - indices[indCount + 2] = vert1 - 1; - indCount += 3; - } - - // Northern cap ------------------------------------------------------- - - // Adding multiple copies of the north pole vertex, each one with a - // different u coordinate, so the texture mapping is correct when - // making the last strip of triangles. - u = 1; v = 0; - for (int i = 0; i < detailU; i++) { - setNormal(0, -1, 0); - addVertex(0, -r, 0, u , v, VERTEX, false); - u -= du; - } - vertCount += detailU; - - for (int i = 0; i < detailU; i++) { - int i0 = vert0 + i; - int i1 = vert0 + i + detailU + 1; - - indices[indCount + 3 * i + 0] = i1; - indices[indCount + 3 * i + 1] = i0; - indices[indCount + 3 * i + 2] = i0 + 1; - - addEdge(i0, i1, true, true); - } - indCount += 3 * detailU; - - return indices; - } - } - - - // Holds tessellated data for polygon, line and point geometry. - static protected class TessGeometry { - int renderMode; - PGraphicsOpenGL pg; - AttributeMap polyAttribs; - - // Tessellated polygon data - int polyVertexCount; - int firstPolyVertex; - int lastPolyVertex; - FloatBuffer polyVerticesBuffer; - IntBuffer polyColorsBuffer; - FloatBuffer polyNormalsBuffer; - FloatBuffer polyTexCoordsBuffer; - - // Polygon material properties (polyColors is used - // as the diffuse color when lighting is enabled) - IntBuffer polyAmbientBuffer; - IntBuffer polySpecularBuffer; - IntBuffer polyEmissiveBuffer; - FloatBuffer polyShininessBuffer; - - // Generic attributes - HashMap polyAttribBuffers = new HashMap(); - - int polyIndexCount; - int firstPolyIndex; - int lastPolyIndex; - ShortBuffer polyIndicesBuffer; - IndexCache polyIndexCache = new IndexCache(); - - // Tessellated line data - int lineVertexCount; - int firstLineVertex; - int lastLineVertex; - FloatBuffer lineVerticesBuffer; - IntBuffer lineColorsBuffer; - FloatBuffer lineDirectionsBuffer; - - int lineIndexCount; - int firstLineIndex; - int lastLineIndex; - ShortBuffer lineIndicesBuffer; - IndexCache lineIndexCache = new IndexCache(); - - // Tessellated point data - int pointVertexCount; - int firstPointVertex; - int lastPointVertex; - FloatBuffer pointVerticesBuffer; - IntBuffer pointColorsBuffer; - FloatBuffer pointOffsetsBuffer; - - int pointIndexCount; - int firstPointIndex; - int lastPointIndex; - ShortBuffer pointIndicesBuffer; - IndexCache pointIndexCache = new IndexCache(); - - // Backing arrays - float[] polyVertices; - int[] polyColors; - float[] polyNormals; - float[] polyTexCoords; - int[] polyAmbient; - int[] polySpecular; - int[] polyEmissive; - float[] polyShininess; - short[] polyIndices; - float[] lineVertices; - int[] lineColors; - float[] lineDirections; - short[] lineIndices; - float[] pointVertices; - int[] pointColors; - float[] pointOffsets; - short[] pointIndices; - - HashMap fpolyAttribs = new HashMap(); - HashMap ipolyAttribs = new HashMap(); - HashMap bpolyAttribs = new HashMap(); - - TessGeometry(PGraphicsOpenGL pg, AttributeMap attr, int mode) { - this.pg = pg; - this.polyAttribs = attr; - renderMode = mode; - allocate(); - } - - // ----------------------------------------------------------------- - // - // Allocate/dispose - - void allocate() { - polyVertices = new float[4 * PGL.DEFAULT_TESS_VERTICES]; - polyColors = new int[PGL.DEFAULT_TESS_VERTICES]; - polyNormals = new float[3 * PGL.DEFAULT_TESS_VERTICES]; - polyTexCoords = new float[2 * PGL.DEFAULT_TESS_VERTICES]; - polyAmbient = new int[PGL.DEFAULT_TESS_VERTICES]; - polySpecular = new int[PGL.DEFAULT_TESS_VERTICES]; - polyEmissive = new int[PGL.DEFAULT_TESS_VERTICES]; - polyShininess = new float[PGL.DEFAULT_TESS_VERTICES]; - polyIndices = new short[PGL.DEFAULT_TESS_VERTICES]; - - lineVertices = new float[4 * PGL.DEFAULT_TESS_VERTICES]; - lineColors = new int[PGL.DEFAULT_TESS_VERTICES]; - lineDirections = new float[4 * PGL.DEFAULT_TESS_VERTICES]; - lineIndices = new short[PGL.DEFAULT_TESS_VERTICES]; - - pointVertices = new float[4 * PGL.DEFAULT_TESS_VERTICES]; - pointColors = new int[PGL.DEFAULT_TESS_VERTICES]; - pointOffsets = new float[2 * PGL.DEFAULT_TESS_VERTICES]; - pointIndices = new short[PGL.DEFAULT_TESS_VERTICES]; - - polyVerticesBuffer = PGL.allocateFloatBuffer(polyVertices); - polyColorsBuffer = PGL.allocateIntBuffer(polyColors); - polyNormalsBuffer = PGL.allocateFloatBuffer(polyNormals); - polyTexCoordsBuffer = PGL.allocateFloatBuffer(polyTexCoords); - polyAmbientBuffer = PGL.allocateIntBuffer(polyAmbient); - polySpecularBuffer = PGL.allocateIntBuffer(polySpecular); - polyEmissiveBuffer = PGL.allocateIntBuffer(polyEmissive); - polyShininessBuffer = PGL.allocateFloatBuffer(polyShininess); - polyIndicesBuffer = PGL.allocateShortBuffer(polyIndices); - - lineVerticesBuffer = PGL.allocateFloatBuffer(lineVertices); - lineColorsBuffer = PGL.allocateIntBuffer(lineColors); - lineDirectionsBuffer = PGL.allocateFloatBuffer(lineDirections); - lineIndicesBuffer = PGL.allocateShortBuffer(lineIndices); - - pointVerticesBuffer = PGL.allocateFloatBuffer(pointVertices); - pointColorsBuffer = PGL.allocateIntBuffer(pointColors); - pointOffsetsBuffer = PGL.allocateFloatBuffer(pointOffsets); - pointIndicesBuffer = PGL.allocateShortBuffer(pointIndices); - - clear(); - } - - void initAttrib(VertexAttribute attrib) { - if (attrib.type == PGL.FLOAT && !fpolyAttribs.containsKey(attrib.name)) { - float[] temp = new float[attrib.tessSize * PGL.DEFAULT_TESS_VERTICES]; - fpolyAttribs.put(attrib.name, temp); - polyAttribBuffers.put(attrib.name, PGL.allocateFloatBuffer(temp)); - } else if (attrib.type == PGL.INT && !ipolyAttribs.containsKey(attrib.name)) { - int[] temp = new int[attrib.tessSize * PGL.DEFAULT_TESS_VERTICES]; - ipolyAttribs.put(attrib.name, temp); - polyAttribBuffers.put(attrib.name, PGL.allocateIntBuffer(temp)); - } else if (attrib.type == PGL.BOOL && !bpolyAttribs.containsKey(attrib.name)) { - byte[] temp = new byte[attrib.tessSize * PGL.DEFAULT_TESS_VERTICES]; - bpolyAttribs.put(attrib.name, temp); - polyAttribBuffers.put(attrib.name, PGL.allocateByteBuffer(temp)); - } - } - - void clear() { - firstPolyVertex = lastPolyVertex = polyVertexCount = 0; - firstPolyIndex = lastPolyIndex = polyIndexCount = 0; - - firstLineVertex = lastLineVertex = lineVertexCount = 0; - firstLineIndex = lastLineIndex = lineIndexCount = 0; - - firstPointVertex = lastPointVertex = pointVertexCount = 0; - firstPointIndex = lastPointIndex = pointIndexCount = 0; - - polyIndexCache.clear(); - lineIndexCache.clear(); - pointIndexCache.clear(); - } - - void polyVertexCheck() { - if (polyVertexCount == polyVertices.length / 4) { - int newSize = polyVertexCount << 1; - - expandPolyVertices(newSize); - expandPolyColors(newSize); - expandPolyNormals(newSize); - expandPolyTexCoords(newSize); - expandPolyAmbient(newSize); - expandPolySpecular(newSize); - expandPolyEmissive(newSize); - expandPolyShininess(newSize); - expandAttributes(newSize); - } - - firstPolyVertex = polyVertexCount; - polyVertexCount++; - lastPolyVertex = polyVertexCount - 1; - } - - void polyVertexCheck(int count) { - int oldSize = polyVertices.length / 4; - if (polyVertexCount + count > oldSize) { - int newSize = expandArraySize(oldSize, polyVertexCount + count); - - expandPolyVertices(newSize); - expandPolyColors(newSize); - expandPolyNormals(newSize); - expandPolyTexCoords(newSize); - expandPolyAmbient(newSize); - expandPolySpecular(newSize); - expandPolyEmissive(newSize); - expandPolyShininess(newSize); - expandAttributes(newSize); - } - - firstPolyVertex = polyVertexCount; - polyVertexCount += count; - lastPolyVertex = polyVertexCount - 1; - } - - void polyIndexCheck(int count) { - int oldSize = polyIndices.length; - if (polyIndexCount + count > oldSize) { - int newSize = expandArraySize(oldSize, polyIndexCount + count); - - expandPolyIndices(newSize); - } - - firstPolyIndex = polyIndexCount; - polyIndexCount += count; - lastPolyIndex = polyIndexCount - 1; - } - - void polyIndexCheck() { - if (polyIndexCount == polyIndices.length) { - int newSize = polyIndexCount << 1; - - expandPolyIndices(newSize); - } - - firstPolyIndex = polyIndexCount; - polyIndexCount++; - lastPolyIndex = polyIndexCount - 1; - } - - void lineVertexCheck(int count) { - int oldSize = lineVertices.length / 4; - if (lineVertexCount + count > oldSize) { - int newSize = expandArraySize(oldSize, lineVertexCount + count); - - expandLineVertices(newSize); - expandLineColors(newSize); - expandLineDirections(newSize); - } - - firstLineVertex = lineVertexCount; - lineVertexCount += count; - lastLineVertex = lineVertexCount - 1; - } - - void lineIndexCheck(int count) { - int oldSize = lineIndices.length; - if (lineIndexCount + count > oldSize) { - int newSize = expandArraySize(oldSize, lineIndexCount + count); - - expandLineIndices(newSize); - } - - firstLineIndex = lineIndexCount; - lineIndexCount += count; - lastLineIndex = lineIndexCount - 1; - } - - void pointVertexCheck(int count) { - int oldSize = pointVertices.length / 4; - if (pointVertexCount + count > oldSize) { - int newSize = expandArraySize(oldSize, pointVertexCount + count); - - expandPointVertices(newSize); - expandPointColors(newSize); - expandPointOffsets(newSize); - } - - firstPointVertex = pointVertexCount; - pointVertexCount += count; - lastPointVertex = pointVertexCount - 1; - } - - void pointIndexCheck(int count) { - int oldSize = pointIndices.length; - if (pointIndexCount + count > oldSize) { - int newSize = expandArraySize(oldSize, pointIndexCount + count); - - expandPointIndices(newSize); - } - - firstPointIndex = pointIndexCount; - pointIndexCount += count; - lastPointIndex = pointIndexCount - 1; - } - - // ----------------------------------------------------------------- - // - // Query - - boolean isFull() { - return PGL.FLUSH_VERTEX_COUNT <= polyVertexCount || - PGL.FLUSH_VERTEX_COUNT <= lineVertexCount || - PGL.FLUSH_VERTEX_COUNT <= pointVertexCount; - } - - void getPolyVertexMin(PVector v, int first, int last) { - for (int i = first; i <= last; i++) { - int index = 4 * i; - v.x = PApplet.min(v.x, polyVertices[index++]); - v.y = PApplet.min(v.y, polyVertices[index++]); - v.z = PApplet.min(v.z, polyVertices[index ]); - } - } - - void getLineVertexMin(PVector v, int first, int last) { - for (int i = first; i <= last; i++) { - int index = 4 * i; - v.x = PApplet.min(v.x, lineVertices[index++]); - v.y = PApplet.min(v.y, lineVertices[index++]); - v.z = PApplet.min(v.z, lineVertices[index ]); - } - } - - void getPointVertexMin(PVector v, int first, int last) { - for (int i = first; i <= last; i++) { - int index = 4 * i; - v.x = PApplet.min(v.x, pointVertices[index++]); - v.y = PApplet.min(v.y, pointVertices[index++]); - v.z = PApplet.min(v.z, pointVertices[index ]); - } - } - - void getPolyVertexMax(PVector v, int first, int last) { - for (int i = first; i <= last; i++) { - int index = 4 * i; - v.x = PApplet.max(v.x, polyVertices[index++]); - v.y = PApplet.max(v.y, polyVertices[index++]); - v.z = PApplet.max(v.z, polyVertices[index ]); - } - } - - void getLineVertexMax(PVector v, int first, int last) { - for (int i = first; i <= last; i++) { - int index = 4 * i; - v.x = PApplet.max(v.x, lineVertices[index++]); - v.y = PApplet.max(v.y, lineVertices[index++]); - v.z = PApplet.max(v.z, lineVertices[index ]); - } - } - - void getPointVertexMax(PVector v, int first, int last) { - for (int i = first; i <= last; i++) { - int index = 4 * i; - v.x = PApplet.max(v.x, pointVertices[index++]); - v.y = PApplet.max(v.y, pointVertices[index++]); - v.z = PApplet.max(v.z, pointVertices[index ]); - } - } - - int getPolyVertexSum(PVector v, int first, int last) { - for (int i = first; i <= last; i++) { - int index = 4 * i; - v.x += polyVertices[index++]; - v.y += polyVertices[index++]; - v.z += polyVertices[index ]; - } - return last - first + 1; - } - - int getLineVertexSum(PVector v, int first, int last) { - for (int i = first; i <= last; i++) { - int index = 4 * i; - v.x += lineVertices[index++]; - v.y += lineVertices[index++]; - v.z += lineVertices[index ]; - } - return last - first + 1; - } - - int getPointVertexSum(PVector v, int first, int last) { - for (int i = first; i <= last; i++) { - int index = 4 * i; - v.x += pointVertices[index++]; - v.y += pointVertices[index++]; - v.z += pointVertices[index ]; - } - return last - first + 1; - } - - // ----------------------------------------------------------------- - // - // Methods to prepare buffers for relative read/write operations - - protected void updatePolyVerticesBuffer() { - updatePolyVerticesBuffer(0, polyVertexCount); - } - - protected void updatePolyVerticesBuffer(int offset, int size) { - PGL.updateFloatBuffer(polyVerticesBuffer, polyVertices, - 4 * offset, 4 * size); - } - - protected void updatePolyColorsBuffer() { - updatePolyColorsBuffer(0, polyVertexCount); - } - - protected void updatePolyColorsBuffer(int offset, int size) { - PGL.updateIntBuffer(polyColorsBuffer, polyColors, offset, size); - } - - protected void updatePolyNormalsBuffer() { - updatePolyNormalsBuffer(0, polyVertexCount); - } - - protected void updatePolyNormalsBuffer(int offset, int size) { - PGL.updateFloatBuffer(polyNormalsBuffer, polyNormals, - 3 * offset, 3 * size); - } - - protected void updatePolyTexCoordsBuffer() { - updatePolyTexCoordsBuffer(0, polyVertexCount); - } - - protected void updatePolyTexCoordsBuffer(int offset, int size) { - PGL.updateFloatBuffer(polyTexCoordsBuffer, polyTexCoords, - 2 * offset, 2 * size); - } - - protected void updatePolyAmbientBuffer() { - updatePolyAmbientBuffer(0, polyVertexCount); - } - - protected void updatePolyAmbientBuffer(int offset, int size) { - PGL.updateIntBuffer(polyAmbientBuffer, polyAmbient, offset, size); - } - - protected void updatePolySpecularBuffer() { - updatePolySpecularBuffer(0, polyVertexCount); - } - - protected void updatePolySpecularBuffer(int offset, int size) { - PGL.updateIntBuffer(polySpecularBuffer, polySpecular, offset, size); - } - - protected void updatePolyEmissiveBuffer() { - updatePolyEmissiveBuffer(0, polyVertexCount); - } - - protected void updatePolyEmissiveBuffer(int offset, int size) { - PGL.updateIntBuffer(polyEmissiveBuffer, polyEmissive, offset, size); - } - - protected void updatePolyShininessBuffer() { - updatePolyShininessBuffer(0, polyVertexCount); - } - - protected void updatePolyShininessBuffer(int offset, int size) { - PGL.updateFloatBuffer(polyShininessBuffer, polyShininess, offset, size); - } - - protected void updateAttribBuffer(String name) { - updateAttribBuffer(name, 0, polyVertexCount); - } - - protected void updateAttribBuffer(String name, int offset, int size) { - VertexAttribute attrib = polyAttribs.get(name); - if (attrib.type == PGL.FLOAT) { - FloatBuffer buffer = (FloatBuffer)polyAttribBuffers.get(name); - float[] array = fpolyAttribs.get(name); - PGL.updateFloatBuffer(buffer, array, - attrib.tessSize * offset, attrib.tessSize * size); - } else if (attrib.type == PGL.INT) { - IntBuffer buffer = (IntBuffer)polyAttribBuffers.get(name); - int[] array = ipolyAttribs.get(name); - PGL.updateIntBuffer(buffer, array, - attrib.tessSize * offset, attrib.tessSize * size); - } else if (attrib.type == PGL.BOOL) { - ByteBuffer buffer = (ByteBuffer)polyAttribBuffers.get(name); - byte[] array = bpolyAttribs.get(name); - PGL.updateByteBuffer(buffer, array, - attrib.tessSize * offset, attrib.tessSize * size); - } - } - - protected void updatePolyIndicesBuffer() { - updatePolyIndicesBuffer(0, polyIndexCount); - } - - protected void updatePolyIndicesBuffer(int offset, int size) { - PGL.updateShortBuffer(polyIndicesBuffer, polyIndices, offset, size); - } - - protected void updateLineVerticesBuffer() { - updateLineVerticesBuffer(0, lineVertexCount); - } - - protected void updateLineVerticesBuffer(int offset, int size) { - PGL.updateFloatBuffer(lineVerticesBuffer, lineVertices, - 4 * offset, 4 * size); - } - - protected void updateLineColorsBuffer() { - updateLineColorsBuffer(0, lineVertexCount); - } - - protected void updateLineColorsBuffer(int offset, int size) { - PGL.updateIntBuffer(lineColorsBuffer, lineColors, offset, size); - } - - protected void updateLineDirectionsBuffer() { - updateLineDirectionsBuffer(0, lineVertexCount); - } - - protected void updateLineDirectionsBuffer(int offset, int size) { - PGL.updateFloatBuffer(lineDirectionsBuffer, lineDirections, - 4 * offset, 4 * size); - } - - protected void updateLineIndicesBuffer() { - updateLineIndicesBuffer(0, lineIndexCount); - } - - protected void updateLineIndicesBuffer(int offset, int size) { - PGL.updateShortBuffer(lineIndicesBuffer, lineIndices, offset, size); - } - - protected void updatePointVerticesBuffer() { - updatePointVerticesBuffer(0, pointVertexCount); - } - - protected void updatePointVerticesBuffer(int offset, int size) { - PGL.updateFloatBuffer(pointVerticesBuffer, pointVertices, - 4 * offset, 4 * size); - } - - protected void updatePointColorsBuffer() { - updatePointColorsBuffer(0, pointVertexCount); - } - - protected void updatePointColorsBuffer(int offset, int size) { - PGL.updateIntBuffer(pointColorsBuffer, pointColors, offset, size); - } - - protected void updatePointOffsetsBuffer() { - updatePointOffsetsBuffer(0, pointVertexCount); - } - - protected void updatePointOffsetsBuffer(int offset, int size) { - PGL.updateFloatBuffer(pointOffsetsBuffer, pointOffsets, - 2 * offset, 2 * size); - } - - protected void updatePointIndicesBuffer() { - updatePointIndicesBuffer(0, pointIndexCount); - } - - protected void updatePointIndicesBuffer(int offset, int size) { - PGL.updateShortBuffer(pointIndicesBuffer, pointIndices, offset, size); - } - - // ----------------------------------------------------------------- - // - // Expand arrays - - void expandPolyVertices(int n) { - float temp[] = new float[4 * n]; - PApplet.arrayCopy(polyVertices, 0, temp, 0, 4 * polyVertexCount); - polyVertices = temp; - polyVerticesBuffer = PGL.allocateFloatBuffer(polyVertices); - } - - void expandPolyColors(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(polyColors, 0, temp, 0, polyVertexCount); - polyColors = temp; - polyColorsBuffer = PGL.allocateIntBuffer(polyColors); - } - - void expandPolyNormals(int n) { - float temp[] = new float[3 * n]; - PApplet.arrayCopy(polyNormals, 0, temp, 0, 3 * polyVertexCount); - polyNormals = temp; - polyNormalsBuffer = PGL.allocateFloatBuffer(polyNormals); - } - - void expandPolyTexCoords(int n) { - float temp[] = new float[2 * n]; - PApplet.arrayCopy(polyTexCoords, 0, temp, 0, 2 * polyVertexCount); - polyTexCoords = temp; - polyTexCoordsBuffer = PGL.allocateFloatBuffer(polyTexCoords); - } - - void expandPolyAmbient(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(polyAmbient, 0, temp, 0, polyVertexCount); - polyAmbient = temp; - polyAmbientBuffer = PGL.allocateIntBuffer(polyAmbient); - } - - void expandPolySpecular(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(polySpecular, 0, temp, 0, polyVertexCount); - polySpecular = temp; - polySpecularBuffer = PGL.allocateIntBuffer(polySpecular); - } - - void expandPolyEmissive(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(polyEmissive, 0, temp, 0, polyVertexCount); - polyEmissive = temp; - polyEmissiveBuffer = PGL.allocateIntBuffer(polyEmissive); - } - - void expandPolyShininess(int n) { - float temp[] = new float[n]; - PApplet.arrayCopy(polyShininess, 0, temp, 0, polyVertexCount); - polyShininess = temp; - polyShininessBuffer = PGL.allocateFloatBuffer(polyShininess); - } - - void expandAttributes(int n) { - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (attrib.type == PGL.FLOAT) { - expandFloatAttribute(attrib, n); - } else if (attrib.type == PGL.INT) { - expandIntAttribute(attrib, n); - } else if (attrib.type == PGL.BOOL) { - expandBoolAttribute(attrib, n); - } - } - } - - void expandFloatAttribute(VertexAttribute attrib, int n) { - float[] array = fpolyAttribs.get(attrib.name); - float temp[] = new float[attrib.tessSize * n]; - PApplet.arrayCopy(array, 0, temp, 0, attrib.tessSize * polyVertexCount); - fpolyAttribs.put(attrib.name, temp); - polyAttribBuffers.put(attrib.name, PGL.allocateFloatBuffer(temp)); - } - - void expandIntAttribute(VertexAttribute attrib, int n) { - int[] array = ipolyAttribs.get(attrib.name); - int temp[] = new int[attrib.tessSize * n]; - PApplet.arrayCopy(array, 0, temp, 0, attrib.tessSize * polyVertexCount); - ipolyAttribs.put(attrib.name, temp); - polyAttribBuffers.put(attrib.name, PGL.allocateIntBuffer(temp)); - } - - void expandBoolAttribute(VertexAttribute attrib, int n) { - byte[] array = bpolyAttribs.get(attrib.name); - byte temp[] = new byte[attrib.tessSize * n]; - PApplet.arrayCopy(array, 0, temp, 0, attrib.tessSize * polyVertexCount); - bpolyAttribs.put(attrib.name, temp); - polyAttribBuffers.put(attrib.name, PGL.allocateByteBuffer(temp)); - } - - void expandPolyIndices(int n) { - short temp[] = new short[n]; - PApplet.arrayCopy(polyIndices, 0, temp, 0, polyIndexCount); - polyIndices = temp; - polyIndicesBuffer = PGL.allocateShortBuffer(polyIndices); - } - - void expandLineVertices(int n) { - float temp[] = new float[4 * n]; - PApplet.arrayCopy(lineVertices, 0, temp, 0, 4 * lineVertexCount); - lineVertices = temp; - lineVerticesBuffer = PGL.allocateFloatBuffer(lineVertices); - } - - void expandLineColors(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(lineColors, 0, temp, 0, lineVertexCount); - lineColors = temp; - lineColorsBuffer = PGL.allocateIntBuffer(lineColors); - } - - void expandLineDirections(int n) { - float temp[] = new float[4 * n]; - PApplet.arrayCopy(lineDirections, 0, temp, 0, 4 * lineVertexCount); - lineDirections = temp; - lineDirectionsBuffer = PGL.allocateFloatBuffer(lineDirections); - } - - void expandLineIndices(int n) { - short temp[] = new short[n]; - PApplet.arrayCopy(lineIndices, 0, temp, 0, lineIndexCount); - lineIndices = temp; - lineIndicesBuffer = PGL.allocateShortBuffer(lineIndices); - } - - void expandPointVertices(int n) { - float temp[] = new float[4 * n]; - PApplet.arrayCopy(pointVertices, 0, temp, 0, 4 * pointVertexCount); - pointVertices = temp; - pointVerticesBuffer = PGL.allocateFloatBuffer(pointVertices); - } - - void expandPointColors(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(pointColors, 0, temp, 0, pointVertexCount); - pointColors = temp; - pointColorsBuffer = PGL.allocateIntBuffer(pointColors); - } - - void expandPointOffsets(int n) { - float temp[] = new float[2 * n]; - PApplet.arrayCopy(pointOffsets, 0, temp, 0, 2 * pointVertexCount); - pointOffsets = temp; - pointOffsetsBuffer = PGL.allocateFloatBuffer(pointOffsets); - } - - void expandPointIndices(int n) { - short temp[] = new short[n]; - PApplet.arrayCopy(pointIndices, 0, temp, 0, pointIndexCount); - pointIndices = temp; - pointIndicesBuffer = PGL.allocateShortBuffer(pointIndices); - } - - // ----------------------------------------------------------------- - // - // Trim arrays - - void trim() { - if (0 < polyVertexCount && polyVertexCount < polyVertices.length / 4) { - trimPolyVertices(); - trimPolyColors(); - trimPolyNormals(); - trimPolyTexCoords(); - trimPolyAmbient(); - trimPolySpecular(); - trimPolyEmissive(); - trimPolyShininess(); - trimPolyAttributes(); - } - - if (0 < polyIndexCount && polyIndexCount < polyIndices.length) { - trimPolyIndices(); - } - - if (0 < lineVertexCount && lineVertexCount < lineVertices.length / 4) { - trimLineVertices(); - trimLineColors(); - trimLineDirections(); - } - - if (0 < lineIndexCount && lineIndexCount < lineIndices.length) { - trimLineIndices(); - } - - if (0 < pointVertexCount && pointVertexCount < pointVertices.length / 4) { - trimPointVertices(); - trimPointColors(); - trimPointOffsets(); - } - - if (0 < pointIndexCount && pointIndexCount < pointIndices.length) { - trimPointIndices(); - } - } - - void trimPolyVertices() { - float temp[] = new float[4 * polyVertexCount]; - PApplet.arrayCopy(polyVertices, 0, temp, 0, 4 * polyVertexCount); - polyVertices = temp; - polyVerticesBuffer = PGL.allocateFloatBuffer(polyVertices); - } - - void trimPolyColors() { - int temp[] = new int[polyVertexCount]; - PApplet.arrayCopy(polyColors, 0, temp, 0, polyVertexCount); - polyColors = temp; - polyColorsBuffer = PGL.allocateIntBuffer(polyColors); - } - - void trimPolyNormals() { - float temp[] = new float[3 * polyVertexCount]; - PApplet.arrayCopy(polyNormals, 0, temp, 0, 3 * polyVertexCount); - polyNormals = temp; - polyNormalsBuffer = PGL.allocateFloatBuffer(polyNormals); - } - - void trimPolyTexCoords() { - float temp[] = new float[2 * polyVertexCount]; - PApplet.arrayCopy(polyTexCoords, 0, temp, 0, 2 * polyVertexCount); - polyTexCoords = temp; - polyTexCoordsBuffer = PGL.allocateFloatBuffer(polyTexCoords); - } - - void trimPolyAmbient() { - int temp[] = new int[polyVertexCount]; - PApplet.arrayCopy(polyAmbient, 0, temp, 0, polyVertexCount); - polyAmbient = temp; - polyAmbientBuffer = PGL.allocateIntBuffer(polyAmbient); - } - - void trimPolySpecular() { - int temp[] = new int[polyVertexCount]; - PApplet.arrayCopy(polySpecular, 0, temp, 0, polyVertexCount); - polySpecular = temp; - polySpecularBuffer = PGL.allocateIntBuffer(polySpecular); - } - - void trimPolyEmissive() { - int temp[] = new int[polyVertexCount]; - PApplet.arrayCopy(polyEmissive, 0, temp, 0, polyVertexCount); - polyEmissive = temp; - polyEmissiveBuffer = PGL.allocateIntBuffer(polyEmissive); - } - - void trimPolyShininess() { - float temp[] = new float[polyVertexCount]; - PApplet.arrayCopy(polyShininess, 0, temp, 0, polyVertexCount); - polyShininess = temp; - polyShininessBuffer = PGL.allocateFloatBuffer(polyShininess); - } - - void trimPolyAttributes() { - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (attrib.type == PGL.FLOAT) { - trimFloatAttribute(attrib); - } else if (attrib.type == PGL.INT) { - trimIntAttribute(attrib); - } else if (attrib.type == PGL.BOOL) { - trimBoolAttribute(attrib); - } - } - } - - void trimFloatAttribute(VertexAttribute attrib) { - float[] array = fpolyAttribs.get(attrib.name); - float temp[] = new float[attrib.tessSize * polyVertexCount]; - PApplet.arrayCopy(array, 0, temp, 0, attrib.tessSize * polyVertexCount); - fpolyAttribs.put(attrib.name, temp); - polyAttribBuffers.put(attrib.name, PGL.allocateFloatBuffer(temp)); - } - - void trimIntAttribute(VertexAttribute attrib) { - int[] array = ipolyAttribs.get(attrib.name); - int temp[] = new int[attrib.tessSize * polyVertexCount]; - PApplet.arrayCopy(array, 0, temp, 0, attrib.tessSize * polyVertexCount); - ipolyAttribs.put(attrib.name, temp); - polyAttribBuffers.put(attrib.name, PGL.allocateIntBuffer(temp)); - } - - void trimBoolAttribute(VertexAttribute attrib) { - byte[] array = bpolyAttribs.get(attrib.name); - byte temp[] = new byte[attrib.tessSize * polyVertexCount]; - PApplet.arrayCopy(array, 0, temp, 0, attrib.tessSize * polyVertexCount); - bpolyAttribs.put(attrib.name, temp); - polyAttribBuffers.put(attrib.name, PGL.allocateByteBuffer(temp)); - } - - void trimPolyIndices() { - short temp[] = new short[polyIndexCount]; - PApplet.arrayCopy(polyIndices, 0, temp, 0, polyIndexCount); - polyIndices = temp; - polyIndicesBuffer = PGL.allocateShortBuffer(polyIndices); - } - - void trimLineVertices() { - float temp[] = new float[4 * lineVertexCount]; - PApplet.arrayCopy(lineVertices, 0, temp, 0, 4 * lineVertexCount); - lineVertices = temp; - lineVerticesBuffer = PGL.allocateFloatBuffer(lineVertices); - } - - void trimLineColors() { - int temp[] = new int[lineVertexCount]; - PApplet.arrayCopy(lineColors, 0, temp, 0, lineVertexCount); - lineColors = temp; - lineColorsBuffer = PGL.allocateIntBuffer(lineColors); - } - - void trimLineDirections() { - float temp[] = new float[4 * lineVertexCount]; - PApplet.arrayCopy(lineDirections, 0, temp, 0, 4 * lineVertexCount); - lineDirections = temp; - lineDirectionsBuffer = PGL.allocateFloatBuffer(lineDirections); - } - - void trimLineIndices() { - short temp[] = new short[lineIndexCount]; - PApplet.arrayCopy(lineIndices, 0, temp, 0, lineIndexCount); - lineIndices = temp; - lineIndicesBuffer = PGL.allocateShortBuffer(lineIndices); - } - - void trimPointVertices() { - float temp[] = new float[4 * pointVertexCount]; - PApplet.arrayCopy(pointVertices, 0, temp, 0, 4 * pointVertexCount); - pointVertices = temp; - pointVerticesBuffer = PGL.allocateFloatBuffer(pointVertices); - } - - void trimPointColors() { - int temp[] = new int[pointVertexCount]; - PApplet.arrayCopy(pointColors, 0, temp, 0, pointVertexCount); - pointColors = temp; - pointColorsBuffer = PGL.allocateIntBuffer(pointColors); - } - - void trimPointOffsets() { - float temp[] = new float[2 * pointVertexCount]; - PApplet.arrayCopy(pointOffsets, 0, temp, 0, 2 * pointVertexCount); - pointOffsets = temp; - pointOffsetsBuffer = PGL.allocateFloatBuffer(pointOffsets); - } - - void trimPointIndices() { - short temp[] = new short[pointIndexCount]; - PApplet.arrayCopy(pointIndices, 0, temp, 0, pointIndexCount); - pointIndices = temp; - pointIndicesBuffer = PGL.allocateShortBuffer(pointIndices); - } - - // ----------------------------------------------------------------- - // - // Aggregation methods - - void incPolyIndices(int first, int last, int inc) { - for (int i = first; i <= last; i++) { - polyIndices[i] += inc; - } - } - - void incLineIndices(int first, int last, int inc) { - for (int i = first; i <= last; i++) { - lineIndices[i] += inc; - } - } - - void incPointIndices(int first, int last, int inc) { - for (int i = first; i <= last; i++) { - pointIndices[i] += inc; - } - } - - // ----------------------------------------------------------------- - // - // Normal calculation - - // Expects vertices in CW (left-handed) order. - void calcPolyNormal(int i0, int i1, int i2) { - int index; - - index = 4 * i0; - float x0 = polyVertices[index++]; - float y0 = polyVertices[index++]; - float z0 = polyVertices[index ]; - - index = 4 * i1; - float x1 = polyVertices[index++]; - float y1 = polyVertices[index++]; - float z1 = polyVertices[index ]; - - index = 4 * i2; - float x2 = polyVertices[index++]; - float y2 = polyVertices[index++]; - float z2 = polyVertices[index ]; - - float v12x = x2 - x1; - float v12y = y2 - y1; - float v12z = z2 - z1; - - float v10x = x0 - x1; - float v10y = y0 - y1; - float v10z = z0 - z1; - - float nx = v12y * v10z - v10y * v12z; - float ny = v12z * v10x - v10z * v12x; - float nz = v12x * v10y - v10x * v12y; - float d = PApplet.sqrt(nx * nx + ny * ny + nz * nz); - nx /= d; - ny /= d; - nz /= d; - - index = 3 * i0; - polyNormals[index++] = nx; - polyNormals[index++] = ny; - polyNormals[index ] = nz; - - index = 3 * i1; - polyNormals[index++] = nx; - polyNormals[index++] = ny; - polyNormals[index ] = nz; - - index = 3 * i2; - polyNormals[index++] = nx; - polyNormals[index++] = ny; - polyNormals[index ] = nz; - } - - // ----------------------------------------------------------------- - // - // Add point geometry - - // Sets point vertex with index tessIdx using the data from input vertex - // inIdx. - void setPointVertex(int tessIdx, InGeometry in, int inIdx) { - int index; - - index = 3 * inIdx; - float x = in.vertices[index++]; - float y = in.vertices[index++]; - float z = in.vertices[index ]; - - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - PMatrix3D mm = pg.modelview; - - index = 4 * tessIdx; - pointVertices[index++] = x*mm.m00 + y*mm.m01 + z*mm.m02 + mm.m03; - pointVertices[index++] = x*mm.m10 + y*mm.m11 + z*mm.m12 + mm.m13; - pointVertices[index++] = x*mm.m20 + y*mm.m21 + z*mm.m22 + mm.m23; - pointVertices[index ] = x*mm.m30 + y*mm.m31 + z*mm.m32 + mm.m33; - } else { - index = 4 * tessIdx; - pointVertices[index++] = x; - pointVertices[index++] = y; - pointVertices[index++] = z; - pointVertices[index ] = 1; - } - - pointColors[tessIdx] = in.strokeColors[inIdx]; - } - - // ----------------------------------------------------------------- - // - // Add line geometry - - void setLineVertex(int tessIdx, float[] vertices, int inIdx0, int rgba) { - int index; - - index = 3 * inIdx0; - float x0 = vertices[index++]; - float y0 = vertices[index++]; - float z0 = vertices[index ]; - - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - PMatrix3D mm = pg.modelview; - - index = 4 * tessIdx; - lineVertices[index++] = x0*mm.m00 + y0*mm.m01 + z0*mm.m02 + mm.m03; - lineVertices[index++] = x0*mm.m10 + y0*mm.m11 + z0*mm.m12 + mm.m13; - lineVertices[index++] = x0*mm.m20 + y0*mm.m21 + z0*mm.m22 + mm.m23; - lineVertices[index ] = x0*mm.m30 + y0*mm.m31 + z0*mm.m32 + mm.m33; - } else { - index = 4 * tessIdx; - lineVertices[index++] = x0; - lineVertices[index++] = y0; - lineVertices[index++] = z0; - lineVertices[index ] = 1; - } - - lineColors[tessIdx] = rgba; - index = 4 * tessIdx; - lineDirections[index++] = 0; - lineDirections[index++] = 0; - lineDirections[index++] = 0; - lineDirections[index ] = 0; - } - - // Sets line vertex with index tessIdx using the data from input vertices - // inIdx0 and inIdx1. - void setLineVertex(int tessIdx, float[] vertices, int inIdx0, int inIdx1, - int rgba, float weight) { - int index; - - index = 3 * inIdx0; - float x0 = vertices[index++]; - float y0 = vertices[index++]; - float z0 = vertices[index ]; - - index = 3 * inIdx1; - float x1 = vertices[index++]; - float y1 = vertices[index++]; - float z1 = vertices[index ]; - - float dx = x1 - x0; - float dy = y1 - y0; - float dz = z1 - z0; - - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - PMatrix3D mm = pg.modelview; - - index = 4 * tessIdx; - lineVertices[index++] = x0*mm.m00 + y0*mm.m01 + z0*mm.m02 + mm.m03; - lineVertices[index++] = x0*mm.m10 + y0*mm.m11 + z0*mm.m12 + mm.m13; - lineVertices[index++] = x0*mm.m20 + y0*mm.m21 + z0*mm.m22 + mm.m23; - lineVertices[index ] = x0*mm.m30 + y0*mm.m31 + z0*mm.m32 + mm.m33; - - index = 4 * tessIdx; - lineDirections[index++] = dx*mm.m00 + dy*mm.m01 + dz*mm.m02; - lineDirections[index++] = dx*mm.m10 + dy*mm.m11 + dz*mm.m12; - lineDirections[index ] = dx*mm.m20 + dy*mm.m21 + dz*mm.m22; - } else { - index = 4 * tessIdx; - lineVertices[index++] = x0; - lineVertices[index++] = y0; - lineVertices[index++] = z0; - lineVertices[index ] = 1; - - index = 4 * tessIdx; - lineDirections[index++] = dx; - lineDirections[index++] = dy; - lineDirections[index ] = dz; - } - - lineColors[tessIdx] = rgba; - lineDirections[4 * tessIdx + 3] = weight; - } - - // ----------------------------------------------------------------- - // - // Add poly geometry - - void addPolyVertex(double[] d, boolean clampXY) { - int fcolor = - (int)d[ 3] << 24 | (int)d[ 4] << 16 | (int)d[ 5] << 8 | (int)d[ 6]; - int acolor = - (int)d[12] << 24 | (int)d[13] << 16 | (int)d[14] << 8 | (int)d[15]; - int scolor = - (int)d[16] << 24 | (int)d[17] << 16 | (int)d[18] << 8 | (int)d[19]; - int ecolor = - (int)d[20] << 24 | (int)d[21] << 16 | (int)d[22] << 8 | (int)d[23]; - - addPolyVertex((float)d[ 0], (float)d[ 1], (float)d[ 2], - fcolor, - (float)d[ 7], (float)d[ 8], (float)d[ 9], - (float)d[10], (float)d[11], - acolor, scolor, ecolor, - (float)d[24], - clampXY); - - if (25 < d.length) { - // Add the values of the custom attributes... - PMatrix3D mm = pg.modelview; - PMatrix3D nm = pg.modelviewInv; - int tessIdx = polyVertexCount - 1; - int index; - int pos = 25; - for (int i = 0; i < polyAttribs.size(); i++) { - VertexAttribute attrib = polyAttribs.get(i); - String name = attrib.name; - index = attrib.tessSize * tessIdx; - if (attrib.isColor()) { - // Reconstruct color from ARGB components - int color = - (int)d[pos + 0] << 24 | (int)d[pos + 1] << 16 | (int)d[pos + 2] << 8 | (int)d[pos + 3]; - int[] tessValues = ipolyAttribs.get(name); - tessValues[index] = color; - pos += 4; - } else if (attrib.isPosition()) { - float[] farray = fpolyAttribs.get(name); - float x = (float)d[pos++]; - float y = (float)d[pos++]; - float z = (float)d[pos++]; - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - if (clampXY) { - // ceil emulates the behavior of JAVA2D - farray[index++] = - PApplet.ceil(x*mm.m00 + y*mm.m01 + z*mm.m02 + mm.m03); - farray[index++] = - PApplet.ceil(x*mm.m10 + y*mm.m11 + z*mm.m12 + mm.m13); - } else { - farray[index++] = x*mm.m00 + y*mm.m01 + z*mm.m02 + mm.m03; - farray[index++] = x*mm.m10 + y*mm.m11 + z*mm.m12 + mm.m13; - } - farray[index++] = x*mm.m20 + y*mm.m21 + z*mm.m22 + mm.m23; - farray[index ] = x*mm.m30 + y*mm.m31 + z*mm.m32 + mm.m33; - } else { - farray[index++] = x; - farray[index++] = y; - farray[index++] = z; - farray[index ] = 1; - } - } else if (attrib.isNormal()) { - float[] farray = fpolyAttribs.get(name); - float x = (float)d[pos + 0]; - float y = (float)d[pos + 1]; - float z = (float)d[pos + 2]; - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - farray[index++] = x*nm.m00 + y*nm.m10 + z*nm.m20; - farray[index++] = x*nm.m01 + y*nm.m11 + z*nm.m21; - farray[index ] = x*nm.m02 + y*nm.m12 + z*nm.m22; - } else { - farray[index++] = x; - farray[index++] = y; - farray[index ] = z; - } - pos += 3; - } else { - if (attrib.isFloat()) { - float[] farray = fpolyAttribs.get(name); - for (int n = 0; n < attrib.size; n++) { - farray[index++] = (float)d[pos++]; - } - } else if (attrib.isInt()) { - int[] iarray = ipolyAttribs.get(name); - for (int n = 0; n < attrib.size; n++) { - iarray[index++] = (int)d[pos++]; - } - } else if (attrib.isBool()) { - byte[] barray = bpolyAttribs.get(name); - for (int n = 0; n < attrib.size; n++) { - barray[index++] = (byte)d[pos++]; - } - } - pos += attrib.size; - } - } - } - } - - void addPolyVertex(float x, float y, float z, - int rgba, - float nx, float ny, float nz, - float u, float v, - int am, int sp, int em, float shine, - boolean clampXY) { - polyVertexCheck(); - int tessIdx = polyVertexCount - 1; - setPolyVertex(tessIdx, x, y, z, - rgba, - nx, ny, nz, - u, v, - am, sp, em, shine, clampXY); - } - - void setPolyVertex(int tessIdx, float x, float y, float z, int rgba, - boolean clampXY) { - setPolyVertex(tessIdx, x, y, z, - rgba, - 0, 0, 1, - 0, 0, - 0, 0, 0, 0, clampXY); - } - - void setPolyVertex(int tessIdx, float x, float y, float z, - int rgba, - float nx, float ny, float nz, - float u, float v, - int am, int sp, int em, float shine, - boolean clampXY) { - int index; - - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - PMatrix3D mm = pg.modelview; - PMatrix3D nm = pg.modelviewInv; - - index = 4 * tessIdx; - if (clampXY) { - // ceil emulates the behavior of JAVA2D - polyVertices[index++] = - PApplet.ceil(x*mm.m00 + y*mm.m01 + z*mm.m02 + mm.m03); - polyVertices[index++] = - PApplet.ceil(x*mm.m10 + y*mm.m11 + z*mm.m12 + mm.m13); - } else { - polyVertices[index++] = x*mm.m00 + y*mm.m01 + z*mm.m02 + mm.m03; - polyVertices[index++] = x*mm.m10 + y*mm.m11 + z*mm.m12 + mm.m13; - } - polyVertices[index++] = x*mm.m20 + y*mm.m21 + z*mm.m22 + mm.m23; - polyVertices[index ] = x*mm.m30 + y*mm.m31 + z*mm.m32 + mm.m33; - - index = 3 * tessIdx; - polyNormals[index++] = nx*nm.m00 + ny*nm.m10 + nz*nm.m20; - polyNormals[index++] = nx*nm.m01 + ny*nm.m11 + nz*nm.m21; - polyNormals[index ] = nx*nm.m02 + ny*nm.m12 + nz*nm.m22; - } else { - index = 4 * tessIdx; - polyVertices[index++] = x; - polyVertices[index++] = y; - polyVertices[index++] = z; - polyVertices[index ] = 1; - - index = 3 * tessIdx; - polyNormals[index++] = nx; - polyNormals[index++] = ny; - polyNormals[index ] = nz; - } - - polyColors[tessIdx] = rgba; - - index = 2 * tessIdx; - polyTexCoords[index++] = u; - polyTexCoords[index ] = v; - - polyAmbient[tessIdx] = am; - polySpecular[tessIdx] = sp; - polyEmissive[tessIdx] = em; - polyShininess[tessIdx] = shine; - } - - void addPolyVertices(InGeometry in, boolean clampXY) { - addPolyVertices(in, 0, in.vertexCount - 1, clampXY); - } - - void addPolyVertex(InGeometry in, int i, boolean clampXY) { - addPolyVertices(in, i, i, clampXY); - } - - void addPolyVertices(InGeometry in, int i0, int i1, boolean clampXY) { - int index = 0; - int nvert = i1 - i0 + 1; - - polyVertexCheck(nvert); - - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - modelviewCoords(in, i0, index, nvert, clampXY); - } else { - if (nvert <= PGL.MIN_ARRAYCOPY_SIZE) { - copyFewCoords(in, i0, index, nvert); - } else { - copyManyCoords(in, i0, index, nvert); - } - } - - if (nvert <= PGL.MIN_ARRAYCOPY_SIZE) { - copyFewAttribs(in, i0, index, nvert); - } else { - copyManyAttribs(in, i0, index, nvert); - } - } - - // Apply modelview transformation on the vertices - private void modelviewCoords(InGeometry in, int i0, int index, int nvert, boolean clampXY) { - PMatrix3D mm = pg.modelview; - PMatrix3D nm = pg.modelviewInv; - - for (int i = 0; i < nvert; i++) { - int inIdx = i0 + i; - int tessIdx = firstPolyVertex + i; - - index = 3 * inIdx; - float x = in.vertices[index++]; - float y = in.vertices[index++]; - float z = in.vertices[index ]; - - index = 3 * inIdx; - float nx = in.normals[index++]; - float ny = in.normals[index++]; - float nz = in.normals[index ]; - - index = 4 * tessIdx; - if (clampXY) { - // ceil emulates the behavior of JAVA2D - polyVertices[index++] = - PApplet.ceil(x*mm.m00 + y*mm.m01 + z*mm.m02 + mm.m03); - polyVertices[index++] = - PApplet.ceil(x*mm.m10 + y*mm.m11 + z*mm.m12 + mm.m13); - } else { - polyVertices[index++] = x*mm.m00 + y*mm.m01 + z*mm.m02 + mm.m03; - polyVertices[index++] = x*mm.m10 + y*mm.m11 + z*mm.m12 + mm.m13; - } - polyVertices[index++] = x*mm.m20 + y*mm.m21 + z*mm.m22 + mm.m23; - polyVertices[index ] = x*mm.m30 + y*mm.m31 + z*mm.m32 + mm.m33; - - index = 3 * tessIdx; - polyNormals[index++] = nx*nm.m00 + ny*nm.m10 + nz*nm.m20; - polyNormals[index++] = nx*nm.m01 + ny*nm.m11 + nz*nm.m21; - polyNormals[index ] = nx*nm.m02 + ny*nm.m12 + nz*nm.m22; - - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (attrib.isColor() || attrib.isOther()) continue; - - float[] inValues = in.fattribs.get(name); - index = 3 * inIdx; - x = inValues[index++]; - y = inValues[index++]; - z = inValues[index ]; - - float[] tessValues = fpolyAttribs.get(name); - if (attrib.isPosition()) { - index = 4 * tessIdx; - if (clampXY) { - // ceil emulates the behavior of JAVA2D - tessValues[index++] = - PApplet.ceil(x*mm.m00 + y*mm.m01 + z*mm.m02 + mm.m03); - tessValues[index++] = - PApplet.ceil(x*mm.m10 + y*mm.m11 + z*mm.m12 + mm.m13); - } else { - tessValues[index++] = x*mm.m00 + y*mm.m01 + z*mm.m02 + mm.m03; - tessValues[index++] = x*mm.m10 + y*mm.m11 + z*mm.m12 + mm.m13; - } - tessValues[index++] = x*mm.m20 + y*mm.m21 + z*mm.m22 + mm.m23; - tessValues[index ] = x*mm.m30 + y*mm.m31 + z*mm.m32 + mm.m33; - } else { - index = 3 * tessIdx; - tessValues[index++] = x*nm.m00 + y*nm.m10 + z*nm.m20; - tessValues[index++] = x*nm.m01 + y*nm.m11 + z*nm.m21; - tessValues[index ] = x*nm.m02 + y*nm.m12 + z*nm.m22; - } - } - } - } - - // Just copy vertices one by one. - private void copyFewCoords(InGeometry in, int i0, int index, int nvert) { - // Copying elements one by one instead of using arrayCopy is more - // efficient for few vertices... - for (int i = 0; i < nvert; i++) { - int inIdx = i0 + i; - int tessIdx = firstPolyVertex + i; - - index = 3 * inIdx; - float x = in.vertices[index++]; - float y = in.vertices[index++]; - float z = in.vertices[index ]; - - index = 3 * inIdx; - float nx = in.normals[index++]; - float ny = in.normals[index++]; - float nz = in.normals[index ]; - - index = 4 * tessIdx; - polyVertices[index++] = x; - polyVertices[index++] = y; - polyVertices[index++] = z; - polyVertices[index ] = 1; - - index = 3 * tessIdx; - polyNormals[index++] = nx; - polyNormals[index++] = ny; - polyNormals[index ] = nz; - - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (attrib.isColor() || attrib.isOther()) continue; - - float[] inValues = in.fattribs.get(name); - index = 3 * inIdx; - x = inValues[index++]; - y = inValues[index++]; - z = inValues[index ]; - - float[] tessValues = fpolyAttribs.get(name); - if (attrib.isPosition()) { - index = 4 * tessIdx; - tessValues[index++] = x; - tessValues[index++] = y; - tessValues[index++] = z; - tessValues[index ] = 1; - } else { - index = 3 * tessIdx; - tessValues[index++] = x; - tessValues[index++] = y; - tessValues[index ] = z; - } - } - } - } - - // Copy many vertices using arrayCopy - private void copyManyCoords(InGeometry in, int i0, int index, int nvert) { - for (int i = 0; i < nvert; i++) { - // Position data needs to be copied in batches of three, because the - // input vertices don't have a w coordinate. - int inIdx = i0 + i; - int tessIdx = firstPolyVertex + i; - PApplet.arrayCopy(in.vertices, 3 * inIdx, - polyVertices, 4 * tessIdx, 3); - polyVertices[4 * tessIdx + 3] = 1; - - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (!attrib.isPosition()) continue; - float[] inValues = in.fattribs.get(name); - float[] tessValues = fpolyAttribs.get(name); - PApplet.arrayCopy(inValues, 3 * inIdx, - tessValues, 4 * tessIdx, 3); - tessValues[4 * tessIdx + 3] = 1; - } - } - PApplet.arrayCopy(in.normals, 3 * i0, - polyNormals, 3 * firstPolyVertex, 3 * nvert); - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (!attrib.isNormal()) continue; - float[] inValues = in.fattribs.get(name); - float[] tessValues = fpolyAttribs.get(name); - PApplet.arrayCopy(inValues, 3 * i0, - tessValues, 3 * firstPolyVertex, 3 * nvert); - } - } - - // Just copy attributes one by one. - private void copyFewAttribs(InGeometry in, int i0, int index, int nvert) { - for (int i = 0; i < nvert; i++) { - int inIdx = i0 + i; - int tessIdx = firstPolyVertex + i; - - index = 2 * inIdx; - float u = in.texcoords[index++]; - float v = in.texcoords[index ]; - - polyColors[tessIdx] = in.colors[inIdx]; - - index = 2 * tessIdx; - polyTexCoords[index++] = u; - polyTexCoords[index ] = v; - - polyAmbient[tessIdx] = in.ambient[inIdx]; - polySpecular[tessIdx] = in.specular[inIdx]; - polyEmissive[tessIdx] = in.emissive[inIdx]; - polyShininess[tessIdx] = in.shininess[inIdx]; - - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (attrib.isPosition() || attrib.isNormal()) continue; - int index0 = attrib.size * inIdx; - int index1 = attrib.size * tessIdx; - if (attrib.isFloat()) { - float[] inValues = in.fattribs.get(name); - float[] tessValues = fpolyAttribs.get(name); - for (int n = 0; n < attrib.size; n++) { - tessValues[index1++] = inValues[index0++]; - } - } else if (attrib.isInt()) { - int[] inValues = in.iattribs.get(name); - int[] tessValues = ipolyAttribs.get(name); - for (int n = 0; n < attrib.size; n++) { - tessValues[index1++] = inValues[index0++]; - } - } else if (attrib.isBool()) { - byte[] inValues = in.battribs.get(name); - byte[] tessValues = bpolyAttribs.get(name); - for (int n = 0; n < attrib.size; n++) { - tessValues[index1++] = inValues[index0++]; - } - } - } - } - } - - // Copy many attributes using arrayCopy() - private void copyManyAttribs(InGeometry in, int i0, int index, int nvert) { - PApplet.arrayCopy(in.colors, i0, - polyColors, firstPolyVertex, nvert); - PApplet.arrayCopy(in.texcoords, 2 * i0, - polyTexCoords, 2 * firstPolyVertex, 2 * nvert); - PApplet.arrayCopy(in.ambient, i0, - polyAmbient, firstPolyVertex, nvert); - PApplet.arrayCopy(in.specular, i0, - polySpecular, firstPolyVertex, nvert); - PApplet.arrayCopy(in.emissive, i0, - polyEmissive, firstPolyVertex, nvert); - PApplet.arrayCopy(in.shininess, i0, - polyShininess, firstPolyVertex, nvert); - - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (attrib.isPosition() || attrib.isNormal()) continue; - Object inValues = null; - Object tessValues = null; - if (attrib.isFloat()) { - inValues = in.fattribs.get(name); - tessValues = fpolyAttribs.get(name); - } else if (attrib.isInt()) { - inValues = in.iattribs.get(name); - tessValues = ipolyAttribs.get(name); - } else if (attrib.isBool()) { - inValues = in.battribs.get(name); - tessValues = bpolyAttribs.get(name); - } - PApplet.arrayCopy(inValues, attrib.size * i0, - tessValues, attrib.tessSize * firstPolyVertex, - attrib.size * nvert); - } - } - - // ----------------------------------------------------------------- - // - // Matrix transformations - - void applyMatrixOnPolyGeometry(PMatrix tr, int first, int last) { - if (tr instanceof PMatrix2D) { - applyMatrixOnPolyGeometry((PMatrix2D) tr, first, last); - } else if (tr instanceof PMatrix3D) { - applyMatrixOnPolyGeometry((PMatrix3D) tr, first, last); - } - } - - void applyMatrixOnLineGeometry(PMatrix tr, int first, int last) { - if (tr instanceof PMatrix2D) { - applyMatrixOnLineGeometry((PMatrix2D) tr, first, last); - } else if (tr instanceof PMatrix3D) { - applyMatrixOnLineGeometry((PMatrix3D) tr, first, last); - } - } - - void applyMatrixOnPointGeometry(PMatrix tr, int first, int last) { - if (tr instanceof PMatrix2D) { - applyMatrixOnPointGeometry((PMatrix2D) tr, first, last); - } else if (tr instanceof PMatrix3D) { - applyMatrixOnPointGeometry((PMatrix3D) tr, first, last); - } - } - - void applyMatrixOnPolyGeometry(PMatrix2D tr, int first, int last) { - if (first < last) { - int index; - - for (int i = first; i <= last; i++) { - index = 4 * i; - float x = polyVertices[index++]; - float y = polyVertices[index ]; - - index = 3 * i; - float nx = polyNormals[index++]; - float ny = polyNormals[index ]; - - index = 4 * i; - polyVertices[index++] = x*tr.m00 + y*tr.m01 + tr.m02; - polyVertices[index ] = x*tr.m10 + y*tr.m11 + tr.m12; - - index = 3 * i; - polyNormals[index++] = nx*tr.m00 + ny*tr.m01; - polyNormals[index ] = nx*tr.m10 + ny*tr.m11; - - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (attrib.isColor() || attrib.isOther()) continue; - float[] values = fpolyAttribs.get(name); - if (attrib.isPosition()) { - index = 4 * i; - x = values[index++]; - y = values[index ]; - index = 4 * i; - values[index++] = x*tr.m00 + y*tr.m01 + tr.m02; - values[index ] = x*tr.m10 + y*tr.m11 + tr.m12; - } else { - index = 3 * i; - nx = values[index++]; - ny = values[index ]; - index = 3 * i; - values[index++] = nx*tr.m00 + ny*tr.m01; - values[index ] = nx*tr.m10 + ny*tr.m11; - } - } - } - } - } - - void applyMatrixOnLineGeometry(PMatrix2D tr, int first, int last) { - if (first < last) { - int index; - - float scaleFactor = matrixScale(tr); - for (int i = first; i <= last; i++) { - index = 4 * i; - float x = lineVertices[index++]; - float y = lineVertices[index ]; - - index = 4 * i; - float dx = lineDirections[index++]; - float dy = lineDirections[index ]; - - index = 4 * i; - lineVertices[index++] = x*tr.m00 + y*tr.m01 + tr.m02; - lineVertices[index ] = x*tr.m10 + y*tr.m11 + tr.m12; - - index = 4 * i; - lineDirections[index++] = dx*tr.m00 + dy*tr.m01; - lineDirections[index ] = dx*tr.m10 + dy*tr.m11; - lineDirections[index + 2] *= scaleFactor; - } - } - } - - void applyMatrixOnPointGeometry(PMatrix2D tr, int first, int last) { - if (first < last) { - int index; - - float matrixScale = matrixScale(tr); - for (int i = first; i <= last; i++) { - index = 4 * i; - float x = pointVertices[index++]; - float y = pointVertices[index ]; - - index = 4 * i; - pointVertices[index++] = x*tr.m00 + y*tr.m01 + tr.m02; - pointVertices[index ] = x*tr.m10 + y*tr.m11 + tr.m12; - - index = 2 * i; - pointOffsets[index++] *= matrixScale; - pointOffsets[index] *= matrixScale; - } - } - } - - void applyMatrixOnPolyGeometry(PMatrix3D tr, int first, int last) { - if (first < last) { - int index; - - for (int i = first; i <= last; i++) { - index = 4 * i; - float x = polyVertices[index++]; - float y = polyVertices[index++]; - float z = polyVertices[index++]; - float w = polyVertices[index ]; - - index = 3 * i; - float nx = polyNormals[index++]; - float ny = polyNormals[index++]; - float nz = polyNormals[index ]; - - index = 4 * i; - polyVertices[index++] = x*tr.m00 + y*tr.m01 + z*tr.m02 + w*tr.m03; - polyVertices[index++] = x*tr.m10 + y*tr.m11 + z*tr.m12 + w*tr.m13; - polyVertices[index++] = x*tr.m20 + y*tr.m21 + z*tr.m22 + w*tr.m23; - polyVertices[index ] = x*tr.m30 + y*tr.m31 + z*tr.m32 + w*tr.m33; - - index = 3 * i; - polyNormals[index++] = nx*tr.m00 + ny*tr.m01 + nz*tr.m02; - polyNormals[index++] = nx*tr.m10 + ny*tr.m11 + nz*tr.m12; - polyNormals[index ] = nx*tr.m20 + ny*tr.m21 + nz*tr.m22; - - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (attrib.isColor() || attrib.isOther()) continue; - float[] values = fpolyAttribs.get(name); - if (attrib.isPosition()) { - index = 4 * i; - x = values[index++]; - y = values[index++]; - z = values[index++]; - w = values[index ]; - index = 4 * i; - values[index++] = x*tr.m00 + y*tr.m01 + z*tr.m02 + w*tr.m03; - values[index++] = x*tr.m10 + y*tr.m11 + z*tr.m12 + w*tr.m13; - values[index++] = x*tr.m20 + y*tr.m21 + z*tr.m22 + w*tr.m23; - values[index ] = x*tr.m30 + y*tr.m31 + z*tr.m32 + w*tr.m33; - } else { - index = 3 * i; - nx = values[index++]; - ny = values[index++]; - nz = values[index ]; - index = 3 * i; - values[index++] = nx*tr.m00 + ny*tr.m01 + nz*tr.m02; - values[index++] = nx*tr.m10 + ny*tr.m11 + nz*tr.m12; - values[index ] = nx*tr.m20 + ny*tr.m21 + nz*tr.m22; - } - } - } - } - } - - void applyMatrixOnLineGeometry(PMatrix3D tr, int first, int last) { - if (first < last) { - int index; - - float scaleFactor = matrixScale(tr); - for (int i = first; i <= last; i++) { - index = 4 * i; - float x = lineVertices[index++]; - float y = lineVertices[index++]; - float z = lineVertices[index++]; - float w = lineVertices[index ]; - - index = 4 * i; - float dx = lineDirections[index++]; - float dy = lineDirections[index++]; - float dz = lineDirections[index ]; - - index = 4 * i; - lineVertices[index++] = x*tr.m00 + y*tr.m01 + z*tr.m02 + w*tr.m03; - lineVertices[index++] = x*tr.m10 + y*tr.m11 + z*tr.m12 + w*tr.m13; - lineVertices[index++] = x*tr.m20 + y*tr.m21 + z*tr.m22 + w*tr.m23; - lineVertices[index ] = x*tr.m30 + y*tr.m31 + z*tr.m32 + w*tr.m33; - - index = 4 * i; - lineDirections[index++] = dx*tr.m00 + dy*tr.m01 + dz*tr.m02; - lineDirections[index++] = dx*tr.m10 + dy*tr.m11 + dz*tr.m12; - lineDirections[index++] = dx*tr.m20 + dy*tr.m21 + dz*tr.m22; - lineDirections[index] *= scaleFactor; - } - } - } - - void applyMatrixOnPointGeometry(PMatrix3D tr, int first, int last) { - if (first < last) { - int index; - - float matrixScale = matrixScale(tr); - for (int i = first; i <= last; i++) { - index = 4 * i; - float x = pointVertices[index++]; - float y = pointVertices[index++]; - float z = pointVertices[index++]; - float w = pointVertices[index ]; - - index = 4 * i; - pointVertices[index++] = x*tr.m00 + y*tr.m01 + z*tr.m02 + w*tr.m03; - pointVertices[index++] = x*tr.m10 + y*tr.m11 + z*tr.m12 + w*tr.m13; - pointVertices[index++] = x*tr.m20 + y*tr.m21 + z*tr.m22 + w*tr.m23; - pointVertices[index ] = x*tr.m30 + y*tr.m31 + z*tr.m32 + w*tr.m33; - - index = 2 * i; - pointOffsets[index++] *= matrixScale; - pointOffsets[index] *= matrixScale; - } - } - } - } - - // Generates tessellated geometry given a batch of input vertices. - static protected class Tessellator { - InGeometry in; - TessGeometry tess; - TexCache texCache; - PImage prevTexImage; - PImage newTexImage; - int firstTexIndex; - int firstTexCache; - - PGL.Tessellator gluTess; - TessellatorCallback callback; - - boolean fill; - boolean stroke; - int strokeColor; - float strokeWeight; - int strokeJoin; - int strokeCap; - boolean accurate2DStrokes; - - PMatrix transform; - float transformScale; - boolean is2D, is3D; - protected PGraphicsOpenGL pg; - - int[] rawIndices; - int rawSize; - int[] dupIndices; - int dupCount; - - int firstPolyIndexCache; - int lastPolyIndexCache; - int firstLineIndexCache; - int lastLineIndexCache; - int firstPointIndexCache; - int lastPointIndexCache; - - // Accessor arrays to get the geometry data needed to tessellate the - // strokes, it can point to either the input geometry, or the internal - // path vertices generated in the polygon discretization. - float[] strokeVertices; - int[] strokeColors; - float[] strokeWeights; - - // Path vertex data that results from discretizing a polygon (i.e.: turning - // bezier, quadratic, and curve vertices into "regular" vertices). - int pathVertexCount; - float[] pathVertices; - int[] pathColors; - float[] pathWeights; - int beginPath; - - public Tessellator() { - rawIndices = new int[512]; - accurate2DStrokes = true; - transform = null; - is2D = false; - is3D = true; - } - - void initGluTess() { - if (gluTess == null) { - callback = new TessellatorCallback(tess.polyAttribs); - gluTess = pg.pgl.createTessellator(callback); - } - } - - void setInGeometry(InGeometry in) { - this.in = in; - - firstPolyIndexCache = -1; - lastPolyIndexCache = -1; - firstLineIndexCache = -1; - lastLineIndexCache = -1; - firstPointIndexCache = -1; - lastPointIndexCache = -1; - } - - void setTessGeometry(TessGeometry tess) { - this.tess = tess; - } - - void setFill(boolean fill) { - this.fill = fill; - } - - void setTexCache(TexCache texCache, PImage newTexImage) { - this.texCache = texCache; - this.newTexImage = newTexImage; - } - - void setStroke(boolean stroke) { - this.stroke = stroke; - } - - void setStrokeColor(int color) { - this.strokeColor = PGL.javaToNativeARGB(color); - } - - void setStrokeWeight(float weight) { - this.strokeWeight = weight; - } - - void setStrokeCap(int strokeCap) { - this.strokeCap = strokeCap; - } - - void setStrokeJoin(int strokeJoin) { - this.strokeJoin = strokeJoin; - } - - void setAccurate2DStrokes(boolean accurate) { - this.accurate2DStrokes = accurate; - } - - protected void setRenderer(PGraphicsOpenGL pg) { - this.pg = pg; - } - - void set3D(boolean value) { - if (value) { - this.is2D = false; - this.is3D = true; - } else { - this.is2D = true; - this.is3D = false; - } - } - - void setTransform(PMatrix transform) { - this.transform = transform; - transformScale = -1; - } - - void resetCurveVertexCount() { - pg.curveVertexCount = 0; - } - - // ----------------------------------------------------------------- - // - // Point tessellation - - void tessellatePoints() { - if (strokeCap == ROUND) { - tessellateRoundPoints(); - } else { - tessellateSquarePoints(); - } - } - - void tessellateRoundPoints() { - int nInVert = in.vertexCount; - if (stroke && 1 <= nInVert) { - // Each point generates a separate triangle fan. - // The number of triangles of each fan depends on the - // stroke weight of the point. - int nPtVert = - PApplet.min(MAX_POINT_ACCURACY, PApplet.max(MIN_POINT_ACCURACY, - (int) (TWO_PI * strokeWeight / - POINT_ACCURACY_FACTOR))) + 1; - if (PGL.MAX_VERTEX_INDEX1 <= nPtVert) { - throw new RuntimeException("Error in point tessellation."); - } - updateTex(); - int nvertTot = nPtVert * nInVert; - int nindTot = 3 * (nPtVert - 1) * nInVert; - if (is3D) { - tessellateRoundPoints3D(nvertTot, nindTot, nPtVert); - } else if (is2D) { - beginNoTex(); - tessellateRoundPoints2D(nvertTot, nindTot, nPtVert); - endNoTex(); - } - } - } - - void tessellateRoundPoints3D(int nvertTot, int nindTot, int nPtVert) { - int perim = nPtVert - 1; - tess.pointVertexCheck(nvertTot); - tess.pointIndexCheck(nindTot); - int vertIdx = tess.firstPointVertex; - int attribIdx = tess.firstPointVertex; - int indIdx = tess.firstPointIndex; - IndexCache cache = tess.pointIndexCache; - int index = in.renderMode == RETAINED ? cache.addNew() : cache.getLast(); - firstPointIndexCache = index; - for (int i = 0; i < in.vertexCount; i++) { - // Creating the triangle fan for each input vertex. - - int count = cache.vertexCount[index]; - if (PGL.MAX_VERTEX_INDEX1 <= count + nPtVert) { - // We need to start a new index block for this point. - index = cache.addNew(); - count = 0; - } - - // All the tessellated vertices are identical to the center point - for (int k = 0; k < nPtVert; k++) { - tess.setPointVertex(vertIdx, in, i); - vertIdx++; - } - - // The attributes for each tessellated vertex are the displacement along - // the circle perimeter. The point shader will read these attributes and - // displace the vertices in screen coordinates so the circles are always - // camera facing (bilboards) - tess.pointOffsets[2 * attribIdx + 0] = 0; - tess.pointOffsets[2 * attribIdx + 1] = 0; - attribIdx++; - float val = 0; - float inc = (float) SINCOS_LENGTH / perim; - for (int k = 0; k < perim; k++) { - tess.pointOffsets[2 * attribIdx + 0] = - 0.5f * cosLUT[(int) val] * transformScale() * strokeWeight; - tess.pointOffsets[2 * attribIdx + 1] = - 0.5f * sinLUT[(int) val] * transformScale() * strokeWeight; - val = (val + inc) % SINCOS_LENGTH; - attribIdx++; - } - - // Adding vert0 to take into account the triangles of all - // the preceding points. - for (int k = 1; k < nPtVert - 1; k++) { - tess.pointIndices[indIdx++] = (short) (count + 0); - tess.pointIndices[indIdx++] = (short) (count + k); - tess.pointIndices[indIdx++] = (short) (count + k + 1); - } - // Final triangle between the last and first point: - tess.pointIndices[indIdx++] = (short) (count + 0); - tess.pointIndices[indIdx++] = (short) (count + 1); - tess.pointIndices[indIdx++] = (short) (count + nPtVert - 1); - - cache.incCounts(index, 3 * (nPtVert - 1), nPtVert); - } - lastPointIndexCache = index; - } - - void tessellateRoundPoints2D(int nvertTot, int nindTot, int nPtVert) { - int perim = nPtVert - 1; - tess.polyVertexCheck(nvertTot); - tess.polyIndexCheck(nindTot); - int vertIdx = tess.firstPolyVertex; - int indIdx = tess.firstPolyIndex; - IndexCache cache = tess.polyIndexCache; - int index = in.renderMode == RETAINED ? cache.addNew() : cache.getLast(); - firstPointIndexCache = index; - if (firstPolyIndexCache == -1) firstPolyIndexCache = index; // If the geometry has no fill, needs the first poly index. - for (int i = 0; i < in.vertexCount; i++) { - int count = cache.vertexCount[index]; - if (PGL.MAX_VERTEX_INDEX1 <= count + nPtVert) { - // We need to start a new index block for this point. - index = cache.addNew(); - count = 0; - } - - float x0 = in.vertices[3 * i + 0]; - float y0 = in.vertices[3 * i + 1]; - int rgba = in.strokeColors[i]; - - float val = 0; - float inc = (float) SINCOS_LENGTH / perim; - tess.setPolyVertex(vertIdx, x0, y0, 0, rgba, false); - vertIdx++; - for (int k = 0; k < perim; k++) { - tess.setPolyVertex(vertIdx, - x0 + 0.5f * cosLUT[(int) val] * strokeWeight, - y0 + 0.5f * sinLUT[(int) val] * strokeWeight, - 0, rgba, false); - vertIdx++; - val = (val + inc) % SINCOS_LENGTH; - } - - // Adding vert0 to take into account the triangles of all - // the preceding points. - for (int k = 1; k < nPtVert - 1; k++) { - tess.polyIndices[indIdx++] = (short) (count + 0); - tess.polyIndices[indIdx++] = (short) (count + k); - tess.polyIndices[indIdx++] = (short) (count + k + 1); - } - // Final triangle between the last and first point: - tess.polyIndices[indIdx++] = (short) (count + 0); - tess.polyIndices[indIdx++] = (short) (count + 1); - tess.polyIndices[indIdx++] = (short) (count + nPtVert - 1); - - cache.incCounts(index, 3 * (nPtVert - 1), nPtVert); - } - lastPointIndexCache = lastPolyIndexCache = index; - } - - void tessellateSquarePoints() { - int nInVert = in.vertexCount; - if (stroke && 1 <= nInVert) { - updateTex(); - int quadCount = nInVert; // Each point generates a separate quad. - // Each quad is formed by 5 vertices, the center one - // is the input vertex, and the other 4 define the - // corners (so, a triangle fan again). - int nvertTot = 5 * quadCount; - // So the quad is formed by 4 triangles, each requires - // 3 indices. - int nindTot = 12 * quadCount; - if (is3D) { - tessellateSquarePoints3D(nvertTot, nindTot); - } else if (is2D) { - beginNoTex(); - tessellateSquarePoints2D(nvertTot, nindTot); - endNoTex(); - } - } - } - - void tessellateSquarePoints3D(int nvertTot, int nindTot) { - tess.pointVertexCheck(nvertTot); - tess.pointIndexCheck(nindTot); - int vertIdx = tess.firstPointVertex; - int attribIdx = tess.firstPointVertex; - int indIdx = tess.firstPointIndex; - IndexCache cache = tess.pointIndexCache; - int index = in.renderMode == RETAINED ? cache.addNew() : cache.getLast(); - firstPointIndexCache = index; - for (int i = 0; i < in.vertexCount; i++) { - int nvert = 5; - int count = cache.vertexCount[index]; - if (PGL.MAX_VERTEX_INDEX1 <= count + nvert) { - // We need to start a new index block for this point. - index = cache.addNew(); - count = 0; - } - - for (int k = 0; k < nvert; k++) { - tess.setPointVertex(vertIdx, in, i); - vertIdx++; - } - - // The attributes for each tessellated vertex are the displacement along - // the quad corners. The point shader will read these attributes and - // displace the vertices in screen coordinates so the quads are always - // camera facing (bilboards) - tess.pointOffsets[2 * attribIdx + 0] = 0; - tess.pointOffsets[2 * attribIdx + 1] = 0; - attribIdx++; - for (int k = 0; k < 4; k++) { - tess.pointOffsets[2 * attribIdx + 0] = - 0.5f * QUAD_POINT_SIGNS[k][0] * transformScale() * strokeWeight; - tess.pointOffsets[2 * attribIdx + 1] = - 0.5f * QUAD_POINT_SIGNS[k][1] * transformScale() * strokeWeight; - attribIdx++; - } - - // Adding firstVert to take into account the triangles of all - // the preceding points. - for (int k = 1; k < nvert - 1; k++) { - tess.pointIndices[indIdx++] = (short) (count + 0); - tess.pointIndices[indIdx++] = (short) (count + k); - tess.pointIndices[indIdx++] = (short) (count + k + 1); - } - // Final triangle between the last and first point: - tess.pointIndices[indIdx++] = (short) (count + 0); - tess.pointIndices[indIdx++] = (short) (count + 1); - tess.pointIndices[indIdx++] = (short) (count + nvert - 1); - - cache.incCounts(index, 12, 5); - } - lastPointIndexCache = index; - } - - void tessellateSquarePoints2D(int nvertTot, int nindTot) { - tess.polyVertexCheck(nvertTot); - tess.polyIndexCheck(nindTot); - boolean clamp = clampSquarePoints2D(); - int vertIdx = tess.firstPolyVertex; - int indIdx = tess.firstPolyIndex; - IndexCache cache = tess.polyIndexCache; - int index = in.renderMode == RETAINED ? cache.addNew() : cache.getLast(); - firstPointIndexCache = index; - if (firstPolyIndexCache == -1) firstPolyIndexCache = index; // If the geometry has no fill, needs the first poly index. - for (int i = 0; i < in.vertexCount; i++) { - int nvert = 5; - int count = cache.vertexCount[index]; - if (PGL.MAX_VERTEX_INDEX1 <= count + nvert) { - // We need to start a new index block for this point. - index = cache.addNew(); - count = 0; - } - - float x0 = in.vertices[3 * i + 0]; - float y0 = in.vertices[3 * i + 1]; - int rgba = in.strokeColors[i]; - - tess.setPolyVertex(vertIdx, x0, y0, 0, rgba, clamp); - vertIdx++; - for (int k = 0; k < nvert - 1; k++) { - tess.setPolyVertex(vertIdx, - x0 + 0.5f * QUAD_POINT_SIGNS[k][0] * strokeWeight, - y0 + 0.5f * QUAD_POINT_SIGNS[k][1] * strokeWeight, - 0, rgba, clamp); - vertIdx++; - } - - for (int k = 1; k < nvert - 1; k++) { - tess.polyIndices[indIdx++] = (short) (count + 0); - tess.polyIndices[indIdx++] = (short) (count + k); - tess.polyIndices[indIdx++] = (short) (count + k + 1); - } - // Final triangle between the last and first point: - tess.polyIndices[indIdx++] = (short) (count + 0); - tess.polyIndices[indIdx++] = (short) (count + 1); - tess.polyIndices[indIdx++] = (short) (count + nvert - 1); - - cache.incCounts(index, 12, 5); - } - lastPointIndexCache = lastPolyIndexCache = index; - } - - boolean clamp2D() { - return is2D && tess.renderMode == IMMEDIATE && - zero(pg.modelview.m01) && zero(pg.modelview.m10); - } - - boolean clampSquarePoints2D() { - return clamp2D(); - } - - // ----------------------------------------------------------------- - // - // Line tessellation - - void tessellateLines() { - int nInVert = in.vertexCount; - if (stroke && 2 <= nInVert) { - strokeVertices = in.vertices; - strokeColors = in.strokeColors; - strokeWeights = in.strokeWeights; - updateTex(); - int lineCount = nInVert / 2; // Each individual line is formed by two consecutive input vertices. - if (is3D) { - tessellateLines3D(lineCount); - } else if (is2D) { - beginNoTex(); // Line geometry in 2D are stored in the poly array next to the fill triangles, but w/out textures. - tessellateLines2D(lineCount); - endNoTex(); - } - } - } - - void tessellateLines3D(int lineCount) { - // Lines are made up of 4 vertices defining the quad. - int nvert = lineCount * 4; - // Each stroke line has 4 vertices, defining 2 triangles, which - // require 3 indices to specify their connectivities. - int nind = lineCount * 2 * 3; - - int vcount0 = tess.lineVertexCount; - int icount0 = tess.lineIndexCount; - tess.lineVertexCheck(nvert); - tess.lineIndexCheck(nind); - int index = in.renderMode == RETAINED ? tess.lineIndexCache.addNew() : - tess.lineIndexCache.getLast(); - firstLineIndexCache = index; - int[] tmp = {0, 0}; - tess.lineIndexCache.setCounter(tmp); - for (int ln = 0; ln < lineCount; ln++) { - int i0 = 2 * ln + 0; - int i1 = 2 * ln + 1; - index = addLineSegment3D(i0, i1, i0 - 2, i1 - 1, index, null, false); - } - // Adjust counts of line vertices and indices to exact values - tess.lineIndexCache.setCounter(null); - tess.lineIndexCount = icount0 + tmp[0]; - tess.lineVertexCount = vcount0 + tmp[1]; - lastLineIndexCache = index; - } - - void tessellateLines2D(int lineCount) { - int nvert = lineCount * 4; - int nind = lineCount * 2 * 3; - - if (noCapsJoins(nvert)) { - tess.polyVertexCheck(nvert); - tess.polyIndexCheck(nind); - int index = in.renderMode == RETAINED ? tess.polyIndexCache.addNew() : - tess.polyIndexCache.getLast(); - firstLineIndexCache = index; - if (firstPolyIndexCache == -1) firstPolyIndexCache = index; // If the geometry has no fill, needs the first poly index. - boolean clamp = clampLines2D(lineCount); - for (int ln = 0; ln < lineCount; ln++) { - int i0 = 2 * ln + 0; - int i1 = 2 * ln + 1; - index = addLineSegment2D(i0, i1, index, false, clamp); - } - lastLineIndexCache = lastPolyIndexCache = index; - } else { // full stroking algorithm - LinePath path = new LinePath(LinePath.WIND_NON_ZERO); - for (int ln = 0; ln < lineCount; ln++) { - int i0 = 2 * ln + 0; - int i1 = 2 * ln + 1; - path.moveTo(in.vertices[3 * i0 + 0], in.vertices[3 * i0 + 1], - in.strokeColors[i0]); - path.lineTo(in.vertices[3 * i1 + 0], in.vertices[3 * i1 + 1], - in.strokeColors[i1]); - } - tessellateLinePath(path); - } - } - - boolean clampLines2D(int lineCount) { - boolean res = clamp2D(); - if (res) { - for (int ln = 0; ln < lineCount; ln++) { - int i0 = 2 * ln + 0; - int i1 = 2 * ln + 1; - res = segmentIsAxisAligned(i0, i1); - if (!res) break; - } - } - return res; - } - - void tessellateLineStrip() { - int nInVert = in.vertexCount; - if (stroke && 2 <= nInVert) { - strokeVertices = in.vertices; - strokeColors = in.strokeColors; - strokeWeights = in.strokeWeights; - updateTex(); - int lineCount = nInVert - 1; - if (is3D) { - tessellateLineStrip3D(lineCount); - } else if (is2D) { - beginNoTex(); - tessellateLineStrip2D(lineCount); - endNoTex(); - } - } - } - - void tessellateLineStrip3D(int lineCount) { - int nBevelTr = noCapsJoins() ? 0 : (lineCount - 1); - int nvert = lineCount * 4 + nBevelTr * 3; - int nind = lineCount * 2 * 3 + nBevelTr * 2 * 3; - - int vcount0 = tess.lineVertexCount; - int icount0 = tess.lineIndexCount; - tess.lineVertexCheck(nvert); - tess.lineIndexCheck(nind); - int index = in.renderMode == RETAINED ? tess.lineIndexCache.addNew() : - tess.lineIndexCache.getLast(); - firstLineIndexCache = index; - int i0 = 0; - short[] lastInd = {-1, -1}; - int[] tmp = {0, 0}; - tess.lineIndexCache.setCounter(tmp); - for (int ln = 0; ln < lineCount; ln++) { - int i1 = ln + 1; - if (0 < nBevelTr) { - index = addLineSegment3D(i0, i1, i1 - 2, i1 - 1, index, lastInd, false); - } else { - index = addLineSegment3D(i0, i1, i1 - 2, i1 - 1, index, null, false); - } - i0 = i1; - } - // Adjust counts of line vertices and indices to exact values - tess.lineIndexCache.setCounter(null); - tess.lineIndexCount = icount0 + tmp[0]; - tess.lineVertexCount = vcount0 + tmp[1]; - lastLineIndexCache = index; - } - - void tessellateLineStrip2D(int lineCount) { - int nvert = lineCount * 4; - int nind = lineCount * 2 * 3; - - if (noCapsJoins(nvert)) { - tess.polyVertexCheck(nvert); - tess.polyIndexCheck(nind); - int index = in.renderMode == RETAINED ? tess.polyIndexCache.addNew() : - tess.polyIndexCache.getLast(); - firstLineIndexCache = index; - if (firstPolyIndexCache == -1) firstPolyIndexCache = index; // If the geometry has no fill, needs the first poly index. - int i0 = 0; - boolean clamp = clampLineStrip2D(lineCount); - for (int ln = 0; ln < lineCount; ln++) { - int i1 = ln + 1; - index = addLineSegment2D(i0, i1, index, false, clamp); - i0 = i1; - } - lastLineIndexCache = lastPolyIndexCache = index; - } else { // full stroking algorithm - LinePath path = new LinePath(LinePath.WIND_NON_ZERO); - path.moveTo(in.vertices[0], in.vertices[1], in.strokeColors[0]); - for (int ln = 0; ln < lineCount; ln++) { - int i1 = ln + 1; - path.lineTo(in.vertices[3 * i1 + 0], in.vertices[3 * i1 + 1], - in.strokeColors[i1]); - } - tessellateLinePath(path); - } - } - - boolean clampLineStrip2D(int lineCount) { - boolean res = clamp2D(); - if (res) { - for (int ln = 0; ln < lineCount; ln++) { - res = segmentIsAxisAligned(0, ln + 1); - if (!res) break; - } - } - return res; - } - - void tessellateLineLoop() { - int nInVert = in.vertexCount; - if (stroke && 2 <= nInVert) { - strokeVertices = in.vertices; - strokeColors = in.strokeColors; - strokeWeights = in.strokeWeights; - updateTex(); - int lineCount = nInVert; - if (is3D) { - tessellateLineLoop3D(lineCount); - } else if (is2D) { - beginNoTex(); - tessellateLineLoop2D(lineCount); - endNoTex(); - } - } - } - - void tessellateLineLoop3D(int lineCount) { - int nBevelTr = noCapsJoins() ? 0 : lineCount; - int nvert = lineCount * 4 + nBevelTr * 3; - int nind = lineCount * 2 * 3 + nBevelTr * 2 * 3; - - int vcount0 = tess.lineVertexCount; - int icount0 = tess.lineIndexCount; - tess.lineVertexCheck(nvert); - tess.lineIndexCheck(nind); - int index = in.renderMode == RETAINED ? tess.lineIndexCache.addNew() : - tess.lineIndexCache.getLast(); - firstLineIndexCache = index; - int i0 = 0; - int i1 = -1; - short[] lastInd = {-1, -1}; - int[] tmp = {0, 0}; - tess.lineIndexCache.setCounter(tmp); - for (int ln = 0; ln < lineCount - 1; ln++) { - i1 = ln + 1; - if (0 < nBevelTr) { - index = addLineSegment3D(i0, i1, i1 - 2, i1 - 1, index, lastInd, false); - } else { - index = addLineSegment3D(i0, i1, i1 - 2, i1 - 1, index, null, false); - } - i0 = i1; - } - index = addLineSegment3D(in.vertexCount - 1, 0, i1 - 2, i1 - 1, index, lastInd, false); - if (0 < nBevelTr) { - index = addBevel3D(0, 1, in.vertexCount - 1, 0, index, lastInd, false); - } - // Adjust counts of line vertices and indices to exact values - tess.lineIndexCache.setCounter(null); - tess.lineIndexCount = icount0 + tmp[0]; - tess.lineVertexCount = vcount0 + tmp[1]; - lastLineIndexCache = index; - } - - void tessellateLineLoop2D(int lineCount) { - int nvert = lineCount * 4; - int nind = lineCount * 2 * 3; - - if (noCapsJoins(nvert)) { - tess.polyVertexCheck(nvert); - tess.polyIndexCheck(nind); - int index = in.renderMode == RETAINED ? tess.polyIndexCache.addNew() : - tess.polyIndexCache.getLast(); - firstLineIndexCache = index; - if (firstPolyIndexCache == -1) firstPolyIndexCache = index; // If the geometry has no fill, needs the first poly index. - int i0 = 0; - boolean clamp = clampLineLoop2D(lineCount); - for (int ln = 0; ln < lineCount - 1; ln++) { - int i1 = ln + 1; - index = addLineSegment2D(i0, i1, index, false, clamp); - i0 = i1; - } - index = addLineSegment2D(0, in.vertexCount - 1, index, false, clamp); - lastLineIndexCache = lastPolyIndexCache = index; - } else { // full stroking algorithm - LinePath path = new LinePath(LinePath.WIND_NON_ZERO); - path.moveTo(in.vertices[0], in.vertices[1], in.strokeColors[0]); - for (int ln = 0; ln < lineCount - 1; ln++) { - int i1 = ln + 1; - path.lineTo(in.vertices[3 * i1 + 0], in.vertices[3 * i1 + 1], - in.strokeColors[i1]); - } - path.closePath(); - tessellateLinePath(path); - } - } - - boolean clampLineLoop2D(int lineCount) { - boolean res = clamp2D(); - if (res) { - for (int ln = 0; ln < lineCount; ln++) { - res = segmentIsAxisAligned(0, ln + 1); - if (!res) break; - } - } - return res; - } - - void tessellateEdges() { - if (stroke) { - if (in.edgeCount == 0) return; - strokeVertices = in.vertices; - strokeColors = in.strokeColors; - strokeWeights = in.strokeWeights; - if (is3D) { - tessellateEdges3D(); - } else if (is2D) { - beginNoTex(); - tessellateEdges2D(); - endNoTex(); - } - } - } - - void tessellateEdges3D() { - boolean bevel = !noCapsJoins(); - int nInVert = in.getNumEdgeVertices(bevel); - int nInInd = in.getNumEdgeIndices(bevel); - - int vcount0 = tess.lineVertexCount; - int icount0 = tess.lineIndexCount; - tess.lineVertexCheck(nInVert); - tess.lineIndexCheck(nInInd); - int index = in.renderMode == RETAINED ? tess.lineIndexCache.addNew() : - tess.lineIndexCache.getLast(); - firstLineIndexCache = index; - int fi0 = 0; - int fi1 = 0; - short[] lastInd = {-1, -1}; - int pi0 = -1; - int pi1 = -1; - - int[] tmp = {0, 0}; - tess.lineIndexCache.setCounter(tmp); - for (int i = 0; i <= in.edgeCount - 1; i++) { - int[] edge = in.edges[i]; - int i0 = edge[0]; - int i1 = edge[1]; - if (bevel) { - if (edge[2] == EDGE_CLOSE) { - index = addBevel3D(fi0, fi1, pi0, pi1, index, lastInd, false); - } else { - index = addLineSegment3D(i0, i1, pi0, pi1, index, lastInd, false); - } - } else if (edge[2] != EDGE_CLOSE) { - index = addLineSegment3D(i0, i1, pi0, pi1, index, null, false); - } - if (edge[2] == EDGE_START) { - fi0 = i0; - fi1 = i1; - } - - if (edge[2] == EDGE_STOP || edge[2] == EDGE_SINGLE || edge[2] == EDGE_CLOSE) { - // No join with next line segment. - lastInd[0] = lastInd[1] = -1; - pi1 = pi0 = -1; - } else { - pi0 = i0; - pi1 = i1; - } - } - // Adjust counts of line vertices and indices to exact values - tess.lineIndexCache.setCounter(null); - tess.lineIndexCount = icount0 + tmp[0]; - tess.lineVertexCount = vcount0 + tmp[1]; - - lastLineIndexCache = index; - } - - void tessellateEdges2D() { - int nInVert = in.getNumEdgeVertices(false); - if (noCapsJoins(nInVert)) { - int nInInd = in.getNumEdgeIndices(false); - - tess.polyVertexCheck(nInVert); - tess.polyIndexCheck(nInInd); - int index = in.renderMode == RETAINED ? tess.polyIndexCache.addNew() : - tess.polyIndexCache.getLast(); - firstLineIndexCache = index; - if (firstPolyIndexCache == -1) firstPolyIndexCache = index; // If the geometry has no fill, needs the first poly index. - boolean clamp = clampEdges2D(); - for (int i = 0; i <= in.edgeCount - 1; i++) { - int[] edge = in.edges[i]; - if (edge[2] == EDGE_CLOSE) continue; // ignoring edge closures when not doing caps or joins. - int i0 = edge[0]; - int i1 = edge[1]; - index = addLineSegment2D(i0, i1, index, false, clamp); - } - lastLineIndexCache = lastPolyIndexCache = index; - } else { // full stroking algorithm - LinePath path = new LinePath(LinePath.WIND_NON_ZERO); - for (int i = 0; i <= in.edgeCount - 1; i++) { - int[] edge = in.edges[i]; - int i0 = edge[0]; - int i1 = edge[1]; - switch (edge[2]) { - case EDGE_MIDDLE: - path.lineTo(strokeVertices[3 * i1 + 0], strokeVertices[3 * i1 + 1], - strokeColors[i1]); - break; - case EDGE_START: - path.moveTo(strokeVertices[3 * i0 + 0], strokeVertices[3 * i0 + 1], - strokeColors[i0]); - path.lineTo(strokeVertices[3 * i1 + 0], strokeVertices[3 * i1 + 1], - strokeColors[i1]); - break; - case EDGE_STOP: - path.lineTo(strokeVertices[3 * i1 + 0], strokeVertices[3 * i1 + 1], - strokeColors[i1]); - path.moveTo(strokeVertices[3 * i1 + 0], strokeVertices[3 * i1 + 1], - strokeColors[i1]); - break; - case EDGE_SINGLE: - path.moveTo(strokeVertices[3 * i0 + 0], strokeVertices[3 * i0 + 1], - strokeColors[i0]); - path.lineTo(strokeVertices[3 * i1 + 0], strokeVertices[3 * i1 + 1], - strokeColors[i1]); - path.moveTo(strokeVertices[3 * i1 + 0], strokeVertices[3 * i1 + 1], - strokeColors[i1]); - break; - case EDGE_CLOSE: - path.closePath(); - break; - } - } - tessellateLinePath(path); - } - } - - boolean clampEdges2D() { - boolean res = clamp2D(); - if (res) { - for (int i = 0; i <= in.edgeCount - 1; i++) { - int[] edge = in.edges[i]; - if (edge[2] == EDGE_CLOSE) continue; - int i0 = edge[0]; - int i1 = edge[1]; - res = segmentIsAxisAligned(strokeVertices, i0, i1); - if (!res) break; - } - } - return res; - } - - // Adding the data that defines a quad starting at vertex i0 and - // ending at i1. - int addLineSegment3D(int i0, int i1, int pi0, int pi1, int index, short[] lastInd, - boolean constStroke) { - IndexCache cache = tess.lineIndexCache; - int count = cache.vertexCount[index]; - boolean addBevel = lastInd != null && -1 < lastInd[0] && -1 < lastInd[1]; - boolean newCache = false; - if (PGL.MAX_VERTEX_INDEX1 <= count + 4 + (addBevel ? 1 : 0)) { - // We need to start a new index block for this line. - index = cache.addNew(); - count = 0; - newCache = true; - } - int iidx = cache.indexOffset[index] + cache.indexCount[index]; - int vidx = cache.vertexOffset[index] + cache.vertexCount[index]; - int color, color0; - float weight; - - color0 = color = constStroke ? strokeColor : strokeColors[i0]; - weight = constStroke ? strokeWeight : strokeWeights[i0]; - weight *= transformScale(); - - tess.setLineVertex(vidx++, strokeVertices, i0, i1, color, +weight/2); - tess.lineIndices[iidx++] = (short) (count + 0); - - tess.setLineVertex(vidx++, strokeVertices, i0, i1, color, -weight/2); - tess.lineIndices[iidx++] = (short) (count + 1); - - color = constStroke ? strokeColor : strokeColors[i1]; - weight = constStroke ? strokeWeight : strokeWeights[i1]; - weight *= transformScale(); - - tess.setLineVertex(vidx++, strokeVertices, i1, i0, color, -weight/2); - tess.lineIndices[iidx++] = (short) (count + 2); - - // Starting a new triangle re-using prev vertices. - tess.lineIndices[iidx++] = (short) (count + 2); - tess.lineIndices[iidx++] = (short) (count + 1); - - tess.setLineVertex(vidx++, strokeVertices, i1, i0, color, +weight/2); - tess.lineIndices[iidx++] = (short) (count + 3); - - cache.incCounts(index, 6, 4); - - if (lastInd != null) { - if (-1 < lastInd[0] && -1 < lastInd[1]) { - // Adding bevel triangles - if (newCache) { - if (-1 < pi0 && -1 < pi1) { - // Vertices used in the previous cache need to be copied to the - // newly created one - color = constStroke ? strokeColor : strokeColors[pi0]; - weight = constStroke ? strokeWeight : strokeWeights[pi0]; - weight *= transformScale(); - - tess.setLineVertex(vidx++, strokeVertices, pi1, color); - tess.setLineVertex(vidx++, strokeVertices, pi1, pi0, color, -weight/2); // count+2 vert from previous block - tess.setLineVertex(vidx, strokeVertices, pi1, pi0, color, +weight/2); // count+3 vert from previous block - - tess.lineIndices[iidx++] = (short) (count + 4); - tess.lineIndices[iidx++] = (short) (count + 5); - tess.lineIndices[iidx++] = (short) (count + 0); - - tess.lineIndices[iidx++] = (short) (count + 4); - tess.lineIndices[iidx++] = (short) (count + 6); - tess.lineIndices[iidx ] = (short) (count + 1); - - cache.incCounts(index, 6, 3); - } - } else { - tess.setLineVertex(vidx, strokeVertices, i0, color0); - - tess.lineIndices[iidx++] = (short) (count + 4); - tess.lineIndices[iidx++] = lastInd[0]; - tess.lineIndices[iidx++] = (short) (count + 0); - - tess.lineIndices[iidx++] = (short) (count + 4); - tess.lineIndices[iidx++] = lastInd[1]; - tess.lineIndices[iidx ] = (short) (count + 1); - - cache.incCounts(index, 6, 1); - } - } - - // The last two vertices of the segment will be used in the next - // bevel triangle - lastInd[0] = (short) (count + 2); - lastInd[1] = (short) (count + 3); - } - return index; - } - - int addBevel3D(int fi0, int fi1, int pi0 ,int pi1, int index, short[] lastInd, - boolean constStroke) { - IndexCache cache = tess.lineIndexCache; - int count = cache.vertexCount[index]; - boolean newCache = false; - if (PGL.MAX_VERTEX_INDEX1 <= count + 3) { - // We need to start a new index block for this line. - index = cache.addNew(); - count = 0; - newCache = true; - } - - int iidx = cache.indexOffset[index] + cache.indexCount[index]; - int vidx = cache.vertexOffset[index] + cache.vertexCount[index]; - int color = constStroke ? strokeColor : strokeColors[fi0]; - float weight = constStroke ? strokeWeight : strokeWeights[fi0]; - weight *= transformScale(); - - tess.setLineVertex(vidx++, strokeVertices, fi0, color); - tess.setLineVertex(vidx++, strokeVertices, fi0, fi1, color, +weight/2); - tess.setLineVertex(vidx++, strokeVertices, fi0, fi1, color, -weight/2); - - int extra = 0; - if (newCache && -1 < pi0 && -1 < pi1) { - // Vertices used in the previous cache need to be copied to the - // newly created one - color = constStroke ? strokeColor : strokeColors[pi1]; - weight = constStroke ? strokeWeight : strokeWeights[pi1]; - weight *= transformScale(); - - tess.setLineVertex(vidx++, strokeVertices, pi1, pi0, color, -weight/2); - tess.setLineVertex(vidx , strokeVertices, pi1, pi0, color, +weight/2); - - lastInd[0] = (short) (count + 3); - lastInd[1] = (short) (count + 4); - extra = 2; - } - - tess.lineIndices[iidx++] = (short) (count + 0); - tess.lineIndices[iidx++] = lastInd[0]; - tess.lineIndices[iidx++] = (short) (count + 1); - - tess.lineIndices[iidx++] = (short) (count + 0); - tess.lineIndices[iidx++] = (short) (count + 2); - tess.lineIndices[iidx ] = lastInd[1]; - - cache.incCounts(index, 6, 3 + extra); - - return index; - } - - // Adding the data that defines a quad starting at vertex i0 and - // ending at i1, in the case of pure 2D renderers (line geometry - // is added to the poly arrays). - int addLineSegment2D(int i0, int i1, int index, - boolean constStroke, boolean clamp) { - IndexCache cache = tess.polyIndexCache; - int count = cache.vertexCount[index]; - if (PGL.MAX_VERTEX_INDEX1 <= count + 4) { - // We need to start a new index block for this line. - index = cache.addNew(); - count = 0; - } - int iidx = cache.indexOffset[index] + cache.indexCount[index]; - int vidx = cache.vertexOffset[index] + cache.vertexCount[index]; - - int color = constStroke ? strokeColor : strokeColors[i0]; - float weight = constStroke ? strokeWeight : strokeWeights[i0]; - if (subPixelStroke(weight)) clamp = false; - - float x0 = strokeVertices[3 * i0 + 0]; - float y0 = strokeVertices[3 * i0 + 1]; - - float x1 = strokeVertices[3 * i1 + 0]; - float y1 = strokeVertices[3 * i1 + 1]; - - // Calculating direction and normal of the line. - float dirx = x1 - x0; - float diry = y1 - y0; - float llen = PApplet.sqrt(dirx * dirx + diry * diry); - float normx = 0, normy = 0; - float dirdx = 0, dirdy = 0; - if (nonZero(llen)) { - normx = -diry / llen; - normy = +dirx / llen; - - // Displacement along the direction of the line to force rounding to next - // integer and so making sure that no pixels are missing, some relevant - // links: - // http://stackoverflow.com/questions/10040961/opengl-pixel-perfect-2d-drawing - // http://msdn.microsoft.com/en-us/library/dd374282(VS.85) - dirdx = (dirx / llen) * PApplet.min(0.75f, weight/2); - dirdy = (diry / llen) * PApplet.min(0.75f, weight/2); - } - - float normdx = normx * weight/2; - float normdy = normy * weight/2; - - tess.setPolyVertex(vidx++, x0 + normdx - dirdx, y0 + normdy - dirdy, - 0, color, clamp); - tess.polyIndices[iidx++] = (short) (count + 0); - - tess.setPolyVertex(vidx++, x0 - normdx - dirdx, y0 - normdy - dirdy, - 0, color, clamp); - tess.polyIndices[iidx++] = (short) (count + 1); - - if (clamp) { - // Check for degeneracy due to coordinate clamping - float xac = tess.polyVertices[4 * (vidx - 2) + 0]; - float yac = tess.polyVertices[4 * (vidx - 2) + 1]; - float xbc = tess.polyVertices[4 * (vidx - 1) + 0]; - float ybc = tess.polyVertices[4 * (vidx - 1) + 1]; - if (same(xac, xbc) && same(yac, ybc)) { - unclampLine2D(vidx - 2, x0 + normdx - dirdx, y0 + normdy - dirdy); - unclampLine2D(vidx - 1, x0 - normdx - dirdx, y0 - normdy - dirdy); - } - } - - if (!constStroke) { - color = strokeColors[i1]; - weight = strokeWeights[i1]; - normdx = normx * weight/2; - normdy = normy * weight/2; - if (subPixelStroke(weight)) clamp = false; - } - - tess.setPolyVertex(vidx++, x1 - normdx + dirdx, y1 - normdy + dirdy, - 0, color, clamp); - tess.polyIndices[iidx++] = (short) (count + 2); - - // Starting a new triangle re-using prev vertices. - tess.polyIndices[iidx++] = (short) (count + 2); - tess.polyIndices[iidx++] = (short) (count + 0); - - tess.setPolyVertex(vidx++, x1 + normdx + dirdx, y1 + normdy + dirdy, - 0, color, clamp); - tess.polyIndices[iidx++] = (short) (count + 3); - - if (clamp) { - // Check for degeneracy due to coordinate clamping - float xac = tess.polyVertices[4 * (vidx - 2) + 0]; - float yac = tess.polyVertices[4 * (vidx - 2) + 1]; - float xbc = tess.polyVertices[4 * (vidx - 1) + 0]; - float ybc = tess.polyVertices[4 * (vidx - 1) + 1]; - if (same(xac, xbc) && same(yac, ybc)) { - unclampLine2D(vidx - 2, x1 - normdx + dirdx, y1 - normdy + dirdy); - unclampLine2D(vidx - 1, x1 + normdx + dirdx, y1 + normdy + dirdy); - } - } - - cache.incCounts(index, 6, 4); - return index; - } - - void unclampLine2D(int tessIdx, float x, float y) { - PMatrix3D mm = pg.modelview; - int index = 4 * tessIdx; - tess.polyVertices[index++] = x*mm.m00 + y*mm.m01 + mm.m03; - tess.polyVertices[index++] = x*mm.m10 + y*mm.m11 + mm.m13; - } - - boolean noCapsJoins(int nInVert) { - if (!accurate2DStrokes) { - return true; - } else if (PGL.MAX_CAPS_JOINS_LENGTH <= nInVert) { - // The line path is too long, so it could make the GLU tess - // to run out of memory, so full caps and joins are disabled. - return true; - } else { - return noCapsJoins(); - } - } - - boolean subPixelStroke(float weight) { - float sw = transformScale() * weight; - return PApplet.abs(sw - (int)sw) > 0; - } - - boolean noCapsJoins() { - // The stroke weight is scaled so it corresponds to the current - // "zoom level" being applied on the geometry due to scaling: - return tess.renderMode == IMMEDIATE && - transformScale() * strokeWeight < PGL.MIN_CAPS_JOINS_WEIGHT; - } - - float transformScale() { - if (-1 < transformScale) return transformScale; - return transformScale = matrixScale(transform); - } - - boolean segmentIsAxisAligned(int i0, int i1) { - return zero(in.vertices[3 * i0 + 0] - in.vertices[3 * i1 + 0]) || - zero(in.vertices[3 * i0 + 1] - in.vertices[3 * i1 + 1]); - } - - boolean segmentIsAxisAligned(float[] vertices, int i0, int i1) { - return zero(vertices[3 * i0 + 0] - vertices[3 * i1 + 0]) || - zero(vertices[3 * i0 + 1] - vertices[3 * i1 + 1]); - } - - // ----------------------------------------------------------------- - // - // Polygon primitives tessellation - - void tessellateTriangles() { - beginTex(); - int nTri = in.vertexCount / 3; - if (fill && 1 <= nTri) { - int nInInd = 3 * nTri; - setRawSize(nInInd); - int idx = 0; - boolean clamp = clampTriangles(); - for (int i = 0; i < 3 * nTri; i++) { - rawIndices[idx++] = i; - } - splitRawIndices(clamp); - } - endTex(); - tessellateEdges(); - } - - boolean clampTriangles() { - boolean res = clamp2D(); - if (res) { - int nTri = in.vertexCount / 3; - for (int i = 0; i < nTri; i++) { - int i0 = 3 * i + 0; - int i1 = 3 * i + 1; - int i2 = 3 * i + 2; - int count = 0; - if (segmentIsAxisAligned(i0, i1)) count++; - if (segmentIsAxisAligned(i0, i2)) count++; - if (segmentIsAxisAligned(i1, i2)) count++; - res = 1 < count; - if (!res) break; - } - } - return res; - } - - void tessellateTriangles(int[] indices) { - beginTex(); - int nInVert = in.vertexCount; - if (fill && 3 <= nInVert) { - int nInInd = indices.length; - setRawSize(nInInd); - PApplet.arrayCopy(indices, rawIndices, nInInd); - boolean clamp = clampTriangles(indices); - splitRawIndices(clamp); - } - endTex(); - tessellateEdges(); - } - - boolean clampTriangles(int[] indices) { - boolean res = clamp2D(); - if (res) { - int nTri = indices.length; - for (int i = 0; i < nTri; i++) { - int i0 = indices[3 * i + 0]; - int i1 = indices[3 * i + 1]; - int i2 = indices[3 * i + 2]; - int count = 0; - if (segmentIsAxisAligned(i0, i1)) count++; - if (segmentIsAxisAligned(i0, i2)) count++; - if (segmentIsAxisAligned(i1, i2)) count++; - res = 1 < count; - if (!res) break; - } - } - return res; - } - - void tessellateTriangleFan() { - beginTex(); - int nInVert = in.vertexCount; - if (fill && 3 <= nInVert) { - int nInInd = 3 * (nInVert - 2); - setRawSize(nInInd); - int idx = 0; - boolean clamp = clampTriangleFan(); - for (int i = 1; i < in.vertexCount - 1; i++) { - rawIndices[idx++] = 0; - rawIndices[idx++] = i; - rawIndices[idx++] = i + 1; - } - splitRawIndices(clamp); - } - endTex(); - tessellateEdges(); - } - - boolean clampTriangleFan() { - boolean res = clamp2D(); - if (res) { - for (int i = 1; i < in.vertexCount - 1; i++) { - int i0 = 0; - int i1 = i; - int i2 = i + 1; - int count = 0; - if (segmentIsAxisAligned(i0, i1)) count++; - if (segmentIsAxisAligned(i0, i2)) count++; - if (segmentIsAxisAligned(i1, i2)) count++; - res = 1 < count; - if (!res) break; - } - } - return res; - } - - void tessellateTriangleStrip() { - beginTex(); - int nInVert = in.vertexCount; - if (fill && 3 <= nInVert) { - int nInInd = 3 * (nInVert - 2); - setRawSize(nInInd); - int idx = 0; - boolean clamp = clampTriangleStrip(); - for (int i = 1; i < in.vertexCount - 1; i++) { - rawIndices[idx++] = i; - if (i % 2 == 0) { - rawIndices[idx++] = i - 1; - rawIndices[idx++] = i + 1; - } else { - rawIndices[idx++] = i + 1; - rawIndices[idx++] = i - 1; - } - } - splitRawIndices(clamp); - } - endTex(); - tessellateEdges(); - } - - boolean clampTriangleStrip() { - boolean res = clamp2D(); - if (res) { - for (int i = 1; i < in.vertexCount - 1; i++) { - int i0 = i; - int i1, i2; - if (i % 2 == 0) { - i1 = i - 1; - i2 = i + 1; - } else { - i1 = i + 1; - i2 = i - 1; - } - int count = 0; - if (segmentIsAxisAligned(i0, i1)) count++; - if (segmentIsAxisAligned(i0, i2)) count++; - if (segmentIsAxisAligned(i1, i2)) count++; - res = 1 < count; - if (!res) break; - } - } - return res; - } - - void tessellateQuads() { - beginTex(); - int quadCount = in.vertexCount / 4; - if (fill && 1 <= quadCount) { - int nInInd = 6 * quadCount; - setRawSize(nInInd); - int idx = 0; - boolean clamp = clampQuads(quadCount); - for (int qd = 0; qd < quadCount; qd++) { - int i0 = 4 * qd + 0; - int i1 = 4 * qd + 1; - int i2 = 4 * qd + 2; - int i3 = 4 * qd + 3; - - rawIndices[idx++] = i0; - rawIndices[idx++] = i1; - rawIndices[idx++] = i2; - - rawIndices[idx++] = i2; - rawIndices[idx++] = i3; - rawIndices[idx++] = i0; - } - splitRawIndices(clamp); - } - endTex(); - tessellateEdges(); - } - - boolean clampQuads(int quadCount) { - boolean res = clamp2D(); - if (res) { - for (int qd = 0; qd < quadCount; qd++) { - int i0 = 4 * qd + 0; - int i1 = 4 * qd + 1; - int i2 = 4 * qd + 2; - int i3 = 4 * qd + 3; - res = segmentIsAxisAligned(i0, i1) && - segmentIsAxisAligned(i1, i2) && - segmentIsAxisAligned(i2, i3); - if (!res) break; - } - } - return res; - } - - void tessellateQuadStrip() { - beginTex(); - int quadCount = in.vertexCount / 2 - 1; - if (fill && 1 <= quadCount) { - int nInInd = 6 * quadCount; - setRawSize(nInInd); - int idx = 0; - boolean clamp = clampQuadStrip(quadCount); - for (int qd = 1; qd < quadCount + 1; qd++) { - int i0 = 2 * (qd - 1); - int i1 = 2 * (qd - 1) + 1; - int i2 = 2 * qd + 1; - int i3 = 2 * qd; - - rawIndices[idx++] = i0; - rawIndices[idx++] = i1; - rawIndices[idx++] = i3; - - rawIndices[idx++] = i1; - rawIndices[idx++] = i2; - rawIndices[idx++] = i3; - } - splitRawIndices(clamp); - } - endTex(); - tessellateEdges(); - } - - boolean clampQuadStrip(int quadCount) { - boolean res = clamp2D(); - if (res) { - for (int qd = 1; qd < quadCount + 1; qd++) { - int i0 = 2 * (qd - 1); - int i1 = 2 * (qd - 1) + 1; - int i2 = 2 * qd + 1; - int i3 = 2 * qd; - res = segmentIsAxisAligned(i0, i1) && - segmentIsAxisAligned(i1, i2) && - segmentIsAxisAligned(i2, i3); - if (!res) break; - } - } - return res; - } - - // Uses the raw indices to split the geometry into contiguous - // index groups when the vertex indices become too large. The basic - // idea of this algorithm is to scan through the array of raw indices - // in groups of three vertices at the time (since we are always dealing - // with triangles) and create a new offset in the index cache once the - // index values go above the MAX_VERTEX_INDEX constant. The tricky part - // is that triangles in the new group might refer to vertices in a - // previous group. Since the index groups are by definition disjoint, - // these vertices need to be duplicated at the end of the corresponding - // region in the vertex array. - // - // Also to keep in mind, the ordering of the indices affects performance - // take a look at some of this references: - // http://gameangst.com/?p=9 - // http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html - // http://www.ludicon.com/castano/blog/2009/02/optimal-grid-rendering/ - void splitRawIndices(boolean clamp) { - tess.polyIndexCheck(rawSize); - int offset = tess.firstPolyIndex; - - // Current index and vertex ranges - int inInd0 = 0, inInd1 = 0; - int inMaxVert0 = 0, inMaxVert1 = 0; - - int inMaxVertRef = inMaxVert0; // Reference vertex where last break split occurred - int inMaxVertRel = -1; // Position of vertices from last range relative to - // split position. - dupCount = 0; - - IndexCache cache = tess.polyIndexCache; - // In retained mode, each shape has with its own cache item, since - // they should always be available to be rendered individually, even - // if contained in a larger hierarchy. - int index = in.renderMode == RETAINED ? cache.addNew() : cache.getLast(); - firstPolyIndexCache = index; - - int trCount = rawSize / 3; - for (int tr = 0; tr < trCount; tr++) { - if (index == -1) index = cache.addNew(); - - int i0 = rawIndices[3 * tr + 0]; - int i1 = rawIndices[3 * tr + 1]; - int i2 = rawIndices[3 * tr + 2]; - - // Vertex indices relative to the last copy position. - int ii0 = i0 - inMaxVertRef; - int ii1 = i1 - inMaxVertRef; - int ii2 = i2 - inMaxVertRef; - - // Vertex indices relative to the current group. - int count = cache.vertexCount[index]; - int ri0, ri1, ri2; - if (ii0 < 0) { - addDupIndex(ii0); - ri0 = ii0; - } else ri0 = count + ii0; - if (ii1 < 0) { - addDupIndex(ii1); - ri1 = ii1; - } else ri1 = count + ii1; - if (ii2 < 0) { - addDupIndex(ii2); - ri2 = ii2; - } else ri2 = count + ii2; - - tess.polyIndices[offset + 3 * tr + 0] = (short) ri0; - tess.polyIndices[offset + 3 * tr + 1] = (short) ri1; - tess.polyIndices[offset + 3 * tr + 2] = (short) ri2; - - inInd1 = 3 * tr + 2; - inMaxVert1 = PApplet.max(inMaxVert1, PApplet.max(i0, i1, i2)); - inMaxVert0 = PApplet.min(inMaxVert0, PApplet.min(i0, i1, i2)); - - inMaxVertRel = PApplet.max(inMaxVertRel, PApplet.max(ri0, ri1, ri2)); - - if ((PGL.MAX_VERTEX_INDEX1 - 3 <= inMaxVertRel + dupCount && - inMaxVertRel + dupCount < PGL.MAX_VERTEX_INDEX1) || - (tr == trCount - 1)) { - // The vertex indices of the current group are about to - // surpass the MAX_VERTEX_INDEX limit, or we are at the last triangle - // so we need to wrap-up things anyways. - - int nondupCount = 0; - if (0 < dupCount) { - // Adjusting the negative indices so they correspond to vertices - // added at the end of the block. - for (int i = inInd0; i <= inInd1; i++) { - int ri = tess.polyIndices[offset + i]; - if (ri < 0) { - tess.polyIndices[offset + i] = - (short) (inMaxVertRel + 1 + dupIndexPos(ri)); - } - } - - if (inMaxVertRef <= inMaxVert1) { - // Copy non-duplicated vertices from current region first - tess.addPolyVertices(in, inMaxVertRef, inMaxVert1, clamp); - nondupCount = inMaxVert1 - inMaxVertRef + 1; - } - - // Copy duplicated vertices from previous regions last - for (int i = 0; i < dupCount; i++) { - tess.addPolyVertex(in, dupIndices[i] + inMaxVertRef, clamp); - } - } else { - // Copy non-duplicated vertices from current region first - tess.addPolyVertices(in, inMaxVert0, inMaxVert1, clamp); - nondupCount = inMaxVert1 - inMaxVert0 + 1; - } - - // Increment counts: - cache.incCounts(index, inInd1 - inInd0 + 1, nondupCount + dupCount); - lastPolyIndexCache = index; - - // Prepare all variables to start next cache: - index = -1; - inMaxVertRel = -1; - inMaxVertRef = inMaxVert1 + 1; - inMaxVert0 = inMaxVertRef; - inInd0 = inInd1 + 1; - if (dupIndices != null) Arrays.fill(dupIndices, 0, dupCount, 0); - dupCount = 0; - } - } - } - - void addDupIndex(int idx) { - if (dupIndices == null) { - dupIndices = new int[16]; - } - if (dupIndices.length == dupCount) { - int n = dupCount << 1; - - int temp[] = new int[n]; - PApplet.arrayCopy(dupIndices, 0, temp, 0, dupCount); - dupIndices = temp; - } - - if (idx < dupIndices[0]) { - // Add at the beginning - for (int i = dupCount; i > 0; i--) dupIndices[i] = dupIndices[i - 1]; - dupIndices[0] = idx; - dupCount++; - } else if (dupIndices[dupCount - 1] < idx) { - // Add at the end - dupIndices[dupCount] = idx; - dupCount++; - } else { - for (int i = 0; i < dupCount - 1; i++) { - if (dupIndices[i] == idx) break; - if (dupIndices[i] < idx && idx < dupIndices[i + 1]) { - // Insert between i and i + 1: - for (int j = dupCount; j > i + 1; j--) { - dupIndices[j] = dupIndices[j - 1]; - } - dupIndices[i + 1] = idx; - dupCount++; - break; - } - } - } - } - - int dupIndexPos(int idx) { - for (int i = 0; i < dupCount; i++) { - if (dupIndices[i] == idx) return i; - } - return 0; - } - - void setRawSize(int size) { - int size0 = rawIndices.length; - if (size0 < size) { - int size1 = expandArraySize(size0, size); - expandRawIndices(size1); - } - rawSize = size; - } - - void expandRawIndices(int n) { - int temp[] = new int[n]; - PApplet.arrayCopy(rawIndices, 0, temp, 0, rawSize); - rawIndices = temp; - } - - void beginTex() { - setFirstTexIndex(tess.polyIndexCount, tess.polyIndexCache.size - 1); - } - - void endTex() { - setLastTexIndex(tess.lastPolyIndex, tess.polyIndexCache.size - 1); - } - - void beginNoTex() { - newTexImage = null; - setFirstTexIndex(tess.polyIndexCount, tess.polyIndexCache.size - 1); - } - - void endNoTex() { - setLastTexIndex(tess.lastPolyIndex, tess.polyIndexCache.size - 1); - } - - void updateTex() { - beginTex(); - endTex(); - } - - void setFirstTexIndex(int firstIndex, int firstCache) { - if (texCache != null) { - firstTexIndex = firstIndex; - firstTexCache = PApplet.max(0, firstCache); - } - } - - void setLastTexIndex(int lastIndex, int lastCache) { - if (texCache != null) { - if (prevTexImage != newTexImage || texCache.size == 0) { - texCache.addTexture(newTexImage, firstTexIndex, firstTexCache, - lastIndex, lastCache); - } else { - texCache.setLastIndex(lastIndex, lastCache); - } - prevTexImage = newTexImage; - } - } - - // ----------------------------------------------------------------- - // - // Polygon tessellation, includes edge calculation and tessellation. - - void tessellatePolygon(boolean solid, boolean closed, boolean calcNormals) { - beginTex(); - - int nInVert = in.vertexCount; - - if (3 <= nInVert) { - firstPolyIndexCache = -1; - - initGluTess(); - boolean clamp = clampPolygon(); - callback.init(in.renderMode == RETAINED, false, calcNormals, clamp); - - if (fill) { - gluTess.beginPolygon(); - if (solid) { - // Using NONZERO winding rule for solid polygons. - gluTess.setWindingRule(PGL.TESS_WINDING_NONZERO); - } else { - // Using ODD winding rule to generate polygon with holes. - gluTess.setWindingRule(PGL.TESS_WINDING_ODD); - } - gluTess.beginContour(); - } - - if (stroke) { - beginPolygonStroke(); - beginStrokePath(); - } - - int i = 0; - int c = 0; - while (i < in.vertexCount) { - int code = VERTEX; - boolean brk = false; - if (in.codes != null && c < in.codeCount) { - code = in.codes[c++]; - if (code == BREAK && c < in.codeCount) { - brk = true; - code = in.codes[c++]; - } - } - - if (brk) { - if (stroke) { - endStrokePath(closed); - beginStrokePath(); - } - if (fill) { - gluTess.endContour(); - gluTess.beginContour(); - } - } - - if (code == BEZIER_VERTEX) { - addBezierVertex(i); - i += 3; - } else if (code == QUADRATIC_VERTEX) { - addQuadraticVertex(i); - i += 2; - } else if (code == CURVE_VERTEX) { - addCurveVertex(i); - i++; - } else { - addVertex(i); - i++; - } - } - if (stroke) { - endStrokePath(closed); - endPolygonStroke(); - } - if (fill) { - gluTess.endContour(); - gluTess.endPolygon(); - } - } - endTex(); - - if (stroke) tessellateStrokePath(); - } - - void addBezierVertex(int i) { - pg.curveVertexCount = 0; - pg.bezierInitCheck(); - pg.bezierVertexCheck(POLYGON, i); - - PMatrix3D draw = pg.bezierDrawMatrix; - - int i1 = i - 1; - float x1 = in.vertices[3*i1 + 0]; - float y1 = in.vertices[3*i1 + 1]; - float z1 = in.vertices[3*i1 + 2]; - - int strokeColor = 0; - float strokeWeight = 0; - if (stroke) { - strokeColor = in.strokeColors[i]; - strokeWeight = in.strokeWeights[i]; - } - - double[] vertexT = fill ? collectVertexAttributes(i) : null; - - float x2 = in.vertices[3*i + 0]; - float y2 = in.vertices[3*i + 1]; - float z2 = in.vertices[3*i + 2]; - float x3 = in.vertices[3*(i+1) + 0]; - float y3 = in.vertices[3*(i+1) + 1]; - float z3 = in.vertices[3*(i+1) + 2]; - float x4 = in.vertices[3*(i+2) + 0]; - float y4 = in.vertices[3*(i+2) + 1]; - float z4 = in.vertices[3*(i+2) + 2]; - - float xplot1 = draw.m10*x1 + draw.m11*x2 + draw.m12*x3 + draw.m13*x4; - float xplot2 = draw.m20*x1 + draw.m21*x2 + draw.m22*x3 + draw.m23*x4; - float xplot3 = draw.m30*x1 + draw.m31*x2 + draw.m32*x3 + draw.m33*x4; - - float yplot1 = draw.m10*y1 + draw.m11*y2 + draw.m12*y3 + draw.m13*y4; - float yplot2 = draw.m20*y1 + draw.m21*y2 + draw.m22*y3 + draw.m23*y4; - float yplot3 = draw.m30*y1 + draw.m31*y2 + draw.m32*y3 + draw.m33*y4; - - float zplot1 = draw.m10*z1 + draw.m11*z2 + draw.m12*z3 + draw.m13*z4; - float zplot2 = draw.m20*z1 + draw.m21*z2 + draw.m22*z3 + draw.m23*z4; - float zplot3 = draw.m30*z1 + draw.m31*z2 + draw.m32*z3 + draw.m33*z4; - - for (int j = 0; j < pg.bezierDetail; j++) { - x1 += xplot1; xplot1 += xplot2; xplot2 += xplot3; - y1 += yplot1; yplot1 += yplot2; yplot2 += yplot3; - z1 += zplot1; zplot1 += zplot2; zplot2 += zplot3; - if (fill) { - double[] vertex = Arrays.copyOf(vertexT, vertexT.length); - vertex[0] = x1; - vertex[1] = y1; - vertex[2] = z1; - gluTess.addVertex(vertex); - } - if (stroke) addStrokeVertex(x1, y1, z1, strokeColor, strokeWeight); - } - } - - void addQuadraticVertex(int i) { - pg.curveVertexCount = 0; - pg.bezierInitCheck(); - pg.bezierVertexCheck(POLYGON, i); - - PMatrix3D draw = pg.bezierDrawMatrix; - - int i1 = i - 1; - float x1 = in.vertices[3*i1 + 0]; - float y1 = in.vertices[3*i1 + 1]; - float z1 = in.vertices[3*i1 + 2]; - - int strokeColor = 0; - float strokeWeight = 0; - if (stroke) { - strokeColor = in.strokeColors[i]; - strokeWeight = in.strokeWeights[i]; - } - - double[] vertexT = fill ? collectVertexAttributes(i) : null; - - float cx = in.vertices[3*i + 0]; - float cy = in.vertices[3*i + 1]; - float cz = in.vertices[3*i + 2]; - float x = in.vertices[3*(i+1) + 0]; - float y = in.vertices[3*(i+1) + 1]; - float z = in.vertices[3*(i+1) + 2]; - - float x2 = x1 + ((cx-x1)*2/3.0f); - float y2 = y1 + ((cy-y1)*2/3.0f); - float z2 = z1 + ((cz-z1)*2/3.0f); - float x3 = x + ((cx-x)*2/3.0f); - float y3 = y + ((cy-y)*2/3.0f); - float z3 = z + ((cz-z)*2/3.0f); - float x4 = x; - float y4 = y; - float z4 = z; - - float xplot1 = draw.m10*x1 + draw.m11*x2 + draw.m12*x3 + draw.m13*x4; - float xplot2 = draw.m20*x1 + draw.m21*x2 + draw.m22*x3 + draw.m23*x4; - float xplot3 = draw.m30*x1 + draw.m31*x2 + draw.m32*x3 + draw.m33*x4; - - float yplot1 = draw.m10*y1 + draw.m11*y2 + draw.m12*y3 + draw.m13*y4; - float yplot2 = draw.m20*y1 + draw.m21*y2 + draw.m22*y3 + draw.m23*y4; - float yplot3 = draw.m30*y1 + draw.m31*y2 + draw.m32*y3 + draw.m33*y4; - - float zplot1 = draw.m10*z1 + draw.m11*z2 + draw.m12*z3 + draw.m13*z4; - float zplot2 = draw.m20*z1 + draw.m21*z2 + draw.m22*z3 + draw.m23*z4; - float zplot3 = draw.m30*z1 + draw.m31*z2 + draw.m32*z3 + draw.m33*z4; - - for (int j = 0; j < pg.bezierDetail; j++) { - x1 += xplot1; xplot1 += xplot2; xplot2 += xplot3; - y1 += yplot1; yplot1 += yplot2; yplot2 += yplot3; - z1 += zplot1; zplot1 += zplot2; zplot2 += zplot3; - if (fill) { - double[] vertex = Arrays.copyOf(vertexT, vertexT.length); - vertex[0] = x1; - vertex[1] = y1; - vertex[2] = z1; - gluTess.addVertex(vertex); - } - if (stroke) addStrokeVertex(x1, y1, z1, strokeColor, strokeWeight); - } - } - - void addCurveVertex(int i) { - pg.curveVertexCheck(POLYGON); - - float[] vertex = pg.curveVertices[pg.curveVertexCount]; - vertex[X] = in.vertices[3*i + 0]; - vertex[Y] = in.vertices[3*i + 1]; - vertex[Z] = in.vertices[3*i + 2]; - pg.curveVertexCount++; - - // draw a segment if there are enough points - if (pg.curveVertexCount == 3) { - float[] v = pg.curveVertices[pg.curveVertexCount - 2]; - addCurveInitialVertex(i, v[X], v[Y], v[Z]); - } - if (pg.curveVertexCount > 3) { - float[] v1 = pg.curveVertices[pg.curveVertexCount - 4]; - float[] v2 = pg.curveVertices[pg.curveVertexCount - 3]; - float[] v3 = pg.curveVertices[pg.curveVertexCount - 2]; - float[] v4 = pg.curveVertices[pg.curveVertexCount - 1]; - addCurveVertexSegment(i, v1[X], v1[Y], v1[Z], - v2[X], v2[Y], v2[Z], - v3[X], v3[Y], v3[Z], - v4[X], v4[Y], v4[Z]); - } - } - - void addCurveInitialVertex(int i, float x, float y, float z) { - if (fill) { - double[] vertex0 = collectVertexAttributes(i); - vertex0[0] = x; - vertex0[1] = y; - vertex0[2] = z; - gluTess.addVertex(vertex0); - } - if (stroke) { - addStrokeVertex(x, y, z, in.strokeColors[i], strokeWeight); - } - } - - void addCurveVertexSegment(int i, float x1, float y1, float z1, - float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - int strokeColor = 0; - float strokeWeight = 0; - if (stroke) { - strokeColor = in.strokeColors[i]; - strokeWeight = in.strokeWeights[i]; - } - - double[] vertexT = fill ? collectVertexAttributes(i) : null; - - float x = x2; - float y = y2; - float z = z2; - - PMatrix3D draw = pg.curveDrawMatrix; - - float xplot1 = draw.m10*x1 + draw.m11*x2 + draw.m12*x3 + draw.m13*x4; - float xplot2 = draw.m20*x1 + draw.m21*x2 + draw.m22*x3 + draw.m23*x4; - float xplot3 = draw.m30*x1 + draw.m31*x2 + draw.m32*x3 + draw.m33*x4; - - float yplot1 = draw.m10*y1 + draw.m11*y2 + draw.m12*y3 + draw.m13*y4; - float yplot2 = draw.m20*y1 + draw.m21*y2 + draw.m22*y3 + draw.m23*y4; - float yplot3 = draw.m30*y1 + draw.m31*y2 + draw.m32*y3 + draw.m33*y4; - - float zplot1 = draw.m10*z1 + draw.m11*z2 + draw.m12*z3 + draw.m13*z4; - float zplot2 = draw.m20*z1 + draw.m21*z2 + draw.m22*z3 + draw.m23*z4; - float zplot3 = draw.m30*z1 + draw.m31*z2 + draw.m32*z3 + draw.m33*z4; - - for (int j = 0; j < pg.curveDetail; j++) { - x += xplot1; xplot1 += xplot2; xplot2 += xplot3; - y += yplot1; yplot1 += yplot2; yplot2 += yplot3; - z += zplot1; zplot1 += zplot2; zplot2 += zplot3; - if (fill) { - double[] vertex1 = Arrays.copyOf(vertexT, vertexT.length); - vertex1[0] = x; - vertex1[1] = y; - vertex1[2] = z; - gluTess.addVertex(vertex1); - } - if (stroke) addStrokeVertex(x, y, z, strokeColor, strokeWeight); - } - } - - void addVertex(int i) { - pg.curveVertexCount = 0; - - float x = in.vertices[3*i + 0]; - float y = in.vertices[3*i + 1]; - float z = in.vertices[3*i + 2]; - - if (fill) { - double[] vertex = collectVertexAttributes(i); - vertex[0] = x; - vertex[1] = y; - vertex[2] = z; - gluTess.addVertex(vertex); - } - if (stroke) { - addStrokeVertex(x, y, z, in.strokeColors[i], in.strokeWeights[i]); - } - } - - double[] collectVertexAttributes(int i) { - final int COORD_COUNT = 3; - final int ATTRIB_COUNT = 22; - - double[] avect = in.getAttribVector(i); - - double[] r = new double[COORD_COUNT + ATTRIB_COUNT + avect.length]; - - int j = COORD_COUNT; - - int fcol = in.colors[i]; - r[j++] = (fcol >> 24) & 0xFF; // fa - r[j++] = (fcol >> 16) & 0xFF; // fr - r[j++] = (fcol >> 8) & 0xFF; // fg - r[j++] = (fcol >> 0) & 0xFF; // fb - - r[j++] = in.normals[3*i + 0]; // nx - r[j++] = in.normals[3*i + 1]; // ny - r[j++] = in.normals[3*i + 2]; // nz - - r[j++] = in.texcoords[2*i + 0]; // u - r[j++] = in.texcoords[2*i + 1]; // v - - int acol = in.ambient[i]; - r[j++] = (acol >> 24) & 0xFF; // aa - r[j++] = (acol >> 16) & 0xFF; // ar - r[j++] = (acol >> 8) & 0xFF; // ag - r[j++] = (acol >> 0) & 0xFF; // ab - - int scol = in.specular[i]; - r[j++] = (scol >> 24) & 0xFF; // sa - r[j++] = (scol >> 16) & 0xFF; // sr - r[j++] = (scol >> 8) & 0xFF; // sg - r[j++] = (scol >> 0) & 0xFF; // sb - - int ecol = in.emissive[i]; - r[j++] = (ecol >> 24) & 0xFF; // ea - r[j++] = (ecol >> 16) & 0xFF; // er - r[j++] = (ecol >> 8) & 0xFF; // eg - r[j++] = (ecol >> 0) & 0xFF; // eb - - r[j++] = in.shininess[i]; // sh - - System.arraycopy(avect, 0, r, j, avect.length); - - return r; - } - - void beginPolygonStroke() { - pathVertexCount = 0; - if (pathVertices == null) { - pathVertices = new float[3 * PGL.DEFAULT_IN_VERTICES]; - pathColors = new int[PGL.DEFAULT_IN_VERTICES]; - pathWeights = new float[PGL.DEFAULT_IN_VERTICES]; - } - } - - void endPolygonStroke() { - // Nothing to do here. - } - - void beginStrokePath() { - beginPath = pathVertexCount; - } - - void endStrokePath(boolean closed) { - int idx = pathVertexCount; - if (beginPath + 1 < idx) { - boolean begin = beginPath == idx - 2; - boolean end = begin || !closed; - in.addEdge(idx - 2, idx - 1, begin, end); - if (!end) { - in.addEdge(idx - 1, beginPath, false, false); - in.closeEdge(idx - 1, beginPath); - } - } - } - - void addStrokeVertex(float x, float y, float z, int c, float w) { - int idx = pathVertexCount; - if (beginPath + 1 < idx) { - in.addEdge(idx - 2, idx - 1, beginPath == idx - 2, false); - } - - if (pathVertexCount == pathVertices.length / 3) { - int newSize = pathVertexCount << 1; - - float vtemp[] = new float[3 * newSize]; - PApplet.arrayCopy(pathVertices, 0, vtemp, 0, 3 * pathVertexCount); - pathVertices = vtemp; - - int ctemp[] = new int[newSize]; - PApplet.arrayCopy(pathColors, 0, ctemp, 0, pathVertexCount); - pathColors = ctemp; - - float wtemp[] = new float[newSize]; - PApplet.arrayCopy(pathWeights, 0, wtemp, 0, pathVertexCount); - pathWeights = wtemp; - } - - pathVertices[3 * idx + 0] = x; - pathVertices[3 * idx + 1] = y; - pathVertices[3 * idx + 2] = z; - pathColors[idx] = c; - pathWeights[idx] = w; - - pathVertexCount++; - } - - void tessellateStrokePath() { - if (in.edgeCount == 0) return; - strokeVertices = pathVertices; - strokeColors = pathColors; - strokeWeights = pathWeights; - if (is3D) { - tessellateEdges3D(); - } else if (is2D) { - beginNoTex(); - tessellateEdges2D(); - endNoTex(); - } - } - - boolean clampPolygon() { - return false; - } - - // Tessellates the path given as parameter. This will work only in 2D. - // Based on the opengl stroke hack described here: - // http://wiki.processing.org/w/Stroke_attributes_in_OpenGL - public void tessellateLinePath(LinePath path) { - initGluTess(); - boolean clamp = clampLinePath(); - callback.init(in.renderMode == RETAINED, true, false, clamp); - - int cap = strokeCap == ROUND ? LinePath.CAP_ROUND : - strokeCap == PROJECT ? LinePath.CAP_SQUARE : - LinePath.CAP_BUTT; - int join = strokeJoin == ROUND ? LinePath.JOIN_ROUND : - strokeJoin == BEVEL ? LinePath.JOIN_BEVEL : - LinePath.JOIN_MITER; - - // Make the outline of the stroke from the path - LinePath strokedPath = LinePath.createStrokedPath(path, strokeWeight, - cap, join); - - gluTess.beginPolygon(); - - double[] vertex; - float[] coords = new float[6]; - - LinePath.PathIterator iter = strokedPath.getPathIterator(); - int rule = iter.getWindingRule(); - switch(rule) { - case LinePath.WIND_EVEN_ODD: - gluTess.setWindingRule(PGL.TESS_WINDING_ODD); - break; - case LinePath.WIND_NON_ZERO: - gluTess.setWindingRule(PGL.TESS_WINDING_NONZERO); - break; - } - - while (!iter.isDone()) { - switch (iter.currentSegment(coords)) { - - case LinePath.SEG_MOVETO: - gluTess.beginContour(); - - // $FALL-THROUGH$ - case LinePath.SEG_LINETO: - // Vertex data includes coordinates, colors, normals, texture - // coordinates, and material properties. - vertex = new double[] { coords[0], coords[1], 0, - coords[2], coords[3], coords[4], coords[5], - 0, 0, 1, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - gluTess.addVertex(vertex); - - break; - case LinePath.SEG_CLOSE: - gluTess.endContour(); - break; - } - iter.next(); - } - gluTess.endPolygon(); - } - - boolean clampLinePath() { - return clamp2D() && - strokeCap == PROJECT && strokeJoin == BEVEL && - !subPixelStroke(strokeWeight); - } - - ///////////////////////////////////////// - - // Interesting notes about using the GLU tessellator to render thick - // polylines: - // http://stackoverflow.com/questions/687173/how-do-i-render-thick-2d-lines-as-polygons - // - // "...Since I disliked the tesselator API I lifted the tesselation code - // from the free SGI OpenGL reference implementation, rewrote the entire - // front-end and added memory pools to get the number of allocations down. - // It took two days to do this, but it was well worth it (like factor five - // performance improvement)..." - // - // This C implementation of GLU could be useful: - // http://code.google.com/p/glues/ - // to eventually come up with an optimized GLU tessellator in native code. - protected class TessellatorCallback implements PGL.TessellatorCallback { - AttributeMap attribs; - boolean calcNormals; - boolean strokeTess; - boolean clampXY; - IndexCache cache; - int cacheIndex; - int vertFirst; - int vertCount; - int vertOffset; - int primitive; - - public TessellatorCallback(AttributeMap attribs) { - this.attribs = attribs; - } - - public void init(boolean addCache, boolean strokeTess, boolean calcNorm, - boolean clampXY) { - this.strokeTess = strokeTess; - this.calcNormals = calcNorm; - this.clampXY = clampXY; - - cache = tess.polyIndexCache; - if (addCache) { - cache.addNew(); - } - } - - public void begin(int type) { - cacheIndex = cache.getLast(); - if (firstPolyIndexCache == -1) { - firstPolyIndexCache = cacheIndex; - } - if (strokeTess && firstLineIndexCache == -1) { - firstLineIndexCache = cacheIndex; - } - - vertFirst = cache.vertexCount[cacheIndex]; - vertOffset = cache.vertexOffset[cacheIndex]; - vertCount = 0; - - if (type == PGL.TRIANGLE_FAN) primitive = TRIANGLE_FAN; - else if (type == PGL.TRIANGLE_STRIP) primitive = TRIANGLE_STRIP; - else if (type == PGL.TRIANGLES) primitive = TRIANGLES; - } - - public void end() { - if (PGL.MAX_VERTEX_INDEX1 <= vertFirst + vertCount) { - // We need a new index block for the new batch of - // vertices resulting from this primitive. tessVert can - // be safely assumed here to be less or equal than - // MAX_VERTEX_INDEX1 because the condition was checked - // every time a new vertex was emitted (see vertex() below). - //tessBlock = tess.addFillIndexBlock(tessBlock); - cacheIndex = cache.addNew(); - vertFirst = cache.vertexCount[cacheIndex]; - vertOffset = cache.vertexOffset[cacheIndex]; - } - - int indCount = 0; - switch (primitive) { - case TRIANGLE_FAN: - indCount = 3 * (vertCount - 2); - for (int i = 1; i < vertCount - 1; i++) { - addIndex(0); - addIndex(i); - addIndex(i + 1); - if (calcNormals) calcTriNormal(0, i, i + 1); - } - break; - case TRIANGLE_STRIP: - indCount = 3 * (vertCount - 2); - for (int i = 1; i < vertCount - 1; i++) { - if (i % 2 == 0) { - addIndex(i + 1); - addIndex(i); - addIndex(i - 1); - if (calcNormals) calcTriNormal(i + 1, i, i - 1); - } else { - addIndex(i - 1); - addIndex(i); - addIndex(i + 1); - if (calcNormals) calcTriNormal(i - 1, i, i + 1); - } - } - break; - case TRIANGLES: - indCount = vertCount; - for (int i = 0; i < vertCount; i++) { - addIndex(i); - } - if (calcNormals) { - for (int tr = 0; tr < vertCount / 3; tr++) { - int i0 = 3 * tr + 0; - int i1 = 3 * tr + 1; - int i2 = 3 * tr + 2; - calcTriNormal(i0, i1, i2); - } - } - break; - } - - cache.incCounts(cacheIndex, indCount, vertCount); - lastPolyIndexCache = cacheIndex; - if (strokeTess) { - lastLineIndexCache = cacheIndex; - } - } - - protected void addIndex(int tessIdx) { - tess.polyIndexCheck(); - tess.polyIndices[tess.polyIndexCount - 1] = - (short) (vertFirst + tessIdx); - } - - protected void calcTriNormal(int tessIdx0, int tessIdx1, int tessIdx2) { - tess.calcPolyNormal(vertFirst + vertOffset + tessIdx0, - vertFirst + vertOffset + tessIdx1, - vertFirst + vertOffset + tessIdx2); - } - - public void vertex(Object data) { - if (data instanceof double[]) { - double[] d = (double[]) data; - int l = d.length; - if (l < 25) { - throw new RuntimeException("TessCallback vertex() data is " + - "too small"); - } - - if (vertCount < PGL.MAX_VERTEX_INDEX1) { - tess.addPolyVertex(d, clampXY); - vertCount++; - } else { - throw new RuntimeException("The tessellator is generating too " + - "many vertices, reduce complexity of " + - "shape."); - } - - } else { - throw new RuntimeException("TessCallback vertex() data not " + - "understood"); - } - } - - public void error(int errnum) { - String estring = pg.pgl.tessError(errnum); - PGraphics.showWarning(TESSELLATION_ERROR, estring); - } - - /** - * Implementation of the GLU_TESS_COMBINE callback. - * @param coords is the 3-vector of the new vertex - * @param data is the vertex data to be combined, up to four elements. - * This is useful when mixing colors together or any other - * user data that was passed in to gluTessVertex. - * @param weight is an array of weights, one for each element of "data" - * that should be linearly combined for new values. - * @param outData is the set of new values of "data" after being - * put back together based on the weights. it's passed back as a - * single element Object[] array because that's the closest - * that Java gets to a pointer. - */ - public void combine(double[] coords, Object[] data, - float[] weight, Object[] outData) { - int n = ((double[])data[0]).length; - double[] vertex = new double[n]; - vertex[0] = coords[0]; - vertex[1] = coords[1]; - vertex[2] = coords[2]; - - // Calculating the rest of the vertex parameters (color, - // normal, texcoords) as the linear combination of the - // combined vertices. - for (int i = 3; i < n; i++) { - vertex[i] = 0; - for (int j = 0; j < 4; j++) { - double[] vertData = (double[])data[j]; - if (vertData != null) { - vertex[i] += weight[j] * vertData[i]; - } - } - } - - // Normalizing normal vectors, since the weighted - // combination of normal vectors is not necessarily - // normal. - normalize(vertex, 7); - if (25 < n) { - // We have custom attributes, look for normal attributes - int pos = 25; - for (int i = 0; i < attribs.size(); i++) { - VertexAttribute attrib = attribs.get(i); - if (attrib.isNormal()) { - normalize(vertex, pos); - pos += 3; - } else { - pos += attrib.size; - } - } - } - - outData[0] = vertex; - } - - private void normalize(double[] v, int i) { - double sum = v[i ] * v[i ] + - v[i + 1] * v[i + 1] + - v[i + 2] * v[i + 2]; - double len = Math.sqrt(sum); - if (0 < len) { - v[i ] /= len; - v[i + 1] /= len; - v[i + 2] /= len; - } - } - } - } - - - static protected class DepthSorter { - - static final int X = 0; - static final int Y = 1; - static final int Z = 2; - static final int W = 3; - - static final int X0 = 0; - static final int Y0 = 1; - static final int Z0 = 2; - static final int X1 = 3; - static final int Y1 = 4; - static final int Z1 = 5; - static final int X2 = 6; - static final int Y2 = 7; - static final int Z2 = 8; - - int[] triangleIndices = new int[0]; - int[] texMap = new int[0]; - int[] voffsetMap = new int[0]; - - float[] minXBuffer = new float[0]; - float[] minYBuffer = new float[0]; - float[] minZBuffer = new float[0]; - float[] maxXBuffer = new float[0]; - float[] maxYBuffer = new float[0]; - float[] maxZBuffer = new float[0]; - - float[] screenVertices = new float[0]; - - float[] triA = new float[9]; - float[] triB = new float[9]; - - BitSet marked = new BitSet(); - BitSet swapped = new BitSet(); - - PGraphicsOpenGL pg; - - DepthSorter (PGraphicsOpenGL pg) { - this.pg = pg; - } - - void checkIndexBuffers(int newTriangleCount) { - if (triangleIndices.length < newTriangleCount) { - int newSize = (newTriangleCount / 4 + 1) * 5; - triangleIndices = new int[newSize]; - texMap = new int[newSize]; - voffsetMap = new int[newSize]; - minXBuffer = new float[newSize]; - minYBuffer = new float[newSize]; - minZBuffer = new float[newSize]; - maxXBuffer = new float[newSize]; - maxYBuffer = new float[newSize]; - maxZBuffer = new float[newSize]; - } - } - - void checkVertexBuffer(int newVertexCount) { - int coordCount = 3*newVertexCount; - if (screenVertices.length < coordCount) { - int newSize = (coordCount / 4 + 1) * 5; - screenVertices = new float[newSize]; - } - } - - // Sorting -------------------------------------------- - - void sort(TessGeometry tessGeo) { - - int triangleCount = tessGeo.polyIndexCount / 3; - checkIndexBuffers(triangleCount); - int[] triangleIndices = this.triangleIndices; - int[] texMap = this.texMap; - int[] voffsetMap = this.voffsetMap; - - { // Initialize triangle indices - for (int i = 0; i < triangleCount; i++) { - triangleIndices[i] = i; - } - } - - { // Map caches to triangles - TexCache texCache = pg.texCache; - IndexCache indexCache = tessGeo.polyIndexCache; - for (int i = 0; i < texCache.size; i++) { - int first = texCache.firstCache[i]; - int last = texCache.lastCache[i]; - for (int n = first; n <= last; n++) { - int ioffset = n == first - ? texCache.firstIndex[i] - : indexCache.indexOffset[n]; - int icount = n == last - ? texCache.lastIndex[i] - ioffset + 1 - : indexCache.indexOffset[n] + indexCache.indexCount[n] - ioffset; - - for (int tr = ioffset / 3; tr < (ioffset + icount) / 3; tr++) { - texMap[tr] = i; - voffsetMap[tr] = n; - } - } - } - } - - { // Map vertices to screen - int polyVertexCount = tessGeo.polyVertexCount; - checkVertexBuffer(polyVertexCount); - float[] screenVertices = this.screenVertices; - - float[] polyVertices = tessGeo.polyVertices; - - PMatrix3D projection = pg.projection; - - for (int i = 0; i < polyVertexCount; i++) { - float x = polyVertices[4*i+X]; - float y = polyVertices[4*i+Y]; - float z = polyVertices[4*i+Z]; - float w = polyVertices[4*i+W]; - - float ox = projection.m00 * x + projection.m01 * y + - projection.m02 * z + projection.m03 * w; - float oy = projection.m10 * x + projection.m11 * y + - projection.m12 * z + projection.m13 * w; - float oz = projection.m20 * x + projection.m21 * y + - projection.m22 * z + projection.m23 * w; - float ow = projection.m30 * x + projection.m31 * y + - projection.m32 * z + projection.m33 * w; - if (nonZero(ow)) { - ox /= ow; - oy /= ow; - oz /= ow; - } - screenVertices[3*i+X] = ox; - screenVertices[3*i+Y] = oy; - screenVertices[3*i+Z] = -oz; - } - } - float[] screenVertices = this.screenVertices; - - int[] vertexOffset = tessGeo.polyIndexCache.vertexOffset; - short[] polyIndices = tessGeo.polyIndices; - - float[] triA = this.triA; - float[] triB = this.triB; - - for (int i = 0; i < triangleCount; i++) { - fetchTriCoords(triA, i, vertexOffset, voffsetMap, screenVertices, polyIndices); - minXBuffer[i] = PApplet.min(triA[X0], triA[X1], triA[X2]); - maxXBuffer[i] = PApplet.max(triA[X0], triA[X1], triA[X2]); - minYBuffer[i] = PApplet.min(triA[Y0], triA[Y1], triA[Y2]); - maxYBuffer[i] = PApplet.max(triA[Y0], triA[Y1], triA[Y2]); - minZBuffer[i] = PApplet.min(triA[Z0], triA[Z1], triA[Z2]); - maxZBuffer[i] = PApplet.max(triA[Z0], triA[Z1], triA[Z2]); - } - - sortByMinZ(0, triangleCount - 1, triangleIndices, minZBuffer); - - int activeTid = 0; - - BitSet marked = this.marked; - BitSet swapped = this.swapped; - - marked.clear(); - - while (activeTid < triangleCount) { - int testTid = activeTid + 1; - boolean draw = false; - - swapped.clear(); - - int ati = triangleIndices[activeTid]; - float minXA = minXBuffer[ati]; - float maxXA = maxXBuffer[ati]; - float minYA = minYBuffer[ati]; - float maxYA = maxYBuffer[ati]; - float maxZA = maxZBuffer[ati]; - - fetchTriCoords(triA, ati, vertexOffset, voffsetMap, screenVertices, polyIndices); - - while (!draw && testTid < triangleCount) { - int tti = triangleIndices[testTid]; - - // TEST 1 // Z overlap - if (maxZA <= minZBuffer[tti] && !marked.get(tti)) { - draw = true; // pass, not overlapping in Z, draw it - - // TEST 2 // XY overlap using square window - } else if (maxXA <= minXBuffer[tti] || maxYA <= minYBuffer[tti] || - minXA >= maxXBuffer[tti] || minYA >= maxYBuffer[tti]) { - testTid++; // pass, not overlapping in XY - - // TEST 3 // test on which side ACTIVE is relative to TEST - } else { - fetchTriCoords(triB, tti, vertexOffset, voffsetMap, - screenVertices, polyIndices); - if (side(triB, triA, -1) > 0) { - testTid++; // pass, ACTIVE is in halfspace behind current TEST - - // TEST 4 // test on which side TEST is relative to ACTIVE - } else if (side(triA, triB, 1) > 0) { - testTid++; // pass, current TEST is in halfspace in front of ACTIVE - - // FAIL, wrong depth order, swap - } else { - if (!swapped.get(tti)) { - swapped.set(ati); - marked.set(tti); - rotateRight(triangleIndices, activeTid, testTid); - - ati = tti; - System.arraycopy(triB, 0, triA, 0, 9); - minXA = minXBuffer[ati]; - maxXA = maxXBuffer[ati]; - minYA = minYBuffer[ati]; - maxYA = maxYBuffer[ati]; - maxZA = maxZBuffer[ati]; - - testTid = activeTid + 1; - } else { - // oops, we already tested this one, either in one plane or - // interlocked in loop with others, just ignore it for now :( - testTid++; - } - } - } - } - activeTid++; - } - - { // Reorder the buffers - for (int id = 0; id < triangleCount; id++) { - int mappedId = triangleIndices[id]; - if (id != mappedId) { - - // put the first index aside - short i0 = polyIndices[3*id+0]; - short i1 = polyIndices[3*id+1]; - short i2 = polyIndices[3*id+2]; - int texId = texMap[id]; - int voffsetId = voffsetMap[id]; - - // process the whole permutation cycle - int currId = id; - int nextId = mappedId; - do { - triangleIndices[currId] = currId; - polyIndices[3*currId+0] = polyIndices[3*nextId+0]; - polyIndices[3*currId+1] = polyIndices[3*nextId+1]; - polyIndices[3*currId+2] = polyIndices[3*nextId+2]; - texMap[currId] = texMap[nextId]; - voffsetMap[currId] = voffsetMap[nextId]; - - currId = nextId; - nextId = triangleIndices[nextId]; - } while (nextId != id); - - // place the first index at the end - triangleIndices[currId] = currId; - polyIndices[3*currId+0] = i0; - polyIndices[3*currId+1] = i1; - polyIndices[3*currId+2] = i2; - texMap[currId] = texId; - voffsetMap[currId] = voffsetId; - } - } - } - - } - - static void fetchTriCoords(float[] tri, int ti, int[] vertexOffset, - int[] voffsetMap, float[] screenVertices, short[] polyIndices) { - int voffset = vertexOffset[voffsetMap[ti]]; - int i0 = 3 * (voffset + polyIndices[3*ti+0]); - int i1 = 3 * (voffset + polyIndices[3*ti+1]); - int i2 = 3 * (voffset + polyIndices[3*ti+2]); - tri[X0] = screenVertices[i0+X]; - tri[Y0] = screenVertices[i0+Y]; - tri[Z0] = screenVertices[i0+Z]; - tri[X1] = screenVertices[i1+X]; - tri[Y1] = screenVertices[i1+Y]; - tri[Z1] = screenVertices[i1+Z]; - tri[X2] = screenVertices[i2+X]; - tri[Y2] = screenVertices[i2+Y]; - tri[Z2] = screenVertices[i2+Z]; - } - - static void sortByMinZ(int leftTid, int rightTid, int[] triangleIndices, - float[] minZBuffer) { - - // swap pivot to the front - swap(triangleIndices, leftTid, ((leftTid + rightTid) / 2)); - - int k = leftTid; - float leftMinZ = minZBuffer[triangleIndices[leftTid]]; - - // sort by min z - for (int tid = leftTid+1; tid <= rightTid; tid++) { - float minZ = minZBuffer[triangleIndices[tid]]; - if (minZ < leftMinZ) { - swap(triangleIndices, ++k, tid); - } - } - - // swap pivot back to the middle - swap(triangleIndices, leftTid, k); - - if (leftTid < k - 1) sortByMinZ(leftTid, k - 1, triangleIndices, - minZBuffer); - if (k + 1 < rightTid) sortByMinZ(k + 1, rightTid, triangleIndices, - minZBuffer); - } - - // Math ----------------------------------------------- - - static int side(float[] tri1, float[] tri2, float tz) { - float Dx, Dy, Dz, Dw; - { // Get the equation of the plane - float - ABx = tri1[X1] - tri1[X0], ACx = tri1[X2] - tri1[X0], - ABy = tri1[Y1] - tri1[Y0], ACy = tri1[Y2] - tri1[Y0], - ABz = tri1[Z1] - tri1[Z0], ACz = tri1[Z2] - tri1[Z0]; - - Dx = ABy*ACz - ABz*ACy; Dy = ABz*ACx - ABx*ACz; Dz = ABx*ACy - ABy*ACx; - - // Normalize normal vector - float rMag = 1.0f/(float) Math.sqrt(Dx * Dx + Dy * Dy + Dz * Dz); - Dx *= rMag; Dy *= rMag; Dz *= rMag; - - Dw = -dot(Dx, Dy, Dz, tri1[X0], tri1[Y0], tri1[Z0]); - } - - float distTest = dot(Dx, Dy, Dz, - tri1[X0], tri1[Y0], tri1[Z0] + 100*tz) + Dw; - - float distA = dot(Dx, Dy, Dz, tri2[X0], tri2[Y0], tri2[Z0]) + Dw; - float distB = dot(Dx, Dy, Dz, tri2[X1], tri2[Y1], tri2[Z1]) + Dw; - float distC = dot(Dx, Dy, Dz, tri2[X2], tri2[Y2], tri2[Z2]) + Dw; - - // Ignore relatively close vertices to get stable results - // when some parts of polygons are close to each other - float absA = PApplet.abs(distA); - float absB = PApplet.abs(distB); - float absC = PApplet.abs(distC); - float eps = PApplet.max(absA, absB, absC) * 0.1f; - - float sideA = ((absA < eps) ? 0.0f : distA) * distTest; - float sideB = ((absB < eps) ? 0.0f : distB) * distTest; - float sideC = ((absC < eps) ? 0.0f : distC) * distTest; - - boolean sameSide = sideA >= 0 && sideB >= 0 && sideC >= 0; - boolean notSameSide = sideA <= 0 && sideB <= 0 && sideC <= 0; - - return sameSide ? 1 : notSameSide ? -1 : 0; - } - - static float dot(float a1, float a2, float a3, - float b1, float b2, float b3) { - return a1 * b1 + a2 * b2 + a3 * b3; - } - - - // Array utils --------------------------------------- - - static void swap(int[] array, int i1, int i2) { - int temp = array[i1]; - array[i1] = array[i2]; - array[i2] = temp; - } - - static void rotateRight(int[] array, int i1, int i2) { - if (i1 == i2) return; - int temp = array[i2]; - System.arraycopy(array, i1, array, i1 + 1, i2 - i1); - array[i1] = temp; - } - - } - -} diff --git a/core/src/processing/opengl/PShader.java b/core/src/processing/opengl/PShader.java deleted file mode 100644 index c3e47ead5..000000000 --- a/core/src/processing/opengl/PShader.java +++ /dev/null @@ -1,1478 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import processing.core.*; -import processing.opengl.PGraphicsOpenGL.GLResourceShader; - -import java.net.URL; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.util.HashMap; - -/** - * This class encapsulates a GLSL shader program, including a vertex - * and a fragment shader. Based on the GLSLShader class from GLGraphics, which - * in turn was originally based in the code by JohnG: - * http://processing.org/discourse/beta/num_1159494801.html - * - * @webref rendering:shaders - */ -public class PShader implements PConstants { - static protected final int POINT = 0; - static protected final int LINE = 1; - static protected final int POLY = 2; - static protected final int COLOR = 3; - static protected final int LIGHT = 4; - static protected final int TEXTURE = 5; - static protected final int TEXLIGHT = 6; - - static protected String pointShaderAttrRegexp = - "attribute *vec2 *offset"; - static protected String pointShaderInRegexp = - "in *vec2 *offset;"; - static protected String lineShaderAttrRegexp = - "attribute *vec4 *direction"; - static protected String lineShaderInRegexp = - "in *vec4 *direction"; - static protected String pointShaderDefRegexp = - "#define *PROCESSING_POINT_SHADER"; - static protected String lineShaderDefRegexp = - "#define *PROCESSING_LINE_SHADER"; - static protected String colorShaderDefRegexp = - "#define *PROCESSING_COLOR_SHADER"; - static protected String lightShaderDefRegexp = - "#define *PROCESSING_LIGHT_SHADER"; - static protected String texShaderDefRegexp = - "#define *PROCESSING_TEXTURE_SHADER"; - static protected String texlightShaderDefRegexp = - "#define *PROCESSING_TEXLIGHT_SHADER"; - static protected String polyShaderDefRegexp = - "#define *PROCESSING_POLYGON_SHADER"; - static protected String triShaderAttrRegexp = - "#define *PROCESSING_TRIANGLES_SHADER"; - static protected String quadShaderAttrRegexp = - "#define *PROCESSING_QUADS_SHADER"; - - protected PApplet parent; - // The main renderer associated to the parent PApplet. - //protected PGraphicsOpenGL pgMain; - // We need a reference to the renderer since a shader might - // be called by different renderers within a single application - // (the one corresponding to the main surface, or other offscreen - // renderers). - protected PGraphicsOpenGL primaryPG; - protected PGraphicsOpenGL currentPG; - protected PGL pgl; - protected int context; // The context that created this shader. - - // The shader type: POINT, LINE, POLY, etc. - protected int type; - - public int glProgram; - public int glVertex; - public int glFragment; - private GLResourceShader glres; - - protected URL vertexURL; - protected URL fragmentURL; - - protected String vertexFilename; - protected String fragmentFilename; - - protected String[] vertexShaderSource; - protected String[] fragmentShaderSource; - - protected boolean bound; - - protected HashMap uniformValues = null; - - protected HashMap textures; - protected HashMap texUnits; - - // Direct buffers to pass shader data to GL - protected IntBuffer intBuffer; - protected FloatBuffer floatBuffer; - - protected boolean loadedAttributes = false; - protected boolean loadedUniforms = false; - - // Uniforms common to all shader types - protected int transformMatLoc; - protected int modelviewMatLoc; - protected int projectionMatLoc; - protected int ppixelsLoc; - protected int ppixelsUnit; - protected int viewportLoc; - protected int resolutionLoc; - - // Uniforms only for lines and points - protected int perspectiveLoc; - protected int scaleLoc; - - // Lighting uniforms - protected int lightCountLoc; - protected int lightPositionLoc; - protected int lightNormalLoc; - protected int lightAmbientLoc; - protected int lightDiffuseLoc; - protected int lightSpecularLoc; - protected int lightFalloffLoc; - protected int lightSpotLoc; - - // Texturing uniforms - protected Texture texture; - protected int texUnit; - protected int textureLoc; - protected int texMatrixLoc; - protected int texOffsetLoc; - protected float[] tcmat; - - // Vertex attributes - protected int vertexLoc; - protected int colorLoc; - protected int normalLoc; - protected int texCoordLoc; - protected int normalMatLoc; - protected int directionLoc; - protected int offsetLoc; - protected int ambientLoc; - protected int specularLoc; - protected int emissiveLoc; - protected int shininessLoc; - - public PShader() { - parent = null; - pgl = null; - context = -1; - - this.vertexURL = null; - this.fragmentURL = null; - this.vertexFilename = null; - this.fragmentFilename = null; - - glProgram = 0; - glVertex = 0; - glFragment = 0; - - intBuffer = PGL.allocateIntBuffer(1); - floatBuffer = PGL.allocateFloatBuffer(1); - - bound = false; - - type = -1; - } - - - public PShader(PApplet parent) { - this(); - this.parent = parent; - primaryPG = (PGraphicsOpenGL)parent.g; - pgl = primaryPG.pgl; - context = pgl.createEmptyContext(); - } - - - /** - * Creates a shader program using the specified vertex and fragment - * shaders. - * - * @param parent the parent program - * @param vertFilename name of the vertex shader - * @param fragFilename name of the fragment shader - */ - public PShader(PApplet parent, String vertFilename, String fragFilename) { - this.parent = parent; - primaryPG = (PGraphicsOpenGL)parent.g; - pgl = primaryPG.pgl; - - this.vertexURL = null; - this.fragmentURL = null; - this.vertexFilename = vertFilename; - this.fragmentFilename = fragFilename; - fragmentShaderSource = pgl.loadFragmentShader(fragFilename); - vertexShaderSource = pgl.loadVertexShader(vertFilename); - - glProgram = 0; - glVertex = 0; - glFragment = 0; - - intBuffer = PGL.allocateIntBuffer(1); - floatBuffer = PGL.allocateFloatBuffer(1); - - int vertType = getShaderType(vertexShaderSource, -1); - int fragType = getShaderType(fragmentShaderSource, -1); - if (vertType == -1 && fragType == -1) { - type = PShader.POLY; - } else if (vertType == -1) { - type = fragType; - } else if (fragType == -1) { - type = vertType; - } else if (fragType == vertType) { - type = vertType; - } else { - PGraphics.showWarning(PGraphicsOpenGL.INCONSISTENT_SHADER_TYPES); - } - } - - - /** - * @param vertURL network location of the vertex shader - * @param fragURL network location of the fragment shader - */ - public PShader(PApplet parent, URL vertURL, URL fragURL) { - this.parent = parent; - primaryPG = (PGraphicsOpenGL)parent.g; - pgl = primaryPG.pgl; - - this.vertexURL = vertURL; - this.fragmentURL = fragURL; - this.vertexFilename = null; - this.fragmentFilename = null; - fragmentShaderSource = pgl.loadFragmentShader(fragURL); - vertexShaderSource = pgl.loadVertexShader(vertURL); - - glProgram = 0; - glVertex = 0; - glFragment = 0; - - intBuffer = PGL.allocateIntBuffer(1); - floatBuffer = PGL.allocateFloatBuffer(1); - - int vertType = getShaderType(vertexShaderSource, -1); - int fragType = getShaderType(fragmentShaderSource, -1); - if (vertType == -1 && fragType == -1) { - type = PShader.POLY; - } else if (vertType == -1) { - type = fragType; - } else if (fragType == -1) { - type = vertType; - } else if (fragType == vertType) { - type = vertType; - } else { - PGraphics.showWarning(PGraphicsOpenGL.INCONSISTENT_SHADER_TYPES); - } - } - - public PShader(PApplet parent, String[] vertSource, String[] fragSource) { - this.parent = parent; - primaryPG = (PGraphicsOpenGL)parent.g; - pgl = primaryPG.pgl; - - this.vertexURL = null; - this.fragmentURL = null; - this.vertexFilename = null; - this.fragmentFilename = null; - vertexShaderSource = vertSource; - fragmentShaderSource = fragSource; - - glProgram = 0; - glVertex = 0; - glFragment = 0; - - intBuffer = PGL.allocateIntBuffer(1); - floatBuffer = PGL.allocateFloatBuffer(1); - - int vertType = getShaderType(vertexShaderSource, -1); - int fragType = getShaderType(fragmentShaderSource, -1); - if (vertType == -1 && fragType == -1) { - type = PShader.POLY; - } else if (vertType == -1) { - type = fragType; - } else if (fragType == -1) { - type = vertType; - } else if (fragType == vertType) { - type = vertType; - } else { - PGraphics.showWarning(PGraphicsOpenGL.INCONSISTENT_SHADER_TYPES); - } - } - - - public void setVertexShader(String vertFilename) { - this.vertexFilename = vertFilename; - vertexShaderSource = pgl.loadVertexShader(vertFilename); - } - - - public void setVertexShader(URL vertURL) { - this.vertexURL = vertURL; - vertexShaderSource = pgl.loadVertexShader(vertURL); - } - - - public void setVertexShader(String[] vertSource) { - vertexShaderSource = vertSource; - } - - - public void setFragmentShader(String fragFilename) { - this.fragmentFilename = fragFilename; - fragmentShaderSource = pgl.loadFragmentShader(fragFilename); - } - - - public void setFragmentShader(URL fragURL) { - this.fragmentURL = fragURL; - fragmentShaderSource = pgl.loadFragmentShader(fragURL); - } - - public void setFragmentShader(String[] fragSource) { - fragmentShaderSource = fragSource; - } - - - /** - * Initializes (if needed) and binds the shader program. - */ - public void bind() { - init(); - if (!bound) { - pgl.useProgram(glProgram); - bound = true; - consumeUniforms(); - bindTextures(); - } - - if (hasType()) bindTyped(); - } - - - /** - * Unbinds the shader program. - */ - public void unbind() { - if (hasType()) unbindTyped(); - - if (bound) { - unbindTextures(); - pgl.useProgram(0); - bound = false; - } - } - - - /** - * Returns true if the shader is bound, false otherwise. - */ - public boolean bound() { - return bound; - } - - /** - * @webref rendering:shaders - * @brief Sets a variable within the shader - * @param name the name of the uniform variable to modify - * @param x first component of the variable to modify - */ - public void set(String name, int x) { - setUniformImpl(name, UniformValue.INT1, new int[] { x }); - } - - /** - * @param y second component of the variable to modify. The variable has to be declared with an array/vector type in the shader (i.e.: int[2], vec2) - */ - public void set(String name, int x, int y) { - setUniformImpl(name, UniformValue.INT2, new int[] { x, y }); - } - - /** - * @param z third component of the variable to modify. The variable has to be declared with an array/vector type in the shader (i.e.: int[3], vec3) - */ - public void set(String name, int x, int y, int z) { - setUniformImpl(name, UniformValue.INT3, new int[] { x, y, z }); - } - - /** - * @param w fourth component of the variable to modify. The variable has to be declared with an array/vector type in the shader (i.e.: int[4], vec4) - */ - public void set(String name, int x, int y, int z, int w) { - setUniformImpl(name, UniformValue.INT4, new int[] { x, y, z, w }); - } - - - public void set(String name, float x) { - setUniformImpl(name, UniformValue.FLOAT1, new float[] { x }); - } - - - public void set(String name, float x, float y) { - setUniformImpl(name, UniformValue.FLOAT2, new float[] { x, y }); - } - - - public void set(String name, float x, float y, float z) { - setUniformImpl(name, UniformValue.FLOAT3, new float[] { x, y, z }); - } - - - public void set(String name, float x, float y, float z, float w) { - setUniformImpl(name, UniformValue.FLOAT4, new float[] { x, y, z, w }); - } - - /** - * @param vec modifies all the components of an array/vector uniform variable. PVector can only be used if the type of the variable is vec3. - */ - public void set(String name, PVector vec) { - setUniformImpl(name, UniformValue.FLOAT3, - new float[] { vec.x, vec.y, vec.z }); - } - - - public void set(String name, boolean x) { - setUniformImpl(name, UniformValue.INT1, new int[] { (x)?1:0 }); - } - - - public void set(String name, boolean x, boolean y) { - setUniformImpl(name, UniformValue.INT2, - new int[] { (x)?1:0, (y)?1:0 }); - } - - - public void set(String name, boolean x, boolean y, boolean z) { - setUniformImpl(name, UniformValue.INT3, - new int[] { (x)?1:0, (y)?1:0, (z)?1:0 }); - } - - - public void set(String name, boolean x, boolean y, boolean z, boolean w) { - setUniformImpl(name, UniformValue.INT4, - new int[] { (x)?1:0, (y)?1:0, (z)?1:0, (w)?1:0 }); - } - - - public void set(String name, int[] vec) { - set(name, vec, 1); - } - - - /** - * @param ncoords number of coordinates per element, max 4 - */ - public void set(String name, int[] vec, int ncoords) { - if (ncoords == 1) { - setUniformImpl(name, UniformValue.INT1VEC, vec); - } else if (ncoords == 2) { - setUniformImpl(name, UniformValue.INT2VEC, vec); - } else if (ncoords == 3) { - setUniformImpl(name, UniformValue.INT3VEC, vec); - } else if (ncoords == 4) { - setUniformImpl(name, UniformValue.INT4VEC, vec); - } else if (4 < ncoords) { - PGraphics.showWarning("Only up to 4 coordinates per element are " + - "supported."); - } else { - PGraphics.showWarning("Wrong number of coordinates: it is negative!"); - } - } - - - public void set(String name, float[] vec) { - set(name, vec, 1); - } - - - public void set(String name, float[] vec, int ncoords) { - if (ncoords == 1) { - setUniformImpl(name, UniformValue.FLOAT1VEC, vec); - } else if (ncoords == 2) { - setUniformImpl(name, UniformValue.FLOAT2VEC, vec); - } else if (ncoords == 3) { - setUniformImpl(name, UniformValue.FLOAT3VEC, vec); - } else if (ncoords == 4) { - setUniformImpl(name, UniformValue.FLOAT4VEC, vec); - } else if (4 < ncoords) { - PGraphics.showWarning("Only up to 4 coordinates per element are " + - "supported."); - } else { - PGraphics.showWarning("Wrong number of coordinates: it is negative!"); - } - } - - - public void set(String name, boolean[] vec) { - set(name, vec, 1); - } - - - public void set(String name, boolean[] boolvec, int ncoords) { - int[] vec = new int[boolvec.length]; - for (int i = 0; i < boolvec.length; i++) { - vec[i] = (boolvec[i])?1:0; - } - set(name, vec, ncoords); - } - - - /** - * @param mat matrix of values - */ - public void set(String name, PMatrix2D mat) { - float[] matv = { mat.m00, mat.m01, - mat.m10, mat.m11 }; - setUniformImpl(name, UniformValue.MAT2, matv); - } - - - public void set(String name, PMatrix3D mat) { - set(name, mat, false); - } - - /** - * @param use3x3 enforces the matrix is 3 x 3 - */ - public void set(String name, PMatrix3D mat, boolean use3x3) { - if (use3x3) { - float[] matv = { mat.m00, mat.m01, mat.m02, - mat.m10, mat.m11, mat.m12, - mat.m20, mat.m21, mat.m22 }; - setUniformImpl(name, UniformValue.MAT3, matv); - } else { - float[] matv = { mat.m00, mat.m01, mat.m02, mat.m03, - mat.m10, mat.m11, mat.m12, mat.m13, - mat.m20, mat.m21, mat.m22, mat.m23, - mat.m30, mat.m31, mat.m32, mat.m33 }; - setUniformImpl(name, UniformValue.MAT4, matv); - } - } - - /** - * @param tex sets the sampler uniform variable to read from this image texture - */ - public void set(String name, PImage tex) { - setUniformImpl(name, UniformValue.SAMPLER2D, tex); - } - - - /** - * Extra initialization method that can be used by subclasses, called after - * compiling and attaching the vertex and fragment shaders, and before - * linking the shader program. - * - */ - protected void setup() { - } - - - protected void draw(int idxId, int count, int offset) { - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, idxId); - pgl.drawElements(PGL.TRIANGLES, count, PGL.INDEX_TYPE, - offset * PGL.SIZEOF_INDEX); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); - } - - - /** - * Returns the ID location of the attribute parameter given its name. - * - * @param name String - * @return int - */ - protected int getAttributeLoc(String name) { - init(); - return pgl.getAttribLocation(glProgram, name); - } - - - /** - * Returns the ID location of the uniform parameter given its name. - * - * @param name String - * @return int - */ - protected int getUniformLoc(String name) { - init(); - return pgl.getUniformLocation(glProgram, name); - } - - - protected void setAttributeVBO(int loc, int vboId, int size, int type, - boolean normalized, int stride, int offset) { - if (-1 < loc) { - pgl.bindBuffer(PGL.ARRAY_BUFFER, vboId); - pgl.vertexAttribPointer(loc, size, type, normalized, stride, offset); - } - } - - - protected void setUniformValue(int loc, int x) { - if (-1 < loc) { - pgl.uniform1i(loc, x); - } - } - - - protected void setUniformValue(int loc, int x, int y) { - if (-1 < loc) { - pgl.uniform2i(loc, x, y); - } - } - - - protected void setUniformValue(int loc, int x, int y, int z) { - if (-1 < loc) { - pgl.uniform3i(loc, x, y, z); - } - } - - - protected void setUniformValue(int loc, int x, int y, int z, int w) { - if (-1 < loc) { - pgl.uniform4i(loc, x, y, z, w); - } - } - - - protected void setUniformValue(int loc, float x) { - if (-1 < loc) { - pgl.uniform1f(loc, x); - } - } - - protected void setUniformValue(int loc, float x, float y) { - if (-1 < loc) { - pgl.uniform2f(loc, x, y); - } - } - - - protected void setUniformValue(int loc, float x, float y, float z) { - if (-1 < loc) { - pgl.uniform3f(loc, x, y, z); - } - } - - - protected void setUniformValue(int loc, float x, float y, float z, float w) { - if (-1 < loc) { - pgl.uniform4f(loc, x, y, z, w); - } - } - - - protected void setUniformVector(int loc, int[] vec, int ncoords, - int length) { - if (-1 < loc) { - updateIntBuffer(vec); - if (ncoords == 1) { - pgl.uniform1iv(loc, length, intBuffer); - } else if (ncoords == 2) { - pgl.uniform2iv(loc, length, intBuffer); - } else if (ncoords == 3) { - pgl.uniform3iv(loc, length, intBuffer); - } else if (ncoords == 4) { - pgl.uniform3iv(loc, length, intBuffer); - } - } - } - - - protected void setUniformVector(int loc, float[] vec, int ncoords, - int length) { - if (-1 < loc) { - updateFloatBuffer(vec); - if (ncoords == 1) { - pgl.uniform1fv(loc, length, floatBuffer); - } else if (ncoords == 2) { - pgl.uniform2fv(loc, length, floatBuffer); - } else if (ncoords == 3) { - pgl.uniform3fv(loc, length, floatBuffer); - } else if (ncoords == 4) { - pgl.uniform4fv(loc, length, floatBuffer); - } - } - } - - - protected void setUniformMatrix(int loc, float[] mat) { - if (-1 < loc) { - updateFloatBuffer(mat); - if (mat.length == 4) { - pgl.uniformMatrix2fv(loc, 1, false, floatBuffer); - } else if (mat.length == 9) { - pgl.uniformMatrix3fv(loc, 1, false, floatBuffer); - } else if (mat.length == 16) { - pgl.uniformMatrix4fv(loc, 1, false, floatBuffer); - } - } - } - - - protected void setUniformTex(int loc, Texture tex) { - if (texUnits != null) { - Integer unit = texUnits.get(loc); - if (unit != null) { - pgl.activeTexture(PGL.TEXTURE0 + unit); - tex.bind(); - } else { - throw new RuntimeException("Cannot find unit for texture " + tex); - } - } - } - - - protected void setUniformImpl(String name, int type, Object value) { - int loc = getUniformLoc(name); - if (-1 < loc) { - if (uniformValues == null) { - uniformValues = new HashMap(); - } - uniformValues.put(loc, new UniformValue(type, value)); - } else { - PGraphics.showWarning("The shader doesn't have a uniform called \"" + - name + "\" OR the uniform was removed during " + - "compilation because it was unused."); - } - } - - - protected void consumeUniforms() { - if (uniformValues != null && 0 < uniformValues.size()) { - int unit = 0; - for (Integer loc: uniformValues.keySet()) { - UniformValue val = uniformValues.get(loc); - if (val.type == UniformValue.INT1) { - int[] v = ((int[])val.value); - pgl.uniform1i(loc, v[0]); - } else if (val.type == UniformValue.INT2) { - int[] v = ((int[])val.value); - pgl.uniform2i(loc, v[0], v[1]); - } else if (val.type == UniformValue.INT3) { - int[] v = ((int[])val.value); - pgl.uniform3i(loc, v[0], v[1], v[2]); - } else if (val.type == UniformValue.INT4) { - int[] v = ((int[])val.value); - pgl.uniform4i(loc, v[0], v[1], v[2], v[3]); - } else if (val.type == UniformValue.FLOAT1) { - float[] v = ((float[])val.value); - pgl.uniform1f(loc, v[0]); - } else if (val.type == UniformValue.FLOAT2) { - float[] v = ((float[])val.value); - pgl.uniform2f(loc, v[0], v[1]); - } else if (val.type == UniformValue.FLOAT3) { - float[] v = ((float[])val.value); - pgl.uniform3f(loc, v[0], v[1], v[2]); - } else if (val.type == UniformValue.FLOAT4) { - float[] v = ((float[])val.value); - pgl.uniform4f(loc, v[0], v[1], v[2], v[3]); - } else if (val.type == UniformValue.INT1VEC) { - int[] v = ((int[])val.value); - updateIntBuffer(v); - pgl.uniform1iv(loc, v.length, intBuffer); - } else if (val.type == UniformValue.INT2VEC) { - int[] v = ((int[])val.value); - updateIntBuffer(v); - pgl.uniform2iv(loc, v.length / 2, intBuffer); - } else if (val.type == UniformValue.INT3VEC) { - int[] v = ((int[])val.value); - updateIntBuffer(v); - pgl.uniform3iv(loc, v.length / 3, intBuffer); - } else if (val.type == UniformValue.INT4VEC) { - int[] v = ((int[])val.value); - updateIntBuffer(v); - pgl.uniform4iv(loc, v.length / 4, intBuffer); - } else if (val.type == UniformValue.FLOAT1VEC) { - float[] v = ((float[])val.value); - updateFloatBuffer(v); - pgl.uniform1fv(loc, v.length, floatBuffer); - } else if (val.type == UniformValue.FLOAT2VEC) { - float[] v = ((float[])val.value); - updateFloatBuffer(v); - pgl.uniform2fv(loc, v.length / 2, floatBuffer); - } else if (val.type == UniformValue.FLOAT3VEC) { - float[] v = ((float[])val.value); - updateFloatBuffer(v); - pgl.uniform3fv(loc, v.length / 3, floatBuffer); - } else if (val.type == UniformValue.FLOAT4VEC) { - float[] v = ((float[])val.value); - updateFloatBuffer(v); - pgl.uniform4fv(loc, v.length / 4, floatBuffer); - } else if (val.type == UniformValue.MAT2) { - float[] v = ((float[])val.value); - updateFloatBuffer(v); - pgl.uniformMatrix2fv(loc, 1, false, floatBuffer); - } else if (val.type == UniformValue.MAT3) { - float[] v = ((float[])val.value); - updateFloatBuffer(v); - pgl.uniformMatrix3fv(loc, 1, false, floatBuffer); - } else if (val.type == UniformValue.MAT4) { - float[] v = ((float[])val.value); - updateFloatBuffer(v); - pgl.uniformMatrix4fv(loc, 1, false, floatBuffer); - } else if (val.type == UniformValue.SAMPLER2D) { - PImage img = (PImage)val.value; - Texture tex = currentPG.getTexture(img); - - if (textures == null) textures = new HashMap(); - textures.put(loc, tex); - - if (texUnits == null) texUnits = new HashMap(); - if (texUnits.containsKey(loc)) { - unit = texUnits.get(loc); - pgl.uniform1i(loc, unit); - } else { - texUnits.put(loc, unit); - pgl.uniform1i(loc, unit); - } - unit++; - } - } - uniformValues.clear(); - } - } - - - protected void updateIntBuffer(int[] vec) { - intBuffer = PGL.updateIntBuffer(intBuffer, vec, false); - } - - - protected void updateFloatBuffer(float[] vec) { - floatBuffer = PGL.updateFloatBuffer(floatBuffer, vec, false); - } - - - protected void bindTextures() { - if (textures != null && texUnits != null) { - for (int loc: textures.keySet()) { - Texture tex = textures.get(loc); - Integer unit = texUnits.get(loc); - if (unit != null) { - pgl.activeTexture(PGL.TEXTURE0 + unit); - tex.bind(); - } else { - throw new RuntimeException("Cannot find unit for texture " + tex); - } - } - } - } - - - protected void unbindTextures() { - if (textures != null && texUnits != null) { - for (int loc: textures.keySet()) { - Texture tex = textures.get(loc); - Integer unit = texUnits.get(loc); - if (unit != null) { - pgl.activeTexture(PGL.TEXTURE0 + unit); - tex.unbind(); - } else { - throw new RuntimeException("Cannot find unit for texture " + tex); - } - } - pgl.activeTexture(PGL.TEXTURE0); - } - } - - - public void init() { - if (glProgram == 0 || contextIsOutdated()) { - create(); - if (compile()) { - pgl.attachShader(glProgram, glVertex); - pgl.attachShader(glProgram, glFragment); - - setup(); - - pgl.linkProgram(glProgram); - - validate(); - } - } - } - - - protected void create() { - context = pgl.getCurrentContext(); - glres = new GLResourceShader(this); - } - - - protected boolean compile() { - boolean vertRes = true; - if (hasVertexShader()) { - vertRes = compileVertexShader(); - } else { - PGraphics.showException("Doesn't have a vertex shader"); - } - - boolean fragRes = true; - if (hasFragmentShader()) { - fragRes = compileFragmentShader(); - } else { - PGraphics.showException("Doesn't have a fragment shader"); - } - - return vertRes && fragRes; - } - - - protected void validate() { - pgl.getProgramiv(glProgram, PGL.LINK_STATUS, intBuffer); - boolean linked = intBuffer.get(0) == 0 ? false : true; - if (!linked) { - PGraphics.showException("Cannot link shader program:\n" + - pgl.getProgramInfoLog(glProgram)); - } - - pgl.validateProgram(glProgram); - pgl.getProgramiv(glProgram, PGL.VALIDATE_STATUS, intBuffer); - boolean validated = intBuffer.get(0) == 0 ? false : true; - if (!validated) { - PGraphics.showException("Cannot validate shader program:\n" + - pgl.getProgramInfoLog(glProgram)); - } - } - - - protected boolean contextIsOutdated() { - boolean outdated = !pgl.contextIsCurrent(context); - if (outdated) { - dispose(); - } - return outdated; - } - - - - protected boolean hasVertexShader() { - return vertexShaderSource != null && 0 < vertexShaderSource.length; - } - - - protected boolean hasFragmentShader() { - return fragmentShaderSource != null && 0 < fragmentShaderSource.length; - } - - - /** - * @param shaderSource a string containing the shader's code - */ - protected boolean compileVertexShader() { - pgl.shaderSource(glVertex, PApplet.join(vertexShaderSource, "\n")); - pgl.compileShader(glVertex); - - pgl.getShaderiv(glVertex, PGL.COMPILE_STATUS, intBuffer); - boolean compiled = intBuffer.get(0) == 0 ? false : true; - if (!compiled) { - PGraphics.showException("Cannot compile vertex shader:\n" + - pgl.getShaderInfoLog(glVertex)); - return false; - } else { - return true; - } - } - - - /** - * @param shaderSource a string containing the shader's code - */ - protected boolean compileFragmentShader() { - pgl.shaderSource(glFragment, PApplet.join(fragmentShaderSource, "\n")); - pgl.compileShader(glFragment); - - pgl.getShaderiv(glFragment, PGL.COMPILE_STATUS, intBuffer); - boolean compiled = intBuffer.get(0) == 0 ? false : true; - if (!compiled) { - PGraphics.showException("Cannot compile fragment shader:\n" + - pgl.getShaderInfoLog(glFragment)); - return false; - } else { - return true; - } - } - - - protected void dispose() { - if (glres != null) { - glres.dispose(); - glVertex = 0; - glFragment = 0; - glProgram = 0; - glres = null; - } - } - - - static protected int getShaderType(String[] source, int defaultType) { - for (int i = 0; i < source.length; i++) { - String line = source[i].trim(); - - if (PApplet.match(line, colorShaderDefRegexp) != null) - return PShader.COLOR; - else if (PApplet.match(line, lightShaderDefRegexp) != null) - return PShader.LIGHT; - else if (PApplet.match(line, texShaderDefRegexp) != null) - return PShader.TEXTURE; - else if (PApplet.match(line, texlightShaderDefRegexp) != null) - return PShader.TEXLIGHT; - else if (PApplet.match(line, polyShaderDefRegexp) != null) - return PShader.POLY; - else if (PApplet.match(line, triShaderAttrRegexp) != null) - return PShader.POLY; - else if (PApplet.match(line, quadShaderAttrRegexp) != null) - return PShader.POLY; - else if (PApplet.match(line, pointShaderDefRegexp) != null) - return PShader.POINT; - else if (PApplet.match(line, lineShaderDefRegexp) != null) - return PShader.LINE; - else if (PApplet.match(line, pointShaderAttrRegexp) != null) - return PShader.POINT; - else if (PApplet.match(line, pointShaderInRegexp) != null) - return PShader.POINT; - else if (PApplet.match(line, lineShaderAttrRegexp) != null) - return PShader.LINE; - else if (PApplet.match(line, lineShaderInRegexp) != null) - return PShader.LINE; - } - return defaultType; - } - - - // *************************************************************************** - // - // Processing specific - - - protected int getType() { - return type; - } - - - protected void setType(int type) { - this.type = type; - } - - - protected boolean hasType() { - return POINT <= type && type <= TEXLIGHT; - } - - - protected boolean isPointShader() { - return type == POINT; - } - - - protected boolean isLineShader() { - return type == LINE; - } - - - protected boolean isPolyShader() { - return POLY <= type && type <= TEXLIGHT; - } - - - protected boolean checkPolyType(int type) { - if (getType() == PShader.POLY) return true; - - if (getType() != type) { - if (type == TEXLIGHT) { - PGraphics.showWarning(PGraphicsOpenGL.NO_TEXLIGHT_SHADER_ERROR); - } else if (type == LIGHT) { - PGraphics.showWarning(PGraphicsOpenGL.NO_LIGHT_SHADER_ERROR); - } else if (type == TEXTURE) { - PGraphics.showWarning(PGraphicsOpenGL.NO_TEXTURE_SHADER_ERROR); - } else if (type == COLOR) { - PGraphics.showWarning(PGraphicsOpenGL.NO_COLOR_SHADER_ERROR); - } - return false; - } - - return true; - } - - - protected int getLastTexUnit() { - return texUnits == null ? -1 : texUnits.size() - 1; - } - - - protected void setRenderer(PGraphicsOpenGL pg) { - this.currentPG = pg; - } - - - protected void loadAttributes() { - if (loadedAttributes) return; - - vertexLoc = getAttributeLoc("vertex"); - if (vertexLoc == -1) vertexLoc = getAttributeLoc("position"); - - colorLoc = getAttributeLoc("color"); - texCoordLoc = getAttributeLoc("texCoord"); - normalLoc = getAttributeLoc("normal"); - - ambientLoc = getAttributeLoc("ambient"); - specularLoc = getAttributeLoc("specular"); - emissiveLoc = getAttributeLoc("emissive"); - shininessLoc = getAttributeLoc("shininess"); - - directionLoc = getAttributeLoc("direction"); - - offsetLoc = getAttributeLoc("offset"); - - directionLoc = getAttributeLoc("direction"); - offsetLoc = getAttributeLoc("offset"); - - loadedAttributes = true; - } - - - protected void loadUniforms() { - if (loadedUniforms) return; - transformMatLoc = getUniformLoc("transform"); - if (transformMatLoc == -1) - transformMatLoc = getUniformLoc("transformMatrix"); - - modelviewMatLoc = getUniformLoc("modelview"); - if (modelviewMatLoc == -1) - modelviewMatLoc = getUniformLoc("modelviewMatrix"); - - projectionMatLoc = getUniformLoc("projection"); - if (projectionMatLoc == -1) - projectionMatLoc = getUniformLoc("projectionMatrix"); - - viewportLoc = getUniformLoc("viewport"); - resolutionLoc = getUniformLoc("resolution"); - ppixelsLoc = getUniformLoc("ppixels"); - - normalMatLoc = getUniformLoc("normalMatrix"); - - lightCountLoc = getUniformLoc("lightCount"); - lightPositionLoc = getUniformLoc("lightPosition"); - lightNormalLoc = getUniformLoc("lightNormal"); - lightAmbientLoc = getUniformLoc("lightAmbient"); - lightDiffuseLoc = getUniformLoc("lightDiffuse"); - lightSpecularLoc = getUniformLoc("lightSpecular"); - lightFalloffLoc = getUniformLoc("lightFalloff"); - lightSpotLoc = getUniformLoc("lightSpot"); - - textureLoc = getUniformLoc("texture"); - if (textureLoc == -1) { - textureLoc = getUniformLoc("texMap"); - } - - texMatrixLoc = getUniformLoc("texMatrix"); - texOffsetLoc = getUniformLoc("texOffset"); - - perspectiveLoc = getUniformLoc("perspective"); - scaleLoc = getUniformLoc("scale"); - loadedUniforms = true; - } - - - protected void setCommonUniforms() { - if (-1 < transformMatLoc) { - currentPG.updateGLProjmodelview(); - setUniformMatrix(transformMatLoc, currentPG.glProjmodelview); - } - - if (-1 < modelviewMatLoc) { - currentPG.updateGLModelview(); - setUniformMatrix(modelviewMatLoc, currentPG.glModelview); - } - - if (-1 < projectionMatLoc) { - currentPG.updateGLProjection(); - setUniformMatrix(projectionMatLoc, currentPG.glProjection); - } - - if (-1 < viewportLoc) { - float x = currentPG.viewport.get(0); - float y = currentPG.viewport.get(1); - float w = currentPG.viewport.get(2); - float h = currentPG.viewport.get(3); - setUniformValue(viewportLoc, x, y, w, h); - } - - if (-1 < resolutionLoc) { - float w = currentPG.viewport.get(2); - float h = currentPG.viewport.get(3); - setUniformValue(resolutionLoc, w, h); - } - - if (-1 < ppixelsLoc) { - ppixelsUnit = getLastTexUnit() + 1; - setUniformValue(ppixelsLoc, ppixelsUnit); - pgl.activeTexture(PGL.TEXTURE0 + ppixelsUnit); - currentPG.bindFrontTexture(); - } else { - ppixelsUnit = -1; - } - } - - - protected void bindTyped() { - if (currentPG == null) { - setRenderer(primaryPG.getCurrentPG()); - loadAttributes(); - loadUniforms(); - } - setCommonUniforms(); - - if (-1 < vertexLoc) pgl.enableVertexAttribArray(vertexLoc); - if (-1 < colorLoc) pgl.enableVertexAttribArray(colorLoc); - if (-1 < texCoordLoc) pgl.enableVertexAttribArray(texCoordLoc); - if (-1 < normalLoc) pgl.enableVertexAttribArray(normalLoc); - - if (-1 < normalMatLoc) { - currentPG.updateGLNormal(); - setUniformMatrix(normalMatLoc, currentPG.glNormal); - } - - if (-1 < ambientLoc) pgl.enableVertexAttribArray(ambientLoc); - if (-1 < specularLoc) pgl.enableVertexAttribArray(specularLoc); - if (-1 < emissiveLoc) pgl.enableVertexAttribArray(emissiveLoc); - if (-1 < shininessLoc) pgl.enableVertexAttribArray(shininessLoc); - - int count = currentPG.lightCount; - setUniformValue(lightCountLoc, count); - if (0 < count) { - setUniformVector(lightPositionLoc, currentPG.lightPosition, 4, count); - setUniformVector(lightNormalLoc, currentPG.lightNormal, 3, count); - setUniformVector(lightAmbientLoc, currentPG.lightAmbient, 3, count); - setUniformVector(lightDiffuseLoc, currentPG.lightDiffuse, 3, count); - setUniformVector(lightSpecularLoc, currentPG.lightSpecular, 3, count); - setUniformVector(lightFalloffLoc, currentPG.lightFalloffCoefficients, - 3, count); - setUniformVector(lightSpotLoc, currentPG.lightSpotParameters, 2, count); - } - - if (-1 < directionLoc) pgl.enableVertexAttribArray(directionLoc); - - if (-1 < offsetLoc) pgl.enableVertexAttribArray(offsetLoc); - - if (-1 < perspectiveLoc) { - if (currentPG.getHint(ENABLE_STROKE_PERSPECTIVE) && - currentPG.nonOrthoProjection()) { - setUniformValue(perspectiveLoc, 1); - } else { - setUniformValue(perspectiveLoc, 0); - } - } - - if (-1 < scaleLoc) { - if (currentPG.getHint(DISABLE_OPTIMIZED_STROKE)) { - setUniformValue(scaleLoc, 1.0f, 1.0f, 1.0f); - } else { - float f = PGL.STROKE_DISPLACEMENT; - if (currentPG.orthoProjection()) { - setUniformValue(scaleLoc, 1, 1, f); - } else { - setUniformValue(scaleLoc, f, f, f); - } - } - } - } - - protected void unbindTyped() { - if (-1 < offsetLoc) pgl.disableVertexAttribArray(offsetLoc); - - if (-1 < directionLoc) pgl.disableVertexAttribArray(directionLoc); - - if (-1 < textureLoc && texture != null) { - pgl.activeTexture(PGL.TEXTURE0 + texUnit); - texture.unbind(); - pgl.activeTexture(PGL.TEXTURE0); - texture = null; - } - - if (-1 < ambientLoc) pgl.disableVertexAttribArray(ambientLoc); - if (-1 < specularLoc) pgl.disableVertexAttribArray(specularLoc); - if (-1 < emissiveLoc) pgl.disableVertexAttribArray(emissiveLoc); - if (-1 < shininessLoc) pgl.disableVertexAttribArray(shininessLoc); - - if (-1 < vertexLoc) pgl.disableVertexAttribArray(vertexLoc); - if (-1 < colorLoc) pgl.disableVertexAttribArray(colorLoc); - if (-1 < texCoordLoc) pgl.disableVertexAttribArray(texCoordLoc); - if (-1 < normalLoc) pgl.disableVertexAttribArray(normalLoc); - - if (-1 < ppixelsLoc) { - pgl.enableFBOLayer(); - pgl.activeTexture(PGL.TEXTURE0 + ppixelsUnit); - currentPG.unbindFrontTexture(); - pgl.activeTexture(PGL.TEXTURE0); - } - - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - protected void setTexture(Texture tex) { - texture = tex; - - float scaleu = 1; - float scalev = 1; - float dispu = 0; - float dispv = 0; - - if (tex != null) { - if (tex.invertedX()) { - scaleu = -1; - dispu = 1; - } - - if (tex.invertedY()) { - scalev = -1; - dispv = 1; - } - - scaleu *= tex.maxTexcoordU(); - dispu *= tex.maxTexcoordU(); - scalev *= tex.maxTexcoordV(); - dispv *= tex.maxTexcoordV(); - - setUniformValue(texOffsetLoc, 1.0f / tex.width, 1.0f / tex.height); - - if (-1 < textureLoc) { - texUnit = -1 < ppixelsUnit ? ppixelsUnit + 1 : getLastTexUnit() + 1; - setUniformValue(textureLoc, texUnit); - pgl.activeTexture(PGL.TEXTURE0 + texUnit); - tex.bind(); - } - } - - if (-1 < texMatrixLoc) { - if (tcmat == null) { - tcmat = new float[16]; - } - tcmat[0] = scaleu; tcmat[4] = 0; tcmat[ 8] = 0; tcmat[12] = dispu; - tcmat[1] = 0; tcmat[5] = scalev; tcmat[ 9] = 0; tcmat[13] = dispv; - tcmat[2] = 0; tcmat[6] = 0; tcmat[10] = 0; tcmat[14] = 0; - tcmat[3] = 0; tcmat[7] = 0; tcmat[11] = 0; tcmat[15] = 0; - setUniformMatrix(texMatrixLoc, tcmat); - } - } - - - protected boolean supportsTexturing() { - return -1 < textureLoc; - } - - protected boolean supportLighting() { - return -1 < lightCountLoc || -1 < lightPositionLoc || -1 < lightNormalLoc; - } - - protected boolean accessTexCoords() { - return -1 < texCoordLoc; - } - - protected boolean accessNormals() { - return -1 < normalLoc; - } - - protected boolean accessLightAttribs() { - return -1 < ambientLoc || -1 < specularLoc || -1 < emissiveLoc || - -1 < shininessLoc; - } - - protected void setVertexAttribute(int vboId, int size, int type, - int stride, int offset) { - setAttributeVBO(vertexLoc, vboId, size, type, false, stride, offset); - } - - protected void setColorAttribute(int vboId, int size, int type, - int stride, int offset) { - setAttributeVBO(colorLoc, vboId, size, type, true, stride, offset); - } - - protected void setNormalAttribute(int vboId, int size, int type, - int stride, int offset) { - setAttributeVBO(normalLoc, vboId, size, type, false, stride, offset); - } - - protected void setTexcoordAttribute(int vboId, int size, int type, - int stride, int offset) { - setAttributeVBO(texCoordLoc, vboId, size, type, false, stride, offset); - } - - protected void setAmbientAttribute(int vboId, int size, int type, - int stride, int offset) { - setAttributeVBO(ambientLoc, vboId, size, type, true, stride, offset); - } - - protected void setSpecularAttribute(int vboId, int size, int type, - int stride, int offset) { - setAttributeVBO(specularLoc, vboId, size, type, true, stride, offset); - } - - protected void setEmissiveAttribute(int vboId, int size, int type, - int stride, int offset) { - setAttributeVBO(emissiveLoc, vboId, size, type, true, stride, offset); - } - - protected void setShininessAttribute(int vboId, int size, int type, - int stride, int offset) { - setAttributeVBO(shininessLoc, vboId, size, type, false, stride, offset); - } - - protected void setLineAttribute(int vboId, int size, int type, - int stride, int offset) { - setAttributeVBO(directionLoc, vboId, size, type, false, stride, offset); - } - - protected void setPointAttribute(int vboId, int size, int type, - int stride, int offset) { - setAttributeVBO(offsetLoc, vboId, size, type, false, stride, offset); - } - - - // *************************************************************************** - // - // Class to store a user-specified value for a uniform parameter - // in the shader - protected static class UniformValue { - static final int INT1 = 0; - static final int INT2 = 1; - static final int INT3 = 2; - static final int INT4 = 3; - static final int FLOAT1 = 4; - static final int FLOAT2 = 5; - static final int FLOAT3 = 6; - static final int FLOAT4 = 7; - static final int INT1VEC = 8; - static final int INT2VEC = 9; - static final int INT3VEC = 10; - static final int INT4VEC = 11; - static final int FLOAT1VEC = 12; - static final int FLOAT2VEC = 13; - static final int FLOAT3VEC = 14; - static final int FLOAT4VEC = 15; - static final int MAT2 = 16; - static final int MAT3 = 17; - static final int MAT4 = 18; - static final int SAMPLER2D = 19; - - int type; - Object value; - - UniformValue(int type, Object value) { - this.type = type; - this.value = value; - } - } -} diff --git a/core/src/processing/opengl/PShapeOpenGL.java b/core/src/processing/opengl/PShapeOpenGL.java deleted file mode 100644 index 3f65727b4..000000000 --- a/core/src/processing/opengl/PShapeOpenGL.java +++ /dev/null @@ -1,5254 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import processing.core.PApplet; -import processing.core.PConstants; -import processing.core.PGraphics; -import processing.core.PImage; -import processing.core.PMatrix; -import processing.core.PMatrix2D; -import processing.core.PMatrix3D; -import processing.core.PShape; -import processing.core.PVector; -import processing.opengl.PGraphicsOpenGL.AttributeMap; -import processing.opengl.PGraphicsOpenGL.IndexCache; -import processing.opengl.PGraphicsOpenGL.InGeometry; -import processing.opengl.PGraphicsOpenGL.TessGeometry; -import processing.opengl.PGraphicsOpenGL.Tessellator; -import processing.opengl.PGraphicsOpenGL.VertexAttribute; - -import java.nio.Buffer; -import java.util.Arrays; -import java.util.HashSet; - -/** - * This class holds a 3D model composed of vertices, normals, colors - * (per vertex) and texture coordinates (also per vertex). All this data is - * stored in Vertex Buffer Objects (VBO) in GPU memory for very fast access. - * OBJ loading implemented using code from Saito's OBJLoader library: - * http://code.google.com/p/saitoobjloader/ - * and OBJReader from Ahmet Kizilay - * http://www.openprocessing.org/visuals/?visualID=191 - * By Andres Colubri - * - * - * Other formats to consider: - * AMF: http://en.wikipedia.org/wiki/Additive_Manufacturing_File_Format - * STL: http://en.wikipedia.org/wiki/STL_(file_format) - * OFF: http://people.sc.fsu.edu/~jburkardt/data/off/off.html(file_format) - * DXF: http://en.wikipedia.org/wiki/AutoCAD_DXF - */ -public class PShapeOpenGL extends PShape { - // Testing these constants, not use as they might go away... - static public final int POSITION = 0; - static public final int NORMAL = 1; - static public final int TEXCOORD = 2; - static public final int DIRECTION = 3; - static public final int OFFSET = 4; - - static protected final int TRANSLATE = 0; - static protected final int ROTATE = 1; - static protected final int SCALE = 2; - static protected final int MATRIX = 3; - - protected PGraphicsOpenGL pg; - protected PGL pgl; - protected int context; // The context that created this shape. - - protected PShapeOpenGL root; - - // ........................................................ - - // Input, tessellated geometry - - protected InGeometry inGeo; - protected TessGeometry tessGeo; - protected Tessellator tessellator; - - protected AttributeMap polyAttribs; - - // ........................................................ - - // Texturing - - protected HashSet textures; - protected boolean strokedTexture; - protected boolean untexChild; - - // ........................................................ - - // OpenGL buffers - - protected VertexBuffer bufPolyVertex; - protected VertexBuffer bufPolyColor; - protected VertexBuffer bufPolyNormal; - protected VertexBuffer bufPolyTexcoord; - protected VertexBuffer bufPolyAmbient; - protected VertexBuffer bufPolySpecular; - protected VertexBuffer bufPolyEmissive; - protected VertexBuffer bufPolyShininess; - protected VertexBuffer bufPolyIndex; - - protected VertexBuffer bufLineVertex; - protected VertexBuffer bufLineColor; - protected VertexBuffer bufLineAttrib; - protected VertexBuffer bufLineIndex; - - protected VertexBuffer bufPointVertex; - protected VertexBuffer bufPointColor; - protected VertexBuffer bufPointAttrib; - protected VertexBuffer bufPointIndex; - - // Testing this field, not use as it might go away... - public int glUsage = PGL.STATIC_DRAW; - - // ........................................................ - - // Offsets for geometry aggregation and update. - - protected int polyVertCopyOffset; - protected int polyIndCopyOffset; - protected int lineVertCopyOffset; - protected int lineIndCopyOffset; - protected int pointVertCopyOffset; - protected int pointIndCopyOffset; - - protected int polyIndexOffset; - protected int polyVertexOffset; - protected int polyVertexAbs; - protected int polyVertexRel; - - protected int lineIndexOffset; - protected int lineVertexOffset; - protected int lineVertexAbs; - protected int lineVertexRel; - - protected int pointIndexOffset; - protected int pointVertexOffset; - protected int pointVertexAbs; - protected int pointVertexRel; - - protected int firstPolyIndexCache; - protected int lastPolyIndexCache; - protected int firstLineIndexCache; - protected int lastLineIndexCache; - protected int firstPointIndexCache; - protected int lastPointIndexCache; - - protected int firstPolyVertex; - protected int lastPolyVertex; - protected int firstLineVertex; - protected int lastLineVertex; - protected int firstPointVertex; - protected int lastPointVertex; - - // ........................................................ - - // Geometric transformations. - - protected PMatrix transform; - protected PMatrix transformInv; - protected PMatrix matrixInv; - - // ........................................................ - - // State/rendering flags - - protected boolean tessellated; - protected boolean needBufferInit = false; - - // Flag to indicate if the shape can have holes or not. - protected boolean solid = true; - - protected boolean breakShape = false; - protected boolean shapeCreated = false; - - // These variables indicate if the shape contains - // polygon, line and/or point geometry. In the case of - // 3D shapes, poly geometry is coincident with the fill - // triangles, as the lines and points are stored separately. - // However, for 2D shapes the poly geometry contains all of - // the three since the same rendering shader applies to - // fill, line and point geometry. - protected boolean hasPolys; - protected boolean hasLines; - protected boolean hasPoints; - - // ........................................................ - - // Bezier and Catmull-Rom curves - - protected int bezierDetail; - protected int curveDetail; - protected float curveTightness; - - protected int savedBezierDetail; - protected int savedCurveDetail; - protected float savedCurveTightness; - - // ........................................................ - - // Normals - - protected float normalX, normalY, normalZ; - - // normal calculated per triangle - static protected final int NORMAL_MODE_AUTO = 0; - // one normal manually specified per shape - static protected final int NORMAL_MODE_SHAPE = 1; - // normals specified for each shape vertex - static protected final int NORMAL_MODE_VERTEX = 2; - - // Current mode for normals, one of AUTO, SHAPE, or VERTEX - protected int normalMode; - - // ........................................................ - - // Modification variables (used only by the root shape) - - protected boolean modified; - - protected boolean modifiedPolyVertices; - protected boolean modifiedPolyColors; - protected boolean modifiedPolyNormals; - protected boolean modifiedPolyTexCoords; - protected boolean modifiedPolyAmbient; - protected boolean modifiedPolySpecular; - protected boolean modifiedPolyEmissive; - protected boolean modifiedPolyShininess; - - protected boolean modifiedLineVertices; - protected boolean modifiedLineColors; - protected boolean modifiedLineAttributes; - - protected boolean modifiedPointVertices; - protected boolean modifiedPointColors; - protected boolean modifiedPointAttributes; - - protected int firstModifiedPolyVertex; - protected int lastModifiedPolyVertex; - protected int firstModifiedPolyColor; - protected int lastModifiedPolyColor; - protected int firstModifiedPolyNormal; - protected int lastModifiedPolyNormal; - protected int firstModifiedPolyTexcoord; - protected int lastModifiedPolyTexcoord; - protected int firstModifiedPolyAmbient; - protected int lastModifiedPolyAmbient; - protected int firstModifiedPolySpecular; - protected int lastModifiedPolySpecular; - protected int firstModifiedPolyEmissive; - protected int lastModifiedPolyEmissive; - protected int firstModifiedPolyShininess; - protected int lastModifiedPolyShininess; - - protected int firstModifiedLineVertex; - protected int lastModifiedLineVertex; - protected int firstModifiedLineColor; - protected int lastModifiedLineColor; - protected int firstModifiedLineAttribute; - protected int lastModifiedLineAttribute; - - protected int firstModifiedPointVertex; - protected int lastModifiedPointVertex; - protected int firstModifiedPointColor; - protected int lastModifiedPointColor; - protected int firstModifiedPointAttribute; - protected int lastModifiedPointAttribute; - - // ........................................................ - - // Saved style variables to style can be re-enabled after disableStyle, - // although it won't work if properties are defined on a per-vertex basis. - - protected boolean savedStroke; - protected int savedStrokeColor; - protected float savedStrokeWeight; - protected int savedStrokeCap; - protected int savedStrokeJoin; - - protected boolean savedFill; - protected int savedFillColor; - - protected boolean savedTint; - protected int savedTintColor; - - protected int savedAmbientColor; - protected int savedSpecularColor; - protected int savedEmissiveColor; - protected float savedShininess; - - protected int savedTextureMode; - - - PShapeOpenGL() { - } - - - public PShapeOpenGL(PGraphicsOpenGL pg, int family) { - this.pg = pg; - this.family = family; - - pgl = pg.pgl; - context = pgl.createEmptyContext(); - - bufPolyVertex = null; - bufPolyColor = null; - bufPolyNormal = null; - bufPolyTexcoord = null; - bufPolyAmbient = null; - bufPolySpecular = null; - bufPolyEmissive = null; - bufPolyShininess = null; - bufPolyIndex = null; - - bufLineVertex = null; - bufLineColor = null; - bufLineAttrib = null; - bufLineIndex = null; - - bufPointVertex = null; - bufPointColor = null; - bufPointAttrib = null; - bufPointIndex = null; - - this.tessellator = pg.tessellator; - this.root = this; - this.parent = null; - this.tessellated = false; - - if (family == GEOMETRY || family == PRIMITIVE || family == PATH) { - polyAttribs = PGraphicsOpenGL.newAttributeMap(); - inGeo = PGraphicsOpenGL.newInGeometry(pg, polyAttribs, PGraphicsOpenGL.RETAINED); - } - - // Style parameters are retrieved from the current values in the renderer. - textureMode = pg.textureMode; - - colorMode(pg.colorMode, - pg.colorModeX, pg.colorModeY, pg.colorModeZ, pg.colorModeA); - - // Initial values for fill, stroke and tint colors are also imported from - // the renderer. This is particular relevant for primitive shapes, since is - // not possible to set their color separately when creating them, and their - // input vertices are actually generated at rendering time, by which the - // color configuration of the renderer might have changed. - fill = pg.fill; - fillColor = pg.fillColor; - - stroke = pg.stroke; - strokeColor = pg.strokeColor; - strokeWeight = pg.strokeWeight; - strokeCap = pg.strokeCap; - strokeJoin = pg.strokeJoin; - - tint = pg.tint; - tintColor = pg.tintColor; - - setAmbient = pg.setAmbient; - ambientColor = pg.ambientColor; - specularColor = pg.specularColor; - emissiveColor = pg.emissiveColor; - shininess = pg.shininess; - - sphereDetailU = pg.sphereDetailU; - sphereDetailV = pg.sphereDetailV; - - bezierDetail = pg.bezierDetail; - curveDetail = pg.curveDetail; - curveTightness = pg.curveTightness; - - rectMode = pg.rectMode; - ellipseMode = pg.ellipseMode; - - normalX = normalY = 0; - normalZ = 1; - - normalMode = NORMAL_MODE_AUTO; - - // To make sure that the first vertex is marked as a break. - // Same behavior as in the immediate mode. - breakShape = false; - - if (family == GROUP) { - // GROUP shapes are always marked as ended. - shapeCreated = true; - } - - // OpenGL supports per-vertex coloring (unlike Java2D) - perVertexStyles = true; - } - - - /** Create a shape from the PRIMITIVE family, using this kind and these params */ - public PShapeOpenGL(PGraphicsOpenGL pg, int kind, float... p) { - this(pg, PRIMITIVE); - setKind(kind); - setParams(p); - } - - - @Override - public void addChild(PShape who) { - if (who instanceof PShapeOpenGL) { - if (family == GROUP) { - PShapeOpenGL c3d = (PShapeOpenGL)who; - - super.addChild(c3d); - c3d.updateRoot(root); - markForTessellation(); - - if (c3d.family == GROUP) { - if (c3d.textures != null) { - for (PImage tex: c3d.textures) { - addTexture(tex); - } - } else { - untexChild(true); - } - if (c3d.strokedTexture) { - strokedTexture(true); - } - } else { - if (c3d.image != null) { - addTexture(c3d.image); - if (c3d.stroke) { - strokedTexture(true); - } - } else { - untexChild(true); - } - } - - } else { - PGraphics.showWarning("Cannot add child shape to non-group shape."); - } - } else { - PGraphics.showWarning("Shape must be OpenGL to be added to the group."); - } - } - - - @Override - public void addChild(PShape who, int idx) { - if (who instanceof PShapeOpenGL) { - if (family == GROUP) { - PShapeOpenGL c3d = (PShapeOpenGL)who; - - super.addChild(c3d, idx); - c3d.updateRoot(root); - markForTessellation(); - - if (c3d.family == GROUP) { - if (c3d.textures != null) { - for (PImage tex: c3d.textures) { - addTexture(tex); - } - } else { - untexChild(true); - } - if (c3d.strokedTexture) { - strokedTexture(true); - } - } else { - if (c3d.image != null) { - addTexture(c3d.image); - if (c3d.stroke) { - strokedTexture(true); - } - } else { - untexChild(true); - } - } - - } else { - PGraphics.showWarning("Cannot add child shape to non-group shape."); - } - } else { - PGraphics.showWarning("Shape must be OpenGL to be added to the group."); - } - } - - - @Override - public void removeChild(int idx) { - super.removeChild(idx); - strokedTexture(false); - untexChild(false); - markForTessellation(); - } - - - protected void updateRoot(PShape root) { - this.root = (PShapeOpenGL) root; - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL)children[i]; - child.updateRoot(root); - } - } - } - - - /////////////////////////////////////////////////////////// - - // - // Shape creation (temporary hack) - - - public static PShapeOpenGL createShape(PGraphicsOpenGL pg, PShape src) { - PShapeOpenGL dest = null; - if (src.getFamily() == GROUP) { - //dest = PGraphics3D.createShapeImpl(pg, GROUP); - dest = (PShapeOpenGL) pg.createShapeFamily(GROUP); - copyGroup(pg, src, dest); - } else if (src.getFamily() == PRIMITIVE) { - //dest = PGraphics3D.createShapeImpl(pg, src.getKind(), src.getParams()); - dest = (PShapeOpenGL) pg.createShapePrimitive(src.getKind(), src.getParams()); - PShape.copyPrimitive(src, dest); - } else if (src.getFamily() == GEOMETRY) { - //dest = PGraphics3D.createShapeImpl(pg, PShape.GEOMETRY); - dest = (PShapeOpenGL) pg.createShapeFamily(PShape.GEOMETRY); - PShape.copyGeometry(src, dest); - } else if (src.getFamily() == PATH) { - dest = (PShapeOpenGL) pg.createShapeFamily(PShape.PATH); - //dest = PGraphics3D.createShapeImpl(pg, PATH); - PShape.copyPath(src, dest); - } - dest.setName(src.getName()); - dest.width = src.width; - dest.height = src.height; - dest.depth = src.depth; - return dest; - } - - - /* - static public PShapeOpenGL createShape2D(PGraphicsOpenGL pg, PShape src) { - PShapeOpenGL dest = null; - if (src.getFamily() == GROUP) { - //dest = PGraphics2D.createShapeImpl(pg, GROUP); - dest = (PShapeOpenGL) pg.createShapeFamily(GROUP); - copyGroup2D(pg, src, dest); - } else if (src.getFamily() == PRIMITIVE) { - //dest = PGraphics2D.createShapeImpl(pg, src.getKind(), src.getParams()); - dest = (PShapeOpenGL) pg.createShapePrimitive(src.getKind(), src.getParams()); - PShape.copyPrimitive(src, dest); - } else if (src.getFamily() == GEOMETRY) { - //dest = PGraphics2D.createShapeImpl(pg, PShape.GEOMETRY); - dest = (PShapeOpenGL) pg.createShapeFamily(PShape.GEOMETRY); - PShape.copyGeometry(src, dest); - } else if (src.getFamily() == PATH) { - //dest = PGraphics2D.createShapeImpl(pg, PATH); - dest = (PShapeOpenGL) pg.createShapeFamily(PShape.PATH); - PShape.copyPath(src, dest); - } - dest.setName(src.getName()); - dest.width = src.width; - dest.height = src.height; - return dest; - } -*/ - - static public void copyGroup(PGraphicsOpenGL pg, PShape src, PShape dest) { - copyMatrix(src, dest); - copyStyles(src, dest); - copyImage(src, dest); - - for (int i = 0; i < src.getChildCount(); i++) { - PShape c = createShape(pg, src.getChild(i)); - dest.addChild(c); - } - } - - - /* - static public void copyGroup2D(PGraphicsOpenGL pg, PShape src, PShape dest) { - copyMatrix(src, dest); - copyStyles(src, dest); - copyImage(src, dest); - - for (int i = 0; i < src.getChildCount(); i++) { - PShape c = createShape2D(pg, src.getChild(i)); - dest.addChild(c); - } - } -*/ - - /////////////////////////////////////////////////////////// - - // - - // Query methods - - - @Override - public float getWidth() { - PVector min = new PVector(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, - Float.POSITIVE_INFINITY); - PVector max = new PVector(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, - Float.NEGATIVE_INFINITY); - if (shapeCreated) { - getVertexMin(min); - getVertexMax(max); - } - width = max.x - min.x; - return width; - } - - - @Override - public float getHeight() { - PVector min = new PVector(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, - Float.POSITIVE_INFINITY); - PVector max = new PVector(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, - Float.NEGATIVE_INFINITY); - if (shapeCreated) { - getVertexMin(min); - getVertexMax(max); - } - height = max.y - min.y; - return height; - } - - - @Override - public float getDepth() { - PVector min = new PVector(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, - Float.POSITIVE_INFINITY); - PVector max = new PVector(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, - Float.NEGATIVE_INFINITY); - if (shapeCreated) { - getVertexMin(min); - getVertexMax(max); - } - depth = max.z - min.z; - return depth; - } - - - protected void getVertexMin(PVector min) { - updateTessellation(); - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.getVertexMin(min); - } - } else { - if (hasPolys) { - tessGeo.getPolyVertexMin(min, firstPolyVertex, lastPolyVertex); - } - if (is3D()) { - if (hasLines) { - tessGeo.getLineVertexMin(min, firstLineVertex, lastLineVertex); - } - if (hasPoints) { - tessGeo.getPointVertexMin(min, firstPointVertex, lastPointVertex); - } - } - } - } - - - protected void getVertexMax(PVector max) { - updateTessellation(); - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.getVertexMax(max); - } - } else { - if (hasPolys) { - tessGeo.getPolyVertexMax(max, firstPolyVertex, lastPolyVertex); - } - if (is3D()) { - if (hasLines) { - tessGeo.getLineVertexMax(max, firstLineVertex, lastLineVertex); - } - if (hasPoints) { - tessGeo.getPointVertexMax(max, firstPointVertex, lastPointVertex); - } - } - } - } - - - protected int getVertexSum(PVector sum, int count) { - updateTessellation(); - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - count += child.getVertexSum(sum, count); - } - } else { - if (hasPolys) { - count += tessGeo.getPolyVertexSum(sum, firstPolyVertex, lastPolyVertex); - } - if (is3D()) { - if (hasLines) { - count += tessGeo.getLineVertexSum(sum, firstLineVertex, - lastLineVertex); - } - if (hasPoints) { - count += tessGeo.getPointVertexSum(sum, firstPointVertex, - lastPointVertex); - } - } - } - return count; - } - - - /////////////////////////////////////////////////////////// - - // - - // Drawing methods - - - @Override - public void setTextureMode(int mode) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTextureMode()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setTextureMode(mode); - } - } else { - setTextureModeImpl(mode); - } - } - - - protected void setTextureModeImpl(int mode) { - if (textureMode == mode) return; - textureMode = mode; - if (image != null) { - float uFactor = image.width; - float vFactor = image.height; - if (textureMode == NORMAL) { - uFactor = 1.0f / uFactor; - vFactor = 1.0f / vFactor; - } - scaleTextureUV(uFactor, vFactor); - } - } - - - @Override - public void setTexture(PImage tex) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTexture()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setTexture(tex); - } - } else { - setTextureImpl(tex); - } - } - - - protected void setTextureImpl(PImage tex) { - PImage image0 = image; - image = tex; - - if (textureMode == IMAGE && image0 != image) { - // Need to rescale the texture coordinates - float uFactor = 1; - float vFactor = 1; - if (image != null) { - uFactor /= image.width; - vFactor /= image.height; - } - if (image0 != null) { - uFactor *= image0.width; - vFactor *= image0.height; - } - scaleTextureUV(uFactor, vFactor); - } - - if (image0 != tex && parent != null) { - ((PShapeOpenGL)parent).removeTexture(image0, this); - } - if (parent != null) { - ((PShapeOpenGL)parent).addTexture(image); - if (is2D() && stroke) { - ((PShapeOpenGL)parent).strokedTexture(true); - } - } - } - - - protected void scaleTextureUV(float uFactor, float vFactor) { - if (PGraphicsOpenGL.same(uFactor, 1) && - PGraphicsOpenGL.same(vFactor, 1)) return; - - for (int i = 0; i < inGeo.vertexCount; i++) { - float u = inGeo.texcoords[2 * i + 0]; - float v = inGeo.texcoords[2 * i + 1]; - inGeo.texcoords[2 * i + 0] = PApplet.min(1, u * uFactor); - inGeo.texcoords[2 * i + 1] = PApplet.min(1, v * uFactor); - } - - if (shapeCreated && tessellated && hasPolys) { - int last1 = 0; - if (is3D()) { - last1 = lastPolyVertex + 1; - } else if (is2D()) { - last1 = lastPolyVertex + 1; - if (-1 < firstLineVertex) last1 = firstLineVertex; - if (-1 < firstPointVertex) last1 = firstPointVertex; - } - for (int i = firstLineVertex; i < last1; i++) { - float u = tessGeo.polyTexCoords[2 * i + 0]; - float v = tessGeo.polyTexCoords[2 * i + 1]; - tessGeo.polyTexCoords[2 * i + 0] = PApplet.min(1, u * uFactor); - tessGeo.polyTexCoords[2 * i + 1] = PApplet.min(1, v * uFactor); - } - root.setModifiedPolyTexCoords(firstPolyVertex, last1 - 1); - } - } - - - protected void addTexture(PImage tex) { - if (textures == null) { - textures = new HashSet<>(); - } - textures.add(tex); - if (parent != null) { - ((PShapeOpenGL)parent).addTexture(tex); - } - } - - - protected void removeTexture(PImage tex, PShapeOpenGL caller) { - if (textures == null || !textures.contains(tex)) return; // Nothing to remove. - - // First check that none of the child shapes have texture tex... - boolean childHasTex = false; - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - if (child == caller) continue; - if (child.hasTexture(tex)) { - childHasTex = true; - break; - } - } - - if (!childHasTex) { - // ...if not, it is safe to remove from this shape. - textures.remove(tex); - if (textures.size() == 0) { - textures = null; - } - } - - // Since this shape and all its child shapes don't contain - // tex anymore, we now can remove it from the parent. - if (parent != null) { - ((PShapeOpenGL)parent).removeTexture(tex, this); - } - } - - - protected void strokedTexture(boolean newValue) { - strokedTexture(newValue, null); - } - - - protected void strokedTexture(boolean newValue, PShapeOpenGL caller) { - if (strokedTexture == newValue) return; // Nothing to change. - - if (newValue) { - strokedTexture = true; - } else { - // Check that none of the child shapes have a stroked texture... - strokedTexture = false; - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - if (child == caller) continue; - if (child.hasStrokedTexture()) { - strokedTexture = true; - break; - } - } - } - - // Now we can update the parent shape. - if (parent != null) { - ((PShapeOpenGL)parent).strokedTexture(newValue, this); - } - } - - - protected void untexChild(boolean newValue) { - untexChild(newValue, null); - } - - - protected void untexChild(boolean newValue, PShapeOpenGL caller) { - if (untexChild == newValue) return; // Nothing to change. - - if (newValue) { - untexChild = true; - } else { - // Check if any of the child shapes is not textured... - untexChild = false; - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - if (child == caller) continue; - if (!child.hasTexture()) { - untexChild = true; - break; - } - } - } - - // Now we can update the parent shape. - if (parent != null) { - ((PShapeOpenGL)parent).untexChild(newValue, this); - } - } - - - protected boolean hasTexture() { - if (family == GROUP) { - return textures != null && 0 < textures.size(); - } else { - return image != null; - } - } - - - protected boolean hasTexture(PImage tex) { - if (family == GROUP) { - return textures != null && textures.contains(tex); - } else { - return image == tex; - } - } - - - protected boolean hasStrokedTexture() { - if (family == GROUP) { - return strokedTexture; - } else { - return image != null && stroke; - } - } - - - @Override - public void solid(boolean solid) { - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.solid(solid); - } - } else { - this.solid = solid; - } - } - - - @Override - protected void beginContourImpl() { - breakShape = true; - } - - - @Override - protected void endContourImpl() { - } - - - @Override - public void vertex(float x, float y) { - vertexImpl(x, y, 0, 0, 0); - if (image != null) - PGraphics.showWarning(PGraphicsOpenGL.MISSING_UV_TEXCOORDS_ERROR); - } - - - @Override - public void vertex(float x, float y, float u, float v) { - vertexImpl(x, y, 0, u, v); - } - - - @Override - public void vertex(float x, float y, float z) { - vertexImpl(x, y, z, 0, 0); - if (image != null) - PGraphics.showWarning(PGraphicsOpenGL.MISSING_UV_TEXCOORDS_ERROR); - } - - - @Override - public void vertex(float x, float y, float z, float u, float v) { - vertexImpl(x, y, z, u, v); - } - - - protected void vertexImpl(float x, float y, float z, float u, float v) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "vertex()"); - return; - } - - if (family == GROUP) { - PGraphics.showWarning("Cannot add vertices to GROUP shape"); - return; - } - - boolean textured = image != null; - int fcolor = 0x00; - if (fill || textured) { - if (!textured) { - fcolor = fillColor; - } else { - if (tint) { - fcolor = tintColor; - } else { - fcolor = 0xffFFFFFF; - } - } - } - - if (textureMode == IMAGE && image != null) { - u /= image.width; - v /= image.height; - } - - int scolor = 0x00; - float sweight = 0; - if (stroke) { - scolor = strokeColor; - sweight = strokeWeight; - } - - inGeo.addVertex(x, y, z, - fcolor, - normalX, normalY, normalZ, - u, v, - scolor, sweight, - ambientColor, specularColor, emissiveColor, shininess, - VERTEX, vertexBreak()); - - markForTessellation(); - } - - - protected boolean vertexBreak() { - if (breakShape) { - breakShape = false; - return true; - } - return false; - } - - - @Override - public void normal(float nx, float ny, float nz) { - if (!openShape) { - PGraphics.showWarning(OUTSIDE_BEGIN_END_ERROR, "normal()"); - return; - } - - if (family == GROUP) { - PGraphics.showWarning("Cannot set normal in GROUP shape"); - return; - } - - normalX = nx; - normalY = ny; - normalZ = nz; - - // if drawing a shape and the normal hasn't been set yet, - // then we need to set the normals for each vertex so far - if (normalMode == NORMAL_MODE_AUTO) { - // One normal per begin/end shape - normalMode = NORMAL_MODE_SHAPE; - } else if (normalMode == NORMAL_MODE_SHAPE) { - // a separate normal for each vertex - normalMode = NORMAL_MODE_VERTEX; - } - } - - - @Override - public void attribPosition(String name, float x, float y, float z) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.POSITION, - PGL.FLOAT, 3); - if (attrib != null) attrib.set(x, y, z); - } - - - @Override - public void attribNormal(String name, float nx, float ny, float nz) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.NORMAL, - PGL.FLOAT, 3); - if (attrib != null) attrib.set(nx, ny, nz); - } - - - @Override - public void attribColor(String name, int color) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.COLOR, PGL.INT, 1); - if (attrib != null) attrib.set(new int[] {color}); - } - - - @Override - public void attrib(String name, float... values) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.OTHER, PGL.FLOAT, - values.length); - if (attrib != null) attrib.set(values); - } - - - @Override - public void attrib(String name, int... values) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.OTHER, PGL.INT, - values.length); - if (attrib != null) attrib.set(values); - } - - - @Override - public void attrib(String name, boolean... values) { - VertexAttribute attrib = attribImpl(name, VertexAttribute.OTHER, PGL.BOOL, - values.length); - if (attrib != null) attrib.set(values); - } - - - protected VertexAttribute attribImpl(String name, int kind, int type, int size) { - if (4 < size) { - PGraphics.showWarning("Vertex attributes cannot have more than 4 values"); - return null; - } - VertexAttribute attrib = polyAttribs.get(name); - if (attrib == null) { - attrib = new VertexAttribute(pg, name, kind, type, size); - polyAttribs.put(name, attrib); - inGeo.initAttrib(attrib); - } - if (attrib.kind != kind) { - PGraphics.showWarning("The attribute kind cannot be changed after creation"); - return null; - } - if (attrib.type != type) { - PGraphics.showWarning("The attribute type cannot be changed after creation"); - return null; - } - if (attrib.size != size) { - PGraphics.showWarning("New value for vertex attribute has wrong number of values"); - return null; - } - return attrib; - } - - - @Override - public void endShape(int mode) { - super.endShape(mode); - - // Input arrays are trimmed since they are expanded by doubling their old - // size, which might lead to arrays larger than the vertex counts. - inGeo.trim(); - - close = mode == CLOSE; - markForTessellation(); - shapeCreated = true; - } - - - @Override - public void setParams(float[] source) { - if (family != PRIMITIVE) { - PGraphics.showWarning("Parameters can only be set to PRIMITIVE shapes"); - return; - } - - super.setParams(source); - markForTessellation(); - shapeCreated = true; - } - - - @Override - public void setPath(int vcount, float[][] verts, int ccount, int[] codes) { - if (family != PATH) { - PGraphics.showWarning("Vertex coordinates and codes can only be set to " + - "PATH shapes"); - return; - } - - super.setPath(vcount, verts, ccount, codes); - markForTessellation(); - shapeCreated = true; - } - - - /////////////////////////////////////////////////////////// - - // - - // Geometric transformations - - - @Override - public void translate(float tx, float ty) { - if (is3D) { - transform(TRANSLATE, tx, ty, 0); - } else { - transform(TRANSLATE, tx, ty); - } - } - - - @Override - public void translate(float tx, float ty, float tz) { - transform(TRANSLATE, tx, ty, tz); - } - - - @Override - public void rotate(float angle) { - if (is3D) { - transform(ROTATE, angle, 0, 0, 1); - } else { - transform(ROTATE, angle); - } - } - - - @Override - public void rotateX(float angle) { - rotate(angle, 1, 0, 0); - } - - - @Override - public void rotateY(float angle) { - rotate(angle, 0, 1, 0); - } - - - @Override - public void rotateZ(float angle) { - transform(ROTATE, angle); - } - - - @Override - public void rotate(float angle, float v0, float v1, float v2) { - transform(ROTATE, angle, v0, v1, v2); - } - - - @Override - public void scale(float s) { - if (is3D) { - transform(SCALE, s, s, s); - } else { - transform(SCALE, s, s); - } - } - - - @Override - public void scale(float x, float y) { - if (is3D) { - transform(SCALE, x, y, 1); - } else { - transform(SCALE, x, y); - } - } - - - @Override - public void scale(float x, float y, float z) { - transform(SCALE, x, y, z); - } - - - @Override - public void applyMatrix(PMatrix2D source) { - transform(MATRIX, source.m00, source.m01, source.m02, - source.m10, source.m11, source.m12); - } - - - @Override - public void applyMatrix(float n00, float n01, float n02, - float n10, float n11, float n12) { - transform(MATRIX, n00, n01, n02, - n10, n11, n12); - } - - - @Override - public void applyMatrix(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - transform(MATRIX, n00, n01, n02, n03, - n10, n11, n12, n13, - n20, n21, n22, n23, - n30, n31, n32, n33); - } - - - @Override - public void resetMatrix() { - if (shapeCreated && matrix != null && matrixInv != null) { - if (family == GROUP) { - updateTessellation(); - } - if (tessellated) { - applyMatrixImpl(matrixInv); - } - matrix.reset(); - matrixInv.reset(); - } - } - - - protected void transform(int type, float... args) { - int dimensions = is3D ? 3 : 2; - boolean invertible = true; - checkMatrix(dimensions); - if (transform == null) { - if (dimensions == 2) { - transform = new PMatrix2D(); - transformInv = new PMatrix2D(); - } else { - transform = new PMatrix3D(); - transformInv = new PMatrix3D(); - } - } else { - transform.reset(); - transformInv.reset(); - } - - int ncoords = args.length; - if (type == ROTATE) { - ncoords = args.length == 1 ? 2 : 3; - } else if (type == MATRIX) { - ncoords = args.length == 6 ? 2 : 3; - } - - switch (type) { - case TRANSLATE: - if (ncoords == 3) { - transform.translate(args[0], args[1], args[2]); - PGraphicsOpenGL.invTranslate((PMatrix3D)transformInv, args[0], args[1], args[2]); - } else { - transform.translate(args[0], args[1]); - PGraphicsOpenGL.invTranslate((PMatrix2D)transformInv, args[0], args[1]); - } - break; - case ROTATE: - if (ncoords == 3) { - transform.rotate(args[0], args[1], args[2], args[3]); - PGraphicsOpenGL.invRotate((PMatrix3D)transformInv, args[0], args[1], args[2], args[3]); - } else { - transform.rotate(args[0]); - PGraphicsOpenGL.invRotate((PMatrix2D)transformInv, -args[0]); - } - break; - case SCALE: - if (ncoords == 3) { - transform.scale(args[0], args[1], args[2]); - PGraphicsOpenGL.invScale((PMatrix3D)transformInv, args[0], args[1], args[2]); - } else { - transform.scale(args[0], args[1]); - PGraphicsOpenGL.invScale((PMatrix2D)transformInv, args[0], args[1]); - } - break; - case MATRIX: - if (ncoords == 3) { - transform.set(args[ 0], args[ 1], args[ 2], args[ 3], - args[ 4], args[ 5], args[ 6], args[ 7], - args[ 8], args[ 9], args[10], args[11], - args[12], args[13], args[14], args[15]); - } else { - transform.set(args[0], args[1], args[2], - args[3], args[4], args[5]); - } - transformInv.set(transform); - invertible = transformInv.invert(); - break; - } - matrix.preApply(transform); - if (invertible) { - matrixInv.apply(transformInv); - } else { - PGraphics.showWarning("Transformation applied on the shape cannot be inverted"); - } - if (tessellated) applyMatrixImpl(transform); - } - - - protected void applyMatrixImpl(PMatrix matrix) { - if (hasPolys) { - tessGeo.applyMatrixOnPolyGeometry(matrix, - firstPolyVertex, lastPolyVertex); - root.setModifiedPolyVertices(firstPolyVertex, lastPolyVertex); - root.setModifiedPolyNormals(firstPolyVertex, lastPolyVertex); - for (VertexAttribute attrib: polyAttribs.values()) { - if (attrib.isPosition() || attrib.isNormal()) { - root.setModifiedPolyAttrib(attrib, firstPolyVertex, lastPolyVertex); - } - } - } - - if (is3D()) { - if (hasLines) { - tessGeo.applyMatrixOnLineGeometry(matrix, - firstLineVertex, lastLineVertex); - root.setModifiedLineVertices(firstLineVertex, lastLineVertex); - root.setModifiedLineAttributes(firstLineVertex, lastLineVertex); - } - - if (hasPoints) { - tessGeo.applyMatrixOnPointGeometry(matrix, - firstPointVertex, lastPointVertex); - root.setModifiedPointVertices(firstPointVertex, lastPointVertex); - root.setModifiedPointAttributes(firstPointVertex, lastPointVertex); - } - } - } - - - @Override - protected void checkMatrix(int dimensions) { - if (matrix == null) { - if (dimensions == 2) { - matrix = new PMatrix2D(); - matrixInv = new PMatrix2D(); - } else { - matrix = new PMatrix3D(); - matrixInv = new PMatrix3D(); - } - } else if (dimensions == 3 && (matrix instanceof PMatrix2D)) { - matrix = new PMatrix3D(matrix); - matrixInv = new PMatrix3D(matrixInv); - } - } - - - /////////////////////////////////////////////////////////// - - // - - // Bezier curves - - - @Override - public void bezierDetail(int detail) { - bezierDetail = detail; - if (0 < inGeo.codeCount) { - markForTessellation(); - } - //pg.bezierDetail(detail); // setting the detail in the renderer, WTF?? - } - - - @Override - public void bezierVertex(float x2, float y2, - float x3, float y3, - float x4, float y4) { - bezierVertexImpl(x2, y2, 0, - x3, y3, 0, - x4, y4, 0); - } - - - @Override - public void bezierVertex(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - bezierVertexImpl(x2, y2, z2, - x3, y3, z3, - x4, y4, z4); - } - - - protected void bezierVertexImpl(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addBezierVertex(x2, y2, z2, - x3, y3, z3, - x4, y4, z4, vertexBreak()); - } - - - @Override - public void quadraticVertex(float cx, float cy, - float x3, float y3) { - quadraticVertexImpl(cx, cy, 0, - x3, y3, 0); - } - - - @Override - public void quadraticVertex(float cx, float cy, float cz, - float x3, float y3, float z3) { - quadraticVertexImpl(cx, cy, cz, - x3, y3, z3); - } - - - protected void quadraticVertexImpl(float cx, float cy, float cz, - float x3, float y3, float z3) { - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addQuadraticVertex(cx, cy, cz, - x3, y3, z3, vertexBreak()); - } - - - /////////////////////////////////////////////////////////// - - // - - // Catmull-Rom curves - - - @Override - public void curveDetail(int detail) { - curveDetail = detail; -// pg.curveDetail(detail); - if (0 < inGeo.codeCount) { - markForTessellation(); - } - } - - - @Override - public void curveTightness(float tightness) { - curveTightness = tightness; -// pg.curveTightness(tightness); - if (0 < inGeo.codeCount) { - markForTessellation(); - } - } - - - @Override - public void curveVertex(float x, float y) { - curveVertexImpl(x, y, 0); - } - - - @Override - public void curveVertex(float x, float y, float z) { - curveVertexImpl(x, y, z); - } - - - protected void curveVertexImpl(float x, float y, float z) { - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addCurveVertex(x, y, z, vertexBreak()); - } - - - /////////////////////////////////////////////////////////// - - // - - // Setters/getters of individual vertices - - - @Override - public int getVertexCount() { - if (family == GROUP) return 0; // Group shapes don't have vertices - else { - if (family == PRIMITIVE || family == PATH) { - // the input geometry of primitive and path shapes is built during - // tessellation - updateTessellation(); - } - return inGeo.vertexCount; - } - } - - - @Override - public PVector getVertex(int index, PVector vec) { - if (vec == null) { - vec = new PVector(); - } - vec.x = inGeo.vertices[3 * index + 0]; - vec.y = inGeo.vertices[3 * index + 1]; - vec.z = inGeo.vertices[3 * index + 2]; - return vec; - } - - - @Override - public float getVertexX(int index) { - return inGeo.vertices[3 * index + 0]; - } - - - @Override - public float getVertexY(int index) { - return inGeo.vertices[3 * index + 1]; - } - - - @Override - public float getVertexZ(int index) { - return inGeo.vertices[3 * index + 2]; - } - - - @Override - public void setVertex(int index, float x, float y) { - setVertex(index, x, y, 0); - } - - - @Override - public void setVertex(int index, float x, float y, float z) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setVertex()"); - return; - } - - // TODO: in certain cases (kind = TRIANGLE, etc) the correspondence between - // input and tessellated vertices is 1-1, so in those cases re-tessellation - // wouldn't be necessary. But in order to reasonable take care of that - // situation, we would need a complete rethinking of the rendering architecture - // in Processing :-) - if (family == PATH) { - if (vertexCodes != null && vertexCodeCount > 0 && - vertexCodes[index] != VERTEX) { - PGraphics.showWarning(NOT_A_SIMPLE_VERTEX, "setVertex()"); - return; - } - vertices[index][X] = x; - vertices[index][Y] = y; - if (is3D && vertices[index].length > 2) { - // P3D allows to modify 2D shapes, ignoring the Z coordinate. - vertices[index][Z] = z; - } - } else { - inGeo.vertices[3 * index + 0] = x; - inGeo.vertices[3 * index + 1] = y; - inGeo.vertices[3 * index + 2] = z; - } - markForTessellation(); - } - - - @Override - public void setVertex(int index, PVector vec) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setVertex()"); - return; - } - - if (family == PATH) { - if (vertexCodes != null && vertexCodeCount > 0 && - vertexCodes[index] != VERTEX) { - PGraphics.showWarning(NOT_A_SIMPLE_VERTEX, "setVertex()"); - return; - } - vertices[index][X] = vec.x; - vertices[index][Y] = vec.y; - if (is3D && vertices[index].length > 2) { - vertices[index][Z] = vec.z; - } - } else { - inGeo.vertices[3 * index + 0] = vec.x; - inGeo.vertices[3 * index + 1] = vec.y; - inGeo.vertices[3 * index + 2] = vec.z; - } - markForTessellation(); - } - - - @Override - public PVector getNormal(int index, PVector vec) { - if (vec == null) { - vec = new PVector(); - } - vec.x = inGeo.normals[3 * index + 0]; - vec.y = inGeo.normals[3 * index + 1]; - vec.z = inGeo.normals[3 * index + 2]; - return vec; - } - - - @Override - public float getNormalX(int index) { - return inGeo.normals[3 * index + 0]; - } - - - @Override - public float getNormalY(int index) { - return inGeo.normals[3 * index + 1]; - } - - - @Override - public float getNormalZ(int index) { - return inGeo.normals[3 * index + 2]; - } - - - @Override - public void setNormal(int index, float nx, float ny, float nz) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setNormal()"); - return; - } - - inGeo.normals[3 * index + 0] = nx; - inGeo.normals[3 * index + 1] = ny; - inGeo.normals[3 * index + 2] = nz; - markForTessellation(); - } - - - @Override - public void setAttrib(String name, int index, float... values) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setNormal()"); - return; - } - - VertexAttribute attrib = attribImpl(name, VertexAttribute.OTHER, PGL.FLOAT, - values.length); - float[] array = inGeo.fattribs.get(name); - for (int i = 0; i < values.length; i++) { - array[attrib.size * index + i] = values[i]; - } - markForTessellation(); - } - - - @Override - public void setAttrib(String name, int index, int... values) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setNormal()"); - return; - } - - VertexAttribute attrib = attribImpl(name, VertexAttribute.OTHER, PGL.INT, - values.length); - int[] array = inGeo.iattribs.get(name); - for (int i = 0; i < values.length; i++) { - array[attrib.size * index + i] = values[i]; - } - markForTessellation(); - } - - - @Override - public void setAttrib(String name, int index, boolean... values) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setNormal()"); - return; - } - - VertexAttribute attrib = attribImpl(name, VertexAttribute.OTHER, PGL.BOOL, - values.length); - byte[] array = inGeo.battribs.get(name); - for (int i = 0; i < values.length; i++) { - array[attrib.size * index + i] = (byte)(values[i]?1:0); - } - markForTessellation(); - } - - - @Override - public float getTextureU(int index) { - return inGeo.texcoords[2 * index + 0]; - } - - - @Override - public float getTextureV(int index) { - return inGeo.texcoords[2 * index + 1]; - } - - - @Override - public void setTextureUV(int index, float u, float v) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTextureUV()"); - return; - } - - if (textureMode == IMAGE && image != null) { - u /= image.width; - v /= image.height; - } - inGeo.texcoords[2 * index + 0] = u; - inGeo.texcoords[2 * index + 1] = v; - - markForTessellation(); - } - - - @Override - public int getFill(int index) { - if (family != GROUP && image == null) { - return PGL.nativeToJavaARGB(inGeo.colors[index]); - } else { - return 0; - } - } - - - @Override - public void setFill(boolean fill) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setFill()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setFill(fill); - } - } else if (this.fill != fill) { - markForTessellation(); - } - this.fill = fill; - } - - - @Override - public void setFill(int fill) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setFill()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setFill(fill); - } - } else { - setFillImpl(fill); - } - } - - - protected void setFillImpl(int fill) { - if (fillColor == fill) return; - fillColor = fill; - - if (image == null) { - Arrays.fill(inGeo.colors, 0, inGeo.vertexCount, - PGL.javaToNativeARGB(fillColor)); - if (shapeCreated && tessellated && hasPolys) { - if (is3D()) { - Arrays.fill(tessGeo.polyColors, firstPolyVertex, lastPolyVertex + 1, - PGL.javaToNativeARGB(fillColor)); - root.setModifiedPolyColors(firstPolyVertex, lastPolyVertex); - } else if (is2D()) { - int last1 = lastPolyVertex + 1; - if (-1 < firstLineVertex) last1 = firstLineVertex; - if (-1 < firstPointVertex) last1 = firstPointVertex; - Arrays.fill(tessGeo.polyColors, firstPolyVertex, last1, - PGL.javaToNativeARGB(fillColor)); - root.setModifiedPolyColors(firstPolyVertex, last1 - 1); - } - } - } - - if (!setAmbient) { - // Setting the ambient color from the current fill - // is what the old P3D did and allows to have an - // default ambient color when the user doesn't specify - // it explicitly. - setAmbientImpl(fill); - setAmbient = false; - } - } - - - @Override - public void setFill(int index, int fill) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setFill()"); - return; - } - - if (image == null) { - inGeo.colors[index] = PGL.javaToNativeARGB(fill); - markForTessellation(); - } - } - - - @Override - public int getTint(int index) { - if (family != GROUP && image != null) { - return PGL.nativeToJavaARGB(inGeo.colors[index]); - } else { - return 0; - } - } - - - @Override - public void setTint(boolean tint) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTint()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setTint(fill); - } - } else if (this.tint && !tint) { - setTintImpl(0xFFFFFFFF); - } - this.tint = tint; - } - - - @Override - public void setTint(int tint) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTint()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setTint(tint); - } - } else { - setTintImpl(tint); - } - } - - - protected void setTintImpl(int tint) { - if (tintColor == tint) return; - tintColor = tint; - - if (image != null) { - Arrays.fill(inGeo.colors, 0, inGeo.vertexCount, - PGL.javaToNativeARGB(tintColor)); - if (shapeCreated && tessellated && hasPolys) { - if (is3D()) { - Arrays.fill(tessGeo.polyColors, firstPolyVertex, lastPolyVertex + 1, - PGL.javaToNativeARGB(tintColor)); - root.setModifiedPolyColors(firstPolyVertex, lastPolyVertex); - } else if (is2D()) { - int last1 = lastPolyVertex + 1; - if (-1 < firstLineVertex) last1 = firstLineVertex; - if (-1 < firstPointVertex) last1 = firstPointVertex; - Arrays.fill(tessGeo.polyColors, firstPolyVertex, last1, - PGL.javaToNativeARGB(tintColor)); - root.setModifiedPolyColors(firstPolyVertex, last1 - 1); - } - } - } - } - - - @Override - public void setTint(int index, int tint) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setTint()"); - return; - } - - if (image != null) { - inGeo.colors[index] = PGL.javaToNativeARGB(tint); - markForTessellation(); - } - } - - - @Override - public int getStroke(int index) { - if (family != GROUP) { - return PGL.nativeToJavaARGB(inGeo.strokeColors[index]); - } else { - return 0; - } - } - - - @Override - public void setStroke(boolean stroke) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStroke()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setStroke(stroke); - } - this.stroke = stroke; - } else { - setStrokeImpl(stroke); - } - } - - - protected void setStrokeImpl(boolean stroke) { - if (this.stroke != stroke) { - if (stroke) { - // Before there was no stroke, now there is stroke, so current stroke - // color should be copied to the input geometry, and geometry should - // be marked as modified in case it needs to be re-tessellated. - int color = strokeColor; - strokeColor += 1; // Forces a color change - setStrokeImpl(color); - } - - markForTessellation(); - if (is2D() && parent != null) { - ((PShapeOpenGL)parent).strokedTexture(stroke && image != null); - } - - this.stroke = stroke; - } - } - - - @Override - public void setStroke(int stroke) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStroke()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setStroke(stroke); - } - } else { - setStrokeImpl(stroke); - } - } - - - protected void setStrokeImpl(int stroke) { - if (strokeColor == stroke) return; - strokeColor = stroke; - - Arrays.fill(inGeo.strokeColors, 0, inGeo.vertexCount, - PGL.javaToNativeARGB(strokeColor)); - if (shapeCreated && tessellated && (hasLines || hasPoints)) { - if (hasLines) { - if (is3D()) { - Arrays.fill(tessGeo.lineColors, firstLineVertex, lastLineVertex + 1, - PGL.javaToNativeARGB(strokeColor)); - root.setModifiedLineColors(firstLineVertex, lastLineVertex); - } else if (is2D()) { - Arrays.fill(tessGeo.polyColors, firstLineVertex, lastLineVertex + 1, - PGL.javaToNativeARGB(strokeColor)); - root.setModifiedPolyColors(firstLineVertex, lastLineVertex); - } - } - if (hasPoints) { - if (is3D()) { - Arrays.fill(tessGeo.pointColors, firstPointVertex, lastPointVertex + 1, - PGL.javaToNativeARGB(strokeColor)); - root.setModifiedPointColors(firstPointVertex, lastPointVertex); - } else if (is2D()) { - Arrays.fill(tessGeo.polyColors, firstPointVertex, lastPointVertex + 1, - PGL.javaToNativeARGB(strokeColor)); - root.setModifiedPolyColors(firstPointVertex, lastPointVertex); - } - } - } - } - - - @Override - public void setStroke(int index, int stroke) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStroke()"); - return; - } - - inGeo.strokeColors[index] = PGL.javaToNativeARGB(stroke); - markForTessellation(); - } - - - @Override - public float getStrokeWeight(int index) { - if (family != GROUP) { - return inGeo.strokeWeights[index]; - } else { - return 0; - } - } - - - @Override - public void setStrokeWeight(float weight) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStrokeWeight()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setStrokeWeight(weight); - } - } else { - setStrokeWeightImpl(weight); - } - } - - - protected void setStrokeWeightImpl(float weight) { - if (PGraphicsOpenGL.same(strokeWeight, weight)) return; - float oldWeight = strokeWeight; - strokeWeight = weight; - - Arrays.fill(inGeo.strokeWeights, 0, inGeo.vertexCount, strokeWeight); - if (shapeCreated && tessellated && (hasLines || hasPoints)) { - float resizeFactor = weight / oldWeight; - if (hasLines) { - if (is3D()) { - for (int i = firstLineVertex; i <= lastLineVertex; i++) { - tessGeo.lineDirections[4 * i + 3] *= resizeFactor; - } - root.setModifiedLineAttributes(firstLineVertex, lastLineVertex); - } else if (is2D()) { - // Changing the stroke weight on a 2D shape needs a - // re-tessellation in order to replace the old line - // geometry. - markForTessellation(); - } - } - if (hasPoints) { - if (is3D()) { - for (int i = firstPointVertex; i <= lastPointVertex; i++) { - tessGeo.pointOffsets[2 * i + 0] *= resizeFactor; - tessGeo.pointOffsets[2 * i + 1] *= resizeFactor; - } - root.setModifiedPointAttributes(firstPointVertex, lastPointVertex); - } else if (is2D()) { - // Changing the stroke weight on a 2D shape needs a - // re-tessellation in order to replace the old point - // geometry. - markForTessellation(); - } - } - } - } - - - @Override - public void setStrokeWeight(int index, float weight) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStrokeWeight()"); - return; - } - - inGeo.strokeWeights[index] = weight; - markForTessellation(); - } - - - @Override - public void setStrokeJoin(int join) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStrokeJoin()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setStrokeJoin(join); - } - } else { - if (is2D() && strokeJoin != join) { - // Changing the stroke join on a 2D shape needs a - // re-tessellation in order to replace the old join - // geometry. - markForTessellation(); - } - strokeJoin = join; - } - } - - - @Override - public void setStrokeCap(int cap) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setStrokeCap()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setStrokeCap(cap); - } - } else { - if (is2D() && strokeCap != cap) { - // Changing the stroke cap on a 2D shape needs a - // re-tessellation in order to replace the old cap - // geometry. - markForTessellation(); - } - strokeCap = cap; - } - } - - - @Override - public int getAmbient(int index) { - if (family != GROUP) { - return PGL.nativeToJavaARGB(inGeo.ambient[index]); - } else { - return 0; - } - } - - - @Override - public void setAmbient(int ambient) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setAmbient()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setAmbient(ambient); - } - } else { - setAmbientImpl(ambient); - } - } - - - protected void setAmbientImpl(int ambient) { - if (ambientColor == ambient) return; - ambientColor = ambient; - - Arrays.fill(inGeo.ambient, 0, inGeo.vertexCount, - PGL.javaToNativeARGB(ambientColor)); - if (shapeCreated && tessellated && hasPolys) { - if (is3D()) { - Arrays.fill(tessGeo.polyAmbient, firstPolyVertex, lastPolyVertex + 1, - PGL.javaToNativeARGB(ambientColor)); - root.setModifiedPolyAmbient(firstPolyVertex, lastPolyVertex); - } else if (is2D()) { - int last1 = lastPolyVertex + 1; - if (-1 < firstLineVertex) last1 = firstLineVertex; - if (-1 < firstPointVertex) last1 = firstPointVertex; - Arrays.fill(tessGeo.polyAmbient, firstPolyVertex, last1, - PGL.javaToNativeARGB(ambientColor)); - root.setModifiedPolyColors(firstPolyVertex, last1 - 1); - } - } - setAmbient = true; - } - - - @Override - public void setAmbient(int index, int ambient) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setAmbient()"); - return; - } - - inGeo.ambient[index] = PGL.javaToNativeARGB(ambient); - markForTessellation(); - setAmbient = true; - } - - - @Override - public int getSpecular(int index) { - if (family == GROUP) { - return PGL.nativeToJavaARGB(inGeo.specular[index]); - } else { - return 0; - } - } - - - @Override - public void setSpecular(int specular) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setSpecular()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setSpecular(specular); - } - } else { - setSpecularImpl(specular); - } - } - - - protected void setSpecularImpl(int specular) { - if (specularColor == specular) return; - specularColor = specular; - - Arrays.fill(inGeo.specular, 0, inGeo.vertexCount, - PGL.javaToNativeARGB(specularColor)); - if (shapeCreated && tessellated && hasPolys) { - if (is3D()) { - Arrays.fill(tessGeo.polySpecular, firstPolyVertex, lastPolyVertex + 1, - PGL.javaToNativeARGB(specularColor)); - root.setModifiedPolySpecular(firstPolyVertex, lastPolyVertex); - } else if (is2D()) { - int last1 = lastPolyVertex + 1; - if (-1 < firstLineVertex) last1 = firstLineVertex; - if (-1 < firstPointVertex) last1 = firstPointVertex; - Arrays.fill(tessGeo.polySpecular, firstPolyVertex, last1, - PGL.javaToNativeARGB(specularColor)); - root.setModifiedPolyColors(firstPolyVertex, last1 - 1); - } - } - } - - - @Override - public void setSpecular(int index, int specular) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setSpecular()"); - return; - } - - inGeo.specular[index] = PGL.javaToNativeARGB(specular); - markForTessellation(); - } - - - @Override - public int getEmissive(int index) { - if (family == GROUP) { - return PGL.nativeToJavaARGB(inGeo.emissive[index]); - } else { - return 0; - } - } - - - @Override - public void setEmissive(int emissive) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setEmissive()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setEmissive(emissive); - } - } else { - setEmissiveImpl(emissive); - } - } - - - protected void setEmissiveImpl(int emissive) { - if (emissiveColor == emissive) return; - emissiveColor = emissive; - - Arrays.fill(inGeo.emissive, 0, inGeo.vertexCount, - PGL.javaToNativeARGB(emissiveColor)); - if (shapeCreated && tessellated && 0 < tessGeo.polyVertexCount) { - if (is3D()) { - Arrays.fill(tessGeo.polyEmissive, firstPolyVertex, lastPolyVertex + 1, - PGL.javaToNativeARGB(emissiveColor)); - root.setModifiedPolyEmissive(firstPolyVertex, lastPolyVertex); - } else if (is2D()) { - int last1 = lastPolyVertex + 1; - if (-1 < firstLineVertex) last1 = firstLineVertex; - if (-1 < firstPointVertex) last1 = firstPointVertex; - Arrays.fill(tessGeo.polyEmissive, firstPolyVertex, last1, - PGL.javaToNativeARGB(emissiveColor)); - root.setModifiedPolyColors(firstPolyVertex, last1 - 1); - } - } - } - - - @Override - public void setEmissive(int index, int emissive) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setEmissive()"); - return; - } - - inGeo.emissive[index] = PGL.javaToNativeARGB(emissive); - markForTessellation(); - } - - - @Override - public float getShininess(int index) { - if (family == GROUP) { - return inGeo.shininess[index]; - } else { - return 0; - } - } - - - @Override - public void setShininess(float shininess) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setShininess()"); - return; - } - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.setShininess(shininess); - } - } else { - setShininessImpl(shininess); - } - } - - - protected void setShininessImpl(float shininess) { - if (PGraphicsOpenGL.same(this.shininess, shininess)) return; - this.shininess = shininess; - - Arrays.fill(inGeo.shininess, 0, inGeo.vertexCount, shininess); - if (shapeCreated && tessellated && hasPolys) { - if (is3D()) { - Arrays.fill(tessGeo.polyShininess, firstPolyVertex, lastPolyVertex + 1, - shininess); - root.setModifiedPolyShininess(firstPolyVertex, lastPolyVertex); - } else if (is2D()) { - int last1 = lastPolyVertex + 1; - if (-1 < firstLineVertex) last1 = firstLineVertex; - if (-1 < firstPointVertex) last1 = firstPointVertex; - Arrays.fill(tessGeo.polyShininess, firstPolyVertex, last1, shininess); - root.setModifiedPolyColors(firstPolyVertex, last1 - 1); - } - } - } - - - @Override - public void setShininess(int index, float shine) { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "setShininess()"); - return; - } - - inGeo.shininess[index] = shine; - markForTessellation(); - } - - /////////////////////////////////////////////////////////// - - // - - // Vertex codes - - - @Override - public int[] getVertexCodes() { - if (family == GROUP) return null; - else { - if (family == PRIMITIVE || family == PATH) { - // the input geometry of primitive and path shapes is built during - // tessellation - updateTessellation(); - } - if (inGeo.codes == null) return null; - return inGeo.codes; - } - } - - - @Override - public int getVertexCodeCount() { - if (family == GROUP) return 0; - else { - if (family == PRIMITIVE || family == PATH) { - // the input geometry of primitive and path shapes is built during - // tessellation - updateTessellation(); - } - return inGeo.codeCount; - } - } - - - /** - * One of VERTEX, BEZIER_VERTEX, CURVE_VERTEX, or BREAK. - */ - @Override - public int getVertexCode(int index) { - return inGeo.codes[index]; - } - - - /////////////////////////////////////////////////////////// - - // - - // Tessellated geometry getter. - - - @Override - public PShape getTessellation() { - updateTessellation(); - - float[] vertices = tessGeo.polyVertices; - float[] normals = tessGeo.polyNormals; - int[] color = tessGeo.polyColors; - float[] uv = tessGeo.polyTexCoords; - short[] indices = tessGeo.polyIndices; - - PShape tess; -// if (is3D()) { -// //tess = PGraphics3D.createShapeImpl(pg, PShape.GEOMETRY); -// tess = pg.createShapeFamily(PShape.GEOMETRY); -// } else if (is2D()) { -// //tess = PGraphics2D.createShapeImpl(pg, PShape.GEOMETRY); -// tess = pg.createShapeFamily(PShape.GEOMETRY); -// } else { -// PGraphics.showWarning("This shape is not either 2D or 3D!"); -// return null; -// } - tess = pg.createShapeFamily(PShape.GEOMETRY); - tess.set3D(is3D); // if this is a 3D shape, make the new shape 3D as well - tess.beginShape(TRIANGLES); - tess.noStroke(); - - IndexCache cache = tessGeo.polyIndexCache; - for (int n = firstPolyIndexCache; n <= lastPolyIndexCache; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int voffset = cache.vertexOffset[n]; - - for (int tr = ioffset / 3; tr < (ioffset + icount) / 3; tr++) { - int i0 = voffset + indices[3 * tr + 0]; - int i1 = voffset + indices[3 * tr + 1]; - int i2 = voffset + indices[3 * tr + 2]; - - if (is3D()) { - float x0 = vertices[4 * i0 + 0]; - float y0 = vertices[4 * i0 + 1]; - float z0 = vertices[4 * i0 + 2]; - float x1 = vertices[4 * i1 + 0]; - float y1 = vertices[4 * i1 + 1]; - float z1 = vertices[4 * i1 + 2]; - float x2 = vertices[4 * i2 + 0]; - float y2 = vertices[4 * i2 + 1]; - float z2 = vertices[4 * i2 + 2]; - - float nx0 = normals[3 * i0 + 0]; - float ny0 = normals[3 * i0 + 1]; - float nz0 = normals[3 * i0 + 2]; - float nx1 = normals[3 * i1 + 0]; - float ny1 = normals[3 * i1 + 1]; - float nz1 = normals[3 * i1 + 2]; - float nx2 = normals[3 * i2 + 0]; - float ny2 = normals[3 * i2 + 1]; - float nz2 = normals[3 * i2 + 2]; - - int argb0 = PGL.nativeToJavaARGB(color[i0]); - int argb1 = PGL.nativeToJavaARGB(color[i1]); - int argb2 = PGL.nativeToJavaARGB(color[i2]); - - tess.fill(argb0); - tess.normal(nx0, ny0, nz0); - tess.vertex(x0, y0, z0, uv[2 * i0 + 0], uv[2 * i0 + 1]); - - tess.fill(argb1); - tess.normal(nx1, ny1, nz1); - tess.vertex(x1, y1, z1, uv[2 * i1 + 0], uv[2 * i1 + 1]); - - tess.fill(argb2); - tess.normal(nx2, ny2, nz2); - tess.vertex(x2, y2, z2, uv[2 * i2 + 0], uv[2 * i2 + 1]); - } else if (is2D()) { - float x0 = vertices[4 * i0 + 0], y0 = vertices[4 * i0 + 1]; - float x1 = vertices[4 * i1 + 0], y1 = vertices[4 * i1 + 1]; - float x2 = vertices[4 * i2 + 0], y2 = vertices[4 * i2 + 1]; - - int argb0 = PGL.nativeToJavaARGB(color[i0]); - int argb1 = PGL.nativeToJavaARGB(color[i1]); - int argb2 = PGL.nativeToJavaARGB(color[i2]); - - tess.fill(argb0); - tess.vertex(x0, y0, uv[2 * i0 + 0], uv[2 * i0 + 1]); - - tess.fill(argb1); - tess.vertex(x1, y1, uv[2 * i1 + 0], uv[2 * i1 + 1]); - - tess.fill(argb2); - tess.vertex(x2, y2, uv[2 * i2 + 0], uv[2 * i2 + 1]); - } - } - } - tess.endShape(); - - return tess; - } - - // Testing this method, not use as it might go away... - public float[] getTessellation(int kind, int data) { - updateTessellation(); - - if (kind == TRIANGLES) { - if (data == POSITION) { - if (is3D()) { - root.setModifiedPolyVertices(firstPolyVertex, lastPolyVertex); - } else if (is2D()) { - int last1 = lastPolyVertex + 1; - if (-1 < firstLineVertex) last1 = firstLineVertex; - if (-1 < firstPointVertex) last1 = firstPointVertex; - root.setModifiedPolyVertices(firstPolyVertex, last1 - 1); - } - return tessGeo.polyVertices; - } else if (data == NORMAL) { - if (is3D()) { - root.setModifiedPolyNormals(firstPolyVertex, lastPolyVertex); - } else if (is2D()) { - int last1 = lastPolyVertex + 1; - if (-1 < firstLineVertex) last1 = firstLineVertex; - if (-1 < firstPointVertex) last1 = firstPointVertex; - root.setModifiedPolyNormals(firstPolyVertex, last1 - 1); - } - return tessGeo.polyNormals; - } else if (data == TEXCOORD) { - if (is3D()) { - root.setModifiedPolyTexCoords(firstPolyVertex, lastPolyVertex); - } else if (is2D()) { - int last1 = lastPolyVertex + 1; - if (-1 < firstLineVertex) last1 = firstLineVertex; - if (-1 < firstPointVertex) last1 = firstPointVertex; - root.setModifiedPolyTexCoords(firstPolyVertex, last1 - 1); - } - return tessGeo.polyTexCoords; - } - } else if (kind == LINES) { - if (data == POSITION) { - if (is3D()) { - root.setModifiedLineVertices(firstLineVertex, lastLineVertex); - } else if (is2D()) { - root.setModifiedPolyVertices(firstLineVertex, lastLineVertex); - } - return tessGeo.lineVertices; - } else if (data == DIRECTION) { - if (is2D()) { - root.setModifiedLineAttributes(firstLineVertex, lastLineVertex); - } - return tessGeo.lineDirections; - } - } else if (kind == POINTS) { - if (data == POSITION) { - if (is3D()) { - root.setModifiedPointVertices(firstPointVertex, lastPointVertex); - } else if (is2D()) { - root.setModifiedPolyVertices(firstPointVertex, lastPointVertex); - } - return tessGeo.pointVertices; - } else if (data == OFFSET) { - if (is2D()) { - root.setModifiedPointAttributes(firstPointVertex, lastPointVertex); - } - return tessGeo.pointOffsets; - } - } - return null; - } - - /////////////////////////////////////////////////////////// - - // - - // Geometry utils - - // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html - @Override - public boolean contains(float x, float y) { - if (family == PATH) { - boolean c = false; - for (int i = 0, j = inGeo.vertexCount-1; i < inGeo.vertexCount; j = i++) { - if (((inGeo.vertices[3 * i + 1] > y) != (inGeo.vertices[3 * j + 1] > y)) && - (x < - (inGeo.vertices[3 * j]-inGeo.vertices[3 * i]) * - (y-inGeo.vertices[3 * i + 1]) / - (inGeo.vertices[3 * j + 1]-inGeo.vertices[3 * i + 1]) + - inGeo.vertices[3 * i])) { - c = !c; - } - } - return c; - } else { - throw new IllegalArgumentException("The contains() method is only implemented for paths."); - } - } - - - /////////////////////////////////////////////////////////// - - // - - // Tessellation - - - protected void updateTessellation() { - if (!root.tessellated) { - root.tessellate(); - root.aggregate(); - root.initModified(); - root.needBufferInit = true; - } - } - - - protected void markForTessellation() { - root.tessellated = false; - tessellated = false; - } - - - protected void initModified() { - modified = false; - - modifiedPolyVertices = false; - modifiedPolyColors = false; - modifiedPolyNormals = false; - modifiedPolyTexCoords = false; - modifiedPolyAmbient = false; - modifiedPolySpecular = false; - modifiedPolyEmissive = false; - modifiedPolyShininess = false; - - modifiedLineVertices = false; - modifiedLineColors = false; - modifiedLineAttributes = false; - - modifiedPointVertices = false; - modifiedPointColors = false; - modifiedPointAttributes = false; - - firstModifiedPolyVertex = PConstants.MAX_INT; - lastModifiedPolyVertex = PConstants.MIN_INT; - firstModifiedPolyColor = PConstants.MAX_INT; - lastModifiedPolyColor = PConstants.MIN_INT; - firstModifiedPolyNormal = PConstants.MAX_INT; - lastModifiedPolyNormal = PConstants.MIN_INT; - firstModifiedPolyTexcoord = PConstants.MAX_INT; - lastModifiedPolyTexcoord = PConstants.MIN_INT; - firstModifiedPolyAmbient = PConstants.MAX_INT; - lastModifiedPolyAmbient = PConstants.MIN_INT; - firstModifiedPolySpecular = PConstants.MAX_INT; - lastModifiedPolySpecular = PConstants.MIN_INT; - firstModifiedPolyEmissive = PConstants.MAX_INT; - lastModifiedPolyEmissive = PConstants.MIN_INT; - firstModifiedPolyShininess = PConstants.MAX_INT; - lastModifiedPolyShininess = PConstants.MIN_INT; - - firstModifiedLineVertex = PConstants.MAX_INT; - lastModifiedLineVertex = PConstants.MIN_INT; - firstModifiedLineColor = PConstants.MAX_INT; - lastModifiedLineColor = PConstants.MIN_INT; - firstModifiedLineAttribute = PConstants.MAX_INT; - lastModifiedLineAttribute = PConstants.MIN_INT; - - firstModifiedPointVertex = PConstants.MAX_INT; - lastModifiedPointVertex = PConstants.MIN_INT; - firstModifiedPointColor = PConstants.MAX_INT; - lastModifiedPointColor = PConstants.MIN_INT; - firstModifiedPointAttribute = PConstants.MAX_INT; - lastModifiedPointAttribute = PConstants.MIN_INT; - } - - - protected void tessellate() { - if (root == this && parent == null) { // Root shape - boolean initAttr = false; - if (polyAttribs == null) { - polyAttribs = PGraphicsOpenGL.newAttributeMap(); - initAttr = true; - } - - if (tessGeo == null) { - tessGeo = PGraphicsOpenGL.newTessGeometry(pg, polyAttribs, PGraphicsOpenGL.RETAINED); - } - tessGeo.clear(); - - if (initAttr) { - collectPolyAttribs(); - } - - for (int i = 0; i < polyAttribs.size(); i++) { - VertexAttribute attrib = polyAttribs.get(i); - tessGeo.initAttrib(attrib); - } - - tessellateImpl(); - - // Tessellated arrays are trimmed since they are expanded - // by doubling their old size, which might lead to arrays - // larger than the vertex counts. - tessGeo.trim(); - } - } - - - protected void collectPolyAttribs() { - AttributeMap rootAttribs = root.polyAttribs; - tessGeo = root.tessGeo; - - if (family == GROUP) { - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.collectPolyAttribs(); - } - } else { - for (int i = 0; i < polyAttribs.size(); i++) { - VertexAttribute attrib = polyAttribs.get(i); - tessGeo.initAttrib(attrib); - if (rootAttribs.containsKey(attrib.name)) { - VertexAttribute rattrib = rootAttribs.get(attrib.name); - if (rattrib.diff(attrib)) { - throw new RuntimeException("Children shapes cannot have different attributes with same name"); - } - } else { - rootAttribs.put(attrib.name, attrib); - } - } - } - } - - protected void tessellateImpl() { - tessGeo = root.tessGeo; - - firstPolyIndexCache = -1; - lastPolyIndexCache = -1; - firstLineIndexCache = -1; - lastLineIndexCache = -1; - firstPointIndexCache = -1; - lastPointIndexCache = -1; - - if (family == GROUP) { - if (polyAttribs == null) { - polyAttribs = PGraphicsOpenGL.newAttributeMap(); - collectPolyAttribs(); - } - - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.tessellateImpl(); - } - } else { - if (shapeCreated) { - // If the geometry was tessellated previously, then - // the edges information will still be stored in the - // input object, so it needs to be removed to avoid - // duplication. - inGeo.clearEdges(); - - tessellator.setInGeometry(inGeo); - tessellator.setTessGeometry(tessGeo); - tessellator.setFill(fill || image != null); - tessellator.setTexCache(null, null); - tessellator.setStroke(stroke); - tessellator.setStrokeColor(strokeColor); - tessellator.setStrokeWeight(strokeWeight); - tessellator.setStrokeCap(strokeCap); - tessellator.setStrokeJoin(strokeJoin); - tessellator.setRenderer(pg); - tessellator.setTransform(matrix); - tessellator.set3D(is3D()); - - if (family == GEOMETRY) { - if (kind == POINTS) { - tessellator.tessellatePoints(); - } else if (kind == LINES) { - tessellator.tessellateLines(); - } else if (kind == LINE_STRIP) { - tessellator.tessellateLineStrip(); - } else if (kind == LINE_LOOP) { - tessellator.tessellateLineLoop(); - } else if (kind == TRIANGLE || kind == TRIANGLES) { - if (stroke) inGeo.addTrianglesEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcTrianglesNormals(); - tessellator.tessellateTriangles(); - } else if (kind == TRIANGLE_FAN) { - if (stroke) inGeo.addTriangleFanEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcTriangleFanNormals(); - tessellator.tessellateTriangleFan(); - } else if (kind == TRIANGLE_STRIP) { - if (stroke) inGeo.addTriangleStripEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcTriangleStripNormals(); - tessellator.tessellateTriangleStrip(); - } else if (kind == QUAD || kind == QUADS) { - if (stroke) inGeo.addQuadsEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcQuadsNormals(); - tessellator.tessellateQuads(); - } else if (kind == QUAD_STRIP) { - if (stroke) inGeo.addQuadStripEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcQuadStripNormals(); - tessellator.tessellateQuadStrip(); - } else if (kind == POLYGON) { - boolean bez = inGeo.hasBezierVertex(); - boolean quad = inGeo.hasQuadraticVertex(); - boolean curv = inGeo.hasCurveVertex(); - if (bez || quad) saveBezierVertexSettings(); - if (curv) { - saveCurveVertexSettings(); - tessellator.resetCurveVertexCount(); - } - tessellator.tessellatePolygon(solid, close, - normalMode == NORMAL_MODE_AUTO); - if (bez ||quad) restoreBezierVertexSettings(); - if (curv) restoreCurveVertexSettings(); - } - } else if (family == PRIMITIVE) { - // The input geometry needs to be cleared because the geometry - // generation methods in InGeometry add the vertices of the - // new primitive to what is already stored. - inGeo.clear(); - - if (kind == POINT) { - tessellatePoint(); - } else if (kind == LINE) { - tessellateLine(); - } else if (kind == TRIANGLE) { - tessellateTriangle(); - } else if (kind == QUAD) { - tessellateQuad(); - } else if (kind == RECT) { - tessellateRect(); - } else if (kind == ELLIPSE) { - tessellateEllipse(); - } else if (kind == ARC) { - tessellateArc(); - } else if (kind == BOX) { - tessellateBox(); - } else if (kind == SPHERE) { - tessellateSphere(); - } - } else if (family == PATH) { - inGeo.clear(); - tessellatePath(); - } - - if (image != null && parent != null) { - ((PShapeOpenGL)parent).addTexture(image); - } - - firstPolyIndexCache = tessellator.firstPolyIndexCache; - lastPolyIndexCache = tessellator.lastPolyIndexCache; - firstLineIndexCache = tessellator.firstLineIndexCache; - lastLineIndexCache = tessellator.lastLineIndexCache; - firstPointIndexCache = tessellator.firstPointIndexCache; - lastPointIndexCache = tessellator.lastPointIndexCache; - } - } - - firstPolyVertex = lastPolyVertex = -1; - firstLineVertex = lastLineVertex = -1; - firstPointVertex = lastPointVertex = -1; - - tessellated = true; - } - - - protected void tessellatePoint() { - float x = 0, y = 0, z = 0; - if (params.length == 2) { - x = params[0]; - y = params[1]; - z = 0; - } else if (params.length == 3) { - x = params[0]; - y = params[1]; - z = params[2]; - } - - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addPoint(x, y, z, fill, stroke); - tessellator.tessellatePoints(); - } - - - protected void tessellateLine() { - float x1 = 0, y1 = 0, z1 = 0; - float x2 = 0, y2 = 0, z2 = 0; - if (params.length == 4) { - x1 = params[0]; - y1 = params[1]; - x2 = params[2]; - y2 = params[3]; - } else if (params.length == 6) { - x1 = params[0]; - y1 = params[1]; - z1 = params[2]; - x2 = params[3]; - y2 = params[4]; - z2 = params[5]; - } - - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addLine(x1, y1, z1, - x2, y2, z2, - fill, stroke); - tessellator.tessellateLines(); - } - - - protected void tessellateTriangle() { - float x1 = 0, y1 = 0; - float x2 = 0, y2 = 0; - float x3 = 0, y3 = 0; - if (params.length == 6) { - x1 = params[0]; - y1 = params[1]; - x2 = params[2]; - y2 = params[3]; - x3 = params[4]; - y3 = params[5]; - } - - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addTriangle(x1, y1, 0, - x2, y2, 0, - x3, y3, 0, - fill, stroke); - tessellator.tessellateTriangles(); - } - - - protected void tessellateQuad() { - float x1 = 0, y1 = 0; - float x2 = 0, y2 = 0; - float x3 = 0, y3 = 0; - float x4 = 0, y4 = 0; - if (params.length == 8) { - x1 = params[0]; - y1 = params[1]; - x2 = params[2]; - y2 = params[3]; - x3 = params[4]; - y3 = params[5]; - x4 = params[6]; - y4 = params[7]; - } - - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addQuad(x1, y1, 0, - x2, y2, 0, - x3, y3, 0, - x4, y4, 0, - stroke); - tessellator.tessellateQuads(); - } - - - protected void tessellateRect() { - float a = 0, b = 0, c = 0, d = 0; - float tl = 0, tr = 0, br = 0, bl = 0; - boolean rounded = false; - int mode = rectMode; - - if (params.length == 4 || params.length == 5) { - a = params[0]; - b = params[1]; - c = params[2]; - d = params[3]; - rounded = false; - if (params.length == 5) { - tl = params[4]; - tr = params[4]; - br = params[4]; - bl = params[4]; - rounded = true; - } - } else if (params.length == 8) { - a = params[0]; - b = params[1]; - c = params[2]; - d = params[3]; - tl = params[4]; - tr = params[5]; - br = params[6]; - bl = params[7]; - rounded = true; - } - - float hradius, vradius; - switch (mode) { - case CORNERS: - break; - case CORNER: - c += a; d += b; - break; - case RADIUS: - hradius = c; - vradius = d; - c = a + hradius; - d = b + vradius; - a -= hradius; - b -= vradius; - break; - case CENTER: - hradius = c / 2.0f; - vradius = d / 2.0f; - c = a + hradius; - d = b + vradius; - a -= hradius; - b -= vradius; - } - - if (a > c) { - float temp = a; a = c; c = temp; - } - - if (b > d) { - float temp = b; b = d; d = temp; - } - - float maxRounding = PApplet.min((c - a) / 2, (d - b) / 2); - if (tl > maxRounding) tl = maxRounding; - if (tr > maxRounding) tr = maxRounding; - if (br > maxRounding) br = maxRounding; - if (bl > maxRounding) bl = maxRounding; - - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - if (rounded) { - saveBezierVertexSettings(); - inGeo.addRect(a, b, c, d, tl, tr, br, bl, stroke); - tessellator.tessellatePolygon(true, true, true); - restoreBezierVertexSettings(); - } else { - inGeo.addRect(a, b, c, d, stroke); - tessellator.tessellateQuads(); - } - } - - - protected void tessellateEllipse() { - float a = 0, b = 0, c = 0, d = 0; - int mode = ellipseMode; - - if (4 <= params.length) { - a = params[0]; - b = params[1]; - c = params[2]; - d = params[3]; - } - - float x = a; - float y = b; - float w = c; - float h = d; - - if (mode == CORNERS) { - w = c - a; - h = d - b; - - } else if (mode == RADIUS) { - x = a - c; - y = b - d; - w = c * 2; - h = d * 2; - - } else if (mode == DIAMETER) { - x = a - c/2f; - y = b - d/2f; - } - - if (w < 0) { // undo negative width - x += w; - w = -w; - } - - if (h < 0) { // undo negative height - y += h; - h = -h; - } - - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addEllipse(x, y, w, h, fill, stroke); - tessellator.tessellateTriangleFan(); - } - - - protected void tessellateArc() { - float a = 0, b = 0, c = 0, d = 0; - float start = 0, stop = 0; - int mode = ellipseMode; - int arcMode = 0; - - if (6 <= params.length) { - a = params[0]; - b = params[1]; - c = params[2]; - d = params[3]; - start = params[4]; - stop = params[5]; - if (params.length == 7) { - arcMode = (int)(params[6]); - } - } - - float x = a; - float y = b; - float w = c; - float h = d; - - if (mode == CORNERS) { - w = c - a; - h = d - b; - - } else if (mode == RADIUS) { - x = a - c; - y = b - d; - w = c * 2; - h = d * 2; - - } else if (mode == CENTER) { - x = a - c/2f; - y = b - d/2f; - } - - // make sure the loop will exit before starting while - if (!Float.isInfinite(start) && !Float.isInfinite(stop)) { - // ignore equal and degenerate cases - if (stop > start) { - // make sure that we're starting at a useful point - while (start < 0) { - start += TWO_PI; - stop += TWO_PI; - } - - if (stop - start > TWO_PI) { - // don't change start, it is visible in PIE mode - stop = start + TWO_PI; - } - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); - inGeo.addArc(x, y, w, h, start, stop, fill, stroke, arcMode); - tessellator.tessellateTriangleFan(); - } - } - } - - - protected void tessellateBox() { - float w = 0, h = 0, d = 0; - if (params.length == 1) { - w = h = d = params[0]; - } else if (params.length == 3) { - w = params[0]; - h = params[1]; - d = params[2]; - } - - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - inGeo.addBox(w, h, d, fill, stroke); - tessellator.tessellateQuads(); - } - - - protected void tessellateSphere() { - float r = 0; - int nu = sphereDetailU; - int nv = sphereDetailV; - if (1 <= params.length) { - r = params[0]; - if (params.length == 2) { - nu = nv = (int)params[1]; - } else if (params.length == 3) { - nu = (int)params[1]; - nv = (int)params[2]; - } - } - - if (nu < 3 || nv < 2) { - nu = nv = 30; - } - int savedDetailU = pg.sphereDetailU; - int savedDetailV = pg.sphereDetailV; - if (pg.sphereDetailU != nu || pg.sphereDetailV != nv) { - pg.sphereDetail(nu, nv); - } - - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - int[] indices = inGeo.addSphere(r, nu, nv, fill, stroke); - tessellator.tessellateTriangles(indices); - - if ((0 < savedDetailU && savedDetailU != nu) || - (0 < savedDetailV && savedDetailV != nv)) { - pg.sphereDetail(savedDetailU, savedDetailV); - } - } - - - protected void tessellatePath() { - if (vertices == null) return; - - inGeo.setMaterial(fillColor, strokeColor, strokeWeight, - ambientColor, specularColor, emissiveColor, shininess); - - if (vertexCodeCount == 0) { // each point is a simple vertex - if (vertices[0].length == 2) { // tessellating 2D vertices - for (int i = 0; i < vertexCount; i++) { - inGeo.addVertex(vertices[i][X], vertices[i][Y], VERTEX, false); - } - } else { // drawing 3D vertices - for (int i = 0; i < vertexCount; i++) { - inGeo.addVertex(vertices[i][X], vertices[i][Y], vertices[i][Z], - VERTEX, false); - } - } - } else { // coded set of vertices - int idx = 0; - boolean brk = true; - - if (vertices[0].length == 2) { // tessellating a 2D path - - for (int j = 0; j < vertexCodeCount; j++) { - switch (vertexCodes[j]) { - - case VERTEX: - inGeo.addVertex(vertices[idx][X], vertices[idx][Y], VERTEX, brk); - brk = false; - idx++; - break; - - case QUADRATIC_VERTEX: - inGeo.addQuadraticVertex(vertices[idx+0][X], vertices[idx+0][Y], 0, - vertices[idx+1][X], vertices[idx+1][Y], 0, - brk); - brk = false; - idx += 2; - break; - - case BEZIER_VERTEX: - inGeo.addBezierVertex(vertices[idx+0][X], vertices[idx+0][Y], 0, - vertices[idx+1][X], vertices[idx+1][Y], 0, - vertices[idx+2][X], vertices[idx+2][Y], 0, - brk); - brk = false; - idx += 3; - break; - - case CURVE_VERTEX: - inGeo.addCurveVertex(vertices[idx][X], vertices[idx][Y], 0, brk); - brk = false; - idx++; - break; - - case BREAK: - brk = true; - } - } - } else { // tessellating a 3D path - for (int j = 0; j < vertexCodeCount; j++) { - switch (vertexCodes[j]) { - - case VERTEX: - inGeo.addVertex(vertices[idx][X], vertices[idx][Y], - vertices[idx][Z], brk); - brk = false; - idx++; - break; - - case QUADRATIC_VERTEX: - inGeo.addQuadraticVertex(vertices[idx+0][X], - vertices[idx+0][Y], - vertices[idx+0][Z], - vertices[idx+1][X], - vertices[idx+1][Y], - vertices[idx+0][Z], - brk); - brk = false; - idx += 2; - break; - - case BEZIER_VERTEX: - inGeo.addBezierVertex(vertices[idx+0][X], - vertices[idx+0][Y], - vertices[idx+0][Z], - vertices[idx+1][X], - vertices[idx+1][Y], - vertices[idx+1][Z], - vertices[idx+2][X], - vertices[idx+2][Y], - vertices[idx+2][Z], - brk); - brk = false; - idx += 3; - break; - - case CURVE_VERTEX: - inGeo.addCurveVertex(vertices[idx][X], - vertices[idx][Y], - vertices[idx][Z], - brk); - brk = false; - idx++; - break; - - case BREAK: - brk = true; - } - } - } - } - - boolean bez = inGeo.hasBezierVertex(); - boolean quad = inGeo.hasQuadraticVertex(); - boolean curv = inGeo.hasCurveVertex(); - if (bez || quad) saveBezierVertexSettings(); - if (curv) { - saveCurveVertexSettings(); - tessellator.resetCurveVertexCount(); - } - tessellator.tessellatePolygon(true, close, true); - if (bez || quad) restoreBezierVertexSettings(); - if (curv) restoreCurveVertexSettings(); - } - - protected void saveBezierVertexSettings() { - savedBezierDetail = pg.bezierDetail; - if (pg.bezierDetail != bezierDetail) { - pg.bezierDetail(bezierDetail); - } - } - - protected void restoreBezierVertexSettings() { - if (savedBezierDetail != bezierDetail) { - pg.bezierDetail(savedBezierDetail); - } - } - - protected void saveCurveVertexSettings() { - savedCurveDetail = pg.curveDetail; - savedCurveTightness = pg.curveTightness; - if (pg.curveDetail != curveDetail) { - pg.curveDetail(curveDetail); - } - if (pg.curveTightness != curveTightness) { - pg.curveTightness(curveTightness); - } - } - - protected void restoreCurveVertexSettings() { - if (savedCurveDetail != curveDetail) { - pg.curveDetail(savedCurveDetail); - } - if (savedCurveTightness != curveTightness) { - pg.curveTightness(savedCurveTightness); - } - } - - /////////////////////////////////////////////////////////// - - // - - // Aggregation - - - protected void aggregate() { - if (root == this && parent == null) { - // Initializing auxiliary variables in root node - // needed for aggregation. - polyIndexOffset = 0; - polyVertexOffset = 0; - polyVertexAbs = 0; - polyVertexRel = 0; - - lineIndexOffset = 0; - lineVertexOffset = 0; - lineVertexAbs = 0; - lineVertexRel = 0; - - pointIndexOffset = 0; - pointVertexOffset = 0; - pointVertexAbs = 0; - pointVertexRel = 0; - - // Recursive aggregation. - aggregateImpl(); - } - } - - - // This method is very important, as it is responsible of generating the - // correct vertex and index offsets for each level of the shape hierarchy. - // This is the core of the recursive algorithm that calculates the indices - // for the vertices accumulated in a single VBO. - // Basically, the algorithm traverses all the shapes in the hierarchy and - // updates the index cache for each child shape holding geometry (those being - // the leaf nodes in the hierarchy tree), and creates index caches for the - // group shapes so that the draw() method can be called from any shape in the - // hierarchy and the correct piece of geometry will be rendered. - // - // For example, in the following hierarchy: - // - // ROOT GROUP - // | - // /-----------------0-----------------\ - // | | - // CHILD GROUP 0 CHILD GROUP 1 - // | | - // | /---------------0-----------------\ - // | | | | - // GEO SHAPE 0 GEO SHAPE 0 GEO SHAPE 1 GEO SHAPE 2 - // 4 vertices 5 vertices 6 vertices 3 vertices - // - // calling draw() from the root group should result in all the - // vertices (4 + 5 + 6 + 3 = 18) being rendered, while calling - // draw() from either child groups 0 or 1 should result in the first - // 4 vertices or the last 14 vertices being rendered, respectively. - protected void aggregateImpl() { - if (family == GROUP) { - // Recursively aggregating the child shapes. - hasPolys = false; - hasLines = false; - hasPoints = false; - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - child.aggregateImpl(); - hasPolys |= child.hasPolys; - hasLines |= child.hasLines; - hasPoints |= child.hasPoints; - } - } else { // LEAF SHAPE (family either GEOMETRY, PATH or PRIMITIVE) - hasPolys = -1 < firstPolyIndexCache && -1 < lastPolyIndexCache; - hasLines = -1 < firstLineIndexCache && -1 < lastLineIndexCache; - hasPoints = -1 < firstPointIndexCache && -1 < lastPointIndexCache; - } - - if (hasPolys) { - updatePolyIndexCache(); - } - if (is3D()) { - if (hasLines) updateLineIndexCache(); - if (hasPoints) updatePointIndexCache(); - } - - if (matrix != null) { - // Some geometric transformations were applied on - // this shape before tessellation, so they are applied now. - if (hasPolys) { - tessGeo.applyMatrixOnPolyGeometry(matrix, - firstPolyVertex, lastPolyVertex); - } - if (is3D()) { - if (hasLines) { - tessGeo.applyMatrixOnLineGeometry(matrix, - firstLineVertex, lastLineVertex); - } - if (hasPoints) { - tessGeo.applyMatrixOnPointGeometry(matrix, - firstPointVertex, lastPointVertex); - } - } - } - } - - - // Updates the index cache for the range that corresponds to this shape. - protected void updatePolyIndexCache() { - IndexCache cache = tessGeo.polyIndexCache; - if (family == GROUP) { - // Updates the index cache to include the elements corresponding to - // a group shape, using the cache entries of the child shapes. The - // index cache has a pyramidal structure where the base is formed - // by the entries corresponding to the leaf (geometry) shapes, and - // each subsequent level is determined by the higher-level group shapes - // The index pyramid is flattened into arrays in order to use simple - // data structures, so each shape needs to store the positions in the - // cache that corresponds to itself. - - // The index ranges of the child shapes that share the vertex offset - // are unified into a single range in the parent level. - - firstPolyIndexCache = lastPolyIndexCache = -1; - int gindex = -1; - - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - - int first = child.firstPolyIndexCache; - int count = -1 < first ? child.lastPolyIndexCache - first + 1 : -1; - for (int n = first; n < first + count; n++) { - if (gindex == -1) { - gindex = cache.addNew(n); - firstPolyIndexCache = gindex; - } else { - if (cache.vertexOffset[gindex] == cache.vertexOffset[n]) { - // When the vertex offsets are the same, this means that the - // current index range in the group shape can be extended to - // include the index range in the current child shape. - // This is a result of how the indices are updated for the - // leaf shapes. - cache.incCounts(gindex, - cache.indexCount[n], cache.vertexCount[n]); - } else { - gindex = cache.addNew(n); - } - } - } - - // Updating the first and last poly vertices for this group shape. - if (-1 < child.firstPolyVertex) { - if (firstPolyVertex == -1) { - firstPolyVertex = Integer.MAX_VALUE; - } - firstPolyVertex = PApplet.min(firstPolyVertex, child.firstPolyVertex); - } - if (-1 < child.lastPolyVertex) { - lastPolyVertex = PApplet.max(lastPolyVertex, child.lastPolyVertex); - } - } - lastPolyIndexCache = gindex; - } else { - // The index cache is updated in order to reflect the fact that all - // the vertices will be stored in a single VBO in the root shape. - // This update works as follows (the methodology is the same for - // poly, line and point): the VertexAbs variable in the root shape - // stores the index of the last vertex up to this shape (plus one) - // without taking into consideration the MAX_VERTEX_INDEX limit, so - // it effectively runs over the entire range. - // VertexRel, on the other hand, is reset every time the limit is - // exceeded, therefore creating the start of a new index group in the - // root shape. When this happens, the indices in the child shape need - // to be restarted as well to reflect the new index offset. - - firstPolyVertex = lastPolyVertex = - cache.vertexOffset[firstPolyIndexCache]; - for (int n = firstPolyIndexCache; n <= lastPolyIndexCache; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int vcount = cache.vertexCount[n]; - - if (PGL.MAX_VERTEX_INDEX1 <= root.polyVertexRel + vcount || // Too many vertices already signal the start of a new cache... - (is2D() && startStrokedTex(n))) { // ... or, in 2D, the beginning of line or points. - root.polyVertexRel = 0; - root.polyVertexOffset = root.polyVertexAbs; - cache.indexOffset[n] = root.polyIndexOffset; - } else { - tessGeo.incPolyIndices(ioffset, ioffset + icount - 1, - root.polyVertexRel); - } - cache.vertexOffset[n] = root.polyVertexOffset; - if (is2D()) { - setFirstStrokeVertex(n, lastPolyVertex); - } - - root.polyIndexOffset += icount; - root.polyVertexAbs += vcount; - root.polyVertexRel += vcount; - lastPolyVertex += vcount; - } - lastPolyVertex--; - if (is2D()) { - setLastStrokeVertex(lastPolyVertex); - } - } - } - - - protected boolean startStrokedTex(int n) { - return image != null && (n == firstLineIndexCache || - n == firstPointIndexCache); - } - - - protected void setFirstStrokeVertex(int n, int vert) { - if (n == firstLineIndexCache && firstLineVertex == -1) { - firstLineVertex = lastLineVertex = vert; - } - if (n == firstPointIndexCache && firstPointVertex == -1) { - firstPointVertex = lastPointVertex = vert; - } - } - - protected void setLastStrokeVertex(int vert) { - if (-1 < lastLineVertex) { - lastLineVertex = vert; - } - if (-1 < lastPointVertex) { - lastPointVertex += vert; - } - } - - protected void updateLineIndexCache() { - IndexCache cache = tessGeo.lineIndexCache; - if (family == GROUP) { - firstLineIndexCache = lastLineIndexCache = -1; - int gindex = -1; - - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - - int first = child.firstLineIndexCache; - int count = -1 < first ? child.lastLineIndexCache - first + 1 : -1; - for (int n = first; n < first + count; n++) { - if (gindex == -1) { - gindex = cache.addNew(n); - firstLineIndexCache = gindex; - } else { - if (cache.vertexOffset[gindex] == cache.vertexOffset[n]) { - cache.incCounts(gindex, cache.indexCount[n], - cache.vertexCount[n]); - } else { - gindex = cache.addNew(n); - } - } - } - - // Updating the first and last line vertices for this group shape. - if (-1 < child.firstLineVertex) { - if (firstLineVertex == -1) firstLineVertex = Integer.MAX_VALUE; - firstLineVertex = PApplet.min(firstLineVertex, child.firstLineVertex); - } - if (-1 < child.lastLineVertex) { - lastLineVertex = PApplet.max(lastLineVertex, child.lastLineVertex); - } - } - lastLineIndexCache = gindex; - } else { - firstLineVertex = lastLineVertex = - cache.vertexOffset[firstLineIndexCache]; - for (int n = firstLineIndexCache; n <= lastLineIndexCache; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int vcount = cache.vertexCount[n]; - - if (PGL.MAX_VERTEX_INDEX1 <= root.lineVertexRel + vcount) { - root.lineVertexRel = 0; - root.lineVertexOffset = root.lineVertexAbs; - cache.indexOffset[n] = root.lineIndexOffset; - } else { - tessGeo.incLineIndices(ioffset, ioffset + icount - 1, - root.lineVertexRel); - } - cache.vertexOffset[n] = root.lineVertexOffset; - - root.lineIndexOffset += icount; - root.lineVertexAbs += vcount; - root.lineVertexRel += vcount; - lastLineVertex += vcount; - } - lastLineVertex--; - } - } - - - protected void updatePointIndexCache() { - IndexCache cache = tessGeo.pointIndexCache; - if (family == GROUP) { - firstPointIndexCache = lastPointIndexCache = -1; - int gindex = -1; - - for (int i = 0; i < childCount; i++) { - PShapeOpenGL child = (PShapeOpenGL) children[i]; - - int first = child.firstPointIndexCache; - int count = -1 < first ? child.lastPointIndexCache - first + 1 : -1; - for (int n = first; n < first + count; n++) { - if (gindex == -1) { - gindex = cache.addNew(n); - firstPointIndexCache = gindex; - } else { - if (cache.vertexOffset[gindex] == cache.vertexOffset[n]) { - // When the vertex offsets are the same, this means that the - // current index range in the group shape can be extended to - // include either the index range in the current child shape. - // This is a result of how the indices are updated for the - // leaf shapes in aggregateImpl(). - cache.incCounts(gindex, cache.indexCount[n], - cache.vertexCount[n]); - } else { - gindex = cache.addNew(n); - } - } - } - - // Updating the first and last point vertices for this group shape. - if (-1 < child.firstPointVertex) { - if (firstPointVertex == -1) firstPointVertex = Integer.MAX_VALUE; - firstPointVertex = PApplet.min(firstPointVertex, - child.firstPointVertex); - } - if (-1 < child.lastPointVertex) { - lastPointVertex = PApplet.max(lastPointVertex, child.lastPointVertex); - } - } - lastPointIndexCache = gindex; - } else { - firstPointVertex = lastPointVertex = - cache.vertexOffset[firstPointIndexCache]; - for (int n = firstPointIndexCache; n <= lastPointIndexCache; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int vcount = cache.vertexCount[n]; - - if (PGL.MAX_VERTEX_INDEX1 <= root.pointVertexRel + vcount) { - root.pointVertexRel = 0; - root.pointVertexOffset = root.pointVertexAbs; - cache.indexOffset[n] = root.pointIndexOffset; - } else { - tessGeo.incPointIndices(ioffset, ioffset + icount - 1, - root.pointVertexRel); - } - cache.vertexOffset[n] = root.pointVertexOffset; - - root.pointIndexOffset += icount; - root.pointVertexAbs += vcount; - root.pointVertexRel += vcount; - lastPointVertex += vcount; - } - lastPointVertex--; - } - } - - - /////////////////////////////////////////////////////////// - - // - - // Buffer initialization - - - protected void initBuffers() { - boolean outdated = contextIsOutdated(); - context = pgl.getCurrentContext(); - - if (hasPolys && (needBufferInit || outdated)) { - initPolyBuffers(); - } - - if (hasLines && (needBufferInit || outdated)) { - initLineBuffers(); - } - - if (hasPoints && (needBufferInit || outdated)) { - initPointBuffers(); - } - - needBufferInit = false; - } - - - protected void initPolyBuffers() { - int size = tessGeo.polyVertexCount; - int sizef = size * PGL.SIZEOF_FLOAT; - int sizei = size * PGL.SIZEOF_INT; - - tessGeo.updatePolyVerticesBuffer(); - if (bufPolyVertex == null) - bufPolyVertex = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyVertex.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, - tessGeo.polyVerticesBuffer, glUsage); - - tessGeo.updatePolyColorsBuffer(); - if (bufPolyColor == null) - bufPolyColor = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyColor.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.polyColorsBuffer, glUsage); - - tessGeo.updatePolyNormalsBuffer(); - if (bufPolyNormal == null) - bufPolyNormal = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 3, PGL.SIZEOF_FLOAT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyNormal.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 3 * sizef, - tessGeo.polyNormalsBuffer, glUsage); - - tessGeo.updatePolyTexCoordsBuffer(); - if (bufPolyTexcoord == null) - bufPolyTexcoord = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 2, PGL.SIZEOF_FLOAT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyTexcoord.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 2 * sizef, - tessGeo.polyTexCoordsBuffer, glUsage); - - tessGeo.updatePolyAmbientBuffer(); - if (bufPolyAmbient == null) - bufPolyAmbient = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyAmbient.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.polyAmbientBuffer, glUsage); - - tessGeo.updatePolySpecularBuffer(); - if (bufPolySpecular == null) - bufPolySpecular = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolySpecular.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.polySpecularBuffer, glUsage); - - tessGeo.updatePolyEmissiveBuffer(); - if (bufPolyEmissive == null) - bufPolyEmissive = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyEmissive.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.polyEmissiveBuffer, glUsage); - - tessGeo.updatePolyShininessBuffer(); - if (bufPolyShininess == null) - bufPolyShininess = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_FLOAT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyShininess.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizef, - tessGeo.polyShininessBuffer, glUsage); - - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - tessGeo.updateAttribBuffer(attrib.name); - if (!attrib.bufferCreated()) attrib.createBuffer(pgl); - pgl.bindBuffer(PGL.ARRAY_BUFFER, attrib.buf.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, attrib.sizeInBytes(size), - tessGeo.polyAttribBuffers.get(name), glUsage); - } - - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - - tessGeo.updatePolyIndicesBuffer(); - if (bufPolyIndex == null) - bufPolyIndex = new VertexBuffer(pg, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, bufPolyIndex.glId); - pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, - tessGeo.polyIndexCount * PGL.SIZEOF_INDEX, - tessGeo.polyIndicesBuffer, glUsage); - - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); - } - - - protected void initLineBuffers() { - int size = tessGeo.lineVertexCount; - int sizef = size * PGL.SIZEOF_FLOAT; - int sizei = size * PGL.SIZEOF_INT; - - tessGeo.updateLineVerticesBuffer(); - if (bufLineVertex == null) - bufLineVertex = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineVertex.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, - tessGeo.lineVerticesBuffer, glUsage); - - tessGeo.updateLineColorsBuffer(); - if (bufLineColor == null) - bufLineColor = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineColor.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.lineColorsBuffer, glUsage); - - tessGeo.updateLineDirectionsBuffer(); - if (bufLineAttrib == null) - bufLineAttrib = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineAttrib.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, - tessGeo.lineDirectionsBuffer, glUsage); - - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - - tessGeo.updateLineIndicesBuffer(); - if (bufLineIndex == null) - bufLineIndex = new VertexBuffer(pg, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, bufLineIndex.glId); - pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, - tessGeo.lineIndexCount * PGL.SIZEOF_INDEX, - tessGeo.lineIndicesBuffer, glUsage); - - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); - } - - - protected void initPointBuffers() { - int size = tessGeo.pointVertexCount; - int sizef = size * PGL.SIZEOF_FLOAT; - int sizei = size * PGL.SIZEOF_INT; - - tessGeo.updatePointVerticesBuffer(); - if (bufPointVertex == null) - bufPointVertex = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointVertex.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, - tessGeo.pointVerticesBuffer, glUsage); - - tessGeo.updatePointColorsBuffer(); - if (bufPointColor == null) - bufPointColor = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointColor.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, sizei, - tessGeo.pointColorsBuffer, glUsage); - - tessGeo.updatePointOffsetsBuffer(); - if (bufPointAttrib == null) - bufPointAttrib = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 2, PGL.SIZEOF_FLOAT); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointAttrib.glId); - pgl.bufferData(PGL.ARRAY_BUFFER, 2 * sizef, - tessGeo.pointOffsetsBuffer, glUsage); - - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - - tessGeo.updatePointIndicesBuffer(); - if (bufPointIndex == null) - bufPointIndex = new VertexBuffer(pg, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, bufPointIndex.glId); - pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, - tessGeo.pointIndexCount * PGL.SIZEOF_INDEX, - tessGeo.pointIndicesBuffer, glUsage); - - pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); - } - - - protected boolean contextIsOutdated() { - boolean outdated = !pgl.contextIsCurrent(context); - if (outdated) { - bufPolyVertex.dispose(); - bufPolyColor.dispose(); - bufPolyNormal.dispose(); - bufPolyTexcoord.dispose(); - bufPolyAmbient.dispose(); - bufPolySpecular.dispose(); - bufPolyEmissive.dispose(); - bufPolyShininess.dispose(); - for (VertexAttribute attrib: polyAttribs.values()) { - attrib.buf.dispose(); - } - bufPolyIndex.dispose(); - - bufLineVertex.dispose(); - bufLineColor.dispose(); - bufLineAttrib.dispose(); - bufLineIndex.dispose(); - - bufPointVertex.dispose(); - bufPointColor.dispose(); - bufPointAttrib.dispose(); - bufPointIndex.dispose(); - } - return outdated; - } - - - /////////////////////////////////////////////////////////// - - // - - // Geometry update - - - protected void updateGeometry() { - root.initBuffers(); - if (root.modified) { - root.updateGeometryImpl(); - } - } - - - protected void updateGeometryImpl() { - if (modifiedPolyVertices) { - int offset = firstModifiedPolyVertex; - int size = lastModifiedPolyVertex - offset + 1; - copyPolyVertices(offset, size); - modifiedPolyVertices = false; - firstModifiedPolyVertex = PConstants.MAX_INT; - lastModifiedPolyVertex = PConstants.MIN_INT; - } - if (modifiedPolyColors) { - int offset = firstModifiedPolyColor; - int size = lastModifiedPolyColor - offset + 1; - copyPolyColors(offset, size); - modifiedPolyColors = false; - firstModifiedPolyColor = PConstants.MAX_INT; - lastModifiedPolyColor = PConstants.MIN_INT; - } - if (modifiedPolyNormals) { - int offset = firstModifiedPolyNormal; - int size = lastModifiedPolyNormal - offset + 1; - copyPolyNormals(offset, size); - modifiedPolyNormals = false; - firstModifiedPolyNormal = PConstants.MAX_INT; - lastModifiedPolyNormal = PConstants.MIN_INT; - } - if (modifiedPolyTexCoords) { - int offset = firstModifiedPolyTexcoord; - int size = lastModifiedPolyTexcoord - offset + 1; - copyPolyTexCoords(offset, size); - modifiedPolyTexCoords = false; - firstModifiedPolyTexcoord = PConstants.MAX_INT; - lastModifiedPolyTexcoord = PConstants.MIN_INT; - } - if (modifiedPolyAmbient) { - int offset = firstModifiedPolyAmbient; - int size = lastModifiedPolyAmbient - offset + 1; - copyPolyAmbient(offset, size); - modifiedPolyAmbient = false; - firstModifiedPolyAmbient = PConstants.MAX_INT; - lastModifiedPolyAmbient = PConstants.MIN_INT; - } - if (modifiedPolySpecular) { - int offset = firstModifiedPolySpecular; - int size = lastModifiedPolySpecular - offset + 1; - copyPolySpecular(offset, size); - modifiedPolySpecular = false; - firstModifiedPolySpecular = PConstants.MAX_INT; - lastModifiedPolySpecular = PConstants.MIN_INT; - } - if (modifiedPolyEmissive) { - int offset = firstModifiedPolyEmissive; - int size = lastModifiedPolyEmissive - offset + 1; - copyPolyEmissive(offset, size); - modifiedPolyEmissive = false; - firstModifiedPolyEmissive = PConstants.MAX_INT; - lastModifiedPolyEmissive = PConstants.MIN_INT; - } - if (modifiedPolyShininess) { - int offset = firstModifiedPolyShininess; - int size = lastModifiedPolyShininess - offset + 1; - copyPolyShininess(offset, size); - modifiedPolyShininess = false; - firstModifiedPolyShininess = PConstants.MAX_INT; - lastModifiedPolyShininess = PConstants.MIN_INT; - } - for (String name: polyAttribs.keySet()) { - VertexAttribute attrib = polyAttribs.get(name); - if (attrib.modified) { - int offset = firstModifiedPolyVertex; - int size = lastModifiedPolyVertex - offset + 1; - copyPolyAttrib(attrib, offset, size); - attrib.modified = false; - attrib.firstModified = PConstants.MAX_INT; - attrib.lastModified = PConstants.MIN_INT; - } - } - - if (modifiedLineVertices) { - int offset = firstModifiedLineVertex; - int size = lastModifiedLineVertex - offset + 1; - copyLineVertices(offset, size); - modifiedLineVertices = false; - firstModifiedLineVertex = PConstants.MAX_INT; - lastModifiedLineVertex = PConstants.MIN_INT; - } - if (modifiedLineColors) { - int offset = firstModifiedLineColor; - int size = lastModifiedLineColor - offset + 1; - copyLineColors(offset, size); - modifiedLineColors = false; - firstModifiedLineColor = PConstants.MAX_INT; - lastModifiedLineColor = PConstants.MIN_INT; - } - if (modifiedLineAttributes) { - int offset = firstModifiedLineAttribute; - int size = lastModifiedLineAttribute - offset + 1; - copyLineAttributes(offset, size); - modifiedLineAttributes = false; - firstModifiedLineAttribute = PConstants.MAX_INT; - lastModifiedLineAttribute = PConstants.MIN_INT; - } - - if (modifiedPointVertices) { - int offset = firstModifiedPointVertex; - int size = lastModifiedPointVertex - offset + 1; - copyPointVertices(offset, size); - modifiedPointVertices = false; - firstModifiedPointVertex = PConstants.MAX_INT; - lastModifiedPointVertex = PConstants.MIN_INT; - } - if (modifiedPointColors) { - int offset = firstModifiedPointColor; - int size = lastModifiedPointColor - offset + 1; - copyPointColors(offset, size); - modifiedPointColors = false; - firstModifiedPointColor = PConstants.MAX_INT; - lastModifiedPointColor = PConstants.MIN_INT; - } - if (modifiedPointAttributes) { - int offset = firstModifiedPointAttribute; - int size = lastModifiedPointAttribute - offset + 1; - copyPointAttributes(offset, size); - modifiedPointAttributes = false; - firstModifiedPointAttribute = PConstants.MAX_INT; - lastModifiedPointAttribute = PConstants.MIN_INT; - } - - modified = false; - } - - - protected void copyPolyVertices(int offset, int size) { - tessGeo.updatePolyVerticesBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyVertex.glId); - tessGeo.polyVerticesBuffer.position(4 * offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, 4 * offset * PGL.SIZEOF_FLOAT, - 4 * size * PGL.SIZEOF_FLOAT, tessGeo.polyVerticesBuffer); - tessGeo.polyVerticesBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyPolyColors(int offset, int size) { - tessGeo.updatePolyColorsBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyColor.glId); - tessGeo.polyColorsBuffer.position(offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT, - size * PGL.SIZEOF_INT, tessGeo.polyColorsBuffer); - tessGeo.polyColorsBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyPolyNormals(int offset, int size) { - tessGeo.updatePolyNormalsBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyNormal.glId); - tessGeo.polyNormalsBuffer.position(3 * offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, 3 * offset * PGL.SIZEOF_FLOAT, - 3 * size * PGL.SIZEOF_FLOAT, tessGeo.polyNormalsBuffer); - tessGeo.polyNormalsBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyPolyTexCoords(int offset, int size) { - tessGeo.updatePolyTexCoordsBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyTexcoord.glId); - tessGeo.polyTexCoordsBuffer.position(2 * offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, 2 * offset * PGL.SIZEOF_FLOAT, - 2 * size * PGL.SIZEOF_FLOAT, tessGeo.polyTexCoordsBuffer); - tessGeo.polyTexCoordsBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyPolyAmbient(int offset, int size) { - tessGeo.updatePolyAmbientBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyAmbient.glId); - tessGeo.polyAmbientBuffer.position(offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT, - size * PGL.SIZEOF_INT, tessGeo.polyAmbientBuffer); - tessGeo.polyAmbientBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyPolySpecular(int offset, int size) { - tessGeo.updatePolySpecularBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolySpecular.glId); - tessGeo.polySpecularBuffer.position(offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT, - size * PGL.SIZEOF_INT, tessGeo.polySpecularBuffer); - tessGeo.polySpecularBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyPolyEmissive(int offset, int size) { - tessGeo.updatePolyEmissiveBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyEmissive.glId); - tessGeo.polyEmissiveBuffer.position(offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT, - size * PGL.SIZEOF_INT, tessGeo.polyEmissiveBuffer); - tessGeo.polyEmissiveBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyPolyShininess(int offset, int size) { - tessGeo.updatePolyShininessBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyShininess.glId); - tessGeo.polyShininessBuffer.position(offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_FLOAT, - size * PGL.SIZEOF_FLOAT, tessGeo.polyShininessBuffer); - tessGeo.polyShininessBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyPolyAttrib(VertexAttribute attrib, int offset, int size) { - tessGeo.updateAttribBuffer(attrib.name, offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, attrib.buf.glId); - Buffer buf = tessGeo.polyAttribBuffers.get(attrib.name); - buf.position(attrib.size * offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, attrib.sizeInBytes(offset), - attrib.sizeInBytes(size), buf); - buf.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyLineVertices(int offset, int size) { - tessGeo.updateLineVerticesBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineVertex.glId); - tessGeo.lineVerticesBuffer.position(4 * offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, 4 * offset * PGL.SIZEOF_FLOAT, - 4 * size * PGL.SIZEOF_FLOAT, tessGeo.lineVerticesBuffer); - tessGeo.lineVerticesBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyLineColors(int offset, int size) { - tessGeo.updateLineColorsBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineColor.glId); - tessGeo.lineColorsBuffer.position(offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT, - size * PGL.SIZEOF_INT, tessGeo.lineColorsBuffer); - tessGeo.lineColorsBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyLineAttributes(int offset, int size) { - tessGeo.updateLineDirectionsBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineAttrib.glId); - tessGeo.lineDirectionsBuffer.position(4 * offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, 4 * offset * PGL.SIZEOF_FLOAT, - 4 * size * PGL.SIZEOF_FLOAT, tessGeo.lineDirectionsBuffer); - tessGeo.lineDirectionsBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyPointVertices(int offset, int size) { - tessGeo.updatePointVerticesBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointVertex.glId); - tessGeo.pointVerticesBuffer.position(4 * offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, 4 * offset * PGL.SIZEOF_FLOAT, - 4 * size * PGL.SIZEOF_FLOAT, tessGeo.pointVerticesBuffer); - tessGeo.pointVerticesBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyPointColors(int offset, int size) { - tessGeo.updatePointColorsBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointColor.glId); - tessGeo.pointColorsBuffer.position(offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT, - size * PGL.SIZEOF_INT,tessGeo.pointColorsBuffer); - tessGeo.pointColorsBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void copyPointAttributes(int offset, int size) { - tessGeo.updatePointOffsetsBuffer(offset, size); - pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointAttrib.glId); - tessGeo.pointOffsetsBuffer.position(2 * offset); - pgl.bufferSubData(PGL.ARRAY_BUFFER, 2 * offset * PGL.SIZEOF_FLOAT, - 2 * size * PGL.SIZEOF_FLOAT, tessGeo.pointOffsetsBuffer); - tessGeo.pointOffsetsBuffer.rewind(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, 0); - } - - - protected void setModifiedPolyVertices(int first, int last) { - if (first < firstModifiedPolyVertex) firstModifiedPolyVertex = first; - if (last > lastModifiedPolyVertex) lastModifiedPolyVertex = last; - modifiedPolyVertices = true; - modified = true; - } - - - protected void setModifiedPolyColors(int first, int last) { - if (first < firstModifiedPolyColor) firstModifiedPolyColor = first; - if (last > lastModifiedPolyColor) lastModifiedPolyColor = last; - modifiedPolyColors = true; - modified = true; - } - - - protected void setModifiedPolyNormals(int first, int last) { - if (first < firstModifiedPolyNormal) firstModifiedPolyNormal = first; - if (last > lastModifiedPolyNormal) lastModifiedPolyNormal = last; - modifiedPolyNormals = true; - modified = true; - } - - - protected void setModifiedPolyTexCoords(int first, int last) { - if (first < firstModifiedPolyTexcoord) firstModifiedPolyTexcoord = first; - if (last > lastModifiedPolyTexcoord) lastModifiedPolyTexcoord = last; - modifiedPolyTexCoords = true; - modified = true; - } - - - protected void setModifiedPolyAmbient(int first, int last) { - if (first < firstModifiedPolyAmbient) firstModifiedPolyAmbient = first; - if (last > lastModifiedPolyAmbient) lastModifiedPolyAmbient = last; - modifiedPolyAmbient = true; - modified = true; - } - - - protected void setModifiedPolySpecular(int first, int last) { - if (first < firstModifiedPolySpecular) firstModifiedPolySpecular = first; - if (last > lastModifiedPolySpecular) lastModifiedPolySpecular = last; - modifiedPolySpecular = true; - modified = true; - } - - - protected void setModifiedPolyEmissive(int first, int last) { - if (first < firstModifiedPolyEmissive) firstModifiedPolyEmissive = first; - if (last > lastModifiedPolyEmissive) lastModifiedPolyEmissive = last; - modifiedPolyEmissive = true; - modified = true; - } - - - protected void setModifiedPolyShininess(int first, int last) { - if (first < firstModifiedPolyShininess) firstModifiedPolyShininess = first; - if (last > lastModifiedPolyShininess) lastModifiedPolyShininess = last; - modifiedPolyShininess = true; - modified = true; - } - - - protected void setModifiedPolyAttrib(VertexAttribute attrib, int first, int last) { - if (first < attrib.firstModified) attrib.firstModified = first; - if (last > attrib.lastModified) attrib.lastModified = last; - attrib.modified = true; - modified = true; - } - - - protected void setModifiedLineVertices(int first, int last) { - if (first < firstModifiedLineVertex) firstModifiedLineVertex = first; - if (last > lastModifiedLineVertex) lastModifiedLineVertex = last; - modifiedLineVertices = true; - modified = true; - } - - - protected void setModifiedLineColors(int first, int last) { - if (first < firstModifiedLineColor) firstModifiedLineColor = first; - if (last > lastModifiedLineColor) lastModifiedLineColor = last; - modifiedLineColors = true; - modified = true; - } - - - protected void setModifiedLineAttributes(int first, int last) { - if (first < firstModifiedLineAttribute) firstModifiedLineAttribute = first; - if (last > lastModifiedLineAttribute) lastModifiedLineAttribute = last; - modifiedLineAttributes = true; - modified = true; - } - - - protected void setModifiedPointVertices(int first, int last) { - if (first < firstModifiedPointVertex) firstModifiedPointVertex = first; - if (last > lastModifiedPointVertex) lastModifiedPointVertex = last; - modifiedPointVertices = true; - modified = true; - } - - - protected void setModifiedPointColors(int first, int last) { - if (first < firstModifiedPointColor) firstModifiedPointColor = first; - if (last > lastModifiedPointColor) lastModifiedPointColor = last; - modifiedPointColors = true; - modified = true; - } - - - protected void setModifiedPointAttributes(int first, int last) { - if (first < firstModifiedPointAttribute) firstModifiedPointAttribute = first; - if (last > lastModifiedPointAttribute) lastModifiedPointAttribute = last; - modifiedPointAttributes = true; - modified = true; - } - - - /////////////////////////////////////////////////////////// - - // - - // Style handling - - - @Override - public void disableStyle() { - if (openShape) { - PGraphics.showWarning(INSIDE_BEGIN_END_ERROR, "disableStyle()"); - return; - } - - // Saving the current values to use if the style is re-enabled later - savedStroke = stroke; - savedStrokeColor = strokeColor; - savedStrokeWeight = strokeWeight; - savedStrokeCap = strokeCap; - savedStrokeJoin = strokeJoin; - savedFill = fill; - savedFillColor = fillColor; - savedTint = tint; - savedTintColor = tintColor; - savedAmbientColor = ambientColor; - savedSpecularColor = specularColor; - savedEmissiveColor = emissiveColor; - savedShininess = shininess; - savedTextureMode = textureMode; - - super.disableStyle(); - } - - - @Override - public void enableStyle() { - if (savedStroke) { - setStroke(true); - setStroke(savedStrokeColor); - setStrokeWeight(savedStrokeWeight); - setStrokeCap(savedStrokeCap); - setStrokeJoin(savedStrokeJoin); - } else { - setStroke(false); - } - - if (savedFill) { - setFill(true); - setFill(savedFillColor); - } else { - setFill(false); - } - - if (savedTint) { - setTint(true); - setTint(savedTintColor); - } - - setAmbient(savedAmbientColor); - setSpecular(savedSpecularColor); - setEmissive(savedEmissiveColor); - setShininess(savedShininess); - - if (image != null) { - setTextureMode(savedTextureMode); - } - - super.enableStyle(); - } - - - @Override - protected void styles(PGraphics g) { - if (g instanceof PGraphicsOpenGL) { - if (g.stroke) { - setStroke(true); - setStroke(g.strokeColor); - setStrokeWeight(g.strokeWeight); - setStrokeCap(g.strokeCap); - setStrokeJoin(g.strokeJoin); - } else { - setStroke(false); - } - - if (g.fill) { - setFill(true); - setFill(g.fillColor); - } else { - setFill(false); - } - - if (g.tint) { - setTint(true); - setTint(g.tintColor); - } - - setAmbient(g.ambientColor); - setSpecular(g.specularColor); - setEmissive(g.emissiveColor); - setShininess(g.shininess); - - if (image != null) { - setTextureMode(g.textureMode); - } - } else { - super.styles(g); - } - } - - - /////////////////////////////////////////////////////////// - - // - - // Rendering methods - - - /* - public void draw() { - draw(pg); - } - */ - - - @Override - public void draw(PGraphics g) { - if (g instanceof PGraphicsOpenGL) { - PGraphicsOpenGL gl = (PGraphicsOpenGL)g; - if (visible) { - pre(gl); - - updateTessellation(); - updateGeometry(); - - if (family == GROUP) { - if (fragmentedGroup(gl)) { - for (int i = 0; i < childCount; i++) { - ((PShapeOpenGL) children[i]).draw(gl); - } - } else { - PImage tex = null; - if (textures != null && textures.size() == 1) { - tex = (PImage)textures.toArray()[0]; - } - render(gl, tex); - } - } else { - render(gl, image); - } - post(gl); - } - } else { - if (family == GEOMETRY) { - inGeoToVertices(); - } - pre(g); - drawImpl(g); - post(g); - } - } - - - private void inGeoToVertices() { - vertexCount = 0; - vertexCodeCount = 0; - if (inGeo.codeCount == 0) { - for (int i = 0; i < inGeo.vertexCount; i++) { - int index = 3 * i; - float x = inGeo.vertices[index++]; - float y = inGeo.vertices[index ]; - super.vertex(x, y); - } - } else { - int v; - float x, y; - float cx, cy; - float x2, y2, x3, y3, x4, y4; - int idx = 0; - boolean insideContour = false; - - for (int j = 0; j < inGeo.codeCount; j++) { - switch (inGeo.codes[j]) { - - case VERTEX: - v = 3 * idx; - x = inGeo.vertices[v++]; - y = inGeo.vertices[v ]; - super.vertex(x, y); - - idx++; - break; - - case QUADRATIC_VERTEX: - v = 3 * idx; - cx = inGeo.vertices[v++]; - cy = inGeo.vertices[v]; - - v = 3 * (idx + 1); - x3 = inGeo.vertices[v++]; - y3 = inGeo.vertices[v]; - - super.quadraticVertex(cx, cy, x3, y3); - - idx += 2; - break; - - case BEZIER_VERTEX: - v = 3 * idx; - x2 = inGeo.vertices[v++]; - y2 = inGeo.vertices[v ]; - - v = 3 * (idx + 1); - x3 = inGeo.vertices[v++]; - y3 = inGeo.vertices[v ]; - - v = 3 * (idx + 2); - x4 = inGeo.vertices[v++]; - y4 = inGeo.vertices[v ]; - - super.bezierVertex(x2, y2, x3, y3, x4, y4); - - idx += 3; - break; - - case CURVE_VERTEX: - v = 3 * idx; - x = inGeo.vertices[v++]; - y = inGeo.vertices[v ]; - - super.curveVertex(x, y); - - idx++; - break; - - case BREAK: - if (insideContour) { - super.endContourImpl(); - } - super.beginContourImpl(); - insideContour = true; - } - } - if (insideContour) { - super.endContourImpl(); - } - } - } - - - // Returns true if some child shapes below this one either - // use different texture maps (or only one texture is used by some while - // others are untextured), or have stroked textures, - // so they cannot rendered in a single call. - // Or accurate 2D mode is enabled, which forces each - // shape to be rendered separately. - protected boolean fragmentedGroup(PGraphicsOpenGL g) { - return g.getHint(DISABLE_OPTIMIZED_STROKE) || - (textures != null && (1 < textures.size() || untexChild)) || - strokedTexture; - } - - - @Override - protected void pre(PGraphics g) { - if (g instanceof PGraphicsOpenGL) { - if (!style) { - styles(g); - } - } else { - super.pre(g); - } - } - - - @Override - protected void post(PGraphics g) { - if (g instanceof PGraphicsOpenGL) { - } else { - super.post(g); - } - } - - - @Override - protected void drawGeometry(PGraphics g) { - vertexCount = inGeo.vertexCount; - vertices = inGeo.getVertexData(); - - super.drawGeometry(g); - - vertexCount = 0; - vertices = null; - } - - - // Render the geometry stored in the root shape as VBOs, for the vertices - // corresponding to this shape. Sometimes we can have root == this. - protected void render(PGraphicsOpenGL g, PImage texture) { - if (root == null) { - // Some error. Root should never be null. At least it should be 'this'. - throw new RuntimeException("Error rendering PShapeOpenGL, root shape is " + - "null"); - } - - if (hasPolys) { - renderPolys(g, texture); - if (g.haveRaw()) { - rawPolys(g, texture); - } - } - - if (is3D()) { - // In 3D mode, the lines and points need to be rendered separately - // as they require their own shaders. - if (hasLines) { - renderLines(g); - if (g.haveRaw()) { - rawLines(g); - } - } - - if (hasPoints) { - renderPoints(g); - if (g.haveRaw()) { - rawPoints(g); - } - } - } - } - - - protected void renderPolys(PGraphicsOpenGL g, PImage textureImage) { - boolean customShader = g.polyShader != null; - boolean needNormals = customShader ? g.polyShader.accessNormals() : false; - boolean needTexCoords = customShader ? g.polyShader.accessTexCoords() : false; - - Texture tex = textureImage != null ? g.getTexture(textureImage) : null; - - boolean renderingFill = false, renderingStroke = false; - PShader shader = null; - IndexCache cache = tessGeo.polyIndexCache; - for (int n = firstPolyIndexCache; n <= lastPolyIndexCache; n++) { - if (is3D() || (tex != null && (firstLineIndexCache == -1 || - n < firstLineIndexCache) && - (firstPointIndexCache == -1 || - n < firstPointIndexCache))) { - // Rendering fill triangles, which can be lit and textured. - if (!renderingFill) { - shader = g.getPolyShader(g.lights, tex != null); - shader.bind(); - renderingFill = true; - } - } else { - // Rendering line or point triangles, which are never lit nor textured. - if (!renderingStroke) { - if (tex != null) { - tex.unbind(); - tex = null; - } - - if (shader != null && shader.bound()) { - shader.unbind(); - } - - // If the renderer is 2D, then g.lights should always be false, - // so no need to worry about that. - shader = g.getPolyShader(g.lights, false); - shader.bind(); - - renderingFill = false; - renderingStroke = true; - } - } - - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int voffset = cache.vertexOffset[n]; - - shader.setVertexAttribute(root.bufPolyVertex.glId, 4, PGL.FLOAT, - 0, 4 * voffset * PGL.SIZEOF_FLOAT); - shader.setColorAttribute(root.bufPolyColor.glId, 4, PGL.UNSIGNED_BYTE, - 0, 4 * voffset * PGL.SIZEOF_BYTE); - - if (g.lights) { - shader.setNormalAttribute(root.bufPolyNormal.glId, 3, PGL.FLOAT, - 0, 3 * voffset * PGL.SIZEOF_FLOAT); - shader.setAmbientAttribute(root.bufPolyAmbient.glId, 4, PGL.UNSIGNED_BYTE, - 0, 4 * voffset * PGL.SIZEOF_BYTE); - shader.setSpecularAttribute(root.bufPolySpecular.glId, 4, PGL.UNSIGNED_BYTE, - 0, 4 * voffset * PGL.SIZEOF_BYTE); - shader.setEmissiveAttribute(root.bufPolyEmissive.glId, 4, PGL.UNSIGNED_BYTE, - 0, 4 * voffset * PGL.SIZEOF_BYTE); - shader.setShininessAttribute(root.bufPolyShininess.glId, 1, PGL.FLOAT, - 0, voffset * PGL.SIZEOF_FLOAT); - } - if (g.lights || needNormals) { - shader.setNormalAttribute(root.bufPolyNormal.glId, 3, PGL.FLOAT, - 0, 3 * voffset * PGL.SIZEOF_FLOAT); - } - - if (tex != null || needTexCoords) { - shader.setTexcoordAttribute(root.bufPolyTexcoord.glId, 2, PGL.FLOAT, - 0, 2 * voffset * PGL.SIZEOF_FLOAT); - shader.setTexture(tex); - } - - for (VertexAttribute attrib: polyAttribs.values()) { - if (!attrib.active(shader)) continue; - attrib.bind(pgl); - shader.setAttributeVBO(attrib.glLoc, attrib.buf.glId, - attrib.tessSize, attrib.type, - attrib.isColor(), 0, attrib.sizeInBytes(voffset)); - } - - shader.draw(root.bufPolyIndex.glId, icount, ioffset); - } - - for (VertexAttribute attrib: polyAttribs.values()) { - if (attrib.active(shader)) attrib.unbind(pgl); - } - if (shader != null && shader.bound()) { - shader.unbind(); - } - } - - - protected void rawPolys(PGraphicsOpenGL g, PImage textureImage) { - PGraphics raw = g.getRaw(); - - raw.colorMode(RGB); - raw.noStroke(); - raw.beginShape(TRIANGLES); - - float[] vertices = tessGeo.polyVertices; - int[] color = tessGeo.polyColors; - float[] uv = tessGeo.polyTexCoords; - short[] indices = tessGeo.polyIndices; - - IndexCache cache = tessGeo.polyIndexCache; - for (int n = firstPolyIndexCache; n <= lastPolyIndexCache; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int voffset = cache.vertexOffset[n]; - - for (int tr = ioffset / 3; tr < (ioffset + icount) / 3; tr++) { - int i0 = voffset + indices[3 * tr + 0]; - int i1 = voffset + indices[3 * tr + 1]; - int i2 = voffset + indices[3 * tr + 2]; - - float[] src0 = {0, 0, 0, 0}; - float[] src1 = {0, 0, 0, 0}; - float[] src2 = {0, 0, 0, 0}; - float[] pt0 = {0, 0, 0, 0}; - float[] pt1 = {0, 0, 0, 0}; - float[] pt2 = {0, 0, 0, 0}; - int argb0 = PGL.nativeToJavaARGB(color[i0]); - int argb1 = PGL.nativeToJavaARGB(color[i1]); - int argb2 = PGL.nativeToJavaARGB(color[i2]); - - PApplet.arrayCopy(vertices, 4 * i0, src0, 0, 4); - PApplet.arrayCopy(vertices, 4 * i1, src1, 0, 4); - PApplet.arrayCopy(vertices, 4 * i2, src2, 0, 4); - // Applying any transformation is currently stored in the - // modelview matrix of the renderer. - g.modelview.mult(src0, pt0); - g.modelview.mult(src1, pt1); - g.modelview.mult(src2, pt2); - - if (textureImage != null) { - raw.texture(textureImage); - if (raw.is3D()) { - raw.fill(argb0); - raw.vertex(pt0[X], pt0[Y], pt0[Z], uv[2 * i0 + 0], uv[2 * i0 + 1]); - raw.fill(argb1); - raw.vertex(pt1[X], pt1[Y], pt1[Z], uv[2 * i1 + 0], uv[2 * i1 + 1]); - raw.fill(argb2); - raw.vertex(pt2[X], pt2[Y], pt2[Z], uv[2 * i2 + 0], uv[2 * i2 + 1]); - } else if (raw.is2D()) { - float sx0 = g.screenXImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sy0 = g.screenYImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sx1 = g.screenXImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sy1 = g.screenYImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sx2 = g.screenXImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - float sy2 = g.screenYImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - raw.fill(argb0); - raw.vertex(sx0, sy0, uv[2 * i0 + 0], uv[2 * i0 + 1]); - raw.fill(argb1); - raw.vertex(sx1, sy1, uv[2 * i1 + 0], uv[2 * i1 + 1]); - raw.fill(argb1); - raw.vertex(sx2, sy2, uv[2 * i2 + 0], uv[2 * i2 + 1]); - } - } else { - if (raw.is3D()) { - raw.fill(argb0); - raw.vertex(pt0[X], pt0[Y], pt0[Z]); - raw.fill(argb1); - raw.vertex(pt1[X], pt1[Y], pt1[Z]); - raw.fill(argb2); - raw.vertex(pt2[X], pt2[Y], pt2[Z]); - } else if (raw.is2D()) { - float sx0 = g.screenXImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sy0 = g.screenYImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sx1 = g.screenXImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sy1 = g.screenYImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sx2 = g.screenXImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - float sy2 = g.screenYImpl(pt2[0], pt2[1], pt2[2], pt2[3]); - raw.fill(argb0); - raw.vertex(sx0, sy0); - raw.fill(argb1); - raw.vertex(sx1, sy1); - raw.fill(argb2); - raw.vertex(sx2, sy2); - } - } - } - } - - raw.endShape(); - } - - - protected void renderLines(PGraphicsOpenGL g) { - PShader shader = g.getLineShader(); - shader.bind(); - - IndexCache cache = tessGeo.lineIndexCache; - for (int n = firstLineIndexCache; n <= lastLineIndexCache; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int voffset = cache.vertexOffset[n]; - - shader.setVertexAttribute(root.bufLineVertex.glId, 4, PGL.FLOAT, - 0, 4 * voffset * PGL.SIZEOF_FLOAT); - shader.setColorAttribute(root.bufLineColor.glId, 4, PGL.UNSIGNED_BYTE, - 0, 4 * voffset * PGL.SIZEOF_BYTE); - shader.setLineAttribute(root.bufLineAttrib.glId, 4, PGL.FLOAT, - 0, 4 * voffset * PGL.SIZEOF_FLOAT); - - shader.draw(root.bufLineIndex.glId, icount, ioffset); - } - - shader.unbind(); - } - - - protected void rawLines(PGraphicsOpenGL g) { - PGraphics raw = g.getRaw(); - - raw.colorMode(RGB); - raw.noFill(); - raw.strokeCap(strokeCap); - raw.strokeJoin(strokeJoin); - raw.beginShape(LINES); - - float[] vertices = tessGeo.lineVertices; - int[] color = tessGeo.lineColors; - float[] attribs = tessGeo.lineDirections; - short[] indices = tessGeo.lineIndices; - - IndexCache cache = tessGeo.lineIndexCache; - for (int n = firstLineIndexCache; n <= lastLineIndexCache; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int voffset = cache.vertexOffset[n]; - - for (int ln = ioffset / 6; ln < (ioffset + icount) / 6; ln++) { - // Each line segment is defined by six indices since its - // formed by two triangles. We only need the first and last - // vertices. - // This bunch of vertices could also be the bevel triangles, - // with we detect this situation by looking at the line weight. - int i0 = voffset + indices[6 * ln + 0]; - int i1 = voffset + indices[6 * ln + 5]; - float sw0 = 2 * attribs[4 * i0 + 3]; - float sw1 = 2 * attribs[4 * i1 + 3]; - - if (PGraphicsOpenGL.zero(sw0)) continue; // Bevel triangles, skip. - - float[] src0 = {0, 0, 0, 0}; - float[] src1 = {0, 0, 0, 0}; - float[] pt0 = {0, 0, 0, 0}; - float[] pt1 = {0, 0, 0, 0}; - int argb0 = PGL.nativeToJavaARGB(color[i0]); - int argb1 = PGL.nativeToJavaARGB(color[i1]); - - PApplet.arrayCopy(vertices, 4 * i0, src0, 0, 4); - PApplet.arrayCopy(vertices, 4 * i1, src1, 0, 4); - // Applying any transformation is currently stored in the - // modelview matrix of the renderer. - g.modelview.mult(src0, pt0); - g.modelview.mult(src1, pt1); - - if (raw.is3D()) { - raw.strokeWeight(sw0); - raw.stroke(argb0); - raw.vertex(pt0[X], pt0[Y], pt0[Z]); - raw.strokeWeight(sw1); - raw.stroke(argb1); - raw.vertex(pt1[X], pt1[Y], pt1[Z]); - } else if (raw.is2D()) { - float sx0 = g.screenXImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sy0 = g.screenYImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sx1 = g.screenXImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - float sy1 = g.screenYImpl(pt1[0], pt1[1], pt1[2], pt1[3]); - raw.strokeWeight(sw0); - raw.stroke(argb0); - raw.vertex(sx0, sy0); - raw.strokeWeight(sw1); - raw.stroke(argb1); - raw.vertex(sx1, sy1); - } - } - } - - raw.endShape(); - } - - - protected void renderPoints(PGraphicsOpenGL g) { - PShader shader = g.getPointShader(); - shader.bind(); - - IndexCache cache = tessGeo.pointIndexCache; - for (int n = firstPointIndexCache; n <= lastPointIndexCache; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int voffset = cache.vertexOffset[n]; - - shader.setVertexAttribute(root.bufPointVertex.glId, 4, PGL.FLOAT, - 0, 4 * voffset * PGL.SIZEOF_FLOAT); - shader.setColorAttribute(root.bufPointColor.glId, 4, PGL.UNSIGNED_BYTE, - 0, 4 * voffset * PGL.SIZEOF_BYTE); - shader.setPointAttribute(root.bufPointAttrib.glId, 2, PGL.FLOAT, - 0, 2 * voffset * PGL.SIZEOF_FLOAT); - - shader.draw(root.bufPointIndex.glId, icount, ioffset); - } - - shader.unbind(); - } - - - protected void rawPoints(PGraphicsOpenGL g) { - PGraphics raw = g.getRaw(); - - raw.colorMode(RGB); - raw.noFill(); - raw.strokeCap(strokeCap); - raw.beginShape(POINTS); - - float[] vertices = tessGeo.pointVertices; - int[] color = tessGeo.pointColors; - float[] attribs = tessGeo.pointOffsets; - short[] indices = tessGeo.pointIndices; - - IndexCache cache = tessGeo.pointIndexCache; - for (int n = 0; n < cache.size; n++) { - int ioffset = cache.indexOffset[n]; - int icount = cache.indexCount[n]; - int voffset = cache.vertexOffset[n]; - - int pt = ioffset; - while (pt < (ioffset + icount) / 3) { - float size = attribs[2 * pt + 2]; - float weight; - int perim; - if (0 < size) { // round point - weight = +size / 0.5f; - perim = PApplet.min(PGraphicsOpenGL.MAX_POINT_ACCURACY, - PApplet.max(PGraphicsOpenGL.MIN_POINT_ACCURACY, - (int) (TWO_PI * weight / - PGraphicsOpenGL.POINT_ACCURACY_FACTOR))) + 1; - } else { // Square point - weight = -size / 0.5f; - perim = 5; - } - - int i0 = voffset + indices[3 * pt]; - int argb0 = PGL.nativeToJavaARGB(color[i0]); - float[] pt0 = {0, 0, 0, 0}; - - float[] src0 = {0, 0, 0, 0}; - PApplet.arrayCopy(vertices, 4 * i0, src0, 0, 4); - g.modelview.mult(src0, pt0); - - if (raw.is3D()) { - raw.strokeWeight(weight); - raw.stroke(argb0); - raw.vertex(pt0[X], pt0[Y], pt0[Z]); - } else if (raw.is2D()) { - float sx0 = g.screenXImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - float sy0 = g.screenYImpl(pt0[0], pt0[1], pt0[2], pt0[3]); - raw.strokeWeight(weight); - raw.stroke(argb0); - raw.vertex(sx0, sy0); - } - - pt += perim; - } - } - - raw.endShape(); - } -} diff --git a/core/src/processing/opengl/PSurfaceGLES.java b/core/src/processing/opengl/PSurfaceGLES.java deleted file mode 100644 index b9a86ae87..000000000 --- a/core/src/processing/opengl/PSurfaceGLES.java +++ /dev/null @@ -1,604 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.opengles.GL10; - -import android.app.ActivityManager; -import android.content.Context; -import android.content.pm.ConfigurationInfo; -import android.opengl.GLSurfaceView; -import android.opengl.GLSurfaceView.EGLConfigChooser; -import android.opengl.GLSurfaceView.Renderer; -import android.service.wallpaper.WallpaperService; -import android.support.wearable.watchface.Gles2WatchFaceService; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.View; - -import processing.android.AppComponent; -import processing.android.PFragment; -import processing.core.PApplet; -import processing.core.PGraphics; -import processing.core.PSurfaceNone; - -public class PSurfaceGLES extends PSurfaceNone { - public PGLES pgl; - private SurfaceViewGLES glsurf; - - public PSurfaceGLES() { } - - public PSurfaceGLES(PGraphics graphics, AppComponent component, SurfaceHolder holder) { - this.sketch = graphics.parent; - this.graphics = graphics; - this.component = component; - this.pgl = (PGLES)((PGraphicsOpenGL)graphics).pgl; - if (component.getKind() == AppComponent.FRAGMENT) { - PFragment frag = (PFragment)component; - activity = frag.getActivity(); - surfaceView = new SurfaceViewGLES(activity, null); - } else if (component.getKind() == AppComponent.WALLPAPER) { - wallpaper = (WallpaperService)component; - surfaceView = new SurfaceViewGLES(wallpaper, holder); - } else if (component.getKind() == AppComponent.WATCHFACE) { - watchface = (Gles2WatchFaceService)component; - // Set as ready here, as watch faces don't have a surface view with a - // surfaceCreate() event to do it. - surfaceReady = true; - } - glsurf = (SurfaceViewGLES)surfaceView; - } - - @Override - public void dispose() { - super.dispose(); - if (glsurf != null) { - glsurf.dispose(); - glsurf = null; - } - } - - /////////////////////////////////////////////////////////// - - // Thread handling - - @Override - protected void callDraw() { - component.requestDraw(); - if (component.canDraw() && glsurf != null) { - glsurf.requestRender(); - } - } - - /////////////////////////////////////////////////////////// - - // GL SurfaceView - - public class SurfaceViewGLES extends GLSurfaceView { - SurfaceHolder holder; - - public SurfaceViewGLES(Context context, SurfaceHolder holder) { - super(context); - this.holder = holder; - - // Check if the system supports OpenGL ES 2.0. - final ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo(); - final boolean supportsGLES2 = configurationInfo.reqGlEsVersion >= 0x20000; - - if (!supportsGLES2) { - throw new RuntimeException("OpenGL ES 2.0 is not supported by this device."); - } - - SurfaceHolder h = getHolder(); - h.addCallback(this); - - // Tells the default EGLContextFactory and EGLConfigChooser to create an GLES2 context. - setEGLContextClientVersion(PGLES.version); - setPreserveEGLContextOnPause(true); - - int samples = sketch.sketchSmooth(); - if (1 < samples) { - setEGLConfigChooser(getConfigChooser(samples)); - } else { - // use default EGL config chooser for now... -// setEGLConfigChooser(getConfigChooser(5, 6, 5, 4, 16, 1, samples)); - - // Some notes on how to choose an EGL configuration: - // https://github.com/mapbox/mapbox-gl-native/issues/574 - // http://malideveloper.arm.com/sample-code/selecting-the-correct-eglconfig/ - } - - - // The renderer can be set only once. - setRenderer(getRenderer()); - setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); - - setFocusable(true); - setFocusableInTouchMode(true); - requestFocus(); - - surfaceReady = false; // Will be ready when the surfaceCreated() event is called - } - - @Override - public SurfaceHolder getHolder() { - if (holder == null) { - return super.getHolder(); - } else { - return holder; - } - } - - public void dispose() { - super.destroyDrawingCache(); - super.onDetachedFromWindow(); - } - - - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - super.surfaceChanged(holder, format, w, h); - -// if (PApplet.DEBUG) { -// System.out.println("SketchSurfaceView3D.surfaceChanged() " + w + " " + h); -// } -// System.out.println("SketchSurfaceView3D.surfaceChanged() " + w + " " + h + " " + sketch); -// sketch.surfaceChanged(); - } - - @Override - public void surfaceCreated(SurfaceHolder holder) { - super.surfaceCreated(holder); - surfaceReady = true; - if (requestedThreadStart) { - startThread(); - } - if (PApplet.DEBUG) { - System.out.println("surfaceCreated()"); - } - } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - super.surfaceDestroyed(holder); - if (PApplet.DEBUG) { - System.out.println("surfaceDestroyed()"); - } - } - - - // Inform the view that the window focus has changed. - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - sketch.surfaceWindowFocusChanged(hasFocus); - } - - // Do we need these to capture events...? - @Override - public boolean onTouchEvent(MotionEvent event) { - boolean fullscreen = sketch.width == sketch.displayWidth && - sketch.height == sketch.displayHeight; - if (fullscreen && PApplet.SDK < 19) { - // The best we can do pre-KitKat to keep the navigation bar hidden - setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); - } - return sketch.surfaceTouchEvent(event); - } - - @Override - public boolean onKeyDown(int code, android.view.KeyEvent event) { - sketch.surfaceKeyDown(code, event); - return super.onKeyDown(code, event); - } - - @Override - public boolean onKeyUp(int code, android.view.KeyEvent event) { - sketch.surfaceKeyUp(code, event); - return super.onKeyUp(code, event); - } - } - - /////////////////////////////////////////////////////////// - - // Android specific classes (Renderer, ConfigChooser) - - - public RendererGLES getRenderer() { -// renderer = new AndroidRenderer(); -// return renderer; - return new RendererGLES(); - } - - - public ContextFactoryGLES getContextFactory() { - return new ContextFactoryGLES(); - } - - - public ConfigChooserGLES getConfigChooser(int samples) { - return new ConfigChooserGLES(5, 6, 5, 4, 16, 1, samples); -// return new AndroidConfigChooser(8, 8, 8, 8, 16, 8, samples); - } - - - public ConfigChooserGLES getConfigChooser(int r, int g, int b, int a, - int d, int s, int samples) { - return new ConfigChooserGLES(r, g, b, a, d, s, samples); - } - - - protected class RendererGLES implements Renderer { - - public RendererGLES() { - } - - @Override - public void onDrawFrame(GL10 igl) { - pgl.getGL(igl); - sketch.handleDraw(); - } - - @Override - public void onSurfaceChanged(GL10 igl, int iwidth, int iheight) { - if (PApplet.DEBUG) { - System.out.println("AndroidRenderer.onSurfaceChanged() " + iwidth + " " + iheight); - } - - pgl.getGL(igl); - - // Here is where we should initialize native libs... - // lib.init(iwidth, iheight); - -// sketch.surfaceChanged(); -// graphics.surfaceChanged(); -// -// sketch.setSize(iwidth, iheight); -// graphics.setSize(sketch.sketchWidth(), sketch.sketchHeight()); - sketch.surfaceChanged(); - sketch.setSize(iwidth, iheight); - } - - @Override - public void onSurfaceCreated(GL10 igl, EGLConfig config) { - pgl.init(igl); - } - } - - - protected class ContextFactoryGLES implements - GLSurfaceView.EGLContextFactory { - public EGLContext createContext(EGL10 egl, EGLDisplay display, - EGLConfig eglConfig) { - int[] attrib_list = { PGLES.EGL_CONTEXT_CLIENT_VERSION, PGLES.version, - EGL10.EGL_NONE }; - EGLContext context = egl.eglCreateContext(display, eglConfig, - EGL10.EGL_NO_CONTEXT, - attrib_list); - return context; - } - - public void destroyContext(EGL10 egl, EGLDisplay display, - EGLContext context) { - egl.eglDestroyContext(display, context); - } - } - - - protected class ConfigChooserGLES implements EGLConfigChooser { - // Desired size (in bits) for the rgba color, depth and stencil buffers. - public int redTarget; - public int greenTarget; - public int blueTarget; - public int alphaTarget; - public int depthTarget; - public int stencilTarget; - - // Actual rgba color, depth and stencil sizes (in bits) supported by the - // device. - public int redBits; - public int greenBits; - public int blueBits; - public int alphaBits; - public int depthBits; - public int stencilBits; - public int[] tempValue = new int[1]; - - public int numSamples; - - /* - The GLES2 extensions supported are: - GL_OES_rgb8_rgba8 GL_OES_depth24 GL_OES_vertex_half_float - GL_OES_texture_float GL_OES_texture_half_float - GL_OES_element_index_uint GL_OES_mapbuffer - GL_OES_fragment_precision_high GL_OES_compressed_ETC1_RGB8_texture - GL_OES_EGL_image GL_OES_required_internalformat GL_OES_depth_texture - GL_OES_get_program_binary GL_OES_packed_depth_stencil - GL_OES_standard_derivatives GL_OES_vertex_array_object GL_OES_egl_sync - GL_EXT_multi_draw_arrays GL_EXT_texture_format_BGRA8888 - GL_EXT_discard_framebuffer GL_EXT_shader_texture_lod - GL_IMG_shader_binary GL_IMG_texture_compression_pvrtc - GL_IMG_texture_stream2 GL_IMG_texture_npot - GL_IMG_texture_format_BGRA8888 GL_IMG_read_format - GL_IMG_program_binary GL_IMG_multisampled_render_to_texture - */ - - /* - // The attributes we want in the frame buffer configuration for Processing. - // For more details on other attributes, see: - // http://www.khronos.org/opengles/documentation/opengles1_0/html/eglChooseConfig.html - protected int[] configAttribsGL_MSAA = { - EGL10.EGL_RED_SIZE, 5, - EGL10.EGL_GREEN_SIZE, 6, - EGL10.EGL_BLUE_SIZE, 5, - EGL10.EGL_ALPHA_SIZE, 4, - EGL10.EGL_DEPTH_SIZE, 16, - EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL10.EGL_SAMPLE_BUFFERS, 1, - EGL10.EGL_SAMPLES, 2, - EGL10.EGL_NONE }; - - protected int[] configAttribsGL_CovMSAA = { - EGL10.EGL_RED_SIZE, 5, - EGL10.EGL_GREEN_SIZE, 6, - EGL10.EGL_BLUE_SIZE, 5, - EGL10.EGL_ALPHA_SIZE, 4, - EGL10.EGL_DEPTH_SIZE, 16, - EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_COVERAGE_BUFFERS_NV, 1, - EGL_COVERAGE_SAMPLES_NV, 2, - EGL10.EGL_NONE }; - - protected int[] configAttribsGL_NoMSAA = { - EGL10.EGL_RED_SIZE, 5, - EGL10.EGL_GREEN_SIZE, 6, - EGL10.EGL_BLUE_SIZE, 5, - EGL10.EGL_ALPHA_SIZE, 4, - EGL10.EGL_DEPTH_SIZE, 16, - EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL10.EGL_NONE }; - - protected int[] configAttribsGL_Good = { - EGL10.EGL_RED_SIZE, 8, - EGL10.EGL_GREEN_SIZE, 8, - EGL10.EGL_BLUE_SIZE, 8, - EGL10.EGL_ALPHA_SIZE, 8, - EGL10.EGL_DEPTH_SIZE, 16, - EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL10.EGL_NONE }; - - protected int[] configAttribsGL_TestMSAA = { - EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL10.EGL_SAMPLE_BUFFERS, 1, - EGL10.EGL_SAMPLES, 2, - EGL10.EGL_NONE }; - */ - - protected int[] attribsNoMSAA = { - EGL10.EGL_RENDERABLE_TYPE, PGLES.EGL_OPENGL_ES2_BIT, - EGL10.EGL_SAMPLE_BUFFERS, 0, - EGL10.EGL_NONE }; - - public ConfigChooserGLES(int rbits, int gbits, int bbits, int abits, - int dbits, int sbits, int samples) { - redTarget = rbits; - greenTarget = gbits; - blueTarget = bbits; - alphaTarget = abits; - depthTarget = dbits; - stencilTarget = sbits; - numSamples = samples; - } - - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { - EGLConfig[] configs = null; - if (1 < numSamples) { - int[] attribs = new int[] { - EGL10.EGL_RENDERABLE_TYPE, PGLES.EGL_OPENGL_ES2_BIT, - EGL10.EGL_SAMPLE_BUFFERS, 1, - EGL10.EGL_SAMPLES, numSamples, - EGL10.EGL_NONE }; - configs = chooseConfigWithAttribs(egl, display, attribs); - if (configs == null) { - // No normal multisampling config was found. Try to create a - // coverage multisampling configuration, for the nVidia Tegra2. - // See the EGL_NV_coverage_sample documentation. - int[] attribsCov = { - EGL10.EGL_RENDERABLE_TYPE, PGLES.EGL_OPENGL_ES2_BIT, - PGLES.EGL_COVERAGE_BUFFERS_NV, 1, - PGLES.EGL_COVERAGE_SAMPLES_NV, numSamples, - EGL10.EGL_NONE }; - configs = chooseConfigWithAttribs(egl, display, attribsCov); - if (configs == null) { - configs = chooseConfigWithAttribs(egl, display, attribsNoMSAA); - } else { - PGLES.usingMultisampling = true; - PGLES.usingCoverageMultisampling = true; - PGLES.multisampleCount = numSamples; - } - } else { - PGLES.usingMultisampling = true; - PGLES.usingCoverageMultisampling = false; - PGLES.multisampleCount = numSamples; - } - } else { - configs = chooseConfigWithAttribs(egl, display, attribsNoMSAA); - } - - if (configs == null) { - throw new IllegalArgumentException("No EGL configs match configSpec"); - } - - if (PApplet.DEBUG) { - for (EGLConfig config : configs) { - String configStr = "P3D - selected EGL config : " - + printConfig(egl, display, config); - System.out.println(configStr); - } - } - - // Now return the configuration that best matches the target one. - return chooseBestConfig(egl, display, configs); - } - - public EGLConfig chooseBestConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs) { - EGLConfig bestConfig = null; - float bestScore = Float.MAX_VALUE; - - for (EGLConfig config : configs) { - int gl = findConfigAttrib(egl, display, config, - EGL10.EGL_RENDERABLE_TYPE, 0); - boolean isGLES2 = (gl & PGLES.EGL_OPENGL_ES2_BIT) != 0; - if (isGLES2) { - int d = findConfigAttrib(egl, display, config, - EGL10.EGL_DEPTH_SIZE, 0); - int s = findConfigAttrib(egl, display, config, - EGL10.EGL_STENCIL_SIZE, 0); - - int r = findConfigAttrib(egl, display, config, - EGL10.EGL_RED_SIZE, 0); - int g = findConfigAttrib(egl, display, config, - EGL10.EGL_GREEN_SIZE, 0); - int b = findConfigAttrib(egl, display, config, - EGL10.EGL_BLUE_SIZE, 0); - int a = findConfigAttrib(egl, display, config, - EGL10.EGL_ALPHA_SIZE, 0); - - float score = 0.20f * PApplet.abs(r - redTarget) + - 0.20f * PApplet.abs(g - greenTarget) + - 0.20f * PApplet.abs(b - blueTarget) + - 0.15f * PApplet.abs(a - alphaTarget) + - 0.15f * PApplet.abs(d - depthTarget) + - 0.10f * PApplet.abs(s - stencilTarget); - - if (score < bestScore) { - // We look for the config closest to the target config. - // Closeness is measured by the score function defined above: - // we give more weight to the RGB components, followed by the - // alpha, depth and finally stencil bits. - bestConfig = config; - bestScore = score; - - redBits = r; - greenBits = g; - blueBits = b; - alphaBits = a; - depthBits = d; - stencilBits = s; - } - } - } - - if (PApplet.DEBUG) { - String configStr = "P3D - selected EGL config : " - + printConfig(egl, display, bestConfig); - System.out.println(configStr); - } - return bestConfig; - } - - protected String printConfig(EGL10 egl, EGLDisplay display, - EGLConfig config) { - int r = findConfigAttrib(egl, display, config, - EGL10.EGL_RED_SIZE, 0); - int g = findConfigAttrib(egl, display, config, - EGL10.EGL_GREEN_SIZE, 0); - int b = findConfigAttrib(egl, display, config, - EGL10.EGL_BLUE_SIZE, 0); - int a = findConfigAttrib(egl, display, config, - EGL10.EGL_ALPHA_SIZE, 0); - int d = findConfigAttrib(egl, display, config, - EGL10.EGL_DEPTH_SIZE, 0); - int s = findConfigAttrib(egl, display, config, - EGL10.EGL_STENCIL_SIZE, 0); - int type = findConfigAttrib(egl, display, config, - EGL10.EGL_RENDERABLE_TYPE, 0); - int nat = findConfigAttrib(egl, display, config, - EGL10.EGL_NATIVE_RENDERABLE, 0); - int bufSize = findConfigAttrib(egl, display, config, - EGL10.EGL_BUFFER_SIZE, 0); - int bufSurf = findConfigAttrib(egl, display, config, - EGL10.EGL_RENDER_BUFFER, 0); - - return String.format("EGLConfig rgba=%d%d%d%d depth=%d stencil=%d", - r,g,b,a,d,s) - + " type=" + type - + " native=" + nat - + " buffer size=" + bufSize - + " buffer surface=" + bufSurf + - String.format(" caveat=0x%04x", - findConfigAttrib(egl, display, config, - EGL10.EGL_CONFIG_CAVEAT, 0)); - } - - protected int findConfigAttrib(EGL10 egl, EGLDisplay display, - EGLConfig config, int attribute, int defaultValue) { - if (egl.eglGetConfigAttrib(display, config, attribute, tempValue)) { - return tempValue[0]; - } - return defaultValue; - } - - protected EGLConfig[] chooseConfigWithAttribs(EGL10 egl, - EGLDisplay display, - int[] configAttribs) { - // Get the number of minimally matching EGL configurations - int[] configCounts = new int[1]; - egl.eglChooseConfig(display, configAttribs, null, 0, configCounts); - - int count = configCounts[0]; - - if (count <= 0) { - //throw new IllegalArgumentException("No EGL configs match configSpec"); - return null; - } - - // Allocate then read the array of minimally matching EGL configs - EGLConfig[] configs = new EGLConfig[count]; - egl.eglChooseConfig(display, configAttribs, configs, count, configCounts); - return configs; - - // Get the number of minimally matching EGL configurations -// int[] num_config = new int[1]; -// egl.eglChooseConfig(display, configAttribsGL, null, 0, num_config); -// -// int numConfigs = num_config[0]; -// -// if (numConfigs <= 0) { -// throw new IllegalArgumentException("No EGL configs match configSpec"); -// } -// -// // Allocate then read the array of minimally matching EGL configs -// EGLConfig[] configs = new EGLConfig[numConfigs]; -// egl.eglChooseConfig(display, configAttribsGL, configs, numConfigs, -// num_config); - - } - } -} diff --git a/core/src/processing/opengl/Texture.java b/core/src/processing/opengl/Texture.java deleted file mode 100644 index 29d8ba4c5..000000000 --- a/core/src/processing/opengl/Texture.java +++ /dev/null @@ -1,1670 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import processing.core.PApplet; -import processing.core.PConstants; -import processing.core.PGraphics; -import processing.opengl.PGraphicsOpenGL.GLResourceTexture; - -import java.lang.reflect.Method; -import java.nio.ByteBuffer; -import java.nio.IntBuffer; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.NoSuchElementException; - -/** - * This class wraps an OpenGL texture. - * By Andres Colubri - * - */ -public class Texture implements PConstants { - /** - * Texture with normalized UV. - */ - protected static final int TEX2D = 0; - /** - * Texture with un-normalized UV. - */ - protected static final int TEXRECT = 1; - - /** Point sampling: both magnification and minification filtering are set - * to nearest */ - protected static final int POINT = 2; - /** Linear sampling: magnification filtering is nearest, minification set - * to linear */ - protected static final int LINEAR = 3; - /** Bilinear sampling: both magnification filtering is set to linear and - * minification either to linear-mipmap-nearest (linear interpolation is used - * within a mipmap, but not between different mipmaps). */ - protected static final int BILINEAR = 4; - /** Trilinear sampling: magnification filtering set to linear, minification to - * linear-mipmap-linear, which offers the best mipmap quality since linear - * interpolation to compute the value in each of two maps and then - * interpolates linearly between these two values. */ - protected static final int TRILINEAR = 5; - - - // This constant controls how many times pixelBuffer and rgbaPixels can be - // accessed before they are not released anymore. The idea is that if they - // have been used only a few times, it doesn't make sense to keep them around. - protected static final int MAX_UPDATES = 10; - - // The minimum amount of free JVM's memory (in MB) before pixelBuffer and - // rgbaPixels are released every time after they are used. - protected static final int MIN_MEMORY = 5; - - public int width, height; - - public int glName; - public int glTarget; - public int glFormat; - public int glMinFilter; - public int glMagFilter; - public int glWrapS; - public int glWrapT; - public int glWidth; - public int glHeight; - private GLResourceTexture glres; - - protected PGraphicsOpenGL pg; - protected PGL pgl; // The interface between Processing and OpenGL. - protected int context; // The context that created this texture. - protected boolean colorBuffer; // true if it is the color attachment of - // FrameBuffer object. - - protected boolean usingMipmaps; - protected boolean usingRepeat; - protected float maxTexcoordU; - protected float maxTexcoordV; - protected boolean bound; - - protected boolean invertedX; - protected boolean invertedY; - - protected int[] rgbaPixels = null; - protected IntBuffer pixelBuffer = null; - - protected int[] edgePixels = null; - protected IntBuffer edgeBuffer = null; - - protected FrameBuffer tempFbo = null; - protected int pixBufUpdateCount = 0; - protected int rgbaPixUpdateCount = 0; - - /** Modified portion of the texture */ - protected boolean modified; - protected int mx1, my1, mx2, my2; - - protected Object bufferSource; - protected LinkedList bufferCache = null; - protected LinkedList usedBuffers = null; - protected Method disposeBufferMethod; - public static final int MAX_BUFFER_CACHE_SIZE = 3; - - //////////////////////////////////////////////////////////// - - // Constructors. - - - public Texture(PGraphicsOpenGL pg) { - this.pg = pg; - pgl = pg.pgl; - context = pgl.createEmptyContext(); - - colorBuffer = false; - - glName = 0; - } - - - /** - * Creates an instance of PTexture with size width x height. The texture is - * initialized (empty) to that size. - * @param width int - * @param height int - */ - public Texture(PGraphicsOpenGL pg, int width, int height) { - this(pg, width, height, new Parameters()); - } - - - /** - * Creates an instance of PTexture with size width x height and with the - * specified parameters. The texture is initialized (empty) to that size. - * @param width int - * @param height int - * @param params Parameters - */ - public Texture(PGraphicsOpenGL pg, int width, int height, Object params) { - this.pg = pg; - pgl = pg.pgl; - context = pgl.createEmptyContext(); - - colorBuffer = false; - - glName = 0; - - init(width, height, (Parameters)params); - } - - - //////////////////////////////////////////////////////////// - - // Init, resize methods - - - /** - * Sets the size of the image and texture to width x height. If the texture is - * already initialized, it first destroys the current OpenGL texture object - * and then creates a new one with the specified size. - * @param width int - * @param height int - */ - public void init(int width, int height) { - Parameters params; - if (0 < glName) { - // Re-initializing a pre-existing texture. - // We use the current parameters as default: - params = getParameters(); - } else { - // Just built-in default parameters otherwise: - params = new Parameters(); - } - init(width, height, params); - } - - - /** - * Sets the size of the image and texture to width x height, and the - * parameters of the texture to params. If the texture is already initialized, - * it first destroys the current OpenGL texture object and then creates a new - * one with the specified size. - * @param width int - * @param height int - * @param params GLTextureParameters - */ - public void init(int width, int height, Parameters params) { - setParameters(params); - setSize(width, height); - allocate(); - } - - - /** - * Initializes the texture using GL parameters - */ - public void init(int width, int height, - int glName, int glTarget, int glFormat, - int glWidth, int glHeight, - int glMinFilter, int glMagFilter, - int glWrapS, int glWrapT) { - this.width = width; - this.height = height; - - this.glName = glName; - this.glTarget = glTarget; - this.glFormat = glFormat; - this.glWidth = glWidth; - this.glHeight = glHeight; - this.glMinFilter = glMinFilter; - this.glMagFilter = glMagFilter; - this.glWrapS = glWrapS; - this.glWrapT = glWrapT; - - maxTexcoordU = (float)width / glWidth; - maxTexcoordV = (float)height / glHeight; - - usingMipmaps = glMinFilter == PGL.LINEAR_MIPMAP_NEAREST || - glMinFilter == PGL.LINEAR_MIPMAP_LINEAR; - - usingRepeat = glWrapS == PGL.REPEAT || glWrapT == PGL.REPEAT; - } - - - public void resize(int wide, int high) { - // Disposing current resources. - dispose(); - - // Creating new texture with the appropriate size. - Texture tex = new Texture(pg, wide, high, getParameters()); - - // Copying the contents of this texture into tex. - tex.set(this); - - // Now, overwriting "this" with tex. - copyObject(tex); - - // Nullifying some utility objects so they are recreated with the - // appropriate size when needed. - tempFbo = null; - } - - - /** - * Returns true if the texture has been initialized. - * @return boolean - */ - public boolean available() { - return 0 < glName; - } - - - //////////////////////////////////////////////////////////// - - // Set methods - - - public void set(Texture tex) { - copyTexture(tex, 0, 0, tex.width, tex.height, true); - } - - - public void set(Texture tex, int x, int y, int w, int h) { - copyTexture(tex, x, y, w, h, true); - } - - - public void set(int texTarget, int texName, int texWidth, int texHeight, - int w, int h) { - copyTexture(texTarget, texName, texWidth, texHeight, 0, 0, w, h, true); - } - - - public void set(int texTarget, int texName, int texWidth, int texHeight, - int target, int tex, int x, int y, int w, int h) { - copyTexture(texTarget, texName, texWidth, texHeight, x, y, w, h, true); - } - - - public void set(int[] pixels) { - set(pixels, 0, 0, width, height, ARGB); - } - - - public void set(int[] pixels, int format) { - set(pixels, 0, 0, width, height, format); - } - - - public void set(int[] pixels, int x, int y, int w, int h) { - set(pixels, x, y, w, h, ARGB); - } - - - public void set(int[] pixels, int x, int y, int w, int h, int format) { - if (pixels == null) { - PGraphics.showWarning("The pixels array is null."); - return; - } - if (pixels.length < w * h) { - PGraphics.showWarning("The pixel array has a length of " + - pixels.length + ", but it should be at least " + - w * h); - return; - } - - if (pixels.length == 0 || w == 0 || h == 0) { - return; - } - - boolean enabledTex = false; - if (!pgl.texturingIsEnabled(glTarget)) { - pgl.enableTexturing(glTarget); - enabledTex = true; - } - pgl.bindTexture(glTarget, glName); - - loadPixels(w * h); - convertToRGBA(pixels, format, w, h); - if (invertedX) flipArrayOnX(rgbaPixels, 1); - if (invertedY) flipArrayOnY(rgbaPixels, 1); - updatePixelBuffer(rgbaPixels); - pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, - pixelBuffer); - fillEdges(x, y, w, h); - - if (usingMipmaps) { - if (PGraphicsOpenGL.autoMipmapGenSupported) { - pgl.generateMipmap(glTarget); - } else { - manualMipmap(); - } - } - - pgl.bindTexture(glTarget, 0); - if (enabledTex) { - pgl.disableTexturing(glTarget); - } - - releasePixelBuffer(); - releaseRGBAPixels(); - - updateTexels(x, y, w, h); - } - - - //////////////////////////////////////////////////////////// - - // Native set methods - - - public void setNative(int[] pixels) { - setNative(pixels, 0, 0, width, height); - } - - - public void setNative(int[] pixels, int x, int y, int w, int h) { - updatePixelBuffer(pixels); - setNative(pixelBuffer, x, y, w, h); - releasePixelBuffer(); - } - - - public void setNative(IntBuffer pixBuf, int x, int y, int w, int h) { - if (pixBuf == null) { - pixBuf = null; - PGraphics.showWarning("The pixel buffer is null."); - return; - } - if (pixBuf.capacity() < w * h) { - PGraphics.showWarning("The pixel bufer has a length of " + - pixBuf.capacity() + ", but it should be at least " + - w * h); - return; - } - - if (pixBuf.capacity() == 0) { - // Nothing to do (means that w == h == 0) but not an erroneous situation - return; - } - - boolean enabledTex = false; - if (!pgl.texturingIsEnabled(glTarget)) { - pgl.enableTexturing(glTarget); - enabledTex = true; - } - pgl.bindTexture(glTarget, glName); - - pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, - pixBuf); - fillEdges(x, y, w, h); - - if (usingMipmaps) { - if (PGraphicsOpenGL.autoMipmapGenSupported) { - pgl.generateMipmap(glTarget); - } else { - manualMipmap(); - } - } - pgl.bindTexture(glTarget, 0); - if (enabledTex) { - pgl.disableTexturing(glTarget); - } - - updateTexels(x, y, w, h); - } - - - //////////////////////////////////////////////////////////// - - // Get methods - - - /** - * Copy texture to pixels. Involves video memory to main memory transfer (slow). - */ - public void get(int[] pixels) { - if (pixels == null) { - throw new RuntimeException("Trying to copy texture to null pixels array"); - } - if (pixels.length != width * height) { - throw new RuntimeException("Trying to copy texture to pixels array of " + - "wrong size"); - } - - if (tempFbo == null) { - tempFbo = new FrameBuffer(pg, glWidth, glHeight); - } - - // Attaching the texture to the color buffer of a FBO, binding the FBO and - // reading the pixels from the current draw buffer (which is the color - // buffer of the FBO). - tempFbo.setColorBuffer(this); - pg.pushFramebuffer(); - pg.setFramebuffer(tempFbo); - tempFbo.readPixels(); - pg.popFramebuffer(); - - tempFbo.getPixels(pixels); - convertToARGB(pixels); - - if (invertedX) flipArrayOnX(pixels, 1); - if (invertedY) flipArrayOnY(pixels, 1); - } - - - //////////////////////////////////////////////////////////// - - // Put methods (the source texture is not resized to cover the entire - // destination). - - - public void put(Texture tex) { - copyTexture(tex, 0, 0, tex.width, tex.height, false); - } - - - public void put(Texture tex, int x, int y, int w, int h) { - copyTexture(tex, x, y, w, h, false); - } - - - public void put(int texTarget, int texName, int texWidth, int texHeight, - int w, int h) { - copyTexture(texTarget, texName, texWidth, texHeight, 0, 0, w, h, false); - } - - - public void put(int texTarget, int texName, int texWidth, int texHeight, - int target, int tex, int x, int y, int w, int h) { - copyTexture(texTarget, texName, texWidth, texHeight, x, y, w, h, false); - } - - - //////////////////////////////////////////////////////////// - - // Get OpenGL parameters - - - /** - * Returns true or false whether or not the texture is using mipmaps. - * @return boolean - */ - public boolean usingMipmaps() { - return usingMipmaps; - } - - - public void usingMipmaps(boolean mipmaps, int sampling) { - int glMagFilter0 = glMagFilter; - int glMinFilter0 = glMinFilter; - if (mipmaps) { - if (sampling == POINT) { - glMagFilter = PGL.NEAREST; - glMinFilter = PGL.NEAREST; - usingMipmaps = false; - } else if (sampling == LINEAR) { - glMagFilter = PGL.NEAREST; - glMinFilter = - PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR; - usingMipmaps = true; - } else if (sampling == BILINEAR) { - glMagFilter = PGL.LINEAR; - glMinFilter = - PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR; - usingMipmaps = true; - } else if (sampling == TRILINEAR) { - glMagFilter = PGL.LINEAR; - glMinFilter = - PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_LINEAR : PGL.LINEAR; - usingMipmaps = true; - } else { - throw new RuntimeException("Unknown texture filtering mode"); - } - } else { - usingMipmaps = false; - if (sampling == POINT) { - glMagFilter = PGL.NEAREST; - glMinFilter = PGL.NEAREST; - } else if (sampling == LINEAR) { - glMagFilter = PGL.NEAREST; - glMinFilter = PGL.LINEAR; - } else if (sampling == BILINEAR || sampling == TRILINEAR) { - glMagFilter = PGL.LINEAR; - glMinFilter = PGL.LINEAR; - } else { - throw new RuntimeException("Unknown texture filtering mode"); - } - } - - if (glMagFilter0 != glMagFilter || glMinFilter0 != glMinFilter) { - bind(); - pgl.texParameteri(glTarget, PGL.TEXTURE_MIN_FILTER, glMinFilter); - pgl.texParameteri(glTarget, PGL.TEXTURE_MAG_FILTER, glMagFilter); - if (usingMipmaps) { - if (PGraphicsOpenGL.autoMipmapGenSupported) { - pgl.generateMipmap(glTarget); - } else { - manualMipmap(); - } - } - unbind(); - } - } - - - /** - * Returns true or false whether or not the texture is using repeat wrap mode - * along either U or V directions. - * @return boolean - */ - public boolean usingRepeat() { - return usingRepeat; - } - - - public void usingRepeat(boolean repeat) { - if (repeat) { - glWrapS = PGL.REPEAT; - glWrapT = PGL.REPEAT; - usingRepeat = true; - } else { - glWrapS = PGL.CLAMP_TO_EDGE; - glWrapT = PGL.CLAMP_TO_EDGE; - usingRepeat = false; - } - - bind(); - pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_S, glWrapS); - pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_T, glWrapT); - unbind(); - } - - - /** - * Returns the maximum possible value for the texture coordinate U - * (horizontal). - * @return float - */ - public float maxTexcoordU() { - return maxTexcoordU; - } - - - /** - * Returns the maximum possible value for the texture coordinate V (vertical). - * @return float - */ - public float maxTexcoordV() { - return maxTexcoordV; - } - - - /** - * Returns true if the texture is inverted along the horizontal direction. - * @return boolean; - */ - public boolean invertedX() { - return invertedX; - } - - - /** - * Sets the texture as inverted or not along the horizontal direction. - * @param v boolean; - */ - public void invertedX(boolean v) { - invertedX = v; - } - - - /** - * Returns true if the texture is inverted along the vertical direction. - * @return boolean; - */ - public boolean invertedY() { - return invertedY; - } - - - /** - * Sets the texture as inverted or not along the vertical direction. - * @param v boolean; - */ - public void invertedY(boolean v) { - invertedY = v; - } - - - public int currentSampling() { - if (glMagFilter == PGL.NEAREST && glMinFilter == PGL.NEAREST) { - return POINT; - } else if (glMagFilter == PGL.NEAREST && - glMinFilter == (PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR)) { - return LINEAR; - } else if (glMagFilter == PGL.LINEAR && - glMinFilter == (PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR)) { - return BILINEAR; - } else if (glMagFilter == PGL.LINEAR && - glMinFilter == PGL.LINEAR_MIPMAP_LINEAR) { - return TRILINEAR; - } else { - return -1; - } - } - - //////////////////////////////////////////////////////////// - - // Bind/unbind - - - public void bind() { - // Binding a texture automatically enables texturing for the - // texture target from that moment onwards. Unbinding the texture - // won't disable texturing. - if (!pgl.texturingIsEnabled(glTarget)) { - pgl.enableTexturing(glTarget); - } - pgl.bindTexture(glTarget, glName); - bound = true; - } - - - public void unbind() { - if (pgl.textureIsBound(glTarget, glName)) { - // We don't want to unbind another texture - // that might be bound instead of this one. - if (!pgl.texturingIsEnabled(glTarget)) { - pgl.enableTexturing(glTarget); - pgl.bindTexture(glTarget, 0); - pgl.disableTexturing(glTarget); - } else { - pgl.bindTexture(glTarget, 0); - } - } - bound = false; - } - - - public boolean bound() { - // A true result might not necessarily mean that texturing is enabled - // (a texture can be bound to the target, but texturing is disabled). - return bound; - } - - - ////////////////////////////////////////////////////////////// - - // Modified flag - - - public boolean isModified() { - return modified; - } - - - public void setModified() { - modified = true; - } - - - public void setModified(boolean m) { - modified = m; - } - - - public int getModifiedX1() { - return mx1; - } - - - public int getModifiedX2() { - return mx2; - } - - - public int getModifiedY1() { - return my1; - } - - - public int getModifiedY2() { - return my2; - } - - - public void updateTexels() { - updateTexelsImpl(0, 0, width, height); - } - - - public void updateTexels(int x, int y, int w, int h) { - updateTexelsImpl(x, y, w, h); - } - - - protected void updateTexelsImpl(int x, int y, int w, int h) { - int x2 = x + w; - int y2 = y + h; - - if (!modified) { - mx1 = PApplet.max(0, x); - mx2 = PApplet.min(width - 1, x2); - my1 = PApplet.max(0, y); - my2 = PApplet.min(height - 1, y2); - modified = true; - - } else { - if (x < mx1) mx1 = PApplet.max(0, x); - if (x > mx2) mx2 = PApplet.min(width - 1, x); - if (y < my1) my1 = PApplet.max(0, y); - if (y > my2) my2 = y; - - if (x2 < mx1) mx1 = PApplet.max(0, x2); - if (x2 > mx2) mx2 = PApplet.min(width - 1, x2); - if (y2 < my1) my1 = PApplet.max(0, y2); - if (y2 > my2) my2 = PApplet.min(height - 1, y2); - } - } - - - protected void loadPixels(int len) { - if (rgbaPixels == null || rgbaPixels.length < len) { - rgbaPixels = new int[len]; - } - } - - - protected void updatePixelBuffer(int[] pixels) { - pixelBuffer = PGL.updateIntBuffer(pixelBuffer, pixels, true); - pixBufUpdateCount++; - } - - - protected void manualMipmap() { - // TODO: finish manual mipmap generation, - // https://github.com/processing/processing/issues/3335 - } - - - //////////////////////////////////////////////////////////// - - // Buffer sink interface. - - - public void setBufferSource(Object source) { - bufferSource = source; - getSourceMethods(); - } - - - public void copyBufferFromSource(Object natRef, ByteBuffer byteBuf, - int w, int h) { - if (bufferCache == null) { - bufferCache = new LinkedList(); - } - - if (bufferCache.size() + 1 <= MAX_BUFFER_CACHE_SIZE) { - bufferCache.add(new BufferData(natRef, byteBuf.asIntBuffer(), w, h)); - } else { - // The buffer cache reached the maximum size, so we just dispose - // the new buffer by adding it to the list of used buffers. - try { - usedBuffers.add(new BufferData(natRef, byteBuf.asIntBuffer(), w, h)); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - - public void disposeSourceBuffer() { - if (usedBuffers == null) return; - - while (0 < usedBuffers.size()) { - BufferData data = null; - try { - data = usedBuffers.remove(0); - } catch (NoSuchElementException ex) { - PGraphics.showWarning("Cannot remove used buffer"); - } - if (data != null) { - data.dispose(); - } - } - } - - public void getBufferPixels(int[] pixels) { - // We get the buffer either from the used buffers or the cache, giving - // priority to the used buffers. Why? Because the used buffer was already - // transferred to the texture, so the pixels should be in sync with the - // texture. - BufferData data = null; - if (usedBuffers != null && 0 < usedBuffers.size()) { - data = usedBuffers.getLast(); - } else if (bufferCache != null && 0 < bufferCache.size()) { - data = bufferCache.getLast(); - } - if (data != null) { - if ((data.w != width) || (data.h != height)) { - init(data.w, data.h); - } - - data.rgbBuf.rewind(); - data.rgbBuf.get(pixels); - convertToARGB(pixels); - - // In order to avoid a cached buffer to overwrite the texture when the - // renderer draws the texture, and hence put the pixels put of sync, we - // simply empty the cache. - if (usedBuffers == null) { - usedBuffers = new LinkedList(); - } - while (0 < bufferCache.size()) { - data = bufferCache.remove(0); - usedBuffers.add(data); - } - } - } - - - public boolean hasBufferSource() { - return bufferSource != null; - } - - - public boolean hasBuffers() { - return bufferSource != null && bufferCache != null && - 0 < bufferCache.size(); - } - - - protected boolean bufferUpdate() { - BufferData data = null; - try { - data = bufferCache.remove(0); - } catch (NoSuchElementException ex) { - PGraphics.showWarning("Don't have pixel data to copy to texture"); - } - - if (data != null) { - if ((data.w != width) || (data.h != height)) { - init(data.w, data.h); - } - data.rgbBuf.rewind(); - setNative(data.rgbBuf, 0, 0, width, height); - - // Putting the buffer in the used buffers list to dispose at the end of - // draw. - if (usedBuffers == null) { - usedBuffers = new LinkedList(); - } - usedBuffers.add(data); - - return true; - } else { - return false; - } - } - - - protected void getSourceMethods() { - try { - disposeBufferMethod = bufferSource.getClass(). - getMethod("disposeBuffer", new Class[] { Object.class }); - } catch (Exception e) { - throw new RuntimeException("Provided source object doesn't have a " + - "disposeBuffer method."); - } - } - - - //////////////////////////////////////////////////////////// - - // Utilities - - - /** - * Flips intArray along the X axis. - * @param intArray int[] - * @param mult int - */ - protected void flipArrayOnX(int[] intArray, int mult) { - int index = 0; - int xindex = mult * (width - 1); - for (int x = 0; x < width / 2; x++) { - for (int y = 0; y < height; y++) { - int i = index + mult * y * width; - int j = xindex + mult * y * width; - - for (int c = 0; c < mult; c++) { - int temp = intArray[i]; - intArray[i] = intArray[j]; - intArray[j] = temp; - - i++; - j++; - } - - } - index += mult; - xindex -= mult; - } - } - - - /** - * Flips intArray along the Y axis. - * @param intArray int[] - * @param mult int - */ - protected void flipArrayOnY(int[] intArray, int mult) { - int index = 0; - int yindex = mult * (height - 1) * width; - for (int y = 0; y < height / 2; y++) { - for (int x = 0; x < mult * width; x++) { - int temp = intArray[index]; - intArray[index] = intArray[yindex]; - intArray[yindex] = temp; - - index++; - yindex++; - } - yindex -= mult * width * 2; - } - } - - - /** - * Reorders a pixel array in the given format into the order required by - * OpenGL (RGBA) and stores it into rgbaPixels. The width and height - * parameters are used in the YUV420 to RBGBA conversion. - * @param pixels int[] - * @param format int - * @param w int - * @param h int - */ - protected void convertToRGBA(int[] pixels, int format, int w, int h) { - if (PGL.BIG_ENDIAN) { - switch (format) { - case ALPHA: - // Converting from xxxA into RGBA. RGB is set to white - // (0xFFFFFF, i.e.: (255, 255, 255)) - for (int i = 0; i< pixels.length; i++) { - rgbaPixels[i] = 0xFFFFFF00 | pixels[i]; - } - break; - case RGB: - // Converting xRGB into RGBA. A is set to 0xFF (255, full opacity). - for (int i = 0; i< pixels.length; i++) { - int pixel = pixels[i]; - rgbaPixels[i] = (pixel << 8) | 0xFF; - } - break; - case ARGB: - // Converting ARGB into RGBA. Shifting RGB to 8 bits to the left, - // and bringing A to the first byte. - for (int i = 0; i< pixels.length; i++) { - int pixel = pixels[i]; - rgbaPixels[i] = (pixel << 8) | ((pixel >> 24) & 0xFF); - } - break; - } - } else { - // LITTLE_ENDIAN - // ARGB native, and RGBA opengl means ABGR on windows - // for the most part just need to swap two components here - // the sun.cpu.endian here might be "false", oddly enough.. - // (that's why just using an "else", rather than check for "little") - switch (format) { - case ALPHA: - // Converting xxxA into ARGB, with RGB set to white. - for (int i = 0; i< pixels.length; i++) { - rgbaPixels[i] = (pixels[i] << 24) | 0x00FFFFFF; - } - break; - case RGB: - // We need to convert xRGB into ABGR, - // so R and B must be swapped, and the x just made 0xFF. - for (int i = 0; i< pixels.length; i++) { - int pixel = pixels[i]; - rgbaPixels[i] = 0xFF000000 | - ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16) | - (pixel & 0x0000FF00); - } - break; - case ARGB: - // We need to convert ARGB into ABGR, - // so R and B must be swapped, A and G just brought back in. - for (int i = 0; i < pixels.length; i++) { - int pixel = pixels[i]; - rgbaPixels[i] = ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16) | - (pixel & 0xFF00FF00); - } - break; - } - } - rgbaPixUpdateCount++; - } - - - /** - * Reorders an OpenGL pixel array (RGBA) into ARGB. The array must be - * of size width * height. - * @param pixels int[] - */ - protected void convertToARGB(int[] pixels) { - int t = 0; - int p = 0; - if (PGL.BIG_ENDIAN) { - // RGBA to ARGB conversion: shifting RGB 8 bits to the right, - // and placing A 24 bits to the left. - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int pixel = pixels[p++]; - pixels[t++] = (pixel >>> 8) | ((pixel << 24) & 0xFF000000); - } - } - } else { - // We have to convert ABGR into ARGB, so R and B must be swapped, - // A and G just brought back in. - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int pixel = pixels[p++]; - pixels[t++] = ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16) | - (pixel & 0xFF00FF00); - } - } - } - } - - - /////////////////////////////////////////////////////////// - - // Allocate/release texture. - - - protected void setSize(int w, int h) { - width = w; - height = h; - - if (PGraphicsOpenGL.npotTexSupported) { - glWidth = w; - glHeight = h; - } else { - glWidth = PGL.nextPowerOfTwo(w); - glHeight = PGL.nextPowerOfTwo(h); - } - - if (glWidth > PGraphicsOpenGL.maxTextureSize || - glHeight > PGraphicsOpenGL.maxTextureSize) { - glWidth = glHeight = 0; - throw new RuntimeException("Image width and height cannot be" + - " larger than " + - PGraphicsOpenGL.maxTextureSize + - " with this graphics card."); - } - - // If non-power-of-two textures are not supported, and the specified width - // or height is non-power-of-two, then glWidth (glHeight) will be greater - // than w (h) because it is chosen to be the next power of two, and this - // quotient will give the appropriate maximum texture coordinate value given - // this situation. - maxTexcoordU = (float)width / glWidth; - maxTexcoordV = (float)height / glHeight; - } - - - /** - * Allocates the opengl texture object. - */ - protected void allocate() { - dispose(); // Just in the case this object is being re-allocated. - - boolean enabledTex = false; - if (!pgl.texturingIsEnabled(glTarget)) { - pgl.enableTexturing(glTarget); - enabledTex = true; - } - - context = pgl.getCurrentContext(); - glres = new GLResourceTexture(this); - - pgl.bindTexture(glTarget, glName); - pgl.texParameteri(glTarget, PGL.TEXTURE_MIN_FILTER, glMinFilter); - pgl.texParameteri(glTarget, PGL.TEXTURE_MAG_FILTER, glMagFilter); - pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_S, glWrapS); - pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_T, glWrapT); - if (PGraphicsOpenGL.anisoSamplingSupported) { - pgl.texParameterf(glTarget, PGL.TEXTURE_MAX_ANISOTROPY, - PGraphicsOpenGL.maxAnisoAmount); - } - - // First, we use glTexImage2D to set the full size of the texture (glW/glH - // might be diff from w/h in the case that the GPU doesn't support NPOT - // textures) - pgl.texImage2D(glTarget, 0, glFormat, glWidth, glHeight, 0, - PGL.RGBA, PGL.UNSIGNED_BYTE, null); - - // Makes sure that the texture buffer in video memory doesn't contain - // any garbage. - pgl.initTexture(glTarget, PGL.RGBA, width, height); - - pgl.bindTexture(glTarget, 0); - if (enabledTex) { - pgl.disableTexturing(glTarget); - } - bound = false; - } - - - /** - * Marks the texture object for deletion. - */ - protected void dispose() { - if (glres != null) { - glres.dispose(); - glres = null; - glName = 0; - } - } - - - protected boolean contextIsOutdated() { - boolean outdated = !pgl.contextIsCurrent(context); - if (outdated) { - dispose(); - } - return outdated; - } - - - public void colorBuffer(boolean value) { - colorBuffer = value; - } - - - public boolean colorBuffer() { - return colorBuffer; - } - - - /////////////////////////////////////////////////////////// - - // Utilities. - - - // Copies source texture tex into this. - protected void copyTexture(Texture tex, int x, int y, int w, int h, - boolean scale) { - if (tex == null) { - throw new RuntimeException("Source texture is null"); - } - - if (tempFbo == null) { - tempFbo = new FrameBuffer(pg, glWidth, glHeight); - } - - // This texture is the color (destination) buffer of the FBO. - tempFbo.setColorBuffer(this); - tempFbo.disableDepthTest(); - - // FBO copy: - pg.pushFramebuffer(); - pg.setFramebuffer(tempFbo); - // Replaces anything that this texture might contain in the area being - // replaced by the new one. - pg.pushStyle(); - pg.blendMode(REPLACE); - if (scale) { - // Rendering tex into "this", and scaling the source rectangle - // to cover the entire destination region. - pgl.drawTexture(tex.glTarget, tex.glName, tex.glWidth, tex.glHeight, - 0, 0, tempFbo.width, tempFbo.height, 1, - x, y, x + w, y + h, 0, 0, width, height); - - } else { - // Rendering tex into "this" but without scaling so the contents - // of the source texture fall in the corresponding texels of the - // destination. - pgl.drawTexture(tex.glTarget, tex.glName, tex.glWidth, tex.glHeight, - 0, 0, tempFbo.width, tempFbo.height, 1, - x, y, x + w, y + h, x, y, x + w, y + h); - } - pgl.flush(); // Needed to make sure that the change in this texture is - // available immediately. - pg.popStyle(); - pg.popFramebuffer(); - updateTexels(x, y, w, h); - } - - - // Copies source texture tex into this. - protected void copyTexture(int texTarget, int texName, - int texWidth, int texHeight, - int x, int y, int w, int h, boolean scale) { - if (tempFbo == null) { - tempFbo = new FrameBuffer(pg, glWidth, glHeight); - } - - // This texture is the color (destination) buffer of the FBO. - tempFbo.setColorBuffer(this); - tempFbo.disableDepthTest(); - - // FBO copy: - pg.pushFramebuffer(); - pg.setFramebuffer(tempFbo); - // Replaces anything that this texture might contain in the area being - // replaced by the new one. - pg.pushStyle(); - pg.blendMode(REPLACE); - if (scale) { - // Rendering tex into "this", and scaling the source rectangle - // to cover the entire destination region. - pgl.drawTexture(texTarget, texName, texWidth, texHeight, - 0, 0, tempFbo.width, tempFbo.height, - x, y, w, h, 0, 0, width, height); - - } else { - // Rendering tex into "this" but without scaling so the contents - // of the source texture fall in the corresponding texels of the - // destination. - pgl.drawTexture(texTarget, texName, texWidth, texHeight, - 0, 0, tempFbo.width, tempFbo.height, - x, y, w, h, x, y, w, h); - } - pgl.flush(); // Needed to make sure that the change in this texture is - // available immediately. - pg.popStyle(); - pg.popFramebuffer(); - updateTexels(x, y, w, h); - } - - - protected void copyObject(Texture src) { - // The OpenGL texture of this object is replaced with the one from the - // source object, so we delete the former to avoid resource wasting. - dispose(); - - width = src.width; - height = src.height; - - glName = src.glName; - glTarget = src.glTarget; - glFormat = src.glFormat; - glMinFilter = src.glMinFilter; - glMagFilter = src.glMagFilter; - - glWidth= src.glWidth; - glHeight = src.glHeight; - - usingMipmaps = src.usingMipmaps; - usingRepeat = src.usingRepeat; - maxTexcoordU = src.maxTexcoordU; - maxTexcoordV = src.maxTexcoordV; - - invertedX = src.invertedX; - invertedY = src.invertedY; - } - - - // Releases the memory used by pixelBuffer either if the buffer hasn't been - // used many times yet, or if the JVM is running low in free memory. - protected void releasePixelBuffer() { - double freeMB = Runtime.getRuntime().freeMemory() / 1E6; - if (pixBufUpdateCount < MAX_UPDATES || freeMB < MIN_MEMORY) { - pixelBuffer = null; - } - } - - - // Releases the memory used by rgbaPixels either if the array hasn't been - // used many times yet, or if the JVM is running low in free memory. - protected void releaseRGBAPixels() { - double freeMB = Runtime.getRuntime().freeMemory() / 1E6; - if (rgbaPixUpdateCount < MAX_UPDATES || freeMB < MIN_MEMORY) { - rgbaPixels = null; - } - } - - - /////////////////////////////////////////////////////////// - - // Parameter handling - - - public Parameters getParameters() { - Parameters res = new Parameters(); - - if (glTarget == PGL.TEXTURE_2D) { - res.target = TEX2D; - } - - if (glFormat == PGL.RGB) { - res.format = RGB; - } else if (glFormat == PGL.RGBA) { - res.format = ARGB; - } else if (glFormat == PGL.ALPHA) { - res.format = ALPHA; - } - - if (glMagFilter == PGL.NEAREST && glMinFilter == PGL.NEAREST) { - res.sampling = POINT; - res.mipmaps = false; - } else if (glMagFilter == PGL.NEAREST && glMinFilter == PGL.LINEAR) { - res.sampling = LINEAR; - res.mipmaps = false; - } else if (glMagFilter == PGL.NEAREST && - glMinFilter == PGL.LINEAR_MIPMAP_NEAREST) { - res.sampling = LINEAR; - res.mipmaps = true; - } else if (glMagFilter == PGL.LINEAR && glMinFilter == PGL.LINEAR) { - res.sampling = BILINEAR; - res.mipmaps = false; - } else if (glMagFilter == PGL.LINEAR && - glMinFilter == PGL.LINEAR_MIPMAP_NEAREST) { - res.sampling = BILINEAR; - res.mipmaps = true; - } else if (glMagFilter == PGL.LINEAR && - glMinFilter == PGL.LINEAR_MIPMAP_LINEAR) { - res.sampling = TRILINEAR; - res.mipmaps = true; - } - - if (glWrapS == PGL.CLAMP_TO_EDGE) { - res.wrapU = CLAMP; - } else if (glWrapS == PGL.REPEAT) { - res.wrapU = REPEAT; - } - - if (glWrapT == PGL.CLAMP_TO_EDGE) { - res.wrapV = CLAMP; - } else if (glWrapT == PGL.REPEAT) { - res.wrapV = REPEAT; - } - - return res; - } - - - /** - * Sets texture target and internal format according to the target and - * type specified. - * @param target int - * @param params GLTextureParameters - */ - protected void setParameters(Parameters params) { - if (params.target == TEX2D) { - glTarget = PGL.TEXTURE_2D; - } else { - throw new RuntimeException("Unknown texture target"); - } - - if (params.format == RGB) { - glFormat = PGL.RGB; - } else if (params.format == ARGB) { - glFormat = PGL.RGBA; - } else if (params.format == ALPHA) { - glFormat = PGL.ALPHA; - } else { - throw new RuntimeException("Unknown texture format"); - } - - boolean mipmaps = params.mipmaps && PGL.MIPMAPS_ENABLED; - if (mipmaps && !PGraphicsOpenGL.autoMipmapGenSupported) { - PGraphics.showWarning("Mipmaps were requested but automatic mipmap " + - "generation is not supported and manual " + - "generation still not implemented, so mipmaps " + - "will be disabled."); - mipmaps = false; - } - - if (params.sampling == POINT) { - glMagFilter = PGL.NEAREST; - glMinFilter = PGL.NEAREST; - } else if (params.sampling == LINEAR) { - glMagFilter = PGL.NEAREST; - glMinFilter = mipmaps ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR; - } else if (params.sampling == BILINEAR) { - glMagFilter = PGL.LINEAR; - glMinFilter = mipmaps ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR; - } else if (params.sampling == TRILINEAR) { - glMagFilter = PGL.LINEAR; - glMinFilter = mipmaps ? PGL.LINEAR_MIPMAP_LINEAR : PGL.LINEAR; - } else { - throw new RuntimeException("Unknown texture filtering mode"); - } - - if (params.wrapU == CLAMP) { - glWrapS = PGL.CLAMP_TO_EDGE; - } else if (params.wrapU == REPEAT) { - glWrapS = PGL.REPEAT; - } else { - throw new RuntimeException("Unknown wrapping mode"); - } - - if (params.wrapV == CLAMP) { - glWrapT = PGL.CLAMP_TO_EDGE; - } else if (params.wrapV == REPEAT) { - glWrapT = PGL.REPEAT; - } else { - throw new RuntimeException("Unknown wrapping mode"); - } - - usingMipmaps = glMinFilter == PGL.LINEAR_MIPMAP_NEAREST || - glMinFilter == PGL.LINEAR_MIPMAP_LINEAR; - - usingRepeat = glWrapS == PGL.REPEAT || glWrapT == PGL.REPEAT; - - invertedX = false; - invertedY = false; - } - - - protected void fillEdges(int x, int y, int w, int h) { - if ((width < glWidth || height < glHeight) && (x + w == width || y + h == height)) { - if (x + w == width) { - int ew = glWidth - width; - edgePixels = new int[h * ew]; - for (int i = 0; i < h; i++) { - int c = rgbaPixels[i * w + (w - 1)]; - Arrays.fill(edgePixels, i * ew, (i + 1) * ew, c); - } - edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true); - pgl.texSubImage2D(glTarget, 0, width, y, ew, h, PGL.RGBA, - PGL.UNSIGNED_BYTE, edgeBuffer); - } - - if (y + h == height) { - int eh = glHeight - height; - edgePixels = new int[eh * w]; - for (int i = 0; i < eh; i++) { - System.arraycopy(rgbaPixels, (h - 1) * w, edgePixels, i * w, w); - } - edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true); - pgl.texSubImage2D(glTarget, 0, x, height, w, eh, PGL.RGBA, - PGL.UNSIGNED_BYTE, edgeBuffer); - } - - if (x + w == width && y + h == height) { - int ew = glWidth - width; - int eh = glHeight - height; - int c = rgbaPixels[w * h - 1]; - edgePixels = new int[eh * ew]; - Arrays.fill(edgePixels, 0, eh * ew, c); - edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true); - pgl.texSubImage2D(glTarget, 0, width, height, ew, eh, PGL.RGBA, - PGL.UNSIGNED_BYTE, edgeBuffer); - } - } - } - - /////////////////////////////////////////////////////////////////////////// - - // Parameters object - - - /** - * This class stores the parameters for a texture: target, internal format, - * minimization filter and magnification filter. - */ - static public class Parameters { - /** - * Texture target. - */ - public int target; - - /** - * Texture internal format. - */ - public int format; - - /** - * Texture filtering (POINT, LINEAR, BILINEAR or TRILINEAR). - */ - public int sampling; - - /** - * Use mipmaps or not. - */ - public boolean mipmaps; - - /** - * Wrapping mode along U. - */ - public int wrapU; - - /** - * Wrapping mode along V. - */ - public int wrapV; - - /** - * Sets all the parameters to default values. - */ - public Parameters() { - this.target = TEX2D; - this.format = ARGB; - this.sampling = BILINEAR; - this.mipmaps = true; - this.wrapU = CLAMP; - this.wrapV = CLAMP; - } - - public Parameters(int format) { - this.target = TEX2D; - this.format = format; - this.sampling = BILINEAR; - this.mipmaps = true; - this.wrapU = CLAMP; - this.wrapV = CLAMP; - } - - public Parameters(int format, int sampling) { - this.target = TEX2D; - this.format = format; - this.sampling = sampling; - this.mipmaps = true; - this.wrapU = CLAMP; - this.wrapV = CLAMP; - } - - public Parameters(int format, int sampling, boolean mipmaps) { - this.target = TEX2D; - this.format = format; - this.mipmaps = mipmaps; - if (sampling == TRILINEAR && !mipmaps) { - this.sampling = BILINEAR; - } else { - this.sampling = sampling; - } - this.wrapU = CLAMP; - this.wrapV = CLAMP; - } - - public Parameters(int format, int sampling, boolean mipmaps, int wrap) { - this.target = TEX2D; - this.format = format; - this.mipmaps = mipmaps; - if (sampling == TRILINEAR && !mipmaps) { - this.sampling = BILINEAR; - } else { - this.sampling = sampling; - } - this.wrapU = wrap; - this.wrapV = wrap; - } - - public Parameters(Parameters src) { - set(src); - } - - public void set(int format) { - this.format = format; - } - - public void set(int format, int sampling) { - this.format = format; - this.sampling = sampling; - } - - public void set(int format, int sampling, boolean mipmaps) { - this.format = format; - this.sampling = sampling; - this.mipmaps = mipmaps; - } - - public void set(Parameters src) { - this.target = src.target; - this.format = src.format; - this.sampling = src.sampling; - this.mipmaps = src.mipmaps; - this.wrapU = src.wrapU; - this.wrapV = src.wrapV; - } - } - - /** - * This class stores a buffer copied from the buffer source. - * - */ - protected class BufferData { - int w, h; - // Native buffer object. - Object natBuf; - // Buffer viewed as int. - IntBuffer rgbBuf; - - BufferData(Object nat, IntBuffer rgb, int w, int h) { - natBuf = nat; - rgbBuf = rgb; - this.w = w; - this.h = h; - } - - void dispose() { - try { - // Disposing the native buffer. - disposeBufferMethod.invoke(bufferSource, new Object[] { natBuf }); - natBuf = null; - rgbBuf = null; - } catch (Exception e) { - e.printStackTrace(); - } - } - } -} \ No newline at end of file diff --git a/core/src/processing/opengl/VertexBuffer.java b/core/src/processing/opengl/VertexBuffer.java deleted file mode 100644 index 114428b03..000000000 --- a/core/src/processing/opengl/VertexBuffer.java +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import processing.opengl.PGraphicsOpenGL.GLResourceVertexBuffer; - -// TODO: need to combine with PGraphicsOpenGL.VertexAttribute -public class VertexBuffer { - static protected final int INIT_VERTEX_BUFFER_SIZE = 256; - static protected final int INIT_INDEX_BUFFER_SIZE = 512; - - public int glId; - int target; - int elementSize; - int ncoords; - boolean index; - - protected PGL pgl; // The interface between Processing and OpenGL. - protected int context; // The context that created this texture. - private GLResourceVertexBuffer glres; - - VertexBuffer(PGraphicsOpenGL pg, int target, int ncoords, int esize) { - this(pg, target, ncoords, esize, false); - } - - VertexBuffer(PGraphicsOpenGL pg, int target, int ncoords, int esize, boolean index) { - pgl = pg.pgl; - context = pgl.createEmptyContext(); - - this.target = target; - this.ncoords = ncoords; - this.elementSize = esize; - this.index = index; - create(); - init(); - } - - protected void create() { - context = pgl.getCurrentContext(); - glres = new GLResourceVertexBuffer(this); - } - - protected void init() { - int size = index ? ncoords * INIT_INDEX_BUFFER_SIZE * elementSize : - ncoords * INIT_VERTEX_BUFFER_SIZE * elementSize; - pgl.bindBuffer(target, glId); - pgl.bufferData(target, size, null, PGL.STATIC_DRAW); - } - - protected void dispose() { - if (glres != null) { - glres.dispose(); - glId = 0; - glres = null; - } - } - - protected boolean contextIsOutdated() { - boolean outdated = !pgl.contextIsCurrent(context); - if (outdated) { - dispose(); - } - return outdated; - } - -} diff --git a/core/src/processing/opengl/tess/ActiveRegion.java b/core/src/processing/opengl/tess/ActiveRegion.java deleted file mode 100644 index 6699923fc..000000000 --- a/core/src/processing/opengl/tess/ActiveRegion.java +++ /dev/null @@ -1,70 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class ActiveRegion { - GLUhalfEdge eUp; /* upper edge, directed right to left */ - DictNode nodeUp; /* dictionary node corresponding to eUp */ - int windingNumber; /* used to determine which regions are - * inside the polygon */ - boolean inside; /* is this region inside the polygon? */ - boolean sentinel; /* marks fake edges at t = +/-infinity */ - boolean dirty; /* marks regions where the upper or lower - * edge has changed, but we haven't checked - * whether they intersect yet */ - boolean fixUpperEdge; /* marks temporary edges introduced when - * we process a "right vertex" (one without - * any edges leaving to the right) */ -} diff --git a/core/src/processing/opengl/tess/CachedVertex.java b/core/src/processing/opengl/tess/CachedVertex.java deleted file mode 100644 index 327960ca0..000000000 --- a/core/src/processing/opengl/tess/CachedVertex.java +++ /dev/null @@ -1,60 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class CachedVertex { - public double[] coords = new double[3]; - public Object data; -} diff --git a/core/src/processing/opengl/tess/Dict.java b/core/src/processing/opengl/tess/Dict.java deleted file mode 100644 index a1c04ea9d..000000000 --- a/core/src/processing/opengl/tess/Dict.java +++ /dev/null @@ -1,142 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class Dict { - DictNode head; - Object frame; - DictLeq leq; - - private Dict() { - } - - static Dict dictNewDict(Object frame, DictLeq leq) { - Dict dict = new Dict(); - dict.head = new DictNode(); - - dict.head.key = null; - dict.head.next = dict.head; - dict.head.prev = dict.head; - - dict.frame = frame; - dict.leq = leq; - - return dict; - } - - static void dictDeleteDict(Dict dict) { - dict.head = null; - dict.frame = null; - dict.leq = null; - } - - static DictNode dictInsert(Dict dict, Object key) { - return dictInsertBefore(dict, dict.head, key); - } - - static DictNode dictInsertBefore(Dict dict, DictNode node, Object key) { - do { - node = node.prev; - } while (node.key != null && !dict.leq.leq(dict.frame, node.key, key)); - - DictNode newNode = new DictNode(); - newNode.key = key; - newNode.next = node.next; - node.next.prev = newNode; - newNode.prev = node; - node.next = newNode; - - return newNode; - } - - static Object dictKey(DictNode aNode) { - return aNode.key; - } - - static DictNode dictSucc(DictNode aNode) { - return aNode.next; - } - - static DictNode dictPred(DictNode aNode) { - return aNode.prev; - } - - static DictNode dictMin(Dict aDict) { - return aDict.head.next; - } - - static DictNode dictMax(Dict aDict) { - return aDict.head.prev; - } - - static void dictDelete(Dict dict, DictNode node) { - node.next.prev = node.prev; - node.prev.next = node.next; - } - - static DictNode dictSearch(Dict dict, Object key) { - DictNode node = dict.head; - - do { - node = node.next; - } while (node.key != null && !(dict.leq.leq(dict.frame, key, node.key))); - - return node; - } - - public interface DictLeq { - boolean leq(Object frame, Object key1, Object key2); - } -} diff --git a/core/src/processing/opengl/tess/DictNode.java b/core/src/processing/opengl/tess/DictNode.java deleted file mode 100644 index 0e1451ef5..000000000 --- a/core/src/processing/opengl/tess/DictNode.java +++ /dev/null @@ -1,61 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class DictNode { - Object key; - DictNode next; - DictNode prev; -} diff --git a/core/src/processing/opengl/tess/GLUface.java b/core/src/processing/opengl/tess/GLUface.java deleted file mode 100644 index 99afc1c4e..000000000 --- a/core/src/processing/opengl/tess/GLUface.java +++ /dev/null @@ -1,66 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class GLUface { - public GLUface next; /* next face (never NULL) */ - public GLUface prev; /* previous face (never NULL) */ - public GLUhalfEdge anEdge; /* a half edge with this left face */ - public Object data; /* room for client's data */ - - /* Internal data (keep hidden) */ - public GLUface trail; /* "stack" for conversion to strips */ - public boolean marked; /* flag for conversion to strips */ - public boolean inside; /* this face is in the polygon interior */ -} diff --git a/core/src/processing/opengl/tess/GLUhalfEdge.java b/core/src/processing/opengl/tess/GLUhalfEdge.java deleted file mode 100644 index 53d8bd51a..000000000 --- a/core/src/processing/opengl/tess/GLUhalfEdge.java +++ /dev/null @@ -1,72 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class GLUhalfEdge { - public GLUhalfEdge next; /* doubly-linked list (prev==Sym->next) */ - public GLUhalfEdge Sym; /* same edge, opposite direction */ - public GLUhalfEdge Onext; /* next edge CCW around origin */ - public GLUhalfEdge Lnext; /* next edge CCW around left face */ - public GLUvertex Org; /* origin vertex (Overtex too long) */ - public GLUface Lface; /* left face */ - - /* Internal data (keep hidden) */ - public ActiveRegion activeRegion; /* a region with this upper edge (sweep.c) */ - public int winding; /* change in winding number when crossing */ - public boolean first; - - public GLUhalfEdge(boolean first) { - this.first = first; - } -} diff --git a/core/src/processing/opengl/tess/GLUmesh.java b/core/src/processing/opengl/tess/GLUmesh.java deleted file mode 100644 index fecee0a75..000000000 --- a/core/src/processing/opengl/tess/GLUmesh.java +++ /dev/null @@ -1,63 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. - -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class GLUmesh { - GLUvertex vHead = new GLUvertex(); /* dummy header for vertex list */ - GLUface fHead = new GLUface(); /* dummy header for face list */ - GLUhalfEdge eHead = new GLUhalfEdge(true); /* dummy header for edge list */ - GLUhalfEdge eHeadSym = new GLUhalfEdge(false); /* and its symmetric counterpart */ -} diff --git a/core/src/processing/opengl/tess/GLUtessellatorImpl.java b/core/src/processing/opengl/tess/GLUtessellatorImpl.java deleted file mode 100644 index 072877f9c..000000000 --- a/core/src/processing/opengl/tess/GLUtessellatorImpl.java +++ /dev/null @@ -1,645 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - - -public class GLUtessellatorImpl implements PGLUtessellator { - public static final int TESS_MAX_CACHE = 100; - - private int state; /* what begin/end calls have we seen? */ - - private GLUhalfEdge lastEdge; /* lastEdge->Org is the most recent vertex */ - GLUmesh mesh; /* stores the input contours, and eventually - the tessellation itself */ - - /*** state needed for projecting onto the sweep plane ***/ - - double[] normal = new double[3]; /* user-specified normal (if provided) */ - double[] sUnit = new double[3]; /* unit vector in s-direction (debugging) */ - double[] tUnit = new double[3]; /* unit vector in t-direction (debugging) */ - - /*** state needed for the line sweep ***/ - - private double relTolerance; /* tolerance for merging features */ - int windingRule; /* rule for determining polygon interior */ - boolean fatalError; /* fatal error: needed combine callback */ - - Dict dict; /* edge dictionary for sweep line */ - PriorityQ pq; /* priority queue of vertex events */ - GLUvertex event; /* current sweep event being processed */ - - /*** state needed for rendering callbacks (see render.c) ***/ - - boolean flagBoundary; /* mark boundary edges (use EdgeFlag) */ - boolean boundaryOnly; /* Extract contours, not triangles */ - boolean avoidDegenerateTris; /* JOGL-specific hint to try to improve triangulation - by avoiding producing degenerate (zero-area) triangles; - has not been tested exhaustively and is therefore an option */ - - GLUface lonelyTriList; - /* list of triangles which could not be rendered as strips or fans */ - - - - /*** state needed to cache single-contour polygons for renderCache() */ - - private boolean flushCacheOnNextVertex; /* empty cache on next vertex() call */ - int cacheCount; /* number of cached vertices */ - CachedVertex[] cache = new CachedVertex[TESS_MAX_CACHE]; /* the vertex data */ - - /*** rendering callbacks that also pass polygon data ***/ - private Object polygonData; /* client data for current polygon */ - - private PGLUtessellatorCallback callBegin; - private PGLUtessellatorCallback callEdgeFlag; - private PGLUtessellatorCallback callVertex; - private PGLUtessellatorCallback callEnd; -// private GLUtessellatorCallback callMesh; - private PGLUtessellatorCallback callError; - private PGLUtessellatorCallback callCombine; - - private PGLUtessellatorCallback callBeginData; - private PGLUtessellatorCallback callEdgeFlagData; - private PGLUtessellatorCallback callVertexData; - private PGLUtessellatorCallback callEndData; -// private GLUtessellatorCallback callMeshData; - private PGLUtessellatorCallback callErrorData; - private PGLUtessellatorCallback callCombineData; - - private static final double GLU_TESS_DEFAULT_TOLERANCE = 0.0; -// private static final int GLU_TESS_MESH = 100112; /* void (*)(GLUmesh *mesh) */ - private static PGLUtessellatorCallback NULL_CB = new PGLUtessellatorCallbackAdapter(); - -// #define MAX_FAST_ALLOC (MAX(sizeof(EdgePair), \ -// MAX(sizeof(GLUvertex),sizeof(GLUface)))) - - private GLUtessellatorImpl() { - state = TessState.T_DORMANT; - - normal[0] = 0; - normal[1] = 0; - normal[2] = 0; - - relTolerance = GLU_TESS_DEFAULT_TOLERANCE; - windingRule = PGLU.GLU_TESS_WINDING_ODD; - flagBoundary = false; - boundaryOnly = false; - - callBegin = NULL_CB; - callEdgeFlag = NULL_CB; - callVertex = NULL_CB; - callEnd = NULL_CB; - callError = NULL_CB; - callCombine = NULL_CB; -// callMesh = NULL_CB; - - callBeginData = NULL_CB; - callEdgeFlagData = NULL_CB; - callVertexData = NULL_CB; - callEndData = NULL_CB; - callErrorData = NULL_CB; - callCombineData = NULL_CB; - - polygonData = null; - - for (int i = 0; i < cache.length; i++) { - cache[i] = new CachedVertex(); - } - } - - static public PGLUtessellator gluNewTess() - { - return new GLUtessellatorImpl(); - } - - - private void makeDormant() { - /* Return the tessellator to its original dormant state. */ - - if (mesh != null) { - Mesh.__gl_meshDeleteMesh(mesh); - } - state = TessState.T_DORMANT; - lastEdge = null; - mesh = null; - } - - private void requireState(int newState) { - if (state != newState) gotoState(newState); - } - - private void gotoState(int newState) { - while (state != newState) { - /* We change the current state one level at a time, to get to - * the desired state. - */ - if (state < newState) { - if (state == TessState.T_DORMANT) { - callErrorOrErrorData(PGLU.GLU_TESS_MISSING_BEGIN_POLYGON); - gluTessBeginPolygon(null); - } else if (state == TessState.T_IN_POLYGON) { - callErrorOrErrorData(PGLU.GLU_TESS_MISSING_BEGIN_CONTOUR); - gluTessBeginContour(); - } - } else { - if (state == TessState.T_IN_CONTOUR) { - callErrorOrErrorData(PGLU.GLU_TESS_MISSING_END_CONTOUR); - gluTessEndContour(); - } else if (state == TessState.T_IN_POLYGON) { - callErrorOrErrorData(PGLU.GLU_TESS_MISSING_END_POLYGON); - /* gluTessEndPolygon( tess ) is too much work! */ - makeDormant(); - } - } - } - } - - public void gluDeleteTess() { - requireState(TessState.T_DORMANT); - } - - public void gluTessProperty(int which, double value) { - switch (which) { - case PGLU.GLU_TESS_TOLERANCE: - if (value < 0.0 || value > 1.0) break; - relTolerance = value; - return; - - case PGLU.GLU_TESS_WINDING_RULE: - int windingRule = (int) value; - if (windingRule != value) break; /* not an integer */ - - switch (windingRule) { - case PGLU.GLU_TESS_WINDING_ODD: - case PGLU.GLU_TESS_WINDING_NONZERO: - case PGLU.GLU_TESS_WINDING_POSITIVE: - case PGLU.GLU_TESS_WINDING_NEGATIVE: - case PGLU.GLU_TESS_WINDING_ABS_GEQ_TWO: - this.windingRule = windingRule; - return; - default: - break; - } - - case PGLU.GLU_TESS_BOUNDARY_ONLY: - boundaryOnly = (value != 0); - return; - - case PGLU.GLU_TESS_AVOID_DEGENERATE_TRIANGLES: - avoidDegenerateTris = (value != 0); - return; - - default: - callErrorOrErrorData(PGLU.GLU_INVALID_ENUM); - return; - } - callErrorOrErrorData(PGLU.GLU_INVALID_VALUE); - } - -/* Returns tessellator property */ - public void gluGetTessProperty(int which, double[] value, int value_offset) { - switch (which) { - case PGLU.GLU_TESS_TOLERANCE: -/* tolerance should be in range [0..1] */ - assert (0.0 <= relTolerance && relTolerance <= 1.0); - value[value_offset] = relTolerance; - break; - case PGLU.GLU_TESS_WINDING_RULE: - assert (windingRule == PGLU.GLU_TESS_WINDING_ODD || - windingRule == PGLU.GLU_TESS_WINDING_NONZERO || - windingRule == PGLU.GLU_TESS_WINDING_POSITIVE || - windingRule == PGLU.GLU_TESS_WINDING_NEGATIVE || - windingRule == PGLU.GLU_TESS_WINDING_ABS_GEQ_TWO); - value[value_offset] = windingRule; - break; - case PGLU.GLU_TESS_BOUNDARY_ONLY: - assert (boundaryOnly == true || boundaryOnly == false); - value[value_offset] = boundaryOnly ? 1 : 0; - break; - case PGLU.GLU_TESS_AVOID_DEGENERATE_TRIANGLES: - value[value_offset] = avoidDegenerateTris ? 1 : 0; - break; - default: - value[value_offset] = 0.0; - callErrorOrErrorData(PGLU.GLU_INVALID_ENUM); - break; - } - } /* gluGetTessProperty() */ - - public void gluTessNormal(double x, double y, double z) { - normal[0] = x; - normal[1] = y; - normal[2] = z; - } - - public void gluTessCallback(int which, PGLUtessellatorCallback aCallback) { - switch (which) { - case PGLU.GLU_TESS_BEGIN: - callBegin = aCallback == null ? NULL_CB : aCallback; - return; - case PGLU.GLU_TESS_BEGIN_DATA: - callBeginData = aCallback == null ? NULL_CB : aCallback; - return; - case PGLU.GLU_TESS_EDGE_FLAG: - callEdgeFlag = aCallback == null ? NULL_CB : aCallback; -/* If the client wants boundary edges to be flagged, - * we render everything as separate triangles (no strips or fans). - */ - flagBoundary = aCallback != null; - return; - case PGLU.GLU_TESS_EDGE_FLAG_DATA: - callEdgeFlagData = callBegin = aCallback == null ? NULL_CB : aCallback; -/* If the client wants boundary edges to be flagged, - * we render everything as separate triangles (no strips or fans). - */ - flagBoundary = (aCallback != null); - return; - case PGLU.GLU_TESS_VERTEX: - callVertex = aCallback == null ? NULL_CB : aCallback; - return; - case PGLU.GLU_TESS_VERTEX_DATA: - callVertexData = aCallback == null ? NULL_CB : aCallback; - return; - case PGLU.GLU_TESS_END: - callEnd = aCallback == null ? NULL_CB : aCallback; - return; - case PGLU.GLU_TESS_END_DATA: - callEndData = aCallback == null ? NULL_CB : aCallback; - return; - case PGLU.GLU_TESS_ERROR: - callError = aCallback == null ? NULL_CB : aCallback; - return; - case PGLU.GLU_TESS_ERROR_DATA: - callErrorData = aCallback == null ? NULL_CB : aCallback; - return; - case PGLU.GLU_TESS_COMBINE: - callCombine = aCallback == null ? NULL_CB : aCallback; - return; - case PGLU.GLU_TESS_COMBINE_DATA: - callCombineData = aCallback == null ? NULL_CB : aCallback; - return; -// case GLU_TESS_MESH: -// callMesh = aCallback == null ? NULL_CB : aCallback; -// return; - default: - callErrorOrErrorData(PGLU.GLU_INVALID_ENUM); - return; - } - } - - private boolean addVertex(double[] coords, Object vertexData) { - GLUhalfEdge e; - - e = lastEdge; - if (e == null) { -/* Make a self-loop (one vertex, one edge). */ - - e = Mesh.__gl_meshMakeEdge(mesh); - if (e == null) return false; - if (!Mesh.__gl_meshSplice(e, e.Sym)) return false; - } else { -/* Create a new vertex and edge which immediately follow e - * in the ordering around the left face. - */ - if (Mesh.__gl_meshSplitEdge(e) == null) return false; - e = e.Lnext; - } - -/* The new vertex is now e.Org. */ - e.Org.data = vertexData; - e.Org.coords[0] = coords[0]; - e.Org.coords[1] = coords[1]; - e.Org.coords[2] = coords[2]; - -/* The winding of an edge says how the winding number changes as we - * cross from the edge''s right face to its left face. We add the - * vertices in such an order that a CCW contour will add +1 to - * the winding number of the region inside the contour. - */ - e.winding = 1; - e.Sym.winding = -1; - - lastEdge = e; - - return true; - } - - private void cacheVertex(double[] coords, Object vertexData) { - if (cache[cacheCount] == null) { - cache[cacheCount] = new CachedVertex(); - } - - CachedVertex v = cache[cacheCount]; - - v.data = vertexData; - v.coords[0] = coords[0]; - v.coords[1] = coords[1]; - v.coords[2] = coords[2]; - ++cacheCount; - } - - - private boolean flushCache() { - CachedVertex[] v = cache; - - mesh = Mesh.__gl_meshNewMesh(); - if (mesh == null) return false; - - for (int i = 0; i < cacheCount; i++) { - CachedVertex vertex = v[i]; - if (!addVertex(vertex.coords, vertex.data)) return false; - } - cacheCount = 0; - flushCacheOnNextVertex = false; - - return true; - } - - public void gluTessVertex(double[] coords, int coords_offset, Object vertexData) { - int i; - boolean tooLarge = false; - double x; - double[] clamped = new double[3]; - - requireState(TessState.T_IN_CONTOUR); - - if (flushCacheOnNextVertex) { - if (!flushCache()) { - callErrorOrErrorData(PGLU.GLU_OUT_OF_MEMORY); - return; - } - lastEdge = null; - } - for (i = 0; i < 3; ++i) { - x = coords[i+coords_offset]; - if (x < -PGLU.GLU_TESS_MAX_COORD) { - x = -PGLU.GLU_TESS_MAX_COORD; - tooLarge = true; - } - if (x > PGLU.GLU_TESS_MAX_COORD) { - x = PGLU.GLU_TESS_MAX_COORD; - tooLarge = true; - } - clamped[i] = x; - } - if (tooLarge) { - callErrorOrErrorData(PGLU.GLU_TESS_COORD_TOO_LARGE); - } - - if (mesh == null) { - if (cacheCount < TESS_MAX_CACHE) { - cacheVertex(clamped, vertexData); - return; - } - if (!flushCache()) { - callErrorOrErrorData(PGLU.GLU_OUT_OF_MEMORY); - return; - } - } - - if (!addVertex(clamped, vertexData)) { - callErrorOrErrorData(PGLU.GLU_OUT_OF_MEMORY); - } - } - - - public void gluTessBeginPolygon(Object data) { - requireState(TessState.T_DORMANT); - - state = TessState.T_IN_POLYGON; - cacheCount = 0; - flushCacheOnNextVertex = false; - mesh = null; - - polygonData = data; - } - - - public void gluTessBeginContour() { - requireState(TessState.T_IN_POLYGON); - - state = TessState.T_IN_CONTOUR; - lastEdge = null; - if (cacheCount > 0) { -/* Just set a flag so we don't get confused by empty contours - * -- these can be generated accidentally with the obsolete - * NextContour() interface. - */ - flushCacheOnNextVertex = true; - } - } - - - public void gluTessEndContour() { - requireState(TessState.T_IN_CONTOUR); - state = TessState.T_IN_POLYGON; - } - - public void gluTessEndPolygon() { - GLUmesh mesh; - - try { - requireState(TessState.T_IN_POLYGON); - state = TessState.T_DORMANT; - - if (this.mesh == null) { - if (!flagBoundary /*&& callMesh == NULL_CB*/) { - -/* Try some special code to make the easy cases go quickly - * (eg. convex polygons). This code does NOT handle multiple contours, - * intersections, edge flags, and of course it does not generate - * an explicit mesh either. - */ - if (Render.__gl_renderCache(this)) { - polygonData = null; - return; - } - } - if (!flushCache()) throw new RuntimeException(); /* could've used a label*/ - } - -/* Determine the polygon normal and project vertices onto the plane - * of the polygon. - */ - Normal.__gl_projectPolygon(this); - -/* __gl_computeInterior( tess ) computes the planar arrangement specified - * by the given contours, and further subdivides this arrangement - * into regions. Each region is marked "inside" if it belongs - * to the polygon, according to the rule given by windingRule. - * Each interior region is guaranteed be monotone. - */ - if (!Sweep.__gl_computeInterior(this)) { - throw new RuntimeException(); /* could've used a label */ - } - - mesh = this.mesh; - if (!fatalError) { - boolean rc = true; - -/* If the user wants only the boundary contours, we throw away all edges - * except those which separate the interior from the exterior. - * Otherwise we tessellate all the regions marked "inside". - */ - if (boundaryOnly) { - rc = TessMono.__gl_meshSetWindingNumber(mesh, 1, true); - } else { - rc = TessMono.__gl_meshTessellateInterior(mesh, avoidDegenerateTris); - } - if (!rc) throw new RuntimeException(); /* could've used a label */ - - Mesh.__gl_meshCheckMesh(mesh); - - if (callBegin != NULL_CB || callEnd != NULL_CB - || callVertex != NULL_CB || callEdgeFlag != NULL_CB - || callBeginData != NULL_CB - || callEndData != NULL_CB - || callVertexData != NULL_CB - || callEdgeFlagData != NULL_CB) { - if (boundaryOnly) { - Render.__gl_renderBoundary(this, mesh); /* output boundary contours */ - } else { - Render.__gl_renderMesh(this, mesh); /* output strips and fans */ - } - } -// if (callMesh != NULL_CB) { -// -///* Throw away the exterior faces, so that all faces are interior. -// * This way the user doesn't have to check the "inside" flag, -// * and we don't need to even reveal its existence. It also leaves -// * the freedom for an implementation to not generate the exterior -// * faces in the first place. -// */ -// TessMono.__gl_meshDiscardExterior(mesh); -// callMesh.mesh(mesh); /* user wants the mesh itself */ -// mesh = null; -// polygonData = null; -// return; -// } - } - Mesh.__gl_meshDeleteMesh(mesh); - polygonData = null; - mesh = null; - } catch (Exception e) { - e.printStackTrace(); - callErrorOrErrorData(PGLU.GLU_OUT_OF_MEMORY); - } - } - - /*******************************************************/ - -/* Obsolete calls -- for backward compatibility */ - - public void gluBeginPolygon() { - gluTessBeginPolygon(null); - gluTessBeginContour(); - } - - -/*ARGSUSED*/ - public void gluNextContour(int type) { - gluTessEndContour(); - gluTessBeginContour(); - } - - - public void gluEndPolygon() { - gluTessEndContour(); - gluTessEndPolygon(); - } - - void callBeginOrBeginData(int a) { - if (callBeginData != NULL_CB) - callBeginData.beginData(a, polygonData); - else - callBegin.begin(a); - } - - void callVertexOrVertexData(Object a) { - if (callVertexData != NULL_CB) - callVertexData.vertexData(a, polygonData); - else - callVertex.vertex(a); - } - - void callEdgeFlagOrEdgeFlagData(boolean a) { - if (callEdgeFlagData != NULL_CB) - callEdgeFlagData.edgeFlagData(a, polygonData); - else - callEdgeFlag.edgeFlag(a); - } - - void callEndOrEndData() { - if (callEndData != NULL_CB) - callEndData.endData(polygonData); - else - callEnd.end(); - } - - void callCombineOrCombineData(double[] coords, Object[] vertexData, float[] weights, Object[] outData) { - if (callCombineData != NULL_CB) - callCombineData.combineData(coords, vertexData, weights, outData, polygonData); - else - callCombine.combine(coords, vertexData, weights, outData); - } - - void callErrorOrErrorData(int a) { - if (callErrorData != NULL_CB) - callErrorData.errorData(a, polygonData); - else - callError.error(a); - } - -} diff --git a/core/src/processing/opengl/tess/GLUvertex.java b/core/src/processing/opengl/tess/GLUvertex.java deleted file mode 100644 index 8349878a1..000000000 --- a/core/src/processing/opengl/tess/GLUvertex.java +++ /dev/null @@ -1,67 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class GLUvertex { - public GLUvertex next; /* next vertex (never NULL) */ - public GLUvertex prev; /* previous vertex (never NULL) */ - public GLUhalfEdge anEdge; /* a half-edge with this origin */ - public Object data; /* client's data */ - - /* Internal data (keep hidden) */ - public double[] coords = new double[3]; /* vertex location in 3D */ - public double s, t; /* projection onto the sweep plane */ - public int pqHandle; /* to allow deletion from priority queue */ -} diff --git a/core/src/processing/opengl/tess/Geom.java b/core/src/processing/opengl/tess/Geom.java deleted file mode 100644 index 3aa5e175d..000000000 --- a/core/src/processing/opengl/tess/Geom.java +++ /dev/null @@ -1,340 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class Geom { - private Geom() { - } - - /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w), - * evaluates the t-coord of the edge uw at the s-coord of the vertex v. - * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v. - * If uw is vertical (and thus passes thru v), the result is zero. - * - * The calculation is extremely accurate and stable, even when v - * is very close to u or w. In particular if we set v->t = 0 and - * let r be the negated result (this evaluates (uw)(v->s)), then - * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t). - */ - static double EdgeEval(GLUvertex u, GLUvertex v, GLUvertex w) { - double gapL, gapR; - - assert (VertLeq(u, v) && VertLeq(v, w)); - - gapL = v.s - u.s; - gapR = w.s - v.s; - - if (gapL + gapR > 0) { - if (gapL < gapR) { - return (v.t - u.t) + (u.t - w.t) * (gapL / (gapL + gapR)); - } else { - return (v.t - w.t) + (w.t - u.t) * (gapR / (gapL + gapR)); - } - } - /* vertical line */ - return 0; - } - - static double EdgeSign(GLUvertex u, GLUvertex v, GLUvertex w) { - double gapL, gapR; - - assert (VertLeq(u, v) && VertLeq(v, w)); - - gapL = v.s - u.s; - gapR = w.s - v.s; - - if (gapL + gapR > 0) { - return (v.t - w.t) * gapL + (v.t - u.t) * gapR; - } - /* vertical line */ - return 0; - } - - - /*********************************************************************** - * Define versions of EdgeSign, EdgeEval with s and t transposed. - */ - - static double TransEval(GLUvertex u, GLUvertex v, GLUvertex w) { - /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w), - * evaluates the t-coord of the edge uw at the s-coord of the vertex v. - * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v. - * If uw is vertical (and thus passes thru v), the result is zero. - * - * The calculation is extremely accurate and stable, even when v - * is very close to u or w. In particular if we set v->s = 0 and - * let r be the negated result (this evaluates (uw)(v->t)), then - * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s). - */ - double gapL, gapR; - - assert (TransLeq(u, v) && TransLeq(v, w)); - - gapL = v.t - u.t; - gapR = w.t - v.t; - - if (gapL + gapR > 0) { - if (gapL < gapR) { - return (v.s - u.s) + (u.s - w.s) * (gapL / (gapL + gapR)); - } else { - return (v.s - w.s) + (w.s - u.s) * (gapR / (gapL + gapR)); - } - } - /* vertical line */ - return 0; - } - - static double TransSign(GLUvertex u, GLUvertex v, GLUvertex w) { - /* Returns a number whose sign matches TransEval(u,v,w) but which - * is cheaper to evaluate. Returns > 0, == 0 , or < 0 - * as v is above, on, or below the edge uw. - */ - double gapL, gapR; - - assert (TransLeq(u, v) && TransLeq(v, w)); - - gapL = v.t - u.t; - gapR = w.t - v.t; - - if (gapL + gapR > 0) { - return (v.s - w.s) * gapL + (v.s - u.s) * gapR; - } - /* vertical line */ - return 0; - } - - - static boolean VertCCW(GLUvertex u, GLUvertex v, GLUvertex w) { - /* For almost-degenerate situations, the results are not reliable. - * Unless the floating-point arithmetic can be performed without - * rounding errors, *any* implementation will give incorrect results - * on some degenerate inputs, so the client must have some way to - * handle this situation. - */ - return (u.s * (v.t - w.t) + v.s * (w.t - u.t) + w.s * (u.t - v.t)) >= 0; - } - -/* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b), - * or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces - * this in the rare case that one argument is slightly negative. - * The implementation is extremely stable numerically. - * In particular it guarantees that the result r satisfies - * MIN(x,y) <= r <= MAX(x,y), and the results are very accurate - * even when a and b differ greatly in magnitude. - */ - static double Interpolate(double a, double x, double b, double y) { - a = (a < 0) ? 0 : a; - b = (b < 0) ? 0 : b; - if (a <= b) { - if (b == 0) { - return (x + y) / 2.0; - } else { - return (x + (y - x) * (a / (a + b))); - } - } else { - return (y + (x - y) * (b / (a + b))); - } - } - - static void EdgeIntersect(GLUvertex o1, GLUvertex d1, - GLUvertex o2, GLUvertex d2, - GLUvertex v) -/* Given edges (o1,d1) and (o2,d2), compute their point of intersection. - * The computed point is guaranteed to lie in the intersection of the - * bounding rectangles defined by each edge. - */ { - double z1, z2; - - /* This is certainly not the most efficient way to find the intersection - * of two line segments, but it is very numerically stable. - * - * Strategy: find the two middle vertices in the VertLeq ordering, - * and interpolate the intersection s-value from these. Then repeat - * using the TransLeq ordering to find the intersection t-value. - */ - - if (!VertLeq(o1, d1)) { - GLUvertex temp = o1; - o1 = d1; - d1 = temp; - } - if (!VertLeq(o2, d2)) { - GLUvertex temp = o2; - o2 = d2; - d2 = temp; - } - if (!VertLeq(o1, o2)) { - GLUvertex temp = o1; - o1 = o2; - o2 = temp; - temp = d1; - d1 = d2; - d2 = temp; - } - - if (!VertLeq(o2, d1)) { - /* Technically, no intersection -- do our best */ - v.s = (o2.s + d1.s) / 2.0; - } else if (VertLeq(d1, d2)) { - /* Interpolate between o2 and d1 */ - z1 = EdgeEval(o1, o2, d1); - z2 = EdgeEval(o2, d1, d2); - if (z1 + z2 < 0) { - z1 = -z1; - z2 = -z2; - } - v.s = Interpolate(z1, o2.s, z2, d1.s); - } else { - /* Interpolate between o2 and d2 */ - z1 = EdgeSign(o1, o2, d1); - z2 = -EdgeSign(o1, d2, d1); - if (z1 + z2 < 0) { - z1 = -z1; - z2 = -z2; - } - v.s = Interpolate(z1, o2.s, z2, d2.s); - } - - /* Now repeat the process for t */ - - if (!TransLeq(o1, d1)) { - GLUvertex temp = o1; - o1 = d1; - d1 = temp; - } - if (!TransLeq(o2, d2)) { - GLUvertex temp = o2; - o2 = d2; - d2 = temp; - } - if (!TransLeq(o1, o2)) { - GLUvertex temp = o2; - o2 = o1; - o1 = temp; - temp = d2; - d2 = d1; - d1 = temp; - } - - if (!TransLeq(o2, d1)) { - /* Technically, no intersection -- do our best */ - v.t = (o2.t + d1.t) / 2.0; - } else if (TransLeq(d1, d2)) { - /* Interpolate between o2 and d1 */ - z1 = TransEval(o1, o2, d1); - z2 = TransEval(o2, d1, d2); - if (z1 + z2 < 0) { - z1 = -z1; - z2 = -z2; - } - v.t = Interpolate(z1, o2.t, z2, d1.t); - } else { - /* Interpolate between o2 and d2 */ - z1 = TransSign(o1, o2, d1); - z2 = -TransSign(o1, d2, d1); - if (z1 + z2 < 0) { - z1 = -z1; - z2 = -z2; - } - v.t = Interpolate(z1, o2.t, z2, d2.t); - } - } - - static boolean VertEq(GLUvertex u, GLUvertex v) { - return u.s == v.s && u.t == v.t; - } - - static boolean VertLeq(GLUvertex u, GLUvertex v) { - return u.s < v.s || (u.s == v.s && u.t <= v.t); - } - -/* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */ - - static boolean TransLeq(GLUvertex u, GLUvertex v) { - return u.t < v.t || (u.t == v.t && u.s <= v.s); - } - - static boolean EdgeGoesLeft(GLUhalfEdge e) { - return VertLeq(e.Sym.Org, e.Org); - } - - static boolean EdgeGoesRight(GLUhalfEdge e) { - return VertLeq(e.Org, e.Sym.Org); - } - - static double VertL1dist(GLUvertex u, GLUvertex v) { - return Math.abs(u.s - v.s) + Math.abs(u.t - v.t); - } - - /***********************************************************************/ - - // Compute the cosine of the angle between the edges between o and - // v1 and between o and v2 - static double EdgeCos(GLUvertex o, GLUvertex v1, GLUvertex v2) { - double ov1s = v1.s - o.s; - double ov1t = v1.t - o.t; - double ov2s = v2.s - o.s; - double ov2t = v2.t - o.t; - double dotp = ov1s * ov2s + ov1t * ov2t; - double len = Math.sqrt(ov1s * ov1s + ov1t * ov1t) * Math.sqrt(ov2s * ov2s + ov2t * ov2t); - if (len > 0.0) { - dotp /= len; - } - return dotp; - } - - static final double EPSILON = 1.0e-5; - static final double ONE_MINUS_EPSILON = 1.0 - EPSILON; -} diff --git a/core/src/processing/opengl/tess/Mesh.java b/core/src/processing/opengl/tess/Mesh.java deleted file mode 100644 index 29764face..000000000 --- a/core/src/processing/opengl/tess/Mesh.java +++ /dev/null @@ -1,736 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class Mesh { - private Mesh() { - } - - /************************ Utility Routines ************************/ -/* MakeEdge creates a new pair of half-edges which form their own loop. - * No vertex or face structures are allocated, but these must be assigned - * before the current edge operation is completed. - */ - static GLUhalfEdge MakeEdge(GLUhalfEdge eNext) { - GLUhalfEdge e; - GLUhalfEdge eSym; - GLUhalfEdge ePrev; - -// EdgePair * pair = (EdgePair *) -// memAlloc(sizeof(EdgePair)); -// if (pair == NULL) return NULL; -// -// e = &pair - > e; - e = new GLUhalfEdge(true); -// eSym = &pair - > eSym; - eSym = new GLUhalfEdge(false); - - - /* Make sure eNext points to the first edge of the edge pair */ - if (!eNext.first) { - eNext = eNext.Sym; - } - - /* Insert in circular doubly-linked list before eNext. - * Note that the prev pointer is stored in Sym->next. - */ - ePrev = eNext.Sym.next; - eSym.next = ePrev; - ePrev.Sym.next = e; - e.next = eNext; - eNext.Sym.next = eSym; - - e.Sym = eSym; - e.Onext = e; - e.Lnext = eSym; - e.Org = null; - e.Lface = null; - e.winding = 0; - e.activeRegion = null; - - eSym.Sym = e; - eSym.Onext = eSym; - eSym.Lnext = e; - eSym.Org = null; - eSym.Lface = null; - eSym.winding = 0; - eSym.activeRegion = null; - - return e; - } - -/* Splice( a, b ) is best described by the Guibas/Stolfi paper or the - * CS348a notes (see mesh.h). Basically it modifies the mesh so that - * a->Onext and b->Onext are exchanged. This can have various effects - * depending on whether a and b belong to different face or vertex rings. - * For more explanation see __gl_meshSplice() below. - */ - static void Splice(GLUhalfEdge a, GLUhalfEdge b) { - GLUhalfEdge aOnext = a.Onext; - GLUhalfEdge bOnext = b.Onext; - - aOnext.Sym.Lnext = b; - bOnext.Sym.Lnext = a; - a.Onext = bOnext; - b.Onext = aOnext; - } - -/* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the - * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives - * a place to insert the new vertex in the global vertex list. We insert - * the new vertex *before* vNext so that algorithms which walk the vertex - * list will not see the newly created vertices. - */ - static void MakeVertex(GLUvertex newVertex, - GLUhalfEdge eOrig, GLUvertex vNext) { - GLUhalfEdge e; - GLUvertex vPrev; - GLUvertex vNew = newVertex; - - assert (vNew != null); - - /* insert in circular doubly-linked list before vNext */ - vPrev = vNext.prev; - vNew.prev = vPrev; - vPrev.next = vNew; - vNew.next = vNext; - vNext.prev = vNew; - - vNew.anEdge = eOrig; - vNew.data = null; - /* leave coords, s, t undefined */ - - /* fix other edges on this vertex loop */ - e = eOrig; - do { - e.Org = vNew; - e = e.Onext; - } while (e != eOrig); - } - -/* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left - * face of all edges in the face loop to which eOrig belongs. "fNext" gives - * a place to insert the new face in the global face list. We insert - * the new face *before* fNext so that algorithms which walk the face - * list will not see the newly created faces. - */ - static void MakeFace(GLUface newFace, GLUhalfEdge eOrig, GLUface fNext) { - GLUhalfEdge e; - GLUface fPrev; - GLUface fNew = newFace; - - assert (fNew != null); - - /* insert in circular doubly-linked list before fNext */ - fPrev = fNext.prev; - fNew.prev = fPrev; - fPrev.next = fNew; - fNew.next = fNext; - fNext.prev = fNew; - - fNew.anEdge = eOrig; - fNew.data = null; - fNew.trail = null; - fNew.marked = false; - - /* The new face is marked "inside" if the old one was. This is a - * convenience for the common case where a face has been split in two. - */ - fNew.inside = fNext.inside; - - /* fix other edges on this face loop */ - e = eOrig; - do { - e.Lface = fNew; - e = e.Lnext; - } while (e != eOrig); - } - -/* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym), - * and removes from the global edge list. - */ - static void KillEdge(GLUhalfEdge eDel) { - GLUhalfEdge ePrev, eNext; - - /* Half-edges are allocated in pairs, see EdgePair above */ - if (!eDel.first) { - eDel = eDel.Sym; - } - - /* delete from circular doubly-linked list */ - eNext = eDel.next; - ePrev = eDel.Sym.next; - eNext.Sym.next = ePrev; - ePrev.Sym.next = eNext; - } - - -/* KillVertex( vDel ) destroys a vertex and removes it from the global - * vertex list. It updates the vertex loop to point to a given new vertex. - */ - static void KillVertex(GLUvertex vDel, GLUvertex newOrg) { - GLUhalfEdge e, eStart = vDel.anEdge; - GLUvertex vPrev, vNext; - - /* change the origin of all affected edges */ - e = eStart; - do { - e.Org = newOrg; - e = e.Onext; - } while (e != eStart); - - /* delete from circular doubly-linked list */ - vPrev = vDel.prev; - vNext = vDel.next; - vNext.prev = vPrev; - vPrev.next = vNext; - } - -/* KillFace( fDel ) destroys a face and removes it from the global face - * list. It updates the face loop to point to a given new face. - */ - static void KillFace(GLUface fDel, GLUface newLface) { - GLUhalfEdge e, eStart = fDel.anEdge; - GLUface fPrev, fNext; - - /* change the left face of all affected edges */ - e = eStart; - do { - e.Lface = newLface; - e = e.Lnext; - } while (e != eStart); - - /* delete from circular doubly-linked list */ - fPrev = fDel.prev; - fNext = fDel.next; - fNext.prev = fPrev; - fPrev.next = fNext; - } - - - /****************** Basic Edge Operations **********************/ - -/* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face). - * The loop consists of the two new half-edges. - */ - public static GLUhalfEdge __gl_meshMakeEdge(GLUmesh mesh) { - GLUvertex newVertex1 = new GLUvertex(); - GLUvertex newVertex2 = new GLUvertex(); - GLUface newFace = new GLUface(); - GLUhalfEdge e; - - e = MakeEdge(mesh.eHead); - if (e == null) return null; - - MakeVertex(newVertex1, e, mesh.vHead); - MakeVertex(newVertex2, e.Sym, mesh.vHead); - MakeFace(newFace, e, mesh.fHead); - return e; - } - - -/* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the - * mesh connectivity and topology. It changes the mesh so that - * eOrg->Onext <- OLD( eDst->Onext ) - * eDst->Onext <- OLD( eOrg->Onext ) - * where OLD(...) means the value before the meshSplice operation. - * - * This can have two effects on the vertex structure: - * - if eOrg->Org != eDst->Org, the two vertices are merged together - * - if eOrg->Org == eDst->Org, the origin is split into two vertices - * In both cases, eDst->Org is changed and eOrg->Org is untouched. - * - * Similarly (and independently) for the face structure, - * - if eOrg->Lface == eDst->Lface, one loop is split into two - * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one - * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. - * - * Some special cases: - * If eDst == eOrg, the operation has no effect. - * If eDst == eOrg->Lnext, the new face will have a single edge. - * If eDst == eOrg->Lprev, the old face will have a single edge. - * If eDst == eOrg->Onext, the new vertex will have a single edge. - * If eDst == eOrg->Oprev, the old vertex will have a single edge. - */ - public static boolean __gl_meshSplice(GLUhalfEdge eOrg, GLUhalfEdge eDst) { - boolean joiningLoops = false; - boolean joiningVertices = false; - - if (eOrg == eDst) return true; - - if (eDst.Org != eOrg.Org) { - /* We are merging two disjoint vertices -- destroy eDst->Org */ - joiningVertices = true; - KillVertex(eDst.Org, eOrg.Org); - } - if (eDst.Lface != eOrg.Lface) { - /* We are connecting two disjoint loops -- destroy eDst.Lface */ - joiningLoops = true; - KillFace(eDst.Lface, eOrg.Lface); - } - - /* Change the edge structure */ - Splice(eDst, eOrg); - - if (!joiningVertices) { - GLUvertex newVertex = new GLUvertex(); - - /* We split one vertex into two -- the new vertex is eDst.Org. - * Make sure the old vertex points to a valid half-edge. - */ - MakeVertex(newVertex, eDst, eOrg.Org); - eOrg.Org.anEdge = eOrg; - } - if (!joiningLoops) { - GLUface newFace = new GLUface(); - - /* We split one loop into two -- the new loop is eDst.Lface. - * Make sure the old face points to a valid half-edge. - */ - MakeFace(newFace, eDst, eOrg.Lface); - eOrg.Lface.anEdge = eOrg; - } - - return true; - } - - -/* __gl_meshDelete( eDel ) removes the edge eDel. There are several cases: - * if (eDel.Lface != eDel.Rface), we join two loops into one; the loop - * eDel.Lface is deleted. Otherwise, we are splitting one loop into two; - * the newly created loop will contain eDel.Dst. If the deletion of eDel - * would create isolated vertices, those are deleted as well. - * - * This function could be implemented as two calls to __gl_meshSplice - * plus a few calls to memFree, but this would allocate and delete - * unnecessary vertices and faces. - */ - static boolean __gl_meshDelete(GLUhalfEdge eDel) { - GLUhalfEdge eDelSym = eDel.Sym; - boolean joiningLoops = false; - - /* First step: disconnect the origin vertex eDel.Org. We make all - * changes to get a consistent mesh in this "intermediate" state. - */ - if (eDel.Lface != eDel.Sym.Lface) { - /* We are joining two loops into one -- remove the left face */ - joiningLoops = true; - KillFace(eDel.Lface, eDel.Sym.Lface); - } - - if (eDel.Onext == eDel) { - KillVertex(eDel.Org, null); - } else { - /* Make sure that eDel.Org and eDel.Sym.Lface point to valid half-edges */ - eDel.Sym.Lface.anEdge = eDel.Sym.Lnext; - eDel.Org.anEdge = eDel.Onext; - - Splice(eDel, eDel.Sym.Lnext); - if (!joiningLoops) { - GLUface newFace = new GLUface(); - - /* We are splitting one loop into two -- create a new loop for eDel. */ - MakeFace(newFace, eDel, eDel.Lface); - } - } - - /* Claim: the mesh is now in a consistent state, except that eDel.Org - * may have been deleted. Now we disconnect eDel.Dst. - */ - if (eDelSym.Onext == eDelSym) { - KillVertex(eDelSym.Org, null); - KillFace(eDelSym.Lface, null); - } else { - /* Make sure that eDel.Dst and eDel.Lface point to valid half-edges */ - eDel.Lface.anEdge = eDelSym.Sym.Lnext; - eDelSym.Org.anEdge = eDelSym.Onext; - Splice(eDelSym, eDelSym.Sym.Lnext); - } - - /* Any isolated vertices or faces have already been freed. */ - KillEdge(eDel); - - return true; - } - - - /******************** Other Edge Operations **********************/ - -/* All these routines can be implemented with the basic edge - * operations above. They are provided for convenience and efficiency. - */ - - -/* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that - * eNew == eOrg.Lnext, and eNew.Dst is a newly created vertex. - * eOrg and eNew will have the same left face. - */ - static GLUhalfEdge __gl_meshAddEdgeVertex(GLUhalfEdge eOrg) { - GLUhalfEdge eNewSym; - GLUhalfEdge eNew = MakeEdge(eOrg); - - eNewSym = eNew.Sym; - - /* Connect the new edge appropriately */ - Splice(eNew, eOrg.Lnext); - - /* Set the vertex and face information */ - eNew.Org = eOrg.Sym.Org; - { - GLUvertex newVertex = new GLUvertex(); - - MakeVertex(newVertex, eNewSym, eNew.Org); - } - eNew.Lface = eNewSym.Lface = eOrg.Lface; - - return eNew; - } - - -/* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, - * such that eNew == eOrg.Lnext. The new vertex is eOrg.Sym.Org == eNew.Org. - * eOrg and eNew will have the same left face. - */ - public static GLUhalfEdge __gl_meshSplitEdge(GLUhalfEdge eOrg) { - GLUhalfEdge eNew; - GLUhalfEdge tempHalfEdge = __gl_meshAddEdgeVertex(eOrg); - - eNew = tempHalfEdge.Sym; - - /* Disconnect eOrg from eOrg.Sym.Org and connect it to eNew.Org */ - Splice(eOrg.Sym, eOrg.Sym.Sym.Lnext); - Splice(eOrg.Sym, eNew); - - /* Set the vertex and face information */ - eOrg.Sym.Org = eNew.Org; - eNew.Sym.Org.anEdge = eNew.Sym; /* may have pointed to eOrg.Sym */ - eNew.Sym.Lface = eOrg.Sym.Lface; - eNew.winding = eOrg.winding; /* copy old winding information */ - eNew.Sym.winding = eOrg.Sym.winding; - - return eNew; - } - - -/* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg.Sym.Org - * to eDst.Org, and returns the corresponding half-edge eNew. - * If eOrg.Lface == eDst.Lface, this splits one loop into two, - * and the newly created loop is eNew.Lface. Otherwise, two disjoint - * loops are merged into one, and the loop eDst.Lface is destroyed. - * - * If (eOrg == eDst), the new face will have only two edges. - * If (eOrg.Lnext == eDst), the old face is reduced to a single edge. - * If (eOrg.Lnext.Lnext == eDst), the old face is reduced to two edges. - */ - static GLUhalfEdge __gl_meshConnect(GLUhalfEdge eOrg, GLUhalfEdge eDst) { - GLUhalfEdge eNewSym; - boolean joiningLoops = false; - GLUhalfEdge eNew = MakeEdge(eOrg); - - eNewSym = eNew.Sym; - - if (eDst.Lface != eOrg.Lface) { - /* We are connecting two disjoint loops -- destroy eDst.Lface */ - joiningLoops = true; - KillFace(eDst.Lface, eOrg.Lface); - } - - /* Connect the new edge appropriately */ - Splice(eNew, eOrg.Lnext); - Splice(eNewSym, eDst); - - /* Set the vertex and face information */ - eNew.Org = eOrg.Sym.Org; - eNewSym.Org = eDst.Org; - eNew.Lface = eNewSym.Lface = eOrg.Lface; - - /* Make sure the old face points to a valid half-edge */ - eOrg.Lface.anEdge = eNewSym; - - if (!joiningLoops) { - GLUface newFace = new GLUface(); - - /* We split one loop into two -- the new loop is eNew.Lface */ - MakeFace(newFace, eNew, eOrg.Lface); - } - return eNew; - } - - - /******************** Other Operations **********************/ - -/* __gl_meshZapFace( fZap ) destroys a face and removes it from the - * global face list. All edges of fZap will have a null pointer as their - * left face. Any edges which also have a null pointer as their right face - * are deleted entirely (along with any isolated vertices this produces). - * An entire mesh can be deleted by zapping its faces, one at a time, - * in any order. Zapped faces cannot be used in further mesh operations! - */ - static void __gl_meshZapFace(GLUface fZap) { - GLUhalfEdge eStart = fZap.anEdge; - GLUhalfEdge e, eNext, eSym; - GLUface fPrev, fNext; - - /* walk around face, deleting edges whose right face is also null */ - eNext = eStart.Lnext; - do { - e = eNext; - eNext = e.Lnext; - - e.Lface = null; - if (e.Sym.Lface == null) { - /* delete the edge -- see __gl_MeshDelete above */ - - if (e.Onext == e) { - KillVertex(e.Org, null); - } else { - /* Make sure that e.Org points to a valid half-edge */ - e.Org.anEdge = e.Onext; - Splice(e, e.Sym.Lnext); - } - eSym = e.Sym; - if (eSym.Onext == eSym) { - KillVertex(eSym.Org, null); - } else { - /* Make sure that eSym.Org points to a valid half-edge */ - eSym.Org.anEdge = eSym.Onext; - Splice(eSym, eSym.Sym.Lnext); - } - KillEdge(e); - } - } while (e != eStart); - - /* delete from circular doubly-linked list */ - fPrev = fZap.prev; - fNext = fZap.next; - fNext.prev = fPrev; - fPrev.next = fNext; - } - - -/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices, - * and no loops (what we usually call a "face"). - */ - public static GLUmesh __gl_meshNewMesh() { - GLUvertex v; - GLUface f; - GLUhalfEdge e; - GLUhalfEdge eSym; - GLUmesh mesh = new GLUmesh(); - - v = mesh.vHead; - f = mesh.fHead; - e = mesh.eHead; - eSym = mesh.eHeadSym; - - v.next = v.prev = v; - v.anEdge = null; - v.data = null; - - f.next = f.prev = f; - f.anEdge = null; - f.data = null; - f.trail = null; - f.marked = false; - f.inside = false; - - e.next = e; - e.Sym = eSym; - e.Onext = null; - e.Lnext = null; - e.Org = null; - e.Lface = null; - e.winding = 0; - e.activeRegion = null; - - eSym.next = eSym; - eSym.Sym = e; - eSym.Onext = null; - eSym.Lnext = null; - eSym.Org = null; - eSym.Lface = null; - eSym.winding = 0; - eSym.activeRegion = null; - - return mesh; - } - - -/* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in - * both meshes, and returns the new mesh (the old meshes are destroyed). - */ - static GLUmesh __gl_meshUnion(GLUmesh mesh1, GLUmesh mesh2) { - GLUface f1 = mesh1.fHead; - GLUvertex v1 = mesh1.vHead; - GLUhalfEdge e1 = mesh1.eHead; - GLUface f2 = mesh2.fHead; - GLUvertex v2 = mesh2.vHead; - GLUhalfEdge e2 = mesh2.eHead; - - /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */ - if (f2.next != f2) { - f1.prev.next = f2.next; - f2.next.prev = f1.prev; - f2.prev.next = f1; - f1.prev = f2.prev; - } - - if (v2.next != v2) { - v1.prev.next = v2.next; - v2.next.prev = v1.prev; - v2.prev.next = v1; - v1.prev = v2.prev; - } - - if (e2.next != e2) { - e1.Sym.next.Sym.next = e2.next; - e2.next.Sym.next = e1.Sym.next; - e2.Sym.next.Sym.next = e1; - e1.Sym.next = e2.Sym.next; - } - - return mesh1; - } - - -/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. - */ - static void __gl_meshDeleteMeshZap(GLUmesh mesh) { - GLUface fHead = mesh.fHead; - - while (fHead.next != fHead) { - __gl_meshZapFace(fHead.next); - } - assert (mesh.vHead.next == mesh.vHead); - } - -/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. - */ - public static void __gl_meshDeleteMesh(GLUmesh mesh) { - GLUface f, fNext; - GLUvertex v, vNext; - GLUhalfEdge e, eNext; - - for (f = mesh.fHead.next; f != mesh.fHead; f = fNext) { - fNext = f.next; - } - - for (v = mesh.vHead.next; v != mesh.vHead; v = vNext) { - vNext = v.next; - } - - for (e = mesh.eHead.next; e != mesh.eHead; e = eNext) { - /* One call frees both e and e.Sym (see EdgePair above) */ - eNext = e.next; - } - } - -/* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency. - */ - public static void __gl_meshCheckMesh(GLUmesh mesh) { - GLUface fHead = mesh.fHead; - GLUvertex vHead = mesh.vHead; - GLUhalfEdge eHead = mesh.eHead; - GLUface f, fPrev; - GLUvertex v, vPrev; - GLUhalfEdge e, ePrev; - - fPrev = fHead; - for (fPrev = fHead; (f = fPrev.next) != fHead; fPrev = f) { - assert (f.prev == fPrev); - e = f.anEdge; - do { - assert (e.Sym != e); - assert (e.Sym.Sym == e); - assert (e.Lnext.Onext.Sym == e); - assert (e.Onext.Sym.Lnext == e); - assert (e.Lface == f); - e = e.Lnext; - } while (e != f.anEdge); - } - assert (f.prev == fPrev && f.anEdge == null && f.data == null); - - vPrev = vHead; - for (vPrev = vHead; (v = vPrev.next) != vHead; vPrev = v) { - assert (v.prev == vPrev); - e = v.anEdge; - do { - assert (e.Sym != e); - assert (e.Sym.Sym == e); - assert (e.Lnext.Onext.Sym == e); - assert (e.Onext.Sym.Lnext == e); - assert (e.Org == v); - e = e.Onext; - } while (e != v.anEdge); - } - assert (v.prev == vPrev && v.anEdge == null && v.data == null); - - ePrev = eHead; - for (ePrev = eHead; (e = ePrev.next) != eHead; ePrev = e) { - assert (e.Sym.next == ePrev.Sym); - assert (e.Sym != e); - assert (e.Sym.Sym == e); - assert (e.Org != null); - assert (e.Sym.Org != null); - assert (e.Lnext.Onext.Sym == e); - assert (e.Onext.Sym.Lnext == e); - } - assert (e.Sym.next == ePrev.Sym - && e.Sym == mesh.eHeadSym - && e.Sym.Sym == e - && e.Org == null && e.Sym.Org == null - && e.Lface == null && e.Sym.Lface == null); - } -} diff --git a/core/src/processing/opengl/tess/Normal.java b/core/src/processing/opengl/tess/Normal.java deleted file mode 100644 index dbee9966d..000000000 --- a/core/src/processing/opengl/tess/Normal.java +++ /dev/null @@ -1,288 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - - -class Normal { - private Normal() { - } - - static boolean SLANTED_SWEEP = false; - static double S_UNIT_X; /* Pre-normalized */ - static double S_UNIT_Y; - private static final boolean TRUE_PROJECT = false; - - static { - if (SLANTED_SWEEP) { -/* The "feature merging" is not intended to be complete. There are - * special cases where edges are nearly parallel to the sweep line - * which are not implemented. The algorithm should still behave - * robustly (ie. produce a reasonable tesselation) in the presence - * of such edges, however it may miss features which could have been - * merged. We could minimize this effect by choosing the sweep line - * direction to be something unusual (ie. not parallel to one of the - * coordinate axes). - */ - S_UNIT_X = 0.50941539564955385; /* Pre-normalized */ - S_UNIT_Y = 0.86052074622010633; - } else { - S_UNIT_X = 1.0; - S_UNIT_Y = 0.0; - } - } - - private static double Dot(double[] u, double[] v) { - return (u[0] * v[0] + u[1] * v[1] + u[2] * v[2]); - } - - static void Normalize(double[] v) { - double len = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; - - assert (len > 0); - len = Math.sqrt(len); - v[0] /= len; - v[1] /= len; - v[2] /= len; - } - - static int LongAxis(double[] v) { - int i = 0; - - if (Math.abs(v[1]) > Math.abs(v[0])) { - i = 1; - } - if (Math.abs(v[2]) > Math.abs(v[i])) { - i = 2; - } - return i; - } - - static void ComputeNormal(GLUtessellatorImpl tess, double[] norm) { - GLUvertex v, v1, v2; - double c, tLen2, maxLen2; - double[] maxVal, minVal, d1, d2, tNorm; - GLUvertex[] maxVert, minVert; - GLUvertex vHead = tess.mesh.vHead; - int i; - - maxVal = new double[3]; - minVal = new double[3]; - minVert = new GLUvertex[3]; - maxVert = new GLUvertex[3]; - d1 = new double[3]; - d2 = new double[3]; - tNorm = new double[3]; - - maxVal[0] = maxVal[1] = maxVal[2] = -2 * PGLU.GLU_TESS_MAX_COORD; - minVal[0] = minVal[1] = minVal[2] = 2 * PGLU.GLU_TESS_MAX_COORD; - - for (v = vHead.next; v != vHead; v = v.next) { - for (i = 0; i < 3; ++i) { - c = v.coords[i]; - if (c < minVal[i]) { - minVal[i] = c; - minVert[i] = v; - } - if (c > maxVal[i]) { - maxVal[i] = c; - maxVert[i] = v; - } - } - } - -/* Find two vertices separated by at least 1/sqrt(3) of the maximum - * distance between any two vertices - */ - i = 0; - if (maxVal[1] - minVal[1] > maxVal[0] - minVal[0]) { - i = 1; - } - if (maxVal[2] - minVal[2] > maxVal[i] - minVal[i]) { - i = 2; - } - if (minVal[i] >= maxVal[i]) { -/* All vertices are the same -- normal doesn't matter */ - norm[0] = 0; - norm[1] = 0; - norm[2] = 1; - return; - } - -/* Look for a third vertex which forms the triangle with maximum area - * (Length of normal == twice the triangle area) - */ - maxLen2 = 0; - v1 = minVert[i]; - v2 = maxVert[i]; - d1[0] = v1.coords[0] - v2.coords[0]; - d1[1] = v1.coords[1] - v2.coords[1]; - d1[2] = v1.coords[2] - v2.coords[2]; - for (v = vHead.next; v != vHead; v = v.next) { - d2[0] = v.coords[0] - v2.coords[0]; - d2[1] = v.coords[1] - v2.coords[1]; - d2[2] = v.coords[2] - v2.coords[2]; - tNorm[0] = d1[1] * d2[2] - d1[2] * d2[1]; - tNorm[1] = d1[2] * d2[0] - d1[0] * d2[2]; - tNorm[2] = d1[0] * d2[1] - d1[1] * d2[0]; - tLen2 = tNorm[0] * tNorm[0] + tNorm[1] * tNorm[1] + tNorm[2] * tNorm[2]; - if (tLen2 > maxLen2) { - maxLen2 = tLen2; - norm[0] = tNorm[0]; - norm[1] = tNorm[1]; - norm[2] = tNorm[2]; - } - } - - if (maxLen2 <= 0) { -/* All points lie on a single line -- any decent normal will do */ - norm[0] = norm[1] = norm[2] = 0; - norm[LongAxis(d1)] = 1; - } - } - - static void CheckOrientation(GLUtessellatorImpl tess) { - double area; - GLUface f, fHead = tess.mesh.fHead; - GLUvertex v, vHead = tess.mesh.vHead; - GLUhalfEdge e; - -/* When we compute the normal automatically, we choose the orientation - * so that the the sum of the signed areas of all contours is non-negative. - */ - area = 0; - for (f = fHead.next; f != fHead; f = f.next) { - e = f.anEdge; - if (e.winding <= 0) continue; - do { - area += (e.Org.s - e.Sym.Org.s) * (e.Org.t + e.Sym.Org.t); - e = e.Lnext; - } while (e != f.anEdge); - } - if (area < 0) { -/* Reverse the orientation by flipping all the t-coordinates */ - for (v = vHead.next; v != vHead; v = v.next) { - v.t = -v.t; - } - tess.tUnit[0] = -tess.tUnit[0]; - tess.tUnit[1] = -tess.tUnit[1]; - tess.tUnit[2] = -tess.tUnit[2]; - } - } - -/* Determine the polygon normal and project vertices onto the plane - * of the polygon. - */ - public static void __gl_projectPolygon(GLUtessellatorImpl tess) { - GLUvertex v, vHead = tess.mesh.vHead; - double w; - double[] norm = new double[3]; - double[] sUnit, tUnit; - int i; - boolean computedNormal = false; - - norm[0] = tess.normal[0]; - norm[1] = tess.normal[1]; - norm[2] = tess.normal[2]; - if (norm[0] == 0 && norm[1] == 0 && norm[2] == 0) { - ComputeNormal(tess, norm); - computedNormal = true; - } - sUnit = tess.sUnit; - tUnit = tess.tUnit; - i = LongAxis(norm); - - if (TRUE_PROJECT) { -/* Choose the initial sUnit vector to be approximately perpendicular - * to the normal. - */ - Normalize(norm); - - sUnit[i] = 0; - sUnit[(i + 1) % 3] = S_UNIT_X; - sUnit[(i + 2) % 3] = S_UNIT_Y; - -/* Now make it exactly perpendicular */ - w = Dot(sUnit, norm); - sUnit[0] -= w * norm[0]; - sUnit[1] -= w * norm[1]; - sUnit[2] -= w * norm[2]; - Normalize(sUnit); - -/* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */ - tUnit[0] = norm[1] * sUnit[2] - norm[2] * sUnit[1]; - tUnit[1] = norm[2] * sUnit[0] - norm[0] * sUnit[2]; - tUnit[2] = norm[0] * sUnit[1] - norm[1] * sUnit[0]; - Normalize(tUnit); - } else { -/* Project perpendicular to a coordinate axis -- better numerically */ - sUnit[i] = 0; - sUnit[(i + 1) % 3] = S_UNIT_X; - sUnit[(i + 2) % 3] = S_UNIT_Y; - - tUnit[i] = 0; - tUnit[(i + 1) % 3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y; - tUnit[(i + 2) % 3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X; - } - -/* Project the vertices onto the sweep plane */ - for (v = vHead.next; v != vHead; v = v.next) { - v.s = Dot(v.coords, sUnit); - v.t = Dot(v.coords, tUnit); - } - if (computedNormal) { - CheckOrientation(tess); - } - } -} diff --git a/core/src/processing/opengl/tess/PGLU.java b/core/src/processing/opengl/tess/PGLU.java deleted file mode 100644 index a4d6eaf76..000000000 --- a/core/src/processing/opengl/tess/PGLU.java +++ /dev/null @@ -1,158 +0,0 @@ -package processing.opengl.tess; - -import android.opengl.GLES20; - -public class PGLU { - public static final int GLU_FALSE = 0; - public static final int GLU_TRUE = 1; - - public static final int GLU_INVALID_ENUM = 100900; - public static final int GLU_INVALID_VALUE = 100901; - public static final int GLU_OUT_OF_MEMORY = 100902; - public static final int GLU_INVALID_OPERATION = 100904; - - public static final int GLU_POINT = 100010; - public static final int GLU_LINE = 100011; - public static final int GLU_FILL = 100012; - public static final int GLU_SILHOUETTE = 100013; - - public static final int GLU_SMOOTH = 100000; - public static final int GLU_FLAT = 100001; - public static final int GLU_NONE = 100002; - - public static final int GLU_OUTSIDE = 100020; - public static final int GLU_INSIDE = 100021; - - public static final int GLU_ERROR = 100103; - public static final int GLU_TESS_ERROR = 100103; - - public static final int GLU_TESS_BEGIN = 100100; - public static final int GLU_BEGIN = 100100; - public static final int GLU_TESS_VERTEX = 100101; - public static final int GLU_VERTEX = 100101; - public static final int GLU_TESS_END = 100102; - public static final int GLU_END = 100102; - - public static final int GLU_TESS_EDGE_FLAG = 100104; - public static final int GLU_EDGE_FLAG = 100104; - public static final int GLU_TESS_COMBINE = 100105; - public static final int GLU_TESS_BEGIN_DATA = 100106; - public static final int GLU_TESS_VERTEX_DATA = 100107; - public static final int GLU_TESS_END_DATA = 100108; - public static final int GLU_TESS_ERROR_DATA = 100109; - public static final int GLU_TESS_EDGE_FLAG_DATA = 100110; - public static final int GLU_TESS_COMBINE_DATA = 100111; - - public static final int GLU_CW = 100120; - public static final int GLU_CCW = 100121; - public static final int GLU_INTERIOR = 100122; - public static final int GLU_EXTERIOR = 100123; - public static final int GLU_UNKNOWN = 100124; - public static final int GLU_TESS_WINDING_RULE = 100140; - public static final int GLU_TESS_BOUNDARY_ONLY = 100141; - public static final int GLU_TESS_TOLERANCE = 100142; - public static final int GLU_TESS_AVOID_DEGENERATE_TRIANGLES = 100149; - - public static final int GLU_TESS_ERROR1 = 100151; - public static final int GLU_TESS_ERROR2 = 100152; - public static final int GLU_TESS_ERROR3 = 100153; - public static final int GLU_TESS_ERROR4 = 100154; - public static final int GLU_TESS_ERROR5 = 100155; - public static final int GLU_TESS_ERROR6 = 100156; - public static final int GLU_TESS_ERROR7 = 100157; - public static final int GLU_TESS_ERROR8 = 100158; - - public static final int GLU_TESS_MISSING_BEGIN_POLYGON = 100151; - public static final int GLU_TESS_MISSING_BEGIN_CONTOUR = 100152; - public static final int GLU_TESS_MISSING_END_POLYGON = 100153; - public static final int GLU_TESS_MISSING_END_CONTOUR = 100154; - public static final int GLU_TESS_COORD_TOO_LARGE = 100155; - public static final int GLU_TESS_NEED_COMBINE_CALLBACK = 100156; - - public static final int GLU_TESS_WINDING_ODD = 100130; - public static final int GLU_TESS_WINDING_NONZERO = 100131; - public static final int GLU_TESS_WINDING_POSITIVE = 100132; - public static final int GLU_TESS_WINDING_NEGATIVE = 100133; - public static final int GLU_TESS_WINDING_ABS_GEQ_TWO = 100134; - - public static final double GLU_TESS_MAX_COORD = 1.0E150; - - private static String[] glErrorStrings = { - "invalid enumerant", - "invalid value", - "invalid operation", - "stack overflow", - "stack underflow", - "out of memory", - "invalid framebuffer operation" - }; - - private static String[] gluErrorStrings = { - "invalid enumerant", - "invalid value", - "out of memory", - "", - "invalid operation" - }; - - private static String[] gluTessErrors = { - " ", - "gluTessBeginPolygon() must precede a gluTessEndPolygon", - "gluTessBeginContour() must precede a gluTessEndContour()", - "gluTessEndPolygon() must follow a gluTessBeginPolygon()", - "gluTessEndContour() must follow a gluTessBeginContour()", - "a coordinate is too large", - "need combine callback" - }; - - public static final PGLUtessellator gluNewTess() { - return GLUtessellatorImpl.gluNewTess(); - } - - public static final void gluTessCallback(PGLUtessellator tess, int which, PGLUtessellatorCallback callback) { - ((GLUtessellatorImpl)tess).gluTessCallback(which, callback); - } - - public static final void gluTessBeginPolygon(PGLUtessellator tess, Object data) { - ((GLUtessellatorImpl)tess).gluTessBeginPolygon(data); - } - - public static final void gluTessEndPolygon(PGLUtessellator tess) { - ((GLUtessellatorImpl)tess).gluTessEndPolygon(); - } - - public static final void gluTessProperty(PGLUtessellator tess, int which, double value) { - ((GLUtessellatorImpl)tess).gluTessProperty(which, value); - } - - public static final void gluTessBeginContour(PGLUtessellator tess) { - ((GLUtessellatorImpl)tess).gluTessBeginContour(); - } - - public static final void gluTessEndContour(PGLUtessellator tess) { - ((GLUtessellatorImpl)tess).gluTessEndContour(); - } - - public static final void gluTessVertex(PGLUtessellator tess, double[] coords, int offset, Object vdata) { - ((GLUtessellatorImpl)tess).gluTessVertex(coords, offset, vdata); - } - - public static String gluErrorString( int errorCode ) { - if( errorCode == 0 ) { - return ("no error"); - } - if( (errorCode >= GLES20.GL_INVALID_ENUM) && (errorCode <= GLES20.GL_INVALID_FRAMEBUFFER_OPERATION) ) { - return (glErrorStrings[errorCode - GLES20.GL_INVALID_ENUM]); - } - if( errorCode == 0x8031 /* GL.GL_TABLE_TOO_LARGE */ ) { - return ("table too large"); - } - if( (errorCode >= GLU_INVALID_ENUM) && (errorCode <= GLU_INVALID_OPERATION) ) { - return (gluErrorStrings[errorCode - GLU_INVALID_ENUM]); - } - if( (errorCode >= GLU_TESS_ERROR1) && (errorCode <= GLU_TESS_ERROR8) ) { - return (gluTessErrors[errorCode - (GLU_TESS_ERROR1 - 1)]); - } - return ("error ("+errorCode+")"); - } -} diff --git a/core/src/processing/opengl/tess/PGLUtessellator.java b/core/src/processing/opengl/tess/PGLUtessellator.java deleted file mode 100644 index c54dc8f92..000000000 --- a/core/src/processing/opengl/tess/PGLUtessellator.java +++ /dev/null @@ -1,70 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. - -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -/** - * The GLUtessellator object is used to hold the data, such as the - * vertices, edges and callback objects, to describe and tessellate complex - * polygons. A GLUtessellator object is used with the - * {@link PGLU GLU} tessellator methods and - * {@link PGLUtessellatorCallback GLU callbacks}. - * - * @author Eric Veach, July 1994 - * @author Java Port: Pepijn Van Eechhoudt, July 2003 - * @author Java Port: Nathan Parker Burg, August 2003 - * @author Processing integration: Andres Colubri, February 2012 - */ -public interface PGLUtessellator {} diff --git a/core/src/processing/opengl/tess/PGLUtessellatorCallback.java b/core/src/processing/opengl/tess/PGLUtessellatorCallback.java deleted file mode 100644 index f047b0764..000000000 --- a/core/src/processing/opengl/tess/PGLUtessellatorCallback.java +++ /dev/null @@ -1,359 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ -package processing.opengl.tess; - -/** - * GLUtessellatorCallback interface provides methods that the user will - * override to define the callbacks for a tessellation object. - * - * @author Eric Veach, July 1994 - * @author Java Port: Pepijn Van Eeckhoudt, July 2003 - * @author Java Port: Nathan Parker Burg, August 2003 - * @author Processing integration: Andres Colubri, February 2012 - */ - -public interface PGLUtessellatorCallback { - /** - * The begin callback method is invoked like - * {@link javax.media.opengl.GL#glBegin glBegin} to indicate the start of a - * (triangle) primitive. The method takes a single argument of type int. If - * the GLU_TESS_BOUNDARY_ONLY property is set to GL_FALSE, then - * the argument is set to either GL_TRIANGLE_FAN, - * GL_TRIANGLE_STRIP, or GL_TRIANGLES. If the - * GLU_TESS_BOUNDARY_ONLY property is set to GL_TRUE, then the - * argument will be set to GL_LINE_LOOP. - * - * @param type - * Specifics the type of begin/end pair being defined. The following - * values are valid: GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP, - * GL_TRIANGLES or GL_LINE_LOOP. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #end end - * @see #begin begin - */ - public void begin(int type); - - /** - * The same as the {@link #begin begin} callback method except that - * it takes an additional reference argument. This reference is - * identical to the opaque reference provided when {@link - * PGLU#gluTessBeginPolygon gluTessBeginPolygon} was called. - * - * @param type - * Specifics the type of begin/end pair being defined. The following - * values are valid: GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP, - * GL_TRIANGLES or GL_LINE_LOOP. - * @param polygonData - * Specifics a reference to user-defined data. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #endData endData - * @see #begin begin - */ - public void beginData(int type, Object polygonData); - - - /** - * The edgeFlag callback method is similar to - * {@link javax.media.opengl.GL#glEdgeFlag glEdgeFlag}. The method takes - * a single boolean boundaryEdge that indicates which edges lie on the - * polygon boundary. If the boundaryEdge is GL_TRUE, then each vertex - * that follows begins an edge that lies on the polygon boundary, that is, - * an edge that separates an interior region from an exterior one. If the - * boundaryEdge is GL_FALSE, then each vertex that follows begins an - * edge that lies in the polygon interior. The edge flag callback (if - * defined) is invoked before the first vertex callback.

    - * - * Since triangle fans and triangle strips do not support edge flags, the - * begin callback is not called with GL_TRIANGLE_FAN or - * GL_TRIANGLE_STRIP if a non-null edge flag callback is provided. - * (If the callback is initialized to null, there is no impact on - * performance). Instead, the fans and strips are converted to independent - * triangles. - * - * @param boundaryEdge - * Specifics which edges lie on the polygon boundary. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #edgeFlagData edgeFlagData - */ - public void edgeFlag(boolean boundaryEdge); - - - /** - * The same as the {@link #edgeFlag edgeFlage} callback method - * except that it takes an additional reference argument. This - * reference is identical to the opaque reference provided when - * {@link PGLU#gluTessBeginPolygon gluTessBeginPolygon} was called. - * - * @param boundaryEdge - * Specifics which edges lie on the polygon boundary. - * @param polygonData - * Specifics a reference to user-defined data. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #edgeFlag edgeFlag - */ - public void edgeFlagData(boolean boundaryEdge, Object polygonData); - - - /** - * The vertex callback method is invoked between the {@link - * #begin begin} and {@link #end end} callback methods. It is - * similar to {@link javax.media.opengl.GL#glVertex3f glVertex3f}, - * and it defines the vertices of the triangles created by the - * tessellation process. The method takes a reference as its only - * argument. This reference is identical to the opaque reference - * provided by the user when the vertex was described (see {@link - * PGLU#gluTessVertex gluTessVertex}). - * - * @param vertexData - * Specifics a reference to the vertices of the triangles created - * by the tessellation process. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #vertexData vertexData - */ - public void vertex(Object vertexData); - - - /** - * The same as the {@link #vertex vertex} callback method except - * that it takes an additional reference argument. This reference is - * identical to the opaque reference provided when {@link - * PGLU#gluTessBeginPolygon gluTessBeginPolygon} was called. - * - * @param vertexData - * Specifics a reference to the vertices of the triangles created - * by the tessellation process. - * @param polygonData - * Specifics a reference to user-defined data. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #vertex vertex - */ - public void vertexData(Object vertexData, Object polygonData); - - - /** - * The end callback serves the same purpose as - * {@link javax.media.opengl.GL#glEnd glEnd}. It indicates the end of a - * primitive and it takes no arguments. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #begin begin - * @see #endData endData - */ - public void end(); - - - /** - * The same as the {@link #end end} callback method except that it - * takes an additional reference argument. This reference is - * identical to the opaque reference provided when {@link - * PGLU#gluTessBeginPolygon gluTessBeginPolygon} was called. - * - * @param polygonData - * Specifics a reference to user-defined data. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #beginData beginData - * @see #end end - */ - public void endData(Object polygonData); - - - /** - * The combine callback method is called to create a new vertex when - * the tessellation detects an intersection, or wishes to merge features. The - * method takes four arguments: an array of three elements each of type - * double, an array of four references, an array of four elements each of - * type float, and a reference to a reference.

    - * - * The vertex is defined as a linear combination of up to four existing - * vertices, stored in data. The coefficients of the linear combination - * are given by weight; these weights always add up to 1. All vertex - * pointers are valid even when some of the weights are 0. coords gives - * the location of the new vertex.

    - * - * The user must allocate another vertex, interpolate parameters using - * data and weight, and return the new vertex pointer in - * outData. This handle is supplied during rendering callbacks. The - * user is responsible for freeing the memory some time after - * {@link PGLU#gluTessEndPolygon gluTessEndPolygon} is - * called.

    - * - * For example, if the polygon lies in an arbitrary plane in 3-space, and a - * color is associated with each vertex, the GLU_TESS_COMBINE - * callback might look like this: - * - *

    -   *         void myCombine(double[] coords, Object[] data,
    -   *                        float[] weight, Object[] outData)
    -   *         {
    -   *            MyVertex newVertex = new MyVertex();
    -   *
    -   *            newVertex.x = coords[0];
    -   *            newVertex.y = coords[1];
    -   *            newVertex.z = coords[2];
    -   *            newVertex.r = weight[0]*data[0].r +
    -   *                          weight[1]*data[1].r +
    -   *                          weight[2]*data[2].r +
    -   *                          weight[3]*data[3].r;
    -   *            newVertex.g = weight[0]*data[0].g +
    -   *                          weight[1]*data[1].g +
    -   *                          weight[2]*data[2].g +
    -   *                          weight[3]*data[3].g;
    -   *            newVertex.b = weight[0]*data[0].b +
    -   *                          weight[1]*data[1].b +
    -   *                          weight[2]*data[2].b +
    -   *                          weight[3]*data[3].b;
    -   *            newVertex.a = weight[0]*data[0].a +
    -   *                          weight[1]*data[1].a +
    -   *                          weight[2]*data[2].a +
    -   *                          weight[3]*data[3].a;
    -   *            outData = newVertex;
    -   *         }
    - * - * @param coords - * Specifics the location of the new vertex. - * @param data - * Specifics the vertices used to create the new vertex. - * @param weight - * Specifics the weights used to create the new vertex. - * @param outData - * Reference user the put the coodinates of the new vertex. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #combineData combineData - */ - public void combine(double[] coords, Object[] data, - float[] weight, Object[] outData); - - - /** - * The same as the {@link #combine combine} callback method except - * that it takes an additional reference argument. This reference is - * identical to the opaque reference provided when {@link - * PGLU#gluTessBeginPolygon gluTessBeginPolygon} was called. - * - * @param coords - * Specifics the location of the new vertex. - * @param data - * Specifics the vertices used to create the new vertex. - * @param weight - * Specifics the weights used to create the new vertex. - * @param outData - * Reference user the put the coodinates of the new vertex. - * @param polygonData - * Specifics a reference to user-defined data. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #combine combine - */ - public void combineData(double[] coords, Object[] data, - float[] weight, Object[] outData, - Object polygonData); - - - /** - * The error callback method is called when an error is encountered. - * The one argument is of type int; it indicates the specific error that - * occurred and will be set to one of GLU_TESS_MISSING_BEGIN_POLYGON, - * GLU_TESS_MISSING_END_POLYGON, GLU_TESS_MISSING_BEGIN_CONTOUR, - * GLU_TESS_MISSING_END_CONTOUR, GLU_TESS_COORD_TOO_LARGE, - * GLU_TESS_NEED_COMBINE_CALLBACK or GLU_OUT_OF_MEMORY. - * Character strings describing these errors can be retrieved with the - * {@link PGLU#gluErrorString gluErrorString} call.

    - * - * The GLU library will recover from the first four errors by inserting the - * missing call(s). GLU_TESS_COORD_TOO_LARGE indicates that some - * vertex coordinate exceeded the predefined constant - * GLU_TESS_MAX_COORD in absolute value, and that the value has been - * clamped. (Coordinate values must be small enough so that two can be - * multiplied together without overflow.) - * GLU_TESS_NEED_COMBINE_CALLBACK indicates that the tessellation - * detected an intersection between two edges in the input data, and the - * GLU_TESS_COMBINE or GLU_TESS_COMBINE_DATA callback was not - * provided. No output is generated. GLU_OUT_OF_MEMORY indicates that - * there is not enough memory so no output is generated. - * - * @param errnum - * Specifics the error number code. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #errorData errorData - */ - public void error(int errnum); - - - /** - * The same as the {@link #error error} callback method except that - * it takes an additional reference argument. This reference is - * identical to the opaque reference provided when {@link - * PGLU#gluTessBeginPolygon gluTessBeginPolygon} was called. - * - * @param errnum - * Specifics the error number code. - * @param polygonData - * Specifics a reference to user-defined data. - * - * @see PGLU#gluTessCallback gluTessCallback - * @see #error error - */ - public void errorData(int errnum, Object polygonData); - - //void mesh(jogamp.opengl.tessellator.GLUmesh mesh); -} diff --git a/core/src/processing/opengl/tess/PGLUtessellatorCallbackAdapter.java b/core/src/processing/opengl/tess/PGLUtessellatorCallbackAdapter.java deleted file mode 100644 index 9ea9a8c74..000000000 --- a/core/src/processing/opengl/tess/PGLUtessellatorCallbackAdapter.java +++ /dev/null @@ -1,87 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -/** - * The GLUtessellatorCallbackAdapter provides a default implementation of - * {@link PGLUtessellatorCallback GLUtessellatorCallback} - * with empty callback methods. This class can be extended to provide user - * defined callback methods. - * - * @author Eric Veach, July 1994 - * @author Java Port: Pepijn Van Eechhoudt, July 2003 - * @author Java Port: Nathan Parker Burg, August 2003 - * @author Processing integration: Andres Colubri, February 2012 - */ - -public class PGLUtessellatorCallbackAdapter implements PGLUtessellatorCallback { - public void begin(int type) {} - public void edgeFlag(boolean boundaryEdge) {} - public void vertex(Object vertexData) {} - public void end() {} -// public void mesh(jogamp.opengl.tessellator.GLUmesh mesh) {} - public void error(int errnum) {} - public void combine(double[] coords, Object[] data, - float[] weight, Object[] outData) {} - public void beginData(int type, Object polygonData) {} - public void edgeFlagData(boolean boundaryEdge, - Object polygonData) {} - public void vertexData(Object vertexData, Object polygonData) {} - public void endData(Object polygonData) {} - public void errorData(int errnum, Object polygonData) {} - public void combineData(double[] coords, Object[] data, - float[] weight, Object[] outData, - Object polygonData) {} -} diff --git a/core/src/processing/opengl/tess/PriorityQ.java b/core/src/processing/opengl/tess/PriorityQ.java deleted file mode 100644 index 99c772869..000000000 --- a/core/src/processing/opengl/tess/PriorityQ.java +++ /dev/null @@ -1,102 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -abstract class PriorityQ { - public static final int INIT_SIZE = 32; - - public static class PQnode { - int handle; - } - - public static class PQhandleElem { - Object key; - int node; - } - - public static interface Leq { - boolean leq(Object key1, Object key2); - } - - // #ifdef FOR_TRITE_TEST_PROGRAM -// private static boolean LEQ(PriorityQCommon.Leq leq, Object x,Object y) { -// return pq.leq.leq(x,y); -// } -// #else -/* Violates modularity, but a little faster */ -// #include "geom.h" - public static boolean LEQ(Leq leq, Object x, Object y) { - return Geom.VertLeq((GLUvertex) x, (GLUvertex) y); - } - - static PriorityQ pqNewPriorityQ(Leq leq) { - return new PriorityQSort(leq); - } - - abstract void pqDeletePriorityQ(); - - abstract boolean pqInit(); - - abstract int pqInsert(Object keyNew); - - abstract Object pqExtractMin(); - - abstract void pqDelete(int hCurr); - - abstract Object pqMinimum(); - - abstract boolean pqIsEmpty(); -// #endif -} diff --git a/core/src/processing/opengl/tess/PriorityQHeap.java b/core/src/processing/opengl/tess/PriorityQHeap.java deleted file mode 100644 index d3fae04d9..000000000 --- a/core/src/processing/opengl/tess/PriorityQHeap.java +++ /dev/null @@ -1,271 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class PriorityQHeap extends PriorityQ { - PriorityQ.PQnode[] nodes; - PriorityQ.PQhandleElem[] handles; - int size, max; - int freeList; - boolean initialized; - PriorityQ.Leq leq; - -/* really __gl_pqHeapNewPriorityQ */ - public PriorityQHeap(PriorityQ.Leq leq) { - size = 0; - max = PriorityQ.INIT_SIZE; - nodes = new PriorityQ.PQnode[PriorityQ.INIT_SIZE + 1]; - for (int i = 0; i < nodes.length; i++) { - nodes[i] = new PQnode(); - } - handles = new PriorityQ.PQhandleElem[PriorityQ.INIT_SIZE + 1]; - for (int i = 0; i < handles.length; i++) { - handles[i] = new PQhandleElem(); - } - initialized = false; - freeList = 0; - this.leq = leq; - - nodes[1].handle = 1; /* so that Minimum() returns NULL */ - handles[1].key = null; - } - -/* really __gl_pqHeapDeletePriorityQ */ - @Override - void pqDeletePriorityQ() { - handles = null; - nodes = null; - } - - void FloatDown(int curr) { - PriorityQ.PQnode[] n = nodes; - PriorityQ.PQhandleElem[] h = handles; - int hCurr, hChild; - int child; - - hCurr = n[curr].handle; - for (; ;) { - child = curr << 1; - if (child < size && LEQ(leq, h[n[child + 1].handle].key, - h[n[child].handle].key)) { - ++child; - } - - assert (child <= max); - - hChild = n[child].handle; - if (child > size || LEQ(leq, h[hCurr].key, h[hChild].key)) { - n[curr].handle = hCurr; - h[hCurr].node = curr; - break; - } - n[curr].handle = hChild; - h[hChild].node = curr; - curr = child; - } - } - - - void FloatUp(int curr) { - PriorityQ.PQnode[] n = nodes; - PriorityQ.PQhandleElem[] h = handles; - int hCurr, hParent; - int parent; - - hCurr = n[curr].handle; - for (; ;) { - parent = curr >> 1; - hParent = n[parent].handle; - if (parent == 0 || LEQ(leq, h[hParent].key, h[hCurr].key)) { - n[curr].handle = hCurr; - h[hCurr].node = curr; - break; - } - n[curr].handle = hParent; - h[hParent].node = curr; - curr = parent; - } - } - -/* really __gl_pqHeapInit */ - @Override - boolean pqInit() { - int i; - - /* This method of building a heap is O(n), rather than O(n lg n). */ - - for (i = size; i >= 1; --i) { - FloatDown(i); - } - initialized = true; - - return true; - } - -/* really __gl_pqHeapInsert */ -/* returns LONG_MAX iff out of memory */ - @Override - int pqInsert(Object keyNew) { - int curr; - int free; - - curr = ++size; - if ((curr * 2) > max) { - PriorityQ.PQnode[] saveNodes = nodes; - PriorityQ.PQhandleElem[] saveHandles = handles; - - /* If the heap overflows, double its size. */ - max <<= 1; -// pq->nodes = (PQnode *)memRealloc( pq->nodes, (size_t) ((pq->max + 1) * sizeof( pq->nodes[0] ))); - PriorityQ.PQnode[] pqNodes = new PriorityQ.PQnode[max + 1]; - System.arraycopy( nodes, 0, pqNodes, 0, nodes.length ); - for (int i = nodes.length; i < pqNodes.length; i++) { - pqNodes[i] = new PQnode(); - } - nodes = pqNodes; - if (nodes == null) { - nodes = saveNodes; /* restore ptr to free upon return */ - return Integer.MAX_VALUE; - } - -// pq->handles = (PQhandleElem *)memRealloc( pq->handles,(size_t)((pq->max + 1) * sizeof( pq->handles[0] ))); - PriorityQ.PQhandleElem[] pqHandles = new PriorityQ.PQhandleElem[max + 1]; - System.arraycopy( handles, 0, pqHandles, 0, handles.length ); - for (int i = handles.length; i < pqHandles.length; i++) { - pqHandles[i] = new PQhandleElem(); - } - handles = pqHandles; - if (handles == null) { - handles = saveHandles; /* restore ptr to free upon return */ - return Integer.MAX_VALUE; - } - } - - if (freeList == 0) { - free = curr; - } else { - free = freeList; - freeList = handles[free].node; - } - - nodes[curr].handle = free; - handles[free].node = curr; - handles[free].key = keyNew; - - if (initialized) { - FloatUp(curr); - } - assert (free != Integer.MAX_VALUE); - return free; - } - -/* really __gl_pqHeapExtractMin */ - @Override - Object pqExtractMin() { - PriorityQ.PQnode[] n = nodes; - PriorityQ.PQhandleElem[] h = handles; - int hMin = n[1].handle; - Object min = h[hMin].key; - - if (size > 0) { - n[1].handle = n[size].handle; - h[n[1].handle].node = 1; - - h[hMin].key = null; - h[hMin].node = freeList; - freeList = hMin; - - if (--size > 0) { - FloatDown(1); - } - } - return min; - } - -/* really __gl_pqHeapDelete */ - @Override - void pqDelete(int hCurr) { - PriorityQ.PQnode[] n = nodes; - PriorityQ.PQhandleElem[] h = handles; - int curr; - - assert (hCurr >= 1 && hCurr <= max && h[hCurr].key != null); - - curr = h[hCurr].node; - n[curr].handle = n[size].handle; - h[n[curr].handle].node = curr; - - if (curr <= --size) { - if (curr <= 1 || LEQ(leq, h[n[curr >> 1].handle].key, h[n[curr].handle].key)) { - FloatDown(curr); - } else { - FloatUp(curr); - } - } - h[hCurr].key = null; - h[hCurr].node = freeList; - freeList = hCurr; - } - - @Override - Object pqMinimum() { - return handles[nodes[1].handle].key; - } - - @Override - boolean pqIsEmpty() { - return size == 0; - } -} diff --git a/core/src/processing/opengl/tess/PriorityQSort.java b/core/src/processing/opengl/tess/PriorityQSort.java deleted file mode 100644 index 8b5c274d2..000000000 --- a/core/src/processing/opengl/tess/PriorityQSort.java +++ /dev/null @@ -1,288 +0,0 @@ -/* -** License Applicability. Except to the extent portions of this file are - -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class PriorityQSort extends PriorityQ { - PriorityQHeap heap; - Object[] keys; - - // JAVA: 'order' contains indices into the keys array. - // This simulates the indirect pointers used in the original C code - // (from Frank Suykens, Luciad.com). - int[] order; - int size, max; - boolean initialized; - PriorityQ.Leq leq; - - public PriorityQSort(PriorityQ.Leq leq) { - heap = new PriorityQHeap(leq); - - keys = new Object[PriorityQ.INIT_SIZE]; - - size = 0; - max = PriorityQ.INIT_SIZE; - initialized = false; - this.leq = leq; - } - -/* really __gl_pqSortDeletePriorityQ */ - @Override - void pqDeletePriorityQ() { - if (heap != null) heap.pqDeletePriorityQ(); - order = null; - keys = null; - } - - private static boolean LT(PriorityQ.Leq leq, Object x, Object y) { - return (!PriorityQ.LEQ(leq, y, x)); - } - - private static boolean GT(PriorityQ.Leq leq, Object x, Object y) { - return (!PriorityQ.LEQ(leq, x, y)); - } - - private static void Swap(int[] array, int a, int b) { - if (true) { - int tmp = array[a]; - array[a] = array[b]; - array[b] = tmp; - } else { - - } - } - - private static class Stack { - int p, r; - } - -/* really __gl_pqSortInit */ - @Override - boolean pqInit() { - int p, r, i, j; - int piv; - Stack[] stack = new Stack[50]; - for (int k = 0; k < stack.length; k++) { - stack[k] = new Stack(); - } - int top = 0; - - int seed = 2016473283; - - /* Create an array of indirect pointers to the keys, so that we - * the handles we have returned are still valid. - */ - order = new int[size + 1]; -/* the previous line is a patch to compensate for the fact that IBM */ -/* machines return a null on a malloc of zero bytes (unlike SGI), */ -/* so we have to put in this defense to guard against a memory */ -/* fault four lines down. from fossum@austin.ibm.com. */ - p = 0; - r = size - 1; - for (piv = 0, i = p; i <= r; ++piv, ++i) { - // indirect pointers: keep an index into the keys array, not a direct pointer to its contents - order[i] = piv; - } - - /* Sort the indirect pointers in descending order, - * using randomized Quicksort - */ - stack[top].p = p; - stack[top].r = r; - ++top; - while (--top >= 0) { - p = stack[top].p; - r = stack[top].r; - while (r > p + 10) { - seed = Math.abs( seed * 1539415821 + 1 ); - i = p + seed % (r - p + 1); - piv = order[i]; - order[i] = order[p]; - order[p] = piv; - i = p - 1; - j = r + 1; - do { - do { - ++i; - } while (GT(leq, keys[order[i]], keys[piv])); - do { - --j; - } while (LT(leq, keys[order[j]], keys[piv])); - Swap(order, i, j); - } while (i < j); - Swap(order, i, j); /* Undo last swap */ - if (i - p < r - j) { - stack[top].p = j + 1; - stack[top].r = r; - ++top; - r = i - 1; - } else { - stack[top].p = p; - stack[top].r = i - 1; - ++top; - p = j + 1; - } - } - /* Insertion sort small lists */ - for (i = p + 1; i <= r; ++i) { - piv = order[i]; - for (j = i; j > p && LT(leq, keys[order[j - 1]], keys[piv]); --j) { - order[j] = order[j - 1]; - } - order[j] = piv; - } - } - max = size; - initialized = true; - heap.pqInit(); /* always succeeds */ - -/* #ifndef NDEBUG - p = order; - r = p + size - 1; - for (i = p; i < r; ++i) { - Assertion.doAssert(LEQ( * * (i + 1), **i )); - } - #endif*/ - - return true; - } - -/* really __gl_pqSortInsert */ -/* returns LONG_MAX iff out of memory */ - @Override - int pqInsert(Object keyNew) { - int curr; - - if (initialized) { - return heap.pqInsert(keyNew); - } - curr = size; - if (++size >= max) { - Object[] saveKey = keys; - - /* If the heap overflows, double its size. */ - max <<= 1; -// pq->keys = (PQHeapKey *)memRealloc( pq->keys,(size_t)(pq->max * sizeof( pq->keys[0] ))); - Object[] pqKeys = new Object[max]; - System.arraycopy( keys, 0, pqKeys, 0, keys.length ); - keys = pqKeys; - if (keys == null) { - keys = saveKey; /* restore ptr to free upon return */ - return Integer.MAX_VALUE; - } - } - assert curr != Integer.MAX_VALUE; - keys[curr] = keyNew; - - /* Negative handles index the sorted array. */ - return -(curr + 1); - } - -/* really __gl_pqSortExtractMin */ - @Override - Object pqExtractMin() { - Object sortMin, heapMin; - - if (size == 0) { - return heap.pqExtractMin(); - } - sortMin = keys[order[size - 1]]; - if (!heap.pqIsEmpty()) { - heapMin = heap.pqMinimum(); - if (LEQ(leq, heapMin, sortMin)) { - return heap.pqExtractMin(); - } - } - do { - --size; - } while (size > 0 && keys[order[size - 1]] == null); - return sortMin; - } - -/* really __gl_pqSortMinimum */ - @Override - Object pqMinimum() { - Object sortMin, heapMin; - - if (size == 0) { - return heap.pqMinimum(); - } - sortMin = keys[order[size - 1]]; - if (!heap.pqIsEmpty()) { - heapMin = heap.pqMinimum(); - if (PriorityQ.LEQ(leq, heapMin, sortMin)) { - return heapMin; - } - } - return sortMin; - } - -/* really __gl_pqSortIsEmpty */ - @Override - boolean pqIsEmpty() { - return (size == 0) && heap.pqIsEmpty(); - } - -/* really __gl_pqSortDelete */ - @Override - void pqDelete(int curr) { - if (curr >= 0) { - heap.pqDelete(curr); - return; - } - curr = -(curr + 1); - assert curr < max && keys[curr] != null; - - keys[curr] = null; - while (size > 0 && keys[order[size - 1]] == null) { - --size; - } - } -} diff --git a/core/src/processing/opengl/tess/Render.java b/core/src/processing/opengl/tess/Render.java deleted file mode 100644 index 17156deda..000000000 --- a/core/src/processing/opengl/tess/Render.java +++ /dev/null @@ -1,558 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -import android.opengl.GLES20; - -class Render { - private static final boolean USE_OPTIMIZED_CODE_PATH = false; - - private Render() { - } - - private static final RenderFan renderFan = new RenderFan(); - private static final RenderStrip renderStrip = new RenderStrip(); - private static final RenderTriangle renderTriangle = new RenderTriangle(); - -/* This structure remembers the information we need about a primitive - * to be able to render it later, once we have determined which - * primitive is able to use the most triangles. - */ - private static class FaceCount { - public FaceCount() { - } - - public FaceCount(long size, GLUhalfEdge eStart, renderCallBack render) { - this.size = size; - this.eStart = eStart; - this.render = render; - } - - long size; /* number of triangles used */ - GLUhalfEdge eStart; /* edge where this primitive starts */ - renderCallBack render; - }; - - private static interface renderCallBack { - void render(GLUtessellatorImpl tess, GLUhalfEdge e, long size); - } - - /************************ Strips and Fans decomposition ******************/ - -/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle - * fans, strips, and separate triangles. A substantial effort is made - * to use as few rendering primitives as possible (ie. to make the fans - * and strips as large as possible). - * - * The rendering output is provided as callbacks (see the api). - */ - public static void __gl_renderMesh(GLUtessellatorImpl tess, GLUmesh mesh) { - GLUface f; - - /* Make a list of separate triangles so we can render them all at once */ - tess.lonelyTriList = null; - - for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { - f.marked = false; - } - for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { - - /* We examine all faces in an arbitrary order. Whenever we find - * an unprocessed face F, we output a group of faces including F - * whose size is maximum. - */ - if (f.inside && !f.marked) { - RenderMaximumFaceGroup(tess, f); - assert (f.marked); - } - } - if (tess.lonelyTriList != null) { - RenderLonelyTriangles(tess, tess.lonelyTriList); - tess.lonelyTriList = null; - } - } - - - static void RenderMaximumFaceGroup(GLUtessellatorImpl tess, GLUface fOrig) { - /* We want to find the largest triangle fan or strip of unmarked faces - * which includes the given face fOrig. There are 3 possible fans - * passing through fOrig (one centered at each vertex), and 3 possible - * strips (one for each CCW permutation of the vertices). Our strategy - * is to try all of these, and take the primitive which uses the most - * triangles (a greedy approach). - */ - GLUhalfEdge e = fOrig.anEdge; - FaceCount max = new FaceCount(); - FaceCount newFace = new FaceCount(); - - max.size = 1; - max.eStart = e; - max.render = renderTriangle; - - if (!tess.flagBoundary) { - newFace = MaximumFan(e); - if (newFace.size > max.size) { - max = newFace; - } - newFace = MaximumFan(e.Lnext); - if (newFace.size > max.size) { - max = newFace; - } - newFace = MaximumFan(e.Onext.Sym); - if (newFace.size > max.size) { - max = newFace; - } - - newFace = MaximumStrip(e); - if (newFace.size > max.size) { - max = newFace; - } - newFace = MaximumStrip(e.Lnext); - if (newFace.size > max.size) { - max = newFace; - } - newFace = MaximumStrip(e.Onext.Sym); - if (newFace.size > max.size) { - max = newFace; - } - } - max.render.render(tess, max.eStart, max.size); - } - - -/* Macros which keep track of faces we have marked temporarily, and allow - * us to backtrack when necessary. With triangle fans, this is not - * really necessary, since the only awkward case is a loop of triangles - * around a single origin vertex. However with strips the situation is - * more complicated, and we need a general tracking method like the - * one here. - */ - private static boolean Marked(GLUface f) { - return !f.inside || f.marked; - } - - private static GLUface AddToTrail(GLUface f, GLUface t) { - f.trail = t; - f.marked = true; - return f; - } - - private static void FreeTrail(GLUface t) { - if (true) { - while (t != null) { - t.marked = false; - t = t.trail; - } - } else { - /* absorb trailing semicolon */ - } - } - - static FaceCount MaximumFan(GLUhalfEdge eOrig) { - /* eOrig.Lface is the face we want to render. We want to find the size - * of a maximal fan around eOrig.Org. To do this we just walk around - * the origin vertex as far as possible in both directions. - */ - FaceCount newFace = new FaceCount(0, null, renderFan); - GLUface trail = null; - GLUhalfEdge e; - - for (e = eOrig; !Marked(e.Lface); e = e.Onext) { - trail = AddToTrail(e.Lface, trail); - ++newFace.size; - } - for (e = eOrig; !Marked(e.Sym.Lface); e = e.Sym.Lnext) { - trail = AddToTrail(e.Sym.Lface, trail); - ++newFace.size; - } - newFace.eStart = e; - /*LINTED*/ - FreeTrail(trail); - return newFace; - } - - - private static boolean IsEven(long n) { - return (n & 0x1L) == 0; - } - - static FaceCount MaximumStrip(GLUhalfEdge eOrig) { - /* Here we are looking for a maximal strip that contains the vertices - * eOrig.Org, eOrig.Dst, eOrig.Lnext.Dst (in that order or the - * reverse, such that all triangles are oriented CCW). - * - * Again we walk forward and backward as far as possible. However for - * strips there is a twist: to get CCW orientations, there must be - * an *even* number of triangles in the strip on one side of eOrig. - * We walk the strip starting on a side with an even number of triangles; - * if both side have an odd number, we are forced to shorten one side. - */ - FaceCount newFace = new FaceCount(0, null, renderStrip); - long headSize = 0, tailSize = 0; - GLUface trail = null; - GLUhalfEdge e, eTail, eHead; - - for (e = eOrig; !Marked(e.Lface); ++tailSize, e = e.Onext) { - trail = AddToTrail(e.Lface, trail); - ++tailSize; - e = e.Lnext.Sym; - if (Marked(e.Lface)) break; - trail = AddToTrail(e.Lface, trail); - } - eTail = e; - - for (e = eOrig; !Marked(e.Sym.Lface); ++headSize, e = e.Sym.Onext.Sym) { - trail = AddToTrail(e.Sym.Lface, trail); - ++headSize; - e = e.Sym.Lnext; - if (Marked(e.Sym.Lface)) break; - trail = AddToTrail(e.Sym.Lface, trail); - } - eHead = e; - - newFace.size = tailSize + headSize; - if (IsEven(tailSize)) { - newFace.eStart = eTail.Sym; - } else if (IsEven(headSize)) { - newFace.eStart = eHead; - } else { - /* Both sides have odd length, we must shorten one of them. In fact, - * we must start from eHead to guarantee inclusion of eOrig.Lface. - */ - --newFace.size; - newFace.eStart = eHead.Onext; - } - /*LINTED*/ - FreeTrail(trail); - return newFace; - } - - private static class RenderTriangle implements renderCallBack { - public void render(GLUtessellatorImpl tess, GLUhalfEdge e, long size) { - /* Just add the triangle to a triangle list, so we can render all - * the separate triangles at once. - */ - assert (size == 1); - tess.lonelyTriList = AddToTrail(e.Lface, tess.lonelyTriList); - } - } - - - static void RenderLonelyTriangles(GLUtessellatorImpl tess, GLUface f) { - /* Now we render all the separate triangles which could not be - * grouped into a triangle fan or strip. - */ - GLUhalfEdge e; - int newState; - int edgeState = -1; /* force edge state output for first vertex */ - - tess.callBeginOrBeginData(GLES20.GL_TRIANGLES); - - for (; f != null; f = f.trail) { - /* Loop once for each edge (there will always be 3 edges) */ - - e = f.anEdge; - do { - if (tess.flagBoundary) { - /* Set the "edge state" to true just before we output the - * first vertex of each edge on the polygon boundary. - */ - newState = (!e.Sym.Lface.inside) ? 1 : 0; - if (edgeState != newState) { - edgeState = newState; - tess.callEdgeFlagOrEdgeFlagData( edgeState != 0); - } - } - tess.callVertexOrVertexData( e.Org.data); - - e = e.Lnext; - } while (e != f.anEdge); - } - tess.callEndOrEndData(); - } - - private static class RenderFan implements renderCallBack { - public void render(GLUtessellatorImpl tess, GLUhalfEdge e, long size) { - /* Render as many CCW triangles as possible in a fan starting from - * edge "e". The fan *should* contain exactly "size" triangles - * (otherwise we've goofed up somewhere). - */ - tess.callBeginOrBeginData(GLES20.GL_TRIANGLE_FAN); - tess.callVertexOrVertexData( e.Org.data); - tess.callVertexOrVertexData( e.Sym.Org.data); - - while (!Marked(e.Lface)) { - e.Lface.marked = true; - --size; - e = e.Onext; - tess.callVertexOrVertexData( e.Sym.Org.data); - } - - assert (size == 0); - tess.callEndOrEndData(); - } - } - - private static class RenderStrip implements renderCallBack { - public void render(GLUtessellatorImpl tess, GLUhalfEdge e, long size) { - /* Render as many CCW triangles as possible in a strip starting from - * edge "e". The strip *should* contain exactly "size" triangles - * (otherwise we've goofed up somewhere). - */ - tess.callBeginOrBeginData(GLES20.GL_TRIANGLE_STRIP); - tess.callVertexOrVertexData( e.Org.data); - tess.callVertexOrVertexData( e.Sym.Org.data); - - while (!Marked(e.Lface)) { - e.Lface.marked = true; - --size; - e = e.Lnext.Sym; - tess.callVertexOrVertexData( e.Org.data); - if (Marked(e.Lface)) break; - - e.Lface.marked = true; - --size; - e = e.Onext; - tess.callVertexOrVertexData( e.Sym.Org.data); - } - - assert (size == 0); - tess.callEndOrEndData(); - } - } - - /************************ Boundary contour decomposition ******************/ - -/* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one - * contour for each face marked "inside". The rendering output is - * provided as callbacks (see the api). - */ - public static void __gl_renderBoundary(GLUtessellatorImpl tess, GLUmesh mesh) { - GLUface f; - GLUhalfEdge e; - - for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { - if (f.inside) { - tess.callBeginOrBeginData(GLES20.GL_LINE_LOOP); - e = f.anEdge; - do { - tess.callVertexOrVertexData( e.Org.data); - e = e.Lnext; - } while (e != f.anEdge); - tess.callEndOrEndData(); - } - } - } - - - /************************ Quick-and-dirty decomposition ******************/ - - private static final int SIGN_INCONSISTENT = 2; - - static int ComputeNormal(GLUtessellatorImpl tess, double[] norm, boolean check) -/* - * If check==false, we compute the polygon normal and place it in norm[]. - * If check==true, we check that each triangle in the fan from v0 has a - * consistent orientation with respect to norm[]. If triangles are - * consistently oriented CCW, return 1; if CW, return -1; if all triangles - * are degenerate return 0; otherwise (no consistent orientation) return - * SIGN_INCONSISTENT. - */ { - CachedVertex[] v = tess.cache; -// CachedVertex vn = v0 + tess.cacheCount; - int vn = tess.cacheCount; -// CachedVertex vc; - int vc; - double dot, xc, yc, zc, xp, yp, zp; - double[] n = new double[3]; - int sign = 0; - - /* Find the polygon normal. It is important to get a reasonable - * normal even when the polygon is self-intersecting (eg. a bowtie). - * Otherwise, the computed normal could be very tiny, but perpendicular - * to the true plane of the polygon due to numerical noise. Then all - * the triangles would appear to be degenerate and we would incorrectly - * decompose the polygon as a fan (or simply not render it at all). - * - * We use a sum-of-triangles normal algorithm rather than the more - * efficient sum-of-trapezoids method (used in CheckOrientation() - * in normal.c). This lets us explicitly reverse the signed area - * of some triangles to get a reasonable normal in the self-intersecting - * case. - */ - if (!check) { - norm[0] = norm[1] = norm[2] = 0.0; - } - - vc = 1; - xc = v[vc].coords[0] - v[0].coords[0]; - yc = v[vc].coords[1] - v[0].coords[1]; - zc = v[vc].coords[2] - v[0].coords[2]; - while (++vc < vn) { - xp = xc; - yp = yc; - zp = zc; - xc = v[vc].coords[0] - v[0].coords[0]; - yc = v[vc].coords[1] - v[0].coords[1]; - zc = v[vc].coords[2] - v[0].coords[2]; - - /* Compute (vp - v0) cross (vc - v0) */ - n[0] = yp * zc - zp * yc; - n[1] = zp * xc - xp * zc; - n[2] = xp * yc - yp * xc; - - dot = n[0] * norm[0] + n[1] * norm[1] + n[2] * norm[2]; - if (!check) { - /* Reverse the contribution of back-facing triangles to get - * a reasonable normal for self-intersecting polygons (see above) - */ - if (dot >= 0) { - norm[0] += n[0]; - norm[1] += n[1]; - norm[2] += n[2]; - } else { - norm[0] -= n[0]; - norm[1] -= n[1]; - norm[2] -= n[2]; - } - } else if (dot != 0) { - /* Check the new orientation for consistency with previous triangles */ - if (dot > 0) { - if (sign < 0) return SIGN_INCONSISTENT; - sign = 1; - } else { - if (sign > 0) return SIGN_INCONSISTENT; - sign = -1; - } - } - } - return sign; - } - -/* __gl_renderCache( tess ) takes a single contour and tries to render it - * as a triangle fan. This handles convex polygons, as well as some - * non-convex polygons if we get lucky. - * - * Returns true if the polygon was successfully rendered. The rendering - * output is provided as callbacks (see the api). - */ - public static boolean __gl_renderCache(GLUtessellatorImpl tess) { - CachedVertex[] v = tess.cache; -// CachedVertex vn = v0 + tess.cacheCount; - int vn = tess.cacheCount; -// CachedVertex vc; - int vc; - double[] norm = new double[3]; - int sign; - - if (tess.cacheCount < 3) { - /* Degenerate contour -- no output */ - return true; - } - - norm[0] = tess.normal[0]; - norm[1] = tess.normal[1]; - norm[2] = tess.normal[2]; - if (norm[0] == 0 && norm[1] == 0 && norm[2] == 0) { - ComputeNormal( tess, norm, false); - } - - sign = ComputeNormal( tess, norm, true); - if (sign == SIGN_INCONSISTENT) { - /* Fan triangles did not have a consistent orientation */ - return false; - } - if (sign == 0) { - /* All triangles were degenerate */ - return true; - } - - if ( !USE_OPTIMIZED_CODE_PATH ) { - return false; - } else { - /* Make sure we do the right thing for each winding rule */ - switch (tess.windingRule) { - case PGLU.GLU_TESS_WINDING_ODD: - case PGLU.GLU_TESS_WINDING_NONZERO: - break; - case PGLU.GLU_TESS_WINDING_POSITIVE: - if (sign < 0) return true; - break; - case PGLU.GLU_TESS_WINDING_NEGATIVE: - if (sign > 0) return true; - break; - case PGLU.GLU_TESS_WINDING_ABS_GEQ_TWO: - return true; - } - - tess.callBeginOrBeginData( tess.boundaryOnly ? GLES20.GL_LINE_LOOP - : (tess.cacheCount > 3) ? GLES20.GL_TRIANGLE_FAN - : GLES20.GL_TRIANGLES); - - tess.callVertexOrVertexData( v[0].data); - if (sign > 0) { - for (vc = 1; vc < vn; ++vc) { - tess.callVertexOrVertexData( v[vc].data); - } - } else { - for (vc = vn - 1; vc > 0; --vc) { - tess.callVertexOrVertexData( v[vc].data); - } - } - tess.callEndOrEndData(); - return true; - } - } -} diff --git a/core/src/processing/opengl/tess/Sweep.java b/core/src/processing/opengl/tess/Sweep.java deleted file mode 100644 index 9117de0d6..000000000 --- a/core/src/processing/opengl/tess/Sweep.java +++ /dev/null @@ -1,1354 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. - -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - - -class Sweep { - private Sweep() { - } - -// #ifdef FOR_TRITE_TEST_PROGRAM -// extern void DebugEvent( GLUtessellator *tess ); -// #else - private static void DebugEvent(GLUtessellatorImpl tess) { - - } -// #endif - -/* - * Invariants for the Edge Dictionary. - * - each pair of adjacent edges e2=Succ(e1) satisfies EdgeLeq(e1,e2) - * at any valid location of the sweep event - * - if EdgeLeq(e2,e1) as well (at any valid sweep event), then e1 and e2 - * share a common endpoint - * - for each e, e.Dst has been processed, but not e.Org - * - each edge e satisfies VertLeq(e.Dst,event) && VertLeq(event,e.Org) - * where "event" is the current sweep line event. - * - no edge e has zero length - * - * Invariants for the Mesh (the processed portion). - * - the portion of the mesh left of the sweep line is a planar graph, - * ie. there is *some* way to embed it in the plane - * - no processed edge has zero length - * - no two processed vertices have identical coordinates - * - each "inside" region is monotone, ie. can be broken into two chains - * of monotonically increasing vertices according to VertLeq(v1,v2) - * - a non-invariant: these chains may intersect (very slightly) - * - * Invariants for the Sweep. - * - if none of the edges incident to the event vertex have an activeRegion - * (ie. none of these edges are in the edge dictionary), then the vertex - * has only right-going edges. - * - if an edge is marked "fixUpperEdge" (it is a temporary edge introduced - * by ConnectRightVertex), then it is the only right-going edge from - * its associated vertex. (This says that these edges exist only - * when it is necessary.) - */ - -/* When we merge two edges into one, we need to compute the combined - * winding of the new edge. - */ - private static void AddWinding(GLUhalfEdge eDst, GLUhalfEdge eSrc) { - eDst.winding += eSrc.winding; - eDst.Sym.winding += eSrc.Sym.winding; - } - - - private static ActiveRegion RegionBelow(ActiveRegion r) { - return ((ActiveRegion) Dict.dictKey(Dict.dictPred(r.nodeUp))); - } - - private static ActiveRegion RegionAbove(ActiveRegion r) { - return ((ActiveRegion) Dict.dictKey(Dict.dictSucc(r.nodeUp))); - } - - static boolean EdgeLeq(GLUtessellatorImpl tess, ActiveRegion reg1, ActiveRegion reg2) -/* - * Both edges must be directed from right to left (this is the canonical - * direction for the upper edge of each region). - * - * The strategy is to evaluate a "t" value for each edge at the - * current sweep line position, given by tess.event. The calculations - * are designed to be very stable, but of course they are not perfect. - * - * Special case: if both edge destinations are at the sweep event, - * we sort the edges by slope (they would otherwise compare equally). - */ { - GLUvertex event = tess.event; - GLUhalfEdge e1, e2; - double t1, t2; - - e1 = reg1.eUp; - e2 = reg2.eUp; - - if (e1.Sym.Org == event) { - if (e2.Sym.Org == event) { - /* Two edges right of the sweep line which meet at the sweep event. - * Sort them by slope. - */ - if (Geom.VertLeq(e1.Org, e2.Org)) { - return Geom.EdgeSign(e2.Sym.Org, e1.Org, e2.Org) <= 0; - } - return Geom.EdgeSign(e1.Sym.Org, e2.Org, e1.Org) >= 0; - } - return Geom.EdgeSign(e2.Sym.Org, event, e2.Org) <= 0; - } - if (e2.Sym.Org == event) { - return Geom.EdgeSign(e1.Sym.Org, event, e1.Org) >= 0; - } - - /* General case - compute signed distance *from* e1, e2 to event */ - t1 = Geom.EdgeEval(e1.Sym.Org, event, e1.Org); - t2 = Geom.EdgeEval(e2.Sym.Org, event, e2.Org); - return (t1 >= t2); - } - - - static void DeleteRegion(GLUtessellatorImpl tess, ActiveRegion reg) { - if (reg.fixUpperEdge) { - /* It was created with zero winding number, so it better be - * deleted with zero winding number (ie. it better not get merged - * with a real edge). - */ - assert (reg.eUp.winding == 0); - } - reg.eUp.activeRegion = null; - Dict.dictDelete(tess.dict, reg.nodeUp); /* __gl_dictListDelete */ - } - - - static boolean FixUpperEdge(ActiveRegion reg, GLUhalfEdge newEdge) -/* - * Replace an upper edge which needs fixing (see ConnectRightVertex). - */ { - assert (reg.fixUpperEdge); - if (!Mesh.__gl_meshDelete(reg.eUp)) return false; - reg.fixUpperEdge = false; - reg.eUp = newEdge; - newEdge.activeRegion = reg; - - return true; - } - - static ActiveRegion TopLeftRegion(ActiveRegion reg) { - GLUvertex org = reg.eUp.Org; - GLUhalfEdge e; - - /* Find the region above the uppermost edge with the same origin */ - do { - reg = RegionAbove(reg); - } while (reg.eUp.Org == org); - - /* If the edge above was a temporary edge introduced by ConnectRightVertex, - * now is the time to fix it. - */ - if (reg.fixUpperEdge) { - e = Mesh.__gl_meshConnect(RegionBelow(reg).eUp.Sym, reg.eUp.Lnext); - if (e == null) return null; - if (!FixUpperEdge(reg, e)) return null; - reg = RegionAbove(reg); - } - return reg; - } - - static ActiveRegion TopRightRegion(ActiveRegion reg) { - GLUvertex dst = reg.eUp.Sym.Org; - - /* Find the region above the uppermost edge with the same destination */ - do { - reg = RegionAbove(reg); - } while (reg.eUp.Sym.Org == dst); - return reg; - } - - static ActiveRegion AddRegionBelow(GLUtessellatorImpl tess, - ActiveRegion regAbove, - GLUhalfEdge eNewUp) -/* - * Add a new active region to the sweep line, *somewhere* below "regAbove" - * (according to where the new edge belongs in the sweep-line dictionary). - * The upper edge of the new region will be "eNewUp". - * Winding number and "inside" flag are not updated. - */ { - ActiveRegion regNew = new ActiveRegion(); - if (regNew == null) throw new RuntimeException(); - - regNew.eUp = eNewUp; - /* __gl_dictListInsertBefore */ - regNew.nodeUp = Dict.dictInsertBefore(tess.dict, regAbove.nodeUp, regNew); - if (regNew.nodeUp == null) throw new RuntimeException(); - regNew.fixUpperEdge = false; - regNew.sentinel = false; - regNew.dirty = false; - - eNewUp.activeRegion = regNew; - return regNew; - } - - static boolean IsWindingInside(GLUtessellatorImpl tess, int n) { - switch (tess.windingRule) { - case PGLU.GLU_TESS_WINDING_ODD: - return (n & 1) != 0; - case PGLU.GLU_TESS_WINDING_NONZERO: - return (n != 0); - case PGLU.GLU_TESS_WINDING_POSITIVE: - return (n > 0); - case PGLU.GLU_TESS_WINDING_NEGATIVE: - return (n < 0); - case PGLU.GLU_TESS_WINDING_ABS_GEQ_TWO: - return (n >= 2) || (n <= -2); - } - /*LINTED*/ -// assert (false); - throw new InternalError(); - /*NOTREACHED*/ - } - - - static void ComputeWinding(GLUtessellatorImpl tess, ActiveRegion reg) { - reg.windingNumber = RegionAbove(reg).windingNumber + reg.eUp.winding; - reg.inside = IsWindingInside(tess, reg.windingNumber); - } - - - static void FinishRegion(GLUtessellatorImpl tess, ActiveRegion reg) -/* - * Delete a region from the sweep line. This happens when the upper - * and lower chains of a region meet (at a vertex on the sweep line). - * The "inside" flag is copied to the appropriate mesh face (we could - * not do this before -- since the structure of the mesh is always - * changing, this face may not have even existed until now). - */ { - GLUhalfEdge e = reg.eUp; - GLUface f = e.Lface; - - f.inside = reg.inside; - f.anEdge = e; /* optimization for __gl_meshTessellateMonoRegion() */ - DeleteRegion(tess, reg); - } - - - static GLUhalfEdge FinishLeftRegions(GLUtessellatorImpl tess, - ActiveRegion regFirst, ActiveRegion regLast) -/* - * We are given a vertex with one or more left-going edges. All affected - * edges should be in the edge dictionary. Starting at regFirst.eUp, - * we walk down deleting all regions where both edges have the same - * origin vOrg. At the same time we copy the "inside" flag from the - * active region to the face, since at this point each face will belong - * to at most one region (this was not necessarily true until this point - * in the sweep). The walk stops at the region above regLast; if regLast - * is null we walk as far as possible. At the same time we relink the - * mesh if necessary, so that the ordering of edges around vOrg is the - * same as in the dictionary. - */ { - ActiveRegion reg, regPrev; - GLUhalfEdge e, ePrev; - - regPrev = regFirst; - ePrev = regFirst.eUp; - while (regPrev != regLast) { - regPrev.fixUpperEdge = false; /* placement was OK */ - reg = RegionBelow(regPrev); - e = reg.eUp; - if (e.Org != ePrev.Org) { - if (!reg.fixUpperEdge) { - /* Remove the last left-going edge. Even though there are no further - * edges in the dictionary with this origin, there may be further - * such edges in the mesh (if we are adding left edges to a vertex - * that has already been processed). Thus it is important to call - * FinishRegion rather than just DeleteRegion. - */ - FinishRegion(tess, regPrev); - break; - } - /* If the edge below was a temporary edge introduced by - * ConnectRightVertex, now is the time to fix it. - */ - e = Mesh.__gl_meshConnect(ePrev.Onext.Sym, e.Sym); - if (e == null) throw new RuntimeException(); - if (!FixUpperEdge(reg, e)) throw new RuntimeException(); - } - - /* Relink edges so that ePrev.Onext == e */ - if (ePrev.Onext != e) { - if (!Mesh.__gl_meshSplice(e.Sym.Lnext, e)) throw new RuntimeException(); - if (!Mesh.__gl_meshSplice(ePrev, e)) throw new RuntimeException(); - } - FinishRegion(tess, regPrev); /* may change reg.eUp */ - ePrev = reg.eUp; - regPrev = reg; - } - return ePrev; - } - - - static void AddRightEdges(GLUtessellatorImpl tess, ActiveRegion regUp, - GLUhalfEdge eFirst, GLUhalfEdge eLast, GLUhalfEdge eTopLeft, - boolean cleanUp) -/* - * Purpose: insert right-going edges into the edge dictionary, and update - * winding numbers and mesh connectivity appropriately. All right-going - * edges share a common origin vOrg. Edges are inserted CCW starting at - * eFirst; the last edge inserted is eLast.Sym.Lnext. If vOrg has any - * left-going edges already processed, then eTopLeft must be the edge - * such that an imaginary upward vertical segment from vOrg would be - * contained between eTopLeft.Sym.Lnext and eTopLeft; otherwise eTopLeft - * should be null. - */ { - ActiveRegion reg, regPrev; - GLUhalfEdge e, ePrev; - boolean firstTime = true; - - /* Insert the new right-going edges in the dictionary */ - e = eFirst; - do { - assert (Geom.VertLeq(e.Org, e.Sym.Org)); - AddRegionBelow(tess, regUp, e.Sym); - e = e.Onext; - } while (e != eLast); - - /* Walk *all* right-going edges from e.Org, in the dictionary order, - * updating the winding numbers of each region, and re-linking the mesh - * edges to match the dictionary ordering (if necessary). - */ - if (eTopLeft == null) { - eTopLeft = RegionBelow(regUp).eUp.Sym.Onext; - } - regPrev = regUp; - ePrev = eTopLeft; - for (; ;) { - reg = RegionBelow(regPrev); - e = reg.eUp.Sym; - if (e.Org != ePrev.Org) break; - - if (e.Onext != ePrev) { - /* Unlink e from its current position, and relink below ePrev */ - if (!Mesh.__gl_meshSplice(e.Sym.Lnext, e)) throw new RuntimeException(); - if (!Mesh.__gl_meshSplice(ePrev.Sym.Lnext, e)) throw new RuntimeException(); - } - /* Compute the winding number and "inside" flag for the new regions */ - reg.windingNumber = regPrev.windingNumber - e.winding; - reg.inside = IsWindingInside(tess, reg.windingNumber); - - /* Check for two outgoing edges with same slope -- process these - * before any intersection tests (see example in __gl_computeInterior). - */ - regPrev.dirty = true; - if (!firstTime && CheckForRightSplice(tess, regPrev)) { - AddWinding(e, ePrev); - DeleteRegion(tess, regPrev); - if (!Mesh.__gl_meshDelete(ePrev)) throw new RuntimeException(); - } - firstTime = false; - regPrev = reg; - ePrev = e; - } - regPrev.dirty = true; - assert (regPrev.windingNumber - e.winding == reg.windingNumber); - - if (cleanUp) { - /* Check for intersections between newly adjacent edges. */ - WalkDirtyRegions(tess, regPrev); - } - } - - - static void CallCombine(GLUtessellatorImpl tess, GLUvertex isect, - Object[] data, float[] weights, boolean needed) { - double[] coords = new double[3]; - - /* Copy coord data in case the callback changes it. */ - coords[0] = isect.coords[0]; - coords[1] = isect.coords[1]; - coords[2] = isect.coords[2]; - - Object[] outData = new Object[1]; - tess.callCombineOrCombineData(coords, data, weights, outData); - isect.data = outData[0]; - if (isect.data == null) { - if (!needed) { - isect.data = data[0]; - } else if (!tess.fatalError) { - /* The only way fatal error is when two edges are found to intersect, - * but the user has not provided the callback necessary to handle - * generated intersection points. - */ - tess.callErrorOrErrorData(PGLU.GLU_TESS_NEED_COMBINE_CALLBACK); - tess.fatalError = true; - } - } - } - - static void SpliceMergeVertices(GLUtessellatorImpl tess, GLUhalfEdge e1, - GLUhalfEdge e2) -/* - * Two vertices with idential coordinates are combined into one. - * e1.Org is kept, while e2.Org is discarded. - */ { - Object[] data = new Object[4]; - float[] weights = new float[]{0.5f, 0.5f, 0.0f, 0.0f}; - - data[0] = e1.Org.data; - data[1] = e2.Org.data; - CallCombine(tess, e1.Org, data, weights, false); - if (!Mesh.__gl_meshSplice(e1, e2)) throw new RuntimeException(); - } - - static void VertexWeights(GLUvertex isect, GLUvertex org, GLUvertex dst, - float[] weights) -/* - * Find some weights which describe how the intersection vertex is - * a linear combination of "org" and "dest". Each of the two edges - * which generated "isect" is allocated 50% of the weight; each edge - * splits the weight between its org and dst according to the - * relative distance to "isect". - */ { - double t1 = Geom.VertL1dist(org, isect); - double t2 = Geom.VertL1dist(dst, isect); - - weights[0] = (float) (0.5 * t2 / (t1 + t2)); - weights[1] = (float) (0.5 * t1 / (t1 + t2)); - isect.coords[0] += weights[0] * org.coords[0] + weights[1] * dst.coords[0]; - isect.coords[1] += weights[0] * org.coords[1] + weights[1] * dst.coords[1]; - isect.coords[2] += weights[0] * org.coords[2] + weights[1] * dst.coords[2]; - } - - - static void GetIntersectData(GLUtessellatorImpl tess, GLUvertex isect, - GLUvertex orgUp, GLUvertex dstUp, - GLUvertex orgLo, GLUvertex dstLo) -/* - * We've computed a new intersection point, now we need a "data" pointer - * from the user so that we can refer to this new vertex in the - * rendering callbacks. - */ { - Object[] data = new Object[4]; - float[] weights = new float[4]; - float[] weights1 = new float[2]; - float[] weights2 = new float[2]; - - data[0] = orgUp.data; - data[1] = dstUp.data; - data[2] = orgLo.data; - data[3] = dstLo.data; - - isect.coords[0] = isect.coords[1] = isect.coords[2] = 0; - VertexWeights(isect, orgUp, dstUp, weights1); - VertexWeights(isect, orgLo, dstLo, weights2); - System.arraycopy(weights1, 0, weights, 0, 2); - System.arraycopy(weights2, 0, weights, 2, 2); - - CallCombine(tess, isect, data, weights, true); - } - - static boolean CheckForRightSplice(GLUtessellatorImpl tess, ActiveRegion regUp) -/* - * Check the upper and lower edge of "regUp", to make sure that the - * eUp.Org is above eLo, or eLo.Org is below eUp (depending on which - * origin is leftmost). - * - * The main purpose is to splice right-going edges with the same - * dest vertex and nearly identical slopes (ie. we can't distinguish - * the slopes numerically). However the splicing can also help us - * to recover from numerical errors. For example, suppose at one - * point we checked eUp and eLo, and decided that eUp.Org is barely - * above eLo. Then later, we split eLo into two edges (eg. from - * a splice operation like this one). This can change the result of - * our test so that now eUp.Org is incident to eLo, or barely below it. - * We must correct this condition to maintain the dictionary invariants. - * - * One possibility is to check these edges for intersection again - * (ie. CheckForIntersect). This is what we do if possible. However - * CheckForIntersect requires that tess.event lies between eUp and eLo, - * so that it has something to fall back on when the intersection - * calculation gives us an unusable answer. So, for those cases where - * we can't check for intersection, this routine fixes the problem - * by just splicing the offending vertex into the other edge. - * This is a guaranteed solution, no matter how degenerate things get. - * Basically this is a combinatorial solution to a numerical problem. - */ { - ActiveRegion regLo = RegionBelow(regUp); - GLUhalfEdge eUp = regUp.eUp; - GLUhalfEdge eLo = regLo.eUp; - - if (Geom.VertLeq(eUp.Org, eLo.Org)) { - if (Geom.EdgeSign(eLo.Sym.Org, eUp.Org, eLo.Org) > 0) return false; - - /* eUp.Org appears to be below eLo */ - if (!Geom.VertEq(eUp.Org, eLo.Org)) { - /* Splice eUp.Org into eLo */ - if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); - if (!Mesh.__gl_meshSplice(eUp, eLo.Sym.Lnext)) throw new RuntimeException(); - regUp.dirty = regLo.dirty = true; - - } else if (eUp.Org != eLo.Org) { - /* merge the two vertices, discarding eUp.Org */ - tess.pq.pqDelete(eUp.Org.pqHandle); /* __gl_pqSortDelete */ - SpliceMergeVertices(tess, eLo.Sym.Lnext, eUp); - } - } else { - if (Geom.EdgeSign(eUp.Sym.Org, eLo.Org, eUp.Org) < 0) return false; - - /* eLo.Org appears to be above eUp, so splice eLo.Org into eUp */ - RegionAbove(regUp).dirty = regUp.dirty = true; - if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); - if (!Mesh.__gl_meshSplice(eLo.Sym.Lnext, eUp)) throw new RuntimeException(); - } - return true; - } - - static boolean CheckForLeftSplice(GLUtessellatorImpl tess, ActiveRegion regUp) -/* - * Check the upper and lower edge of "regUp", to make sure that the - * eUp.Sym.Org is above eLo, or eLo.Sym.Org is below eUp (depending on which - * destination is rightmost). - * - * Theoretically, this should always be true. However, splitting an edge - * into two pieces can change the results of previous tests. For example, - * suppose at one point we checked eUp and eLo, and decided that eUp.Sym.Org - * is barely above eLo. Then later, we split eLo into two edges (eg. from - * a splice operation like this one). This can change the result of - * the test so that now eUp.Sym.Org is incident to eLo, or barely below it. - * We must correct this condition to maintain the dictionary invariants - * (otherwise new edges might get inserted in the wrong place in the - * dictionary, and bad stuff will happen). - * - * We fix the problem by just splicing the offending vertex into the - * other edge. - */ { - ActiveRegion regLo = RegionBelow(regUp); - GLUhalfEdge eUp = regUp.eUp; - GLUhalfEdge eLo = regLo.eUp; - GLUhalfEdge e; - - assert (!Geom.VertEq(eUp.Sym.Org, eLo.Sym.Org)); - - if (Geom.VertLeq(eUp.Sym.Org, eLo.Sym.Org)) { - if (Geom.EdgeSign(eUp.Sym.Org, eLo.Sym.Org, eUp.Org) < 0) return false; - - /* eLo.Sym.Org is above eUp, so splice eLo.Sym.Org into eUp */ - RegionAbove(regUp).dirty = regUp.dirty = true; - e = Mesh.__gl_meshSplitEdge(eUp); - if (e == null) throw new RuntimeException(); - if (!Mesh.__gl_meshSplice(eLo.Sym, e)) throw new RuntimeException(); - e.Lface.inside = regUp.inside; - } else { - if (Geom.EdgeSign(eLo.Sym.Org, eUp.Sym.Org, eLo.Org) > 0) return false; - - /* eUp.Sym.Org is below eLo, so splice eUp.Sym.Org into eLo */ - regUp.dirty = regLo.dirty = true; - e = Mesh.__gl_meshSplitEdge(eLo); - if (e == null) throw new RuntimeException(); - if (!Mesh.__gl_meshSplice(eUp.Lnext, eLo.Sym)) throw new RuntimeException(); - e.Sym.Lface.inside = regUp.inside; - } - return true; - } - - - static boolean CheckForIntersect(GLUtessellatorImpl tess, ActiveRegion regUp) -/* - * Check the upper and lower edges of the given region to see if - * they intersect. If so, create the intersection and add it - * to the data structures. - * - * Returns true if adding the new intersection resulted in a recursive - * call to AddRightEdges(); in this case all "dirty" regions have been - * checked for intersections, and possibly regUp has been deleted. - */ { - ActiveRegion regLo = RegionBelow(regUp); - GLUhalfEdge eUp = regUp.eUp; - GLUhalfEdge eLo = regLo.eUp; - GLUvertex orgUp = eUp.Org; - GLUvertex orgLo = eLo.Org; - GLUvertex dstUp = eUp.Sym.Org; - GLUvertex dstLo = eLo.Sym.Org; - double tMinUp, tMaxLo; - GLUvertex isect = new GLUvertex(); - GLUvertex orgMin; - GLUhalfEdge e; - - assert (!Geom.VertEq(dstLo, dstUp)); - assert (Geom.EdgeSign(dstUp, tess.event, orgUp) <= 0); - assert (Geom.EdgeSign(dstLo, tess.event, orgLo) >= 0); - assert (orgUp != tess.event && orgLo != tess.event); - assert (!regUp.fixUpperEdge && !regLo.fixUpperEdge); - - if (orgUp == orgLo) return false; /* right endpoints are the same */ - - tMinUp = Math.min(orgUp.t, dstUp.t); - tMaxLo = Math.max(orgLo.t, dstLo.t); - if (tMinUp > tMaxLo) return false; /* t ranges do not overlap */ - - if (Geom.VertLeq(orgUp, orgLo)) { - if (Geom.EdgeSign(dstLo, orgUp, orgLo) > 0) return false; - } else { - if (Geom.EdgeSign(dstUp, orgLo, orgUp) < 0) return false; - } - - /* At this point the edges intersect, at least marginally */ - DebugEvent(tess); - - Geom.EdgeIntersect(dstUp, orgUp, dstLo, orgLo, isect); - /* The following properties are guaranteed: */ - assert (Math.min(orgUp.t, dstUp.t) <= isect.t); - assert (isect.t <= Math.max(orgLo.t, dstLo.t)); - assert (Math.min(dstLo.s, dstUp.s) <= isect.s); - assert (isect.s <= Math.max(orgLo.s, orgUp.s)); - - if (Geom.VertLeq(isect, tess.event)) { - /* The intersection point lies slightly to the left of the sweep line, - * so move it until it''s slightly to the right of the sweep line. - * (If we had perfect numerical precision, this would never happen - * in the first place). The easiest and safest thing to do is - * replace the intersection by tess.event. - */ - isect.s = tess.event.s; - isect.t = tess.event.t; - } - /* Similarly, if the computed intersection lies to the right of the - * rightmost origin (which should rarely happen), it can cause - * unbelievable inefficiency on sufficiently degenerate inputs. - * (If you have the test program, try running test54.d with the - * "X zoom" option turned on). - */ - orgMin = Geom.VertLeq(orgUp, orgLo) ? orgUp : orgLo; - if (Geom.VertLeq(orgMin, isect)) { - isect.s = orgMin.s; - isect.t = orgMin.t; - } - - if (Geom.VertEq(isect, orgUp) || Geom.VertEq(isect, orgLo)) { - /* Easy case -- intersection at one of the right endpoints */ - CheckForRightSplice(tess, regUp); - return false; - } - - if ((!Geom.VertEq(dstUp, tess.event) - && Geom.EdgeSign(dstUp, tess.event, isect) >= 0) - || (!Geom.VertEq(dstLo, tess.event) - && Geom.EdgeSign(dstLo, tess.event, isect) <= 0)) { - /* Very unusual -- the new upper or lower edge would pass on the - * wrong side of the sweep event, or through it. This can happen - * due to very small numerical errors in the intersection calculation. - */ - if (dstLo == tess.event) { - /* Splice dstLo into eUp, and process the new region(s) */ - if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); - if (!Mesh.__gl_meshSplice(eLo.Sym, eUp)) throw new RuntimeException(); - regUp = TopLeftRegion(regUp); - if (regUp == null) throw new RuntimeException(); - eUp = RegionBelow(regUp).eUp; - FinishLeftRegions(tess, RegionBelow(regUp), regLo); - AddRightEdges(tess, regUp, eUp.Sym.Lnext, eUp, eUp, true); - return true; - } - if (dstUp == tess.event) { - /* Splice dstUp into eLo, and process the new region(s) */ - if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); - if (!Mesh.__gl_meshSplice(eUp.Lnext, eLo.Sym.Lnext)) throw new RuntimeException(); - regLo = regUp; - regUp = TopRightRegion(regUp); - e = RegionBelow(regUp).eUp.Sym.Onext; - regLo.eUp = eLo.Sym.Lnext; - eLo = FinishLeftRegions(tess, regLo, null); - AddRightEdges(tess, regUp, eLo.Onext, eUp.Sym.Onext, e, true); - return true; - } - /* Special case: called from ConnectRightVertex. If either - * edge passes on the wrong side of tess.event, split it - * (and wait for ConnectRightVertex to splice it appropriately). - */ - if (Geom.EdgeSign(dstUp, tess.event, isect) >= 0) { - RegionAbove(regUp).dirty = regUp.dirty = true; - if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); - eUp.Org.s = tess.event.s; - eUp.Org.t = tess.event.t; - } - if (Geom.EdgeSign(dstLo, tess.event, isect) <= 0) { - regUp.dirty = regLo.dirty = true; - if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); - eLo.Org.s = tess.event.s; - eLo.Org.t = tess.event.t; - } - /* leave the rest for ConnectRightVertex */ - return false; - } - - /* General case -- split both edges, splice into new vertex. - * When we do the splice operation, the order of the arguments is - * arbitrary as far as correctness goes. However, when the operation - * creates a new face, the work done is proportional to the size of - * the new face. We expect the faces in the processed part of - * the mesh (ie. eUp.Lface) to be smaller than the faces in the - * unprocessed original contours (which will be eLo.Sym.Lnext.Lface). - */ - if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); - if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); - if (!Mesh.__gl_meshSplice(eLo.Sym.Lnext, eUp)) throw new RuntimeException(); - eUp.Org.s = isect.s; - eUp.Org.t = isect.t; - eUp.Org.pqHandle = tess.pq.pqInsert(eUp.Org); /* __gl_pqSortInsert */ - if (eUp.Org.pqHandle == Long.MAX_VALUE) { - tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ - tess.pq = null; - throw new RuntimeException(); - } - GetIntersectData(tess, eUp.Org, orgUp, dstUp, orgLo, dstLo); - RegionAbove(regUp).dirty = regUp.dirty = regLo.dirty = true; - return false; - } - - static void WalkDirtyRegions(GLUtessellatorImpl tess, ActiveRegion regUp) -/* - * When the upper or lower edge of any region changes, the region is - * marked "dirty". This routine walks through all the dirty regions - * and makes sure that the dictionary invariants are satisfied - * (see the comments at the beginning of this file). Of course - * new dirty regions can be created as we make changes to restore - * the invariants. - */ { - ActiveRegion regLo = RegionBelow(regUp); - GLUhalfEdge eUp, eLo; - - for (; ;) { - /* Find the lowest dirty region (we walk from the bottom up). */ - while (regLo.dirty) { - regUp = regLo; - regLo = RegionBelow(regLo); - } - if (!regUp.dirty) { - regLo = regUp; - regUp = RegionAbove(regUp); - if (regUp == null || !regUp.dirty) { - /* We've walked all the dirty regions */ - return; - } - } - regUp.dirty = false; - eUp = regUp.eUp; - eLo = regLo.eUp; - - if (eUp.Sym.Org != eLo.Sym.Org) { - /* Check that the edge ordering is obeyed at the Dst vertices. */ - if (CheckForLeftSplice(tess, regUp)) { - - /* If the upper or lower edge was marked fixUpperEdge, then - * we no longer need it (since these edges are needed only for - * vertices which otherwise have no right-going edges). - */ - if (regLo.fixUpperEdge) { - DeleteRegion(tess, regLo); - if (!Mesh.__gl_meshDelete(eLo)) throw new RuntimeException(); - regLo = RegionBelow(regUp); - eLo = regLo.eUp; - } else if (regUp.fixUpperEdge) { - DeleteRegion(tess, regUp); - if (!Mesh.__gl_meshDelete(eUp)) throw new RuntimeException(); - regUp = RegionAbove(regLo); - eUp = regUp.eUp; - } - } - } - if (eUp.Org != eLo.Org) { - if (eUp.Sym.Org != eLo.Sym.Org - && !regUp.fixUpperEdge && !regLo.fixUpperEdge - && (eUp.Sym.Org == tess.event || eLo.Sym.Org == tess.event)) { - /* When all else fails in CheckForIntersect(), it uses tess.event - * as the intersection location. To make this possible, it requires - * that tess.event lie between the upper and lower edges, and also - * that neither of these is marked fixUpperEdge (since in the worst - * case it might splice one of these edges into tess.event, and - * violate the invariant that fixable edges are the only right-going - * edge from their associated vertex). - */ - if (CheckForIntersect(tess, regUp)) { - /* WalkDirtyRegions() was called recursively; we're done */ - return; - } - } else { - /* Even though we can't use CheckForIntersect(), the Org vertices - * may violate the dictionary edge ordering. Check and correct this. - */ - CheckForRightSplice(tess, regUp); - } - } - if (eUp.Org == eLo.Org && eUp.Sym.Org == eLo.Sym.Org) { - /* A degenerate loop consisting of only two edges -- delete it. */ - AddWinding(eLo, eUp); - DeleteRegion(tess, regUp); - if (!Mesh.__gl_meshDelete(eUp)) throw new RuntimeException(); - regUp = RegionAbove(regLo); - } - } - } - - - static void ConnectRightVertex(GLUtessellatorImpl tess, ActiveRegion regUp, - GLUhalfEdge eBottomLeft) -/* - * Purpose: connect a "right" vertex vEvent (one where all edges go left) - * to the unprocessed portion of the mesh. Since there are no right-going - * edges, two regions (one above vEvent and one below) are being merged - * into one. "regUp" is the upper of these two regions. - * - * There are two reasons for doing this (adding a right-going edge): - * - if the two regions being merged are "inside", we must add an edge - * to keep them separated (the combined region would not be monotone). - * - in any case, we must leave some record of vEvent in the dictionary, - * so that we can merge vEvent with features that we have not seen yet. - * For example, maybe there is a vertical edge which passes just to - * the right of vEvent; we would like to splice vEvent into this edge. - * - * However, we don't want to connect vEvent to just any vertex. We don''t - * want the new edge to cross any other edges; otherwise we will create - * intersection vertices even when the input data had no self-intersections. - * (This is a bad thing; if the user's input data has no intersections, - * we don't want to generate any false intersections ourselves.) - * - * Our eventual goal is to connect vEvent to the leftmost unprocessed - * vertex of the combined region (the union of regUp and regLo). - * But because of unseen vertices with all right-going edges, and also - * new vertices which may be created by edge intersections, we don''t - * know where that leftmost unprocessed vertex is. In the meantime, we - * connect vEvent to the closest vertex of either chain, and mark the region - * as "fixUpperEdge". This flag says to delete and reconnect this edge - * to the next processed vertex on the boundary of the combined region. - * Quite possibly the vertex we connected to will turn out to be the - * closest one, in which case we won''t need to make any changes. - */ { - GLUhalfEdge eNew; - GLUhalfEdge eTopLeft = eBottomLeft.Onext; - ActiveRegion regLo = RegionBelow(regUp); - GLUhalfEdge eUp = regUp.eUp; - GLUhalfEdge eLo = regLo.eUp; - boolean degenerate = false; - - if (eUp.Sym.Org != eLo.Sym.Org) { - CheckForIntersect(tess, regUp); - } - - /* Possible new degeneracies: upper or lower edge of regUp may pass - * through vEvent, or may coincide with new intersection vertex - */ - if (Geom.VertEq(eUp.Org, tess.event)) { - if (!Mesh.__gl_meshSplice(eTopLeft.Sym.Lnext, eUp)) throw new RuntimeException(); - regUp = TopLeftRegion(regUp); - if (regUp == null) throw new RuntimeException(); - eTopLeft = RegionBelow(regUp).eUp; - FinishLeftRegions(tess, RegionBelow(regUp), regLo); - degenerate = true; - } - if (Geom.VertEq(eLo.Org, tess.event)) { - if (!Mesh.__gl_meshSplice(eBottomLeft, eLo.Sym.Lnext)) throw new RuntimeException(); - eBottomLeft = FinishLeftRegions(tess, regLo, null); - degenerate = true; - } - if (degenerate) { - AddRightEdges(tess, regUp, eBottomLeft.Onext, eTopLeft, eTopLeft, true); - return; - } - - /* Non-degenerate situation -- need to add a temporary, fixable edge. - * Connect to the closer of eLo.Org, eUp.Org. - */ - if (Geom.VertLeq(eLo.Org, eUp.Org)) { - eNew = eLo.Sym.Lnext; - } else { - eNew = eUp; - } - eNew = Mesh.__gl_meshConnect(eBottomLeft.Onext.Sym, eNew); - if (eNew == null) throw new RuntimeException(); - - /* Prevent cleanup, otherwise eNew might disappear before we've even - * had a chance to mark it as a temporary edge. - */ - AddRightEdges(tess, regUp, eNew, eNew.Onext, eNew.Onext, false); - eNew.Sym.activeRegion.fixUpperEdge = true; - WalkDirtyRegions(tess, regUp); - } - -/* Because vertices at exactly the same location are merged together - * before we process the sweep event, some degenerate cases can't occur. - * However if someone eventually makes the modifications required to - * merge features which are close together, the cases below marked - * TOLERANCE_NONZERO will be useful. They were debugged before the - * code to merge identical vertices in the main loop was added. - */ - private static final boolean TOLERANCE_NONZERO = false; - - static void ConnectLeftDegenerate(GLUtessellatorImpl tess, - ActiveRegion regUp, GLUvertex vEvent) -/* - * The event vertex lies exacty on an already-processed edge or vertex. - * Adding the new vertex involves splicing it into the already-processed - * part of the mesh. - */ { - GLUhalfEdge e, eTopLeft, eTopRight, eLast; - ActiveRegion reg; - - e = regUp.eUp; - if (Geom.VertEq(e.Org, vEvent)) { - /* e.Org is an unprocessed vertex - just combine them, and wait - * for e.Org to be pulled from the queue - */ - assert (TOLERANCE_NONZERO); - SpliceMergeVertices(tess, e, vEvent.anEdge); - return; - } - - if (!Geom.VertEq(e.Sym.Org, vEvent)) { - /* General case -- splice vEvent into edge e which passes through it */ - if (Mesh.__gl_meshSplitEdge(e.Sym) == null) throw new RuntimeException(); - if (regUp.fixUpperEdge) { - /* This edge was fixable -- delete unused portion of original edge */ - if (!Mesh.__gl_meshDelete(e.Onext)) throw new RuntimeException(); - regUp.fixUpperEdge = false; - } - if (!Mesh.__gl_meshSplice(vEvent.anEdge, e)) throw new RuntimeException(); - SweepEvent(tess, vEvent); /* recurse */ - return; - } - - /* vEvent coincides with e.Sym.Org, which has already been processed. - * Splice in the additional right-going edges. - */ - assert (TOLERANCE_NONZERO); - regUp = TopRightRegion(regUp); - reg = RegionBelow(regUp); - eTopRight = reg.eUp.Sym; - eTopLeft = eLast = eTopRight.Onext; - if (reg.fixUpperEdge) { - /* Here e.Sym.Org has only a single fixable edge going right. - * We can delete it since now we have some real right-going edges. - */ - assert (eTopLeft != eTopRight); /* there are some left edges too */ - DeleteRegion(tess, reg); - if (!Mesh.__gl_meshDelete(eTopRight)) throw new RuntimeException(); - eTopRight = eTopLeft.Sym.Lnext; - } - if (!Mesh.__gl_meshSplice(vEvent.anEdge, eTopRight)) throw new RuntimeException(); - if (!Geom.EdgeGoesLeft(eTopLeft)) { - /* e.Sym.Org had no left-going edges -- indicate this to AddRightEdges() */ - eTopLeft = null; - } - AddRightEdges(tess, regUp, eTopRight.Onext, eLast, eTopLeft, true); - } - - - static void ConnectLeftVertex(GLUtessellatorImpl tess, GLUvertex vEvent) -/* - * Purpose: connect a "left" vertex (one where both edges go right) - * to the processed portion of the mesh. Let R be the active region - * containing vEvent, and let U and L be the upper and lower edge - * chains of R. There are two possibilities: - * - * - the normal case: split R into two regions, by connecting vEvent to - * the rightmost vertex of U or L lying to the left of the sweep line - * - * - the degenerate case: if vEvent is close enough to U or L, we - * merge vEvent into that edge chain. The subcases are: - * - merging with the rightmost vertex of U or L - * - merging with the active edge of U or L - * - merging with an already-processed portion of U or L - */ { - ActiveRegion regUp, regLo, reg; - GLUhalfEdge eUp, eLo, eNew; - ActiveRegion tmp = new ActiveRegion(); - - /* assert ( vEvent.anEdge.Onext.Onext == vEvent.anEdge ); */ - - /* Get a pointer to the active region containing vEvent */ - tmp.eUp = vEvent.anEdge.Sym; - /* __GL_DICTLISTKEY */ /* __gl_dictListSearch */ - regUp = (ActiveRegion) Dict.dictKey(Dict.dictSearch(tess.dict, tmp)); - regLo = RegionBelow(regUp); - eUp = regUp.eUp; - eLo = regLo.eUp; - - /* Try merging with U or L first */ - if (Geom.EdgeSign(eUp.Sym.Org, vEvent, eUp.Org) == 0) { - ConnectLeftDegenerate(tess, regUp, vEvent); - return; - } - - /* Connect vEvent to rightmost processed vertex of either chain. - * e.Sym.Org is the vertex that we will connect to vEvent. - */ - reg = Geom.VertLeq(eLo.Sym.Org, eUp.Sym.Org) ? regUp : regLo; - - if (regUp.inside || reg.fixUpperEdge) { - if (reg == regUp) { - eNew = Mesh.__gl_meshConnect(vEvent.anEdge.Sym, eUp.Lnext); - if (eNew == null) throw new RuntimeException(); - } else { - GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(eLo.Sym.Onext.Sym, vEvent.anEdge); - if (tempHalfEdge == null) throw new RuntimeException(); - - eNew = tempHalfEdge.Sym; - } - if (reg.fixUpperEdge) { - if (!FixUpperEdge(reg, eNew)) throw new RuntimeException(); - } else { - ComputeWinding(tess, AddRegionBelow(tess, regUp, eNew)); - } - SweepEvent(tess, vEvent); - } else { - /* The new vertex is in a region which does not belong to the polygon. - * We don''t need to connect this vertex to the rest of the mesh. - */ - AddRightEdges(tess, regUp, vEvent.anEdge, vEvent.anEdge, null, true); - } - } - - - static void SweepEvent(GLUtessellatorImpl tess, GLUvertex vEvent) -/* - * Does everything necessary when the sweep line crosses a vertex. - * Updates the mesh and the edge dictionary. - */ { - ActiveRegion regUp, reg; - GLUhalfEdge e, eTopLeft, eBottomLeft; - - tess.event = vEvent; /* for access in EdgeLeq() */ - DebugEvent(tess); - - /* Check if this vertex is the right endpoint of an edge that is - * already in the dictionary. In this case we don't need to waste - * time searching for the location to insert new edges. - */ - e = vEvent.anEdge; - while (e.activeRegion == null) { - e = e.Onext; - if (e == vEvent.anEdge) { - /* All edges go right -- not incident to any processed edges */ - ConnectLeftVertex(tess, vEvent); - return; - } - } - - /* Processing consists of two phases: first we "finish" all the - * active regions where both the upper and lower edges terminate - * at vEvent (ie. vEvent is closing off these regions). - * We mark these faces "inside" or "outside" the polygon according - * to their winding number, and delete the edges from the dictionary. - * This takes care of all the left-going edges from vEvent. - */ - regUp = TopLeftRegion(e.activeRegion); - if (regUp == null) throw new RuntimeException(); - reg = RegionBelow(regUp); - eTopLeft = reg.eUp; - eBottomLeft = FinishLeftRegions(tess, reg, null); - - /* Next we process all the right-going edges from vEvent. This - * involves adding the edges to the dictionary, and creating the - * associated "active regions" which record information about the - * regions between adjacent dictionary edges. - */ - if (eBottomLeft.Onext == eTopLeft) { - /* No right-going edges -- add a temporary "fixable" edge */ - ConnectRightVertex(tess, regUp, eBottomLeft); - } else { - AddRightEdges(tess, regUp, eBottomLeft.Onext, eTopLeft, eTopLeft, true); - } - } - - -/* Make the sentinel coordinates big enough that they will never be - * merged with real input features. (Even with the largest possible - * input contour and the maximum tolerance of 1.0, no merging will be - * done with coordinates larger than 3 * GLU_TESS_MAX_COORD). - */ - private static final double SENTINEL_COORD = (4.0 * PGLU.GLU_TESS_MAX_COORD); - - static void AddSentinel(GLUtessellatorImpl tess, double t) -/* - * We add two sentinel edges above and below all other edges, - * to avoid special cases at the top and bottom. - */ { - GLUhalfEdge e; - ActiveRegion reg = new ActiveRegion(); - if (reg == null) throw new RuntimeException(); - - e = Mesh.__gl_meshMakeEdge(tess.mesh); - if (e == null) throw new RuntimeException(); - - e.Org.s = SENTINEL_COORD; - e.Org.t = t; - e.Sym.Org.s = -SENTINEL_COORD; - e.Sym.Org.t = t; - tess.event = e.Sym.Org; /* initialize it */ - - reg.eUp = e; - reg.windingNumber = 0; - reg.inside = false; - reg.fixUpperEdge = false; - reg.sentinel = true; - reg.dirty = false; - reg.nodeUp = Dict.dictInsert(tess.dict, reg); /* __gl_dictListInsertBefore */ - if (reg.nodeUp == null) throw new RuntimeException(); - } - - - static void InitEdgeDict(final GLUtessellatorImpl tess) -/* - * We maintain an ordering of edge intersections with the sweep line. - * This order is maintained in a dynamic dictionary. - */ { - /* __gl_dictListNewDict */ - tess.dict = Dict.dictNewDict(tess, new Dict.DictLeq() { - public boolean leq(Object frame, Object key1, Object key2) { - return EdgeLeq(tess, (ActiveRegion) key1, (ActiveRegion) key2); - } - }); - if (tess.dict == null) throw new RuntimeException(); - - AddSentinel(tess, -SENTINEL_COORD); - AddSentinel(tess, SENTINEL_COORD); - } - - - static void DoneEdgeDict(GLUtessellatorImpl tess) { - ActiveRegion reg; - int fixedEdges = 0; - - /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */ - while ((reg = (ActiveRegion) Dict.dictKey(Dict.dictMin(tess.dict))) != null) { - /* - * At the end of all processing, the dictionary should contain - * only the two sentinel edges, plus at most one "fixable" edge - * created by ConnectRightVertex(). - */ - if (!reg.sentinel) { - assert (reg.fixUpperEdge); - assert (++fixedEdges == 1); - } - assert (reg.windingNumber == 0); - DeleteRegion(tess, reg); -/* __gl_meshDelete( reg.eUp );*/ - } - Dict.dictDeleteDict(tess.dict); /* __gl_dictListDeleteDict */ - } - - - static void RemoveDegenerateEdges(GLUtessellatorImpl tess) -/* - * Remove zero-length edges, and contours with fewer than 3 vertices. - */ { - GLUhalfEdge e, eNext, eLnext; - GLUhalfEdge eHead = tess.mesh.eHead; - - /*LINTED*/ - for (e = eHead.next; e != eHead; e = eNext) { - eNext = e.next; - eLnext = e.Lnext; - - if (Geom.VertEq(e.Org, e.Sym.Org) && e.Lnext.Lnext != e) { - /* Zero-length edge, contour has at least 3 edges */ - - SpliceMergeVertices(tess, eLnext, e); /* deletes e.Org */ - if (!Mesh.__gl_meshDelete(e)) throw new RuntimeException(); /* e is a self-loop */ - e = eLnext; - eLnext = e.Lnext; - } - if (eLnext.Lnext == e) { - /* Degenerate contour (one or two edges) */ - - if (eLnext != e) { - if (eLnext == eNext || eLnext == eNext.Sym) { - eNext = eNext.next; - } - if (!Mesh.__gl_meshDelete(eLnext)) throw new RuntimeException(); - } - if (e == eNext || e == eNext.Sym) { - eNext = eNext.next; - } - if (!Mesh.__gl_meshDelete(e)) throw new RuntimeException(); - } - } - } - - static boolean InitPriorityQ(GLUtessellatorImpl tess) -/* - * Insert all vertices into the priority queue which determines the - * order in which vertices cross the sweep line. - */ { - PriorityQ pq; - GLUvertex v, vHead; - - /* __gl_pqSortNewPriorityQ */ - pq = tess.pq = PriorityQ.pqNewPriorityQ(new PriorityQ.Leq() { - public boolean leq(Object key1, Object key2) { - return Geom.VertLeq(((GLUvertex) key1), (GLUvertex) key2); - } - }); - if (pq == null) return false; - - vHead = tess.mesh.vHead; - for (v = vHead.next; v != vHead; v = v.next) { - v.pqHandle = pq.pqInsert(v); /* __gl_pqSortInsert */ - if (v.pqHandle == Long.MAX_VALUE) break; - } - if (v != vHead || !pq.pqInit()) { /* __gl_pqSortInit */ - tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ - tess.pq = null; - return false; - } - - return true; - } - - - static void DonePriorityQ(GLUtessellatorImpl tess) { - tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ - } - - - static boolean RemoveDegenerateFaces(GLUmesh mesh) -/* - * Delete any degenerate faces with only two edges. WalkDirtyRegions() - * will catch almost all of these, but it won't catch degenerate faces - * produced by splice operations on already-processed edges. - * The two places this can happen are in FinishLeftRegions(), when - * we splice in a "temporary" edge produced by ConnectRightVertex(), - * and in CheckForLeftSplice(), where we splice already-processed - * edges to ensure that our dictionary invariants are not violated - * by numerical errors. - * - * In both these cases it is *very* dangerous to delete the offending - * edge at the time, since one of the routines further up the stack - * will sometimes be keeping a pointer to that edge. - */ { - GLUface f, fNext; - GLUhalfEdge e; - - /*LINTED*/ - for (f = mesh.fHead.next; f != mesh.fHead; f = fNext) { - fNext = f.next; - e = f.anEdge; - assert (e.Lnext != e); - - if (e.Lnext.Lnext == e) { - /* A face with only two edges */ - AddWinding(e.Onext, e); - if (!Mesh.__gl_meshDelete(e)) return false; - } - } - return true; - } - - public static boolean __gl_computeInterior(GLUtessellatorImpl tess) -/* - * __gl_computeInterior( tess ) computes the planar arrangement specified - * by the given contours, and further subdivides this arrangement - * into regions. Each region is marked "inside" if it belongs - * to the polygon, according to the rule given by tess.windingRule. - * Each interior region is guaranteed be monotone. - */ { - GLUvertex v, vNext; - - tess.fatalError = false; - - /* Each vertex defines an event for our sweep line. Start by inserting - * all the vertices in a priority queue. Events are processed in - * lexicographic order, ie. - * - * e1 < e2 iff e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y) - */ - RemoveDegenerateEdges(tess); - if (!InitPriorityQ(tess)) return false; /* if error */ - InitEdgeDict(tess); - - /* __gl_pqSortExtractMin */ - while ((v = (GLUvertex) tess.pq.pqExtractMin()) != null) { - for (; ;) { - vNext = (GLUvertex) tess.pq.pqMinimum(); /* __gl_pqSortMinimum */ - if (vNext == null || !Geom.VertEq(vNext, v)) break; - - /* Merge together all vertices at exactly the same location. - * This is more efficient than processing them one at a time, - * simplifies the code (see ConnectLeftDegenerate), and is also - * important for correct handling of certain degenerate cases. - * For example, suppose there are two identical edges A and B - * that belong to different contours (so without this code they would - * be processed by separate sweep events). Suppose another edge C - * crosses A and B from above. When A is processed, we split it - * at its intersection point with C. However this also splits C, - * so when we insert B we may compute a slightly different - * intersection point. This might leave two edges with a small - * gap between them. This kind of error is especially obvious - * when using boundary extraction (GLU_TESS_BOUNDARY_ONLY). - */ - vNext = (GLUvertex) tess.pq.pqExtractMin(); /* __gl_pqSortExtractMin*/ - SpliceMergeVertices(tess, v.anEdge, vNext.anEdge); - } - SweepEvent(tess, v); - } - - /* Set tess.event for debugging purposes */ - /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */ - tess.event = ((ActiveRegion) Dict.dictKey(Dict.dictMin(tess.dict))).eUp.Org; - DebugEvent(tess); - DoneEdgeDict(tess); - DonePriorityQ(tess); - - if (!RemoveDegenerateFaces(tess.mesh)) return false; - Mesh.__gl_meshCheckMesh(tess.mesh); - - return true; - } -} diff --git a/core/src/processing/opengl/tess/TessMono.java b/core/src/processing/opengl/tess/TessMono.java deleted file mode 100644 index 683197f6c..000000000 --- a/core/src/processing/opengl/tess/TessMono.java +++ /dev/null @@ -1,243 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class TessMono { -/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region - * (what else would it do??) The region must consist of a single - * loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this - * case means that any vertical line intersects the interior of the - * region in a single interval. - * - * Tessellation consists of adding interior edges (actually pairs of - * half-edges), to split the region into non-overlapping triangles. - * - * The basic idea is explained in Preparata and Shamos (which I don''t - * have handy right now), although their implementation is more - * complicated than this one. The are two edge chains, an upper chain - * and a lower chain. We process all vertices from both chains in order, - * from right to left. - * - * The algorithm ensures that the following invariant holds after each - * vertex is processed: the untessellated region consists of two - * chains, where one chain (say the upper) is a single edge, and - * the other chain is concave. The left vertex of the single edge - * is always to the left of all vertices in the concave chain. - * - * Each step consists of adding the rightmost unprocessed vertex to one - * of the two chains, and forming a fan of triangles from the rightmost - * of two chain endpoints. Determining whether we can add each triangle - * to the fan is a simple orientation test. By making the fan as large - * as possible, we restore the invariant (check it yourself). - */ - static boolean __gl_meshTessellateMonoRegion(GLUface face, boolean avoidDegenerateTris) { - GLUhalfEdge up, lo; - - /* All edges are oriented CCW around the boundary of the region. - * First, find the half-edge whose origin vertex is rightmost. - * Since the sweep goes from left to right, face->anEdge should - * be close to the edge we want. - */ - up = face.anEdge; - assert (up.Lnext != up && up.Lnext.Lnext != up); - - for (; Geom.VertLeq(up.Sym.Org, up.Org); up = up.Onext.Sym) - ; - for (; Geom.VertLeq(up.Org, up.Sym.Org); up = up.Lnext) - ; - lo = up.Onext.Sym; - - boolean mustConnect = false; // hack for avoidDegenerateTris - - while (up.Lnext != lo) { - if (avoidDegenerateTris && !mustConnect) { - // Skip over regions where several vertices are collinear, - // to try to avoid producing degenerate (zero-area) triangles - // - // The "mustConnect" flag is a hack to try to avoid - // skipping too large regions and causing incorrect - // triangulations. This entire modification is overall - // not robust and needs more work - if (Geom.EdgeCos(lo.Lnext.Org, lo.Org, lo.Lnext.Lnext.Org) <= -Geom.ONE_MINUS_EPSILON) { - // Lines around lo - do { - lo = lo.Onext.Sym; - mustConnect = true; - } while (up.Lnext != lo && - Geom.EdgeCos(lo.Lnext.Org, lo.Org, lo.Lnext.Lnext.Org) <= -Geom.ONE_MINUS_EPSILON); - } else if (Geom.EdgeCos(up.Onext.Sym.Org, up.Org, up.Onext.Sym.Onext.Sym.Org) <= -Geom.ONE_MINUS_EPSILON) { - // Lines around up - do { - up = up.Lnext; - mustConnect = true; - } while (up.Lnext != lo && - Geom.EdgeCos(up.Onext.Sym.Org, up.Org, up.Onext.Sym.Onext.Sym.Org) <= -Geom.ONE_MINUS_EPSILON); - } - - if (up.Lnext == lo) - break; - } - - if (Geom.VertLeq(up.Sym.Org, lo.Org)) { - /* up.Sym.Org is on the left. It is safe to form triangles from lo.Org. - * The EdgeGoesLeft test guarantees progress even when some triangles - * are CW, given that the upper and lower chains are truly monotone. - */ - while (lo.Lnext != up && (Geom.EdgeGoesLeft(lo.Lnext) - || Geom.EdgeSign(lo.Org, lo.Sym.Org, lo.Lnext.Sym.Org) <= 0)) { - GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo); - mustConnect = false; - if (tempHalfEdge == null) return false; - lo = tempHalfEdge.Sym; - } - lo = lo.Onext.Sym; - } else { - /* lo.Org is on the left. We can make CCW triangles from up.Sym.Org. */ - while (lo.Lnext != up && (Geom.EdgeGoesRight(up.Onext.Sym) - || Geom.EdgeSign(up.Sym.Org, up.Org, up.Onext.Sym.Org) >= 0)) { - GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(up, up.Onext.Sym); - mustConnect = false; - if (tempHalfEdge == null) return false; - up = tempHalfEdge.Sym; - } - up = up.Lnext; - } - } - - /* Now lo.Org == up.Sym.Org == the leftmost vertex. The remaining region - * can be tessellated in a fan from this leftmost vertex. - */ - assert (lo.Lnext != up); - while (lo.Lnext.Lnext != up) { - GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo); - if (tempHalfEdge == null) return false; - lo = tempHalfEdge.Sym; - } - - return true; - } - - -/* __gl_meshTessellateInterior( mesh ) tessellates each region of - * the mesh which is marked "inside" the polygon. Each such region - * must be monotone. - */ - public static boolean __gl_meshTessellateInterior(GLUmesh mesh, boolean avoidDegenerateTris) { - GLUface f, next; - - /*LINTED*/ - for (f = mesh.fHead.next; f != mesh.fHead; f = next) { - /* Make sure we don''t try to tessellate the new triangles. */ - next = f.next; - if (f.inside) { - if (!__gl_meshTessellateMonoRegion(f, avoidDegenerateTris)) return false; - } - } - - return true; - } - - -/* __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces - * which are not marked "inside" the polygon. Since further mesh operations - * on NULL faces are not allowed, the main purpose is to clean up the - * mesh so that exterior loops are not represented in the data structure. - */ - public static void __gl_meshDiscardExterior(GLUmesh mesh) { - GLUface f, next; - - /*LINTED*/ - for (f = mesh.fHead.next; f != mesh.fHead; f = next) { - /* Since f will be destroyed, save its next pointer. */ - next = f.next; - if (!f.inside) { - Mesh.__gl_meshZapFace(f); - } - } - } - -// private static final int MARKED_FOR_DELETION = 0x7fffffff; - -/* __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the - * winding numbers on all edges so that regions marked "inside" the - * polygon have a winding number of "value", and regions outside - * have a winding number of 0. - * - * If keepOnlyBoundary is TRUE, it also deletes all edges which do not - * separate an interior region from an exterior one. - */ - public static boolean __gl_meshSetWindingNumber(GLUmesh mesh, int value, boolean keepOnlyBoundary) { - GLUhalfEdge e, eNext; - - for (e = mesh.eHead.next; e != mesh.eHead; e = eNext) { - eNext = e.next; - if (e.Sym.Lface.inside != e.Lface.inside) { - - /* This is a boundary edge (one side is interior, one is exterior). */ - e.winding = (e.Lface.inside) ? value : -value; - } else { - - /* Both regions are interior, or both are exterior. */ - if (!keepOnlyBoundary) { - e.winding = 0; - } else { - if (!Mesh.__gl_meshDelete(e)) return false; - } - } - } - return true; - } - -} diff --git a/core/src/processing/opengl/tess/TessState.java b/core/src/processing/opengl/tess/TessState.java deleted file mode 100644 index 123d3bf71..000000000 --- a/core/src/processing/opengl/tess/TessState.java +++ /dev/null @@ -1,61 +0,0 @@ -/* -* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. -* All rights reserved. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 2.0 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** NOTE: The Original Code (as defined below) has been licensed to Sun -** Microsystems, Inc. ("Sun") under the SGI Free Software License B -** (Version 1.1), shown above ("SGI License"). Pursuant to Section -** 3.2(3) of the SGI License, Sun is distributing the Covered Code to -** you under an alternative license ("Alternative License"). This -** Alternative License includes all of the provisions of the SGI License -** except that Section 2.2 and 11 are omitted. Any differences between -** the Alternative License and the SGI License are offered solely by Sun -** and not by SGI. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: The application programming interfaces -** established by SGI in conjunction with the Original Code are The -** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released -** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version -** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X -** Window System(R) (Version 1.3), released October 19, 1998. This software -** was created using the OpenGL(R) version 1.2.1 Sample Implementation -** published by SGI, but has not been independently verified as being -** compliant with the OpenGL(R) version 1.2.1 Specification. -** -** Author: Eric Veach, July 1994 -** Java Port: Pepijn Van Eeckhoudt, July 2003 -** Java Port: Nathan Parker Burg, August 2003 -** Processing integration: Andres Colubri, February 2012 -*/ - -package processing.opengl.tess; - -class TessState { - public static final int T_DORMANT = 0; - public static final int T_IN_POLYGON = 1; - public static final int T_IN_CONTOUR = 2; -} diff --git a/debug/apps/arscene/build.gradle b/debug/apps/arscene/build.gradle deleted file mode 100644 index f125ce512..000000000 --- a/debug/apps/arscene/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 33 - defaultConfig { - applicationId "processing.tests.arscene" - minSdkVersion 23 - targetSdkVersion 33 - versionCode 1 - versionName "1.0" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - productFlavors { - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - namespace 'arscene' -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - testImplementation 'junit:junit:4.13.2' - implementation project(':libs:processing-core') - implementation project(':libs:processing-ar') - implementation 'androidx.appcompat:appcompat:1.6.0' - implementation 'com.google.ar:core:1.35.0' -} diff --git a/debug/apps/arscene/gradle.properties b/debug/apps/arscene/gradle.properties deleted file mode 100644 index 5465fec0e..000000000 --- a/debug/apps/arscene/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/debug/apps/arscene/src/main/AndroidManifest.xml b/debug/apps/arscene/src/main/AndroidManifest.xml deleted file mode 100644 index a4adeca84..000000000 --- a/debug/apps/arscene/src/main/AndroidManifest.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/debug/apps/arscene/src/main/java/arscene/MainActivity.java b/debug/apps/arscene/src/main/java/arscene/MainActivity.java deleted file mode 100644 index 3ad989d87..000000000 --- a/debug/apps/arscene/src/main/java/arscene/MainActivity.java +++ /dev/null @@ -1,105 +0,0 @@ -package arscene; - -import android.Manifest; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.os.Bundle; -import android.content.Intent; -import android.provider.Settings; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.Toast; - -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - -import processing.android.PFragment; -import processing.android.CompatUtils; -import processing.core.PApplet; - -public class MainActivity extends AppCompatActivity { - private static final int CAMERA_PERMISSION_CODE = 0; - private static final String CAMERA_PERMISSION = Manifest.permission.CAMERA; - private static final String CAMERA_PERMISSION_MESSAGE = "Camera permission is needed to use AR"; - - private PApplet sketch; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - FrameLayout frame = new FrameLayout(this); - frame.setId(CompatUtils.getUniqueViewId()); - setContentView(frame, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - - sketch = new Sketch(); - PFragment fragment = new PFragment(sketch); - fragment.setView(frame, this); - } - - @Override - protected void onResume() { - super.onResume(); - if (!hasCameraPermission()) requestCameraPermission(); - } - - @Override - public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (!hasCameraPermission()) { - Toast.makeText(this, CAMERA_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show(); - if (!shouldShowRequestPermissionRationale()) { - launchPermissionSettings(); - } - finish(); - } - - if (sketch != null) { - sketch.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - } - - @Override - public void onNewIntent(Intent intent) { - super.onNewIntent(intent); - if (sketch != null) { - sketch.onNewIntent(intent); - } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (sketch != null) { - sketch.onActivityResult(requestCode, resultCode, data); - } - } - - @Override - public void onBackPressed() { - if (sketch != null) { - sketch.onBackPressed(); - } - } - - private boolean hasCameraPermission() { - int res = ContextCompat.checkSelfPermission(this, CAMERA_PERMISSION); - return res == PackageManager.PERMISSION_GRANTED; - } - - private void requestCameraPermission() { - ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_CODE); - } - - private boolean shouldShowRequestPermissionRationale() { - return ActivityCompat.shouldShowRequestPermissionRationale(this, CAMERA_PERMISSION); - } - - private void launchPermissionSettings() { - Intent intent = new Intent(); - intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - intent.setData(Uri.fromParts("package", this.getPackageName(), null)); - this.startActivity(intent); - } -} diff --git a/debug/apps/arscene/src/main/java/arscene/Sketch.java b/debug/apps/arscene/src/main/java/arscene/Sketch.java deleted file mode 100644 index cf01c9b38..000000000 --- a/debug/apps/arscene/src/main/java/arscene/Sketch.java +++ /dev/null @@ -1,103 +0,0 @@ -package arscene; - -import java.util.ArrayList; - -import processing.ar.*; -import processing.core.PApplet; - -public class Sketch extends PApplet { - ARTracker tracker; - ARAnchor touchAnchor; - ArrayList trackAnchors; - float angle; - - public void settings() { - fullScreen(AR); - } - - public void setup() { - tracker = new ARTracker(this); - tracker.start(); - trackAnchors = new ArrayList(); - } - - public void draw() { - // The AR Core session, frame and camera can be accessed through Processing's surface object - // to obtain the full information about the AR scene: -// ARSurface surface = (ARSurface) getSurface(); -// surface.camera.getPose(); -// surface.frame.getLightEstimate(); - - lights(); - - if (mousePressed) { - // Create new anchor at the current touch point - if (touchAnchor != null) touchAnchor.dispose(); - ARTrackable hit = tracker.get(mouseX, mouseY); - if (hit != null) touchAnchor = new ARAnchor(hit); - else touchAnchor = null; - } - - // Draw objects attached to each anchor - for (ARAnchor anchor : trackAnchors) { - if (anchor.isTracking()) drawBox(anchor, 255, 255, 255); - - // It is very important to dispose anchors once they are no longer tracked. - if (anchor.isStopped()) anchor.dispose(); - } - if (touchAnchor != null) drawBox(touchAnchor, 255, 0, 0); - - // Conveniency function in the tracker object to remove disposed anchors from a list - tracker.clearAnchors(trackAnchors); - - // Draw trackable planes - for (int i = 0; i < tracker.count(); i++) { - ARTrackable trackable = tracker.get(i); - if (!trackable.isTracking()) continue; - - pushMatrix(); - trackable.transform(); - if (mousePressed && trackable.isSelected(mouseX, mouseY)) { - fill(255, 0, 0, 100); - } else { - fill(255, 100); - } - beginShape(); - float[] points = trackable.getPolygon(); - for (int n = 0; n < points.length / 2; n++) { - float x = points[2 * n]; - float z = points[2 * n + 1]; - vertex(x, 0, z); - } - endShape(); - popMatrix(); - } - - angle += 0.1; - } - - public void drawBox(ARAnchor anchor, int r, int g, int b) { - anchor.attach(); - fill(r, g, b); - rotateY(angle); - box(0.15f); - anchor.detach(); - } - - public void trackableEvent(ARTrackable t) { - if (trackAnchors.size() < 10) { - float x0 = 0, y0 = 0; - if (t.isWallPlane()) { - // The new trackable is a wall, so adding the anchor 0.3 meters to its side - x0 = 0.3f; - } else if (t.isFloorPlane()) { - // The new trackable is a floor plane, so adding the anchor 0.3 meters above it - y0 = 0.3f; - } else { - // The new trackable is a floor plane, so adding the anchor 0.3 meters below it - y0 = -0.3f; - } - trackAnchors.add(new ARAnchor(t, x0, y0, 0)); - } - } -} diff --git a/debug/apps/arscene/src/main/res/layout/main.xml b/debug/apps/arscene/src/main/res/layout/main.xml deleted file mode 100644 index 4b602d5f6..000000000 --- a/debug/apps/arscene/src/main/res/layout/main.xml +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/debug/apps/arscene/src/main/res/mipmap-hdpi/ic_launcher.png b/debug/apps/arscene/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index cde69bccc..000000000 Binary files a/debug/apps/arscene/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/arscene/src/main/res/mipmap-mdpi/ic_launcher.png b/debug/apps/arscene/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index c133a0cbd..000000000 Binary files a/debug/apps/arscene/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/arscene/src/main/res/mipmap-xhdpi/ic_launcher.png b/debug/apps/arscene/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index bfa42f0e7..000000000 Binary files a/debug/apps/arscene/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/arscene/src/main/res/mipmap-xxhdpi/ic_launcher.png b/debug/apps/arscene/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 324e72cdd..000000000 Binary files a/debug/apps/arscene/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/arscene/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/debug/apps/arscene/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index aee44e138..000000000 Binary files a/debug/apps/arscene/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/arscene/src/main/res/values/strings.xml b/debug/apps/arscene/src/main/res/values/strings.xml deleted file mode 100644 index f57f444bd..000000000 --- a/debug/apps/arscene/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - AR Test - diff --git a/debug/apps/arscene/src/main/res/values/styles.xml b/debug/apps/arscene/src/main/res/values/styles.xml deleted file mode 100644 index 375954d4a..000000000 --- a/debug/apps/arscene/src/main/res/values/styles.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/debug/apps/fast2d/build.gradle b/debug/apps/fast2d/build.gradle deleted file mode 100644 index e9a8b3cde..000000000 --- a/debug/apps/fast2d/build.gradle +++ /dev/null @@ -1,32 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 33 - defaultConfig { - applicationId "processing.tests.fast2d" - minSdkVersion 17 - targetSdkVersion 33 - versionCode 1 - versionName "1.0" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - productFlavors { - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - namespace 'fast2d' -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - testImplementation 'junit:junit:4.13.2' - implementation project(':libs:processing-core') - implementation 'androidx.appcompat:appcompat:1.6.0' -} diff --git a/debug/apps/fast2d/gradle.properties b/debug/apps/fast2d/gradle.properties deleted file mode 100644 index 5465fec0e..000000000 --- a/debug/apps/fast2d/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/debug/apps/fast2d/src/main/AndroidManifest.xml b/debug/apps/fast2d/src/main/AndroidManifest.xml deleted file mode 100644 index 5204a615a..000000000 --- a/debug/apps/fast2d/src/main/AndroidManifest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/debug/apps/fast2d/src/main/assets/blur.glsl b/debug/apps/fast2d/src/main/assets/blur.glsl deleted file mode 100644 index 2aa9d6079..000000000 --- a/debug/apps/fast2d/src/main/assets/blur.glsl +++ /dev/null @@ -1,42 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -#define PROCESSING_TEXTURE_SHADER - -uniform sampler2D texture; -uniform vec2 texOffset; - -varying vec4 vertColor; -varying vec4 vertTexCoord; - -void main(void) { - // Grouping texcoord variables in order to make it work in the GMA 950. See post #13 - // in this thread: - // http://www.idevgames.com/forums/thread-3467.html - vec2 tc0 = vertTexCoord.st + vec2(-texOffset.s, -texOffset.t); - vec2 tc1 = vertTexCoord.st + vec2( 0.0, -texOffset.t); - vec2 tc2 = vertTexCoord.st + vec2(+texOffset.s, -texOffset.t); - vec2 tc3 = vertTexCoord.st + vec2(-texOffset.s, 0.0); - vec2 tc4 = vertTexCoord.st + vec2( 0.0, 0.0); - vec2 tc5 = vertTexCoord.st + vec2(+texOffset.s, 0.0); - vec2 tc6 = vertTexCoord.st + vec2(-texOffset.s, +texOffset.t); - vec2 tc7 = vertTexCoord.st + vec2( 0.0, +texOffset.t); - vec2 tc8 = vertTexCoord.st + vec2(+texOffset.s, +texOffset.t); - - vec4 col0 = texture2D(texture, tc0); - vec4 col1 = texture2D(texture, tc1); - vec4 col2 = texture2D(texture, tc2); - vec4 col3 = texture2D(texture, tc3); - vec4 col4 = texture2D(texture, tc4); - vec4 col5 = texture2D(texture, tc5); - vec4 col6 = texture2D(texture, tc6); - vec4 col7 = texture2D(texture, tc7); - vec4 col8 = texture2D(texture, tc8); - - vec4 sum = (1.0 * col0 + 2.0 * col1 + 1.0 * col2 + - 2.0 * col3 + 4.0 * col4 + 2.0 * col4 + - 1.0 * col5 + 2.0 * col6 + 1.0 * col7) / 16.0; - gl_FragColor = vec4(sum.rgb, 1.0) * vertColor; -} diff --git a/debug/apps/fast2d/src/main/assets/bot1.svg b/debug/apps/fast2d/src/main/assets/bot1.svg deleted file mode 100644 index 3c56f2d60..000000000 --- a/debug/apps/fast2d/src/main/assets/bot1.svg +++ /dev/null @@ -1,160 +0,0 @@ - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/debug/apps/fast2d/src/main/assets/edges.glsl b/debug/apps/fast2d/src/main/assets/edges.glsl deleted file mode 100644 index 42d4383ba..000000000 --- a/debug/apps/fast2d/src/main/assets/edges.glsl +++ /dev/null @@ -1,36 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -varying vec4 vertColor; -varying vec2 vertTexCoord; -varying float vertTexFactor; - -uniform sampler2D texture; -uniform vec2 texScale; - -void main(void) { - vec2 tc0 = vertTexCoord.st + vec2(-texScale.s, -texScale.t); - vec2 tc1 = vertTexCoord.st + vec2( 0.0, -texScale.t); - vec2 tc2 = vertTexCoord.st + vec2(+texScale.s, -texScale.t); - vec2 tc3 = vertTexCoord.st + vec2(-texScale.s, 0.0); - vec2 tc4 = vertTexCoord.st + vec2( 0.0, 0.0); - vec2 tc5 = vertTexCoord.st + vec2(+texScale.s, 0.0); - vec2 tc6 = vertTexCoord.st + vec2(-texScale.s, +texScale.t); - vec2 tc7 = vertTexCoord.st + vec2( 0.0, +texScale.t); - vec2 tc8 = vertTexCoord.st + vec2(+texScale.s, +texScale.t); - - vec4 col0 = texture2D(texture, tc0); - vec4 col1 = texture2D(texture, tc1); - vec4 col2 = texture2D(texture, tc2); - vec4 col3 = texture2D(texture, tc3); - vec4 col4 = texture2D(texture, tc4); - vec4 col5 = texture2D(texture, tc5); - vec4 col6 = texture2D(texture, tc6); - vec4 col7 = texture2D(texture, tc7); - vec4 col8 = texture2D(texture, tc8); - - vec4 sum = 8.0 * col4 - (col0 + col1 + col2 + col3 + col5 + col6 + col7 + col8); - gl_FragColor = vec4(sum.rgb, 1.0) * vertColor; -} diff --git a/debug/apps/fast2d/src/main/assets/frag.glsl b/debug/apps/fast2d/src/main/assets/frag.glsl deleted file mode 100644 index 94fd39b36..000000000 --- a/debug/apps/fast2d/src/main/assets/frag.glsl +++ /dev/null @@ -1,10 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -varying vec4 vertColor; - -void main() { - gl_FragColor = vertColor; -} diff --git a/debug/apps/fast2d/src/main/assets/img.png b/debug/apps/fast2d/src/main/assets/img.png deleted file mode 100644 index 82fa26300..000000000 Binary files a/debug/apps/fast2d/src/main/assets/img.png and /dev/null differ diff --git a/debug/apps/fast2d/src/main/assets/leaves.jpg b/debug/apps/fast2d/src/main/assets/leaves.jpg deleted file mode 100644 index 72c86a092..000000000 Binary files a/debug/apps/fast2d/src/main/assets/leaves.jpg and /dev/null differ diff --git a/debug/apps/fast2d/src/main/assets/vert.glsl b/debug/apps/fast2d/src/main/assets/vert.glsl deleted file mode 100644 index 6c0069068..000000000 --- a/debug/apps/fast2d/src/main/assets/vert.glsl +++ /dev/null @@ -1,16 +0,0 @@ -uniform mat4 transform; - -attribute vec3 position; -attribute vec4 color; - -varying vec4 vertColor; - -void main() { - gl_Position = transform * vec4(position, 1); - - //we avoid affecting the Z component by the transform - //because it would mess up our depth testing - gl_Position.z = position.z; - - vertColor = color.zyxw; -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/MainActivity.java b/debug/apps/fast2d/src/main/java/fast2d/MainActivity.java deleted file mode 100644 index c164255fa..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/MainActivity.java +++ /dev/null @@ -1,104 +0,0 @@ -package fast2d; - -import android.os.Bundle; -import android.content.Intent; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import androidx.appcompat.app.AppCompatActivity; - -import processing.android.PFragment; -import processing.android.CompatUtils; -import processing.core.PApplet; - -public class MainActivity extends AppCompatActivity { -// private int TEST = 1; // Basic self-intersecting polygon -// private int TEST = 2; // Mouse controlled polygon -// private int TEST = 3; // Textured poly -// private int TEST = 4; // Text rendering - private int TEST = 5; // Shapes benchmark -// private int TEST = 6; // Duplicated vertex -// private int TEST = 7; // User-defined contours -// private int TEST = 8; // Primitive types -// private int TEST = 9; // Arc test -// private int TEST = 10; // Arc test -// private int TEST = 11; // Load and display SVG -// private int TEST = 12; // Filter test -// private int TEST = 13; // Custom shader test (texture) -// private int TEST = 14; // Custom shader test (no texture) - - private PApplet sketch; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - FrameLayout frame = new FrameLayout(this); - frame.setId(CompatUtils.getUniqueViewId()); - setContentView(frame, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - - if (TEST == 1) { - sketch = new SketchBasicPoly(); - } else if (TEST == 2) { - sketch = new SketchMousePoly(); - } else if (TEST == 3) { - sketch = new SketchTexturedPoly(); - } else if (TEST == 4) { - sketch = new SketchDisplayText(); - } else if (TEST == 5) { - sketch = new SketchShapeBenchmark(); - } else if (TEST == 6) { - sketch = new SketchDuplicatedVert(); - } else if (TEST == 7) { - sketch = new SketchUserDefinedContours(); - } else if (TEST == 8) { - sketch = new SketchPrimitiveTypes(); - } else if (TEST == 9) { - sketch = new SketchArcTest(); - } else if (TEST == 10) { - sketch = new SketchCurveTest(); - } else if (TEST == 11) { - sketch = new SketchLoadDisplaySVG(); - } else if (TEST == 12) { - sketch = new SketchFilterTest(); - } else if (TEST == 13) { - sketch = new SketchCustomShader(); - } else if (TEST == 14) { - sketch = new SketchShaderNoTex(); - } - - PFragment fragment = new PFragment(sketch); - fragment.setView(frame, this); - } - - @Override - public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (sketch != null) { - sketch.onRequestPermissionsResult( - requestCode, permissions, grantResults); - } - } - - @Override - public void onNewIntent(Intent intent) { - super.onNewIntent(intent); - if (sketch != null) { - sketch.onNewIntent(intent); - } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (sketch != null) { - sketch.onActivityResult(requestCode, resultCode, data); - } - } - - @Override - public void onBackPressed() { - if (sketch != null) { - sketch.onBackPressed(); - } - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/Sketch.java b/debug/apps/fast2d/src/main/java/fast2d/Sketch.java deleted file mode 100644 index 4bd118d34..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/Sketch.java +++ /dev/null @@ -1,560 +0,0 @@ -package fast2d; - -import android.opengl.GLES20; - -import processing.core.PApplet; -import processing.core.PShape; -import processing.opengl.PShader; -import processing.core.PImage; -import processing.core.PFont; -import processing.core.PVector; -import java.util.ArrayList; -import processing.opengl.PGraphics2DX; - -public class Sketch extends PApplet { - boolean keyboard = false; - boolean wireframe = false; - - int join = MITER, cap = SQUARE, mode = OPEN; - - PImage img; - PFont font; - - float sc = 1; - float weight = 1; - - boolean runDemo[] = new boolean[10]; - - //useful for debugging - private boolean printDemo = false; - - //data for demo 2 - int[] c = new int[4096]; - ArrayList points = new ArrayList(); - - - public void settings() { - fullScreen(P2DX); -// fullScreen(P2D); - } - - public void setup() { -// orientation(LANDSCAPE); - - //pardon the silly image - img = loadImage("leaves.jpg"); - font = createFont("SansSerif", displayDensity * 72); - - //setup for demo 2 - for (int i = 0; i < c.length; ++i) { - c[i] = color(random(255), random(255), random(255)); - } - } - - public void draw() { - background(255); - - fill(255, 0, 63, 127); - stroke(255, 0, 255, 127); - strokeWeight(12 * displayDensity); - strokeJoin(ROUND); - noStroke(); - - if (keyPressed && key == 'z') { - sc /= 1.01; - } else if (keyPressed && key == 'x') { - sc *= 1.01; - } else if (keyPressed && key == 'c') { - weight /= 1.01; - } else if (keyPressed && key == 'v') { - weight *= 1.01; - } - - scale(sc); - -// println(); -// println("FRAME #" + frameCount); -// println(); - - if (frameCount % 10 == 0) println((int) frameRate + " fps"); - - strokeCap(cap); - strokeJoin(join); - - if (runDemo[5]) demo5(); - if (runDemo[2]) demo2(); - fill(255, 0, 255, 127); - if (runDemo[1]) demo1(); - if (runDemo[3]) demo3(); - if (runDemo[4]) demo4(); - translate(100, 200); - if (runDemo[3]) demo3(); - if (runDemo[6]) demo6(); - if (runDemo[7]) demo7(); - if (runDemo[8]) demo8(); - if (runDemo[9]) demo9(); - if (runDemo[0]) demo10(); - } - - //basic self-intersecting polygon - private void demo1() { - if (printDemo) println("demo1"); - - strokeWeight(6 * weight * displayDensity); - stroke(0, 127, 95, 191); - beginShape(); - vertex(100, 200); - vertex(200, 100); - vertex(300, 200); - vertex(400, 100); - vertex(350, 200); - vertex(450, 100); - - vertex(300, 300); - vertex(mouseX, mouseY); - vertex(600, 200); - - vertex(550, 100); - vertex(550, 400); - vertex(750, 400); - vertex(750, 600); - vertex(100, 600); - endShape(mode); - } - - - //mouse controlled polygon - private void demo2() { - if (printDemo) println("demo2"); - - //NOTE: we draw each vertex with a random fill color to test how it behaves. - //in P2D, the colors are interpolated across the triangles output by the GLU tessellator. - //in JAVA2D, when endShape() is called, the currently active color is used for all vertices. - //for now P4D follows the behavior of P2D, but switching to JAVA2D's behavior - //would allow us to simplify our implementation a bit - beginShape(); - for (int i = 0; i < points.size(); ++i) { - fill(c[i]); - vertex(points.get(i).x, points.get(i).y); - } - endShape(); - } - - - //textured polygon - private void demo3() { - if (printDemo) println("demo3"); - - //test that textured shapes and tint() work correctly - float s = 4; - beginShape(); - texture(img); - vertex(10*s, 20*s, 0, 0); - tint(0, 255, 127, 127); - vertex(80*s, 5*s, 800, 0); - vertex(95*s, 90*s, 800, 800); - noTint(); - vertex(40*s, 95*s, 0, 800); - endShape(); - - //test that image() function works correctly - tint(255, 31); - rotate(-1); - image(img, -200, 100); - rotate(1); - tint(255); - image(img, 700, 100, 200, 100); - } - - //text rendering - private void demo4() { - if (printDemo) println("demo4"); - - textFont(font); - text("Now is the time for all good men to come to the aid of their country.\n" - + "If they do not the quick brown fox may never jump over the lazy sleeping dog again.\n" - + "He may, however, take up knitting as a suitable hobby for all retired quick brown foxes.\n" - + "This is test #1 of 9,876,543,210.\n" - + "Collect them all!", 0, 100); - } - - //shapes benchmark - private void demo5() { - if (printDemo) println("demo5"); - - strokeWeight(2 * displayDensity); - stroke(0); - fill(200); - - float dev = 10; //deviation - - //change these parameters to benchmark various things - int unit = 10; - //line, triangle, rect, ellipse, point - int[] amount = { 20, 15, 10, 5, 40 }; - - for (int i = 0; i < amount[0]*unit; ++i) { - float x = random(width); - float y = random(height); - line(x, y, x + random(-dev, dev), y + random(-dev, dev)); - } - - for (int i = 0; i < amount[1]*unit; ++i) { - float x = random(width); - float y = random(height); - triangle(x, y, - x + random(-dev*2, dev*2), y + random(-dev*2, dev*2), - x + random(-dev*2, dev*2), y + random(-dev*2, dev*2)); - } - - for (int i = 0; i < amount[2]*unit; ++i) { - rect(random(width), random(height), random(dev), random(dev)); - } - - for (int i = 0; i < amount[3]*unit; ++i) { - ellipse(random(width), random(height), random(dev*2), random(dev*2)); - } - - for (int i = 0; i < amount[4]*unit; ++i) { - point(random(width), random(height)); - } - - //large ellipse to test smoothness of outline - ellipse(width/2, height/2, width/2, height/4); - } - - //duplicate vertex test - private void demo6() { - if (printDemo) println("demo6"); - - //NOTE: yes, this produces the wrong result in P4D - //see PGraphics4D.shapeVertex() for why - beginShape(); - vertex(500, 300); - vertex(600, 400); //dupe - vertex(700, 300); - vertex(650, 300); - vertex(600, 400); //dupe - vertex(550, 300); - endShape(CLOSE); - } - - //user-define contours - private void demo7() { - if (printDemo) println("demo7"); - - //from https://processing.org/reference/beginContour_.html - - fill(127, 255, 127); - stroke(255, 0, 0); - beginShape(); - // Exterior part of shape, clockwise winding - vertex(-40, -40); - vertex(40, -40); - vertex(40, 40); - vertex(-40, 40); - // Interior part of shape, counter-clockwise winding - beginContour(); - vertex(-20, -20); - vertex(-20, 20); - vertex(20, 20); - vertex(20, -20); - endContour(); - endShape(CLOSE); - } - - //primitive types - private void demo8() { - if (printDemo) println("demo8"); - - //from https://processing.org/reference/beginShape_.html - - stroke(0); - strokeWeight(4 * displayDensity); - fill(255, 127, 127); - - pushMatrix(); - resetMatrix(); - scale(2); - - beginShape(); - vertex(30, 20); - vertex(85, 20); - vertex(85, 75); - vertex(30, 75); - endShape(CLOSE); - - translate(100, 0); - - beginShape(POINTS); - vertex(30, 20); - vertex(85, 20); - vertex(85, 75); - vertex(30, 75); - endShape(); - - translate(100, 0); - - beginShape(LINES); - vertex(30, 40); - vertex(85, 20); - vertex(85, 75); - vertex(30, 75); - endShape(); - - translate(100, 0); - - pushStyle(); - noFill(); - beginShape(); - vertex(30, 20); - vertex(85, 20); - vertex(85, 75); - vertex(30, 75); - endShape(); - popStyle(); - - translate(100, 0); - - pushStyle(); - noFill(); - beginShape(); - vertex(30, 20); - vertex(85, 20); - vertex(85, 75); - vertex(30, 75); - endShape(CLOSE); - popStyle(); - - translate(100, 0); - - beginShape(TRIANGLES); - vertex(30, 75); - vertex(40, 20); - vertex(50, 75); - vertex(60, 20); - vertex(70, 75); - vertex(80, 20); - endShape(); - - resetMatrix(); - scale(2); - translate(0, 100); - - beginShape(TRIANGLE_STRIP); - vertex(30, 75); - vertex(40, 20); - vertex(50, 75); - vertex(60, 20); - vertex(70, 75); - vertex(80, 20); - vertex(90, 75); - endShape(); - - translate(100, 0); - - beginShape(TRIANGLE_FAN); - vertex(57.5f, 50); - vertex(57.5f, 15); - vertex(92, 50); - vertex(57.5f, 85); - vertex(22, 50); - vertex(57.5f, 15); - endShape(); - - translate(100, 0); - - beginShape(QUADS); - vertex(30, 20); - vertex(30, 75); - vertex(50, 75); - vertex(50, 20); - vertex(65, 20); - vertex(65, 75); - vertex(85, 75); - vertex(85, 20); - endShape(); - - translate(100, 0); - - beginShape(QUAD_STRIP); - vertex(30, 20); - vertex(30, 75); - vertex(50, 20); - vertex(50, 75); - vertex(65, 20); - vertex(65, 75); - vertex(85, 20); - vertex(85, 75); - endShape(); - - translate(100, 0); - - beginShape(); - vertex(20, 20); - vertex(40, 20); - vertex(40, 40); - vertex(60, 40); - vertex(60, 60); - vertex(20, 60); - endShape(CLOSE); - - //test handling of concave and self-intersecting quads - //NOTE: JAVA2D currently draws these correctly, but P2D does not - resetMatrix(); - scale(2); - translate(0, 200); - strokeWeight(2 * displayDensity); - float t = frameCount * 0.01f; - - beginShape(QUADS); - vertex(50, 10); - vertex(90, 50); - vertex(30 + 20*sin(t), 70 + 20*cos(t)); - vertex(30 - 20*sin(t), 70 - 20*cos(t)); - endShape(CLOSE); - - translate(100, 0); - - beginShape(QUAD_STRIP); - vertex(50, 10); - vertex(90, 50); - vertex(30 + 20*sin(t), 70 + 20*cos(t)); - vertex(30 - 20*sin(t), 70 - 20*cos(t)); - endShape(CLOSE); - - popMatrix(); - } - - //testing angular stuff - private void demo9() { - if (printDemo) println("demo9"); - - strokeWeight(4 * displayDensity); - stroke(127, 0, 0); - fill(255, 255, 255); - - //testing the behavior of floating point % operator (for dealing with angles) - float py = 0; - for (int i = 0; i < width; ++i) { - float x = (i - width/2) * 0.1f; - float y = height/2 - (x % PI) * 10; - line(i, y, i - 1, py); - py = y; - } - - //testing the behavior of P2D arc() at various angles - //NOTE: arcs with negative angle aren't drawn - arc(100, 100, 100, 100, -1, new PVector(mouseX, mouseY).sub(100, 100).heading()); - - //test for whether LINES primitive type has self-overlap - //NOTE: it does in JAVA2D, but not in P2D - stroke(0, 127, 127, 127); - beginShape(LINES); - vertex(0, 0); - vertex(width, height + 100); - vertex(width, 0); - vertex(0, height + 100); - endShape(); - } - - //curve tests - private void demo10() { - if (printDemo) println("demo10"); - - //these cause errors in P4D because we haven't implemented them yet - //so they're disabled in the demo for now - if (getGraphics() instanceof PGraphics2DX) { - return; - } - - noFill(); - stroke(0); - strokeWeight(4 * displayDensity); - pushMatrix(); - scale(2); - - beginShape(); - curveVertex(84, 91); - curveVertex(84, 91); - curveVertex(68, 19); - curveVertex(21, 17); - curveVertex(32, 100); - curveVertex(32, 100); - endShape(); - - translate(100, 0); - - beginShape(); - vertex(30, 20); - bezierVertex(80, 0, 80, 75, 30, 75); - bezierVertex(50, 80, 60, 25, 30, 20); - endShape(); - - translate(100, 0); - - beginShape(); - vertex(20, 20); - quadraticVertex(80, 20, 50, 50); - quadraticVertex(20, 80, 80, 80); - vertex(80, 60); - endShape(); - - popMatrix(); - } - - public void mousePressed() { - if (keyboard) { - closeKeyboard(); - keyboard = false; - } else { - if (0.9 * height < mouseY) { - openKeyboard(); - keyboard = true; - } else { - // behavior for demo 2 - points.add(new PVector(mouseX, mouseY)); - } - } - } - - public void mouseDragged() { - if ( mouseY < 0.1 * height) { - points.get(points.size() - 1).x = mouseX; - points.get(points.size() - 1).y = mouseY; - } - } - - public void keyPressed() { - if (key == 'q') { - join = MITER; - } else if (key == 'w') { - join = BEVEL; - } else if (key == 'e') { - join = ROUND; - } else if (key == 'a') { - cap = SQUARE; - } else if (key == 's') { - cap = PROJECT; - } else if (key == 'd') { - cap = ROUND; - } else if (key == 'r') { - mode = OPEN; - } else if (key == 'f') { - mode = CLOSE; - } else if (key == 't') { -// PGraphics2DX.premultiplyMatrices = true; - } else if (key == 'g') { -// PGraphics2DX.premultiplyMatrices = false; - } else if (key == ' ') { -// PJOGL pgl = (PJOGL)((PGraphics2D)this.g).pgl; -// if (wireframe) -// pgl.gl.getGL4().glPolygonMode(GL4.GL_FRONT_AND_BACK, GL4.GL_FILL); -// else -// pgl.gl.getGL4().glPolygonMode(GL4.GL_FRONT_AND_BACK, GL4.GL_LINE); -// wireframe = !wireframe; - } else if (key - '0' >= 0 && key - '0' < 10) { - runDemo[key - '0'] = !runDemo[key - '0']; - } - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchArcTest.java b/debug/apps/fast2d/src/main/java/fast2d/SketchArcTest.java deleted file mode 100644 index d873db96c..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchArcTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package fast2d; - -import processing.core.PApplet; -import processing.core.PVector; - -public class SketchArcTest extends PApplet { - float weight = 1; - - int join = MITER; - int cap = SQUARE; - int mode = OPEN; - - public void settings() { - fullScreen(P2DX); - } - - public void setup() { - strokeCap(cap); - strokeJoin(join); - } - - public void draw() { - background(255); - - strokeWeight(4 * displayDensity); - stroke(127, 0, 0); - fill(255, 255, 255); - - //testing the behavior of floating point % operator (for dealing with angles) - float py = 0; - for (int i = 0; i < width; ++i) { - float x = (i - width/2) * 0.1f; - float y = height/2 - (x % PI) * 10; - line(i, y, i - 1, py); - py = y; - } - - //testing the behavior of P2D arc() at various angles - //NOTE: arcs with negative angle aren't drawn - arc(100, 100, 100, 100, -1, new PVector(mouseX, mouseY).sub(100, 100).heading()); - - //test for whether LINES primitive type has self-overlap - //NOTE: it does in JAVA2D, but not in P2D - stroke(0, 127, 127, 127); - beginShape(LINES); - vertex(0, 0); - vertex(width, height + 100); - vertex(width, 0); - vertex(0, height + 100); - endShape(); - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchBasicPoly.java b/debug/apps/fast2d/src/main/java/fast2d/SketchBasicPoly.java deleted file mode 100644 index 2d92ed81b..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchBasicPoly.java +++ /dev/null @@ -1,48 +0,0 @@ -package fast2d; - -import processing.core.PApplet; - -public class SketchBasicPoly extends PApplet { - float weight = 1; - - int join = MITER; - int cap = SQUARE; - int mode = OPEN; - - public void settings() { - fullScreen(P2DX); - } - - public void setup() { - strokeCap(cap); - strokeJoin(join); - } - - public void draw() { - background(255); - - fill(255, 0, 63, 127); - translate(100, 200); - - strokeWeight(6 * weight * displayDensity); - stroke(0, 127, 95, 191); - beginShape(); - vertex(100, 200); - vertex(200, 100); - vertex(300, 200); - vertex(400, 100); - vertex(350, 200); - vertex(450, 100); - - vertex(300, 300); - vertex(mouseX, mouseY); - vertex(600, 200); - - vertex(550, 100); - vertex(550, 400); - vertex(750, 400); - vertex(750, 600); - vertex(100, 600); - endShape(mode); - } -} \ No newline at end of file diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchCurveTest.java b/debug/apps/fast2d/src/main/java/fast2d/SketchCurveTest.java deleted file mode 100644 index 55c1b391a..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchCurveTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package fast2d; - -import processing.core.PApplet; -import processing.opengl.PGraphics2DX; - -public class SketchCurveTest extends PApplet { - int join = MITER; - int cap = SQUARE; - - public void settings() { - fullScreen(P2DX); - } - - public void setup() { - strokeCap(cap); - strokeJoin(join); - } - - public void draw() { - background(255); - - //these cause errors in P4D because we haven't implemented them yet - //so they're disabled in the demo for now - if (getGraphics() instanceof PGraphics2DX) { - return; - } - - noFill(); - stroke(0); - strokeWeight(4 * displayDensity); - pushMatrix(); - scale(2); - - beginShape(); - curveVertex(84, 91); - curveVertex(84, 91); - curveVertex(68, 19); - curveVertex(21, 17); - curveVertex(32, 100); - curveVertex(32, 100); - endShape(); - - translate(100, 0); - - beginShape(); - vertex(30, 20); - bezierVertex(80, 0, 80, 75, 30, 75); - bezierVertex(50, 80, 60, 25, 30, 20); - endShape(); - - translate(100, 0); - - beginShape(); - vertex(20, 20); - quadraticVertex(80, 20, 50, 50); - quadraticVertex(20, 80, 80, 80); - vertex(80, 60); - endShape(); - - popMatrix(); - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchCustomShader.java b/debug/apps/fast2d/src/main/java/fast2d/SketchCustomShader.java deleted file mode 100644 index d8036d06e..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchCustomShader.java +++ /dev/null @@ -1,36 +0,0 @@ -package fast2d; - -import processing.core.PApplet; -import processing.core.PImage; -import processing.opengl.PShader; - -public class SketchCustomShader extends PApplet { - PShader edges; - PImage img; - boolean enabled = true; - - public void settings() { -// fullScreen(P2D); - fullScreen(P2DX); - } - - public void setup() { - orientation(LANDSCAPE); - img = loadImage("leaves.jpg"); - edges = loadShader("edges.glsl"); - } - - public void draw() { - if (enabled == true) { - shader(edges); - } - image(img, 0, 0, width, height); - } - - public void mousePressed() { - enabled = !enabled; - if (!enabled) { - resetShader(); - } - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchDisplayText.java b/debug/apps/fast2d/src/main/java/fast2d/SketchDisplayText.java deleted file mode 100644 index b79c08b02..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchDisplayText.java +++ /dev/null @@ -1,27 +0,0 @@ -package fast2d; - -import processing.core.PApplet; -import processing.core.PFont; - -public class SketchDisplayText extends PApplet { - PFont font; - - public void settings() { - fullScreen(P2DX); - } - - public void setup() { - font = createFont("SansSerif", displayDensity * 72); - } - - public void draw() { - background(255); - - textFont(font); - text("Now is the time for all good men to come to the aid of their country.\n" - + "If they do not the quick brown fox may never jump over the lazy sleeping dog again.\n" - + "He may, however, take up knitting as a suitable hobby for all retired quick brown foxes.\n" - + "This is test #1 of 9,876,543,210.\n" - + "Collect them all!", 0, 100); - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchDuplicatedVert.java b/debug/apps/fast2d/src/main/java/fast2d/SketchDuplicatedVert.java deleted file mode 100644 index f3093f81d..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchDuplicatedVert.java +++ /dev/null @@ -1,32 +0,0 @@ -package fast2d; - -import processing.core.PApplet; - -public class SketchDuplicatedVert extends PApplet { - int join = MITER; - int cap = SQUARE; - - public void settings() { - fullScreen(P2DX); - } - - public void setup() { - strokeCap(cap); - strokeJoin(join); - } - - public void draw() { - background(255); - - //NOTE: yes, this produces the wrong result in P4D - //see PGraphics4D.shapeVertex() for why - beginShape(); - vertex(500, 300); - vertex(600, 400); //dupe - vertex(700, 300); - vertex(650, 300); - vertex(600, 400); //dupe - vertex(550, 300); - endShape(CLOSE); - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchFilterTest.java b/debug/apps/fast2d/src/main/java/fast2d/SketchFilterTest.java deleted file mode 100644 index 3b73ccc83..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchFilterTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package fast2d; - -import processing.core.PApplet; -import processing.opengl.PShader; - -public class SketchFilterTest extends PApplet { - PShader blur; - - public void settings() { -// fullScreen(P2D); - fullScreen(P2DX); - } - - public void setup() { -// orientation(LANDSCAPE); - blur = loadShader("blur.glsl"); - stroke(255, 0, 0); - rectMode(CENTER); - strokeWeight(5 * displayDensity); - } - - public void draw() { - filter(blur); - rect(mouseX, mouseY, 150, 150); - ellipse(mouseX, mouseY, 100, 100); - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchLoadDisplaySVG.java b/debug/apps/fast2d/src/main/java/fast2d/SketchLoadDisplaySVG.java deleted file mode 100644 index aa146fb59..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchLoadDisplaySVG.java +++ /dev/null @@ -1,22 +0,0 @@ -package fast2d; - -import processing.core.PApplet; -import processing.core.PShape; - -public class SketchLoadDisplaySVG extends PApplet { - PShape bot; - - public void settings() { - fullScreen(P2DX); - } - - public void setup() { - bot = loadShape("bot1.svg"); - } - - public void draw() { - background(102); - shape(bot, 110, 90, 100, 100); // Draw at coordinate (110, 90) at size 100 x 100 - shape(bot, 280, 40); // Draw at coordinate (280, 40) at the default size - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchMousePoly.java b/debug/apps/fast2d/src/main/java/fast2d/SketchMousePoly.java deleted file mode 100644 index 39e5e9a15..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchMousePoly.java +++ /dev/null @@ -1,52 +0,0 @@ -package fast2d; - -import java.util.ArrayList; - -import processing.core.PApplet; -import processing.core.PVector; - -public class SketchMousePoly extends PApplet { - float weight = 1; - - //data for demo 2 - int[] c = new int[4096]; - ArrayList points = new ArrayList(); - - public void settings() { - fullScreen(P2DX); - } - - public void setup() { - //setup for demo 2 - for (int i = 0; i < c.length; ++i) { - c[i] = color(random(255), random(255), random(255)); - } - } - - public void draw() { - background(255); - - noStroke(); - - //NOTE: we draw each vertex with a random fill color to test how it behaves. - //in P2D, the colors are interpolated across the triangles output by the GLU tessellator. - //in JAVA2D, when endShape() is called, the currently active color is used for all vertices. - //for now P4D follows the behavior of P2D, but switching to JAVA2D's behavior - //would allow us to simplify our implementation a bit - beginShape(); - for (int i = 0; i < points.size(); ++i) { - fill(c[i]); - vertex(points.get(i).x, points.get(i).y); - } - endShape(); - } - - public void mousePressed() { - points.add(new PVector(mouseX, mouseY)); - } - - public void mouseDragged() { - points.get(points.size() - 1).x = mouseX; - points.get(points.size() - 1).y = mouseY; - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchPrimitiveTypes.java b/debug/apps/fast2d/src/main/java/fast2d/SketchPrimitiveTypes.java deleted file mode 100644 index b14593c31..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchPrimitiveTypes.java +++ /dev/null @@ -1,182 +0,0 @@ -package fast2d; - -import processing.core.PApplet; - -public class SketchPrimitiveTypes extends PApplet { - float weight = 1; - - int join = MITER; - int cap = SQUARE; - int mode = OPEN; - - public void settings() { - fullScreen(P2DX); - } - - public void setup() { - strokeCap(cap); - strokeJoin(join); - } - - public void draw() { - background(255); - - //from https://processing.org/reference/beginShape_.html - - stroke(0); - strokeWeight(4 * displayDensity); - fill(255, 127, 127); - - pushMatrix(); - resetMatrix(); - scale(2); - - beginShape(); - vertex(30, 20); - vertex(85, 20); - vertex(85, 75); - vertex(30, 75); - endShape(CLOSE); - - translate(100, 0); - - beginShape(POINTS); - vertex(30, 20); - vertex(85, 20); - vertex(85, 75); - vertex(30, 75); - endShape(); - - translate(100, 0); - - beginShape(LINES); - vertex(30, 40); - vertex(85, 20); - vertex(85, 75); - vertex(30, 75); - endShape(); - - translate(100, 0); - - pushStyle(); - noFill(); - beginShape(); - vertex(30, 20); - vertex(85, 20); - vertex(85, 75); - vertex(30, 75); - endShape(); - popStyle(); - - translate(100, 0); - - pushStyle(); - noFill(); - beginShape(); - vertex(30, 20); - vertex(85, 20); - vertex(85, 75); - vertex(30, 75); - endShape(CLOSE); - popStyle(); - - translate(100, 0); - - beginShape(TRIANGLES); - vertex(30, 75); - vertex(40, 20); - vertex(50, 75); - vertex(60, 20); - vertex(70, 75); - vertex(80, 20); - endShape(); - - resetMatrix(); - scale(2); - translate(0, 100); - - beginShape(TRIANGLE_STRIP); - vertex(30, 75); - vertex(40, 20); - vertex(50, 75); - vertex(60, 20); - vertex(70, 75); - vertex(80, 20); - vertex(90, 75); - endShape(); - - translate(100, 0); - - beginShape(TRIANGLE_FAN); - vertex(57.5f, 50); - vertex(57.5f, 15); - vertex(92, 50); - vertex(57.5f, 85); - vertex(22, 50); - vertex(57.5f, 15); - endShape(); - - translate(100, 0); - - beginShape(QUADS); - vertex(30, 20); - vertex(30, 75); - vertex(50, 75); - vertex(50, 20); - vertex(65, 20); - vertex(65, 75); - vertex(85, 75); - vertex(85, 20); - endShape(); - - translate(100, 0); - - beginShape(QUAD_STRIP); - vertex(30, 20); - vertex(30, 75); - vertex(50, 20); - vertex(50, 75); - vertex(65, 20); - vertex(65, 75); - vertex(85, 20); - vertex(85, 75); - endShape(); - - translate(100, 0); - - beginShape(); - vertex(20, 20); - vertex(40, 20); - vertex(40, 40); - vertex(60, 40); - vertex(60, 60); - vertex(20, 60); - endShape(CLOSE); - - //test handling of concave and self-intersecting quads - //NOTE: JAVA2D currently draws these correctly, but P2D does not - resetMatrix(); - scale(2); - translate(0, 200); - strokeWeight(2 * displayDensity); - float t = frameCount * 0.01f; - - beginShape(QUADS); - vertex(50, 10); - vertex(90, 50); - vertex(30 + 20*sin(t), 70 + 20*cos(t)); - vertex(30 - 20*sin(t), 70 - 20*cos(t)); - endShape(CLOSE); - - translate(100, 0); - - beginShape(QUAD_STRIP); - vertex(50, 10); - vertex(90, 50); - vertex(30 + 20*sin(t), 70 + 20*cos(t)); - vertex(30 - 20*sin(t), 70 - 20*cos(t)); - endShape(CLOSE); - - popMatrix(); - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchShaderNoTex.java b/debug/apps/fast2d/src/main/java/fast2d/SketchShaderNoTex.java deleted file mode 100644 index 5abfb4c70..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchShaderNoTex.java +++ /dev/null @@ -1,24 +0,0 @@ -package fast2d; - -import processing.core.PApplet; -import processing.opengl.PShader; - -public class SketchShaderNoTex extends PApplet { - PShader sh; - - public void settings() { -// fullScreen(P2D); - fullScreen(P2DX); - } - - public void setup() { - orientation(LANDSCAPE); - sh = loadShader("frag.glsl", "vert.glsl"); - shader(sh); - } - - public void draw() { - translate(mouseX, mouseY); - rect(0, 0, 400, 400); - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchShapeBenchmark.java b/debug/apps/fast2d/src/main/java/fast2d/SketchShapeBenchmark.java deleted file mode 100644 index 8f21dae08..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchShapeBenchmark.java +++ /dev/null @@ -1,70 +0,0 @@ -package fast2d; - -import processing.core.PApplet; -import processing.opengl.PGraphics2DX; - -public class SketchShapeBenchmark extends PApplet { - int join = MITER; - int cap = SQUARE; - - boolean premultiply = true; - - float dev = 10; //deviation - - //change these parameters to benchmark various things - int unit = 10; - //line, triangle, rect, ellipse, point - int[] amount = { 20, 15, 10, 5, 40 }; - - public void settings() { - fullScreen(P2DX); - } - - public void setup() { - strokeCap(cap); - strokeJoin(join); -// PGraphics2DX.premultiplyMatrices = premultiply; - - textFont(createFont("SansSerif", 15 * displayDensity)); - } - - public void draw() { - background(255); - - strokeWeight(2 * displayDensity); - stroke(0); - fill(200); - - for (int i = 0; i < amount[0]*unit; ++i) { - float x = random(width); - float y = random(height); - line(x, y, x + random(-dev, dev), y + random(-dev, dev)); - } - - for (int i = 0; i < amount[1]*unit; ++i) { - float x = random(width); - float y = random(height); - triangle(x, y, - x + random(-dev*2, dev*2), y + random(-dev*2, dev*2), - x + random(-dev*2, dev*2), y + random(-dev*2, dev*2)); - } - - for (int i = 0; i < amount[2]*unit; ++i) { - rect(random(width), random(height), random(dev), random(dev)); - } - - for (int i = 0; i < amount[3]*unit; ++i) { - ellipse(random(width), random(height), random(dev*2), random(dev*2)); - } - - for (int i = 0; i < amount[4]*unit; ++i) { - point(random(width), random(height)); - } - - //large ellipse to test smoothness of outline - ellipse(width/2, height/2, width/2, height/4); - - fill(255, 0, 0); - text((int) frameRate + " fps", 30, 30); - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchTexturedPoly.java b/debug/apps/fast2d/src/main/java/fast2d/SketchTexturedPoly.java deleted file mode 100644 index 97d8ff292..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchTexturedPoly.java +++ /dev/null @@ -1,47 +0,0 @@ -package fast2d; - -import processing.core.PApplet; -import processing.core.PImage; - -public class SketchTexturedPoly extends PApplet { - PImage img; - - int join = MITER; - int cap = SQUARE; - - public void settings() { - fullScreen(P2DX); - } - - public void setup() { - img = loadImage("leaves.jpg"); - strokeCap(cap); - strokeJoin(join); - } - - public void draw() { - background(255); - - translate(100, 200); - - //test that textured shapes and tint() work correctly - float s = 4; - beginShape(); - texture(img); - vertex(10*s, 20*s, 0, 0); - tint(0, 255, 127, 127); - vertex(80*s, 5*s, 800, 0); - vertex(95*s, 90*s, 800, 800); - noTint(); - vertex(40*s, 95*s, 0, 800); - endShape(); - - //test that image() function works correctly - tint(255, 31); - rotate(-1); - image(img, -200, 100); - rotate(1); - tint(255); - image(img, 700, 100, 200, 100); - } -} diff --git a/debug/apps/fast2d/src/main/java/fast2d/SketchUserDefinedContours.java b/debug/apps/fast2d/src/main/java/fast2d/SketchUserDefinedContours.java deleted file mode 100644 index 1b4635cc3..000000000 --- a/debug/apps/fast2d/src/main/java/fast2d/SketchUserDefinedContours.java +++ /dev/null @@ -1,41 +0,0 @@ -package fast2d; - -import processing.core.PApplet; - -public class SketchUserDefinedContours extends PApplet { - - int join = MITER; - int cap = SQUARE; - - public void settings() { - fullScreen(P2DX); - } - - public void setup() { - strokeCap(cap); - strokeJoin(join); - } - - public void draw() { - background(255); - - //from https://processing.org/reference/beginContour_.html - - fill(127, 255, 127); - stroke(255, 0, 0); - beginShape(); - // Exterior part of shape, clockwise winding - vertex(-40, -40); - vertex(40, -40); - vertex(40, 40); - vertex(-40, 40); - // Interior part of shape, counter-clockwise winding - beginContour(); - vertex(-20, -20); - vertex(-20, 20); - vertex(20, 20); - vertex(20, -20); - endContour(); - endShape(CLOSE); - } -} diff --git a/debug/apps/fast2d/src/main/res/layout/activity_main.xml b/debug/apps/fast2d/src/main/res/layout/activity_main.xml deleted file mode 100644 index 1f9d42012..000000000 --- a/debug/apps/fast2d/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - \ No newline at end of file diff --git a/debug/apps/fast2d/src/main/res/mipmap-hdpi/ic_launcher.png b/debug/apps/fast2d/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index cde69bccc..000000000 Binary files a/debug/apps/fast2d/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/fast2d/src/main/res/mipmap-mdpi/ic_launcher.png b/debug/apps/fast2d/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index c133a0cbd..000000000 Binary files a/debug/apps/fast2d/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/fast2d/src/main/res/mipmap-xhdpi/ic_launcher.png b/debug/apps/fast2d/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index bfa42f0e7..000000000 Binary files a/debug/apps/fast2d/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/fast2d/src/main/res/mipmap-xxhdpi/ic_launcher.png b/debug/apps/fast2d/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 324e72cdd..000000000 Binary files a/debug/apps/fast2d/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/fast2d/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/debug/apps/fast2d/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index aee44e138..000000000 Binary files a/debug/apps/fast2d/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/fast2d/src/main/res/values-w820dp/dimens.xml b/debug/apps/fast2d/src/main/res/values-w820dp/dimens.xml deleted file mode 100644 index 63fc81644..000000000 --- a/debug/apps/fast2d/src/main/res/values-w820dp/dimens.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 64dp - diff --git a/debug/apps/fast2d/src/main/res/values/colors.xml b/debug/apps/fast2d/src/main/res/values/colors.xml deleted file mode 100644 index 3ab3e9cbc..000000000 --- a/debug/apps/fast2d/src/main/res/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #3F51B5 - #303F9F - #FF4081 - diff --git a/debug/apps/fast2d/src/main/res/values/dimens.xml b/debug/apps/fast2d/src/main/res/values/dimens.xml deleted file mode 100644 index 47c822467..000000000 --- a/debug/apps/fast2d/src/main/res/values/dimens.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - 16dp - 16dp - diff --git a/debug/apps/fast2d/src/main/res/values/strings.xml b/debug/apps/fast2d/src/main/res/values/strings.xml deleted file mode 100644 index 44978fbbe..000000000 --- a/debug/apps/fast2d/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Fast 2D - diff --git a/debug/apps/fast2d/src/main/res/values/styles.xml b/debug/apps/fast2d/src/main/res/values/styles.xml deleted file mode 100644 index 5885930df..000000000 --- a/debug/apps/fast2d/src/main/res/values/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/debug/apps/simple/build.gradle b/debug/apps/simple/build.gradle deleted file mode 100644 index 749a0801b..000000000 --- a/debug/apps/simple/build.gradle +++ /dev/null @@ -1,32 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 33 - defaultConfig { - applicationId "processing.tests.simple" - minSdkVersion 17 - targetSdkVersion 33 - versionCode 1 - versionName "1.0" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - productFlavors { - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - namespace 'simple' -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - testImplementation 'junit:junit:4.13.2' - implementation project(':libs:processing-core') - implementation 'androidx.appcompat:appcompat:1.6.0' -} diff --git a/debug/apps/simple/gradle.properties b/debug/apps/simple/gradle.properties deleted file mode 100644 index 5465fec0e..000000000 --- a/debug/apps/simple/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/debug/apps/simple/src/main/AndroidManifest.xml b/debug/apps/simple/src/main/AndroidManifest.xml deleted file mode 100644 index 5204a615a..000000000 --- a/debug/apps/simple/src/main/AndroidManifest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/debug/apps/simple/src/main/assets/leaf.png b/debug/apps/simple/src/main/assets/leaf.png deleted file mode 100644 index 61ca00df8..000000000 Binary files a/debug/apps/simple/src/main/assets/leaf.png and /dev/null differ diff --git a/debug/apps/simple/src/main/java/simple/MainActivity.java b/debug/apps/simple/src/main/java/simple/MainActivity.java deleted file mode 100644 index 7328c802f..000000000 --- a/debug/apps/simple/src/main/java/simple/MainActivity.java +++ /dev/null @@ -1,60 +0,0 @@ -package simple; - -import android.os.Bundle; -import android.content.Intent; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import androidx.appcompat.app.AppCompatActivity; - -import processing.android.PFragment; -import processing.android.CompatUtils; -import processing.core.PApplet; - -public class MainActivity extends AppCompatActivity { - private PApplet sketch; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - FrameLayout frame = new FrameLayout(this); - frame.setId(CompatUtils.getUniqueViewId()); - setContentView(frame, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - - sketch = new Sketch(); - PFragment fragment = new PFragment(sketch); - fragment.setView(frame, this); - } - - @Override - public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (sketch != null) { - sketch.onRequestPermissionsResult( - requestCode, permissions, grantResults); - } - } - - @Override - public void onNewIntent(Intent intent) { - super.onNewIntent(intent); - if (sketch != null) { - sketch.onNewIntent(intent); - } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (sketch != null) { - sketch.onActivityResult(requestCode, resultCode, data); - } - } - - @Override - public void onBackPressed() { - if (sketch != null) { - sketch.onBackPressed(); - } - } -} diff --git a/debug/apps/simple/src/main/java/simple/Sketch.java b/debug/apps/simple/src/main/java/simple/Sketch.java deleted file mode 100644 index 436ff3f94..000000000 --- a/debug/apps/simple/src/main/java/simple/Sketch.java +++ /dev/null @@ -1,23 +0,0 @@ -package simple; - -import processing.core.PApplet; -import processing.core.PImage; - -public class Sketch extends PApplet { - - PImage leaf; - - public void settings() { - fullScreen(); - } - - public void setup() { - leaf = loadImage("leaf.png"); - imageMode(CENTER); - } - - public void draw() { - background(9); - image(leaf, mouseX, mouseY); - } -} \ No newline at end of file diff --git a/debug/apps/simple/src/main/res/layout/activity_main.xml b/debug/apps/simple/src/main/res/layout/activity_main.xml deleted file mode 100644 index 1f9d42012..000000000 --- a/debug/apps/simple/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - \ No newline at end of file diff --git a/debug/apps/simple/src/main/res/mipmap-hdpi/ic_launcher.png b/debug/apps/simple/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index cde69bccc..000000000 Binary files a/debug/apps/simple/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/simple/src/main/res/mipmap-mdpi/ic_launcher.png b/debug/apps/simple/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index c133a0cbd..000000000 Binary files a/debug/apps/simple/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/simple/src/main/res/mipmap-xhdpi/ic_launcher.png b/debug/apps/simple/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index bfa42f0e7..000000000 Binary files a/debug/apps/simple/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/simple/src/main/res/mipmap-xxhdpi/ic_launcher.png b/debug/apps/simple/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 324e72cdd..000000000 Binary files a/debug/apps/simple/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/simple/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/debug/apps/simple/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index aee44e138..000000000 Binary files a/debug/apps/simple/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/simple/src/main/res/values-w820dp/dimens.xml b/debug/apps/simple/src/main/res/values-w820dp/dimens.xml deleted file mode 100644 index 63fc81644..000000000 --- a/debug/apps/simple/src/main/res/values-w820dp/dimens.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 64dp - diff --git a/debug/apps/simple/src/main/res/values/colors.xml b/debug/apps/simple/src/main/res/values/colors.xml deleted file mode 100644 index 3ab3e9cbc..000000000 --- a/debug/apps/simple/src/main/res/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #3F51B5 - #303F9F - #FF4081 - diff --git a/debug/apps/simple/src/main/res/values/dimens.xml b/debug/apps/simple/src/main/res/values/dimens.xml deleted file mode 100644 index 47c822467..000000000 --- a/debug/apps/simple/src/main/res/values/dimens.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - 16dp - 16dp - diff --git a/debug/apps/simple/src/main/res/values/strings.xml b/debug/apps/simple/src/main/res/values/strings.xml deleted file mode 100644 index 5f98a3846..000000000 --- a/debug/apps/simple/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Simple Test - diff --git a/debug/apps/simple/src/main/res/values/styles.xml b/debug/apps/simple/src/main/res/values/styles.xml deleted file mode 100644 index 5885930df..000000000 --- a/debug/apps/simple/src/main/res/values/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/debug/apps/vrcube/build.gradle b/debug/apps/vrcube/build.gradle deleted file mode 100644 index 3c02e6788..000000000 --- a/debug/apps/vrcube/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 33 - defaultConfig { - applicationId "processing.tests.vrcube" - minSdkVersion 19 - targetSdkVersion 33 - versionCode 1 - versionName "1.0" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - productFlavors { - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - namespace 'vrcube' -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - testImplementation 'junit:junit:4.13.2' - implementation project(':libs:processing-core') - implementation project(':libs:google-vr') - implementation project(':libs:processing-vr') - implementation 'androidx.appcompat:appcompat:1.6.0' -} diff --git a/debug/apps/vrcube/gradle.properties b/debug/apps/vrcube/gradle.properties deleted file mode 100644 index 5465fec0e..000000000 --- a/debug/apps/vrcube/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/debug/apps/vrcube/src/main/AndroidManifest.xml b/debug/apps/vrcube/src/main/AndroidManifest.xml deleted file mode 100644 index 152a3c5cc..000000000 --- a/debug/apps/vrcube/src/main/AndroidManifest.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/debug/apps/vrcube/src/main/java/vrcube/MainActivity.java b/debug/apps/vrcube/src/main/java/vrcube/MainActivity.java deleted file mode 100644 index 073189db3..000000000 --- a/debug/apps/vrcube/src/main/java/vrcube/MainActivity.java +++ /dev/null @@ -1,15 +0,0 @@ -package vrcube; - -import android.os.Bundle; - -import processing.vr.VRActivity; -import processing.core.PApplet; - -public class MainActivity extends VRActivity { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - PApplet sketch = new Sketch(); - setSketch(sketch); - } -} \ No newline at end of file diff --git a/debug/apps/vrcube/src/main/java/vrcube/Sketch.java b/debug/apps/vrcube/src/main/java/vrcube/Sketch.java deleted file mode 100644 index 5c7ee3f59..000000000 --- a/debug/apps/vrcube/src/main/java/vrcube/Sketch.java +++ /dev/null @@ -1,181 +0,0 @@ -package vrcube; - -import processing.core.PApplet; -import processing.core.PMatrix3D; -import processing.core.PVector; -import processing.vr.*; - -public class Sketch extends PApplet { - float boxSize = 140; - VRCamera vrcam; - Selector vrsel; - - public void settings() { - fullScreen(VR); - } - - public void setup() { - vrcam = new VRCamera(this); - vrsel = new Selector(this); -// vrcam.setNear(1000); -// vrcam.setFar(1100); - } - - public void draw() { - vrsel.update(); - background(120); - translate(width/2, height/2); - lights(); - drawGrid(); - drawAim(); - } - - void drawGrid() { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - float x = map(i, 0, 3, -350, +350); - float y = map(j, 0, 3, -350, +350); - pushMatrix(); - translate(x, y); - rotateY(millis()/1000.0f); - if (vrsel.hit(boxSize)) { - strokeWeight(5); - stroke(0xFF2FB1EA); - if (mousePressed) { - fill(0xFF2FB1EA); - } else { - fill(0xFFE3993E); - } - } else { - noStroke(); - fill(0xFFE3993E); - } - box(boxSize); - popMatrix(); - } - } - } - - void drawAim() { - vrcam.sticky(); - stroke(47, 177, 234, 150); - strokeWeight(50); - point(0, 0, 100); - vrcam.noSticky(); - } - - class Selector { - protected PApplet parent; - - protected PVector dir = new PVector(); - protected PVector cam = new PVector(); - - protected PMatrix3D eyeMat = new PMatrix3D(); - protected PMatrix3D objMat = new PMatrix3D(); - - protected PVector front = new PVector(); - protected PVector objCam = new PVector(); - protected PVector objFront = new PVector(); - protected PVector objDir = new PVector(); - - protected PVector hit = new PVector(); - - public Selector(PApplet parent) { - this.parent = parent; - } - - public void update() { - parent.getEyeMatrix(eyeMat); - cam.set(eyeMat.m03, eyeMat.m13, eyeMat.m23); - dir.set(eyeMat.m02, eyeMat.m12, eyeMat.m22); - PVector.add(cam, dir, front); - } - - public boolean hit(PMatrix3D mat, float boxSize) { - objMat.set(mat); - return hitImpl(boxSize); - } - - public boolean hit(float boxSize) { - parent.getObjectMatrix(objMat); - return hitImpl(boxSize); - } - - protected boolean hitImpl(float boxSize) { - objMat.mult(cam, objCam); - objMat.mult(front, objFront); - PVector.sub(objFront, objCam, objDir); - PVector boxMin = new PVector(-boxSize/2, -boxSize/2, -boxSize/2); - PVector boxMax = new PVector(+boxSize/2, +boxSize/2, +boxSize/2); - return intersectsLine(objCam, objDir, boxMin, boxMax, 0, 1000, hit); - } - - protected boolean intersectsLine(PVector orig, PVector dir, - PVector minPos, PVector maxPos, float minDist, float maxDist, PVector hit) { - PVector bbox; - PVector invDir = new PVector(1/dir.x, 1/dir.y, 1/dir.z); - - boolean signDirX = invDir.x < 0; - boolean signDirY = invDir.y < 0; - boolean signDirZ = invDir.z < 0; - - bbox = signDirX ? maxPos : minPos; - float txmin = (bbox.x - orig.x) * invDir.x; - bbox = signDirX ? minPos : maxPos; - float txmax = (bbox.x - orig.x) * invDir.x; - bbox = signDirY ? maxPos : minPos; - float tymin = (bbox.y - orig.y) * invDir.y; - bbox = signDirY ? minPos : maxPos; - float tymax = (bbox.y - orig.y) * invDir.y; - - if ((txmin > tymax) || (tymin > txmax)) { - return false; - } - if (tymin > txmin) { - txmin = tymin; - } - if (tymax < txmax) { - txmax = tymax; - } - - bbox = signDirZ ? maxPos : minPos; - float tzmin = (bbox.z - orig.z) * invDir.z; - bbox = signDirZ ? minPos : maxPos; - float tzmax = (bbox.z - orig.z) * invDir.z; - - if ((txmin > tzmax) || (tzmin > txmax)) { - return false; - } - if (tzmin > txmin) { - txmin = tzmin; - } - if (tzmax < txmax) { - txmax = tzmax; - } - if ((txmin < maxDist) && (txmax > minDist)) { - hit.x = orig.x + txmin * dir.x; - hit.y = orig.y + txmin * dir.y; - hit.z = orig.z + txmin * dir.z; - return true; - } - return false; - } - } - -/* - public void settings() { - fullScreen(STEREO); - } - - public void setup() { } - - public void draw() { - background(157); - lights(); - translate(width / 2, height / 2); - rotateX(frameCount * 0.01f); - rotateY(frameCount * 0.01f); - box(350); - } -*/ -} diff --git a/debug/apps/vrcube/src/main/res/layout/main.xml b/debug/apps/vrcube/src/main/res/layout/main.xml deleted file mode 100644 index 4b602d5f6..000000000 --- a/debug/apps/vrcube/src/main/res/layout/main.xml +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/debug/apps/vrcube/src/main/res/mipmap-hdpi/ic_launcher.png b/debug/apps/vrcube/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index cde69bccc..000000000 Binary files a/debug/apps/vrcube/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/vrcube/src/main/res/mipmap-mdpi/ic_launcher.png b/debug/apps/vrcube/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index c133a0cbd..000000000 Binary files a/debug/apps/vrcube/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/vrcube/src/main/res/mipmap-xhdpi/ic_launcher.png b/debug/apps/vrcube/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index bfa42f0e7..000000000 Binary files a/debug/apps/vrcube/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/vrcube/src/main/res/mipmap-xxhdpi/ic_launcher.png b/debug/apps/vrcube/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 324e72cdd..000000000 Binary files a/debug/apps/vrcube/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/vrcube/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/debug/apps/vrcube/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index aee44e138..000000000 Binary files a/debug/apps/vrcube/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/vrcube/src/main/res/values/strings.xml b/debug/apps/vrcube/src/main/res/values/strings.xml deleted file mode 100644 index db8a2b518..000000000 --- a/debug/apps/vrcube/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - VR Test - diff --git a/debug/apps/vrcube/src/main/res/values/styles.xml b/debug/apps/vrcube/src/main/res/values/styles.xml deleted file mode 100644 index 9f408b9b2..000000000 --- a/debug/apps/vrcube/src/main/res/values/styles.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/debug/apps/wallpaper/build.gradle b/debug/apps/wallpaper/build.gradle deleted file mode 100644 index 7870d99b1..000000000 --- a/debug/apps/wallpaper/build.gradle +++ /dev/null @@ -1,32 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 33 - defaultConfig { - applicationId "processing.tests.wallpaper" - minSdkVersion 17 - targetSdkVersion 33 - versionCode 1 - versionName "1.0" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - productFlavors { - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - namespace 'wallpaper' -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - testImplementation 'junit:junit:4.13.2' - implementation project(':libs:processing-core') - implementation 'androidx.appcompat:appcompat:1.6.0' -} \ No newline at end of file diff --git a/debug/apps/wallpaper/gradle.properties b/debug/apps/wallpaper/gradle.properties deleted file mode 100644 index 5465fec0e..000000000 --- a/debug/apps/wallpaper/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/debug/apps/wallpaper/src/main/AndroidManifest.xml b/debug/apps/wallpaper/src/main/AndroidManifest.xml deleted file mode 100644 index 37695c4da..000000000 --- a/debug/apps/wallpaper/src/main/AndroidManifest.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/debug/apps/wallpaper/src/main/java/wallpaper/DebuggerEntryPointActivity.java b/debug/apps/wallpaper/src/main/java/wallpaper/DebuggerEntryPointActivity.java deleted file mode 100644 index ca80b0079..000000000 --- a/debug/apps/wallpaper/src/main/java/wallpaper/DebuggerEntryPointActivity.java +++ /dev/null @@ -1,12 +0,0 @@ -package wallpaper; - -import android.app.Activity; -import android.os.Bundle; -import androidx.annotation.Nullable; - -public class DebuggerEntryPointActivity extends Activity { - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } -} diff --git a/debug/apps/wallpaper/src/main/java/wallpaper/MainService.java b/debug/apps/wallpaper/src/main/java/wallpaper/MainService.java deleted file mode 100644 index 48a61388f..000000000 --- a/debug/apps/wallpaper/src/main/java/wallpaper/MainService.java +++ /dev/null @@ -1,14 +0,0 @@ -package wallpaper; - -import processing.android.PWallpaper; -import processing.core.PApplet; - -public class MainService extends PWallpaper { - @Override - public PApplet createSketch() { - // Uncomment the following line when debugging: -// android.os.Debug.waitForDebugger(); - PApplet sketch = new Sketch(); - return sketch; - } -} diff --git a/debug/apps/wallpaper/src/main/java/wallpaper/Sketch.java b/debug/apps/wallpaper/src/main/java/wallpaper/Sketch.java deleted file mode 100644 index a5188d848..000000000 --- a/debug/apps/wallpaper/src/main/java/wallpaper/Sketch.java +++ /dev/null @@ -1,41 +0,0 @@ -package wallpaper; - -import processing.core.PApplet; - -public class Sketch extends PApplet { - - float currH, currB; - float nextH, nextB; - float easing = 0.001f; - int lastChange = 0; - - public void settings() { - fullScreen(); - } - - public void setup() { - colorMode(HSB, 100); - currH = nextH = 100; - currB = nextB = 100; - } - - public void draw() { - background(currH, currB, 100); - updateCurrColor(); - if (5000 < millis() - lastChange) { - pickNextColor(); - lastChange = millis(); - } - } - - public void pickNextColor() { - nextH = random(100); - nextB = random(100); - } - - public void updateCurrColor() { - // Easing between current and next colors - currH += easing * (nextH - currH); - currB += easing * (nextB - currB); - } -} diff --git a/debug/apps/wallpaper/src/main/res/layout/main.xml b/debug/apps/wallpaper/src/main/res/layout/main.xml deleted file mode 100644 index 4f22eb184..000000000 --- a/debug/apps/wallpaper/src/main/res/layout/main.xml +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/debug/apps/wallpaper/src/main/res/mipmap-hdpi/ic_launcher.png b/debug/apps/wallpaper/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index cde69bccc..000000000 Binary files a/debug/apps/wallpaper/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/wallpaper/src/main/res/mipmap-mdpi/ic_launcher.png b/debug/apps/wallpaper/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index c133a0cbd..000000000 Binary files a/debug/apps/wallpaper/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/wallpaper/src/main/res/mipmap-xhdpi/ic_launcher.png b/debug/apps/wallpaper/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index bfa42f0e7..000000000 Binary files a/debug/apps/wallpaper/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/wallpaper/src/main/res/mipmap-xxhdpi/ic_launcher.png b/debug/apps/wallpaper/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 324e72cdd..000000000 Binary files a/debug/apps/wallpaper/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/wallpaper/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/debug/apps/wallpaper/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index aee44e138..000000000 Binary files a/debug/apps/wallpaper/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/wallpaper/src/main/res/values-w820dp/dimens.xml b/debug/apps/wallpaper/src/main/res/values-w820dp/dimens.xml deleted file mode 100644 index 63fc81644..000000000 --- a/debug/apps/wallpaper/src/main/res/values-w820dp/dimens.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 64dp - diff --git a/debug/apps/wallpaper/src/main/res/values/strings.xml b/debug/apps/wallpaper/src/main/res/values/strings.xml deleted file mode 100644 index 207396e9f..000000000 --- a/debug/apps/wallpaper/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - wallpaper - diff --git a/debug/apps/wallpaper/src/main/res/xml/wallpaper.xml b/debug/apps/wallpaper/src/main/res/xml/wallpaper.xml deleted file mode 100644 index ec6db83cc..000000000 --- a/debug/apps/wallpaper/src/main/res/xml/wallpaper.xml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/debug/apps/watchface/build.gradle b/debug/apps/watchface/build.gradle deleted file mode 100644 index 215878d49..000000000 --- a/debug/apps/watchface/build.gradle +++ /dev/null @@ -1,35 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 33 - defaultConfig { - applicationId "processing.tests.watchface" - minSdkVersion 25 - targetSdkVersion 33 - versionCode 1 - versionName "1.0" - multiDexEnabled true - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - productFlavors { - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - namespace 'watchface' -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - testImplementation 'junit:junit:4.13.2' - implementation project(':libs:processing-core') - implementation 'com.google.android.gms:play-services-wearable:18.0.0' - implementation 'com.google.android.support:wearable:2.9.0' - compileOnly 'com.google.android.wearable:wearable:2.9.0' -} diff --git a/debug/apps/watchface/gradle.properties b/debug/apps/watchface/gradle.properties deleted file mode 100644 index 5465fec0e..000000000 --- a/debug/apps/watchface/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/debug/apps/watchface/src/main/AndroidManifest.xml b/debug/apps/watchface/src/main/AndroidManifest.xml deleted file mode 100644 index e6f990184..000000000 --- a/debug/apps/watchface/src/main/AndroidManifest.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/debug/apps/watchface/src/main/java/watchface/MainService.java b/debug/apps/watchface/src/main/java/watchface/MainService.java deleted file mode 100644 index 6879f1b97..000000000 --- a/debug/apps/watchface/src/main/java/watchface/MainService.java +++ /dev/null @@ -1,15 +0,0 @@ -package watchface; - -import processing.android.PWatchFaceCanvas; -//import processing.android.PWatchFaceGLES; -import processing.core.PApplet; - -// The service needs to extend PWatchFaceCanvas if the renderer in the sketch is P2D or P3D. -//public class MainService extends PWatchFaceGLES { -public class MainService extends PWatchFaceCanvas { - @Override - public PApplet createSketch() { - PApplet sketch = new Sketch(); - return sketch; - } -} diff --git a/debug/apps/watchface/src/main/java/watchface/Sketch.java b/debug/apps/watchface/src/main/java/watchface/Sketch.java deleted file mode 100644 index 9af8a1d39..000000000 --- a/debug/apps/watchface/src/main/java/watchface/Sketch.java +++ /dev/null @@ -1,25 +0,0 @@ -package watchface; - -import processing.core.PApplet; - - -public class Sketch extends PApplet { - public void settings() { - fullScreen(); - } - - public void setup() { - frameRate(1); - textFont(createFont("Serif-Bold", 48 * displayDensity)); - textAlign(CENTER, CENTER); - fill(255); - } - - public void draw() { - background(0); - if (wearInteractive()) { - String str = hour() + ":" + nfs(minute(), 2) + ":" + nfs(second(), 2); - text(str, width/2, height/2); - } - } -} diff --git a/debug/apps/watchface/src/main/res/drawable-nodpi/bg.png b/debug/apps/watchface/src/main/res/drawable-nodpi/bg.png deleted file mode 100644 index 6fb4fd15d..000000000 Binary files a/debug/apps/watchface/src/main/res/drawable-nodpi/bg.png and /dev/null differ diff --git a/debug/apps/watchface/src/main/res/drawable-nodpi/preview_analog.png b/debug/apps/watchface/src/main/res/drawable-nodpi/preview_analog.png deleted file mode 100644 index 605674c9a..000000000 Binary files a/debug/apps/watchface/src/main/res/drawable-nodpi/preview_analog.png and /dev/null differ diff --git a/debug/apps/watchface/src/main/res/layout/main.xml b/debug/apps/watchface/src/main/res/layout/main.xml deleted file mode 100644 index 190e3e161..000000000 --- a/debug/apps/watchface/src/main/res/layout/main.xml +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/debug/apps/watchface/src/main/res/mipmap-hdpi/ic_launcher.png b/debug/apps/watchface/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index cde69bccc..000000000 Binary files a/debug/apps/watchface/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/watchface/src/main/res/mipmap-mdpi/ic_launcher.png b/debug/apps/watchface/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index c133a0cbd..000000000 Binary files a/debug/apps/watchface/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/watchface/src/main/res/mipmap-xhdpi/ic_launcher.png b/debug/apps/watchface/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index bfa42f0e7..000000000 Binary files a/debug/apps/watchface/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/watchface/src/main/res/mipmap-xxhdpi/ic_launcher.png b/debug/apps/watchface/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 324e72cdd..000000000 Binary files a/debug/apps/watchface/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/debug/apps/watchface/src/main/res/values/strings.xml b/debug/apps/watchface/src/main/res/values/strings.xml deleted file mode 100644 index 5d0817ef2..000000000 --- a/debug/apps/watchface/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - Watchface test - Watch face tapped - My Analog - diff --git a/debug/apps/watchface/src/main/res/xml/watch_face.xml b/debug/apps/watchface/src/main/res/xml/watch_face.xml deleted file mode 100644 index 11a664b76..000000000 --- a/debug/apps/watchface/src/main/res/xml/watch_face.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/debug/build.gradle b/debug/build.gradle deleted file mode 100644 index 78b7a12c1..000000000 --- a/debug/build.gradle +++ /dev/null @@ -1,44 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:7.3.1' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - // This was was added to address an issue in JCenter with some Android packages (https://stackoverflow.com/questions/50563338/could-not-find-runtime-jar-android-arch-lifecycleruntime1-0-0/50564224). - // JCenter is no longer used but keep it just in case. - maven { url "https://maven.google.com" } - - // Apparently needed by AndroidX dependencies - maven { url "https://jitpack.io" } - - // Needed to get google-vr dependencies - maven { url 'https://repo.gradle.org/gradle/libs-releases' } - - // Using the legacy Google VR libs included in the mode's VR library, since they are no - // longer available online -// flatDir { -// dirs '../mode/libraries/vr/libs' -// } - - mavenCentral() - google() - - google() - mavenCentral() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/debug/gradle.properties b/debug/gradle.properties deleted file mode 100644 index 278e9e7db..000000000 --- a/debug/gradle.properties +++ /dev/null @@ -1,21 +0,0 @@ -## For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx1024m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -# -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -#Wed Dec 30 11:02:34 EST 2020 -android.enableJetifier=true -android.useAndroidX=true - -# Line to fix the ''module java.base does not "opens java.io" to unnamed module '' error in Android Studio: -# https://stackoverflow.com/questions/67782975/how-to-fix-the-module-java-base-does-not-opens-java-io-to-unnamed-module -# Probably not needed if using a version of the Android Gradle Plugin compatible with the JDK: -# https://docs.gradle.org/current/userguide/compatibility.html -org.gradle.jvmargs=-Xmx1536M --add-exports=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED \ No newline at end of file diff --git a/debug/gradle/wrapper/gradle-wrapper.jar b/debug/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 41d9927a4..000000000 Binary files a/debug/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/debug/gradle/wrapper/gradle-wrapper.properties b/debug/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index aa991fcea..000000000 --- a/debug/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/debug/libs/google-vr/build.gradle b/debug/libs/google-vr/build.gradle deleted file mode 100644 index ad6fe686d..000000000 --- a/debug/libs/google-vr/build.gradle +++ /dev/null @@ -1,10 +0,0 @@ -// Dummy Gradle project to be able to import local aar files: -// https://stackoverflow.com/a/60888941 - -configurations.maybeCreate("default") -artifacts.add("default", file('sdk-audio-1.180.0.aar')) -artifacts.add("default", file('sdk-base-1.180.0.aar')) -artifacts.add("default", file('sdk-common-1.180.0.aar')) - -// https://mvnrepository.com/artifact/com.google.protobuf.nano/protobuf-javanano/3.1.0 -//artifacts.add("default", file('protobuf-javanano-3.1.0.jar')) diff --git a/debug/libs/google-vr/protobuf-javanano-3.1.0.jar b/debug/libs/google-vr/protobuf-javanano-3.1.0.jar deleted file mode 100644 index 8aac9068d..000000000 Binary files a/debug/libs/google-vr/protobuf-javanano-3.1.0.jar and /dev/null differ diff --git a/debug/libs/google-vr/sdk-audio-1.180.0.aar b/debug/libs/google-vr/sdk-audio-1.180.0.aar deleted file mode 100644 index 007485cf4..000000000 Binary files a/debug/libs/google-vr/sdk-audio-1.180.0.aar and /dev/null differ diff --git a/debug/libs/google-vr/sdk-base-1.180.0.aar b/debug/libs/google-vr/sdk-base-1.180.0.aar deleted file mode 100644 index e9047d226..000000000 Binary files a/debug/libs/google-vr/sdk-base-1.180.0.aar and /dev/null differ diff --git a/debug/libs/google-vr/sdk-common-1.180.0.aar b/debug/libs/google-vr/sdk-common-1.180.0.aar deleted file mode 100644 index 7ba5cff92..000000000 Binary files a/debug/libs/google-vr/sdk-common-1.180.0.aar and /dev/null differ diff --git a/debug/libs/processing-ar/AndroidManifest.xml b/debug/libs/processing-ar/AndroidManifest.xml deleted file mode 100755 index 8c707a40f..000000000 --- a/debug/libs/processing-ar/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/debug/libs/processing-ar/build.gradle b/debug/libs/processing-ar/build.gradle deleted file mode 100755 index fab391e4d..000000000 --- a/debug/libs/processing-ar/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 33 - defaultConfig { - minSdkVersion 19 - targetSdkVersion 33 - } - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['../../../mode/libraries/ar/src'] - assets.srcDirs = ['../../../mode/libraries/ar/src/assets'] - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - productFlavors { - } -} - -dependencies { - implementation project(':libs:processing-core') - implementation 'com.google.ar:core:1.35.0' -} \ No newline at end of file diff --git a/debug/libs/processing-ar/gradle.properties b/debug/libs/processing-ar/gradle.properties deleted file mode 100755 index 0b8af424f..000000000 --- a/debug/libs/processing-ar/gradle.properties +++ /dev/null @@ -1,5 +0,0 @@ -POM_NAME=Processing for Android AR Library -POM_ARTIFACT_ID=processing-ar -POM_PACKAGING=aar -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/debug/libs/processing-ar/project.properties b/debug/libs/processing-ar/project.properties deleted file mode 100755 index 91d2b0246..000000000 --- a/debug/libs/processing-ar/project.properties +++ /dev/null @@ -1,15 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-19 -android.library=true diff --git a/debug/libs/processing-core/AndroidManifest.xml b/debug/libs/processing-core/AndroidManifest.xml deleted file mode 100755 index 5587f2ed2..000000000 --- a/debug/libs/processing-core/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/debug/libs/processing-core/build.gradle b/debug/libs/processing-core/build.gradle deleted file mode 100644 index 89fd0764e..000000000 --- a/debug/libs/processing-core/build.gradle +++ /dev/null @@ -1,28 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 33 - defaultConfig { - minSdkVersion 17 - targetSdkVersion 33 - } - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['../../../core/src'] - assets.srcDirs = ['../../../core/src/assets'] - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - productFlavors { - } -} - -dependencies { - implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'com.google.android.support:wearable:2.9.0' - compileOnly 'com.google.android.wearable:wearable:2.9.0' -} \ No newline at end of file diff --git a/debug/libs/processing-core/gradle.properties b/debug/libs/processing-core/gradle.properties deleted file mode 100755 index 7420d96aa..000000000 --- a/debug/libs/processing-core/gradle.properties +++ /dev/null @@ -1,5 +0,0 @@ -POM_NAME=Processing for Android Core Library -POM_ARTIFACT_ID=processing-core -POM_PACKAGING=aar -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/debug/libs/processing-core/project.properties b/debug/libs/processing-core/project.properties deleted file mode 100755 index 36f15941e..000000000 --- a/debug/libs/processing-core/project.properties +++ /dev/null @@ -1,15 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-15 -android.library=true diff --git a/debug/libs/processing-vr/AndroidManifest.xml b/debug/libs/processing-vr/AndroidManifest.xml deleted file mode 100755 index bd9f8c46f..000000000 --- a/debug/libs/processing-vr/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/debug/libs/processing-vr/build.gradle b/debug/libs/processing-vr/build.gradle deleted file mode 100644 index 82ef75198..000000000 --- a/debug/libs/processing-vr/build.gradle +++ /dev/null @@ -1,26 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 33 - defaultConfig { - minSdkVersion 19 - targetSdkVersion 33 - } - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['../../../mode/libraries/vr/src'] - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - productFlavors { - } -} - -dependencies { - implementation project(':libs:processing-core') - implementation project(':libs:google-vr') -} \ No newline at end of file diff --git a/debug/libs/processing-vr/gradle.properties b/debug/libs/processing-vr/gradle.properties deleted file mode 100755 index 66fa090a2..000000000 --- a/debug/libs/processing-vr/gradle.properties +++ /dev/null @@ -1,5 +0,0 @@ -POM_NAME=Processing for Android VR Library -POM_ARTIFACT_ID=processing-vr -POM_PACKAGING=aar -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/debug/libs/processing-vr/project.properties b/debug/libs/processing-vr/project.properties deleted file mode 100755 index 91d2b0246..000000000 --- a/debug/libs/processing-vr/project.properties +++ /dev/null @@ -1,15 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-19 -android.library=true diff --git a/debug/settings.gradle b/debug/settings.gradle deleted file mode 100644 index 649bcc56e..000000000 --- a/debug/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':apps:simple', ':apps:wallpaper', ':apps:vrcube', ':apps:arscene', ':apps:watchface', ':apps:fast2d', ':libs:processing-core', 'libs:google-vr',':libs:processing-vr', ':libs:processing-ar' \ No newline at end of file diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index 5465fec0e..000000000 --- a/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 41d9927a4..000000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index aa991fcea..000000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew deleted file mode 100755 index 1b6c78733..000000000 --- a/gradlew +++ /dev/null @@ -1,234 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index ac1b06f93..000000000 --- a/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/mode/.classpath b/mode/.classpath deleted file mode 100644 index 3242dff64..000000000 --- a/mode/.classpath +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mode/.project b/mode/.project deleted file mode 100644 index a1e217daa..000000000 --- a/mode/.project +++ /dev/null @@ -1,34 +0,0 @@ - - - android-mode - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.buildship.core.gradleprojectnature - - - - 1650246874247 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - - diff --git a/mode/.settings/org.eclipse.buildship.core.prefs b/mode/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index e8895216f..000000000 --- a/mode/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,2 +0,0 @@ -connection.project.dir= -eclipse.preferences.version=1 diff --git a/mode/.settings/org.eclipse.jdt.core.prefs b/mode/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 0fee6a9c4..000000000 --- a/mode/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,15 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/mode/build.gradle b/mode/build.gradle deleted file mode 100644 index fefd9c866..000000000 --- a/mode/build.gradle +++ /dev/null @@ -1,106 +0,0 @@ -import java.nio.file.Files -import org.zeroturnaround.zip.ZipUtil -import org.apache.commons.io.FileUtils -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; - - -// Extend compile to copy the jars from gradle-tooling and slf4j: -// https://stackoverflow.com/a/43602463 -configurations { - implementation.extendsFrom implementationCopy - implementation.extendsFrom implementationExtract -} - -dependencies { - // implementation group: "org.processing", name: "core", version: "${processingVersion}" - // implementation group: "org.processing", name: "pde", version: "${processingVersion}" - // implementation group: "org.processing", name: "java-mode", version: "${processingVersion}" - - implementationExtract "org.eclipse.jdt:org.eclipse.jdt.debug:${jdtVersion}" - - implementationCopy "org.gradle:gradle-tooling-api:${toolingVersion}" - implementationCopy "org.slf4j:slf4j-api:${slf4jVersion}" - implementationCopy "org.slf4j:slf4j-simple:${slf4jVersion}" - - implementation fileTree(include: ["jdi.jar", "jdimodel.jar", "core.jar", "pde.jar", "JavaMode.jar"], dir: 'mode') -} - -// This task copies the gradle tooling jar into the mode folder -task copyToLib(type: Copy) { - from configurations.implementationCopy.files - into "mode" -} -build.dependsOn(copyToLib) -compileJava.dependsOn(copyToLib) - -sourceSets { - main { - java { - srcDirs = ["src/"] - } - } -} - -task getjdi(type: Copy) { - // This task extracts the jar files inside org.eclipse.jdt.debug, which are - // jdi.jar and jdimodel.jar and needed to build the debugger. - from(zipTree(configurations.implementationExtract.files[0])) { - include '**/*.jar' - exclude 'META-INF' - } - into "mode" -} - -task permissions(type:Exec) { - // This task retrieves the latest list of Android permissions and adds them - // to the Permissions.java file. The python scripts requries BeautifulSoup - workingDir "scripts" - commandLine "python", "permissions.py" -} - -task wrapper(type: Wrapper) { - gradleVersion = "${gradlewVersion}" // version required for gradle wrapper -} - -wrapper.doLast { - File wrapperFolder = file("mode/gradlew"); - wrapperFolder.mkdirs(); - file("gradle").renameTo(file("mode/gradlew/gradle")) - file("gradlew").renameTo(file("mode/gradlew/gradlew")) - file("gradlew.bat").renameTo(file("mode/gradlew/gradlew.bat")) - FileUtils.copyDirectory(file("gradle"), file("../debug/gradle")) - delete "gradle" - ZipUtil.pack(file("mode/gradlew"), new File("mode/mode/gradlew.zip")); - delete "mode/gradlew" -} - -clean.doFirst { - delete fileTree("mode") { - include "**/*.jar" - exclude "jdi.jar" - exclude "jdimodel.jar" - exclude "istack-commons-runtime.jar" - exclude "javax.activation-api.jar" - exclude "jaxb-api.jar" - exclude "jaxb-jxc.jar" - exclude "jaxb-runtime.jar" - exclude "jaxb-xjc.jar" - exclude "core.jar" - exclude "pde.jar" - exclude "JavaMode.jar" - exclude "org.eclipse.core.contenttype.jar" - exclude "org.eclipse.core.jobs.jar" - exclude "org.eclipse.core.resources.jar" - exclude "org.eclipse.core.runtime.jar" - exclude "org.eclipse.equinox.common.jar" - exclude "org.eclipse.equinox.preferences.jar" - exclude "org.eclipse.jdt.core.jar" - exclude "org.eclipse.osgi.jar" - exclude "org.eclipse.text.jar" - } -} - -build.doLast { - Files.copy(file("$buildDir/libs/mode.jar").toPath(), - file("mode/AndroidMode.jar").toPath(), REPLACE_EXISTING); -} diff --git a/mode/examples/Basics/Arrays/Array/Array.pde b/mode/examples/Basics/Arrays/Array/Array.pde deleted file mode 100644 index a981fa470..000000000 --- a/mode/examples/Basics/Arrays/Array/Array.pde +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Array. - * - * An array is a list of data. Each piece of data in an array - * is identified by an index number representing its position in - * the array. Arrays are zero based, which means that the first - * element in the array is [0], the second element is [1], and so on. - * In this example, an array named "coswav" is created and - * filled with the cosine values. This data is displayed three - * separate ways on the screen. - */ - -size(200, 200); - -float[] coswave = new float[width]; - -for (int i = 0; i < width; i++) { - float amount = map(i, 0, width, 0, PI); - coswave[i] = abs(cos(amount)); -} - -for (int i = 0; i < width; i++) { - stroke(coswave[i]*255); - line(i, 0, i, height/3); -} - -for (int i = 0; i < width; i++) { - stroke(coswave[i]*255 / 4); - line(i, height/3, i, height/3*2); -} - -for (int i = 0; i < width; i++) { - stroke(255 - coswave[i]*255); - line(i, height/3*2, i, height); -} diff --git a/mode/examples/Basics/Arrays/Array2D/Array2D.pde b/mode/examples/Basics/Arrays/Array2D/Array2D.pde deleted file mode 100644 index 3a97587e7..000000000 --- a/mode/examples/Basics/Arrays/Array2D/Array2D.pde +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Array 2D. - * - * Demonstrates the syntax for creating a two-dimensional (2D) array. - * Values in a 2D array are accessed through two index values. - * 2D arrays are useful for storing images. In this example, each dot - * is colored in relation to its distance from the center of the image. - */ - -float[][] distances; -float maxDistance; - -size(200, 200); -background(0); -maxDistance = dist(width/2, height/2, width, height); -distances = new float[width][height]; -for(int i=0; i= big || x <= 0) { - xdir *= -1; - x = x + (1 * xdir); - y = y + (1 * ydir); - } - if (y >= big || y <= 0) { - ydir *= -1; - y = y + (1 * ydir); - } - } - - // Custom method for drawing the object - void draw() { - stroke(second() * 4); - point(mx+x-1, my+y-1); - } -} diff --git a/mode/examples/Basics/Camera/MoveEye/MoveEye.pde b/mode/examples/Basics/Camera/MoveEye/MoveEye.pde deleted file mode 100644 index 0e305f592..000000000 --- a/mode/examples/Basics/Camera/MoveEye/MoveEye.pde +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Move Eye. - * by Simon Greenwold. - * - * The camera lifts up (controlled by mouseY) while looking at the same point. - */ - -void setup() { - size(640, 360, P3D); - orientation(LANDSCAPE); - fill(204); -} - -void draw() { - lights(); - background(0); - - // Change height of the camera with mouseY - camera(30.0, mouseY, 220.0, // eyeX, eyeY, eyeZ - 0.0, 0.0, 0.0, // centerX, centerY, centerZ - 0.0, 1.0, 0.0); // upX, upY, upZ - - noStroke(); - box(90); - stroke(255); - line(-100, 0, 0, 100, 0, 0); - line(0, -100, 0, 0, 100, 0); - line(0, 0, -100, 0, 0, 100); -} diff --git a/mode/examples/Basics/Camera/Perspective/Perspective.pde b/mode/examples/Basics/Camera/Perspective/Perspective.pde deleted file mode 100644 index 819248d05..000000000 --- a/mode/examples/Basics/Camera/Perspective/Perspective.pde +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Perspective. - * - * Move the mouse left and right to change the field of view (fov). - * Click to modify the aspect ratio. The perspective() function - * sets a perspective projection applying foreshortening, making - * distant objects appear smaller than closer ones. The parameters - * define a viewing volume with the shape of truncated pyramid. - * Objects near to the front of the volume appear their actual size, - * while farther objects appear smaller. This projection simulates - * the perspective of the world more accurately than orthographic projection. - * The version of perspective without parameters sets the default - * perspective and the version with four parameters allows the programmer - * to set the area precisely. - */ - -void setup() { - size(displayWidth, displayHeight, P3D); - orientation(LANDSCAPE); - noStroke(); -} - -void draw() { - lights(); - background(204); - float cameraY = height/2.0; - float fov = mouseX/float(width) * PI/2; - float cameraZ = cameraY / tan(fov / 2.0); - float aspect = float(width)/float(height); - if (mousePressed) { - aspect = aspect / 2.0; - } - perspective(fov, aspect, cameraZ/10.0, cameraZ*10.0); - - translate(width/2+30, height/2, 0); - rotateX(-PI/6); - rotateY(PI/3 + mouseY/float(height) * PI); - box(45); - translate(0, 0, -50); - box(30); -} - diff --git a/mode/examples/Basics/Color/Brightness/Brightness.pde b/mode/examples/Basics/Color/Brightness/Brightness.pde deleted file mode 100644 index a91331e30..000000000 --- a/mode/examples/Basics/Color/Brightness/Brightness.pde +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Brightness - * by Rusty Robison. - * - * Brightness is the relative lightness or darkness of a color. - * Move the cursor vertically over each bar to alter its brightness. - * - * Updated 28 February 2010. - */ - -int barWidth = 5; -int lastBar = -1; - -void setup() { - size(200, 200); - colorMode(HSB, 360, 100, height); - noStroke(); - background(0); -} - -void draw() { - int whichBar = mouseX / barWidth; - if (whichBar != lastBar) { - int barX = whichBar * barWidth; - fill(barX, 100, mouseY); - rect(barX, 0, barWidth, height); - lastBar = whichBar; - } -} diff --git a/mode/examples/Basics/Color/ColorWheel/ColorWheel.pde b/mode/examples/Basics/Color/ColorWheel/ColorWheel.pde deleted file mode 100644 index 69c34602a..000000000 --- a/mode/examples/Basics/Color/ColorWheel/ColorWheel.pde +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Subtractive Color Wheel - * by Ira Greenberg. - * - * The primaries are red, yellow, and blue. The secondaries are green, - * purple, and orange. The tertiaries are yellow-orange, red-orange, - * red-purple, blue-purple, blue-green, and yellow-green. - * - * Create a shade or tint of the subtractive color wheel using - * SHADE or TINT parameters. - * - * Updated 26 February 2010. - */ - -int segs = 12; -int steps = 6; -float rotAdjust = TWO_PI / segs / 2; -float radius; -float segWidth; -float interval = TWO_PI / segs; - - -void setup() { - size(200, 200); - background(127); - smooth(); - ellipseMode(RADIUS); - noStroke(); - // make the diameter 90% of the sketch area - radius = min(width, height) * 0.45; - segWidth = radius / steps; - - // swap which line is commented out to draw the other version - //drawTintWheel(); - drawShadeWheel(); -} - - -void drawShadeWheel() { - for (int j = 0; j < steps; j++) { - color[] cols = { - color(255-(255/steps)*j, 255-(255/steps)*j, 0), - color(255-(255/steps)*j, (255/1.5)-((255/1.5)/steps)*j, 0), - color(255-(255/steps)*j, (255/2)-((255/2)/steps)*j, 0), - color(255-(255/steps)*j, (255/2.5)-((255/2.5)/steps)*j, 0), - color(255-(255/steps)*j, 0, 0), - color(255-(255/steps)*j, 0, (255/2)-((255/2)/steps)*j), - color(255-(255/steps)*j, 0, 255-(255/steps)*j), - color((255/2)-((255/2)/steps)*j, 0, 255-(255/steps)*j), - color(0, 0, 255-(255/steps)*j), - color(0, 255-(255/steps)*j, (255/2.5)-((255/2.5)/steps)*j), - color(0, 255-(255/steps)*j, 0), - color((255/2)-((255/2)/steps)*j, 255-(255/steps)*j, 0) - }; - for (int i = 0; i < segs; i++) { - fill(cols[i]); - arc(width/2, height/2, radius, radius, - interval*i+rotAdjust, interval*(i+1)+rotAdjust); - } - radius -= segWidth; - } -} - - -void drawTintWheel() { - for (int j = 0; j < steps; j++) { - color[] cols = { - color((255/steps)*j, (255/steps)*j, 0), - color((255/steps)*j, ((255/1.5)/steps)*j, 0), - color((255/steps)*j, ((255/2)/steps)*j, 0), - color((255/steps)*j, ((255/2.5)/steps)*j, 0), - color((255/steps)*j, 0, 0), - color((255/steps)*j, 0, ((255/2)/steps)*j), - color((255/steps)*j, 0, (255/steps)*j), - color(((255/2)/steps)*j, 0, (255/steps)*j), - color(0, 0, (255/steps)*j), - color(0, (255/steps)*j, ((255/2.5)/steps)*j), - color(0, (255/steps)*j, 0), - color(((255/2)/steps)*j, (255/steps)*j, 0) - }; - for (int i = 0; i < segs; i++) { - fill(cols[i]); - arc(width/2, height/2, radius, radius, - interval*i+rotAdjust, interval*(i+1)+rotAdjust); - } - radius -= segWidth; - } -} diff --git a/mode/examples/Basics/Color/Creating/Creating.pde b/mode/examples/Basics/Color/Creating/Creating.pde deleted file mode 100644 index 628e1f7ac..000000000 --- a/mode/examples/Basics/Color/Creating/Creating.pde +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Creating Colors (Homage to Albers). - * - * Creating variables for colors that may be referred to - * in the program by their name, rather than a number. - */ - -size(200, 200); -noStroke(); - -color inside = color(204, 102, 0); -color middle = color(204, 153, 0); -color outside = color(153, 51, 0); - -// These statements are equivalent to the statements above. -// Programmers may use the format they prefer. -//color inside = #CC6600; -//color middle = #CC9900; -//color outside = #993300; - -fill(outside); -rect(0, 0, 200, 200); -fill(middle); -rect(40, 60, 120, 120); -fill(inside); -rect(60, 90, 80, 80); diff --git a/mode/examples/Basics/Color/Hue/Hue.pde b/mode/examples/Basics/Color/Hue/Hue.pde deleted file mode 100644 index b22ffb535..000000000 --- a/mode/examples/Basics/Color/Hue/Hue.pde +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Hue. - * - * Hue is the color reflected from or transmitted through an object - * and is typically referred to as the name of the color (red, blue, yellow, etc.) - * Move the cursor vertically over each bar to alter its hue. - */ - -int barWidth = 5; -int[] hue; - -void setup() -{ - size(200, 200); - colorMode(HSB, 360, height, height); - hue = new int[width/barWidth]; - noStroke(); -} - -void draw() -{ - int j = 0; - for (int i=0; i<=(width-barWidth); i+=barWidth) { - if ((mouseX > i) && (mouseX < i+barWidth)) { - hue[j] = mouseY; - } - fill(hue[j], height/1.2, height/1.2); - rect(i, 0, barWidth, height); - j++; - } -} diff --git a/mode/examples/Basics/Color/LinearGradient/LinearGradient.pde b/mode/examples/Basics/Color/LinearGradient/LinearGradient.pde deleted file mode 100644 index f41fc2b66..000000000 --- a/mode/examples/Basics/Color/LinearGradient/LinearGradient.pde +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Simple Linear Gradient - * by Ira Greenberg. - * - * Using the convenient red(), green() - * and blue() component functions, - * generate some linear gradients. - */ - -// constants -int Y_AXIS = 1; -int X_AXIS = 2; - -void setup(){ - size(200, 200); - - // create some gradients - // background - color b1 = color(190, 190, 190); - color b2 = color(20, 20, 20); - setGradient(0, 0, width, height, b1, b2, Y_AXIS); - //center squares - color c1 = color(255, 120, 0); - color c2 = color(10, 45, 255); - color c3 = color(10, 255, 15); - color c4 = color(125, 2, 140); - color c5 = color(255, 255, 0); - color c6 = color(25, 255, 200); - setGradient(25, 25, 75, 75, c1, c2, Y_AXIS); - setGradient(100, 25, 75, 75, c3, c4, X_AXIS); - setGradient(25, 100, 75, 75, c2, c5, X_AXIS); - setGradient(100, 100, 75, 75, c4, c6, Y_AXIS); -} - -void setGradient(int x, int y, float w, float h, color c1, color c2, int axis ){ - // calculate differences between color components - float deltaR = red(c2)-red(c1); - float deltaG = green(c2)-green(c1); - float deltaB = blue(c2)-blue(c1); - - // choose axis - if(axis == Y_AXIS){ - /*nested for loops set pixels - in a basic table structure */ - // column - for (int i=x; i<=(x+w); i++){ - // row - for (int j = y; j<=(y+h); j++){ - color c = color( - (red(c1)+(j-y)*(deltaR/h)), - (green(c1)+(j-y)*(deltaG/h)), - (blue(c1)+(j-y)*(deltaB/h)) - ); - set(i, j, c); - } - } - } - else if(axis == X_AXIS){ - // column - for (int i=y; i<=(y+h); i++){ - // row - for (int j = x; j<=(x+w); j++){ - color c = color( - (red(c1)+(j-x)*(deltaR/h)), - (green(c1)+(j-x)*(deltaG/h)), - (blue(c1)+(j-x)*(deltaB/h)) - ); - set(j, i, c); - } - } - } -} - diff --git a/mode/examples/Basics/Color/RadialGradient/RadialGradient.pde b/mode/examples/Basics/Color/RadialGradient/RadialGradient.pde deleted file mode 100644 index f5ba2b3fe..000000000 --- a/mode/examples/Basics/Color/RadialGradient/RadialGradient.pde +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Simple Radial Gradient - * by Ira Greenberg. - * - * Using the convenient red(), green() - * and blue() component functions, - * generate an array of radial gradients. - */ - -void setup(){ - size(200, 200); - background(0); - smooth(); - - // create a simple table of gradients - int columns = 4; - int radius = (width/columns)/2; - // create some gradients - for (int i=radius; i< width; i+=radius*2){ - for (int j =radius; j< height; j+=radius*2){ - createGradient(i, j, radius, - color(int(random(255)), int(random(255)), int(random(255))), - color(int(random(255)), int(random(255)), int(random(255)))); - } - } -} - -void createGradient (float x, float y, float radius, color c1, color c2){ - float px = 0, py = 0, angle = 0; - - // calculate differences between color components - float deltaR = red(c2)-red(c1); - float deltaG = green(c2)-green(c1); - float deltaB = blue(c2)-blue(c1); - // hack to ensure there are no holes in gradient - // needs to be increased, as radius increases - float gapFiller = 8.0; - - for (int i=0; i< radius; i++){ - for (float j=0; j<360; j+=1.0/gapFiller){ - px = x+cos(radians(angle))*i; - py = y+sin(radians(angle))*i; - angle+=1.0/gapFiller; - color c = color( - (red(c1)+(i)*(deltaR/radius)), - (green(c1)+(i)*(deltaG/radius)), - (blue(c1)+(i)*(deltaB/radius)) - ); - set(int(px), int(py), c); - } - } - // adds smooth edge - // hack anti-aliasing - noFill(); - strokeWeight(3); - ellipse(x, y, radius*2, radius*2); -} - diff --git a/mode/examples/Basics/Color/RadialGradient2/RadialGradient2.pde b/mode/examples/Basics/Color/RadialGradient2/RadialGradient2.pde deleted file mode 100644 index ad571fcc0..000000000 --- a/mode/examples/Basics/Color/RadialGradient2/RadialGradient2.pde +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Inspired by Ira Greenberg's RadialGradient sketch, - * but uses a different method for the gradients. - */ - -int dim = 40; - -void setup() { - size(200, 200); - background(0); - smooth(); - noStroke(); - ellipseMode(RADIUS); - - // create a simple table of gradients - int rows = height / dim; - int cols = width / dim; - - for (int row = 0; row < rows; row++) { - for (int col = 0; col < cols; col++) { - drawGradient(col*dim + dim/2, row*dim + dim/2); - } - } -} - -void drawGradient(float x, float y) { - int radius = dim/2 - 2; - float r1 = random(255); - float g1 = random(255); - float b1 = random(255); - float dr = (random(255) - r1) / radius; - float dg = (random(255) - g1) / radius; - float db = (random(255) - b1) / radius; - - for (int r = radius; r > 0; --r) { - fill(r1, g1, b1); - ellipse(x, y, r, r); - r1 += dr; - g1 += dg; - b1 += db; - } -} - diff --git a/mode/examples/Basics/Color/Reading/Reading.pde b/mode/examples/Basics/Color/Reading/Reading.pde deleted file mode 100644 index d142aff88..000000000 --- a/mode/examples/Basics/Color/Reading/Reading.pde +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Reading. - * - * An image is recreated from its individual component colors. - * The many colors of the image are created through modulating the - * red, green, and blue values. This is an exageration of an LCD display. - */ - -size(200, 200); -noStroke(); -background(0); - -// Load an image from the data directory -PImage img = loadImage("cait.jpg"); -img.loadPixels(); - -// figure out how big to make each block based on -// the sketch area and the size of the input image -int eachW = width / img.width; -int eachH = height / img.height; -int each = min(eachW, eachH); -// vertical stripes will be a third as wide -int stripeW = each / 3; -// make sure the block size is a multiple of 3 -each = 3 * stripeW; - -int left = (width - (img.width * each)) / 2; -int top = (height - (img.height * each)) / 2; - -for (int y = 0; y < img.height; y++) { - int y1 = top + y*each; - - for (int x = 0; x < img.width; x++) { - int pixel = img.get(x, y); - int x1 = left + x*each; - - fill(red(pixel), 0, 0); - rect(x1 + stripeW*0, y1, stripeW, each); - - fill(0, green(pixel), 0); - rect(x1 + stripeW*1, y1, stripeW, each); - - fill(0, 0, blue(pixel)); - rect(x1 + stripeW*2, y1, stripeW, each); - } -} diff --git a/mode/examples/Basics/Color/Reading/data/cait.jpg b/mode/examples/Basics/Color/Reading/data/cait.jpg deleted file mode 100644 index bc15e16a5..000000000 Binary files a/mode/examples/Basics/Color/Reading/data/cait.jpg and /dev/null differ diff --git a/mode/examples/Basics/Color/Relativity/Relativity.pde b/mode/examples/Basics/Color/Relativity/Relativity.pde deleted file mode 100644 index 9332e9baf..000000000 --- a/mode/examples/Basics/Color/Relativity/Relativity.pde +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Relativity. - * - * Each color is perceived in relation to other colors. - * The top and bottom bars each contain the same component colors, - * but a different display order causes individual colors to appear differently. - */ - -color a, b, c, d, e; - -void setup() { - size(200, 200); - noStroke(); - a = color(165, 167, 20); - b = color(77, 86, 59); - c = color(42, 106, 105); - d = color(165, 89, 20); - e = color(146, 150, 127); - noLoop(); -} - -void draw() { - drawBand(a, b, c, d, e, 0, width/50); - drawBand(c, a, d, b, e, height/2, width/50); -} - -void drawBand(color v, color w, color x, color y, color z, int ypos, int barWidth) { - int num = 5; - color[] colorOrder = { v, w, x, y, z }; - for(int i = 0; i < width; i += barWidth*num) { - for(int j = 0; j < num; j++) { - fill(colorOrder[j]); - rect(i+j*barWidth, ypos, barWidth, height/2); - } - } -} - - - - - - diff --git a/mode/examples/Basics/Color/Saturation/Saturation.pde b/mode/examples/Basics/Color/Saturation/Saturation.pde deleted file mode 100644 index 84137147e..000000000 --- a/mode/examples/Basics/Color/Saturation/Saturation.pde +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Saturation. - * - * Saturation is the strength or purity of the color and represents the - * amount of gray in proportion to the hue. A "saturated" color is pure - * and an "unsaturated" color has a large percentage of gray. - * Move the cursor vertically over each bar to alter its saturation. - */ - -int barWidth = 5; -int lastBar = -1; - - -void setup() { - size(200, 200); - colorMode(HSB, width, height, 100); - noStroke(); -} - - -void draw() { - int whichBar = mouseX / barWidth; - if (whichBar != lastBar) { - int barX = whichBar * barWidth; - fill(barX, mouseY, 66); - rect(barX, 0, barWidth, height); - lastBar = whichBar; - } -} diff --git a/mode/examples/Basics/Color/WaveGradient/WaveGradient.pde b/mode/examples/Basics/Color/WaveGradient/WaveGradient.pde deleted file mode 100644 index eac305093..000000000 --- a/mode/examples/Basics/Color/WaveGradient/WaveGradient.pde +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Wave Gradient - * by Ira Greenberg. - * - * Generate a gradient along a sin() wave. - */ - -float angle = 0; -float px = 0, py = 0; -float amplitude = 30; -float frequency = 0; -float fillGap = 2.5; -color c; - -void setup() { - size(200, 200); - background(200,200,200); - noLoop(); -} - -void draw() { - for (int i =- 75; i < height+75; i++){ - // Reset angle to 0, so waves stack properly - angle = 0; - // Increasing frequency causes more gaps - frequency+=.006; - for (float j=0; j 0){ - for(int j = margin; j < width-margin; j+= box_space){ - fill(255-box_size*10); - rect(j, i, box_size, box_size); - } - box_size = box_size - 0.6; - } -} - - diff --git a/mode/examples/Basics/Control/Iteration/Iteration.pde b/mode/examples/Basics/Control/Iteration/Iteration.pde deleted file mode 100644 index 722806122..000000000 --- a/mode/examples/Basics/Control/Iteration/Iteration.pde +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Iteration. - * - * Iteration with a "for" structure constructs repetitive forms. - */ - -int k; -int xpos1 = 100; -int xpos2 = 118; -int count = 0; -int timey = 0; -int num = 12; - -size(200, 200); -background(102); -noStroke(); - -// Draw gray bars -fill(255); -k=60; -for(int i=0; i < num/3; i++) { - rect(25, k, 155, 5); - k+=10; -} - -// Black bars -fill(51); -k = 40; -for(int i=0; i < num; i++) { - rect(105, k, 30, 5); - k += 10; -} -k = 15; -for(int i = 0; i < num; i++) { - rect(125, k, 30, 5); - k +=10; -} - -// Thin lines -k = 42; -fill(0); -for(int i=0; i < num-1; i++) { - rect(36, k, 20, 1); - k+=10; -} diff --git a/mode/examples/Basics/Control/LogicalOperators/LogicalOperators.pde b/mode/examples/Basics/Control/LogicalOperators/LogicalOperators.pde deleted file mode 100644 index d9329c004..000000000 --- a/mode/examples/Basics/Control/LogicalOperators/LogicalOperators.pde +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Logical Operators. - * - * The logical operators for AND (&&) and OR (||) are used to - * combine simple relational statements into more complex expressions. - * The NOT (!) operator is used to negate a boolean statement. - */ - -size(200, 200); -background(126); - -boolean op = false; - -for(int i=5; i<=195; i+=5) { - // Logical AND - stroke(0); - if((i > 35) && (i < 100)) { - line(5, i, 95, i); - op = false; - } - - // Logical OR - stroke(76); - if((i <= 35) || (i >= 100)) { - line(105, i, 195, i); - op = true; - } - - // Testing if a boolean value is "true" - // The expression "if(op)" is equivalent to "if(op == true)" - if(op) { - stroke(0); - point(width/2, i); - } - - // Testing if a boolean value is "false" - // The expression "if(!op)" is equivalent to "if(op == false)" - if(!op) { - stroke(255); - point(width/4, i); - } -} - - - diff --git a/mode/examples/Basics/Data/CharactersStrings/CharactersStrings.pde b/mode/examples/Basics/Data/CharactersStrings/CharactersStrings.pde deleted file mode 100644 index c5b528562..000000000 --- a/mode/examples/Basics/Data/CharactersStrings/CharactersStrings.pde +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Characters Strings. - * - * Click on the image to give it focus and then type letters to - * shift the location of the image. - * Characters are typographic symbols such as A, d, and %. - * The character datatype, abbreviated as char, stores letters and - * symbols in the Unicode format, a coding system developed to support - * a variety of world languages. Characters are distinguished from other - * symbols by putting them between single quotes ('P'). - * A string is a sequence of characters. A string is noted by surrounding - * a group of letters with double quotes ("Processing"). - * Chars and strings are most often used with the keyboard methods, - * to display text to the screen, and to load images or files. - */ - -PImage frog; -PFont font; -int xoffset; -char letter; - -void setup() -{ - size(200, 200, P2D); - - font = loadFont("Eureka-90.vlw"); - textFont(font); - // Draw text more accurately and efficiently. - textMode(SCREEN); - textAlign(CENTER); - - // The String datatype must be capitalized because it is a complex datatype. - // A String is actually a class with its own methods, some of which are - // featured below. - String name = "rathausFrog"; - String extension = ".jpg"; - int nameLength = name.length(); - println("The length of " + name + " is " + nameLength + "."); - name = name.concat(extension); - nameLength = name.length(); - println("The length of " + name + " is " + nameLength + "."); - - // The parameter for the loadImage() method must be a string - // This line could also be written "frog = loadImage("rathausFrog.jpg"); - frog = loadImage(name); -} - -void draw() -{ - background(51); // Set background to dark gray - - // Same as image(frog, xoffset, 0), but more efficient - // because no transformations or tint() or smooth() are used. - set(xoffset, 0, frog); - - // Draw an X - line(0, 0, width, height); - line(0, height, width, 0); - -// // Get the width of the letter -// float letterWidth = textWidth(letter); -// - // Draw the letter to the center of the screen - text(letter, width/2, height/2); -} - -void keyPressed() -{ - // The variable "key" always contains the value of the most recent key pressed. - // If the key is an upper or lowercase letter between 'A' and 'z' - // the image is shifted to the corresponding value of that key - if (key >= 'A' && key <= 'z') { - // Map the index of the key pressed from the range between 'A' and 'z', - // into a position for the left edge of the image. The maximum xoffset - // is the width of the drawing area minus the size of the image. - xoffset = int(map(key, 'A', 'z', 0, width - frog.width)); - // Update the letter shown to the screen - letter = key; - // Write the letter to the console - println(key); - } -} diff --git a/mode/examples/Basics/Data/CharactersStrings/data/Eureka-90.vlw b/mode/examples/Basics/Data/CharactersStrings/data/Eureka-90.vlw deleted file mode 100644 index d78d18272..000000000 Binary files a/mode/examples/Basics/Data/CharactersStrings/data/Eureka-90.vlw and /dev/null differ diff --git a/mode/examples/Basics/Data/CharactersStrings/data/rathausFrog.jpg b/mode/examples/Basics/Data/CharactersStrings/data/rathausFrog.jpg deleted file mode 100644 index 220deece8..000000000 Binary files a/mode/examples/Basics/Data/CharactersStrings/data/rathausFrog.jpg and /dev/null differ diff --git a/mode/examples/Basics/Data/DatatypeConversion/DatatypeConversion.pde b/mode/examples/Basics/Data/DatatypeConversion/DatatypeConversion.pde deleted file mode 100644 index 381afd181..000000000 --- a/mode/examples/Basics/Data/DatatypeConversion/DatatypeConversion.pde +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Datatype Conversion. - * - * It is sometimes beneficial to convert a value from one type of - * data to another. Each of the conversion functions converts its parameter - * to an equivalent representation within its datatype. - * The conversion functions include int(), float(), char(), byte(), and others. - */ - -size(200, 200); -background(51); -noStroke(); - -char c; // Chars are used for storing typographic symbols -float f; // Floats are decimal numbers -int i; // Ints are values between 2,147,483,647 and -2147483648 -byte b; // Bytes are values between -128 and 128 - -c = 'A'; -f = float(c); // Sets f = 65.0 -i = int(f * 1.4); // Sets i to 91 -b = byte(c / 2); // Sets b to 32 - -rect(f, 0, 40, 66); -fill(204); -rect(i, 67, 40, 66); -fill(255); -rect(b, 134, 40, 66); diff --git a/mode/examples/Basics/Data/IntegersFloats/IntegersFloats.pde b/mode/examples/Basics/Data/IntegersFloats/IntegersFloats.pde deleted file mode 100644 index 87bf67f19..000000000 --- a/mode/examples/Basics/Data/IntegersFloats/IntegersFloats.pde +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Integers Floats. - * - * Integers and floats are two different kinds of numerical data. - * An integer (more commonly called an int) is a number without - * a decimal point. A float is a floating-point number, which means - * it is a number that has a decimal place. Floats are used when - * more precision is needed. - */ - -int a = 0; // Create a variable "a" of the datatype "int" -float b = 0.0; // Create a variable "b" of the datatype "float" - -void setup() -{ - size(200, 200); - stroke(255); - frameRate(30); -} - -void draw() -{ - background(51); - - a = a + 1; - b = b + 0.2; - line(a, 0, a, height/2); - line(b, height/2, b, height); - - if(a > width) { - a = 0; - } - if(b > width) { - b = 0; - } -} diff --git a/mode/examples/Basics/Data/TrueFalse/TrueFalse.pde b/mode/examples/Basics/Data/TrueFalse/TrueFalse.pde deleted file mode 100644 index c4bb0531f..000000000 --- a/mode/examples/Basics/Data/TrueFalse/TrueFalse.pde +++ /dev/null @@ -1,34 +0,0 @@ -/** - * True/False. - * - * Boolean data is one bit of information. True or false. - * It is common to use Booleans with control statements to - * determine the flow of a program. In this example, when the - * boolean value "x" is true, vertical black lines are drawn and when - * the boolean value "x" is false, horizontal gray lines are drawn. - */ - -boolean x = false; - -size(200, 200); -background(0); -stroke(0); - -for (int i = 1; i < width; i += 2) -{ - if (i < width/2) { - x = true; - } else { - x = false; - } - - if (x) { - stroke(255); - line(i, 1, i, height-1); - } - - if (!x) { - stroke(126); - line(width/2 , i, width-2, i); - } -} diff --git a/mode/examples/Basics/Data/VariableScope/VariableScope.pde b/mode/examples/Basics/Data/VariableScope/VariableScope.pde deleted file mode 100644 index 8c2ae3559..000000000 --- a/mode/examples/Basics/Data/VariableScope/VariableScope.pde +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Variable Scope. - * - * Variables may either have a global or local "scope". - * For example, variables declared within either the - * setup() or loop() functions may be only used in these - * functions. Global variables, variables declared outside - * of setup() and loop(), may be used anywhere within the program. - * If a local variable is declared with the same name as a - * global variable, the program will use the local variable to make - * its calculations within the current scope. Variables may be localized - * within classes, functions, and iterative statements. - */ - -int a = 20; // Create a global variable "a" - -void setup() -{ - size(200, 200); - background(51); - stroke(255); - noLoop(); -} - -void draw() -{ - // Draw a line using the global variable "a" - line(a, 0, a, height); - - // Create a new variable "a" local to the for() statement - for(int a=50; a<80; a += 2) { - line(a, 0, a, height); - } - - // Create a new variable "a" local to the loop() method - int a = 100; - // Draw a line using the new local variable "a" - line(a, 0, a, height); - - // Make a call to the custom function drawAnotherLine() - drawAnotherLine(); - - // Make a call to the custom function setYetAnotherLine() - drawYetAnotherLine(); -} - -void drawAnotherLine() -{ - // Create a new variable "a" local to this method - int a = 185; - // Draw a line using the local variable "a" - line(a, 0, a, height); -} - -void drawYetAnotherLine() -{ - // Because no new local variable "a" is set, - // this lines draws using the original global - // variable "a" which is set to the value 20. - line(a+2, 0, a+2, height); -} diff --git a/mode/examples/Basics/Data/Variables/Variables.pde b/mode/examples/Basics/Data/Variables/Variables.pde deleted file mode 100644 index 9566ae472..000000000 --- a/mode/examples/Basics/Data/Variables/Variables.pde +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Variables. - * - * Variables are used for storing values. In this example, changing - * the values of variables 'a' and 'b' significantly change the composition. - */ - -size(200, 200); -background(0); -stroke(153); - -int a = 20; -int b = 50; -int c = a*8; -int d = a*9; -int e = b-a; -int f = b*2; -int g = f+e; - -line(a, f, b, g); -line(b, e, b, g); -line(b, e, d, c); -line(a, e, d-e, c); diff --git a/mode/examples/Basics/Form/Bezier/Bezier.pde b/mode/examples/Basics/Form/Bezier/Bezier.pde deleted file mode 100644 index e0b53db21..000000000 --- a/mode/examples/Basics/Form/Bezier/Bezier.pde +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Bezier. - * - * The first two parameters for the bezier() function specify the - * first point in the curve and the last two parameters specify - * the last point. The middle parameters set the control points - * that define the shape of the curve. - */ - -size(200, 200); -background(0); -stroke(255); -noFill(); -smooth(); - -for(int i = 0; i < 100; i += 20) { - bezier(90-(i/2.0), 20+i, 210, 10, 220, 150, 120-(i/8.0), 150+(i/4.0)); -} diff --git a/mode/examples/Basics/Form/BezierEllipse/BezierEllipse.pde b/mode/examples/Basics/Form/BezierEllipse/BezierEllipse.pde deleted file mode 100644 index 7db555f8c..000000000 --- a/mode/examples/Basics/Form/BezierEllipse/BezierEllipse.pde +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Bezier Ellipse - * By Ira Greenberg - * - * Generates an ellipse using bezier() and - * trig functions. Approximately every 1/2 - * second a new ellipse is plotted using - * random values for control/anchor points. - */ - -// arrays to hold ellipse coordinate data -float[] px, py, cx, cy, cx2, cy2; - -// global variable-points in ellipse -int pts = 4; - -color controlPtCol = #222222; -color anchorPtCol = #BBBBBB; - -void setup(){ - size(200, 200); - smooth(); - setEllipse(pts, 65, 65); - frameRate(1); -} - -void draw(){ - background(145); - drawEllipse(); - setEllipse(int(random(3, 12)), random(-100, 150), random(-100, 150)); -} - -// draw ellipse with anchor/control points -void drawEllipse(){ - strokeWeight(1.125); - stroke(255); - noFill(); - // create ellipse - for (int i=0; i0){ - line(px[i], py[i], cx2[i-1], cy2[i-1]); - } - line(px[i], py[i], cx[i], cy[i]); - } - - for ( int i=0; i< pts; i++){ - fill(controlPtCol); - noStroke(); - //control handles - ellipse(cx[i], cy[i], 4, 4); - ellipse(cx2[i], cy2[i], 4, 4); - - fill(anchorPtCol); - stroke(0); - //anchor points - rect(px[i], py[i], 5, 5); - } -} - -// fill up arrays with ellipse coordinate data -void setEllipse(int points, float radius, float controlRadius){ - pts = points; - px = new float[points]; - py = new float[points]; - cx = new float[points]; - cy = new float[points]; - cx2 = new float[points]; - cy2 = new float[points]; - float angle = 360.0/points; - float controlAngle1 = angle/3.0; - float controlAngle2 = controlAngle1*2.0; - for ( int i=0; i 1) { sa = 1; } - return 1-sa; -} - -float squared(float sa) { - sa = sa*sa; - return sa; -} diff --git a/mode/examples/Basics/Form/TriangleStrip/TriangleStrip.pde b/mode/examples/Basics/Form/TriangleStrip/TriangleStrip.pde deleted file mode 100644 index 8ad1dbdc0..000000000 --- a/mode/examples/Basics/Form/TriangleStrip/TriangleStrip.pde +++ /dev/null @@ -1,36 +0,0 @@ -/** - * TRIANGLE_STRIP Mode - * by Ira Greenberg. - * - * Generate a closed ring using vertex() - * function and beginShape(TRIANGLE_STRIP) - * mode. outerRad and innerRad variables - * control ring's outer/inner radii respectively. - * Trig functions generate ring. - */ - -size(200, 200); -background(204); -smooth(); - -int x = width/2; -int y = height/2; -float outerRad = min(width, height) * 0.4; -float innerRad = outerRad * 0.6; -float px = 0, py = 0, angle = 0; -float pts = 36; -float rot = 360.0/pts; - -beginShape(TRIANGLE_STRIP); -for (int i = 0; i < pts; i++) { - px = x + cos(radians(angle))*outerRad; - py = y + sin(radians(angle))*outerRad; - angle += rot; - vertex(px, py); - px = x + cos(radians(angle))*innerRad; - py = y + sin(radians(angle))*innerRad; - vertex(px, py); - angle += rot; -} -endShape(); - diff --git a/mode/examples/Basics/Form/Vertices/Vertices.pde b/mode/examples/Basics/Form/Vertices/Vertices.pde deleted file mode 100644 index f8c705650..000000000 --- a/mode/examples/Basics/Form/Vertices/Vertices.pde +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Vertices. - * - * The beginShape() function begins recording vertices - * for a shape and endShape() stops recording. - * A vertex is a location in space specified by X, Y, - * and sometimes Z coordinates. After calling the beginShape() function, - * a series of vertex() functions must follow. - * To stop drawing the shape, call the endShape() functions. - */ - -size(200, 200); -background(0); -noFill(); - -stroke(102); -beginShape(); -curveVertex(168, 182); -curveVertex(168, 182); -curveVertex(136, 38); -curveVertex(42, 34); -curveVertex(64, 200); -curveVertex(64, 200); -endShape(); - -stroke(51); -beginShape(LINES); -vertex(60, 40); -vertex(160, 10); -vertex(170, 150); -vertex(60, 150); -endShape(); - -stroke(126); -beginShape(); -vertex(60, 40); -bezierVertex(160, 10, 170, 150, 60, 150); -endShape(); - -stroke(255); -beginShape(POINTS); -vertex(60, 40); -vertex(160, 10); -vertex(170, 150); -vertex(60, 150); -endShape(); - diff --git a/mode/examples/Basics/Image/Alphamask/Alphamask.pde b/mode/examples/Basics/Image/Alphamask/Alphamask.pde deleted file mode 100644 index 59684e6a4..000000000 --- a/mode/examples/Basics/Image/Alphamask/Alphamask.pde +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Alpha Mask. - * - * Loads a "mask" for an image to specify the transparency - * in different parts of the image. The two images are blended - * together using the mask() method of PImage. - */ - -PImage img; -PImage maskImg; - -void setup() { - size(200, 200); - img = loadImage("test.jpg"); - maskImg = loadImage("mask.jpg"); - img.mask(maskImg); - imageMode(CENTER); -} - -void draw() { - background(map(mouseX+mouseY, 0, width+height, 0, 255)); - image(img, width/2, height/2); - image(img, mouseX, mouseY); -} diff --git a/mode/examples/Basics/Image/Alphamask/data/mask.jpg b/mode/examples/Basics/Image/Alphamask/data/mask.jpg deleted file mode 100644 index bbd138254..000000000 Binary files a/mode/examples/Basics/Image/Alphamask/data/mask.jpg and /dev/null differ diff --git a/mode/examples/Basics/Image/Alphamask/data/test.jpg b/mode/examples/Basics/Image/Alphamask/data/test.jpg deleted file mode 100644 index 04d3fc56d..000000000 Binary files a/mode/examples/Basics/Image/Alphamask/data/test.jpg and /dev/null differ diff --git a/mode/examples/Basics/Image/BackgroundImage/BackgroundImage.pde b/mode/examples/Basics/Image/BackgroundImage/BackgroundImage.pde deleted file mode 100644 index 2c5f1aac8..000000000 --- a/mode/examples/Basics/Image/BackgroundImage/BackgroundImage.pde +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Background Image. - * - * This example presents the fastest way to load a background image - * into Processing. To load an image as the background, it must be - * the same width and height as the program. - */ - -PImage bg; -int a; - -void setup() -{ - size(200,200); - frameRate(30); - // The background image must be the same size as the parameters - // into the size() method. In this program, the size of "milan_rubbish.jpg" - // is 200 x 200 pixels. - bg = loadImage("milan_rubbish.jpg"); -} - -void draw() -{ - background(bg); - - a = (a + 1)%(width+32); - stroke(226, 204, 0); - line(0, a, width, a-26); - line(0, a-6, width, a-32); -} diff --git a/mode/examples/Basics/Image/BackgroundImage/data/milan_rubbish.jpg b/mode/examples/Basics/Image/BackgroundImage/data/milan_rubbish.jpg deleted file mode 100644 index 516d46d5d..000000000 Binary files a/mode/examples/Basics/Image/BackgroundImage/data/milan_rubbish.jpg and /dev/null differ diff --git a/mode/examples/Basics/Image/CreateImage/CreateImage.pde b/mode/examples/Basics/Image/CreateImage/CreateImage.pde deleted file mode 100644 index 04e42d07b..000000000 --- a/mode/examples/Basics/Image/CreateImage/CreateImage.pde +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Create Image. - * - * The createImage() function provides a fresh buffer of pixels to play with. - * This example creates an image gradient. - */ - -PImage img; - -void setup() -{ - size(200, 200); - img = createImage(120, 120, ARGB); - img.loadPixels(); - for(int i=0; i < img.pixels.length; i++) { - img.pixels[i] = color(0, 90, 102, i%img.width * 2); - } -} - -void draw() -{ - background(204); - image(img, 33, 33); - image(img, mouseX-60, mouseY-60); -} diff --git a/mode/examples/Basics/Image/CreateImage/data/mask.jpg b/mode/examples/Basics/Image/CreateImage/data/mask.jpg deleted file mode 100644 index bbd138254..000000000 Binary files a/mode/examples/Basics/Image/CreateImage/data/mask.jpg and /dev/null differ diff --git a/mode/examples/Basics/Image/CreateImage/data/test.jpg b/mode/examples/Basics/Image/CreateImage/data/test.jpg deleted file mode 100644 index 04d3fc56d..000000000 Binary files a/mode/examples/Basics/Image/CreateImage/data/test.jpg and /dev/null differ diff --git a/mode/examples/Basics/Image/LoadDisplayImage/LoadDisplayImage.pde b/mode/examples/Basics/Image/LoadDisplayImage/LoadDisplayImage.pde deleted file mode 100644 index 8252c5cbc..000000000 --- a/mode/examples/Basics/Image/LoadDisplayImage/LoadDisplayImage.pde +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Load and Display - * - * Images can be loaded and displayed to the screen at their actual size - * or any other size. - */ - -PImage a; // Declare variable "a" of type PImage - -void setup() { - size(200, 200); - // The file "jelly.jpg" must be in the data folder - // of the current sketch to load successfully - a = loadImage("jelly.jpg"); // Load the image into the program - noLoop(); // Makes draw() only run once -} - -void draw() { - // Displays the image at its actual size at point (0,0) - image(a, 0, 0); - // Displays the image at point (100, 0) at half of its size - image(a, 100, 0, a.width/2, a.height/2); -} diff --git a/mode/examples/Basics/Image/LoadDisplayImage/data/jelly.jpg b/mode/examples/Basics/Image/LoadDisplayImage/data/jelly.jpg deleted file mode 100644 index a881c7e8b..000000000 Binary files a/mode/examples/Basics/Image/LoadDisplayImage/data/jelly.jpg and /dev/null differ diff --git a/mode/examples/Basics/Image/Pointillism/Pointillism.pde b/mode/examples/Basics/Image/Pointillism/Pointillism.pde deleted file mode 100644 index 3b7c96700..000000000 --- a/mode/examples/Basics/Image/Pointillism/Pointillism.pde +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Pointillism - * by Daniel Shiffman. - * - * Mouse horizontal location controls size of dots. - * Creates a simple pointillist effect using ellipses colored - * according to pixels in an image. - * - * Updated 27 February 2010. - */ - -PImage img; - -int smallPoint = 2; -int largePoint; -int top, left; - -void setup() { - size(200, 200); - img = loadImage("eames.jpg"); - //img = loadImage("sunflower.jpg"); // an alternative image - noStroke(); - background(255); - smooth(); - largePoint = min(width, height) / 10; - // center the image on the screen - left = (width - img.width) / 2; - top = (height - img.height) / 2; -} - -void draw() { - float pointillize = map(mouseX, 0, width, smallPoint, largePoint); - int x = int(random(img.width)); - int y = int(random(img.height)); - color pix = img.get(x, y); - fill(pix, 128); - ellipse(left + x, top + y, pointillize, pointillize); -} diff --git a/mode/examples/Basics/Image/Pointillism/data/eames.jpg b/mode/examples/Basics/Image/Pointillism/data/eames.jpg deleted file mode 100644 index c89377e40..000000000 Binary files a/mode/examples/Basics/Image/Pointillism/data/eames.jpg and /dev/null differ diff --git a/mode/examples/Basics/Image/Pointillism/data/sunflower.jpg b/mode/examples/Basics/Image/Pointillism/data/sunflower.jpg deleted file mode 100644 index 88398d188..000000000 Binary files a/mode/examples/Basics/Image/Pointillism/data/sunflower.jpg and /dev/null differ diff --git a/mode/examples/Basics/Image/RequestImage/RequestImage.pde b/mode/examples/Basics/Image/RequestImage/RequestImage.pde deleted file mode 100644 index 0e835c7ca..000000000 --- a/mode/examples/Basics/Image/RequestImage/RequestImage.pde +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Request Image - * by Ira Greenberg. - * From Processing for Flash Developers, Friends of ED, 2009. - * - * Shows how to use the requestImage() function with preloader animation. - * The requestImage() function loads images on a separate thread so that - * the sketch does not freeze while they load. It's very useful when you are - * loading large images, as this example demonstrates. - * - * To work, this example requires 10 images named dublin0.jpg ... dublin9.jpg - * in the sketch data directory. To save space, these images are not included - * with the example. - */ - -int imgCount = 10; -PImage[] imgs = new PImage[imgCount]; -float imgW; - -// Keeps track of loaded images (true or false) -boolean[] loadStates = new boolean[imgCount]; - -// For loading animation -float loaderX, loaderY, theta; - -void setup() { - size(800, 60); - smooth(); - imgW = width/imgCount; - - // Load images asynchronously - for (int i = 0; i < imgCount; i++){ - imgs[i] = requestImage("dublin"+i+".jpg"); - } -} - -void draw(){ - background(0); - - // Start loading animation - runLoaderAni(); - - for (int i = 0; i < imgs.length; i++){ - // Check if individual images are fully loaded - if ((imgs[i].width != 0) && (imgs[i].width != -1)){ - // As images are loaded set true in boolean array - loadStates[i] = true; - } - } - // When all images are loaded draw them to the screen - if (checkLoadStates()){ - drawImages(); - } -} - -void drawImages(){ - for (int i = 0; i < imgs.length; i++){ - image(imgs[i], width/10*i, 0, imgW, height); - } -} - -// Loading animation -void runLoaderAni(){ - // Only run when images are loading - if (!checkLoadStates()){ - ellipse(loaderX, loaderY, 10, 10); - loaderX += 2; - loaderY = height/2 + sin(theta) * (height/2.5); - theta += PI/22; - // Reposition ellipse if it goes off the screen - if (loaderX > width + 5){ - loaderX = -5; - } - } -} - -// Return true when all images are loaded - no false values left in array -boolean checkLoadStates(){ - for (int i = 0; i < imgs.length; i++){ - if (loadStates[i] == false){ - return false; - } - } - return true; -} - - - - - - diff --git a/mode/examples/Basics/Image/Sprite/Sprite.pde b/mode/examples/Basics/Image/Sprite/Sprite.pde deleted file mode 100644 index 2ea0c2782..000000000 --- a/mode/examples/Basics/Image/Sprite/Sprite.pde +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Sprite (Teddy) - * by James Patterson. - * - * Demonstrates loading and displaying a transparent GIF image. - */ - -PImage teddy; - -float xpos; -float ypos; -float drag = 30; - -void setup() { - size(200, 200); - teddy = loadImage("teddy.gif"); - xpos = width/2; - ypos = height/2; -} - -void draw() { - background(102); - - float difx = mouseX - xpos-teddy.width/2; - if (abs(difx) > 1) { - xpos = xpos + difx/drag; - xpos = constrain(xpos, 0, width-teddy.width); - } - - float dify = mouseY - ypos-teddy.height/2; - if (abs(dify) > 1) { - ypos = ypos + dify/drag; - ypos = constrain(ypos, 0, height-teddy.height); - } - - // Display the sprite at the position xpos, ypos - image(teddy, xpos, ypos); -} diff --git a/mode/examples/Basics/Image/Sprite/data/teddy.gif b/mode/examples/Basics/Image/Sprite/data/teddy.gif deleted file mode 100644 index 8994c1bdd..000000000 Binary files a/mode/examples/Basics/Image/Sprite/data/teddy.gif and /dev/null differ diff --git a/mode/examples/Basics/Image/Sprite2/Sprite2.pde b/mode/examples/Basics/Image/Sprite2/Sprite2.pde deleted file mode 100644 index dff97453a..000000000 --- a/mode/examples/Basics/Image/Sprite2/Sprite2.pde +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Sprite2 (Teddy) - * by James Patterson. - * - * Demonstrates loading and displaying a transparent GIF image. - * This alternate version shows a sky image in the background. - */ - -PImage teddy; -PImage sky; - -float xpos; -float ypos; -float drag = 30.0; - -void setup() { - size(200, 200); - teddy = loadImage("teddy.gif"); - sky = loadImage("sky.jpg"); - xpos = width/2; - ypos = height/2; - // resize the background image so that it fills the screen - if (sky.width != width || sky.height != height) { - sky.resize(width, height); - } -} - -void draw() { - background(sky); - - float difx = mouseX - xpos-teddy.width/2; - if (abs(difx) > 1) { - xpos = xpos + difx/drag; - xpos = constrain(xpos, 0, width-teddy.width); - } - - float dify = mouseY - ypos-teddy.height/2; - if (abs(dify) > 1 ) { - ypos = ypos + dify/drag; - ypos = constrain(ypos, 0, height-teddy.height); - } - - // Display the sprite at the position xpos, ypos - image(teddy, xpos, ypos); -} diff --git a/mode/examples/Basics/Image/Sprite2/data/sky.jpg b/mode/examples/Basics/Image/Sprite2/data/sky.jpg deleted file mode 100644 index 361509941..000000000 Binary files a/mode/examples/Basics/Image/Sprite2/data/sky.jpg and /dev/null differ diff --git a/mode/examples/Basics/Image/Sprite2/data/teddy.gif b/mode/examples/Basics/Image/Sprite2/data/teddy.gif deleted file mode 100644 index 8994c1bdd..000000000 Binary files a/mode/examples/Basics/Image/Sprite2/data/teddy.gif and /dev/null differ diff --git a/mode/examples/Basics/Image/Transparency/Transparency.pde b/mode/examples/Basics/Image/Transparency/Transparency.pde deleted file mode 100644 index a528ddb35..000000000 --- a/mode/examples/Basics/Image/Transparency/Transparency.pde +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Transparency. - * - * Move the pointer left and right across the image to change - * its position. This program overlays one image over another - * by modifying the alpha value of the image with the tint() function. - */ - -PImage a, b; -float offset; - -void setup() { - size(200, 200); - a = loadImage("construct.jpg"); // Load an image into the program - b = loadImage("wash.jpg"); // Load an image into the program -} - -void draw() { - image(a, 0, 0); - float offsetTarget = map(mouseX, 0, width, -b.width/2 - width/2, 0); - offset += (offsetTarget-offset)*0.05; - tint(255, 153); - image(b, offset, 20); -} - - - - - diff --git a/mode/examples/Basics/Image/Transparency/data/construct.jpg b/mode/examples/Basics/Image/Transparency/data/construct.jpg deleted file mode 100644 index 648678bb9..000000000 Binary files a/mode/examples/Basics/Image/Transparency/data/construct.jpg and /dev/null differ diff --git a/mode/examples/Basics/Image/Transparency/data/wash.jpg b/mode/examples/Basics/Image/Transparency/data/wash.jpg deleted file mode 100644 index 03beb544d..000000000 Binary files a/mode/examples/Basics/Image/Transparency/data/wash.jpg and /dev/null differ diff --git a/mode/examples/Basics/Input/Clock/Clock.pde b/mode/examples/Basics/Input/Clock/Clock.pde deleted file mode 100644 index 27ce7b334..000000000 --- a/mode/examples/Basics/Input/Clock/Clock.pde +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Clock. - * - * The current time can be read with the second(), minute(), - * and hour() functions. In this example, sin() and cos() values - * are used to set the position of the hands. - * - * Updated 27 February 2010 to handle size() changes. - */ - -int cx, cy; -float secondsRadius; -float minutesRadius; -float hoursRadius; -float clockDiameter; - -void setup() { - size(200, 200); - stroke(255); - smooth(); - - int radius = min(width, height) / 2; - secondsRadius = radius * 0.72; - minutesRadius = radius * 0.60; - hoursRadius = radius * 0.50; - clockDiameter = radius * 1.8; - - cx = width / 2; - cy = height / 2; -} - -void draw2() { - background(0); - - // Draw the clock background - fill(80); - noStroke(); - ellipse(cx, cy, clockDiameter, clockDiameter); - - // Angles for sin() and cos() start at 3 o'clock; - // subtract HALF_PI to make them start at the top - float s = map(second(), 0, 60, 0, TWO_PI) - HALF_PI; - float m = map(minute() + norm(second(), 0, 60), 0, 60, 0, TWO_PI) - HALF_PI; - float h = map(hour() + norm(minute(), 0, 60), 0, 24, 0, TWO_PI * 2) - HALF_PI; - - // Draw the hands of the clock - stroke(255); - strokeWeight(1); - line(cx, cy, cx + cos(s) * secondsRadius, cy + sin(s) * secondsRadius); - strokeWeight(2); - line(cx, cy, cx + cos(m) * minutesRadius, cy + sin(m) * minutesRadius); - strokeWeight(4); - line(cx, cy, cx + cos(h) * hoursRadius, cy + sin(h) * hoursRadius); - - // Draw the minute ticks - strokeWeight(2); - beginShape(POINTS); - for (int a = 0; a < 360; a+=6) { - float x = cx + cos(radians(a)) * secondsRadius; - float y = cy + sin(radians(a)) * secondsRadius; - vertex(x, y); - } - endShape(); -} diff --git a/mode/examples/Basics/Input/Constrain/Constrain.pde b/mode/examples/Basics/Input/Constrain/Constrain.pde deleted file mode 100644 index 84fcf06fe..000000000 --- a/mode/examples/Basics/Input/Constrain/Constrain.pde +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Constrain. - * - * Move the mouse across the screen to move the circle. - * The program constrains the circle to its box. - * - * Updated 27 February 2010 to handle changes in size(). - */ - -float mx; -float my; -float easing = 0.05; -int radius = 24; -int edge = 56; -int inner = edge + radius; - -void setup() { - size(200, 200); - noStroke(); - smooth(); - ellipseMode(RADIUS); - rectMode(CORNERS); -} - -void draw() { - background(51); - - if (abs(mouseX - mx) > 0.1) { - mx = mx + (mouseX - mx) * easing; - } - if (abs(mouseY - my) > 0.1) { - my = my + (mouseY- my) * easing; - } - - mx = constrain(mx, inner, width - inner); - my = constrain(my, inner, height - inner); - fill(76); - rect(edge, edge, width-edge, height-edge); - fill(255); - ellipse(mx, my, radius, radius); -} diff --git a/mode/examples/Basics/Input/Easing/Easing.pde b/mode/examples/Basics/Input/Easing/Easing.pde deleted file mode 100644 index a09011639..000000000 --- a/mode/examples/Basics/Input/Easing/Easing.pde +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Easing. - * - * Move the mouse across the screen and the symbol will follow. - * Between drawing each frame of the animation, the program - * calculates the difference between the position of the - * symbol and the cursor. If the distance is larger than - * 1 pixel, the symbol moves part of the distance (0.05) from its - * current position toward the cursor. - */ - -float x; -float y; -float targetX, targetY; -float easing = 0.05; - -void setup() -{ - size(200, 200); - smooth(); - noStroke(); -} - -void draw() -{ - background( 51 ); - - targetX = mouseX; - float dx = targetX - x; - if(abs(dx) > 1) { - x += dx * easing; - } - - targetY = mouseY; - float dy = targetY - y; - if(abs(dy) > 1) { - y += dy * easing; - } - - ellipse(x, y, 33, 33); -} diff --git a/mode/examples/Basics/Input/Keyboard/Keyboard.pde b/mode/examples/Basics/Input/Keyboard/Keyboard.pde deleted file mode 100644 index 3eba1f1d2..000000000 --- a/mode/examples/Basics/Input/Keyboard/Keyboard.pde +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Keyboard. - * - * Click on the image to give it focus and press the letter keys - * to create forms in time and space. Each key has a unique identifying - * number called its ASCII value. These numbers can be used to position - * shapes in space. - */ - -int rectWidth; - -void setup() { - size(200, 200); - noStroke(); - background(0); - rectWidth = width/4; -} - -void draw() { - // keep draw() here to continue looping while waiting for keys -} - -void keyPressed() { - int keyIndex = -1; - if (key >= 'A' && key <= 'Z') { - keyIndex = key - 'A'; - } else if (key >= 'a' && key <= 'z') { - keyIndex = key - 'a'; - } - if (keyIndex == -1) { - // If it's not a letter key, clear the screen - background(0); - } else { - // It's a letter key, fill a rectangle - fill(millis() % 255); - float x = map(keyIndex, 0, 25, 0, width - rectWidth); - rect(x, 0, rectWidth, height); - } -} diff --git a/mode/examples/Basics/Input/KeyboardFunctions/KeyboardFunctions.pde b/mode/examples/Basics/Input/KeyboardFunctions/KeyboardFunctions.pde deleted file mode 100644 index 882e92d63..000000000 --- a/mode/examples/Basics/Input/KeyboardFunctions/KeyboardFunctions.pde +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Keyboard Functions. - * Modified from code by Martin. - * Original 'Color Typewriter' concept by John Maeda. - * - * Click on the window to give it focus and press the letter keys to type colors. - * The keyboard function keyPressed() is called whenever - * a key is pressed. keyReleased() is another keyboard - * function that is called when a key is released. - */ - -int max_height = 20; -int min_height = 10; -int letter_height = max_height; // Height of the letters -int letter_width = 10; // Width of the letter - -int x = -letter_width; // X position of the letters -int y = 0; // Y position of the letters - -boolean newletter; - -int numChars = 26; // There are 26 characters in the alphabet -color[] colors = new color[numChars]; - -void setup() -{ - size(200, 200); - noStroke(); - colorMode(RGB, numChars); - background(numChars/2); - // Set a gray value for each key - for(int i=0; i= 'A' && key <= 'z') { - int keyIndex; - if(key <= 'Z') { - keyIndex = key-'A'; - letter_height = max_height; - fill(colors[key-'A']); - } else { - keyIndex = key-'a'; - letter_height = min_height; - fill(colors[key-'a']); - } - } else { - fill(0); - letter_height = 10; - } - - newletter = true; - - // Update the "letter" position - x = ( x + letter_width ); - - // Wrap horizontally - if (x > width - letter_width) { - x = 0; - y+= max_height; - } - - // Wrap vertically - if( y > height - letter_height) { - y = 0; // reset y to 0 - } -} diff --git a/mode/examples/Basics/Input/KeyboardFunctions/data/brugges.jpg b/mode/examples/Basics/Input/KeyboardFunctions/data/brugges.jpg deleted file mode 100644 index fa723f9da..000000000 Binary files a/mode/examples/Basics/Input/KeyboardFunctions/data/brugges.jpg and /dev/null differ diff --git a/mode/examples/Basics/Input/Milliseconds/Milliseconds.pde b/mode/examples/Basics/Input/Milliseconds/Milliseconds.pde deleted file mode 100644 index 2439ba363..000000000 --- a/mode/examples/Basics/Input/Milliseconds/Milliseconds.pde +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Milliseconds. - * - * A millisecond is 1/1000 of a second. - * Processing keeps track of the number of milliseconds a program has run. - * By modifying this number with the modulo(%) operator, - * different patterns in time are created. - */ - -float scale; - -void setup() -{ - size(200, 200); - noStroke(); - scale = width/10; -} - -void draw() -{ - for(int i=0; i 90) { - gx = 90; - } - - if (gy > 90) { - gy = 90; - } else if (gy < 10) { - gy = 10; - } -} diff --git a/mode/examples/Basics/Input/Mouse2D/Mouse2D.pde b/mode/examples/Basics/Input/Mouse2D/Mouse2D.pde deleted file mode 100644 index c316bc6ce..000000000 --- a/mode/examples/Basics/Input/Mouse2D/Mouse2D.pde +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Mouse 2D. - * - * Moving the mouse changes the position and size of each box. - */ - -void setup() -{ - size(200, 200); - noStroke(); - rectMode(CENTER); -} - -void draw() -{ - background(51); - fill(255, 204); - rect(mouseX, height/2, mouseY/2+10, mouseY/2+10); - fill(255, 204); - int inverseX = width-mouseX; - int inverseY = height-mouseY; - rect(inverseX, height/2, (inverseY/2)+10, (inverseY/2)+10); -} - diff --git a/mode/examples/Basics/Input/MouseFunctions/MouseFunctions.pde b/mode/examples/Basics/Input/MouseFunctions/MouseFunctions.pde deleted file mode 100644 index 8d4e0fe36..000000000 --- a/mode/examples/Basics/Input/MouseFunctions/MouseFunctions.pde +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Mouse Functions. - * - * Click on the box and drag it across the screen. - */ - -float bx; -float by; -int bs = 20; -boolean bover = false; -boolean locked = false; -float bdifx = 0.0; -float bdify = 0.0; - - -void setup() -{ - size(200, 200); - bx = width/2.0; - by = height/2.0; - rectMode(RADIUS); -} - -void draw() -{ - background(0); - - // Test if the cursor is over the box - if (mouseX > bx-bs && mouseX < bx+bs && - mouseY > by-bs && mouseY < by+bs) { - bover = true; - if(!locked) { - stroke(255); - fill(153); - } - } else { - stroke(153); - fill(153); - bover = false; - } - - // Draw the box - rect(bx, by, bs, bs); -} - -void mousePressed() { - if(bover) { - locked = true; - fill(255, 255, 255); - } else { - locked = false; - } - bdifx = mouseX-bx; - bdify = mouseY-by; - -} - -void mouseDragged() { - if(locked) { - bx = mouseX-bdifx; - by = mouseY-bdify; - } -} - -void mouseReleased() { - locked = false; -} - diff --git a/mode/examples/Basics/Input/MousePress/MousePress.pde b/mode/examples/Basics/Input/MousePress/MousePress.pde deleted file mode 100644 index 526eced76..000000000 --- a/mode/examples/Basics/Input/MousePress/MousePress.pde +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Click. - * - * Move the mouse to position the shape. - * Press the mouse button to invert the color. - */ - - -void setup() { - size(200, 200); - fill(126); - background(102); -} - -void draw() { - if(mousePressed) { - stroke(255); - } else { - stroke(0); - } - line(mouseX-66, mouseY, mouseX+66, mouseY); - line(mouseX, mouseY-66, mouseX, mouseY+66); -} diff --git a/mode/examples/Basics/Input/MouseSignals/MouseSignals.pde b/mode/examples/Basics/Input/MouseSignals/MouseSignals.pde deleted file mode 100644 index 6e1fd2bbc..000000000 --- a/mode/examples/Basics/Input/MouseSignals/MouseSignals.pde +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Mouse Signals. - * - * Move and click the mouse to generate signals. - * The top row is the signal from "mouseX", - * the middle row is the signal from "mouseY", - * and the bottom row is the signal from "mousePressed". - */ - -int[] xvals; -int[] yvals; -int[] bvals; - -void setup() -{ - size(200, 200); - xvals = new int[width]; - yvals = new int[width]; - bvals = new int[width]; -} - -int arrayindex = 0; - -void draw() -{ - background(102); - - for(int i=1; i 10000 - -void setup() -{ - size(640, 360, P3D); - orientation(LANDSCAPE); - noStroke(); - fill(204); - sphereDetail(30); -} - -void draw() -{ - background(0); - - // Light the bottom of the sphere - directionalLight(51, 102, 126, 0, -1, 0); - - // Orange light on the upper-right of the sphere - spotLight(204, 153, 0, 360, 160, 600, 0, 0, -1, PI/2, 600); - - // Moving spotlight that follows the mouse - spotLight(102, 153, 204, 360, mouseY, 600, 0, 0, -1, PI/2, 600); - - translate(width/2, height/2, 0); - sphere(120); -} - diff --git a/mode/examples/Basics/Math/AdditiveWave/AdditiveWave.pde b/mode/examples/Basics/Math/AdditiveWave/AdditiveWave.pde deleted file mode 100644 index 14ba9914f..000000000 --- a/mode/examples/Basics/Math/AdditiveWave/AdditiveWave.pde +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Additive Wave - * by Daniel Shiffman. - * - * Create a more complex wave by adding two waves together. - */ - -int xspacing = 8; // How far apart should each horizontal location be spaced -int w; // Width of entire wave -int maxwaves = 4; // total # of waves to add together - -float theta = 0.0; -float[] amplitude = new float[maxwaves]; // Height of wave -float[] dx = new float[maxwaves]; // Value for incrementing X, to be calculated as a function of period and xspacing -float[] yvalues; // Using an array to store height values for the wave (not entirely necessary) - -void setup() { - size(200, 200); - frameRate(30); - colorMode(RGB, 255, 255, 255, 100); - smooth(); - w = width + 16; - - for (int i = 0; i < maxwaves; i++) { - amplitude[i] = random(10,30); - float period = random(100,300); // How many pixels before the wave repeats - dx[i] = (TWO_PI / period) * xspacing; - } - - yvalues = new float[w/xspacing]; -} - -void draw() { - background(0); - calcWave(); - renderWave(); -} - -void calcWave() { - // Increment theta (try different values for 'angular velocity' here - theta += 0.02; - - // Set all height values to zero - for (int i = 0; i < yvalues.length; i++) { - yvalues[i] = 0; - } - - // Accumulate wave height values - for (int j = 0; j < maxwaves; j++) { - float x = theta; - for (int i = 0; i < yvalues.length; i++) { - // Every other wave is cosine instead of sine - if (j % 2 == 0) yvalues[i] += sin(x)*amplitude[j]; - else yvalues[i] += cos(x)*amplitude[j]; - x+=dx[j]; - } - } -} - -void renderWave() { - // A simple way to draw the wave with an ellipse at each location - noStroke(); - fill(255,50); - ellipseMode(CENTER); - for (int x = 0; x < yvalues.length; x++) { - ellipse(x*xspacing,width/2+yvalues[x],16,16); - } -} - diff --git a/mode/examples/Basics/Math/Arctangent/Arctangent.pde b/mode/examples/Basics/Math/Arctangent/Arctangent.pde deleted file mode 100644 index b03e0bda6..000000000 --- a/mode/examples/Basics/Math/Arctangent/Arctangent.pde +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Arctangent. - * - * Move the mouse to change the direction of the eyes. - * The atan2() function computes the angle from each eye - * to the cursor. - */ - -Eye e1, e2, e3, e4, e5; - -void setup() -{ - size(200, 200); - smooth(); - noStroke(); - e1 = new Eye( 50, 16, 80); - e2 = new Eye( 64, 85, 40); - e3 = new Eye( 90, 200, 120); - e4 = new Eye(150, 44, 40); - e5 = new Eye(175, 120, 80); -} - -void draw() -{ - background(102); - - e1.update(mouseX, mouseY); - e2.update(mouseX, mouseY); - e3.update(mouseX, mouseY); - e4.update(mouseX, mouseY); - e5.update(mouseX, mouseY); - - e1.display(); - e2.display(); - e3.display(); - e4.display(); - e5.display(); -} - -class Eye -{ - int ex, ey; - int size; - float angle = 0.0; - - Eye(int x, int y, int s) { - ex = x; - ey = y; - size = s; - } - - void update(int mx, int my) { - angle = atan2(my-ey, mx-ex); - } - - void display() { - pushMatrix(); - translate(ex, ey); - fill(255); - ellipse(0, 0, size, size); - rotate(angle); - fill(153); - ellipse(size/4, 0, size/2, size/2); - popMatrix(); - } -} - diff --git a/mode/examples/Basics/Math/Distance1D/Distance1D.pde b/mode/examples/Basics/Math/Distance1D/Distance1D.pde deleted file mode 100644 index a17b3febc..000000000 --- a/mode/examples/Basics/Math/Distance1D/Distance1D.pde +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Distance 1D. - * - * Move the mouse left and right to control the - * speed and direction of the moving shapes. - */ - -int thin = 8; -int thick = 36; -float xpos1 = 134.0; -float xpos2 = 44.0; -float xpos3 = 58.0; -float xpos4 = 120.0; - -void setup() -{ - size(200, 200); - noStroke(); - frameRate(60); -} - -void draw() -{ - background(0); - - float mx = mouseX * 0.4 - width/5.0; - - fill(102); - rect(xpos2, 0, thick, height/2); - fill(204); - rect(xpos1, 0, thin, height/2); - fill(102); - rect(xpos4, height/2, thick, height/2); - fill(204); - rect(xpos3, height/2, thin, height/2); - - xpos1 += mx/16; - xpos2 += mx/64; - xpos3 -= mx/16; - xpos4 -= mx/64; - - if(xpos1 < -thin) { xpos1 = width; } - if(xpos1 > width) { xpos1 = -thin; } - if(xpos2 < -thick) { xpos2 = width; } - if(xpos2 > width) { xpos2 = -thick; } - if(xpos3 < -thin) { xpos3 = width; } - if(xpos3 > width) { xpos3 = -thin; } - if(xpos4 < -thick) { xpos4 = width; } - if(xpos4 > width) { xpos4 = -thick; } -} - diff --git a/mode/examples/Basics/Math/Distance2D/Distance2D.pde b/mode/examples/Basics/Math/Distance2D/Distance2D.pde deleted file mode 100644 index e2bfe4b44..000000000 --- a/mode/examples/Basics/Math/Distance2D/Distance2D.pde +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Distance 2D. - * - * Move the mouse across the image to obscure and reveal the matrix. - * Measures the distance from the mouse to each square and sets the - * size proportionally. - */ - -float max_distance; - -void setup() { - size(200, 200); - smooth(); - noStroke(); - max_distance = dist(0, 0, width, height); -} - -void draw() -{ - background(51); - - for(int i = 0; i <= width; i += 20) { - for(int j = 0; j <= height; j += 20) { - float size = dist(mouseX, mouseY, i, j); - size = size/max_distance * 66; - ellipse(i, j, size, size); - } - } -} diff --git a/mode/examples/Basics/Math/DoubleRandom/DoubleRandom.pde b/mode/examples/Basics/Math/DoubleRandom/DoubleRandom.pde deleted file mode 100644 index a33bc7523..000000000 --- a/mode/examples/Basics/Math/DoubleRandom/DoubleRandom.pde +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Double Random - * by Ira Greenberg. - * - * Using two random() calls and the point() function - * to create an irregular sawtooth line. - */ - -size(200, 200); -background(0); -int totalPts = 300; -float steps = totalPts + 1; -stroke(255); -float rand = 0; - -for (int i = 1; i < steps; i++){ - point( (width/steps) * i, (height/2) + random(-rand, rand) ); - rand += random(-5, 5); -} - diff --git a/mode/examples/Basics/Math/Graphing2DEquation/Graphing2DEquation.pde b/mode/examples/Basics/Math/Graphing2DEquation/Graphing2DEquation.pde deleted file mode 100644 index bd20ed864..000000000 --- a/mode/examples/Basics/Math/Graphing2DEquation/Graphing2DEquation.pde +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Graphing 2D Equations - * by Daniel Shiffman. - * - * Graphics the following equation: - * sin(n*cos(r) + 5*theta) - * where n is a function of horizontal mouse location. - */ - -void setup() { - size(200,200); - frameRate(30); -} - -void draw() { - loadPixels(); - float n = (mouseX * 10.0) / width; - float w = 16.0; // 2D space width - float h = 16.0; // 2D space height - float dx = w / width; // Increment x this amount per pixel - float dy = h / height; // Increment y this amount per pixel - float x = -w/2; // Start x at -1 * width / 2 - for (int i = 0; i < width; i++) { - float y = -h/2; // Start y at -1 * height / 2 - for (int j = 0; j < height; j++) { - float r = sqrt((x*x) + (y*y)); // Convert cartesian to polar - float theta = atan2(y,x); // Convert cartesian to polar - // Compute 2D polar coordinate function - float val = sin(n*cos(r) + 5 * theta); // Results in a value between -1 and 1 - //float val = cos(r); // Another simple function - //float val = sin(theta); // Another simple function - // Map resulting vale to grayscale value - pixels[i+j*width] = color((val + 1.0) * 255.0/2.0); // Scale to between 0 and 255 - y += dy; // Increment y - } - x += dx; // Increment x - } - updatePixels(); -} - diff --git a/mode/examples/Basics/Math/IncrementDecrement/IncrementDecrement.pde b/mode/examples/Basics/Math/IncrementDecrement/IncrementDecrement.pde deleted file mode 100644 index 8398c5faa..000000000 --- a/mode/examples/Basics/Math/IncrementDecrement/IncrementDecrement.pde +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Increment Decrement. - * - * Writing "a++" is equivalent to "a = a + 1". - * Writing "a--" is equivalent to "a = a - 1". - */ - -int a; -int b; -boolean direction; - -void setup() -{ - size(200, 200); - colorMode(RGB, width); - a = 0; - b = width; - direction = true; - frameRate(30); -} - -void draw() -{ - a++; - if(a > width) { - a = 0; - direction = !direction; - } - if(direction == true){ - stroke(a); - } else { - stroke(width-a); - } - line(a, 0, a, height/2); - - b--; - if(b < 0) { - b = width; - } - if(direction == true) { - stroke(width-b); - } else { - stroke(b); - } - line(b, height/2+1, b, height); -} diff --git a/mode/examples/Basics/Math/Modulo/Modulo.pde b/mode/examples/Basics/Math/Modulo/Modulo.pde deleted file mode 100644 index 7ad1f5dc3..000000000 --- a/mode/examples/Basics/Math/Modulo/Modulo.pde +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Modulo. - * - * The modulo operator (%) returns the remainder of a number - * divided by another. As in this example, it is often used - * to keep numerical values within a set range. - */ - -int num = 20; -float c; - -void setup() -{ - size(200,200); - fill(255); - frameRate(30); -} - -void draw() -{ - background(0); - c+=0.1; - for(int i=1; i <= >= -// Equality: == != -// Logical AND: && -// Logical OR: || -// Assignment: = += -= *= /= %= - -size(200, 200); -background(51); -noFill(); -stroke(51); - -stroke(204); -for(int i=0; i< width-20; i+= 4) { - // The 30 is added to 70 and then evaluated - // if it is greater than the current value of "i" - // For clarity, write as "if(i > (30 + 70)) {" - if(i > 30 + 70) { - line(i, 0, i, 50); - } -} - -stroke(255); -// The 2 is multiplied by the 8 and the result is added to the 5 -// For clarity, write as "rect(5 + (2 * 8), 0, 90, 20);" -rect(4 + 2 * 8, 52, 90, 48); -rect((4 + 2) * 8, 100, 90, 49); - -stroke(153); -for(int i=0; i< width; i+= 2) { - // The relational statements are evaluated - // first, and then the logical AND statements and - // finally the logical OR. For clarity, write as: - // "if(((i > 10) && (i < 50)) || ((i > 80) && (i < 160))) {" - if(i > 20 && i < 50 || i > 100 && i < width-20) { - line(i, 151, i, height-1); - } -} - - diff --git a/mode/examples/Basics/Math/PolarToCartesian/PolarToCartesian.pde b/mode/examples/Basics/Math/PolarToCartesian/PolarToCartesian.pde deleted file mode 100644 index f1f2b1e7d..000000000 --- a/mode/examples/Basics/Math/PolarToCartesian/PolarToCartesian.pde +++ /dev/null @@ -1,52 +0,0 @@ -/** - * PolarToCartesian - * by Daniel Shiffman. - * - * Convert a polar coordinate (r,theta) to cartesian (x,y): - * x = r * cos(theta) - * y = r * sin(theta) - */ - -float r; - -// Angle and angular velocity, accleration -float theta; -float theta_vel; -float theta_acc; - -void setup() { - size(200, 200); - frameRate(30); - smooth(); - - // Initialize all values - r = 50; - theta = 0; - theta_vel = 0; - theta_acc = 0.0001; -} - -void draw() { - background(0); - // Translate the origin point to the center of the screen - translate(width/2, height/2); - - // Convert polar to cartesian - float x = r * cos(theta); - float y = r * sin(theta); - - // Draw the ellipse at the cartesian coordinate - ellipseMode(CENTER); - noStroke(); - fill(200); - ellipse(x, y, 16, 16); - - // Apply acceleration and velocity to angle (r remains static in this example) - theta_vel += theta_acc; - theta += theta_vel; - -} - - - - diff --git a/mode/examples/Basics/Math/Random/Random.pde b/mode/examples/Basics/Math/Random/Random.pde deleted file mode 100644 index 5fa97b8f0..000000000 --- a/mode/examples/Basics/Math/Random/Random.pde +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Random. - * - * Random numbers create the basis of this image. - * Each time the program is loaded the result is different. - */ - -size(200, 200); -smooth(); -background(0); -strokeWeight(10); - -for(int i = 0; i < width; i++) { - float r = random(255); - float x = random(0, width); - stroke(r, 100); - line(i, 0, x, height); -} - diff --git a/mode/examples/Basics/Math/Sine/Sine.pde b/mode/examples/Basics/Math/Sine/Sine.pde deleted file mode 100644 index 848add369..000000000 --- a/mode/examples/Basics/Math/Sine/Sine.pde +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Sine. - * - * Smoothly scaling size with the sin() function. - */ - -float spin = 0.0; -float diameter = 84.0; -float angle; - -float angle_rot; -int rad_points = 90; - -void setup() -{ - size(200, 200); - noStroke(); - smooth(); -} - -void draw() -{ - background(153); - - translate(130, 65); - - fill(255); - ellipse(0, 0, 16, 16); - - angle_rot = 0; - fill(51); - - for(int i=0; i<5; i++) { - pushMatrix(); - rotate(angle_rot + -45); - ellipse(-116, 0, diameter, diameter); - popMatrix(); - angle_rot += PI*2/5; - } - - diameter = 34 * sin(angle) + 168; - - angle += 0.02; - if (angle > TWO_PI) { angle = 0; } -} - diff --git a/mode/examples/Basics/Math/SineCosine/SineCosine.pde b/mode/examples/Basics/Math/SineCosine/SineCosine.pde deleted file mode 100644 index 4a40ddee2..000000000 --- a/mode/examples/Basics/Math/SineCosine/SineCosine.pde +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Sine Cosine. - * - * Linear movement with sin() and cos(). - * Numbers between 0 and PI*2 (TWO_PI which is roughly 6.28) - * are put into these functions and numbers between -1 and 1 are - * returned. These values are then scaled to produce larger movements. - */ - -int i = 45; -int j = 225; -float pos1 = 0; -float pos2 = 0; -float pos3 = 0; -float pos4 = 0; -int sc = 40; - -void setup() -{ - size(200, 200); - noStroke(); - smooth(); -} - -void draw() -{ - background(0); - - fill(51); - rect(60, 60, 80, 80); - - fill(255); - ellipse(pos1, 36, 32, 32); - - fill(153); - ellipse(36, pos2, 32, 32); - - fill(255); - ellipse(pos3, 164, 32, 32); - - fill(153); - ellipse(164, pos4, 32, 32); - - i += 3; - j -= 3; - - if(i > 405) { - i = 45; - j = 225; - } - - float ang1 = radians(i); // convert degrees to radians - float ang2 = radians(j); // convert degrees to radians - pos1 = width/2 + (sc * cos(ang1)); - pos2 = width/2 + (sc * sin(ang1)); - pos3 = width/2 + (sc * cos(ang2)); - pos4 = width/2 + (sc * sin(ang2)); -} - diff --git a/mode/examples/Basics/Math/SineWave/SineWave.pde b/mode/examples/Basics/Math/SineWave/SineWave.pde deleted file mode 100644 index da47bed36..000000000 --- a/mode/examples/Basics/Math/SineWave/SineWave.pde +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Sine Wave - * by Daniel Shiffman. - * - * Render a simple sine wave. - */ - -int xspacing = 8; // How far apart should each horizontal location be spaced -int w; // Width of entire wave - -float theta = 0.0; // Start angle at 0 -float amplitude = 75.0; // Height of wave -float period = 500.0; // How many pixels before the wave repeats -float dx; // Value for incrementing X, a function of period and xspacing -float[] yvalues; // Using an array to store height values for the wave - -void setup() { - size(200,200); - frameRate(30); - colorMode(RGB,255,255,255,100); - smooth(); - w = width+16; - dx = (TWO_PI / period) * xspacing; - yvalues = new float[w/xspacing]; -} - -void draw() { - background(0); - calcWave(); - renderWave(); - -} - -void calcWave() { - // Increment theta (try different values for 'angular velocity' here - theta += 0.02; - - // For every x value, calculate a y value with sine function - float x = theta; - for (int i = 0; i < yvalues.length; i++) { - yvalues[i] = sin(x)*amplitude; - x+=dx; - } -} - -void renderWave() { - // A simple way to draw the wave with an ellipse at each location - for (int x = 0; x < yvalues.length; x++) { - noStroke(); - fill(255,50); - ellipseMode(CENTER); - ellipse(x*xspacing,width/2+yvalues[x],16,16); - } -} - diff --git a/mode/examples/Basics/Objects/CompositeObjects/CompositeObjects.pde b/mode/examples/Basics/Objects/CompositeObjects/CompositeObjects.pde deleted file mode 100644 index 8987bda9e..000000000 --- a/mode/examples/Basics/Objects/CompositeObjects/CompositeObjects.pde +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Composite Objects - * - * An object can include several other objects. Creating such composite objects - * is a good way to use the principles of modularity and build higher levels of - * abstraction within a program. - */ - -EggRing er1, er2; - - -void setup() { - size(200, 200); - smooth(); - er1 = new EggRing(66, 132, 0.1, 66); - er2 = new EggRing(132, 180, 0.05, 132); -} - - -void draw() { - background(0); - er1.transmit(); - er2.transmit(); -} diff --git a/mode/examples/Basics/Objects/CompositeObjects/Egg.pde b/mode/examples/Basics/Objects/CompositeObjects/Egg.pde deleted file mode 100644 index e6638aa79..000000000 --- a/mode/examples/Basics/Objects/CompositeObjects/Egg.pde +++ /dev/null @@ -1,36 +0,0 @@ -class Egg { - float x, y; // X-coordinate, y-coordinate - float tilt; // Left and right angle offset - float angle; // Used to define the tilt - float scalar; // Height of the egg - - // Constructor - Egg(int xpos, int ypos, float t, float s) { - x = xpos; - y = ypos; - tilt = t; - scalar = s / 100.0; - } - - void wobble() { - tilt = cos(angle) / 8; - angle += 0.1; - } - - void display() { - noStroke(); - fill(255); - pushMatrix(); - translate(x, y); - rotate(tilt); - scale(scalar); - beginShape(); - vertex(0, -100); - bezierVertex(25, -100, 40, -65, 40, -40); - bezierVertex(40, -15, 25, 0, 0, 0); - bezierVertex(-25, 0, -40, -15, -40, -40); - bezierVertex(-40, -65, -25, -100, 0, -100); - endShape(); - popMatrix(); - } -} \ No newline at end of file diff --git a/mode/examples/Basics/Objects/CompositeObjects/EggRing.pde b/mode/examples/Basics/Objects/CompositeObjects/EggRing.pde deleted file mode 100644 index 2648603f9..000000000 --- a/mode/examples/Basics/Objects/CompositeObjects/EggRing.pde +++ /dev/null @@ -1,19 +0,0 @@ -class EggRing { - Egg ovoid; - Ring circle = new Ring(); - - EggRing(int x, int y, float t, float sp) { - ovoid = new Egg(x, y, t, sp); - circle.start(x, y - sp/2); - } - - void transmit() { - ovoid.wobble(); - ovoid.display(); - circle.grow(); - circle.display(); - if (circle.on == false) { - circle.on = true; - } - } -} diff --git a/mode/examples/Basics/Objects/CompositeObjects/Ring.pde b/mode/examples/Basics/Objects/CompositeObjects/Ring.pde deleted file mode 100644 index 3baf5623d..000000000 --- a/mode/examples/Basics/Objects/CompositeObjects/Ring.pde +++ /dev/null @@ -1,27 +0,0 @@ -class Ring { - float x, y; // X-coordinate, y-coordinate - float diameter; // Diameter of the ring - boolean on = false; // Turns the display on and off - void start(float xpos, float ypos) { - x = xpos; - y = ypos; - on = true; - diameter = 1; - } - void grow() { - if (on == true) { - diameter += 0.5; - if (diameter > width*2) { - diameter = 0.0; - } - } - } - void display() { - if (on == true) { - noFill(); - strokeWeight(4); - stroke(155, 153); - ellipse(x, y, diameter, diameter); - } - } -} diff --git a/mode/examples/Basics/Objects/Inheritance/Inheritance.pde b/mode/examples/Basics/Objects/Inheritance/Inheritance.pde deleted file mode 100644 index 6c4af0bc8..000000000 --- a/mode/examples/Basics/Objects/Inheritance/Inheritance.pde +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Inheritance - * - * A class can be defined using another class as a foundation. In object-oriented - * programming terminology, one class can inherit fi elds and methods from another. - * An object that inherits from another is called a subclass, and the object it - * inherits from is called a superclass. A subclass extends the superclass. - */ - -SpinSpots spots; -SpinArm arm; - -void setup() -{ - size(200, 200); - smooth(); - arm = new SpinArm(width/2, height/2, 0.01); - spots = new SpinSpots(width/2, height/2, -0.02, 33.0); -} - -void draw() -{ - background(204); - arm.update(); - arm.display(); - spots.update(); - spots.display(); -} - -class Spin -{ - float x, y, speed; - float angle = 0.0; - Spin(float xpos, float ypos, float s) { - x = xpos; - y = ypos; - speed = s; - } - void update() { - angle += speed; - } -} - -class SpinArm extends Spin -{ - SpinArm(float x, float y, float s) { - super(x, y, s); - } - void display() { - strokeWeight(1); - stroke(0); - pushMatrix(); - translate(x, y); - angle += speed; - rotate(angle); - line(0, 0, 66, 0); - popMatrix(); - } -} - -class SpinSpots extends Spin -{ - float dim; - SpinSpots(float x, float y, float s, float d) { - super(x, y, s); - dim = d; - } - void display() { - noStroke(); - pushMatrix(); - translate(x, y); - angle += speed; - rotate(angle); - ellipse(-dim/2, 0, dim, dim); - ellipse(dim/2, 0, dim, dim); - popMatrix(); - } -} diff --git a/mode/examples/Basics/Objects/MultipleConstructors/MultipleConstructors.pde b/mode/examples/Basics/Objects/MultipleConstructors/MultipleConstructors.pde deleted file mode 100644 index fd57edbfd..000000000 --- a/mode/examples/Basics/Objects/MultipleConstructors/MultipleConstructors.pde +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Multiple constructors - * - * A class can have multiple constructors that assign the fields in different ways. - * Sometimes it's beneficial to specify every aspect of an object's data by assigning - * parameters to the fields, but other times it might be appropriate to define only - * one or a few. - */ - -Spot sp1, sp2; -void setup() -{ - size(200, 200); - background(204); - smooth(); - noLoop(); - // Run the constructor without parameters - sp1 = new Spot(); - // Run the constructor with three parameters - sp2 = new Spot(122, 100, 40); -} - -void draw() { - sp1.display(); - sp2.display(); -} - -class Spot { - float x, y, radius; - // First version of the Spot constructor; - // the fields are assigned default values - Spot() { - x = 66; - y = 100; - radius = 16; - } - // Second version of the Spot constructor; - // the fields are assigned with parameters - Spot(float xpos, float ypos, float r) { - x = xpos; - y = ypos; - radius = r; - } - void display() { - ellipse(x, y, radius*2, radius*2); - } -} diff --git a/mode/examples/Basics/Objects/Neighborhood/Neighborhood.pde b/mode/examples/Basics/Objects/Neighborhood/Neighborhood.pde deleted file mode 100644 index f70893d25..000000000 --- a/mode/examples/Basics/Objects/Neighborhood/Neighborhood.pde +++ /dev/null @@ -1,303 +0,0 @@ -/** - * Neighborhood (OOP Example) - * By Ira Greenberg - * - * Draw a neighborhood of houses using - * Door, Window, Roof and House classes. - * Good example of class composition, with component - * Door, Window, Roof class references encapsulated - * within House class. This arrangement allows - * House class to handle placement and sizing of - * its components, while still allowing user - * customization of the individual components. - */ - -void setup(){ - size(200, 200); - background(190); - smooth(); - // Ground plane - int groundHeight = 10; - fill(0); - rect(0, height-groundHeight, width, groundHeight); - fill(255); - - // Center the houses - translate(12, 0); - - // Houses - Door door1 = new Door(20, 40); - Window window1 = new Window(50, 62, false, Window.DOUBLE); - Roof roof1 = new Roof(Roof.DOME); - House house1 = new House(75, 75, door1, window1, roof1, House.MIDDLE_DOOR); - house1.drawHouse(0, height-groundHeight-house1.h, true); - - Door door2 = new Door(20, 40); - Window window2 = new Window(50, 62, true, Window.QUAD); - Roof roof2 = new Roof(Roof.GAMBREL); - House house2 = new House(100, 60, door2, window2, roof2, House.LEFT_DOOR); - house2.drawHouse(house1.x + house1.w, height-groundHeight-house2.h, true); -} - -class Door{ - //door properties - int x; - int y; - int w; - int h; - - // for knob - int knobLoc = 1; - //constants - final static int RT = 0; - final static int LFT = 1; - - // constructor - Door(int w, int h){ - this.w = w; - this.h = h; - } - - // draw the door - void drawDoor(int x, int y) { - rect(x, y, w, h); - int knobsize = w/10; - if (knobLoc == 0){ - //right side - ellipse(x+w-knobsize, y+h/2, knobsize, knobsize); - } - else { - //left side - ellipse(x+knobsize, y+h/2, knobsize, knobsize); - } - } - - // set knob position - void setKnob(int knobLoc){ - this. knobLoc = knobLoc; - } -} - -class Window{ - //window properties - int x; - int y; - int w; - int h; - - // customized features - boolean hasSash = false; - - // single, double, quad pane - int style = 0; - //constants - final static int SINGLE = 0; - final static int DOUBLE = 1; - final static int QUAD = 2; - - // constructor 1 - Window(int w, int h){ - this.w = w; - this.h = h; - } - // constructor 2 - Window(int w, int h, int style){ - this.w = w; - this.h = h; - this.style = style; - } - // constructor 3 - Window(int w, int h, boolean hasSash, int style){ - this.w = w; - this.h = h; - this.hasSash = hasSash; - this.style = style; - } - - // draw the window - void drawWindow(int x, int y) { - //local variables - int margin = 0; - int winHt = 0; - int winWdth = 0; - - if (hasSash){ - margin = w/15; - } - - switch(style){ - case 0: - //outer window (sash) - rect(x, y, w, h); - //inner window - rect(x+margin, y+margin, w-margin*2, h-margin*2); - break; - case 1: - winHt = (h-margin*3)/2; - //outer window (sash) - rect(x, y, w, h); - //inner window (top) - rect(x+margin, y+margin, w-margin*2, winHt); - //inner windows (bottom) - rect(x+margin, y+winHt+margin*2, w-margin*2, winHt); - break; - case 2: - winWdth = (w-margin*3)/2; - winHt = (h-margin*3)/2; - //outer window (sash) - rect(x, y, w, h); - //inner window (top-left) - rect(x+margin, y+margin, winWdth, winHt); - //inner window (top-right) - rect(x+winWdth+margin*2, y+margin, winWdth, winHt); - //inner windows (bottom-left) - rect(x+margin, y+winHt+margin*2, winWdth, winHt); - //inner windows (bottom-right) - rect(x+winWdth+margin*2, y+winHt+margin*2, winWdth, winHt); - break; - } - } - - // set window style (number of panes) - void setStyle(int style){ - this.style = style; - } -} - -class Roof{ - //roof properties - int x; - int y; - int w; - int h; - - // roof style - int style = 0; - //constants - final static int CATHEDRAL = 0; - final static int GAMBREL = 1; - final static int DOME = 2; - - // default constructor - Roof(){ - } - - // constructor 2 - Roof(int style){ - this.style = style; - } - - // draw the roof - void drawRoof(int x, int y, int w, int h) { - switch(style){ - case 0: - beginShape(); - vertex(x, y); - vertex(x+w/2, y-h/3); - vertex(x+w, y); - endShape(CLOSE); - break; - case 1: - beginShape(); - vertex(x, y); - vertex(x+w/7, y-h/4); - vertex(x+w/2, y-h/2); - vertex(x+(w-w/7), y-h/4); - vertex(x+w, y); - endShape(CLOSE); - break; - case 2: - ellipseMode(CORNER); - arc(x, y-h/2, w, h, PI, TWO_PI); - line(x, y, x+w, y); - break; - } - - } - - // set roof style - void setStyle(int style){ - this.style = style; - } -} - -class House{ - //house properties - int x; - int y; - int w; - int h; - - //component reference variables - Door door; - Window window; - Roof roof; - - //optional autosize variable - boolean AutoSizeComponents = false; - - //door placement - int doorLoc = 0; - //constants - final static int MIDDLE_DOOR = 0; - final static int LEFT_DOOR = 1; - final static int RIGHT_DOOR = 2; - - //constructor - House(int w, int h, Door door, Window window, Roof roof, int doorLoc) { - this.w = w; - this.h = h; - this.door = door; - this.window = window; - this.roof = roof; - this.doorLoc = doorLoc; - } - - void drawHouse(int x, int y, boolean AutoSizeComponents) { - this.x = x; - this.y =y; - this.AutoSizeComponents = AutoSizeComponents; - - //automatically sizes doors and windows - if(AutoSizeComponents){ - //autosize door - door.h = h/4; - door.w = door.h/2; - - //autosize windows - window.h = h/3; - window.w = window.h/2; - - } - // draw bldg block - rect(x, y, w, h); - - // draw door - switch(doorLoc){ - case 0: - door.drawDoor(x+w/2-door.w/2, y+h-door.h); - break; - case 1: - door.drawDoor(x+w/8, y+h-door.h); - break; - case 2: - door.drawDoor(x+w-w/8-door.w, y+h-door.h); - break; - } - - // draw windows - int windowMargin = (w-window.w*2)/3; - window.drawWindow(x+windowMargin, y+h/6); - window.drawWindow(x+windowMargin*2+window.w, y+h/6); - - // draw roof - roof.drawRoof(x, y, w, h); - } - - // catch drawHouse method without boolean argument - void drawHouse(int x, int y){ - // recall with required 3rd argument - drawHouse(x, y, false); - } -} - diff --git a/mode/examples/Basics/Objects/Objects/Objects.pde b/mode/examples/Basics/Objects/Objects/Objects.pde deleted file mode 100644 index 80a09a3d6..000000000 --- a/mode/examples/Basics/Objects/Objects/Objects.pde +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Objects - * by hbarragan. - * - * Move the cursor across the image to change the speed and positions - * of the geometry. The class MRect defines a group of lines. - */ - -MRect r1, r2, r3, r4; - -void setup() -{ - size(200, 200); - fill(255, 204); - noStroke(); - r1 = new MRect(1, 134.0, 0.532, 0.083*height, 10.0, 60.0); - r2 = new MRect(2, 44.0, 0.166, 0.332*height, 5.0, 50.0); - r3 = new MRect(2, 58.0, 0.332, 0.4482*height, 10.0, 35.0); - r4 = new MRect(1, 120.0, 0.0498, 0.913*height, 15.0, 60.0); -} - -void draw() -{ - background(0); - - r1.display(); - r2.display(); - r3.display(); - r4.display(); - - r1.move(mouseX-(width/2), mouseY+(height*0.1), 30); - r2.move((mouseX+(width*0.05))%width, mouseY+(height*0.025), 20); - r3.move(mouseX/4, mouseY-(height*0.025), 40); - r4.move(mouseX-(width/2), (height-mouseY), 50); -} - -class MRect -{ - int w; // single bar width - float xpos; // rect xposition - float h; // rect height - float ypos ; // rect yposition - float d; // single bar distance - float t; // number of bars - - MRect(int iw, float ixp, float ih, float iyp, float id, float it) { - w = iw; - xpos = ixp; - h = ih; - ypos = iyp; - d = id; - t = it; - } - - void move (float posX, float posY, float damping) { - float dif = ypos - posY; - if (abs(dif) > 1) { - ypos -= dif/damping; - } - dif = xpos - posX; - if (abs(dif) > 1) { - xpos -= dif/damping; - } - } - - void display() { - for (int i=0; i - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mode/examples/Basics/Shape/GetChild/GetChild.pde b/mode/examples/Basics/Shape/GetChild/GetChild.pde deleted file mode 100644 index 0b9b9d393..000000000 --- a/mode/examples/Basics/Shape/GetChild/GetChild.pde +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Get Child. - * - * SVG files can be made of many individual shapes. - * Each of these shapes (called a "child") has its own name - * that can be used to extract it from the "parent" file. - * This example loads a map of the United States and creates - * two new PShape objects by extracting the data from two states. - */ - -PShape usa; -PShape michigan; -PShape ohio; - -void setup() { - size(640, 360); - usa = loadShape("usa-wikipedia.svg"); - michigan = usa.getChild("MI"); - ohio = usa.getChild("OH"); - smooth(); // Improves the drawing quality of the SVG - noLoop(); -} - -void draw() { - background(255); - - // Draw the full map - shape(usa, -600, -180); - - // Disable the colors found in the SVG file - michigan.disableStyle(); - // Set our own coloring - fill(0, 51, 102); - noStroke(); - // Draw a single state - shape(michigan, -600, -180); // Go Blue! - - // Disable the colors found in the SVG file - ohio.disableStyle(); - // Set our own coloring - fill(153, 0, 0); - noStroke(); - // Draw a single state - shape(ohio, -600, -180); // Boo Buckeyes! -} diff --git a/mode/examples/Basics/Shape/GetChild/data/usa-wikipedia.svg b/mode/examples/Basics/Shape/GetChild/data/usa-wikipedia.svg deleted file mode 100644 index 247ba7383..000000000 --- a/mode/examples/Basics/Shape/GetChild/data/usa-wikipedia.svg +++ /dev/null @@ -1,452 +0,0 @@ - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mode/examples/Basics/Shape/LoadDisplayOBJ/LoadDisplayOBJ.pde b/mode/examples/Basics/Shape/LoadDisplayOBJ/LoadDisplayOBJ.pde deleted file mode 100644 index 154eeb4f0..000000000 --- a/mode/examples/Basics/Shape/LoadDisplayOBJ/LoadDisplayOBJ.pde +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Load and Display an OBJ Shape. - * - * The loadShape() command is used to read simple SVG (Scalable Vector Graphics) - * files and OBJ (Object) files into a Processing sketch. This example loads an - * OBJ file of a rocket and displays it to the screen. - */ - - -PShape rocket; - -float ry; - -public void setup() { - size(640, 360, P3D); - orientation(LANDSCAPE); - - rocket = loadShape("rocket.obj"); -} - -public void draw() { - background(0); - lights(); - - translate(width/2, height/2 + 100, -200); - rotateZ(PI); - rotateY(ry); - shape(rocket); - - ry += 0.02; -} diff --git a/mode/examples/Basics/Shape/LoadDisplayOBJ/data/rocket.mtl b/mode/examples/Basics/Shape/LoadDisplayOBJ/data/rocket.mtl deleted file mode 100644 index fbce8d026..000000000 --- a/mode/examples/Basics/Shape/LoadDisplayOBJ/data/rocket.mtl +++ /dev/null @@ -1,8 +0,0 @@ -newmtl Default -illum 2 -Ka 0.698039 0.698039 0.698039 -Kd 0.698039 0.698039 0.698039 -Ks 0.710000 0.710000 0.710000 -Ns 76.109253 -map_Kd rocket.png - diff --git a/mode/examples/Basics/Shape/LoadDisplayOBJ/data/rocket.obj b/mode/examples/Basics/Shape/LoadDisplayOBJ/data/rocket.obj deleted file mode 100644 index 1a3b68915..000000000 --- a/mode/examples/Basics/Shape/LoadDisplayOBJ/data/rocket.obj +++ /dev/null @@ -1,1688 +0,0 @@ -mtllib rocket.mtl -g Rocket -v 0.088187 27.748848 0.016643 -v 25.227547 19.502979 -25.122717 -v 35.640614 19.502979 0.016642 -v 0.088185 19.502979 -35.535782 -v 0.088187 27.748848 0.016643 -v -25.051176 19.502979 -25.122717 -v -35.464237 19.502979 0.016645 -v -25.051170 19.502979 25.156006 -v 0.088191 19.502979 35.569065 -v 0.088187 27.748848 0.016643 -v 25.227552 19.502979 25.156000 -v 0.088187 27.748848 0.016643 -v 35.640614 19.502979 0.016642 -v 35.199703 86.845764 -35.094872 -v 49.743370 86.845764 0.016642 -v 25.227547 19.502979 -25.122717 -v 0.088184 86.845764 -49.638538 -v 0.088185 19.502979 -35.535782 -v -35.023331 86.845764 -35.094872 -v 0.088185 19.502979 -35.535782 -v -25.051176 19.502979 -25.122717 -v -49.566994 86.845764 0.016646 -v -35.023331 86.845764 -35.094872 -v -35.464237 19.502979 0.016645 -v -35.023323 86.845764 35.128162 -v -49.566994 86.845764 0.016646 -v -25.051170 19.502979 25.156006 -v 0.088193 86.845764 49.671825 -v -35.023323 86.845764 35.128162 -v -25.051170 19.502979 25.156006 -v 0.088191 19.502979 35.569065 -v 0.088191 19.502979 35.569065 -v 35.199711 86.845764 35.128155 -v 0.088193 86.845764 49.671825 -v 25.227552 19.502979 25.156000 -v 25.227552 19.502979 25.156000 -v 35.640614 19.502979 0.016642 -v 35.199703 173.055786 -35.094872 -v 49.743370 173.055786 0.016643 -v 35.199703 86.845764 -35.094872 -v 0.088184 173.055786 -49.638535 -v 35.199703 86.845764 -35.094872 -v -35.023331 173.055786 -35.094872 -v -35.023331 86.845764 -35.094872 -v -49.566994 173.055786 0.016647 -v -35.023331 173.055786 -35.094872 -v -49.566994 86.845764 0.016646 -v -35.023323 173.055786 35.128166 -v -49.566994 86.845764 0.016646 -v 0.088193 173.055786 49.671829 -v 0.088193 86.845764 49.671825 -v 35.199711 173.055786 35.128159 -v 0.088193 173.055786 49.671829 -v 35.199711 86.845764 35.128155 -v 35.199711 173.055786 35.128159 -v 49.743370 173.055786 0.016643 -v 27.145910 222.581848 -27.041082 -v 38.353592 222.581848 0.016642 -v 49.743370 173.055786 0.016643 -v 35.199703 173.055786 -35.094872 -v 0.088185 222.581848 -38.248760 -v 35.199703 173.055786 -35.094872 -v 0.088184 173.055786 -49.638535 -v 0.088184 173.055786 -49.638535 -v -26.969542 222.581848 -27.041082 -v -35.023331 173.055786 -35.094872 -v -38.177216 222.581848 0.016646 -v -26.969542 222.581848 -27.041082 -v -49.566994 173.055786 0.016647 -v -26.969536 222.581848 27.074369 -v -38.177216 222.581848 0.016646 -v -35.023323 173.055786 35.128166 -v 0.088192 222.581848 38.282043 -v -26.969536 222.581848 27.074369 -v -35.023323 173.055786 35.128166 -v 0.088193 173.055786 49.671829 -v 27.145916 222.581848 27.074364 -v 0.088192 222.581848 38.282043 -v 0.088193 173.055786 49.671829 -v 35.199711 173.055786 35.128159 -v 35.199711 173.055786 35.128159 -v 0.088187 317.654602 0.016646 -v 0.088185 222.581848 -38.248760 -v 0.088187 317.654602 0.016646 -v 0.088185 222.581848 -38.248760 -v 0.088187 317.654602 0.016646 -v -38.177216 222.581848 0.016646 -v 0.088187 317.654602 0.016646 -v -26.969536 222.581848 27.074369 -v 0.088187 317.654602 0.016646 -v 27.145916 222.581848 27.074364 -v 38.353592 222.581848 0.016642 -vt 0.365478 0.904922 -vt 0.427267 0.972178 -vt 0.452861 0.904922 -vt 0.365478 1.000036 -vt 0.365478 0.904922 -vt 0.303689 0.972178 -vt 0.278095 0.904922 -vt 0.303689 0.837667 -vt 0.365478 0.809809 -vt 0.365478 0.904922 -vt 0.427267 0.837667 -vt 0.365478 0.904922 -vt 0.183561 0.319288 -vt 0.274884 0.473113 -vt 0.183561 0.473113 -vt 0.274884 0.319288 -vt 0.366208 0.473113 -vt 0.366208 0.319288 -vt 0.457532 0.473113 -vt 0.366208 0.319288 -vt 0.457532 0.319288 -vt 0.548855 0.473113 -vt 0.457532 0.473113 -vt 0.548855 0.319288 -vt 0.640179 0.473113 -vt 0.548855 0.473113 -vt 0.640179 0.319288 -vt 0.731503 0.473113 -vt 0.640179 0.473113 -vt 0.640179 0.319288 -vt 0.731503 0.319288 -vt 0.000913 0.319288 -vt 0.092237 0.473113 -vt 0.000913 0.473113 -vt 0.092237 0.319288 -vt 0.092237 0.319288 -vt 0.183561 0.319288 -vt 0.274884 0.670034 -vt 0.183561 0.670034 -vt 0.274884 0.473113 -vt 0.366208 0.670034 -vt 0.274884 0.473113 -vt 0.457532 0.670034 -vt 0.457532 0.473113 -vt 0.548855 0.670034 -vt 0.457532 0.670034 -vt 0.548855 0.473113 -vt 0.640179 0.670034 -vt 0.548855 0.473113 -vt 0.731503 0.670034 -vt 0.731503 0.473113 -vt 0.092237 0.670034 -vt 0.000913 0.670034 -vt 0.092237 0.473113 -vt 0.092237 0.670034 -vt 0.183561 0.670034 -vt 0.274884 0.783161 -vt 0.183561 0.783161 -vt 0.183561 0.670034 -vt 0.274884 0.670034 -vt 0.366208 0.783161 -vt 0.274884 0.670034 -vt 0.366208 0.670034 -vt 0.366208 0.670034 -vt 0.457532 0.783161 -vt 0.457532 0.670034 -vt 0.548855 0.783161 -vt 0.457532 0.783161 -vt 0.548855 0.670034 -vt 0.640179 0.783161 -vt 0.548855 0.783161 -vt 0.640179 0.670034 -vt 0.731503 0.783161 -vt 0.640179 0.783161 -vt 0.640179 0.670034 -vt 0.731503 0.670034 -vt 0.092237 0.783161 -vt 0.000913 0.783161 -vt 0.000913 0.670034 -vt 0.092237 0.670034 -vt 0.092237 0.670034 -vt 0.000913 1.000327 -vt 0.366208 0.783161 -vt 0.731503 1.000327 -vt 0.366208 0.783161 -vt 0.731503 1.000327 -vt 0.548855 0.783161 -vt 0.731503 1.000327 -vt 0.640179 0.783161 -vt 0.000913 1.000327 -vt 0.092237 0.783161 -vt 0.183561 0.783161 -usemtl Default -f 1/1 2/2 3/3 -f 1/1 4/4 2/2 -f 5/5 6/6 4/4 -f 5/5 7/7 6/6 -f 5/5 8/8 7/7 -f 5/5 9/9 8/8 -f 10/10 11/11 9/9 -f 12/12 3/3 11/11 -f 13/13 14/14 15/15 -f 13/13 16/16 14/14 -f 16/16 17/17 14/14 -f 16/16 18/18 17/17 -f 18/18 19/19 17/17 -f 20/20 21/21 19/19 -f 21/21 22/22 23/23 -f 21/21 24/24 22/22 -f 24/24 25/25 26/26 -f 24/24 27/27 25/25 -f 27/27 28/28 29/29 -f 30/30 31/31 28/28 -f 32/32 33/33 34/34 -f 32/32 35/35 33/33 -f 35/35 15/15 33/33 -f 36/36 37/37 15/15 -f 15/15 38/38 39/39 -f 15/15 14/14 38/38 -f 40/40 41/41 38/38 -f 42/42 17/17 41/41 -f 17/17 43/43 41/41 -f 17/17 44/44 43/43 -f 19/19 45/45 46/46 -f 19/19 22/22 45/45 -f 47/47 48/48 45/45 -f 49/49 25/25 48/48 -f 29/29 50/50 48/48 -f 29/29 51/51 50/50 -f 34/34 52/52 53/53 -f 34/34 54/54 52/52 -f 33/33 39/39 55/55 -f 33/33 15/15 39/39 -f 56/56 57/57 58/58 -f 59/59 38/38 57/57 -f 60/60 61/61 57/57 -f 62/62 63/63 61/61 -f 64/64 65/65 61/61 -f 64/64 46/46 65/65 -f 66/66 67/67 68/68 -f 43/43 45/45 67/67 -f 69/69 70/70 71/71 -f 69/69 48/48 70/70 -f 72/72 73/73 74/74 -f 75/75 76/76 73/73 -f 53/53 77/77 78/78 -f 79/79 80/80 77/77 -f 81/81 58/58 77/77 -f 55/55 59/59 58/58 -f 82/82 58/58 57/57 -f 82/82 57/57 83/83 -f 84/84 85/85 68/68 -f 84/84 65/65 71/71 -f 86/86 87/87 74/74 -f 88/88 89/89 73/73 -f 82/82 78/78 77/77 -f 90/90 91/91 92/92 -g wing01 -v -72.964706 -60.615013 2.752965 -v -80.651077 -69.945724 2.752970 -v -79.178032 -68.157547 0.201571 -v -72.964706 -60.615013 2.752965 -v -72.964706 -60.615021 -2.628587 -v -58.352703 -20.619514 -2.628605 -v -58.352703 -20.619514 -2.628605 -v -58.352703 -20.619511 2.752947 -v -72.964706 -60.615013 2.752965 -v -58.352703 -20.619511 2.752947 -v -58.352703 -20.619514 -2.628605 -v -46.947498 1.234928 -2.628614 -v -46.947498 1.234928 -2.628614 -v -46.947498 1.234928 2.752937 -v -58.352703 -20.619511 2.752947 -v -41.276043 7.132179 0.062164 -v -46.947498 1.234928 -2.628614 -v -40.422783 8.019409 -2.628617 -v -81.873581 11.210991 0.201533 -v -49.119144 52.636772 -1.776468 -v -48.766163 52.964798 -2.628637 -v -48.766163 52.964798 -2.628637 -v -82.419724 10.123146 -2.628616 -v -81.873581 11.210991 0.201533 -v -82.482941 10.347294 2.752934 -v -80.651093 4.123146 2.752937 -v -58.352703 -20.619511 2.752947 -v -58.352703 -20.619511 2.752947 -v -46.947498 1.234928 2.752937 -v -82.482941 10.347294 2.752934 -v -79.178032 -68.157547 0.201571 -v -80.812019 -70.141090 -2.628582 -v -72.964706 -60.615021 -2.628587 -v -72.964706 -60.615021 -2.628587 -v -72.964706 -60.615013 2.752965 -v -79.178032 -68.157547 0.201571 -v -80.651077 -69.945724 2.752970 -v -72.964706 -60.615013 2.752965 -v -58.352703 -20.619511 2.752947 -v -58.352703 -20.619511 2.752947 -v -80.651093 4.123146 2.752937 -v -80.651077 -69.945724 2.752970 -v -46.947498 1.234928 2.752937 -v -40.422787 8.019402 2.752935 -v -48.766171 36.348991 2.752924 -v -48.766171 36.348991 2.752924 -v -82.482941 10.347294 2.752934 -v -46.947498 1.234928 2.752937 -v -58.352703 -20.619514 -2.628605 -v -72.964706 -60.615021 -2.628587 -v -80.812019 -70.141090 -2.628582 -v -80.812019 -70.141090 -2.628582 -v -80.812027 4.123146 -2.628614 -v -58.352703 -20.619514 -2.628605 -v -82.419724 10.123146 -2.628616 -v -48.766163 52.964798 -2.628637 -v -48.766171 36.348991 -2.628628 -v -58.352703 -20.619514 -2.628605 -v -80.812027 4.123146 -2.628614 -v -82.419724 10.123146 -2.628616 -v -82.419724 10.123146 -2.628616 -v -46.947498 1.234928 -2.628614 -v -58.352703 -20.619514 -2.628605 -v -82.482941 10.347294 2.752934 -v -48.765190 53.047668 2.755279 -v -49.880726 51.661064 0.062147 -v -49.880726 51.661064 0.062147 -v -81.873581 11.210991 0.201533 -v -82.482941 10.347294 2.752934 -v -41.276043 7.132179 0.062164 -v -40.422787 8.019402 2.752935 -v -46.947498 1.234928 2.752937 -v -46.947498 1.234928 2.752937 -v -46.947498 1.234928 -2.628614 -v -41.276043 7.132179 0.062164 -v -48.766171 36.348991 2.752924 -v -48.765190 53.047668 2.755279 -v -82.482941 10.347294 2.752934 -v -40.422783 8.019409 -2.628617 -v -46.947498 1.234928 -2.628614 -v -82.419724 10.123146 -2.628616 -v -82.419724 10.123146 -2.628616 -v -48.766171 36.348991 -2.628628 -v -40.422783 8.019409 -2.628617 -v -49.880726 51.661064 0.062147 -v -49.119144 52.636772 -1.776468 -v -81.873581 11.210991 0.201533 -vt 0.653246 0.106736 -vt 0.645259 0.106736 -vt 0.646789 0.060132 -vt 0.653246 0.106736 -vt 0.653246 0.008436 -vt 0.687484 0.008435 -vt 0.687484 0.008435 -vt 0.687484 0.106736 -vt 0.653246 0.106736 -vt 0.687484 0.106736 -vt 0.687484 0.008435 -vt 0.706193 0.008435 -vt 0.706193 0.008435 -vt 0.706193 0.106735 -vt 0.687484 0.106736 -vt 0.711241 0.057585 -vt 0.706193 0.008435 -vt 0.712001 0.008435 -vt 0.487940 0.249578 -vt 0.452478 0.213447 -vt 0.452197 0.197881 -vt 0.452197 0.197881 -vt 0.488872 0.197882 -vt 0.487940 0.249578 -vt 0.992226 0.113639 -vt 0.982006 0.129463 -vt 0.857606 0.192369 -vt 0.857606 0.192369 -vt 0.793978 0.136806 -vt 0.992226 0.113639 -vt 0.646789 0.060132 -vt 0.645091 0.008436 -vt 0.653246 0.008436 -vt 0.653246 0.008436 -vt 0.653246 0.106736 -vt 0.646789 0.060132 -vt 0.982006 0.317777 -vt 0.939125 0.294054 -vt 0.857606 0.192369 -vt 0.857606 0.192369 -vt 0.982006 0.129463 -vt 0.982006 0.317777 -vt 0.793978 0.136806 -vt 0.757577 0.119557 -vt 0.804124 0.047532 -vt 0.804124 0.047532 -vt 0.992226 0.113639 -vt 0.793978 0.136806 -vt 0.481912 0.158658 -vt 0.390770 0.067710 -vt 0.369062 0.018867 -vt 0.369062 0.018867 -vt 0.538296 0.018867 -vt 0.481912 0.158658 -vt 0.551969 0.008861 -vt 0.649597 0.218327 -vt 0.611733 0.218327 -vt 0.481912 0.158658 -vt 0.538296 0.018867 -vt 0.551969 0.008861 -vt 0.551969 0.008861 -vt 0.531714 0.229646 -vt 0.481912 0.158658 -vt 0.488680 0.296182 -vt 0.452126 0.296225 -vt 0.453313 0.247032 -vt 0.453313 0.247032 -vt 0.487940 0.249578 -vt 0.488680 0.296182 -vt 0.711241 0.057585 -vt 0.712001 0.106735 -vt 0.706193 0.106735 -vt 0.706193 0.106735 -vt 0.706193 0.008435 -vt 0.711241 0.057585 -vt 0.804124 0.047532 -vt 0.804119 0.005077 -vt 0.992226 0.113639 -vt 0.547175 0.270257 -vt 0.531714 0.229646 -vt 0.551969 0.008861 -vt 0.551969 0.008861 -vt 0.611733 0.218327 -vt 0.547175 0.270257 -vt 0.453313 0.247032 -vt 0.452478 0.213447 -vt 0.487940 0.249578 -usemtl Default -f 93/93 94/94 95/95 -f 96/96 97/97 98/98 -f 99/99 100/100 101/101 -f 102/102 103/103 104/104 -f 105/105 106/106 107/107 -f 108/108 109/109 110/110 -f 111/111 112/112 113/113 -f 114/114 115/115 116/116 -f 117/117 118/118 119/119 -f 120/120 121/121 122/122 -f 123/123 124/124 125/125 -f 126/126 127/127 128/128 -f 129/129 130/130 131/131 -f 132/132 133/133 134/134 -f 135/135 136/136 137/137 -f 138/138 139/139 140/140 -f 141/141 142/142 143/143 -f 144/144 145/145 146/146 -f 147/147 148/148 149/149 -f 150/150 151/151 152/152 -f 153/153 154/154 155/155 -f 156/156 157/157 158/158 -f 159/159 160/160 161/161 -f 162/162 163/163 164/164 -f 165/165 166/166 167/167 -f 168/168 169/169 170/170 -f 171/171 172/172 173/173 -f 174/174 175/175 176/176 -f 177/177 178/178 179/179 -g reactor01 -v -92.410393 -77.997627 0.213196 -v -86.097389 -76.306053 0.213195 -v -89.253891 -76.306053 5.680415 -v -92.410393 -77.997627 0.213196 -v -89.253891 -76.306053 5.680415 -v -95.566895 -76.306053 5.680414 -v -98.723396 -76.306053 0.213195 -v -92.410393 -77.997627 0.213196 -v -95.566895 -76.306068 -5.254023 -v -89.253891 -76.306068 -5.254023 -v -86.097389 -76.306053 0.213195 -v -81.475952 -71.684624 0.213195 -v -86.943176 -71.684624 9.682695 -v -86.943176 -71.684624 9.682695 -v -97.877609 -71.684624 9.682695 -v -95.566895 -76.306053 5.680414 -v -95.566895 -76.306053 5.680414 -v -103.344833 -71.684624 0.213194 -v -95.566895 -76.306053 5.680414 -v -98.723396 -76.306053 0.213195 -v -103.344833 -71.684624 0.213194 -v -97.877609 -71.684624 -9.256306 -v -86.943176 -71.684624 -9.256305 -v -95.566895 -76.306068 -5.254023 -v -86.943176 -71.684624 -9.256305 -v -89.253891 -76.306068 -5.254023 -v -81.475952 -71.684624 0.213195 -v -86.097389 -76.306053 0.213195 -v -81.475952 -71.684624 0.213195 -v -79.784393 -65.371635 0.213195 -v -86.097397 -65.371620 11.147633 -v -81.475952 -71.684624 0.213195 -v -86.943176 -71.684624 9.682695 -v -86.097397 -65.371620 11.147633 -v -98.723396 -65.371620 11.147632 -v -97.877609 -71.684624 9.682695 -v -105.036392 -65.371635 0.213194 -v -103.344833 -71.684624 0.213194 -v -105.036392 -65.371635 0.213194 -v -98.723389 -65.371635 -10.721243 -v -97.877609 -71.684624 -9.256306 -v -86.097389 -65.371635 -10.721241 -v -97.877609 -71.684624 -9.256306 -v -81.475952 -71.684624 0.213195 -v -79.784393 6.376373 0.213193 -v -86.097397 6.376373 11.147631 -v -79.784393 -65.371635 0.213195 -v -86.097397 6.376373 11.147631 -v -98.723396 6.376373 11.147630 -v -98.723396 -65.371620 11.147632 -v -105.036392 6.376373 0.213192 -v -105.036392 -65.371635 0.213194 -v -105.036392 -65.371635 0.213194 -v -98.723389 6.376373 -10.721245 -v -98.723389 -65.371635 -10.721243 -v -86.097389 6.376373 -10.721243 -v -86.097389 -65.371635 -10.721241 -v -86.097389 6.376373 -10.721243 -v -79.784393 -65.371635 0.213195 -v -81.475952 12.689369 0.213193 -v -86.943176 12.689369 9.682693 -v -86.943176 12.689369 9.682693 -v -97.877609 12.689369 9.682693 -v -86.097397 6.376373 11.147631 -v -98.723396 6.376373 11.147630 -v -103.344833 12.689369 0.213192 -v -105.036392 6.376373 0.213192 -v -103.344833 12.689369 0.213192 -v -97.877609 12.689369 -9.256309 -v -105.036392 6.376373 0.213192 -v -98.723389 6.376373 -10.721245 -v -86.943176 12.689369 -9.256308 -v -98.723389 6.376373 -10.721245 -v -86.097389 6.376373 -10.721243 -v -86.097389 6.376373 -10.721243 -v -86.943176 12.689369 -9.256308 -v -79.784393 6.376373 0.213193 -v -81.475952 12.689369 0.213193 -v -86.097389 17.310806 0.213192 -v -89.253891 17.310806 5.680411 -v -81.475952 12.689369 0.213193 -v -89.253891 17.310806 5.680411 -v -95.566895 17.310806 5.680411 -v -86.943176 12.689369 9.682693 -v -97.877609 12.689369 9.682693 -v -95.566895 17.310806 5.680411 -v -98.723396 17.310806 0.213192 -v -103.344833 12.689369 0.213192 -v -98.723396 17.310806 0.213192 -v -95.566895 17.310806 -5.254026 -v -97.877609 12.689369 -9.256309 -v -97.877609 12.689369 -9.256309 -v -95.566895 17.310806 -5.254026 -v -89.253891 17.310806 -5.254026 -v -86.097389 17.310806 0.213192 -v -81.475952 12.689369 0.213193 -v -92.410393 19.002373 0.213192 -v -89.253891 17.310806 5.680411 -v -95.566895 17.310806 5.680411 -v -98.723396 17.310806 0.213192 -v -92.410393 19.002373 0.213192 -v -92.410393 19.002373 0.213192 -vt 0.750000 0.750000 -vt 0.807692 0.754360 -vt 0.769231 0.754360 -vt 0.980769 0.750000 -vt 1.000000 0.754360 -vt 0.961538 0.754360 -vt 0.923077 0.754360 -vt 0.980769 0.750000 -vt 0.884615 0.754360 -vt 0.846154 0.754360 -vt 0.807692 0.754360 -vt 0.807692 0.766271 -vt 0.769231 0.766271 -vt 1.000000 0.766271 -vt 0.961538 0.766271 -vt 0.961538 0.754360 -vt 0.961538 0.754360 -vt 0.923077 0.766271 -vt 0.961538 0.754360 -vt 0.923077 0.754360 -vt 0.923077 0.766271 -vt 0.884615 0.766271 -vt 0.846154 0.766271 -vt 0.884615 0.754360 -vt 0.846154 0.766271 -vt 0.846154 0.754360 -vt 0.807692 0.766271 -vt 0.807692 0.754360 -vt 0.807692 0.766271 -vt 0.807692 0.782541 -vt 0.769231 0.782541 -vt 0.807692 0.766271 -vt 0.769231 0.766271 -vt 1.000000 0.782541 -vt 0.961538 0.782541 -vt 0.961538 0.766271 -vt 0.923077 0.782541 -vt 0.923077 0.766271 -vt 0.923077 0.782541 -vt 0.884615 0.782541 -vt 0.884615 0.766271 -vt 0.846154 0.782541 -vt 0.884615 0.766271 -vt 0.807692 0.766271 -vt 0.807692 0.967459 -vt 0.769231 0.967459 -vt 0.807692 0.782541 -vt 1.000000 0.967459 -vt 0.961538 0.967459 -vt 0.961538 0.782541 -vt 0.923077 0.967459 -vt 0.923077 0.782541 -vt 0.923077 0.782541 -vt 0.884615 0.967459 -vt 0.884615 0.782541 -vt 0.846154 0.967459 -vt 0.846154 0.782541 -vt 0.846154 0.967459 -vt 0.807692 0.782541 -vt 0.807692 0.983729 -vt 0.769231 0.983729 -vt 1.000000 0.983729 -vt 0.961538 0.983729 -vt 1.000000 0.967459 -vt 0.961538 0.967459 -vt 0.923077 0.983729 -vt 0.923077 0.967459 -vt 0.923077 0.983729 -vt 0.884615 0.983729 -vt 0.923077 0.967459 -vt 0.884615 0.967459 -vt 0.846154 0.983729 -vt 0.884615 0.967459 -vt 0.846154 0.967459 -vt 0.846154 0.967459 -vt 0.846154 0.983729 -vt 0.807692 0.967459 -vt 0.807692 0.983729 -vt 0.807692 0.995640 -vt 0.769231 0.995640 -vt 0.807692 0.983729 -vt 1.000000 0.995640 -vt 0.961538 0.995640 -vt 1.000000 0.983729 -vt 0.961538 0.983729 -vt 0.961538 0.995640 -vt 0.923077 0.995640 -vt 0.923077 0.983729 -vt 0.923077 0.995640 -vt 0.884615 0.995640 -vt 0.884615 0.983729 -vt 0.884615 0.983729 -vt 0.884615 0.995640 -vt 0.846154 0.995640 -vt 0.807692 0.995640 -vt 0.807692 0.983729 -vt 0.865385 1.000000 -vt 0.769231 0.995640 -vt 0.961538 0.995640 -vt 0.923077 0.995640 -vt 0.865385 1.000000 -vt 0.865385 1.000000 -usemtl Default -f 180/180 181/181 182/182 -f 183/183 184/184 185/185 -f 183/183 185/185 186/186 -f 187/187 186/186 188/188 -f 180/180 188/188 189/189 -f 180/180 189/189 181/181 -f 190/190 191/191 192/192 -f 181/181 192/192 182/182 -f 184/184 193/193 194/194 -f 184/184 194/194 195/195 -f 196/196 194/194 197/197 -f 198/198 197/197 199/199 -f 186/186 200/200 201/201 -f 199/199 201/201 188/188 -f 188/188 201/201 202/202 -f 203/203 202/202 189/189 -f 189/189 204/204 191/191 -f 205/205 206/206 207/207 -f 208/208 209/209 210/210 -f 211/211 210/210 212/212 -f 193/193 213/213 214/214 -f 193/193 214/214 194/194 -f 215/215 214/214 216/216 -f 215/215 216/216 217/217 -f 200/200 218/218 219/219 -f 200/200 219/219 201/201 -f 220/220 219/219 221/221 -f 222/222 221/221 204/204 -f 202/202 221/221 209/209 -f 202/202 209/209 223/223 -f 209/209 224/224 225/225 -f 226/226 225/225 210/210 -f 213/213 227/227 228/228 -f 213/213 228/228 214/214 -f 229/229 228/228 230/230 -f 229/229 230/230 231/231 -f 232/232 230/230 233/233 -f 232/232 233/233 219/219 -f 234/234 233/233 235/235 -f 234/234 235/235 221/221 -f 236/236 237/237 224/224 -f 236/236 224/224 238/238 -f 224/224 239/239 240/240 -f 224/224 240/240 225/225 -f 227/227 241/241 242/242 -f 243/243 242/242 244/244 -f 244/244 242/242 245/245 -f 244/244 245/245 246/246 -f 246/246 247/247 248/248 -f 249/249 248/248 233/233 -f 250/250 248/248 251/251 -f 252/252 251/251 253/253 -f 254/254 255/255 239/239 -f 253/253 239/239 256/256 -f 257/257 258/258 259/259 -f 260/260 259/259 240/240 -f 241/241 261/261 262/262 -f 263/263 262/262 264/264 -f 242/242 265/265 266/266 -f 242/242 266/266 247/247 -f 267/267 268/268 269/269 -f 267/267 269/269 270/270 -f 271/271 272/272 273/273 -f 271/271 273/273 255/255 -f 251/251 273/273 258/258 -f 251/251 274/274 275/275 -f 258/258 276/276 277/277 -f 261/261 276/276 265/265 -f 278/278 276/276 279/279 -f 266/266 280/280 269/269 -f 269/269 276/276 273/273 -f 273/273 281/281 258/258 -g wing02 -v 39.599403 -60.615013 60.362041 -v 43.442596 -69.945724 67.018631 -v 40.496494 -68.157547 67.018639 -v 39.599403 -60.615013 60.362041 -v 34.938843 -60.615013 63.052818 -v 27.632818 -20.619514 50.398453 -v 27.632818 -20.619514 50.398453 -v 32.293377 -20.619514 47.707680 -v 39.599403 -60.615013 60.362041 -v 32.293377 -20.619514 47.707680 -v 27.632818 -20.619514 50.398453 -v 21.930204 1.234921 40.521259 -v 21.930204 1.234921 40.521259 -v 26.590763 1.234924 37.830482 -v 32.293377 -20.619514 47.707680 -v 21.424757 7.132172 34.264244 -v 21.930204 1.234921 40.521259 -v 18.667843 8.019402 34.870689 -v 41.844223 11.210991 69.353058 -v 23.754000 52.636765 41.975880 -v 22.839508 52.964790 42.096275 -v 22.839508 52.964790 42.096275 -v 39.666317 10.123146 71.241112 -v 41.844223 11.210991 69.353058 -v 44.358482 10.347294 68.605080 -v 43.442562 4.123146 67.018654 -v 32.293377 -20.619514 47.707680 -v 32.293377 -20.619514 47.707680 -v 26.590763 1.234924 37.830482 -v 44.358482 10.347294 68.605080 -v 40.496494 -68.157547 67.018639 -v 38.862507 -70.141083 69.848785 -v 34.938843 -60.615013 63.052818 -v 34.938843 -60.615013 63.052818 -v 39.599403 -60.615013 60.362041 -v 40.496494 -68.157547 67.018639 -v 43.442596 -69.945724 67.018631 -v 39.599403 -60.615013 60.362041 -v 32.293377 -20.619514 47.707680 -v 32.293377 -20.619514 47.707680 -v 43.442562 4.123146 67.018654 -v 43.442596 -69.945724 67.018631 -v 26.590763 1.234924 37.830482 -v 23.328405 8.019394 32.179916 -v 27.500082 36.348984 39.405502 -v 27.500082 36.348984 39.405502 -v 44.358482 10.347294 68.605080 -v 26.590763 1.234924 37.830482 -v 27.632818 -20.619514 50.398453 -v 34.938843 -60.615013 63.052818 -v 38.862507 -70.141083 69.848785 -v 38.862507 -70.141083 69.848785 -v 38.862469 4.123146 69.848801 -v 27.632818 -20.619514 50.398453 -v 39.666317 10.123146 71.241112 -v 22.839508 52.964790 42.096275 -v 22.839521 36.348984 42.096279 -v 27.632818 -20.619514 50.398453 -v 38.862469 4.123146 69.848801 -v 39.666317 10.123146 71.241112 -v 39.666317 10.123146 71.241112 -v 21.930204 1.234921 40.521259 -v 27.632818 -20.619514 50.398453 -v 44.358482 10.347294 68.605080 -v 27.501629 53.047661 39.403473 -v 25.727077 51.661057 41.716122 -v 25.727077 51.661057 41.716122 -v 41.844223 11.210991 69.353058 -v 44.358482 10.347294 68.605080 -v 21.424757 7.132172 34.264244 -v 23.328405 8.019394 32.179916 -v 26.590763 1.234924 37.830482 -v 26.590763 1.234924 37.830482 -v 21.930204 1.234921 40.521259 -v 21.424757 7.132172 34.264244 -v 27.500082 36.348984 39.405502 -v 27.501629 53.047661 39.403473 -v 44.358482 10.347294 68.605080 -v 18.667843 8.019402 34.870689 -v 21.930204 1.234921 40.521259 -v 39.666317 10.123146 71.241112 -v 39.666317 10.123146 71.241112 -v 22.839521 36.348984 42.096279 -v 18.667843 8.019402 34.870689 -v 25.727077 51.661057 41.716122 -v 23.754000 52.636765 41.975880 -v 41.844223 11.210991 69.353058 -vt 0.675235 0.145939 -vt 0.659189 0.137027 -vt 0.671489 0.138735 -vt 0.675235 0.145939 -vt 0.694693 0.145939 -vt 0.725197 0.184137 -vt 0.725197 0.184137 -vt 0.705738 0.184137 -vt 0.675235 0.145939 -vt 0.705738 0.184137 -vt 0.725197 0.184137 -vt 0.749006 0.205010 -vt 0.749006 0.205010 -vt 0.729548 0.205010 -vt 0.705738 0.184137 -vt 0.029621 0.222596 -vt 0.031731 0.241442 -vt 0.018110 0.224422 -vt 0.591267 0.027020 -vt 0.626730 0.111287 -vt 0.627011 0.115546 -vt 0.627011 0.115546 -vt 0.590336 0.037165 -vt 0.591267 0.027020 -vt 0.994963 0.356031 -vt 0.983367 0.371855 -vt 0.842205 0.434762 -vt 0.842205 0.434762 -vt 0.770004 0.379199 -vt 0.994963 0.356031 -vt 0.671489 0.138735 -vt 0.678311 0.136840 -vt 0.694693 0.145939 -vt 0.694693 0.145939 -vt 0.675235 0.145939 -vt 0.671489 0.138735 -vt 0.983367 0.560169 -vt 0.934708 0.536447 -vt 0.842205 0.434762 -vt 0.842205 0.434762 -vt 0.983367 0.371855 -vt 0.983367 0.560169 -vt 0.770004 0.379199 -vt 0.745067 0.361950 -vt 0.781517 0.289924 -vt 0.781517 0.289924 -vt 0.994963 0.356031 -vt 0.770004 0.379199 -vt 0.263651 0.176102 -vt 0.172508 0.072900 -vt 0.150800 0.017476 -vt 0.150800 0.017476 -vt 0.320035 0.017476 -vt 0.263651 0.176102 -vt 0.333708 0.006121 -vt 0.431336 0.243810 -vt 0.393471 0.243810 -vt 0.263651 0.176102 -vt 0.320035 0.017476 -vt 0.333708 0.006121 -vt 0.333708 0.006121 -vt 0.313453 0.256655 -vt 0.263651 0.176102 -vt 0.590528 0.015309 -vt 0.627082 0.093830 -vt 0.625895 0.102096 -vt 0.625895 0.102096 -vt 0.591267 0.027020 -vt 0.590528 0.015309 -vt 0.029621 0.222596 -vt 0.037569 0.216318 -vt 0.051190 0.233338 -vt 0.051190 0.233338 -vt 0.031731 0.241442 -vt 0.029621 0.222596 -vt 0.781517 0.289924 -vt 0.781502 0.247469 -vt 0.994963 0.356031 -vt 0.328914 0.302738 -vt 0.313453 0.256655 -vt 0.333708 0.006121 -vt 0.333708 0.006121 -vt 0.393471 0.243810 -vt 0.328914 0.302738 -vt 0.625895 0.102096 -vt 0.626730 0.111287 -vt 0.591267 0.027020 -usemtl Default -f 282/282 283/283 284/284 -f 285/285 286/286 287/287 -f 288/288 289/289 290/290 -f 291/291 292/292 293/293 -f 294/294 295/295 296/296 -f 297/297 298/298 299/299 -f 300/300 301/301 302/302 -f 303/303 304/304 305/305 -f 306/306 307/307 308/308 -f 309/309 310/310 311/311 -f 312/312 313/313 314/314 -f 315/315 316/316 317/317 -f 318/318 319/319 320/320 -f 321/321 322/322 323/323 -f 324/324 325/325 326/326 -f 327/327 328/328 329/329 -f 330/330 331/331 332/332 -f 333/333 334/334 335/335 -f 336/336 337/337 338/338 -f 339/339 340/340 341/341 -f 342/342 343/343 344/344 -f 345/345 346/346 347/347 -f 348/348 349/349 350/350 -f 351/351 352/352 353/353 -f 354/354 355/355 356/356 -f 357/357 358/358 359/359 -f 360/360 361/361 362/362 -f 363/363 364/364 365/365 -f 366/366 367/367 368/368 -g reactor03 -v 45.685333 -77.997643 -78.439079 -v 42.528831 -76.306068 -72.971855 -v 39.372334 -76.306068 -78.439079 -v 45.685333 -77.997643 -78.439079 -v 42.528839 -76.306068 -83.906296 -v 48.841839 -76.306068 -83.906296 -v 51.998333 -76.306068 -78.439072 -v 45.685333 -77.997643 -78.439079 -v 48.841831 -76.306068 -72.971855 -v 48.841831 -76.306068 -72.971855 -v 40.218109 -71.684639 -68.969574 -v 34.750896 -71.684639 -78.439079 -v 39.372334 -76.306068 -78.439079 -v 39.372334 -76.306068 -78.439079 -v 34.750896 -71.684639 -78.439079 -v 40.218121 -71.684639 -87.908577 -v 39.372334 -76.306068 -78.439079 -v 42.528839 -76.306068 -83.906296 -v 51.152557 -71.684624 -87.908577 -v 48.841839 -76.306068 -83.906296 -v 48.841839 -76.306068 -83.906296 -v 51.152557 -71.684624 -87.908577 -v 56.619770 -71.684624 -78.439072 -v 51.998333 -76.306068 -78.439072 -v 51.998333 -76.306068 -78.439072 -v 56.619770 -71.684624 -78.439072 -v 51.152546 -71.684624 -68.969574 -v 51.998333 -76.306068 -78.439072 -v 51.152546 -71.684624 -68.969574 -v 42.528831 -76.306068 -72.971855 -v 40.218109 -71.684639 -68.969574 -v 39.372326 -65.371635 -67.504639 -v 33.059330 -65.371635 -78.439087 -v 33.059330 -65.371635 -78.439087 -v 39.372337 -65.371635 -89.373520 -v 34.750896 -71.684639 -78.439079 -v 40.218121 -71.684639 -87.908577 -v 39.372337 -65.371635 -89.373520 -v 51.998341 -65.371635 -89.373512 -v 40.218121 -71.684639 -87.908577 -v 51.152557 -71.684624 -87.908577 -v 51.998341 -65.371635 -89.373512 -v 58.311333 -65.371635 -78.439072 -v 56.619770 -71.684624 -78.439072 -v 51.998325 -65.371635 -67.504631 -v 56.619770 -71.684624 -78.439072 -v 51.152546 -71.684624 -68.969574 -v 51.998325 -65.371635 -67.504631 -v 39.372314 6.376366 -67.504646 -v 33.059319 6.376366 -78.439087 -v 39.372326 -65.371635 -67.504639 -v 33.059330 -65.371635 -78.439087 -v 33.059330 -65.371635 -78.439087 -v 33.059319 6.376366 -78.439087 -v 39.372326 6.376366 -89.373520 -v 39.372337 -65.371635 -89.373520 -v 39.372337 -65.371635 -89.373520 -v 51.998329 6.376366 -89.373512 -v 58.311321 6.376366 -78.439072 -v 58.311333 -65.371635 -78.439072 -v 58.311321 6.376366 -78.439072 -v 51.998314 6.376366 -67.504639 -v 51.998325 -65.371635 -67.504631 -v 51.998314 6.376366 -67.504639 -v 39.372326 -65.371635 -67.504639 -v 40.218094 12.689362 -68.969582 -v 34.750881 12.689362 -78.439087 -v 40.218105 12.689362 -87.908585 -v 33.059319 6.376366 -78.439087 -v 39.372326 6.376366 -89.373520 -v 51.152542 12.689362 -87.908577 -v 51.998329 6.376366 -89.373512 -v 56.619755 12.689362 -78.439072 -v 58.311321 6.376366 -78.439072 -v 58.311321 6.376366 -78.439072 -v 51.152531 12.689362 -68.969574 -v 58.311321 6.376366 -78.439072 -v 51.998314 6.376366 -67.504639 -v 51.152531 12.689362 -68.969574 -v 51.998314 6.376366 -67.504639 -v 40.218094 12.689362 -68.969582 -v 39.372314 6.376366 -67.504646 -v 40.218094 12.689362 -68.969582 -v 42.528816 17.310799 -72.971863 -v 39.372318 17.310799 -78.439079 -v 34.750881 12.689362 -78.439087 -v 39.372318 17.310799 -78.439079 -v 42.528820 17.310799 -83.906303 -v 40.218105 12.689362 -87.908585 -v 48.841824 17.310799 -83.906296 -v 40.218105 12.689362 -87.908585 -v 51.152542 12.689362 -87.908577 -v 51.152542 12.689362 -87.908577 -v 48.841824 17.310799 -83.906296 -v 51.998318 17.310799 -78.439072 -v 56.619755 12.689362 -78.439072 -v 48.841816 17.310799 -72.971855 -v 51.152531 12.689362 -68.969574 -v 48.841816 17.310799 -72.971855 -v 42.528816 17.310799 -72.971863 -v 45.685318 19.002365 -78.439079 -v 39.372318 17.310799 -78.439079 -v 42.528820 17.310799 -83.906303 -v 48.841824 17.310799 -83.906296 -v 51.998318 17.310799 -78.439072 -v 48.841816 17.310799 -72.971855 -v 45.685318 19.002365 -78.439079 -vt 0.750000 1.000000 -vt 0.821429 0.995640 -vt 0.857143 0.995640 -vt 0.964286 1.000000 -vt 0.892857 0.995640 -vt 0.928571 0.995640 -vt 0.964286 0.995640 -vt 0.964286 1.000000 -vt 1.000000 0.995640 -vt 0.785714 0.995640 -vt 0.821429 0.983729 -vt 0.857143 0.983729 -vt 0.857143 0.995640 -vt 0.857143 0.995640 -vt 0.857143 0.983729 -vt 0.892857 0.983729 -vt 0.857143 0.995640 -vt 0.892857 0.995640 -vt 0.928571 0.983729 -vt 0.928571 0.995640 -vt 0.928571 0.995640 -vt 0.928571 0.983729 -vt 0.964286 0.983729 -vt 0.964286 0.995640 -vt 0.964286 0.995640 -vt 0.964286 0.983729 -vt 1.000000 0.983729 -vt 0.964286 0.995640 -vt 0.785714 0.983729 -vt 0.821429 0.995640 -vt 0.821429 0.983729 -vt 0.821429 0.967459 -vt 0.857143 0.967459 -vt 0.857143 0.967459 -vt 0.892857 0.967459 -vt 0.857143 0.983729 -vt 0.892857 0.983729 -vt 0.892857 0.967459 -vt 0.928571 0.967459 -vt 0.892857 0.983729 -vt 0.928571 0.983729 -vt 0.928571 0.967459 -vt 0.964286 0.967459 -vt 0.964286 0.983729 -vt 1.000000 0.967459 -vt 0.964286 0.983729 -vt 1.000000 0.983729 -vt 0.785714 0.967459 -vt 0.821429 0.782541 -vt 0.857143 0.782541 -vt 0.821429 0.967459 -vt 0.857143 0.967459 -vt 0.857143 0.967459 -vt 0.857143 0.782541 -vt 0.892857 0.782541 -vt 0.892857 0.967459 -vt 0.892857 0.967459 -vt 0.928571 0.782541 -vt 0.964286 0.782541 -vt 0.964286 0.967459 -vt 0.964286 0.782541 -vt 1.000000 0.782541 -vt 1.000000 0.967459 -vt 0.785714 0.782541 -vt 0.821429 0.967459 -vt 0.821429 0.766271 -vt 0.857143 0.766271 -vt 0.892857 0.766271 -vt 0.857143 0.782541 -vt 0.892857 0.782541 -vt 0.928571 0.766271 -vt 0.928571 0.782541 -vt 0.964286 0.766271 -vt 0.964286 0.782541 -vt 0.964286 0.782541 -vt 1.000000 0.766271 -vt 0.964286 0.782541 -vt 1.000000 0.782541 -vt 0.785714 0.766271 -vt 0.785714 0.782541 -vt 0.821429 0.766271 -vt 0.821429 0.782541 -vt 0.821429 0.766271 -vt 0.821429 0.754360 -vt 0.857143 0.754360 -vt 0.857143 0.766271 -vt 0.857143 0.754360 -vt 0.892857 0.754360 -vt 0.892857 0.766271 -vt 0.928571 0.754360 -vt 0.892857 0.766271 -vt 0.928571 0.766271 -vt 0.928571 0.766271 -vt 0.928571 0.754360 -vt 0.964286 0.754360 -vt 0.964286 0.766271 -vt 1.000000 0.754360 -vt 1.000000 0.766271 -vt 0.785714 0.754360 -vt 0.821429 0.754360 -vt 0.857143 0.750000 -vt 0.857143 0.754360 -vt 0.892857 0.754360 -vt 0.928571 0.754360 -vt 0.750000 0.754360 -vt 0.785714 0.754360 -vt 0.857143 0.750000 -usemtl Default -f 369/369 370/370 371/371 -f 372/372 371/371 373/373 -f 372/372 373/373 374/374 -f 372/372 374/374 375/375 -f 376/376 375/375 377/377 -f 369/369 378/378 370/370 -f 370/370 379/379 380/380 -f 370/370 380/380 381/381 -f 382/382 383/383 384/384 -f 385/385 384/384 373/373 -f 386/386 384/384 387/387 -f 373/373 387/387 388/388 -f 389/389 390/390 391/391 -f 389/389 391/391 392/392 -f 393/393 394/394 395/395 -f 396/396 395/395 377/377 -f 378/378 397/397 379/379 -f 378/378 379/379 398/398 -f 399/399 400/400 401/401 -f 379/379 401/401 380/380 -f 383/383 402/402 403/403 -f 404/404 403/403 384/384 -f 405/405 406/406 407/407 -f 408/408 407/407 409/409 -f 409/409 410/410 411/411 -f 409/409 411/411 412/412 -f 412/412 411/411 413/413 -f 414/414 413/413 415/415 -f 397/397 416/416 400/400 -f 397/397 400/400 399/399 -f 400/400 417/417 418/418 -f 419/419 418/418 420/420 -f 421/421 422/422 423/423 -f 421/421 423/423 424/424 -f 425/425 423/423 426/426 -f 425/425 426/426 407/407 -f 410/410 426/426 427/427 -f 410/410 427/427 411/411 -f 428/428 429/429 430/430 -f 428/428 430/430 431/431 -f 416/416 432/432 417/417 -f 416/416 417/417 433/433 -f 417/417 434/434 435/435 -f 417/417 435/435 418/418 -f 422/422 435/435 436/436 -f 437/437 436/436 438/438 -f 423/423 436/436 439/439 -f 423/423 439/439 440/440 -f 426/426 439/439 441/441 -f 426/426 441/441 442/442 -f 443/443 441/441 444/444 -f 445/445 444/444 446/446 -f 432/432 447/447 434/434 -f 448/448 449/449 450/450 -f 451/451 452/452 453/453 -f 434/434 453/453 454/454 -f 435/435 455/455 456/456 -f 435/435 456/456 436/436 -f 457/457 456/456 458/458 -f 459/459 458/458 460/460 -f 461/461 462/462 463/463 -f 439/439 463/463 441/441 -f 464/464 463/463 465/465 -f 464/464 465/465 466/466 -f 447/447 467/467 452/452 -f 447/447 452/452 451/451 -f 468/468 469/469 470/470 -f 470/470 469/469 456/456 -f 471/471 469/469 458/458 -f 472/472 469/469 463/463 -f 473/473 469/469 467/467 -f 474/474 475/475 468/468 -g wing03 -v 33.762955 -60.615021 -62.868530 -v 37.606140 -69.945724 -69.525124 -v 39.079193 -68.157547 -66.973732 -v 33.762955 -60.615021 -62.868530 -v 38.423519 -60.615021 -60.177750 -v 31.117521 -20.619514 -47.523380 -v 31.117521 -20.619514 -47.523380 -v 26.456961 -20.619514 -50.214157 -v 33.762955 -60.615021 -62.868530 -v 26.456961 -20.619514 -50.214157 -v 31.117521 -20.619514 -47.523380 -v 25.414923 1.234928 -37.646183 -v 20.754362 1.234928 -40.336960 -v 20.248913 7.132179 -34.079948 -v 25.414923 1.234928 -37.646183 -v 22.152567 8.019409 -31.995615 -v 40.426983 11.210987 -69.308144 -v 25.762754 52.636772 -39.952969 -v 26.324265 52.964798 -39.221191 -v 26.324265 52.964798 -39.221191 -v 43.151035 10.123142 -68.366035 -v 40.426983 11.210987 -69.308144 -v 38.522083 10.347294 -71.111565 -v 37.606159 4.123146 -69.525139 -v 26.456961 -20.619514 -50.214157 -v 26.456961 -20.619514 -50.214157 -v 20.754362 1.234928 -40.336960 -v 38.522083 10.347294 -71.111565 -v 39.079193 -68.157547 -66.973732 -v 42.347172 -70.141090 -66.973724 -v 38.423519 -60.615021 -60.177750 -v 38.423519 -60.615021 -60.177750 -v 33.762955 -60.615021 -62.868530 -v 39.079193 -68.157547 -66.973732 -v 37.606140 -69.945724 -69.525124 -v 33.762955 -60.615021 -62.868530 -v 26.456961 -20.619514 -50.214157 -v 26.456961 -20.619514 -50.214157 -v 37.606159 4.123146 -69.525139 -v 37.606140 -69.945724 -69.525124 -v 20.754362 1.234928 -40.336960 -v 17.492006 8.019402 -34.686394 -v 21.663702 36.348991 -41.911976 -v 21.663702 36.348991 -41.911976 -v 38.522083 10.347294 -71.111565 -v 20.754362 1.234928 -40.336960 -v 31.117521 -20.619514 -47.523380 -v 38.423519 -60.615021 -60.177750 -v 42.347172 -70.141090 -66.973724 -v 42.347172 -70.141090 -66.973724 -v 42.347187 4.123142 -66.973732 -v 31.117521 -20.619514 -47.523380 -v 43.151035 10.123142 -68.366035 -v 26.324265 52.964798 -39.221191 -v 26.324265 36.348991 -39.221199 -v 31.117521 -20.619514 -47.523380 -v 42.347187 4.123142 -66.973732 -v 43.151035 10.123142 -68.366035 -v 43.151035 10.123142 -68.366035 -v 25.414923 1.234928 -37.646183 -v 31.117521 -20.619514 -47.523380 -v 38.522083 10.347294 -71.111565 -v 21.661169 53.047668 -41.912308 -v 24.551258 51.661064 -41.531822 -v 24.551258 51.661064 -41.531822 -v 40.426983 11.210987 -69.308144 -v 38.522083 10.347294 -71.111565 -v 20.248913 7.132179 -34.079948 -v 17.492006 8.019402 -34.686394 -v 20.754362 1.234928 -40.336960 -v 20.754362 1.234928 -40.336960 -v 25.414923 1.234928 -37.646183 -v 20.248913 7.132179 -34.079948 -v 21.663702 36.348991 -41.911976 -v 21.661169 53.047668 -41.912308 -v 38.522083 10.347294 -71.111565 -v 22.152567 8.019409 -31.995615 -v 25.414923 1.234928 -37.646183 -v 43.151035 10.123142 -68.366035 -v 43.151035 10.123142 -68.366035 -v 26.324265 36.348991 -39.221199 -v 22.152567 8.019409 -31.995615 -v 24.551258 51.661064 -41.531822 -v 25.762754 52.636772 -39.952969 -v 40.426983 11.210987 -69.308144 -vt 0.716045 0.241039 -vt 0.731750 0.232127 -vt 0.737769 0.233835 -vt 0.716045 0.241039 -vt 0.735090 0.241039 -vt 0.705235 0.279237 -vt 0.705235 0.279237 -vt 0.686190 0.279237 -vt 0.716045 0.241039 -vt 0.686190 0.279237 -vt 0.705235 0.279237 -vt 0.681932 0.300110 -vt 0.662887 0.300110 -vt 0.034182 0.291360 -vt 0.055292 0.280633 -vt 0.041961 0.297629 -vt 0.767298 0.024370 -vt 0.731836 0.091226 -vt 0.731555 0.088666 -vt 0.731555 0.088666 -vt 0.768230 0.011951 -vt 0.767298 0.024370 -vt 0.745454 0.612416 -vt 0.756774 0.596591 -vt 0.894572 0.533685 -vt 0.894572 0.533685 -vt 0.965052 0.589248 -vt 0.745454 0.612416 -vt 0.737769 0.233835 -vt 0.751124 0.231941 -vt 0.735090 0.241039 -vt 0.735090 0.241039 -vt 0.716045 0.241039 -vt 0.737769 0.233835 -vt 0.756774 0.408278 -vt 0.804274 0.432001 -vt 0.894572 0.533685 -vt 0.894572 0.533685 -vt 0.756774 0.596591 -vt 0.756774 0.408278 -vt 0.965052 0.589248 -vt 0.989004 0.606497 -vt 0.953814 0.678523 -vt 0.953814 0.678523 -vt 0.745454 0.612416 -vt 0.965052 0.589248 -vt 0.177091 0.135932 -vt 0.268233 0.236675 -vt 0.289941 0.290778 -vt 0.289941 0.290778 -vt 0.120707 0.290778 -vt 0.177091 0.135932 -vt 0.107034 0.301862 -vt 0.009406 0.069838 -vt 0.047271 0.069838 -vt 0.177091 0.135932 -vt 0.120707 0.290778 -vt 0.107034 0.301862 -vt 0.107034 0.301862 -vt 0.127289 0.057299 -vt 0.177091 0.135932 -vt 0.768038 0.033055 -vt 0.731484 0.109925 -vt 0.732671 0.096749 -vt 0.732671 0.096749 -vt 0.767298 0.024370 -vt 0.768038 0.033055 -vt 0.034182 0.291360 -vt 0.022916 0.289536 -vt 0.036247 0.272540 -vt 0.036247 0.272540 -vt 0.055292 0.280633 -vt 0.034182 0.291360 -vt 0.953814 0.678523 -vt 0.953811 0.720977 -vt 0.745454 0.612416 -vt 0.111828 0.012315 -vt 0.127289 0.057299 -vt 0.107034 0.301862 -vt 0.107034 0.301862 -vt 0.047271 0.069838 -vt 0.111828 0.012315 -vt 0.732671 0.096749 -vt 0.731836 0.091226 -vt 0.767298 0.024370 -usemtl Default -f 476/476 477/477 478/478 -f 479/479 480/480 481/481 -f 482/482 483/483 484/484 -f 485/485 486/486 487/487 -f 487/487 488/488 485/485 -f 489/489 490/490 491/491 -f 492/492 493/493 494/494 -f 495/495 496/496 497/497 -f 498/498 499/499 500/500 -f 501/501 502/502 503/503 -f 504/504 505/505 506/506 -f 507/507 508/508 509/509 -f 510/510 511/511 512/512 -f 513/513 514/514 515/515 -f 516/516 517/517 518/518 -f 519/519 520/520 521/521 -f 522/522 523/523 524/524 -f 525/525 526/526 527/527 -f 528/528 529/529 530/530 -f 531/531 532/532 533/533 -f 534/534 535/535 536/536 -f 537/537 538/538 539/539 -f 540/540 541/541 542/542 -f 543/543 544/544 545/545 -f 546/546 547/547 548/548 -f 549/549 550/550 551/551 -f 552/552 553/553 554/554 -f 555/555 556/556 557/557 -f 558/558 559/559 560/560 -g reactor02 -v 47.122719 -77.997612 78.472374 -v 43.966217 -76.306053 73.005157 -v 50.279217 -76.306053 73.005157 -v 53.435719 -76.306053 78.472374 -v 53.435719 -76.306053 78.472374 -v 50.279217 -76.306053 83.939598 -v 47.122719 -77.997612 78.472374 -v 43.966217 -76.306053 83.939598 -v 47.122719 -77.997612 78.472374 -v 40.809719 -76.306053 78.472374 -v 47.122719 -77.997612 78.472374 -v 43.966217 -76.306053 73.005157 -v 41.655499 -71.684608 69.002876 -v 52.589939 -71.684624 69.002876 -v 50.279217 -76.306053 73.005157 -v 58.057159 -71.684624 78.472374 -v 52.589939 -71.684624 87.941879 -v 50.279217 -76.306053 83.939598 -v 52.589939 -71.684624 87.941879 -v 41.655502 -71.684608 87.941879 -v 50.279217 -76.306053 83.939598 -v 43.966217 -76.306053 83.939598 -v 36.188282 -71.684608 78.472374 -v 43.966217 -76.306053 83.939598 -v 40.809719 -76.306053 78.472374 -v 41.655499 -71.684608 69.002876 -v 43.966217 -76.306053 73.005157 -v 40.809723 -65.371620 67.537941 -v 53.435722 -65.371620 67.537941 -v 52.589939 -71.684624 69.002876 -v 59.748722 -65.371620 78.472374 -v 52.589939 -71.684624 69.002876 -v 58.057159 -71.684624 78.472374 -v 53.435722 -65.371620 89.406815 -v 58.057159 -71.684624 78.472374 -v 52.589939 -71.684624 87.941879 -v 53.435722 -65.371620 89.406815 -v 40.809723 -65.371620 89.406815 -v 52.589939 -71.684624 87.941879 -v 40.809723 -65.371620 89.406815 -v 34.496723 -65.371620 78.472374 -v 41.655502 -71.684608 87.941879 -v 36.188282 -71.684608 78.472374 -v 34.496723 -65.371620 78.472374 -v 36.188282 -71.684608 78.472374 -v 41.655499 -71.684608 69.002876 -v 40.809750 6.376381 67.537941 -v 53.435753 6.376381 67.537933 -v 53.435722 -65.371620 67.537941 -v 53.435722 -65.371620 67.537941 -v 59.748753 6.376373 78.472374 -v 59.748722 -65.371620 78.472374 -v 53.435753 6.376381 89.406815 -v 53.435722 -65.371620 89.406815 -v 53.435753 6.376381 89.406815 -v 40.809750 6.376381 89.406815 -v 34.496750 6.376389 78.472374 -v 34.496723 -65.371620 78.472374 -v 34.496723 -65.371620 78.472374 -v 40.809723 -65.371620 67.537941 -v 41.655537 12.689377 69.002876 -v 52.589973 12.689377 69.002876 -v 40.809750 6.376381 67.537941 -v 58.057194 12.689369 78.472374 -v 59.748753 6.376373 78.472374 -v 58.057194 12.689369 78.472374 -v 52.589973 12.689377 87.941872 -v 59.748753 6.376373 78.472374 -v 52.589973 12.689377 87.941872 -v 41.655537 12.689377 87.941872 -v 53.435753 6.376381 89.406815 -v 36.188316 12.689384 78.472374 -v 34.496750 6.376389 78.472374 -v 34.496750 6.376389 78.472374 -v 41.655537 12.689377 69.002876 -v 43.966255 17.310814 73.005157 -v 50.279255 17.310814 73.005157 -v 52.589973 12.689377 69.002876 -v 53.435757 17.310814 78.472374 -v 53.435757 17.310814 78.472374 -v 50.279255 17.310814 83.939590 -v 50.279255 17.310814 83.939590 -v 43.966255 17.310814 83.939590 -v 43.966255 17.310814 83.939590 -v 40.809757 17.310814 78.472374 -v 36.188316 12.689384 78.472374 -v 36.188316 12.689384 78.472374 -v 43.966255 17.310814 73.005157 -v 47.122757 19.002380 78.472374 -v 50.279255 17.310814 83.939590 -v 47.122757 19.002380 78.472374 -v 40.809757 17.310814 78.472374 -v 47.122757 19.002380 78.472374 -vt 0.857143 1.000000 -vt 0.892857 0.995640 -vt 0.928571 0.995640 -vt 0.964286 0.995640 -vt 0.750000 0.995640 -vt 0.785714 0.995640 -vt 0.857143 1.000000 -vt 0.821429 0.995640 -vt 0.857143 1.000000 -vt 0.857143 0.995640 -vt 0.857143 1.000000 -vt 0.892857 0.995640 -vt 0.892857 0.983729 -vt 0.928571 0.983729 -vt 0.928571 0.995640 -vt 0.964286 0.983729 -vt 1.000000 0.983729 -vt 1.000000 0.995640 -vt 0.785714 0.983729 -vt 0.821429 0.983729 -vt 0.785714 0.995640 -vt 0.821429 0.995640 -vt 0.857143 0.983729 -vt 0.821429 0.995640 -vt 0.857143 0.995640 -vt 0.892857 0.983729 -vt 0.892857 0.995640 -vt 0.892857 0.967459 -vt 0.928571 0.967459 -vt 0.928571 0.983729 -vt 0.964286 0.967459 -vt 0.928571 0.983729 -vt 0.964286 0.983729 -vt 1.000000 0.967459 -vt 0.964286 0.983729 -vt 1.000000 0.983729 -vt 0.785714 0.967459 -vt 0.821429 0.967459 -vt 0.785714 0.983729 -vt 0.821429 0.967459 -vt 0.857143 0.967459 -vt 0.821429 0.983729 -vt 0.857143 0.983729 -vt 0.857143 0.967459 -vt 0.857143 0.983729 -vt 0.892857 0.983729 -vt 0.892857 0.782541 -vt 0.928571 0.782541 -vt 0.928571 0.967459 -vt 0.928571 0.967459 -vt 0.964286 0.782541 -vt 0.964286 0.967459 -vt 1.000000 0.782541 -vt 1.000000 0.967459 -vt 0.785714 0.782541 -vt 0.821429 0.782541 -vt 0.857143 0.782541 -vt 0.857143 0.967459 -vt 0.857143 0.967459 -vt 0.892857 0.967459 -vt 0.892857 0.766271 -vt 0.928571 0.766271 -vt 0.892857 0.782541 -vt 0.964286 0.766271 -vt 0.964286 0.782541 -vt 0.964286 0.766271 -vt 1.000000 0.766271 -vt 0.964286 0.782541 -vt 0.785714 0.766271 -vt 0.821428 0.766271 -vt 0.785714 0.782541 -vt 0.857143 0.766271 -vt 0.857143 0.782541 -vt 0.857143 0.782541 -vt 0.892857 0.766271 -vt 0.892857 0.754360 -vt 0.928571 0.754360 -vt 0.928571 0.766271 -vt 0.964286 0.754360 -vt 0.964286 0.754360 -vt 1.000000 0.754360 -vt 0.785714 0.754360 -vt 0.821428 0.754360 -vt 0.821428 0.754360 -vt 0.857143 0.754360 -vt 0.857143 0.766271 -vt 0.857143 0.766271 -vt 0.892857 0.754360 -vt 0.964286 0.750000 -vt 1.000000 0.754360 -vt 0.750000 0.750000 -vt 0.857143 0.754360 -vt 0.964286 0.750000 -usemtl Default -f 561/561 562/562 563/563 -f 561/561 563/563 564/564 -f 561/561 565/565 566/566 -f 567/567 566/566 568/568 -f 569/569 568/568 570/570 -f 571/571 570/570 562/562 -f 572/572 573/573 574/574 -f 572/572 574/574 575/575 -f 563/563 574/574 576/576 -f 575/575 576/576 564/564 -f 564/564 576/576 577/577 -f 564/564 577/577 578/578 -f 566/566 579/579 580/580 -f 581/581 580/580 582/582 -f 582/582 580/580 583/583 -f 584/584 583/583 585/585 -f 570/570 583/583 573/573 -f 570/570 586/586 587/587 -f 586/586 588/588 589/589 -f 573/573 589/589 574/574 -f 590/590 589/589 591/591 -f 592/592 591/591 593/593 -f 576/576 591/591 594/594 -f 595/595 594/594 596/596 -f 579/579 597/597 598/598 -f 599/599 598/598 580/580 -f 580/580 600/600 601/601 -f 602/602 601/601 603/603 -f 583/583 604/604 588/588 -f 605/605 588/588 606/606 -f 588/588 607/607 608/608 -f 588/588 608/608 609/609 -f 610/610 608/608 611/611 -f 610/610 611/611 591/591 -f 612/612 611/611 613/613 -f 612/612 613/613 614/614 -f 597/597 615/615 616/616 -f 597/597 616/616 598/598 -f 600/600 616/616 617/617 -f 600/600 617/617 604/604 -f 618/618 617/617 607/607 -f 619/619 607/607 620/620 -f 607/607 621/621 622/622 -f 623/623 622/622 608/608 -f 608/608 622/622 624/624 -f 608/608 624/624 611/611 -f 625/625 626/626 627/627 -f 628/628 627/627 613/613 -f 615/615 629/629 630/630 -f 631/631 630/630 616/616 -f 616/616 630/630 632/632 -f 616/616 632/632 633/633 -f 634/634 632/632 621/621 -f 617/617 635/635 607/607 -f 621/621 636/636 637/637 -f 621/621 637/637 622/622 -f 638/638 637/637 639/639 -f 622/622 639/639 626/626 -f 626/626 640/640 641/641 -f 626/626 641/641 627/627 -f 629/629 642/642 643/643 -f 629/629 643/643 630/630 -f 630/630 644/644 645/645 -f 630/630 645/645 632/632 -f 646/646 645/645 636/636 -f 647/647 636/636 621/621 -f 648/648 649/649 637/637 -f 637/637 649/649 639/639 -f 639/639 649/649 650/650 -f 642/642 651/651 643/643 -f 643/643 651/651 652/652 -f 645/645 653/653 648/648 diff --git a/mode/examples/Basics/Shape/LoadDisplayOBJ/data/rocket.png b/mode/examples/Basics/Shape/LoadDisplayOBJ/data/rocket.png deleted file mode 100644 index b9724ab8e..000000000 Binary files a/mode/examples/Basics/Shape/LoadDisplayOBJ/data/rocket.png and /dev/null differ diff --git a/mode/examples/Basics/Shape/LoadDisplaySVG/LoadDisplaySVG.pde b/mode/examples/Basics/Shape/LoadDisplaySVG/LoadDisplaySVG.pde deleted file mode 100644 index 5cb9c91d4..000000000 --- a/mode/examples/Basics/Shape/LoadDisplaySVG/LoadDisplaySVG.pde +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Load and Display a Shape. - * Illustration by George Brower. - * - * The loadShape() command is used to read simple SVG (Scalable Vector Graphics) - * files and OBJ (Object) files into a Processing sketch. This example loads an - * SVG file of a monster robot face and displays it to the screen. - */ - -// The next line is needed if running in JavaScript Mode with Processing.js -/* @pjs preload="bot1.svg"; */ - -PShape bot; - -void setup() { - size(640, 360); - // The file "bot1.svg" must be in the data folder - // of the current sketch to load successfully - bot = loadShape("bot1.svg"); -} - -void draw(){ - background(102); - shape(bot, 110, 90, 100, 100); // Draw at coordinate (110, 90) at size 100 x 100 - shape(bot, 280, 40); // Draw at coordinate (280, 40) at the default size -} diff --git a/mode/examples/Basics/Shape/LoadDisplaySVG/data/bot1.svg b/mode/examples/Basics/Shape/LoadDisplaySVG/data/bot1.svg deleted file mode 100644 index 3c56f2d60..000000000 --- a/mode/examples/Basics/Shape/LoadDisplaySVG/data/bot1.svg +++ /dev/null @@ -1,160 +0,0 @@ - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mode/examples/Basics/Shape/ScaleShape/ScaleShape.pde b/mode/examples/Basics/Shape/ScaleShape/ScaleShape.pde deleted file mode 100644 index 879f20b68..000000000 --- a/mode/examples/Basics/Shape/ScaleShape/ScaleShape.pde +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Scale Shape. - * Illustration by George Brower. - * - * Move the mouse left and right to zoom the SVG file. - * This shows how, unlike an imported image, the lines - * remain smooth at any size. - */ - -PShape bot; - -void setup() { - size(640, 360); - smooth(); - // The file "bot1.svg" must be in the data folder - // of the current sketch to load successfully - bot = loadShape("bot1.svg"); -} - -void draw() { - background(102); - translate(width/2, height/2); - float zoom = map(mouseX, 0, width, 0.1, 4.5); - scale(zoom); - shape(bot, -140, -140); -} diff --git a/mode/examples/Basics/Shape/ScaleShape/data/bot1.svg b/mode/examples/Basics/Shape/ScaleShape/data/bot1.svg deleted file mode 100644 index 3c56f2d60..000000000 --- a/mode/examples/Basics/Shape/ScaleShape/data/bot1.svg +++ /dev/null @@ -1,160 +0,0 @@ - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mode/examples/Basics/Structure/Coordinates/Coordinates.pde b/mode/examples/Basics/Structure/Coordinates/Coordinates.pde deleted file mode 100644 index c63c147b7..000000000 --- a/mode/examples/Basics/Structure/Coordinates/Coordinates.pde +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Coordinates. - * - * All shapes drawn to the screen have a position that is specified as a coordinate. - * All coordinates are measured as the distance from the origin in units of pixels. - * The origin [0, 0] is the coordinate is in the upper left of the window - * and the coordinate in the lower right is [width-1, height-1]. - */ - -// Sets the screen to be 200, 200, so the width of the window is 200 pixels -// and the height of the window is 200 pixels -size(200, 200); -background(0); -noFill(); -stroke(255); - -// The two parameters of the point() method each specify coordinates. -// This call to point() draws at the position [100, 100] -point(width/2, height/2); - -// Draws to the position [100, 50] -point(width/2, height/4); - -// It is also possible to specify a point with any parameter, -// but only coordinates on the screen are visible -point(60, 30); -point(60, 134); -point(160, 50); -point(280, -800); -point(201, 100); - -// Coordinates are used for drawing all shapes, not just points. -// Parameters for different methods are used for different purposes. -// For example, the first two parameters to line() specify the coordinates of the -// first point and the second two parameters specify the second point -stroke(204); -line(0, 73, width, 73); - -// The first two parameters to rect() are coordinates -// and the second two are the width and height -rect(110, 55, 40, 36); diff --git a/mode/examples/Basics/Structure/CreateGraphics/CreateGraphics.pde b/mode/examples/Basics/Structure/CreateGraphics/CreateGraphics.pde deleted file mode 100644 index af137112e..000000000 --- a/mode/examples/Basics/Structure/CreateGraphics/CreateGraphics.pde +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Create Graphics. - * - * The createGraphics() function creates an object from the PGraphics class - * (PGraphics is the main graphics and rendering context for Processing). - * The beginDraw() method is necessary to prepare for drawing and endDraw() is - * necessary to finish. Use this class if you need to draw into an off-screen - * graphics buffer or to maintain two contexts with different properties. - */ - -PGraphics pg; - -void setup() { - size(200, 200); - pg = createGraphics(80, 80); -} - -void draw() { - fill(0, 12); - rect(0, 0, width, height); - fill(255); - noStroke(); - ellipse(mouseX, mouseY, 60, 60); - - pg.beginDraw(); - pg.background(102); - pg.noFill(); - pg.stroke(255); - pg.ellipse(mouseX-60, mouseY-60, 60, 60); - pg.endDraw(); - - image(pg, 60, 60); -} diff --git a/mode/examples/Basics/Structure/CreateGraphics/data/mask.jpg b/mode/examples/Basics/Structure/CreateGraphics/data/mask.jpg deleted file mode 100644 index bbd138254..000000000 Binary files a/mode/examples/Basics/Structure/CreateGraphics/data/mask.jpg and /dev/null differ diff --git a/mode/examples/Basics/Structure/CreateGraphics/data/test.jpg b/mode/examples/Basics/Structure/CreateGraphics/data/test.jpg deleted file mode 100644 index 04d3fc56d..000000000 Binary files a/mode/examples/Basics/Structure/CreateGraphics/data/test.jpg and /dev/null differ diff --git a/mode/examples/Basics/Structure/Functions/Functions.pde b/mode/examples/Basics/Structure/Functions/Functions.pde deleted file mode 100644 index b94fdb01e..000000000 --- a/mode/examples/Basics/Structure/Functions/Functions.pde +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Functions. - * - * The drawTarget() function makes it easy to draw many distinct targets. - * Each call to drawTarget() specifies the position, size, and number of - * rings for each target. - */ - -void setup() -{ - size(200, 200); - background(51); - noStroke(); - smooth(); - noLoop(); -} - -void draw() -{ - drawTarget(68, 34, 200, 10); - drawTarget(152, 16, 100, 3); - drawTarget(100, 144, 80, 5); -} - -void drawTarget(int xloc, int yloc, int size, int num) -{ - float grayvalues = 255/num; - float steps = size/num; - for(int i=0; i 1) { - level = level - 1; - drawCircle(x - radius/2, radius/2, level); - drawCircle(x + radius/2, radius/2, level); - } -} diff --git a/mode/examples/Basics/Structure/Recursion2/Recursion2.pde b/mode/examples/Basics/Structure/Recursion2/Recursion2.pde deleted file mode 100644 index 0da7d10cc..000000000 --- a/mode/examples/Basics/Structure/Recursion2/Recursion2.pde +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Recursion. - * - * A demonstration of recursion, which means functions call themselves. - * Notice how the drawCircle() function calls itself at the end of its block. - * It continues to do this until the variable "level" is equal to 1. - */ - -void setup() -{ - size(200, 200); - noStroke(); - smooth(); - drawCircle(100, 100, 80, 8); -} - -void drawCircle(float x, float y, int radius, int level) -{ - float tt = 126 * level/6.0; - fill(tt, 153); - ellipse(x, y, radius*2, radius*2); - if(level > 1) { - level = level - 1; - int num = int(random(2, 6)); - for(int i=0; i TWO_PI) { - a = 0.0; - } - - translate(width/2, height/2); - - rotateX(a); - rotateY(a * 2.0); - fill(255); - rect(-rSize, -rSize, rSize*2, rSize*2); - - rotateX(a * 1.001); - rotateY(a * 2.002); - fill(0); - rect(-rSize, -rSize, rSize*2, rSize*2); - -} diff --git a/mode/examples/Basics/Transform/Scale/Scale.pde b/mode/examples/Basics/Transform/Scale/Scale.pde deleted file mode 100644 index dc41a584d..000000000 --- a/mode/examples/Basics/Transform/Scale/Scale.pde +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Scale - * by Denis Grutze. - * - * Paramenters for the scale() function are values specified - * as decimal percentages. For example, the method call scale(2.0) - * will increase the dimension of the shape by 200 percent. - * Objects always scale from the origin. - */ - -float a = 0.0; -float s = 0.0; - -void setup() -{ - size(200,200); - noStroke(); - rectMode(CENTER); - frameRate(30); -} - -void draw() -{ - background(102); - - a = a + 0.04; - s = cos(a)*2; - - translate(width/2, height/2); - scale(s); - fill(51); - rect(0, 0, 50, 50); - - translate(75, 0); - fill(255); - scale(s); - rect(0, 0, 50, 50); -} diff --git a/mode/examples/Basics/Transform/Translate/Translate.pde b/mode/examples/Basics/Transform/Translate/Translate.pde deleted file mode 100644 index 81b39af9d..000000000 --- a/mode/examples/Basics/Transform/Translate/Translate.pde +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Translate. - * - * The translate() function allows objects to be moved - * to any location within the window. The first parameter - * sets the x-axis offset and the second parameter sets the - * y-axis offset. - */ - -float x, y; -float size = 40.0; - -void setup() -{ - size(200,200); - noStroke(); - frameRate(30); -} - -void draw() -{ - background(102); - - x = x + 0.8; - - if (x > width + size) { - x = -size; - } - - translate(x, height/2-size/2); - fill(255); - rect(-size/2, -size/2, size, size); - - // Transforms accumulate. - // Notice how this rect moves twice - // as fast as the other, but it has - // the same parameter for the x-axis value - translate(x, size); - fill(0); - rect(-size/2, -size/2, size, size); -} diff --git a/mode/examples/Basics/Transform/TriangleFlower/TriangleFlower.pde b/mode/examples/Basics/Transform/TriangleFlower/TriangleFlower.pde deleted file mode 100644 index e87e97c72..000000000 --- a/mode/examples/Basics/Transform/TriangleFlower/TriangleFlower.pde +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Triangle Flower - * by Ira Greenberg. - * - * Using rotate() and triangle() functions generate a pretty - * flower. Uncomment the line "// rotate(rot+=radians(spin));" - * in the triBlur() function for a nice variation. - * - * Updated 27 February 2010. - */ - -PVector[] p = new PVector[3]; -float shift = 1.0; -float fade = 0; -float fillCol = 0; -float rot = 0; -float spin = 0; - -void setup() { - size(200, 200); - background(0); - smooth(); - fade = 255.0 / (width/2.0/shift); - spin = 360.0 / (width/2.0/shift); - p[0] = new PVector(-width/2, height/2); - p[1] = new PVector(width/2, height/2); - p[2] = new PVector(0, -height/2); - noStroke(); - translate(width/2, height/2); - triBlur(); -} - -void triBlur() { - fill(fillCol); - fillCol += fade; - rotate(spin); - // another interesting variation: uncomment the line below - // rotate(rot+=radians(spin)); - triangle(p[0].x += shift, p[0].y -= shift/2, - p[1].x -= shift, p[1].y -= shift/2, - p[2].x, p[2].y += shift); - if (p[0].x < 0) { - // recursive call - triBlur(); - } -} - diff --git a/mode/examples/Basics/Typography/Letters/Letters.pde b/mode/examples/Basics/Typography/Letters/Letters.pde deleted file mode 100644 index 66fd2302f..000000000 --- a/mode/examples/Basics/Typography/Letters/Letters.pde +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Letters. - * - * Draws letters to the screen. This requires loading a font, - * setting the font, and then drawing the letters. - */ - -PFont fontA; - -void setup() -{ - size(200, 200); - background(0); - smooth(); - // Load the font. Fonts must be placed within the data - // directory of your sketch. A font must first be created - // using the 'Create Font...' option in the Tools menu. - fontA = loadFont("CourierNew36.vlw"); - textAlign(CENTER); - - // Set the font and its size (in units of pixels) - textFont(fontA, 32); - - // Only draw once - noLoop(); -} - -void draw() -{ - // Set the gray value of the letters - fill(255); - - // Set the left and top margin - int margin = 6; - int gap = 30; - translate(margin*1.5, margin*2); - - // Create a matrix of letterforms - int counter = 0; - for(int i=0; i= 26) { - counter = 0; - } - } - } -} - diff --git a/mode/examples/Basics/Typography/Letters/data/CourierNew36.vlw b/mode/examples/Basics/Typography/Letters/data/CourierNew36.vlw deleted file mode 100644 index 904771486..000000000 Binary files a/mode/examples/Basics/Typography/Letters/data/CourierNew36.vlw and /dev/null differ diff --git a/mode/examples/Basics/Typography/Words/Words.pde b/mode/examples/Basics/Typography/Words/Words.pde deleted file mode 100644 index d8e8a5f96..000000000 --- a/mode/examples/Basics/Typography/Words/Words.pde +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Words. - * - * The text() function is used for writing words to the screen. - */ - - -int x = 30; -PFont fontA; - -void setup() -{ - size(200, 200); - background(102); - - // Load the font. Fonts must be placed within the data - // directory of your sketch. Use Tools > Create Font - // to create a distributable bitmap font. - // For vector fonts, use the createFont() function. - fontA = loadFont("Ziggurat-HTF-Black-32.vlw"); - - // Set the font and its size (in units of pixels) - textFont(fontA, 32); - - // Only draw once - noLoop(); -} - -void draw() { - // Use fill() to change the value or color of the text - fill(0); - text("ichi", x, 60); - fill(51); - text("ni", x, 95); - fill(204); - text("san", x, 130); - fill(255); - text("shi", x, 165); -} diff --git a/mode/examples/Basics/Typography/Words/data/Ziggurat-HTF-Black-32.vlw b/mode/examples/Basics/Typography/Words/data/Ziggurat-HTF-Black-32.vlw deleted file mode 100644 index 84c2d4b59..000000000 Binary files a/mode/examples/Basics/Typography/Words/data/Ziggurat-HTF-Black-32.vlw and /dev/null differ diff --git a/mode/examples/Basics/Web/EmbeddedLinks/EmbeddedLinks.pde b/mode/examples/Basics/Web/EmbeddedLinks/EmbeddedLinks.pde deleted file mode 100644 index 2501487e3..000000000 --- a/mode/examples/Basics/Web/EmbeddedLinks/EmbeddedLinks.pde +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Loading URLs. - * - * Click on the left button to open a different URL in the same window (Only - * works online). Click on the right button to open a URL in a new browser window. -*/ - -boolean overLeftButton = false; -boolean overRightButton = false; - -void setup() { - size(200, 200); -} - -void draw() { - background(204); - - // Left buttom - if (overLeftButton == true) { - fill(255); - } else { - noFill(); - } - rect(20, 60, 75, 75); - rect(50, 90, 15, 15); - - // Right button - if (overRightButton == true) { - fill(255); - } else { - noFill(); - } - rect(105, 60, 75, 75); - line(135, 105, 155, 85); - line(140, 85, 155, 85); - line(155, 85, 155, 100); -} - -void mousePressed() { - if (overLeftButton) { - link("http://www.processing.org"); - } else if (overRightButton) { - link("http://www.processing.org", "_new"); - } -} - -void mouseMoved() { - checkButtons(); -} - -void mouseDragged() { - checkButtons(); -} - -void checkButtons() { - if (mouseX > 20 && mouseX < 95 && mouseY > 60 && mouseY < 135) { - overLeftButton = true; - } else if (mouseX > 105 && mouseX < 180 && mouseY > 60 && mouseY <135) { - overRightButton = true; - } else { - overLeftButton = overRightButton = false; - } -} - - - - diff --git a/mode/examples/Basics/Web/LoadingImages/LoadingImages.pde b/mode/examples/Basics/Web/LoadingImages/LoadingImages.pde deleted file mode 100644 index e2a958d22..000000000 --- a/mode/examples/Basics/Web/LoadingImages/LoadingImages.pde +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Loading Images. - * - * Loads an image from over the network. Be sure to have INTERNET - * permission enabled, otherwise img will always return null. - */ - -size(200, 200); -PImage img1; -img1 = loadImage("http://processing.org/img/processing_cover.gif"); -if (img != null) { - image(img1, 0, 0); -} diff --git a/mode/examples/Demos/Graphics/Particles/Particle.pde b/mode/examples/Demos/Graphics/Particles/Particle.pde deleted file mode 100644 index b205887c8..000000000 --- a/mode/examples/Demos/Graphics/Particles/Particle.pde +++ /dev/null @@ -1,59 +0,0 @@ -class Particle { - - PVector velocity; - float lifespan = 255; - - PShape part; - float partSize; - - PVector gravity = new PVector(0,0.1); - - - Particle() { - partSize = random(10,60); - part = createShape(); - part.beginShape(QUAD); - part.noStroke(); - part.texture(sprite); - part.normal(0, 0, 1); - part.vertex(-partSize/2, -partSize/2, 0, 0); - part.vertex(+partSize/2, -partSize/2, sprite.width, 0); - part.vertex(+partSize/2, +partSize/2, sprite.width, sprite.height); - part.vertex(-partSize/2, +partSize/2, 0, sprite.height); - part.endShape(); - - rebirth(width/2,height/2); - lifespan = random(255); - } - - PShape getShape() { - return part; - } - - void rebirth(float x, float y) { - float a = random(TWO_PI); - float speed = random(0.5,4); - velocity = new PVector(cos(a), sin(a)); - velocity.mult(speed); - lifespan = 255; - part.resetMatrix(); - part.translate(x, y); - } - - boolean isDead() { - if (lifespan < 0) { - return true; - } else { - return false; - } - } - - - public void update() { - lifespan = lifespan - 1; - velocity.add(gravity); - - part.setTint(color(255,lifespan)); - part.translate(velocity.x, velocity.y); - } -} diff --git a/mode/examples/Demos/Graphics/Particles/ParticleSystem.pde b/mode/examples/Demos/Graphics/Particles/ParticleSystem.pde deleted file mode 100644 index 0d164dcd7..000000000 --- a/mode/examples/Demos/Graphics/Particles/ParticleSystem.pde +++ /dev/null @@ -1,36 +0,0 @@ -class ParticleSystem { - ArrayList particles; - - PShape particleShape; - - ParticleSystem(int n) { - particles = new ArrayList(); - particleShape = createShape(PShape.GROUP); - - for (int i = 0; i < n; i++) { - Particle p = new Particle(); - particles.add(p); - particleShape.addChild(p.getShape()); - } - } - - void update() { - for (Particle p : particles) { - p.update(); - } - } - - void setEmitter(float x, float y) { - for (Particle p : particles) { - if (p.isDead()) { - p.rebirth(x, y); - } - } - } - - void display() { - - shape(particleShape); - } -} - diff --git a/mode/examples/Demos/Graphics/Particles/Particles.pde b/mode/examples/Demos/Graphics/Particles/Particles.pde deleted file mode 100644 index 4d9cd03e6..000000000 --- a/mode/examples/Demos/Graphics/Particles/Particles.pde +++ /dev/null @@ -1,30 +0,0 @@ -// Particles, by Daniel Shiffman - -ParticleSystem ps; -PImage sprite; - -void setup() { - size(displayWidth, displayHeight, P2D); - orientation(LANDSCAPE); - sprite = loadImage("sprite.png"); - ps = new ParticleSystem(2000); - - // Writing to the depth buffer is disabled to avoid rendering - // artifacts due to the fact that the particles are semi-transparent - // but not z-sorted. - hint(DISABLE_DEPTH_MASK); -} - -void draw () { - background(0); - ps.update(); - ps.display(); - - ps.setEmitter(mouseX,mouseY); - - fill(255); - textSize(16); - text("Frame rate: " + int(frameRate),10,20); -} - - diff --git a/mode/examples/Demos/Graphics/Particles/data/sprite.png b/mode/examples/Demos/Graphics/Particles/data/sprite.png deleted file mode 100644 index cc0f45cba..000000000 Binary files a/mode/examples/Demos/Graphics/Particles/data/sprite.png and /dev/null differ diff --git a/mode/examples/Demos/Graphics/Patch/Patch.pde b/mode/examples/Demos/Graphics/Patch/Patch.pde deleted file mode 100644 index 2b11d6f3a..000000000 --- a/mode/examples/Demos/Graphics/Patch/Patch.pde +++ /dev/null @@ -1,162 +0,0 @@ -// Bezier patch By Maritus Watz: -// http://www.openprocessing.org/sketch/57709 -// Normal calculation added by Andres Colubri -// Direct port of sample code by Paul Bourke. -// Original code: http://paulbourke.net/geometry/bezier/ - -int ni=3, nj=4, RESI=ni*10, RESJ=nj*10; -PVector outp[][], inp[][]; -PVector normp[][]; -boolean autoNormals = false; - -void setup() { - size(displayWidth, displayHeight, P3D); - orientation(LANDSCAPE); - build(); -} - -void draw() { - background(255); - translate(width/2,height/2); - lights(); - scale(0.9); - rotateY(map(mouseX,0,width,-PI,PI)); - rotateX(map(mouseY,0,height,-PI,PI)); - - noStroke(); - fill(255); - for(int i=0; i= 1) { - blend *= nn; - nn--; - if (kn > 1) { - blend /= (double)kn; - kn--; - } - if (nkn > 1) { - blend /= (double)nkn; - nkn--; - } - } - if (k > 0) - blend *= Math.pow(mu, (double)k); - if (n-k > 0) - blend *= Math.pow(1-mu, (double)(n-k)); - - return(blend); -} - -double DBezierBlend(int k, double mu, int n) { - int nn, kn, nkn; - double dblendf = 1; - - nn = n; - kn = k; - nkn = n - k; - - while (nn >= 1) { - dblendf *= nn; - nn--; - if (kn > 1) { - dblendf /= (double)kn; - kn--; - } - if (nkn > 1) { - dblendf /= (double)nkn; - nkn--; - } - } - - double fk = 1; - double dk = 0; - double fnk = 1; - double dnk = 0; - if (k > 0) { - fk = Math.pow(mu, (double)k); - dk = k*Math.pow(mu, (double)k-1); - } - if (n-k > 0) { - fnk = Math.pow(1-mu, (double)(n-k)); - dnk = (k-n)*Math.pow(1-mu, (double)(n-k-1)); - } - dblendf *= (dk * fnk + fk * dnk); - - return(dblendf); -} diff --git a/mode/examples/Demos/Graphics/Planets/Perlin.pde b/mode/examples/Demos/Graphics/Planets/Perlin.pde deleted file mode 100644 index 20963499d..000000000 --- a/mode/examples/Demos/Graphics/Planets/Perlin.pde +++ /dev/null @@ -1,261 +0,0 @@ -// Implementation of 1D, 2D, and 3D Perlin noise. Based on the -// C code by Paul Bourke: -// http://local.wasp.uwa.edu.au/~pbourke/texture_colour/perlin/ -class Perlin { - int B = 0x100; - int BM = 0xff; - int N = 0x1000; - int NP = 12; - int NM = 0xfff; - - int p[]; - float g3[][]; - float g2[][]; - float g1[]; - - void normalize2(float v[]) { - float s = sqrt(v[0] * v[0] + v[1] * v[1]); - v[0] = v[0] / s; - v[1] = v[1] / s; - } - - void normalize3(float v[]) { - float s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); - v[0] = v[0] / s; - v[1] = v[1] / s; - v[2] = v[2] / s; - } - - float sCurve(float t) { - return t * t * (3.0 - 2.0 * t); - } - - float at2(float q[], float rx, float ry) { - return rx * q[0] + ry * q[1]; - } - - float at3(float q[], float rx, float ry, float rz) { - return rx * q[0] + ry * q[1] + rz * q[2]; - } - - Perlin() { - p = new int[B + B + 2]; - g3 = new float[B + B + 2][3]; - g2 = new float[B + B + 2][2]; - g1 = new float[B + B + 2]; - - init(); - } - - void init() { - int i, j, k; - - for (i = 0 ; i < B ; i++) { - p[i] = i; - g1[i] = (random(B + B) - B) / B; - - for (j = 0 ; j < 2 ; j++) - g2[i][j] = (random(B + B) - B) / B; - normalize2(g2[i]); - - for (j = 0 ; j < 3 ; j++) - g3[i][j] = (random(B + B) - B) / B; - normalize3(g3[i]); - } - - while (0 < --i) { - k = p[i]; - p[i] = p[j = int(random(B))]; - p[j] = k; - } - - for (i = 0 ; i < B + 2 ; i++) { - p[B + i] = p[i]; - g1[B + i] = g1[i]; - for (j = 0 ; j < 2 ; j++) - g2[B + i][j] = g2[i][j]; - for (j = 0 ; j < 3 ; j++) - g3[B + i][j] = g3[i][j]; - } - } - - float noise1(float[] vec) { - int bx0, bx1; - float rx0, rx1, sx, t, u, v; - - t = vec[0] + N; - bx0 = int(t) & BM; - bx1 = (bx0 + 1) & BM; - rx0 = t - int(t); - rx1 = rx0 - 1.0; - - sx = sCurve(rx0); - u = rx0 * g1[p[bx0]]; - v = rx1 * g1[p[bx1]]; - - return lerp(u, v, sx); - } - - float noise2(float[] vec) { - int bx0, bx1, by0, by1, b00, b10, b01, b11; - float rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v; - float[] q; - int i, j; - - t = vec[0] + N; - bx0 = int(t) & BM; - bx1 = (bx0 + 1) & BM; - rx0 = t - int(t); - rx1 = rx0 - 1.0; - - t = vec[1] + N; - by0 = int(t) & BM; - by1 = (by0 + 1) & BM; - ry0 = t - int(t); - ry1 = ry0 - 1.0; - - i = p[bx0]; - j = p[bx1]; - - b00 = p[i + by0]; - b10 = p[j + by0]; - b01 = p[i + by1]; - b11 = p[j + by1]; - - sx = sCurve(rx0); - sy = sCurve(ry0); - - q = g2[b00]; - u = at2(q, rx0, ry0); - q = g2[b10]; - v = at2(q, rx1, ry0); - a = lerp(u, v, sx); - - q = g2[b01] ; - u = at2(q, rx0, ry1); - q = g2[b11] ; - v = at2(q, rx1, ry1); - b = lerp(u, v, sx); - - return lerp(a, b, sy); - } - - float noise3(float[] vec) { - int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; - float rx0, rx1, ry0, ry1, rz0, rz1, sy, sz, a, b, c, d, t, u, v; - float[] q; - int i, j; - - t = vec[0] + N; - bx0 = int(t) & BM; - bx1 = (bx0 + 1) & BM; - rx0 = t - int(t); - rx1 = rx0 - 1.0; - - t = vec[1] + N; - by0 = int(t) & BM; - by1 = (by0 + 1) & BM; - ry0 = t - int(t); - ry1 = ry0 - 1.0; - - t = vec[2] + N; - bz0 = int(t) & BM; - bz1 = (bz0 + 1) & BM; - rz0 = t - int(t); - rz1 = rz0 - 1.0; - - i = p[bx0]; - j = p[bx1]; - - b00 = p[i + by0]; - b10 = p[j + by0]; - b01 = p[i + by1]; - b11 = p[j + by1]; - - t = sCurve(rx0); - sy = sCurve(ry0); - sz = sCurve(rz0); - - q = g3[b00 + bz0]; - u = at3(q, rx0, ry0, rz0); - q = g3[b10 + bz0]; - v = at3(q, rx1, ry0, rz0); - a = lerp(u, v, t); - - q = g3[b01 + bz0]; - u = at3(q, rx0, ry1, rz0); - q = g3[b11 + bz0]; - v = at3(q, rx1, ry1, rz0); - b = lerp(u, v, t); - - c = lerp(a, b, sy); - - q = g3[b00 + bz1]; - u = at3(q, rx0, ry0, rz1); - q = g3[b10 + bz1]; - v = at3(q, rx1, ry0, rz1); - a = lerp(u, v, t); - - q = g3[b01 + bz1]; - u = at3(q, rx0, ry1, rz1); - q = g3[b11 + bz1]; - v = at3(q, rx1, ry1, rz1); - b = lerp(u, v, t); - - d = lerp(a, b, sy); - - return lerp(c, d, sz); - } - - // In what follows "nalpha" is the weight when the sum is formed. - // Typically it is 2, as this approaches 1 the function is noisier. - // "nbeta" is the harmonic scaling/spacing, typically 2. n is the - // number of harmonics added up in the final result. Higher number - // results in more detailed noise. - - float noise1D(float x, float nalpha, float nbeta, int n) { - float val, sum = 0; - float v[] = {x}; - float nscale = 1; - - for (int i = 0; i < n; i++) { - val = noise1(v); - sum += val / nscale; - nscale *= nalpha; - v[0] *= nbeta; - } - return sum; - } - - float noise2D(float x, float y, float nalpha, float nbeta, int n) { - float val,sum = 0; - float v[] = {x, y}; - float nscale = 1; - - for (int i = 0; i < n; i++) { - val = noise2(v); - sum += val / nscale; - nscale *= nalpha; - v[0] *= nbeta; - v[1] *= nbeta; - } - return sum; - } - - float noise3D(float x, float y, float z, float nalpha, float nbeta, int n) { - float val, sum = 0; - float v[] = {x, y, z}; - float nscale = 1; - - for (int i = 0 ; i < n; i++) { - val = noise3(v); - sum += val / nscale; - nscale *= nalpha; - v[0] *= nbeta; - v[1] *= nbeta; - v[2] *= nbeta; - } - return sum; - } -} - diff --git a/mode/examples/Demos/Graphics/Planets/Planets.pde b/mode/examples/Demos/Graphics/Planets/Planets.pde deleted file mode 100644 index 7c74f9738..000000000 --- a/mode/examples/Demos/Graphics/Planets/Planets.pde +++ /dev/null @@ -1,123 +0,0 @@ -// Planets, by Andres Colubri -// -// Sun and mercury textures from http://planetpixelemporium.com -// Star field picture from http://www.galacticimages.com/ - -PImage starfield; - -PShape sun; -PImage suntex; - -PShape planet1; -PImage surftex1; -PImage cloudtex; - -PShape planet2; -PImage surftex2; - -void setup() { - size(800, 480, P3D); - orientation(LANDSCAPE); - - starfield = loadImage("starfield.jpg"); - suntex = loadImage("sun.jpg"); - surftex1 = loadImage("planet.jpg"); - - // We need trilinear sampling for this texture so it looks good - // even when rendered very small. - //PTexture.Parameters params1 = PTexture.newParameters(ARGB, TRILINEAR); - surftex2 = loadImage("mercury.jpg"); - - /* - // The clouds texture will "move" having the values of its u - // texture coordinates displaced by adding a constant increment - // in each frame. This requires REPEAT wrapping mode so texture - // coordinates can be larger than 1. - //PTexture.Parameters params2 = PTexture.newParameters(); - //params2.wrapU = REPEAT; - cloudtex = createImage(512, 256); - - // Using 3D Perlin noise to generate a clouds texture that is seamless on - // its edges so it can be applied on a sphere. - cloudtex.loadPixels(); - Perlin perlin = new Perlin(); - for (int j = 0; j < cloudtex.height; j++) { - for (int i = 0; i < cloudtex.width; i++) { - // The angle values corresponding to each u,v pair: - float u = float(i) / cloudtex.width; - float v = float(j) / cloudtex.height; - float phi = map(u, 0, 1, TWO_PI, 0); - float theta = map(v, 0, 1, -HALF_PI, HALF_PI); - // The x, y, z point corresponding to these angles: - float x = cos(phi) * cos(theta); - float y = sin(theta); - float z = sin(phi) * cos(theta); - float n = perlin.noise3D(x, y, z, 1.2, 2, 8); - cloudtex.pixels[j * cloudtex.width + i] = color(255, 255, 255, 255 * n * n); - } - } - cloudtex.updatePixels(); - */ - - noStroke(); - fill(255); - sphereDetail(30); - - sun = createShape(SPHERE, 150); - sun.texture(suntex); - - planet1 = createShape(SPHERE, 150); - planet1.texture(surftex1); - - planet2 = createShape(SPHERE, 50); - planet2.texture(surftex2); -} - -void draw() { - // Even we draw a full screen image after this, it is recommended to use - // background to clear the screen anyways, otherwise A3D will think - // you want to keep each drawn frame in the framebuffer, which results in - // slower rendering. - background(0); - - // Disabling writing to the depth mask so the - // background image doesn't occludes any 3D object. - hint(DISABLE_DEPTH_MASK); - image(starfield, 0, 0, width, height); - hint(ENABLE_DEPTH_MASK); - - /* - // Displacing the u texture coordinate of layer 1 in planet - // so it creates the effect of moving clouds. - PShape3D p = (PShape3D)planet1; - p.loadTexcoords(1); - for (int i = 0; i < p.getVertexCount(); i++) { - float u = p.texcoords[2 * i + 0]; - u += 0.002; - p.texcoords[2 * i + 0] = u; - } - p.updateTexcoords(); - */ - - pushMatrix(); - translate(width/2, height/2, -300); - - pushMatrix(); - rotateY(PI * frameCount / 500); - shape(sun); - popMatrix(); - - pointLight(255, 255, 255, 0, 0, 0); - rotateY(PI * frameCount / 300); - translate(0, 0, 300); - - shape(planet2); - - popMatrix(); - - noLights(); - pointLight(255, 255, 255, 0, 0, -150); - - translate(0.75 * width, 0.6 * height, 50); - shape(planet1); -} diff --git a/mode/examples/Demos/Graphics/Planets/data/mercury.jpg b/mode/examples/Demos/Graphics/Planets/data/mercury.jpg deleted file mode 100644 index 9bb2c0be0..000000000 Binary files a/mode/examples/Demos/Graphics/Planets/data/mercury.jpg and /dev/null differ diff --git a/mode/examples/Demos/Graphics/Planets/data/planet.jpg b/mode/examples/Demos/Graphics/Planets/data/planet.jpg deleted file mode 100644 index 8fd33bf9b..000000000 Binary files a/mode/examples/Demos/Graphics/Planets/data/planet.jpg and /dev/null differ diff --git a/mode/examples/Demos/Graphics/Planets/data/starfield.jpg b/mode/examples/Demos/Graphics/Planets/data/starfield.jpg deleted file mode 100644 index bf190dfb0..000000000 Binary files a/mode/examples/Demos/Graphics/Planets/data/starfield.jpg and /dev/null differ diff --git a/mode/examples/Demos/Graphics/Planets/data/sun.jpg b/mode/examples/Demos/Graphics/Planets/data/sun.jpg deleted file mode 100644 index 46d7beae6..000000000 Binary files a/mode/examples/Demos/Graphics/Planets/data/sun.jpg and /dev/null differ diff --git a/mode/examples/Demos/Graphics/Ribbons/ArcBall.pde b/mode/examples/Demos/Graphics/Ribbons/ArcBall.pde deleted file mode 100644 index 5c4f74cc2..000000000 --- a/mode/examples/Demos/Graphics/Ribbons/ArcBall.pde +++ /dev/null @@ -1,190 +0,0 @@ -// Ariel and V3ga's arcball class with a couple tiny mods by Robert Hodgin - -class Arcball { - float center_x, center_y, radius; - Vec3 v_down, v_drag; - Quat q_now, q_down, q_drag; - Vec3[] axisSet; - int axis; - float mxv, myv; - float x, y; - - Arcball(float center_x, float center_y, float radius){ - this.center_x = center_x; - this.center_y = center_y; - this.radius = radius; - - v_down = new Vec3(); - v_drag = new Vec3(); - - q_now = new Quat(); - q_down = new Quat(); - q_drag = new Quat(); - - axisSet = new Vec3[] {new Vec3(1.0f, 0.0f, 0.0f), new Vec3(0.0f, 1.0f, 0.0f), new Vec3(0.0f, 0.0f, 1.0f)}; - axis = -1; // no constraints... - } - - void mousePressed(){ - v_down = mouse_to_sphere(mouseX, mouseY); - q_down.set(q_now); - q_drag.reset(); - } - - void mouseDragged(){ - v_drag = mouse_to_sphere(mouseX, mouseY); - q_drag.set(Vec3.dot(v_down, v_drag), Vec3.cross(v_down, v_drag)); - } - - void run(){ - q_now = Quat.mul(q_drag, q_down); - applyQuat2Matrix(q_now); - - x += mxv; - y += myv; - mxv -= mxv * .01; - myv -= myv * .01; - } - - Vec3 mouse_to_sphere(float x, float y){ - Vec3 v = new Vec3(); - v.x = (x - center_x) / radius; - v.y = (y - center_y) / radius; - - float mag = v.x * v.x + v.y * v.y; - if (mag > 1.0f){ - v.normalize(); - } else { - v.z = sqrt(1.0f - mag); - } - - return (axis == -1) ? v : constrain_vector(v, axisSet[axis]); - } - - Vec3 constrain_vector(Vec3 vector, Vec3 axis){ - Vec3 res = new Vec3(); - res.sub(vector, Vec3.mul(axis, Vec3.dot(axis, vector))); - res.normalize(); - return res; - } - - void applyQuat2Matrix(Quat q){ - // instead of transforming q into a matrix and applying it... - - float[] aa = q.getValue(); - rotate(aa[0], aa[1], aa[2], aa[3]); - } -} - -static class Vec3{ - float x, y, z; - - Vec3(){ - } - - Vec3(float x, float y, float z){ - this.x = x; - this.y = y; - this.z = z; - } - - void normalize(){ - float length = length(); - x /= length; - y /= length; - z /= length; - } - - float length(){ - return (float) Math.sqrt(x * x + y * y + z * z); - } - - static Vec3 cross(Vec3 v1, Vec3 v2){ - Vec3 res = new Vec3(); - res.x = v1.y * v2.z - v1.z * v2.y; - res.y = v1.z * v2.x - v1.x * v2.z; - res.z = v1.x * v2.y - v1.y * v2.x; - return res; - } - - static float dot(Vec3 v1, Vec3 v2){ - return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; - } - - static Vec3 mul(Vec3 v, float d){ - Vec3 res = new Vec3(); - res.x = v.x * d; - res.y = v.y * d; - res.z = v.z * d; - return res; - } - - void sub(Vec3 v1, Vec3 v2){ - x = v1.x - v2.x; - y = v1.y - v2.y; - z = v1.z - v2.z; - } -} - -static class Quat{ - float w, x, y, z; - - Quat(){ - reset(); - } - - Quat(float w, float x, float y, float z){ - this.w = w; - this.x = x; - this.y = y; - this.z = z; - } - - void reset(){ - w = 1.0f; - x = 0.0f; - y = 0.0f; - z = 0.0f; - } - - void set(float w, Vec3 v){ - this.w = w; - x = v.x; - y = v.y; - z = v.z; - } - - void set(Quat q){ - w = q.w; - x = q.x; - y = q.y; - z = q.z; - } - - static Quat mul(Quat q1, Quat q2){ - Quat res = new Quat(); - res.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; - res.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y; - res.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z; - res.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x; - return res; - } - - float[] getValue(){ - // transforming this quat into an angle and an axis vector... - - float[] res = new float[4]; - - float sa = (float) Math.sqrt(1.0f - w * w); - if (sa < EPSILON){ - sa = 1.0f; - } - - res[0] = (float) Math.acos(w) * 2.0f; - res[1] = x / sa; - res[2] = y / sa; - res[3] = z / sa; - - return res; - } -} diff --git a/mode/examples/Demos/Graphics/Ribbons/BSpline.pde b/mode/examples/Demos/Graphics/Ribbons/BSpline.pde deleted file mode 100644 index b622e8498..000000000 --- a/mode/examples/Demos/Graphics/Ribbons/BSpline.pde +++ /dev/null @@ -1,307 +0,0 @@ -final int MAX_BEZIER_ORDER = 10; // Maximum curve order. - -final float[][] BSplineMatrix = { - {-1.0/6.0, 1.0/2.0, -1.0/2.0, 1.0/6.0}, - { 1.0/2.0, -1.0, 1.0/2.0, 0.0}, - {-1.0/2.0, 0.0, 1.0/2.0, 0.0}, - { 1.0/6.0, 2.0/3.0, 1.0/6.0, 0.0} -}; - -// The element(i, n) of this array contains the binomial coefficient -// C(i, n) = n!/(i!(n-i)!) -final int[][] BinomialCoefTable = { - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, - {0, 1, 3, 6, 10, 15, 21, 28, 36, 45}, - {0, 0, 1, 4, 10, 20, 35, 56, 84, 120}, - {0, 0, 0, 1, 5, 15, 35, 70, 126, 210}, - {0, 0, 0, 0, 1, 6, 21, 56, 126, 252}, - {0, 0, 0, 0, 0, 1, 7, 28, 84, 210}, - {0, 0, 0, 0, 0, 0, 1, 8, 36, 120}, - {0, 0, 0, 0, 0, 0, 0, 1, 9, 45}, - {0, 0, 0, 0, 0, 0, 0, 0, 1, 10}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1} -}; - -// The element of this(i, j) of this table contains(i/10)^(3-j). -final float[][] TVectorTable = { -// t^3, t^2, t^1, t^0 - { 0, 0, 0, 1}, // t = 0.0 - {0.001, 0.01, 0.1, 1}, // t = 0.1 - {0.008, 0.04, 0.2, 1}, // t = 0.2 - {0.027, 0.09, 0.3, 1}, // t = 0.3 - {0.064, 0.16, 0.4, 1}, // t = 0.4 - {0.125, 0.25, 0.5, 1}, // t = 0.5 - {0.216, 0.36, 0.6, 1}, // t = 0.6 - {0.343, 0.49, 0.7, 1}, // t = 0.7 - {0.512, 0.64, 0.8, 1}, // u = 0.8 - {0.729, 0.81, 0.9, 1}, // t = 0.9 - { 1, 1, 1, 1} // t = 1.0 -}; - -// The element of this(i, j) of this table contains(3-j)*(i/10)^(2-j) if -// j < 3, 0 otherwise. -final float[][] DTVectorTable = { -// 3t^2, 2t^1, t^0 - { 0, 0, 1, 0}, // t = 0.0 - {0.03, 0.2, 1, 0}, // t = 0.1 - {0.12, 0.4, 1, 0}, // t = 0.2 - {0.27, 0.6, 1, 0}, // t = 0.3 - {0.48, 0.8, 1, 0}, // t = 0.4 - {0.75, 1.0, 1, 0}, // t = 0.5 - {1.08, 1.2, 1, 0}, // t = 0.6 - {1.47, 1.4, 1, 0}, // t = 0.7 - {1.92, 1.6, 1, 0}, // t = 0.8 - {2.43, 1.8, 1, 0}, // t = 0.9 - { 3, 2, 1, 0} // t = 1.0 -}; - -abstract class Curve3D { - abstract void feval(float t, PVector p); - abstract void deval(float t, PVector d); - abstract float fevalX(float t); - abstract float fevalY(float t); - abstract float fevalZ(float t); - abstract float devalX(float t); - abstract float devalY(float t); - abstract float devalZ(float t); -} - -abstract class Spline extends Curve3D { - // The factorial of n. - int factorial(int n) { - return n <= 0 ? 1 : n * factorial(n - 1); - } - - // Gives n!/(i!(n-i)!). - int binomialCoef(int i, int n) { - if ((i <= MAX_BEZIER_ORDER) && (n <= MAX_BEZIER_ORDER)) return BinomialCoefTable[i][n - 1]; - else return int(factorial(n) / (factorial(i) * factorial(n - i))); - } - - // Evaluates the Berstein polinomial(i, n) at u. - float bersteinPol(int i, int n, float u) { - return binomialCoef(i, n) * pow(u, i) * pow(1 - u, n - i); - } - - // The derivative of the Berstein polinomial. - float dbersteinPol(int i, int n, float u) { - float s1, s2; - if (i == 0) s1 = 0; - else s1 = i * pow(u, i-1) * pow(1 - u, n - i); - if (n == i) s2 = 0; - else s2 = -(n - i) * pow(u, i) * pow(1 - u, n - i - 1); - return binomialCoef(i, n) *(s1 + s2); - } -} - -class BSpline extends Spline { - // Control points. - float[][] bsplineCPoints; - - // Parameters. - boolean lookup; - - // Auxiliary arrays used in the calculations. - float[][] M3; - float[] TVector, DTVector; - - // Point and tangent vectors. - float[] pt, tg; - - BSpline() { - initParameters(true); - } - - BSpline(boolean t) { - initParameters(t); - } - - // Sets lookup table use. - void initParameters(boolean t) { - bsplineCPoints = new float[4][3]; - TVector = new float[4]; - DTVector = new float[4]; - M3 = new float[4][3]; - pt = new float[3]; - tg = new float[3]; - lookup = t; - } - - // Sets n-th control point. - void setCPoint(int n, PVector P) { - bsplineCPoints[n][0] = P.x; - bsplineCPoints[n][1] = P.y; - bsplineCPoints[n][2] = P.z; - updateMatrix3(); - } - - // Gets n-th control point. - void getCPoint(int n, PVector P) { - P.set(bsplineCPoints[n]); - } - - // Replaces the current B-spline control points(0, 1, 2) with(1, 2, 3). This - // is used when a new spline is to be joined to the recently drawn. - void shiftBSplineCPoints() { - for (int i = 0; i < 3; i++) { - bsplineCPoints[0][i] = bsplineCPoints[1][i]; - bsplineCPoints[1][i] = bsplineCPoints[2][i]; - bsplineCPoints[2][i] = bsplineCPoints[3][i]; - } - updateMatrix3(); - } - - void copyCPoints(int n_source, int n_dest) { - for (int i = 0; i < 3; i++) { - bsplineCPoints[n_dest][i] = bsplineCPoints[n_source][i]; - } - } - - // Updates the temporal matrix used in order 3 calculations. - void updateMatrix3() { - float s; - int i, j, k; - for(i = 0; i < 4; i++) { - for(j = 0; j < 3; j++) { - s = 0; - for(k = 0; k < 4; k++) s += BSplineMatrix[i][k] * bsplineCPoints[k][j]; - M3[i][j] = s; - } - } - } - - void feval(float t, PVector p) { - evalPoint(t); - p.set(pt); - } - - void deval(float t, PVector d) { - evalTangent(t); - d.set(tg); - } - - float fevalX(float t) { - evalPoint(t); - return pt[0]; - } - - float fevalY(float t) { - evalPoint(t); - return pt[1]; - } - - float fevalZ(float t) { - evalPoint(t); - return pt[2]; - } - - float devalX(float t) { - evalTangent(t); - return tg[0]; - } - - float devalY(float t) { - evalTangent(t); - return tg[1]; - } - - float devalZ(float t) { - evalTangent(t); - return tg[2]; - } - - // Point evaluation. - void evalPoint(float t) { - if (lookup) { - bsplinePointI(int(10 * t)); - } else { - bsplinePoint(t); - } - } - - // Tangent evaluation. - void evalTangent(float t) { - if (lookup) { - bsplineTangentI(int(10 * t)); - } else { - bsplineTangent(t); - } - } - - // Calculates the point on the cubic spline corresponding to the parameter value t in [0, 1]. - void bsplinePoint(float t) { - // Q(u) = UVector * BSplineMatrix * BSplineCPoints - - float s; - int i, j, k; - - for(i = 0; i < 4; i++) { - TVector[i] = pow(t, 3 - i); - } - - for(j = 0; j < 3; j++) { - s = 0; - for(k = 0; k < 4; k++) { - s += TVector[k] * M3[k][j]; - } - pt[j] = s; - } - } - - // Calculates the tangent vector of the spline at t. - void bsplineTangent(float t) { - // Q(u) = DTVector * BSplineMatrix * BSplineCPoints - - float s; - int i, j, k; - - for(i = 0; i < 4; i++) { - if (i < 3) { - DTVector[i] = (3 - i) * pow(t, 2 - i); - } else { - DTVector[i] = 0; - } - } - - for(j = 0; j < 3; j++) { - s = 0; - for(k = 0; k < 4; k++) { - s += DTVector[k] * M3[k][j]; - } - tg[j] = s; - } - } - - // Gives the point on the cubic spline corresponding to t/10(using the lookup table). - void bsplinePointI(int t) { - // Q(u) = TVectorTable[u] * BSplineMatrix * BSplineCPoints - - float s; - int j, k; - - for(j = 0; j < 3; j++) { - s = 0; - for(k = 0; k < 4; k++) { - s += TVectorTable[t][k] * M3[k][j]; - } - pt[j] = s; - } - } - - // Calulates the tangent vector of the spline at t/10. - void bsplineTangentI(int t) { - // Q(u) = DTVectorTable[u] * BSplineMatrix * BSplineCPoints - - float s; - int j, k; - - for(j = 0; j < 3; j++) { - s = 0; - for(k = 0; k < 4; k++) { - s += DTVectorTable[t][k] * M3[k][j]; - } - tg[j] = s; - } - } -} diff --git a/mode/examples/Demos/Graphics/Ribbons/Geometry.pde b/mode/examples/Demos/Graphics/Ribbons/Geometry.pde deleted file mode 100644 index 302b0f413..000000000 --- a/mode/examples/Demos/Graphics/Ribbons/Geometry.pde +++ /dev/null @@ -1,497 +0,0 @@ -BSpline splineSide1; -BSpline splineCenter; -BSpline splineSide2; -PVector flipTestV; -int uspacing; - -int HELIX = 0; -int STRAND = 1; -int COIL = 2; -int LHANDED = -1; -int RHANDED = 1; - -void createRibbonModel(ArrayList residues, PShape model, ArrayList trj) { - // For line ribbons - ArrayList vertices0 = new ArrayList(); - ArrayList vertices1 = new ArrayList(); - ArrayList vertices2 = new ArrayList(); - - // For flat ribbons - ArrayList vertices = new ArrayList(); - ArrayList normals = new ArrayList(); - - if (ribbonDetail == 1) uspacing = 10; - else if (ribbonDetail == 2) uspacing = 5; - else if (ribbonDetail == 3) uspacing = 2; - else uspacing = 1; - - flipTestV = new PVector(); - splineSide1 = new BSpline(false); - splineCenter = new BSpline(false); - splineSide2 = new BSpline(false); - - int[] ss = new int[residues.size()]; - int[] handness = new int[residues.size()]; - - calculateSecStr(residues, ss, handness); - - for (int i = 0; i < residues.size(); i++) { - constructControlPoints(residues, i, ss[i], handness[i]); - - if (renderMode == 0) { - generateSpline(0, vertices0); - generateSpline(1, vertices1); - generateSpline(2, vertices2); - } - else { - generateFlatRibbon(vertices, normals); - } - } - - if (renderMode == 0) { - model = createShape(); - model.beginShape(); - model.stroke(ribbonColor); - model.noFill(); - model.beginContour(); - for (int i = 0; i < vertices0.size(); i++) { - PVector posVec = (PVector)vertices0.get(i); - model.vertex(posVec.x, posVec.y, posVec.z); - } - model.endContour(); - model.beginContour(); - for (int i = 0; i < vertices1.size(); i++) { - PVector posVec = (PVector)vertices1.get(i); - model.vertex(posVec.x, posVec.y, posVec.z); - } - model.endContour(); - model.beginContour(); - for (int i = 0; i < vertices2.size(); i++) { - PVector posVec = (PVector)vertices2.get(i); - model.vertex(posVec.x, posVec.y, posVec.z); - } - model.endContour(); - model.endShape(OPEN); - } else { - // The ribbon construction is fairly inneficient here, since - // it could use triangle strips instead to avoid duplicating - // shared vertices... - model = createShape(); - model.beginShape(TRIANGLES); - model.noStroke(); - model.fill(ribbonColor); - for (int i = 0; i < vertices.size(); i++) { - PVector posVec = (PVector)vertices.get(i); - PVector normVec = (PVector)normals.get(i); - model.normal(-normVec.x, -normVec.y, -normVec.z); - model.vertex(posVec.x, posVec.y, posVec.z); - } - model.endShape(); - } - - trj.add(model); - - if (renderMode == 0) { - int totCount = vertices0.size() + vertices1.size() + vertices2.size(); - println("Adding new model with " + totCount + " vertices."); - } else { - println("Adding new model with " + vertices.size() + " vertices."); - } -} - -float calculateGyrRadius(ArrayList atoms) { - PVector ati, atj; - float dx, dy, dz; - float r = 0; - for (int i = 0; i < atoms.size(); i++) { - ati = (PVector)atoms.get(i); - for (int j = i + 1; j < atoms.size(); j++) { - atj = (PVector)atoms.get(j); - - dx = ati.x - atj.x; - dy = ati.y - atj.y; - dz = ati.z - atj.z; - r += dx * dx + dy * dy + dz * dz; - } - } - return sqrt(r) / (atoms.size() + 1); -} - -// Does a cheap and dirty secondary structure assignment to the protein -// residues given in the array. -void calculateSecStr(ArrayList residues, int[] ss, int[] handness) { - PVector c0, n1, ca1, c1, n2; - HashMap res0, res1, res2; - int n = residues.size(); - - float[] phi = new float[n]; - float[] psi = new float[n]; - - for (int i = 0; i < n; i++) { - if (i == 0 || i == n - 1) { - phi[i] = 90; - psi[i] = 90; - } else { - res0 = (HashMap)residues.get(i - 1); - res1 = (HashMap)residues.get(i); - res2 = (HashMap)residues.get(i + 1); - - c0 = (PVector)res0.get("C"); - n1 = (PVector)res1.get("N"); - ca1 = (PVector)res1.get("CA"); - c1 = (PVector)res1.get("C"); - n2 = (PVector)res2.get("N"); - - phi[i] = calculateTorsionalAngle(c0, n1, ca1, c1); - psi[i] = calculateTorsionalAngle(n1, ca1, c1, n2); - } - } - - int firstHelix = 0; - int nconsRHelix = 0; - int nconsLHelix = 0; - int firstStrand = 0; - int nconsStrand = 0; - for (int i = 0; i < n; i++) { - // Right-handed helix - if ((dist(phi[i], psi[i], -60, -45) < 30) && (i < n - 1)) { - if (nconsRHelix == 0) firstHelix = i; - nconsRHelix++; - } - else { - if (3 <= nconsRHelix) { - for (int k = firstHelix; k < i; k++) { - ss[k] = HELIX; - handness[k] = RHANDED; - } - } - nconsRHelix = 0; - } - - // Left-handed helix - if ((dist(phi[i], psi[i], +60, +45) < 30) && (i < n - 1)) { - if (nconsLHelix == 0) firstHelix = i; - nconsLHelix++; - - } else { - if (3 <= nconsLHelix) { - for (int k = firstHelix; k < i; k++) { - ss[k] = HELIX; - handness[k] = LHANDED; - } - } - nconsLHelix = 0; - } - - // Strand - if ((dist(phi[i], psi[i], -110, +130) < 30) && (i < n - 1)) { - if (nconsStrand == 0) firstStrand = i; - nconsStrand++; - } else { - if (2 <= nconsStrand) { - for (int k = firstStrand; k < i; k++) { - ss[k] = STRAND; - handness[k] = RHANDED; - - } - } - nconsStrand = 0; - } - - ss[i] = COIL; - handness[i] = RHANDED; - } -} - -// Calculates the torsional angle defined by four atoms with positions at0, at1, at2 and at3. -float calculateTorsionalAngle(PVector at0, PVector at1, PVector at2, PVector at3) { - PVector r01 = PVector.sub(at0, at1); - PVector r32 = PVector.sub(at3, at2); - PVector r12 = PVector.sub(at1, at2); - - PVector p = r12.cross(r01); - PVector q = r12.cross(r32); - PVector r = r12.cross(q); - - float u = q.dot(q); - float v = r.dot(r); - - float a; - if (u <= 0.0 || v <= 0.0) { - a = 360.0; - } else { - float u1 = p.dot(q); // u1 = p * q - float v1 = p.dot(r); // v1 = p * r - - u = u1 / sqrt(u); - v = v1 / sqrt(v); - - if (abs(u) > 0.01 || abs(v) > 0.01) a = degrees(atan2(v, u)); - else a = 360.0; - } - return a; -} - -void generateSpline(int n, ArrayList vertices) { - int ui; - float u; - PVector v0, v1; - - v1 = new PVector(); - - if (n == 0) splineSide1.feval(0, v1); - else if (n == 1) splineCenter.feval(0, v1); - else splineSide2.feval(0, v1); - vertices.add(new PVector(v1.x, v1.y, v1.z)); - - for (ui = 1; ui <= 10; ui ++) { - if (ui % uspacing == 0) { - u = 0.1 * ui; - - if (n == 0) splineSide1.feval(u, v1); - else if (n == 1) splineCenter.feval(u, v1); - else splineSide2.feval(u, v1); - - vertices.add(new PVector(v1.x, v1.y, v1.z)); - } - } -} - -void generateFlatRibbon(ArrayList vertices, ArrayList normals) { - PVector CentPoint0, CentPoint1; - PVector Sid1Point0, Sid1Point1; - PVector Sid2Point0, Sid2Point1; - PVector Transversal, Tangent; - PVector Normal0, Normal1; - int ui; - float u; - - CentPoint0 = new PVector(); - CentPoint1 = new PVector(); - Sid1Point0 = new PVector(); - Sid1Point1 = new PVector(); - Sid2Point0 = new PVector(); - Sid2Point1 = new PVector(); - Transversal = new PVector(); - Tangent = new PVector(); - Normal0 = new PVector(); - Normal1 = new PVector(); - - // The initial geometry is generated. - splineSide1.feval(0, Sid1Point1); - splineCenter.feval(0, CentPoint1); - splineSide2.feval(0, Sid2Point1); - - // The tangents at the three previous points are the same. - splineSide2.deval(0, Tangent); - - // Vector transversal to the ribbon. - Transversal = PVector.sub(Sid1Point1, Sid2Point1); - - // The normal is calculated. - Normal1 = Transversal.cross(Tangent); - Normal1.normalize(); - - for (ui = 1; ui <= 10; ui ++) { - if (ui % uspacing == 0) { - u = 0.1 * ui; - - // The geometry of the previous iteration is saved. - Sid1Point0.set(Sid1Point1); - CentPoint0.set(CentPoint1); - Sid2Point0.set(Sid2Point1); - Normal0.set(Normal1); - - // The new geometry is generated. - splineSide1.feval(u, Sid1Point1); - splineCenter.feval(u, CentPoint1); - splineSide2.feval(u, Sid2Point1); - - // The tangents at the three previous points are the same. - splineSide2.deval(u, Tangent); - // Vector transversal to the ribbon. - Transversal = PVector.sub(Sid1Point1, Sid2Point1); - // The normal is calculated. - Normal1 = Transversal.cross(Tangent); - Normal1.normalize(); - - // The (Sid1Point0, Sid1Point1, CentPoint1) triangle is added. - vertices.add(new PVector(Sid1Point0.x, Sid1Point0.y, Sid1Point0.z)); - normals.add(new PVector(Normal0.x, Normal0.y, Normal0.z)); - - vertices.add(new PVector(Sid1Point1.x, Sid1Point1.y, Sid1Point1.z)); - normals.add(new PVector(Normal1.x, Normal1.y, Normal1.z)); - - vertices.add(new PVector(CentPoint1.x, CentPoint1.y, CentPoint1.z)); - normals.add(new PVector(Normal1.x, Normal1.y, Normal1.z)); - - // The (Sid1Point0, CentPoint1, CentPoint0) triangle is added. - vertices.add(new PVector(Sid1Point0.x, Sid1Point0.y, Sid1Point0.z)); - normals.add(new PVector(Normal0.x, Normal0.y, Normal0.z)); - - vertices.add(new PVector(CentPoint1.x, CentPoint1.y, CentPoint1.z)); - normals.add(new PVector(Normal1.x, Normal1.y, Normal1.z)); - - vertices.add(new PVector(CentPoint0.x, CentPoint0.y, CentPoint0.z)); - normals.add(new PVector(Normal0.x, Normal0.y, Normal0.z)); - - // (Sid2Point0, Sid2Point1, CentPoint1) triangle is added. - vertices.add(new PVector(Sid2Point0.x, Sid2Point0.y, Sid2Point0.z)); - normals.add(new PVector(Normal0.x, Normal0.y, Normal0.z)); - - vertices.add(new PVector(Sid2Point1.x, Sid2Point1.y, Sid2Point1.z)); - normals.add(new PVector(Normal1.x, Normal1.y, Normal1.z)); - - vertices.add(new PVector(CentPoint1.x, CentPoint1.y, CentPoint1.z)); - normals.add(new PVector(Normal1.x, Normal1.y, Normal1.z)); - - // (Sid2Point0, CentPoint1, CentPoint0) triangle is added. - vertices.add(new PVector(Sid2Point0.x, Sid2Point0.y, Sid2Point0.z)); - normals.add(new PVector(Normal0.x, Normal0.y, Normal0.z)); - - vertices.add(new PVector(CentPoint1.x, CentPoint1.y, CentPoint1.z)); - normals.add(new PVector(Normal1.x, Normal1.y, Normal1.z)); - - vertices.add(new PVector(CentPoint0.x, CentPoint0.y, CentPoint0.z)); - normals.add(new PVector(Normal0.x, Normal0.y, Normal0.z)); - } - } -} - -/****************************************************************************** - * The code in the following three functions is based in the method introduced - * in this paper: - * "Algorithm for ribbon models of proteins." - * Authors: Mike Carson and Charles E. Bugg - * Published in: J.Mol.Graphics 4, pp. 121-122 (1986) - ******************************************************************************/ - -// Shifts the control points one place to the left. -void shiftControlPoints() { - splineSide1.shiftBSplineCPoints(); - splineCenter.shiftBSplineCPoints(); - splineSide2.shiftBSplineCPoints(); -} - -// Adds a new control point to the arrays CPCenter, CPRight and CPLeft -void addControlPoints(PVector ca0, PVector ox0, PVector ca1, int ss, int handness) { - PVector A, B, C, D, p0, cpt0, cpt1, cpt2; - - A = PVector.sub(ca1, ca0); - B = PVector.sub(ox0, ca0); - - // Vector normal to the peptide plane (pointing outside in the case of the - // alpha helix). - C = A.cross(B); - - // Vector contained in the peptide plane (perpendicular to its direction). - D = C.cross(A); - - // Normalizing vectors. - C.normalize(); - D.normalize(); - - // Flipping test (to avoid self crossing in the strands). - if ((ss != HELIX) && (90.0 < degrees(PVector.angleBetween(flipTestV, D)))) { - // Flip detected. The plane vector is inverted. - D.mult(-1.0); - } - - // The central control point is constructed. - cpt0 = linearComb(0.5, ca0, 0.5, ca1); - splineCenter.setCPoint(3, cpt0); - - if (ss == HELIX) { - // When residue i is contained in a helix, the control point is moved away - // from the helix axis, along the C direction. - p0 = new PVector(); - splineCenter.getCPoint(3, p0); - cpt0 = linearComb(1.0, p0, handness * helixDiam, C); - splineCenter.setCPoint(3, cpt0); - } - - // The control points for the side ribbons are constructed. - cpt1 = linearComb(1.0, cpt0, +ribbonWidth[ss], D); - splineSide1.setCPoint(3, cpt1); - - cpt2 = linearComb(1.0, cpt0, -ribbonWidth[ss], D); - splineSide2.setCPoint(3, cpt2); - - // Saving the plane vector (for the flipping test in the next call). - flipTestV.set(D); -} - -void constructControlPoints(ArrayList residues, int res, int ss, int handness) { - PVector ca0, ox0, ca1; - PVector p0, p1, p2, p3; - - p1 = new PVector(); - p2 = new PVector(); - p3 = new PVector(); - - HashMap res0, res1; - - res0 = res1 = null; - if (res == 0) { - // The control points 2 and 3 are created. - flipTestV.set(0, 0, 0); - - res0 = (HashMap)residues.get(res); - res1 = (HashMap)residues.get(res + 1); - ca0 = (PVector)res0.get("CA"); - ox0 = (PVector)res0.get("O"); - ca1 = (PVector)res1.get("CA"); - addControlPoints(ca0, ox0, ca1, ss, handness); - splineSide1.copyCPoints(3, 2); - splineCenter.copyCPoints(3, 2); - splineSide2.copyCPoints(3, 2); - - res0 = (HashMap)residues.get(res + 1); - res1 = (HashMap)residues.get(res + 2); - ca0 = (PVector)res0.get("CA"); - ox0 = (PVector)res0.get("O"); - ca1 = (PVector)res1.get("CA"); - addControlPoints(ca0, ox0, ca1, ss, handness); - - // We still need the two first control points. - // Moving backwards along the cp_center[2] - cp_center[3] direction. - splineCenter.getCPoint(2, p2); - splineCenter.getCPoint(3, p3); - - p1 = linearComb(2.0, p2, -1, p3); - splineCenter.setCPoint(1, p1); - splineSide1.setCPoint(1, linearComb(1.0, p1, +ribbonWidth[ss], flipTestV)); - splineSide2.setCPoint(1, linearComb(1.0, p1, -ribbonWidth[ss], flipTestV)); - - p0 = linearComb(2.0, p1, -1, p2); - splineCenter.setCPoint(0, p0); - splineSide1.setCPoint(0, linearComb(1.0, p0, +ribbonWidth[ss], flipTestV)); - splineSide2.setCPoint(0, linearComb(1.0, p0, -ribbonWidth[ss], flipTestV)); - } else { - shiftControlPoints(); - if ((residues.size() - 1 == res) || (residues.size() - 2 == res)) { - // Moving forward along the cp_center[1] - cp_center[2] direction. - splineCenter.getCPoint(1, p1); - splineCenter.getCPoint(2, p2); - - p3 = linearComb(2.0, p2, -1, p1); - splineCenter.setCPoint(3, p3); - splineSide1.setCPoint(3, linearComb(1.0, p3, +ribbonWidth[ss], flipTestV)); - splineSide2.setCPoint(3, linearComb(1.0, p3, -ribbonWidth[ss], flipTestV)); - } else { - res0 = (HashMap)residues.get(res + 1); - res1 = (HashMap)residues.get(res + 2); - ca0 = (PVector)res0.get("CA"); - ox0 = (PVector)res0.get("O"); - ca1 = (PVector)res1.get("CA"); - addControlPoints(ca0, ox0, ca1, ss, handness); - } - } - splineSide1.updateMatrix3(); - splineCenter.updateMatrix3(); - splineSide2.updateMatrix3(); -} - -PVector linearComb(float scalar0, PVector vector0, float scalar1, PVector vector1) { - return PVector.add(PVector.mult(vector0, scalar0), PVector.mult(vector1, scalar1)); -} diff --git a/mode/examples/Demos/Graphics/Ribbons/PDB.pde b/mode/examples/Demos/Graphics/Ribbons/PDB.pde deleted file mode 100644 index c3daf443b..000000000 --- a/mode/examples/Demos/Graphics/Ribbons/PDB.pde +++ /dev/null @@ -1,115 +0,0 @@ -void readPDB(String filename) { - String strLines[]; - - float xmin, xmax, ymin, ymax, zmin, zmax; - - String xstr, ystr, zstr; - float x, y, z; - int res, res0; - int nmdl; - String atstr, resstr; - - PShape model; - ArrayList atoms; - ArrayList residues; - HashMap residue; - PVector v; - String s; - strLines = loadStrings(filename); - - models = new ArrayList(); - - xmin = ymin = zmin = 10000; - xmax = ymax = zmax = -10000; - - atoms = null; - residues = null; - residue = null; - model = null; - res0 = -1; - nmdl = -1; - for (int i = 0; i < strLines.length; i++) { - s = strLines[i]; - - if (s.startsWith("MODEL") || (s.startsWith("ATOM") && res0 == -1)) { - nmdl++; - - res0 = -1; - - atoms = new ArrayList(); - residues = new ArrayList(); - } - - if (s.startsWith("ATOM")) { - atstr = s.substring(12, 15); - atstr = atstr.trim(); - resstr = s.substring(22, 26); - resstr = resstr.trim(); - res = parseInt(resstr); - - xstr = s.substring(30, 37); - xstr = xstr.trim(); - ystr = s.substring(38, 45); - ystr = ystr.trim(); - zstr = s.substring(46, 53); - zstr = zstr.trim(); - - x = scaleFactor * parseFloat(xstr); - y = scaleFactor * parseFloat(ystr); - z = scaleFactor * parseFloat(zstr); - v = new PVector(x, y, z); - - xmin = min(xmin, x); - xmax = max(xmax, x); - - ymin = min(ymin, y); - ymax = max(ymax, y); - - zmin = min(zmin, z); - zmax = max(zmax, z); - - atoms.add(v); - - if (res0 != res) { - if (residue != null) residues.add(residue); - residue = new HashMap(); - } - residue.put(atstr, v); - - res0 = res; - } - - if (s.startsWith("ENDMDL") || s.startsWith("TER")) { - if (residue != null) residues.add(residue); - - createRibbonModel(residues, model, models); - float rgyr = calculateGyrRadius(atoms); - - res0 = -1; - residue = null; - atoms = null; - residues = null; - } - } - - if (residue != null) { - if (residue != null) residues.add(residue); - - createRibbonModel(residues, model, models); - float rgyr = calculateGyrRadius(atoms); - - atoms = null; - residues = null; - } - - // Centering models at (0, 0, 0). - float dx = -0.5f * (xmin + xmax); - float dy = -0.5f * (ymin + ymax); - float dz = -0.5f * (zmin + zmax); - for (int n = 0; n < models.size(); n++) { - model = (PShape) models.get(n); - model.translate(dx, dy, dz); - } - - println("Loaded PDB file with " + models.size() + " models."); -} diff --git a/mode/examples/Demos/Graphics/Ribbons/Ribbons.pde b/mode/examples/Demos/Graphics/Ribbons/Ribbons.pde deleted file mode 100644 index 69b3f77b0..000000000 --- a/mode/examples/Demos/Graphics/Ribbons/Ribbons.pde +++ /dev/null @@ -1,52 +0,0 @@ -// Ribbons, by Andres Colubri -// ArcBall class by Ariel, V3ga and Robert Hodgin (flight404) -// This sketch loads 3D atomic coordinates of a protein molecule -// from a file in PDB format (http://www.pdb.org/) and displays -// the structure using a ribbon representation. - -String pdbFile = "4HHB.pdb"; // PDB file to read -//String pdbFile = "1CBS.pdb"; -//String pdbFile = "2POR.pdb"; - -// Some parameters to control the visual appearance: -float scaleFactor = 10; // Size factor -int renderMode = 1; // 0 = lines, 1 = flat ribbons -int ribbonDetail = 4; // Ribbon detail: from 1 (lowest) to 4 (highest) -float helixDiam = 10; // Helix diameter. -int[] ribbonWidth = {10, 7, 2}; // Ribbon widths for helix, strand and coil -color ribbonColor = color(0, 102, 153, 255); // Ribbon color - -// All the molecular models read from the PDB file (it could contain more than one) -ArrayList models; - -Arcball arcball; - -void setup() { - size(displayWidth, displayHeight, P3D); - orientation(LANDSCAPE); - - arcball = new Arcball(width/2, height/2, 600); - readPDB(pdbFile); -} - -void draw() { - background(0); - - ambient(80); - lights(); - - translate(width/2, height/2, 200); - arcball.run(); - - for (int i = 0; i < models.size(); i++) { - shape((PShape)models.get(i)); - } -} - -void mousePressed(){ - arcball.mousePressed(); -} - -void mouseDragged(){ - arcball.mouseDragged(); -} diff --git a/mode/examples/Demos/Graphics/Ribbons/data/1CBS.pdb b/mode/examples/Demos/Graphics/Ribbons/data/1CBS.pdb deleted file mode 100644 index 2f1693c72..000000000 --- a/mode/examples/Demos/Graphics/Ribbons/data/1CBS.pdb +++ /dev/null @@ -1,1573 +0,0 @@ -HEADER RETINOIC-ACID TRANSPORT 28-SEP-94 1CBS -TITLE CRYSTAL STRUCTURE OF CELLULAR RETINOIC-ACID-BINDING -TITLE 2 PROTEINS I AND II IN COMPLEX WITH ALL-TRANS-RETINOIC ACID -TITLE 3 AND A SYNTHETIC RETINOID -COMPND MOL_ID: 1; -COMPND 2 MOLECULE: CELLULAR RETINOIC ACID BINDING PROTEIN TYPE II; -COMPND 3 CHAIN: A; -COMPND 4 ENGINEERED: YES -SOURCE MOL_ID: 1; -SOURCE 2 ORGANISM_SCIENTIFIC: HOMO SAPIENS; -SOURCE 3 ORGANISM_COMMON: HUMAN; -SOURCE 4 ORGANISM_TAXID: 9606; -SOURCE 5 CELL_LINE: BL21; -SOURCE 6 GENE: HUMAN CRABP-II; -SOURCE 7 EXPRESSION_SYSTEM: ESCHERICHIA COLI BL21(DE3); -SOURCE 8 EXPRESSION_SYSTEM_TAXID: 469008; -SOURCE 9 EXPRESSION_SYSTEM_STRAIN: BL21 (DE3); -SOURCE 10 EXPRESSION_SYSTEM_PLASMID: PET-3A -KEYWDS RETINOIC-ACID TRANSPORT -EXPDTA X-RAY DIFFRACTION -AUTHOR G.J.KLEYWEGT,T.BERGFORS,T.A.JONES -REVDAT 3 24-FEB-09 1CBS 1 VERSN -REVDAT 2 01-APR-03 1CBS 1 JRNL -REVDAT 1 26-JAN-95 1CBS 0 -JRNL AUTH G.J.KLEYWEGT,T.BERGFORS,H.SENN,P.LE MOTTE,B.GSELL, -JRNL AUTH 2 K.SHUDO,T.A.JONES -JRNL TITL CRYSTAL STRUCTURES OF CELLULAR RETINOIC ACID -JRNL TITL 2 BINDING PROTEINS I AND II IN COMPLEX WITH -JRNL TITL 3 ALL-TRANS-RETINOIC ACID AND A SYNTHETIC RETINOID. -JRNL REF STRUCTURE V. 2 1241 1994 -JRNL REFN ISSN 0969-2126 -JRNL PMID 7704533 -JRNL DOI 10.1016/S0969-2126(94)00125-1 -REMARK 1 -REMARK 1 REFERENCE 1 -REMARK 1 AUTH L.BANASZAK,N.WINTER,Z.XU,D.A.BERNLOHR,S.W.COWAN, -REMARK 1 AUTH 2 T.A.JONES -REMARK 1 TITL LIPID-BINDING PROTEINS: A FAMILY OF FATTY ACID AND -REMARK 1 TITL 2 RETINOID TRANSPORT PROTEINS -REMARK 1 REF ADV.PROTEIN CHEM. V. 45 89 1994 -REMARK 1 REFN ISSN 0065-3233 -REMARK 1 REFERENCE 2 -REMARK 1 AUTH T.BERGFORS,G.J.KLEYWEGT,T.A.JONES -REMARK 1 TITL CRYSTALLISATION AND PRELIMINARY X-RAY ANALYSIS OF -REMARK 1 TITL 2 RECOMBINANT BOVINE CELLULAR RETINOIC ACID-BINDING -REMARK 1 TITL 3 PROTEIN -REMARK 1 REF ACTA CRYSTALLOGR.,SECT.D V. 50 370 1994 -REMARK 1 REFN ISSN 0907-4449 -REMARK 1 REFERENCE 3 -REMARK 1 AUTH S.W.COWAN,M.E.NEWCOMER,T.A.JONES -REMARK 1 TITL CRYSTALLOGRAPHIC STUDIES ON A FAMILY OF LIPOPHILIC -REMARK 1 TITL 2 TRANSPORT PROTEINS. REFINEMENT OF P2 MYELIN -REMARK 1 TITL 3 PROTEIN AND THE STRUCTURE DETERMINATION AND -REMARK 1 TITL 4 REFINEMENT OF CELLULAR RETINOL-BINDING PROTEIN IN -REMARK 1 TITL 5 COMPLEX WITH ALL-TRANS-RETINOL -REMARK 1 REF J.MOL.BIOL. V. 230 1225 1993 -REMARK 1 REFN ISSN 0022-2836 -REMARK 1 REFERENCE 4 -REMARK 1 AUTH T.A.JONES,T.BERGFORS,J.SEDZIK,T.UNGE -REMARK 1 TITL THE THREE-DIMENSIONAL STRUCTURE OF P2 MYELIN -REMARK 1 TITL 2 PROTEIN -REMARK 1 REF EMBO J. V. 7 1597 1988 -REMARK 1 REFN ISSN 0261-4189 -REMARK 2 -REMARK 2 RESOLUTION. 1.80 ANGSTROMS. -REMARK 3 -REMARK 3 REFINEMENT. -REMARK 3 PROGRAM : X-PLOR -REMARK 3 AUTHORS : BRUNGER -REMARK 3 -REMARK 3 DATA USED IN REFINEMENT. -REMARK 3 RESOLUTION RANGE HIGH (ANGSTROMS) : 1.80 -REMARK 3 RESOLUTION RANGE LOW (ANGSTROMS) : 8.00 -REMARK 3 DATA CUTOFF (SIGMA(F)) : 2.000 -REMARK 3 DATA CUTOFF HIGH (ABS(F)) : NULL -REMARK 3 DATA CUTOFF LOW (ABS(F)) : NULL -REMARK 3 COMPLETENESS (WORKING+TEST) (%) : 90.3 -REMARK 3 NUMBER OF REFLECTIONS : 14312 -REMARK 3 -REMARK 3 FIT TO DATA USED IN REFINEMENT. -REMARK 3 CROSS-VALIDATION METHOD : NULL -REMARK 3 FREE R VALUE TEST SET SELECTION : NULL -REMARK 3 R VALUE (WORKING SET) : 0.200 -REMARK 3 FREE R VALUE : 0.237 -REMARK 3 FREE R VALUE TEST SET SIZE (%) : NULL -REMARK 3 FREE R VALUE TEST SET COUNT : NULL -REMARK 3 ESTIMATED ERROR OF FREE R VALUE : NULL -REMARK 3 -REMARK 3 FIT IN THE HIGHEST RESOLUTION BIN. -REMARK 3 TOTAL NUMBER OF BINS USED : NULL -REMARK 3 BIN RESOLUTION RANGE HIGH (A) : NULL -REMARK 3 BIN RESOLUTION RANGE LOW (A) : NULL -REMARK 3 BIN COMPLETENESS (WORKING+TEST) (%) : NULL -REMARK 3 REFLECTIONS IN BIN (WORKING SET) : NULL -REMARK 3 BIN R VALUE (WORKING SET) : NULL -REMARK 3 BIN FREE R VALUE : NULL -REMARK 3 BIN FREE R VALUE TEST SET SIZE (%) : NULL -REMARK 3 BIN FREE R VALUE TEST SET COUNT : NULL -REMARK 3 ESTIMATED ERROR OF BIN FREE R VALUE : NULL -REMARK 3 -REMARK 3 NUMBER OF NON-HYDROGEN ATOMS USED IN REFINEMENT. -REMARK 3 PROTEIN ATOMS : 1091 -REMARK 3 NUCLEIC ACID ATOMS : 0 -REMARK 3 HETEROGEN ATOMS : 22 -REMARK 3 SOLVENT ATOMS : 100 -REMARK 3 -REMARK 3 B VALUES. -REMARK 3 FROM WILSON PLOT (A**2) : NULL -REMARK 3 MEAN B VALUE (OVERALL, A**2) : 16.60 -REMARK 3 OVERALL ANISOTROPIC B VALUE. -REMARK 3 B11 (A**2) : NULL -REMARK 3 B22 (A**2) : NULL -REMARK 3 B33 (A**2) : NULL -REMARK 3 B12 (A**2) : NULL -REMARK 3 B13 (A**2) : NULL -REMARK 3 B23 (A**2) : NULL -REMARK 3 -REMARK 3 ESTIMATED COORDINATE ERROR. -REMARK 3 ESD FROM LUZZATI PLOT (A) : 0.20 -REMARK 3 ESD FROM SIGMAA (A) : NULL -REMARK 3 LOW RESOLUTION CUTOFF (A) : NULL -REMARK 3 -REMARK 3 CROSS-VALIDATED ESTIMATED COORDINATE ERROR. -REMARK 3 ESD FROM C-V LUZZATI PLOT (A) : NULL -REMARK 3 ESD FROM C-V SIGMAA (A) : NULL -REMARK 3 -REMARK 3 RMS DEVIATIONS FROM IDEAL VALUES. -REMARK 3 BOND LENGTHS (A) : 0.010 -REMARK 3 BOND ANGLES (DEGREES) : 1.51 -REMARK 3 DIHEDRAL ANGLES (DEGREES) : 27.40 -REMARK 3 IMPROPER ANGLES (DEGREES) : 1.32 -REMARK 3 -REMARK 3 ISOTROPIC THERMAL MODEL : NULL -REMARK 3 -REMARK 3 ISOTROPIC THERMAL FACTOR RESTRAINTS. RMS SIGMA -REMARK 3 MAIN-CHAIN BOND (A**2) : NULL ; NULL -REMARK 3 MAIN-CHAIN ANGLE (A**2) : NULL ; NULL -REMARK 3 SIDE-CHAIN BOND (A**2) : NULL ; NULL -REMARK 3 SIDE-CHAIN ANGLE (A**2) : NULL ; NULL -REMARK 3 -REMARK 3 NCS MODEL : NULL -REMARK 3 -REMARK 3 NCS RESTRAINTS. RMS SIGMA/WEIGHT -REMARK 3 GROUP 1 POSITIONAL (A) : NULL ; NULL -REMARK 3 GROUP 1 B-FACTOR (A**2) : NULL ; NULL -REMARK 3 -REMARK 3 PARAMETER FILE 1 : NULL -REMARK 3 TOPOLOGY FILE 1 : NULL -REMARK 3 -REMARK 3 OTHER REFINEMENT REMARKS: NULL -REMARK 4 -REMARK 4 1CBS COMPLIES WITH FORMAT V. 3.15, 01-DEC-08 -REMARK 100 -REMARK 100 THIS ENTRY HAS BEEN PROCESSED BY BNL. -REMARK 200 -REMARK 200 EXPERIMENTAL DETAILS -REMARK 200 EXPERIMENT TYPE : X-RAY DIFFRACTION -REMARK 200 DATE OF DATA COLLECTION : NULL -REMARK 200 TEMPERATURE (KELVIN) : NULL -REMARK 200 PH : NULL -REMARK 200 NUMBER OF CRYSTALS USED : NULL -REMARK 200 -REMARK 200 SYNCHROTRON (Y/N) : NULL -REMARK 200 RADIATION SOURCE : NULL -REMARK 200 BEAMLINE : NULL -REMARK 200 X-RAY GENERATOR MODEL : NULL -REMARK 200 MONOCHROMATIC OR LAUE (M/L) : NULL -REMARK 200 WAVELENGTH OR RANGE (A) : NULL -REMARK 200 MONOCHROMATOR : NULL -REMARK 200 OPTICS : NULL -REMARK 200 -REMARK 200 DETECTOR TYPE : NULL -REMARK 200 DETECTOR MANUFACTURER : NULL -REMARK 200 INTENSITY-INTEGRATION SOFTWARE : NULL -REMARK 200 DATA SCALING SOFTWARE : NULL -REMARK 200 -REMARK 200 NUMBER OF UNIQUE REFLECTIONS : 14678 -REMARK 200 RESOLUTION RANGE HIGH (A) : NULL -REMARK 200 RESOLUTION RANGE LOW (A) : NULL -REMARK 200 REJECTION CRITERIA (SIGMA(I)) : 3.000 -REMARK 200 -REMARK 200 OVERALL. -REMARK 200 COMPLETENESS FOR RANGE (%) : 90.3 -REMARK 200 DATA REDUNDANCY : NULL -REMARK 200 R MERGE (I) : NULL -REMARK 200 R SYM (I) : NULL -REMARK 200 FOR THE DATA SET : NULL -REMARK 200 -REMARK 200 IN THE HIGHEST RESOLUTION SHELL. -REMARK 200 HIGHEST RESOLUTION SHELL, RANGE HIGH (A) : NULL -REMARK 200 HIGHEST RESOLUTION SHELL, RANGE LOW (A) : NULL -REMARK 200 COMPLETENESS FOR SHELL (%) : NULL -REMARK 200 DATA REDUNDANCY IN SHELL : NULL -REMARK 200 R MERGE FOR SHELL (I) : NULL -REMARK 200 R SYM FOR SHELL (I) : NULL -REMARK 200 FOR SHELL : NULL -REMARK 200 -REMARK 200 DIFFRACTION PROTOCOL: NULL -REMARK 200 METHOD USED TO DETERMINE THE STRUCTURE: NULL -REMARK 200 SOFTWARE USED: X-PLOR -REMARK 200 STARTING MODEL: NULL -REMARK 200 -REMARK 200 REMARK: NULL -REMARK 280 -REMARK 280 CRYSTAL -REMARK 280 SOLVENT CONTENT, VS (%): 54.49 -REMARK 280 MATTHEWS COEFFICIENT, VM (ANGSTROMS**3/DA): 2.70 -REMARK 280 -REMARK 280 CRYSTALLIZATION CONDITIONS: NULL -REMARK 290 -REMARK 290 CRYSTALLOGRAPHIC SYMMETRY -REMARK 290 SYMMETRY OPERATORS FOR SPACE GROUP: P 21 21 21 -REMARK 290 -REMARK 290 SYMOP SYMMETRY -REMARK 290 NNNMMM OPERATOR -REMARK 290 1555 X,Y,Z -REMARK 290 2555 -X+1/2,-Y,Z+1/2 -REMARK 290 3555 -X,Y+1/2,-Z+1/2 -REMARK 290 4555 X+1/2,-Y+1/2,-Z -REMARK 290 -REMARK 290 WHERE NNN -> OPERATOR NUMBER -REMARK 290 MMM -> TRANSLATION VECTOR -REMARK 290 -REMARK 290 CRYSTALLOGRAPHIC SYMMETRY TRANSFORMATIONS -REMARK 290 THE FOLLOWING TRANSFORMATIONS OPERATE ON THE ATOM/HETATM -REMARK 290 RECORDS IN THIS ENTRY TO PRODUCE CRYSTALLOGRAPHICALLY -REMARK 290 RELATED MOLECULES. -REMARK 290 SMTRY1 1 1.000000 0.000000 0.000000 0.00000 -REMARK 290 SMTRY2 1 0.000000 1.000000 0.000000 0.00000 -REMARK 290 SMTRY3 1 0.000000 0.000000 1.000000 0.00000 -REMARK 290 SMTRY1 2 -1.000000 0.000000 0.000000 22.82500 -REMARK 290 SMTRY2 2 0.000000 -1.000000 0.000000 0.00000 -REMARK 290 SMTRY3 2 0.000000 0.000000 1.000000 38.80500 -REMARK 290 SMTRY1 3 -1.000000 0.000000 0.000000 0.00000 -REMARK 290 SMTRY2 3 0.000000 1.000000 0.000000 23.78000 -REMARK 290 SMTRY3 3 0.000000 0.000000 -1.000000 38.80500 -REMARK 290 SMTRY1 4 1.000000 0.000000 0.000000 22.82500 -REMARK 290 SMTRY2 4 0.000000 -1.000000 0.000000 23.78000 -REMARK 290 SMTRY3 4 0.000000 0.000000 -1.000000 0.00000 -REMARK 290 -REMARK 290 REMARK: NULL -REMARK 300 -REMARK 300 BIOMOLECULE: 1 -REMARK 300 SEE REMARK 350 FOR THE AUTHOR PROVIDED AND/OR PROGRAM -REMARK 300 GENERATED ASSEMBLY INFORMATION FOR THE STRUCTURE IN -REMARK 300 THIS ENTRY. THE REMARK MAY ALSO PROVIDE INFORMATION ON -REMARK 300 BURIED SURFACE AREA. -REMARK 350 -REMARK 350 COORDINATES FOR A COMPLETE MULTIMER REPRESENTING THE KNOWN -REMARK 350 BIOLOGICALLY SIGNIFICANT OLIGOMERIZATION STATE OF THE -REMARK 350 MOLECULE CAN BE GENERATED BY APPLYING BIOMT TRANSFORMATIONS -REMARK 350 GIVEN BELOW. BOTH NON-CRYSTALLOGRAPHIC AND -REMARK 350 CRYSTALLOGRAPHIC OPERATIONS ARE GIVEN. -REMARK 350 -REMARK 350 BIOMOLECULE: 1 -REMARK 350 AUTHOR DETERMINED BIOLOGICAL UNIT: MONOMERIC -REMARK 350 APPLY THE FOLLOWING TO CHAINS: A -REMARK 350 BIOMT1 1 1.000000 0.000000 0.000000 0.00000 -REMARK 350 BIOMT2 1 0.000000 1.000000 0.000000 0.00000 -REMARK 350 BIOMT3 1 0.000000 0.000000 1.000000 0.00000 -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: TORSION ANGLES -REMARK 500 -REMARK 500 TORSION ANGLES OUTSIDE THE EXPECTED RAMACHANDRAN REGIONS: -REMARK 500 (M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN IDENTIFIER; -REMARK 500 SSEQ=SEQUENCE NUMBER; I=INSERTION CODE). -REMARK 500 -REMARK 500 STANDARD TABLE: -REMARK 500 FORMAT:(10X,I3,1X,A3,1X,A1,I4,A1,4X,F7.2,3X,F7.2) -REMARK 500 -REMARK 500 EXPECTED VALUES: GJ KLEYWEGT AND TA JONES (1996). PHI/PSI- -REMARK 500 CHOLOGY: RAMACHANDRAN REVISITED. STRUCTURE 4, 1395 - 1400 -REMARK 500 -REMARK 500 M RES CSSEQI PSI PHI -REMARK 500 GLU A 73 -154.28 -144.94 -REMARK 500 ASP A 126 -115.96 55.69 -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 525 -REMARK 525 SOLVENT -REMARK 525 -REMARK 525 THE SOLVENT MOLECULES HAVE CHAIN IDENTIFIERS THAT -REMARK 525 INDICATE THE POLYMER CHAIN WITH WHICH THEY ARE MOST -REMARK 525 CLOSELY ASSOCIATED. THE REMARK LISTS ALL THE SOLVENT -REMARK 525 MOLECULES WHICH ARE MORE THAN 5A AWAY FROM THE -REMARK 525 NEAREST POLYMER CHAIN (M = MODEL NUMBER; -REMARK 525 RES=RESIDUE NAME; C=CHAIN IDENTIFIER; SSEQ=SEQUENCE -REMARK 525 NUMBER; I=INSERTION CODE): -REMARK 525 -REMARK 525 M RES CSSEQI -REMARK 525 HOH A 376 DISTANCE = 5.94 ANGSTROMS -REMARK 800 -REMARK 800 SITE -REMARK 800 SITE_IDENTIFIER: AC1 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE REA A 200 -DBREF 1CBS A 1 137 UNP P29373 RABP2_HUMAN 1 137 -SEQRES 1 A 137 PRO ASN PHE SER GLY ASN TRP LYS ILE ILE ARG SER GLU -SEQRES 2 A 137 ASN PHE GLU GLU LEU LEU LYS VAL LEU GLY VAL ASN VAL -SEQRES 3 A 137 MET LEU ARG LYS ILE ALA VAL ALA ALA ALA SER LYS PRO -SEQRES 4 A 137 ALA VAL GLU ILE LYS GLN GLU GLY ASP THR PHE TYR ILE -SEQRES 5 A 137 LYS THR SER THR THR VAL ARG THR THR GLU ILE ASN PHE -SEQRES 6 A 137 LYS VAL GLY GLU GLU PHE GLU GLU GLN THR VAL ASP GLY -SEQRES 7 A 137 ARG PRO CYS LYS SER LEU VAL LYS TRP GLU SER GLU ASN -SEQRES 8 A 137 LYS MET VAL CYS GLU GLN LYS LEU LEU LYS GLY GLU GLY -SEQRES 9 A 137 PRO LYS THR SER TRP THR ARG GLU LEU THR ASN ASP GLY -SEQRES 10 A 137 GLU LEU ILE LEU THR MET THR ALA ASP ASP VAL VAL CYS -SEQRES 11 A 137 THR ARG VAL TYR VAL ARG GLU -HET REA A 200 22 -HETNAM REA RETINOIC ACID -FORMUL 2 REA C20 H28 O2 -FORMUL 3 HOH *100(H2 O) -HELIX 1 1 ASN A 14 LEU A 22 1 9 -HELIX 2 2 ASN A 25 SER A 37 1 13 -SHEET 1 A10 THR A 60 LYS A 66 0 -SHEET 2 A10 THR A 49 SER A 55 -1 N PHE A 50 O PHE A 65 -SHEET 3 A10 ALA A 40 GLU A 46 -1 O ALA A 40 N SER A 55 -SHEET 4 A10 GLY A 5 GLU A 13 -1 O GLY A 5 N ILE A 43 -SHEET 5 A10 VAL A 128 ARG A 136 -1 O THR A 131 N GLU A 13 -SHEET 6 A10 LEU A 119 ALA A 125 -1 O LEU A 119 N TYR A 134 -SHEET 7 A10 THR A 107 LEU A 113 -1 O SER A 108 N THR A 124 -SHEET 8 A10 LYS A 92 LEU A 99 -1 N MET A 93 O ARG A 111 -SHEET 9 A10 PRO A 80 SER A 89 -1 N LYS A 82 O LYS A 98 -SHEET 10 A10 PHE A 71 GLN A 74 -1 O PHE A 71 N SER A 83 -SITE 1 AC1 10 GLU A 13 ALA A 32 THR A 54 VAL A 58 -SITE 2 AC1 10 VAL A 76 LEU A 121 ARG A 132 TYR A 134 -SITE 3 AC1 10 HOH A 309 HOH A 343 -CRYST1 45.650 47.560 77.610 90.00 90.00 90.00 P 21 21 21 4 -ORIGX1 1.000000 0.000000 0.000000 0.00000 -ORIGX2 0.000000 1.000000 0.000000 0.00000 -ORIGX3 0.000000 0.000000 1.000000 0.00000 -SCALE1 0.021906 0.000000 0.000000 0.00000 -SCALE2 0.000000 0.021026 0.000000 0.00000 -SCALE3 0.000000 0.000000 0.012885 0.00000 -ATOM 1 N PRO A 1 16.979 13.301 44.555 1.00 30.05 N -ATOM 2 CA PRO A 1 18.150 13.525 43.680 1.00 28.82 C -ATOM 3 C PRO A 1 18.656 14.966 43.784 1.00 26.59 C -ATOM 4 O PRO A 1 17.890 15.889 44.078 1.00 26.84 O -ATOM 5 CB PRO A 1 17.678 13.270 42.255 1.00 29.24 C -ATOM 6 CG PRO A 1 16.248 13.734 42.347 1.00 29.29 C -ATOM 7 CD PRO A 1 15.762 13.216 43.724 1.00 30.71 C -ATOM 8 N ASN A 2 19.957 15.139 43.558 1.00 24.04 N -ATOM 9 CA ASN A 2 20.576 16.457 43.578 1.00 20.79 C -ATOM 10 C ASN A 2 21.301 16.714 42.262 1.00 16.75 C -ATOM 11 O ASN A 2 22.402 16.215 42.028 1.00 15.23 O -ATOM 12 CB ASN A 2 21.559 16.620 44.724 1.00 22.81 C -ATOM 13 CG ASN A 2 22.240 17.968 44.685 1.00 24.29 C -ATOM 14 OD1 ASN A 2 21.612 18.984 44.358 1.00 21.87 O -ATOM 15 ND2 ASN A 2 23.537 17.983 44.966 1.00 27.94 N -ATOM 16 N PHE A 3 20.637 17.477 41.402 1.00 14.69 N -ATOM 17 CA PHE A 3 21.144 17.838 40.087 1.00 12.62 C -ATOM 18 C PHE A 3 22.152 18.987 40.140 1.00 12.43 C -ATOM 19 O PHE A 3 22.796 19.289 39.136 1.00 12.12 O -ATOM 20 CB PHE A 3 19.970 18.262 39.188 1.00 10.74 C -ATOM 21 CG PHE A 3 19.073 17.128 38.750 1.00 11.85 C -ATOM 22 CD1 PHE A 3 18.066 16.646 39.581 1.00 10.90 C -ATOM 23 CD2 PHE A 3 19.189 16.588 37.475 1.00 13.26 C -ATOM 24 CE1 PHE A 3 17.200 15.662 39.149 1.00 9.12 C -ATOM 25 CE2 PHE A 3 18.312 15.594 37.041 1.00 11.76 C -ATOM 26 CZ PHE A 3 17.324 15.137 37.878 1.00 10.30 C -ATOM 27 N SER A 4 22.282 19.630 41.299 1.00 11.24 N -ATOM 28 CA SER A 4 23.170 20.780 41.464 1.00 11.30 C -ATOM 29 C SER A 4 24.627 20.568 41.091 1.00 10.39 C -ATOM 30 O SER A 4 25.201 19.532 41.384 1.00 10.24 O -ATOM 31 CB SER A 4 23.112 21.301 42.906 1.00 13.53 C -ATOM 32 OG SER A 4 21.821 21.787 43.240 1.00 16.76 O -ATOM 33 N GLY A 5 25.224 21.572 40.460 1.00 9.87 N -ATOM 34 CA GLY A 5 26.628 21.486 40.103 1.00 10.86 C -ATOM 35 C GLY A 5 26.985 22.158 38.794 1.00 11.21 C -ATOM 36 O GLY A 5 26.123 22.761 38.142 1.00 9.91 O -ATOM 37 N ASN A 6 28.277 22.142 38.475 1.00 10.41 N -ATOM 38 CA ASN A 6 28.796 22.676 37.211 1.00 11.06 C -ATOM 39 C ASN A 6 29.117 21.435 36.378 1.00 10.33 C -ATOM 40 O ASN A 6 29.947 20.603 36.754 1.00 11.28 O -ATOM 41 CB ASN A 6 30.023 23.548 37.445 1.00 12.95 C -ATOM 42 CG ASN A 6 29.675 24.816 38.200 1.00 18.08 C -ATOM 43 OD1 ASN A 6 29.022 25.708 37.665 1.00 19.52 O -ATOM 44 ND2 ASN A 6 30.047 24.872 39.467 1.00 21.23 N -ATOM 45 N TRP A 7 28.399 21.289 35.272 1.00 8.66 N -ATOM 46 CA TRP A 7 28.518 20.119 34.424 1.00 8.74 C -ATOM 47 C TRP A 7 29.246 20.352 33.092 1.00 9.63 C -ATOM 48 O TRP A 7 29.064 21.389 32.440 1.00 9.45 O -ATOM 49 CB TRP A 7 27.115 19.563 34.152 1.00 8.00 C -ATOM 50 CG TRP A 7 26.325 19.198 35.391 1.00 8.01 C -ATOM 51 CD1 TRP A 7 25.556 20.031 36.159 1.00 8.29 C -ATOM 52 CD2 TRP A 7 26.174 17.885 35.947 1.00 7.60 C -ATOM 53 NE1 TRP A 7 24.922 19.308 37.156 1.00 9.20 N -ATOM 54 CE2 TRP A 7 25.286 17.987 37.046 1.00 8.73 C -ATOM 55 CE3 TRP A 7 26.694 16.625 35.618 1.00 6.99 C -ATOM 56 CZ2 TRP A 7 24.909 16.876 37.815 1.00 7.67 C -ATOM 57 CZ3 TRP A 7 26.320 15.527 36.380 1.00 7.58 C -ATOM 58 CH2 TRP A 7 25.433 15.663 37.468 1.00 5.92 C -ATOM 59 N LYS A 8 30.052 19.368 32.702 1.00 9.39 N -ATOM 60 CA LYS A 8 30.802 19.424 31.450 1.00 11.56 C -ATOM 61 C LYS A 8 30.342 18.243 30.611 1.00 10.56 C -ATOM 62 O LYS A 8 30.091 17.158 31.138 1.00 10.14 O -ATOM 63 CB LYS A 8 32.308 19.360 31.710 1.00 15.20 C -ATOM 64 CG LYS A 8 32.785 18.080 32.313 1.00 18.52 C -ATOM 65 CD LYS A 8 34.263 18.182 32.618 1.00 26.26 C -ATOM 66 CE LYS A 8 35.091 18.499 31.378 1.00 29.22 C -ATOM 67 NZ LYS A 8 35.067 17.393 30.369 1.00 32.48 N -ATOM 68 N ILE A 9 30.222 18.447 29.308 1.00 8.21 N -ATOM 69 CA ILE A 9 29.739 17.384 28.441 1.00 8.08 C -ATOM 70 C ILE A 9 30.798 16.325 28.117 1.00 7.86 C -ATOM 71 O ILE A 9 31.990 16.635 28.028 1.00 8.38 O -ATOM 72 CB ILE A 9 29.148 17.997 27.144 1.00 10.70 C -ATOM 73 CG1 ILE A 9 28.285 16.981 26.401 1.00 10.95 C -ATOM 74 CG2 ILE A 9 30.261 18.500 26.243 1.00 10.70 C -ATOM 75 CD1 ILE A 9 27.586 17.597 25.207 1.00 13.23 C -ATOM 76 N ILE A 10 30.373 15.067 27.995 1.00 7.08 N -ATOM 77 CA ILE A 10 31.288 13.988 27.656 1.00 7.45 C -ATOM 78 C ILE A 10 30.812 13.201 26.441 1.00 8.49 C -ATOM 79 O ILE A 10 31.561 12.397 25.892 1.00 9.49 O -ATOM 80 CB ILE A 10 31.586 13.023 28.847 1.00 10.28 C -ATOM 81 CG1 ILE A 10 30.304 12.393 29.382 1.00 10.51 C -ATOM 82 CG2 ILE A 10 32.349 13.756 29.963 1.00 10.10 C -ATOM 83 CD1 ILE A 10 30.578 11.242 30.325 1.00 12.18 C -ATOM 84 N ARG A 11 29.566 13.419 26.030 1.00 7.59 N -ATOM 85 CA ARG A 11 29.015 12.742 24.851 1.00 8.70 C -ATOM 86 C ARG A 11 27.821 13.500 24.290 1.00 9.41 C -ATOM 87 O ARG A 11 26.990 14.004 25.043 1.00 9.84 O -ATOM 88 CB ARG A 11 28.563 11.316 25.184 1.00 8.07 C -ATOM 89 CG ARG A 11 27.912 10.616 23.998 1.00 12.26 C -ATOM 90 CD ARG A 11 27.234 9.340 24.394 1.00 13.46 C -ATOM 91 NE ARG A 11 28.157 8.304 24.847 1.00 15.44 N -ATOM 92 CZ ARG A 11 28.815 7.470 24.037 1.00 19.59 C -ATOM 93 NH1 ARG A 11 28.677 7.559 22.714 1.00 19.40 N -ATOM 94 NH2 ARG A 11 29.521 6.467 24.547 1.00 17.50 N -ATOM 95 N SER A 12 27.748 13.594 22.965 1.00 8.84 N -ATOM 96 CA SER A 12 26.621 14.245 22.310 1.00 8.61 C -ATOM 97 C SER A 12 26.278 13.431 21.063 1.00 9.48 C -ATOM 98 O SER A 12 27.159 13.147 20.250 1.00 9.84 O -ATOM 99 CB SER A 12 26.966 15.676 21.925 1.00 9.02 C -ATOM 100 OG SER A 12 25.863 16.285 21.273 1.00 11.97 O -ATOM 101 N GLU A 13 25.016 13.038 20.924 1.00 7.59 N -ATOM 102 CA GLU A 13 24.586 12.258 19.768 1.00 9.67 C -ATOM 103 C GLU A 13 23.368 12.887 19.118 1.00 9.06 C -ATOM 104 O GLU A 13 22.457 13.343 19.815 1.00 7.34 O -ATOM 105 CB GLU A 13 24.185 10.833 20.184 1.00 9.72 C -ATOM 106 CG GLU A 13 25.257 10.018 20.895 1.00 15.17 C -ATOM 107 CD GLU A 13 26.262 9.340 19.954 1.00 18.75 C -ATOM 108 OE1 GLU A 13 26.031 9.310 18.726 1.00 18.53 O -ATOM 109 OE2 GLU A 13 27.286 8.822 20.457 1.00 19.23 O -ATOM 110 N ASN A 14 23.363 12.919 17.786 1.00 8.79 N -ATOM 111 CA ASN A 14 22.202 13.408 17.025 1.00 8.29 C -ATOM 112 C ASN A 14 21.813 14.896 17.153 1.00 7.35 C -ATOM 113 O ASN A 14 20.681 15.245 16.860 1.00 7.00 O -ATOM 114 CB ASN A 14 20.989 12.522 17.383 1.00 7.23 C -ATOM 115 CG ASN A 14 20.358 11.833 16.172 1.00 9.38 C -ATOM 116 OD1 ASN A 14 20.996 11.670 15.128 1.00 10.37 O -ATOM 117 ND2 ASN A 14 19.106 11.436 16.310 1.00 6.35 N -ATOM 118 N PHE A 15 22.734 15.777 17.536 1.00 7.26 N -ATOM 119 CA PHE A 15 22.385 17.198 17.681 1.00 9.06 C -ATOM 120 C PHE A 15 22.041 17.878 16.358 1.00 9.15 C -ATOM 121 O PHE A 15 21.041 18.578 16.265 1.00 8.64 O -ATOM 122 CB PHE A 15 23.497 17.990 18.379 1.00 10.05 C -ATOM 123 CG PHE A 15 23.102 19.397 18.746 1.00 10.57 C -ATOM 124 CD1 PHE A 15 22.032 19.633 19.605 1.00 13.39 C -ATOM 125 CD2 PHE A 15 23.813 20.485 18.254 1.00 11.47 C -ATOM 126 CE1 PHE A 15 21.678 20.929 19.968 1.00 13.52 C -ATOM 127 CE2 PHE A 15 23.467 21.784 18.609 1.00 11.60 C -ATOM 128 CZ PHE A 15 22.399 22.006 19.469 1.00 13.52 C -ATOM 129 N GLU A 16 22.878 17.699 15.342 1.00 11.17 N -ATOM 130 CA GLU A 16 22.583 18.313 14.053 1.00 12.58 C -ATOM 131 C GLU A 16 21.271 17.797 13.468 1.00 11.71 C -ATOM 132 O GLU A 16 20.503 18.567 12.888 1.00 12.66 O -ATOM 133 CB GLU A 16 23.711 18.081 13.060 1.00 15.91 C -ATOM 134 CG GLU A 16 23.274 18.337 11.626 1.00 21.31 C -ATOM 135 CD GLU A 16 24.376 18.878 10.757 1.00 25.39 C -ATOM 136 OE1 GLU A 16 25.526 18.984 11.240 1.00 27.92 O -ATOM 137 OE2 GLU A 16 24.084 19.213 9.588 1.00 28.60 O -ATOM 138 N GLU A 17 21.018 16.497 13.619 1.00 11.67 N -ATOM 139 CA GLU A 17 19.785 15.878 13.116 1.00 13.65 C -ATOM 140 C GLU A 17 18.529 16.490 13.767 1.00 13.48 C -ATOM 141 O GLU A 17 17.490 16.662 13.115 1.00 11.68 O -ATOM 142 CB GLU A 17 19.811 14.361 13.325 1.00 17.06 C -ATOM 143 CG GLU A 17 20.806 13.602 12.430 1.00 23.45 C -ATOM 144 CD GLU A 17 22.279 13.624 12.909 1.00 27.80 C -ATOM 145 OE1 GLU A 17 22.637 14.338 13.881 1.00 26.52 O -ATOM 146 OE2 GLU A 17 23.097 12.897 12.291 1.00 31.80 O -ATOM 147 N LEU A 18 18.640 16.834 15.048 1.00 10.82 N -ATOM 148 CA LEU A 18 17.547 17.468 15.777 1.00 9.45 C -ATOM 149 C LEU A 18 17.302 18.849 15.155 1.00 9.27 C -ATOM 150 O LEU A 18 16.153 19.246 14.927 1.00 9.04 O -ATOM 151 CB LEU A 18 17.931 17.644 17.253 1.00 9.77 C -ATOM 152 CG LEU A 18 16.921 18.358 18.163 1.00 11.36 C -ATOM 153 CD1 LEU A 18 15.817 17.402 18.554 1.00 13.85 C -ATOM 154 CD2 LEU A 18 17.616 18.876 19.409 1.00 12.69 C -ATOM 155 N LEU A 19 18.387 19.568 14.864 1.00 10.75 N -ATOM 156 CA LEU A 19 18.275 20.906 14.276 1.00 11.15 C -ATOM 157 C LEU A 19 17.671 20.873 12.874 1.00 12.52 C -ATOM 158 O LEU A 19 16.932 21.777 12.485 1.00 10.05 O -ATOM 159 CB LEU A 19 19.631 21.616 14.263 1.00 12.01 C -ATOM 160 CG LEU A 19 20.282 21.963 15.614 1.00 10.42 C -ATOM 161 CD1 LEU A 19 21.560 22.763 15.369 1.00 13.01 C -ATOM 162 CD2 LEU A 19 19.312 22.742 16.513 1.00 11.45 C -ATOM 163 N LYS A 20 17.944 19.795 12.150 1.00 14.41 N -ATOM 164 CA LYS A 20 17.427 19.628 10.800 1.00 16.54 C -ATOM 165 C LYS A 20 15.902 19.512 10.832 1.00 16.17 C -ATOM 166 O LYS A 20 15.201 20.164 10.053 1.00 15.90 O -ATOM 167 CB LYS A 20 18.048 18.390 10.157 1.00 20.07 C -ATOM 168 CG LYS A 20 18.592 18.643 8.765 1.00 26.61 C -ATOM 169 CD LYS A 20 18.960 17.349 8.027 1.00 30.95 C -ATOM 170 CE LYS A 20 20.226 16.690 8.579 1.00 35.68 C -ATOM 171 NZ LYS A 20 21.485 17.466 8.342 1.00 39.27 N -ATOM 172 N VAL A 21 15.395 18.700 11.759 1.00 15.31 N -ATOM 173 CA VAL A 21 13.958 18.508 11.927 1.00 14.41 C -ATOM 174 C VAL A 21 13.275 19.831 12.316 1.00 15.02 C -ATOM 175 O VAL A 21 12.150 20.119 11.878 1.00 13.59 O -ATOM 176 CB VAL A 21 13.674 17.422 12.998 1.00 14.93 C -ATOM 177 CG1 VAL A 21 12.194 17.383 13.364 1.00 17.29 C -ATOM 178 CG2 VAL A 21 14.115 16.082 12.482 1.00 15.09 C -ATOM 179 N LEU A 22 13.966 20.643 13.119 1.00 14.52 N -ATOM 180 CA LEU A 22 13.432 21.938 13.569 1.00 14.42 C -ATOM 181 C LEU A 22 13.478 22.984 12.467 1.00 15.49 C -ATOM 182 O LEU A 22 13.038 24.115 12.666 1.00 16.81 O -ATOM 183 CB LEU A 22 14.180 22.440 14.818 1.00 13.61 C -ATOM 184 CG LEU A 22 13.986 21.565 16.069 1.00 13.97 C -ATOM 185 CD1 LEU A 22 14.852 22.047 17.225 1.00 13.25 C -ATOM 186 CD2 LEU A 22 12.525 21.580 16.467 1.00 14.62 C -ATOM 187 N GLY A 23 14.062 22.618 11.328 1.00 16.41 N -ATOM 188 CA GLY A 23 14.123 23.516 10.183 1.00 17.05 C -ATOM 189 C GLY A 23 15.241 24.539 10.125 1.00 18.00 C -ATOM 190 O GLY A 23 15.112 25.545 9.425 1.00 19.45 O -ATOM 191 N VAL A 24 16.320 24.315 10.869 1.00 14.78 N -ATOM 192 CA VAL A 24 17.440 25.241 10.860 1.00 13.71 C -ATOM 193 C VAL A 24 18.289 24.983 9.607 1.00 15.09 C -ATOM 194 O VAL A 24 18.679 23.840 9.334 1.00 14.12 O -ATOM 195 CB VAL A 24 18.297 25.081 12.139 1.00 12.19 C -ATOM 196 CG1 VAL A 24 19.465 26.054 12.109 1.00 8.69 C -ATOM 197 CG2 VAL A 24 17.416 25.294 13.388 1.00 11.37 C -ATOM 198 N ASN A 25 18.595 26.047 8.866 1.00 15.37 N -ATOM 199 CA ASN A 25 19.360 25.914 7.635 1.00 17.74 C -ATOM 200 C ASN A 25 20.808 25.466 7.819 1.00 18.29 C -ATOM 201 O ASN A 25 21.377 25.592 8.903 1.00 18.05 O -ATOM 202 CB ASN A 25 19.230 27.172 6.742 1.00 19.41 C -ATOM 203 CG ASN A 25 20.090 28.351 7.200 1.00 22.35 C -ATOM 204 OD1 ASN A 25 21.207 28.189 7.698 1.00 22.64 O -ATOM 205 ND2 ASN A 25 19.602 29.558 6.933 1.00 24.15 N -ATOM 206 N VAL A 26 21.398 24.971 6.733 1.00 18.67 N -ATOM 207 CA VAL A 26 22.755 24.444 6.742 1.00 19.24 C -ATOM 208 C VAL A 26 23.825 25.280 7.421 1.00 18.39 C -ATOM 209 O VAL A 26 24.558 24.764 8.261 1.00 18.50 O -ATOM 210 CB VAL A 26 23.223 24.088 5.320 1.00 20.77 C -ATOM 211 CG1 VAL A 26 24.624 23.523 5.378 1.00 22.39 C -ATOM 212 CG2 VAL A 26 22.276 23.084 4.698 1.00 21.28 C -ATOM 213 N MET A 27 23.932 26.556 7.052 1.00 19.00 N -ATOM 214 CA MET A 27 24.948 27.433 7.628 1.00 19.54 C -ATOM 215 C MET A 27 24.734 27.741 9.099 1.00 19.04 C -ATOM 216 O MET A 27 25.702 27.820 9.849 1.00 18.28 O -ATOM 217 CB MET A 27 25.104 28.736 6.830 1.00 23.31 C -ATOM 218 CG MET A 27 25.955 28.602 5.552 1.00 29.99 C -ATOM 219 SD MET A 27 24.975 28.527 4.010 1.00 37.48 S -ATOM 220 CE MET A 27 26.198 29.150 2.776 1.00 35.24 C -ATOM 221 N LEU A 28 23.480 27.932 9.507 1.00 16.74 N -ATOM 222 CA LEU A 28 23.190 28.209 10.912 1.00 16.39 C -ATOM 223 C LEU A 28 23.477 26.954 11.722 1.00 16.86 C -ATOM 224 O LEU A 28 23.954 27.038 12.852 1.00 15.09 O -ATOM 225 CB LEU A 28 21.739 28.679 11.111 1.00 15.94 C -ATOM 226 CG LEU A 28 21.490 30.154 10.741 1.00 16.72 C -ATOM 227 CD1 LEU A 28 20.008 30.496 10.780 1.00 14.38 C -ATOM 228 CD2 LEU A 28 22.302 31.074 11.665 1.00 12.81 C -ATOM 229 N ARG A 29 23.228 25.791 11.121 1.00 16.05 N -ATOM 230 CA ARG A 29 23.498 24.524 11.798 1.00 18.43 C -ATOM 231 C ARG A 29 24.980 24.377 12.076 1.00 19.22 C -ATOM 232 O ARG A 29 25.383 23.987 13.171 1.00 17.97 O -ATOM 233 CB ARG A 29 23.030 23.334 10.969 1.00 18.63 C -ATOM 234 CG ARG A 29 21.596 22.983 11.189 1.00 21.26 C -ATOM 235 CD ARG A 29 21.339 21.572 10.739 1.00 24.71 C -ATOM 236 NE ARG A 29 20.571 21.564 9.513 1.00 29.88 N -ATOM 237 CZ ARG A 29 21.019 21.147 8.340 1.00 29.19 C -ATOM 238 NH1 ARG A 29 22.248 20.682 8.205 1.00 30.52 N -ATOM 239 NH2 ARG A 29 20.232 21.233 7.295 1.00 31.61 N -ATOM 240 N LYS A 30 25.790 24.709 11.078 1.00 19.76 N -ATOM 241 CA LYS A 30 27.235 24.619 11.198 1.00 21.96 C -ATOM 242 C LYS A 30 27.706 25.418 12.417 1.00 20.91 C -ATOM 243 O LYS A 30 28.470 24.916 13.239 1.00 22.15 O -ATOM 244 CB LYS A 30 27.894 25.143 9.915 1.00 25.07 C -ATOM 245 CG LYS A 30 29.404 25.031 9.905 1.00 30.48 C -ATOM 246 CD LYS A 30 30.013 25.631 8.639 1.00 35.43 C -ATOM 247 CE LYS A 30 31.533 25.759 8.778 1.00 37.96 C -ATOM 248 NZ LYS A 30 32.180 26.388 7.584 1.00 41.61 N -ATOM 249 N ILE A 31 27.208 26.643 12.544 1.00 18.38 N -ATOM 250 CA ILE A 31 27.557 27.527 13.652 1.00 16.41 C -ATOM 251 C ILE A 31 27.105 26.932 14.989 1.00 15.39 C -ATOM 252 O ILE A 31 27.888 26.855 15.930 1.00 14.90 O -ATOM 253 CB ILE A 31 26.881 28.920 13.471 1.00 16.63 C -ATOM 254 CG1 ILE A 31 27.419 29.606 12.208 1.00 18.74 C -ATOM 255 CG2 ILE A 31 27.071 29.791 14.713 1.00 15.71 C -ATOM 256 CD1 ILE A 31 26.735 30.946 11.858 1.00 17.27 C -ATOM 257 N ALA A 32 25.853 26.487 15.048 1.00 13.39 N -ATOM 258 CA ALA A 32 25.271 25.930 16.267 1.00 12.76 C -ATOM 259 C ALA A 32 25.994 24.685 16.775 1.00 12.11 C -ATOM 260 O ALA A 32 26.325 24.598 17.946 1.00 10.54 O -ATOM 261 CB ALA A 32 23.790 25.638 16.040 1.00 12.45 C -ATOM 262 N VAL A 33 26.252 23.731 15.886 1.00 11.95 N -ATOM 263 CA VAL A 33 26.932 22.490 16.256 1.00 13.80 C -ATOM 264 C VAL A 33 28.328 22.701 16.855 1.00 14.00 C -ATOM 265 O VAL A 33 28.693 22.048 17.832 1.00 14.07 O -ATOM 266 CB VAL A 33 27.016 21.504 15.044 1.00 13.56 C -ATOM 267 CG1 VAL A 33 27.909 20.318 15.375 1.00 16.07 C -ATOM 268 CG2 VAL A 33 25.621 21.006 14.684 1.00 14.96 C -ATOM 269 N ALA A 34 29.101 23.620 16.281 1.00 14.73 N -ATOM 270 CA ALA A 34 30.443 23.898 16.780 1.00 14.95 C -ATOM 271 C ALA A 34 30.381 24.505 18.178 1.00 15.59 C -ATOM 272 O ALA A 34 31.120 24.085 19.065 1.00 16.65 O -ATOM 273 CB ALA A 34 31.191 24.844 15.833 1.00 16.10 C -ATOM 274 N ALA A 35 29.495 25.480 18.375 1.00 13.20 N -ATOM 275 CA ALA A 35 29.371 26.134 19.671 1.00 13.04 C -ATOM 276 C ALA A 35 28.807 25.200 20.749 1.00 12.91 C -ATOM 277 O ALA A 35 29.245 25.239 21.895 1.00 12.32 O -ATOM 278 CB ALA A 35 28.517 27.387 19.552 1.00 12.14 C -ATOM 279 N ALA A 36 27.878 24.332 20.362 1.00 11.40 N -ATOM 280 CA ALA A 36 27.253 23.416 21.312 1.00 12.63 C -ATOM 281 C ALA A 36 28.128 22.256 21.770 1.00 13.40 C -ATOM 282 O ALA A 36 27.743 21.512 22.668 1.00 13.47 O -ATOM 283 CB ALA A 36 25.952 22.883 20.744 1.00 11.79 C -ATOM 284 N SER A 37 29.286 22.080 21.148 1.00 13.86 N -ATOM 285 CA SER A 37 30.169 20.983 21.520 1.00 15.95 C -ATOM 286 C SER A 37 30.938 21.245 22.818 1.00 16.46 C -ATOM 287 O SER A 37 31.488 20.320 23.406 1.00 18.23 O -ATOM 288 CB SER A 37 31.145 20.689 20.388 1.00 16.93 C -ATOM 289 OG SER A 37 32.100 21.729 20.293 1.00 21.65 O -ATOM 290 N LYS A 38 30.957 22.496 23.272 1.00 16.91 N -ATOM 291 CA LYS A 38 31.657 22.869 24.502 1.00 18.36 C -ATOM 292 C LYS A 38 30.817 23.809 25.382 1.00 15.90 C -ATOM 293 O LYS A 38 31.175 24.975 25.591 1.00 16.72 O -ATOM 294 CB LYS A 38 33.004 23.539 24.156 1.00 23.99 C -ATOM 295 CG LYS A 38 32.907 24.607 23.046 1.00 30.97 C -ATOM 296 CD LYS A 38 34.250 25.320 22.792 1.00 36.44 C -ATOM 297 CE LYS A 38 34.266 26.098 21.456 1.00 38.70 C -ATOM 298 NZ LYS A 38 33.193 27.131 21.321 1.00 39.37 N -ATOM 299 N PRO A 39 29.669 23.321 25.906 1.00 13.53 N -ATOM 300 CA PRO A 39 28.851 24.201 26.747 1.00 11.87 C -ATOM 301 C PRO A 39 29.292 24.248 28.211 1.00 12.05 C -ATOM 302 O PRO A 39 30.027 23.380 28.676 1.00 12.12 O -ATOM 303 CB PRO A 39 27.469 23.560 26.649 1.00 9.34 C -ATOM 304 CG PRO A 39 27.779 22.131 26.593 1.00 10.32 C -ATOM 305 CD PRO A 39 29.009 22.020 25.703 1.00 10.86 C -ATOM 306 N ALA A 40 28.921 25.316 28.898 1.00 11.52 N -ATOM 307 CA ALA A 40 29.192 25.423 30.329 1.00 11.84 C -ATOM 308 C ALA A 40 27.773 25.329 30.894 1.00 10.23 C -ATOM 309 O ALA A 40 26.894 26.080 30.478 1.00 10.42 O -ATOM 310 CB ALA A 40 29.830 26.767 30.673 1.00 11.40 C -ATOM 311 N VAL A 41 27.518 24.345 31.750 1.00 10.73 N -ATOM 312 CA VAL A 41 26.185 24.169 32.333 1.00 9.92 C -ATOM 313 C VAL A 41 26.226 24.295 33.854 1.00 11.64 C -ATOM 314 O VAL A 41 27.026 23.627 34.514 1.00 11.40 O -ATOM 315 CB VAL A 41 25.594 22.772 31.987 1.00 10.67 C -ATOM 316 CG1 VAL A 41 24.204 22.596 32.612 1.00 11.34 C -ATOM 317 CG2 VAL A 41 25.507 22.583 30.475 1.00 11.31 C -ATOM 318 N GLU A 42 25.364 25.147 34.399 1.00 10.94 N -ATOM 319 CA GLU A 42 25.271 25.327 35.845 1.00 12.40 C -ATOM 320 C GLU A 42 23.837 25.095 36.316 1.00 11.42 C -ATOM 321 O GLU A 42 22.898 25.720 35.825 1.00 10.46 O -ATOM 322 CB GLU A 42 25.711 26.721 36.270 1.00 16.26 C -ATOM 323 CG GLU A 42 25.495 26.947 37.768 1.00 23.78 C -ATOM 324 CD GLU A 42 25.944 28.311 38.242 1.00 27.94 C -ATOM 325 OE1 GLU A 42 25.308 29.329 37.872 1.00 29.92 O -ATOM 326 OE2 GLU A 42 26.935 28.351 39.002 1.00 32.64 O -ATOM 327 N ILE A 43 23.673 24.176 37.261 1.00 10.55 N -ATOM 328 CA ILE A 43 22.362 23.864 37.794 1.00 10.69 C -ATOM 329 C ILE A 43 22.360 24.120 39.300 1.00 11.07 C -ATOM 330 O ILE A 43 23.307 23.764 39.992 1.00 10.83 O -ATOM 331 CB ILE A 43 21.996 22.374 37.552 1.00 10.47 C -ATOM 332 CG1 ILE A 43 21.974 22.072 36.056 1.00 10.46 C -ATOM 333 CG2 ILE A 43 20.636 22.031 38.186 1.00 10.34 C -ATOM 334 CD1 ILE A 43 21.607 20.639 35.726 1.00 9.00 C -ATOM 335 N LYS A 44 21.315 24.784 39.778 1.00 12.26 N -ATOM 336 CA LYS A 44 21.127 25.051 41.201 1.00 13.96 C -ATOM 337 C LYS A 44 19.729 24.528 41.516 1.00 14.16 C -ATOM 338 O LYS A 44 18.749 24.920 40.873 1.00 14.12 O -ATOM 339 CB LYS A 44 21.220 26.545 41.503 1.00 16.58 C -ATOM 340 CG LYS A 44 22.580 27.150 41.170 1.00 22.90 C -ATOM 341 CD LYS A 44 22.571 28.654 41.385 1.00 29.01 C -ATOM 342 CE LYS A 44 23.890 29.293 40.982 1.00 31.56 C -ATOM 343 NZ LYS A 44 23.818 30.781 41.111 1.00 34.70 N -ATOM 344 N GLN A 45 19.649 23.594 42.460 1.00 15.66 N -ATOM 345 CA GLN A 45 18.377 22.993 42.852 1.00 16.03 C -ATOM 346 C GLN A 45 18.098 23.182 44.342 1.00 17.60 C -ATOM 347 O GLN A 45 18.989 23.024 45.164 1.00 17.17 O -ATOM 348 CB GLN A 45 18.397 21.498 42.544 1.00 15.51 C -ATOM 349 CG GLN A 45 17.168 20.744 43.015 1.00 13.62 C -ATOM 350 CD GLN A 45 17.312 19.256 42.838 1.00 15.68 C -ATOM 351 OE1 GLN A 45 18.348 18.769 42.397 1.00 18.84 O -ATOM 352 NE2 GLN A 45 16.276 18.521 43.177 1.00 16.73 N -ATOM 353 N GLU A 46 16.868 23.551 44.670 1.00 18.48 N -ATOM 354 CA GLU A 46 16.441 23.718 46.062 1.00 21.26 C -ATOM 355 C GLU A 46 15.108 23.004 46.105 1.00 19.06 C -ATOM 356 O GLU A 46 14.080 23.589 45.784 1.00 20.08 O -ATOM 357 CB GLU A 46 16.239 25.194 46.408 1.00 26.45 C -ATOM 358 CG GLU A 46 17.284 25.787 47.361 1.00 37.46 C -ATOM 359 CD GLU A 46 17.093 25.374 48.832 1.00 42.24 C -ATOM 360 OE1 GLU A 46 16.192 25.944 49.501 1.00 44.05 O -ATOM 361 OE2 GLU A 46 17.867 24.507 49.320 1.00 44.14 O -ATOM 362 N GLY A 47 15.131 21.720 46.429 1.00 18.35 N -ATOM 363 CA GLY A 47 13.893 20.970 46.463 1.00 18.96 C -ATOM 364 C GLY A 47 13.382 20.755 45.053 1.00 18.27 C -ATOM 365 O GLY A 47 14.067 20.157 44.238 1.00 18.05 O -ATOM 366 N ASP A 48 12.194 21.262 44.755 1.00 16.66 N -ATOM 367 CA ASP A 48 11.617 21.107 43.420 1.00 16.86 C -ATOM 368 C ASP A 48 11.771 22.378 42.566 1.00 15.92 C -ATOM 369 O ASP A 48 11.139 22.511 41.504 1.00 14.50 O -ATOM 370 CB ASP A 48 10.136 20.694 43.513 1.00 19.00 C -ATOM 371 CG ASP A 48 9.943 19.221 43.897 1.00 21.49 C -ATOM 372 OD1 ASP A 48 10.901 18.406 43.840 1.00 23.51 O -ATOM 373 OD2 ASP A 48 8.802 18.868 44.243 1.00 25.04 O -ATOM 374 N THR A 49 12.610 23.299 43.042 1.00 13.75 N -ATOM 375 CA THR A 49 12.870 24.551 42.348 1.00 13.82 C -ATOM 376 C THR A 49 14.231 24.460 41.678 1.00 13.22 C -ATOM 377 O THR A 49 15.235 24.152 42.322 1.00 12.56 O -ATOM 378 CB THR A 49 12.847 25.741 43.316 1.00 16.10 C -ATOM 379 OG1 THR A 49 11.556 25.815 43.941 1.00 17.94 O -ATOM 380 CG2 THR A 49 13.100 27.037 42.571 1.00 16.15 C -ATOM 381 N PHE A 50 14.266 24.794 40.392 1.00 12.20 N -ATOM 382 CA PHE A 50 15.485 24.704 39.602 1.00 10.82 C -ATOM 383 C PHE A 50 15.842 25.979 38.855 1.00 10.40 C -ATOM 384 O PHE A 50 14.968 26.758 38.460 1.00 9.90 O -ATOM 385 CB PHE A 50 15.338 23.591 38.547 1.00 10.78 C -ATOM 386 CG PHE A 50 15.316 22.192 39.107 1.00 13.13 C -ATOM 387 CD1 PHE A 50 14.146 21.653 39.634 1.00 11.97 C -ATOM 388 CD2 PHE A 50 16.464 21.401 39.079 1.00 14.34 C -ATOM 389 CE1 PHE A 50 14.113 20.367 40.120 1.00 12.69 C -ATOM 390 CE2 PHE A 50 16.439 20.098 39.569 1.00 14.64 C -ATOM 391 CZ PHE A 50 15.258 19.582 40.092 1.00 13.15 C -ATOM 392 N TYR A 51 17.147 26.165 38.678 1.00 10.37 N -ATOM 393 CA TYR A 51 17.709 27.258 37.910 1.00 10.95 C -ATOM 394 C TYR A 51 18.714 26.513 37.039 1.00 9.84 C -ATOM 395 O TYR A 51 19.540 25.761 37.547 1.00 9.78 O -ATOM 396 CB TYR A 51 18.436 28.284 38.790 1.00 12.57 C -ATOM 397 CG TYR A 51 19.396 29.178 38.014 1.00 12.91 C -ATOM 398 CD1 TYR A 51 18.939 30.302 37.327 1.00 15.83 C -ATOM 399 CD2 TYR A 51 20.762 28.896 37.974 1.00 14.05 C -ATOM 400 CE1 TYR A 51 19.822 31.126 36.621 1.00 16.52 C -ATOM 401 CE2 TYR A 51 21.655 29.705 37.275 1.00 14.62 C -ATOM 402 CZ TYR A 51 21.179 30.818 36.604 1.00 16.59 C -ATOM 403 OH TYR A 51 22.060 31.633 35.932 1.00 17.52 O -ATOM 404 N ILE A 52 18.610 26.676 35.726 1.00 10.57 N -ATOM 405 CA ILE A 52 19.520 26.004 34.801 1.00 9.09 C -ATOM 406 C ILE A 52 20.066 27.020 33.801 1.00 8.55 C -ATOM 407 O ILE A 52 19.296 27.652 33.086 1.00 10.49 O -ATOM 408 CB ILE A 52 18.807 24.859 34.026 1.00 8.96 C -ATOM 409 CG1 ILE A 52 18.242 23.814 35.013 1.00 9.15 C -ATOM 410 CG2 ILE A 52 19.792 24.189 33.070 1.00 10.39 C -ATOM 411 CD1 ILE A 52 17.585 22.616 34.366 1.00 8.10 C -ATOM 412 N LYS A 53 21.388 27.197 33.791 1.00 8.61 N -ATOM 413 CA LYS A 53 22.049 28.115 32.868 1.00 9.66 C -ATOM 414 C LYS A 53 22.939 27.319 31.924 1.00 8.71 C -ATOM 415 O LYS A 53 23.815 26.583 32.362 1.00 7.58 O -ATOM 416 CB LYS A 53 22.909 29.120 33.611 1.00 10.60 C -ATOM 417 CG LYS A 53 23.580 30.135 32.688 1.00 14.21 C -ATOM 418 CD LYS A 53 24.496 31.006 33.505 1.00 20.27 C -ATOM 419 CE LYS A 53 24.831 32.319 32.828 1.00 26.91 C -ATOM 420 NZ LYS A 53 25.878 33.009 33.659 1.00 29.12 N -ATOM 421 N THR A 54 22.686 27.445 30.625 1.00 8.49 N -ATOM 422 CA THR A 54 23.478 26.747 29.628 1.00 7.98 C -ATOM 423 C THR A 54 24.118 27.820 28.764 1.00 8.23 C -ATOM 424 O THR A 54 23.433 28.584 28.087 1.00 8.40 O -ATOM 425 CB THR A 54 22.621 25.817 28.789 1.00 8.33 C -ATOM 426 OG1 THR A 54 21.896 24.946 29.660 1.00 9.95 O -ATOM 427 CG2 THR A 54 23.505 24.976 27.873 1.00 4.95 C -ATOM 428 N SER A 55 25.444 27.840 28.758 1.00 8.75 N -ATOM 429 CA SER A 55 26.171 28.865 28.047 1.00 10.50 C -ATOM 430 C SER A 55 27.116 28.382 26.950 1.00 9.24 C -ATOM 431 O SER A 55 27.802 27.370 27.101 1.00 8.98 O -ATOM 432 CB SER A 55 26.934 29.694 29.082 1.00 13.09 C -ATOM 433 OG SER A 55 27.781 30.646 28.473 1.00 23.11 O -ATOM 434 N THR A 56 27.091 29.094 25.825 1.00 8.86 N -ATOM 435 CA THR A 56 27.978 28.831 24.684 1.00 8.05 C -ATOM 436 C THR A 56 28.393 30.215 24.138 1.00 8.09 C -ATOM 437 O THR A 56 27.834 31.237 24.525 1.00 7.17 O -ATOM 438 CB THR A 56 27.296 28.024 23.534 1.00 6.70 C -ATOM 439 OG1 THR A 56 26.294 28.829 22.909 1.00 9.76 O -ATOM 440 CG2 THR A 56 26.653 26.751 24.049 1.00 7.76 C -ATOM 441 N THR A 57 29.381 30.242 23.249 1.00 9.17 N -ATOM 442 CA THR A 57 29.871 31.485 22.644 1.00 8.49 C -ATOM 443 C THR A 57 28.820 32.222 21.802 1.00 7.50 C -ATOM 444 O THR A 57 28.952 33.412 21.565 1.00 9.40 O -ATOM 445 CB THR A 57 31.091 31.205 21.716 1.00 9.12 C -ATOM 446 OG1 THR A 57 30.758 30.171 20.786 1.00 9.41 O -ATOM 447 CG2 THR A 57 32.297 30.775 22.516 1.00 11.48 C -ATOM 448 N VAL A 58 27.786 31.510 21.356 1.00 8.04 N -ATOM 449 CA VAL A 58 26.733 32.090 20.500 1.00 9.09 C -ATOM 450 C VAL A 58 25.328 32.224 21.102 1.00 8.67 C -ATOM 451 O VAL A 58 24.466 32.892 20.531 1.00 6.97 O -ATOM 452 CB VAL A 58 26.602 31.287 19.155 1.00 9.96 C -ATOM 453 CG1 VAL A 58 27.976 31.161 18.454 1.00 11.08 C -ATOM 454 CG2 VAL A 58 26.010 29.890 19.404 1.00 9.41 C -ATOM 455 N ARG A 59 25.100 31.620 22.266 1.00 8.88 N -ATOM 456 CA ARG A 59 23.783 31.655 22.882 1.00 9.95 C -ATOM 457 C ARG A 59 23.843 31.140 24.303 1.00 10.14 C -ATOM 458 O ARG A 59 24.440 30.108 24.556 1.00 10.10 O -ATOM 459 CB ARG A 59 22.837 30.751 22.074 1.00 13.11 C -ATOM 460 CG ARG A 59 21.417 30.569 22.623 1.00 16.80 C -ATOM 461 CD ARG A 59 20.521 29.961 21.535 1.00 18.74 C -ATOM 462 NE ARG A 59 19.250 29.440 22.032 1.00 20.63 N -ATOM 463 CZ ARG A 59 18.147 30.165 22.193 1.00 22.94 C -ATOM 464 NH1 ARG A 59 18.138 31.462 21.894 1.00 22.55 N -ATOM 465 NH2 ARG A 59 17.051 29.594 22.686 1.00 23.68 N -ATOM 466 N THR A 60 23.183 31.849 25.211 1.00 11.23 N -ATOM 467 CA THR A 60 23.120 31.458 26.611 1.00 11.84 C -ATOM 468 C THR A 60 21.650 31.500 27.005 1.00 11.73 C -ATOM 469 O THR A 60 20.934 32.423 26.620 1.00 13.69 O -ATOM 470 CB THR A 60 23.916 32.451 27.519 1.00 10.13 C -ATOM 471 OG1 THR A 60 25.320 32.302 27.276 1.00 10.55 O -ATOM 472 CG2 THR A 60 23.632 32.181 29.003 1.00 11.01 C -ATOM 473 N THR A 61 21.183 30.470 27.706 1.00 11.78 N -ATOM 474 CA THR A 61 19.797 30.413 28.175 1.00 11.54 C -ATOM 475 C THR A 61 19.831 30.214 29.686 1.00 10.88 C -ATOM 476 O THR A 61 20.734 29.570 30.205 1.00 9.63 O -ATOM 477 CB THR A 61 18.965 29.229 27.539 1.00 12.65 C -ATOM 478 OG1 THR A 61 19.563 27.976 27.874 1.00 14.13 O -ATOM 479 CG2 THR A 61 18.889 29.336 26.012 1.00 14.15 C -ATOM 480 N GLU A 62 18.878 30.828 30.382 1.00 12.14 N -ATOM 481 CA GLU A 62 18.749 30.698 31.833 1.00 12.88 C -ATOM 482 C GLU A 62 17.283 30.444 32.100 1.00 12.21 C -ATOM 483 O GLU A 62 16.450 31.270 31.745 1.00 13.95 O -ATOM 484 CB GLU A 62 19.151 31.990 32.538 1.00 16.15 C -ATOM 485 CG GLU A 62 20.585 32.344 32.326 1.00 23.65 C -ATOM 486 CD GLU A 62 20.961 33.649 32.979 1.00 29.90 C -ATOM 487 OE1 GLU A 62 20.969 33.703 34.229 1.00 31.84 O -ATOM 488 OE2 GLU A 62 21.258 34.616 32.236 1.00 33.89 O -ATOM 489 N ILE A 63 16.943 29.292 32.657 1.00 10.43 N -ATOM 490 CA ILE A 63 15.548 29.021 32.946 1.00 11.02 C -ATOM 491 C ILE A 63 15.352 28.816 34.446 1.00 11.60 C -ATOM 492 O ILE A 63 16.286 28.434 35.144 1.00 9.20 O -ATOM 493 CB ILE A 63 14.976 27.816 32.125 1.00 11.28 C -ATOM 494 CG1 ILE A 63 15.717 26.519 32.431 1.00 10.60 C -ATOM 495 CG2 ILE A 63 15.020 28.129 30.638 1.00 11.62 C -ATOM 496 CD1 ILE A 63 15.126 25.293 31.720 1.00 13.40 C -ATOM 497 N ASN A 64 14.184 29.219 34.933 1.00 12.13 N -ATOM 498 CA ASN A 64 13.824 29.083 36.343 1.00 14.79 C -ATOM 499 C ASN A 64 12.451 28.441 36.375 1.00 13.29 C -ATOM 500 O ASN A 64 11.490 28.976 35.802 1.00 13.29 O -ATOM 501 CB ASN A 64 13.732 30.450 37.054 1.00 16.87 C -ATOM 502 CG ASN A 64 15.079 31.089 37.279 1.00 20.91 C -ATOM 503 OD1 ASN A 64 15.775 30.764 38.238 1.00 22.91 O -ATOM 504 ND2 ASN A 64 15.459 32.007 36.393 1.00 22.20 N -ATOM 505 N PHE A 65 12.347 27.301 37.044 1.00 12.90 N -ATOM 506 CA PHE A 65 11.058 26.641 37.132 1.00 12.63 C -ATOM 507 C PHE A 65 10.858 25.841 38.410 1.00 13.07 C -ATOM 508 O PHE A 65 11.811 25.531 39.121 1.00 12.50 O -ATOM 509 CB PHE A 65 10.829 25.731 35.922 1.00 11.31 C -ATOM 510 CG PHE A 65 11.794 24.586 35.825 1.00 12.32 C -ATOM 511 CD1 PHE A 65 11.549 23.386 36.494 1.00 10.31 C -ATOM 512 CD2 PHE A 65 12.947 24.706 35.070 1.00 11.23 C -ATOM 513 CE1 PHE A 65 12.441 22.329 36.413 1.00 11.00 C -ATOM 514 CE2 PHE A 65 13.847 23.645 34.984 1.00 11.69 C -ATOM 515 CZ PHE A 65 13.593 22.461 35.655 1.00 12.20 C -ATOM 516 N LYS A 66 9.599 25.560 38.713 1.00 13.15 N -ATOM 517 CA LYS A 66 9.251 24.735 39.849 1.00 13.41 C -ATOM 518 C LYS A 66 8.555 23.552 39.178 1.00 12.17 C -ATOM 519 O LYS A 66 7.763 23.747 38.251 1.00 12.93 O -ATOM 520 CB LYS A 66 8.313 25.498 40.800 1.00 16.68 C -ATOM 521 CG LYS A 66 7.722 24.639 41.907 1.00 24.60 C -ATOM 522 CD LYS A 66 7.391 25.453 43.165 1.00 28.53 C -ATOM 523 CE LYS A 66 6.664 24.585 44.213 1.00 32.17 C -ATOM 524 NZ LYS A 66 7.393 23.332 44.604 1.00 32.54 N -ATOM 525 N VAL A 67 8.918 22.329 39.562 1.00 11.82 N -ATOM 526 CA VAL A 67 8.295 21.141 38.975 1.00 10.93 C -ATOM 527 C VAL A 67 6.783 21.174 39.226 1.00 11.97 C -ATOM 528 O VAL A 67 6.343 21.480 40.342 1.00 13.54 O -ATOM 529 CB VAL A 67 8.908 19.827 39.541 1.00 10.09 C -ATOM 530 CG1 VAL A 67 8.271 18.617 38.883 1.00 10.96 C -ATOM 531 CG2 VAL A 67 10.410 19.808 39.320 1.00 10.21 C -ATOM 532 N GLY A 68 6.006 20.965 38.160 1.00 9.80 N -ATOM 533 CA GLY A 68 4.557 20.962 38.265 1.00 9.33 C -ATOM 534 C GLY A 68 3.887 22.298 38.031 1.00 10.60 C -ATOM 535 O GLY A 68 2.653 22.389 38.039 1.00 11.93 O -ATOM 536 N GLU A 69 4.688 23.337 37.809 1.00 11.12 N -ATOM 537 CA GLU A 69 4.165 24.682 37.553 1.00 12.64 C -ATOM 538 C GLU A 69 4.604 25.185 36.184 1.00 13.09 C -ATOM 539 O GLU A 69 5.774 25.107 35.820 1.00 12.17 O -ATOM 540 CB GLU A 69 4.578 25.642 38.668 1.00 12.20 C -ATOM 541 CG GLU A 69 3.857 25.282 39.964 1.00 17.44 C -ATOM 542 CD GLU A 69 4.116 26.211 41.138 1.00 21.02 C -ATOM 543 OE1 GLU A 69 4.496 27.384 40.945 1.00 21.43 O -ATOM 544 OE2 GLU A 69 3.902 25.753 42.282 1.00 23.44 O -ATOM 545 N GLU A 70 3.633 25.622 35.397 1.00 14.53 N -ATOM 546 CA GLU A 70 3.912 26.102 34.059 1.00 15.80 C -ATOM 547 C GLU A 70 4.816 27.329 34.007 1.00 13.72 C -ATOM 548 O GLU A 70 4.761 28.208 34.863 1.00 13.66 O -ATOM 549 CB GLU A 70 2.606 26.359 33.320 1.00 19.99 C -ATOM 550 CG GLU A 70 2.814 26.634 31.851 1.00 28.23 C -ATOM 551 CD GLU A 70 1.518 26.678 31.097 1.00 32.73 C -ATOM 552 OE1 GLU A 70 0.975 25.589 30.789 1.00 35.76 O -ATOM 553 OE2 GLU A 70 1.045 27.802 30.823 1.00 35.75 O -ATOM 554 N PHE A 71 5.713 27.340 33.028 1.00 12.80 N -ATOM 555 CA PHE A 71 6.638 28.448 32.837 1.00 12.36 C -ATOM 556 C PHE A 71 6.856 28.678 31.350 1.00 12.97 C -ATOM 557 O PHE A 71 6.382 27.917 30.516 1.00 12.54 O -ATOM 558 CB PHE A 71 7.975 28.243 33.589 1.00 10.02 C -ATOM 559 CG PHE A 71 8.851 27.148 33.033 1.00 10.48 C -ATOM 560 CD1 PHE A 71 8.549 25.815 33.256 1.00 9.95 C -ATOM 561 CD2 PHE A 71 10.006 27.459 32.331 1.00 9.29 C -ATOM 562 CE1 PHE A 71 9.380 24.811 32.793 1.00 9.74 C -ATOM 563 CE2 PHE A 71 10.832 26.464 31.868 1.00 9.51 C -ATOM 564 CZ PHE A 71 10.518 25.136 32.102 1.00 8.47 C -ATOM 565 N GLU A 72 7.581 29.733 31.028 1.00 15.04 N -ATOM 566 CA GLU A 72 7.826 30.063 29.644 1.00 17.19 C -ATOM 567 C GLU A 72 9.323 30.036 29.357 1.00 15.53 C -ATOM 568 O GLU A 72 10.130 30.511 30.158 1.00 16.16 O -ATOM 569 CB GLU A 72 7.248 31.448 29.379 1.00 22.03 C -ATOM 570 CG GLU A 72 6.700 31.658 28.002 1.00 30.80 C -ATOM 571 CD GLU A 72 6.157 33.060 27.827 1.00 34.75 C -ATOM 572 OE1 GLU A 72 5.014 33.309 28.276 1.00 35.88 O -ATOM 573 OE2 GLU A 72 6.885 33.912 27.255 1.00 38.91 O -ATOM 574 N GLU A 73 9.691 29.378 28.263 1.00 13.46 N -ATOM 575 CA GLU A 73 11.088 29.302 27.836 1.00 13.89 C -ATOM 576 C GLU A 73 11.083 29.318 26.301 1.00 13.70 C -ATOM 577 O GLU A 73 10.159 29.859 25.690 1.00 13.63 O -ATOM 578 CB GLU A 73 11.780 28.032 28.379 1.00 12.63 C -ATOM 579 CG GLU A 73 11.145 26.706 27.986 1.00 10.55 C -ATOM 580 CD GLU A 73 11.997 25.499 28.366 1.00 8.94 C -ATOM 581 OE1 GLU A 73 13.191 25.650 28.642 1.00 12.29 O -ATOM 582 OE2 GLU A 73 11.485 24.374 28.363 1.00 10.37 O -ATOM 583 N GLN A 74 12.115 28.751 25.685 1.00 13.09 N -ATOM 584 CA GLN A 74 12.187 28.691 24.239 1.00 13.16 C -ATOM 585 C GLN A 74 12.618 27.315 23.806 1.00 12.86 C -ATOM 586 O GLN A 74 13.290 26.596 24.552 1.00 13.17 O -ATOM 587 CB GLN A 74 13.218 29.685 23.706 1.00 15.91 C -ATOM 588 CG GLN A 74 12.803 31.133 23.779 1.00 19.68 C -ATOM 589 CD GLN A 74 13.827 32.066 23.159 1.00 21.00 C -ATOM 590 OE1 GLN A 74 15.010 31.730 23.024 1.00 22.37 O -ATOM 591 NE2 GLN A 74 13.373 33.247 22.774 1.00 24.07 N -ATOM 592 N THR A 75 12.229 26.935 22.600 1.00 10.98 N -ATOM 593 CA THR A 75 12.664 25.656 22.056 1.00 11.83 C -ATOM 594 C THR A 75 14.162 25.828 21.729 1.00 11.24 C -ATOM 595 O THR A 75 14.681 26.951 21.764 1.00 9.95 O -ATOM 596 CB THR A 75 11.895 25.325 20.757 1.00 11.93 C -ATOM 597 OG1 THR A 75 12.123 26.366 19.795 1.00 13.31 O -ATOM 598 CG2 THR A 75 10.396 25.202 21.042 1.00 13.29 C -ATOM 599 N VAL A 76 14.841 24.731 21.377 1.00 13.77 N -ATOM 600 CA VAL A 76 16.278 24.762 21.049 1.00 14.39 C -ATOM 601 C VAL A 76 16.612 25.734 19.914 1.00 12.97 C -ATOM 602 O VAL A 76 17.639 26.407 19.956 1.00 13.75 O -ATOM 603 CB VAL A 76 16.827 23.351 20.680 1.00 15.44 C -ATOM 604 CG1 VAL A 76 18.332 23.314 20.844 1.00 17.74 C -ATOM 605 CG2 VAL A 76 16.218 22.293 21.548 1.00 19.99 C -ATOM 606 N ASP A 77 15.730 25.824 18.921 1.00 13.67 N -ATOM 607 CA ASP A 77 15.933 26.727 17.789 1.00 14.47 C -ATOM 608 C ASP A 77 15.486 28.172 18.061 1.00 15.23 C -ATOM 609 O ASP A 77 15.461 29.002 17.153 1.00 14.90 O -ATOM 610 CB ASP A 77 15.301 26.158 16.503 1.00 15.63 C -ATOM 611 CG ASP A 77 13.790 26.007 16.585 1.00 15.92 C -ATOM 612 OD1 ASP A 77 13.260 25.470 17.586 1.00 14.64 O -ATOM 613 OD2 ASP A 77 13.123 26.409 15.613 1.00 17.79 O -ATOM 614 N GLY A 78 15.095 28.445 19.312 1.00 15.17 N -ATOM 615 CA GLY A 78 14.709 29.790 19.726 1.00 15.90 C -ATOM 616 C GLY A 78 13.268 30.281 19.701 1.00 16.89 C -ATOM 617 O GLY A 78 13.038 31.489 19.790 1.00 19.37 O -ATOM 618 N ARG A 79 12.292 29.389 19.620 1.00 16.76 N -ATOM 619 CA ARG A 79 10.896 29.822 19.587 1.00 18.08 C -ATOM 620 C ARG A 79 10.229 29.768 20.961 1.00 16.55 C -ATOM 621 O ARG A 79 10.379 28.787 21.680 1.00 16.57 O -ATOM 622 CB ARG A 79 10.112 28.961 18.604 1.00 20.74 C -ATOM 623 CG ARG A 79 10.667 28.997 17.194 1.00 25.89 C -ATOM 624 CD ARG A 79 9.986 27.976 16.310 1.00 29.77 C -ATOM 625 NE ARG A 79 10.144 26.626 16.842 1.00 34.52 N -ATOM 626 CZ ARG A 79 10.128 25.516 16.109 1.00 35.90 C -ATOM 627 NH1 ARG A 79 9.971 25.580 14.789 1.00 37.70 N -ATOM 628 NH2 ARG A 79 10.266 24.337 16.702 1.00 35.58 N -ATOM 629 N PRO A 80 9.501 30.830 21.352 1.00 15.98 N -ATOM 630 CA PRO A 80 8.819 30.867 22.651 1.00 15.47 C -ATOM 631 C PRO A 80 7.825 29.725 22.833 1.00 14.23 C -ATOM 632 O PRO A 80 7.058 29.393 21.926 1.00 14.56 O -ATOM 633 CB PRO A 80 8.100 32.220 22.628 1.00 15.48 C -ATOM 634 CG PRO A 80 9.010 33.057 21.846 1.00 18.18 C -ATOM 635 CD PRO A 80 9.418 32.145 20.696 1.00 17.08 C -ATOM 636 N CYS A 81 7.817 29.148 24.028 1.00 13.52 N -ATOM 637 CA CYS A 81 6.914 28.055 24.331 1.00 12.41 C -ATOM 638 C CYS A 81 6.548 28.054 25.811 1.00 12.52 C -ATOM 639 O CYS A 81 7.202 28.718 26.624 1.00 11.74 O -ATOM 640 CB CYS A 81 7.563 26.705 23.950 1.00 11.59 C -ATOM 641 SG CYS A 81 9.063 26.255 24.894 1.00 12.86 S -ATOM 642 N LYS A 82 5.448 27.379 26.121 1.00 13.86 N -ATOM 643 CA LYS A 82 4.988 27.197 27.492 1.00 14.38 C -ATOM 644 C LYS A 82 5.436 25.779 27.839 1.00 13.51 C -ATOM 645 O LYS A 82 5.227 24.842 27.063 1.00 12.69 O -ATOM 646 CB LYS A 82 3.473 27.299 27.589 1.00 18.36 C -ATOM 647 CG LYS A 82 2.940 28.716 27.584 1.00 26.02 C -ATOM 648 CD LYS A 82 3.353 29.506 28.826 1.00 31.13 C -ATOM 649 CE LYS A 82 2.686 30.894 28.832 1.00 35.39 C -ATOM 650 NZ LYS A 82 2.868 31.652 30.120 1.00 37.63 N -ATOM 651 N SER A 83 6.110 25.638 28.974 1.00 11.15 N -ATOM 652 CA SER A 83 6.624 24.352 29.397 1.00 10.10 C -ATOM 653 C SER A 83 6.083 23.931 30.752 1.00 11.16 C -ATOM 654 O SER A 83 5.721 24.769 31.575 1.00 10.21 O -ATOM 655 CB SER A 83 8.149 24.418 29.446 1.00 10.30 C -ATOM 656 OG SER A 83 8.686 24.518 28.132 1.00 11.50 O -ATOM 657 N LEU A 84 6.028 22.620 30.954 1.00 11.17 N -ATOM 658 CA LEU A 84 5.557 22.016 32.192 1.00 11.84 C -ATOM 659 C LEU A 84 6.427 20.793 32.470 1.00 10.42 C -ATOM 660 O LEU A 84 6.444 19.846 31.684 1.00 11.20 O -ATOM 661 CB LEU A 84 4.091 21.576 32.067 1.00 13.44 C -ATOM 662 CG LEU A 84 3.552 20.784 33.270 1.00 15.74 C -ATOM 663 CD1 LEU A 84 3.515 21.683 34.484 1.00 16.96 C -ATOM 664 CD2 LEU A 84 2.178 20.231 32.982 1.00 18.76 C -ATOM 665 N VAL A 85 7.146 20.828 33.589 1.00 9.60 N -ATOM 666 CA VAL A 85 8.028 19.738 34.006 1.00 9.50 C -ATOM 667 C VAL A 85 7.344 18.878 35.082 1.00 9.74 C -ATOM 668 O VAL A 85 6.680 19.404 35.985 1.00 9.28 O -ATOM 669 CB VAL A 85 9.384 20.291 34.598 1.00 8.89 C -ATOM 670 CG1 VAL A 85 10.327 19.140 34.970 1.00 8.20 C -ATOM 671 CG2 VAL A 85 10.062 21.227 33.612 1.00 8.48 C -ATOM 672 N LYS A 86 7.504 17.563 34.971 1.00 9.96 N -ATOM 673 CA LYS A 86 6.946 16.621 35.945 1.00 11.92 C -ATOM 674 C LYS A 86 8.003 15.558 36.247 1.00 11.88 C -ATOM 675 O LYS A 86 8.917 15.340 35.453 1.00 11.00 O -ATOM 676 CB LYS A 86 5.700 15.911 35.385 1.00 12.40 C -ATOM 677 CG LYS A 86 4.538 16.819 35.058 1.00 16.01 C -ATOM 678 CD LYS A 86 3.333 16.017 34.559 1.00 21.36 C -ATOM 679 CE LYS A 86 2.140 16.939 34.345 1.00 23.23 C -ATOM 680 NZ LYS A 86 0.919 16.212 33.929 1.00 28.41 N -ATOM 681 N TRP A 87 7.868 14.889 37.386 1.00 10.75 N -ATOM 682 CA TRP A 87 8.775 13.811 37.738 1.00 9.53 C -ATOM 683 C TRP A 87 8.238 12.559 37.052 1.00 9.89 C -ATOM 684 O TRP A 87 7.144 12.107 37.370 1.00 11.80 O -ATOM 685 CB TRP A 87 8.791 13.569 39.268 1.00 8.76 C -ATOM 686 CG TRP A 87 9.494 14.641 40.062 1.00 8.86 C -ATOM 687 CD1 TRP A 87 8.923 15.525 40.939 1.00 8.80 C -ATOM 688 CD2 TRP A 87 10.889 14.990 39.992 1.00 9.42 C -ATOM 689 NE1 TRP A 87 9.872 16.410 41.400 1.00 8.01 N -ATOM 690 CE2 TRP A 87 11.086 16.103 40.835 1.00 10.85 C -ATOM 691 CE3 TRP A 87 11.985 14.475 39.283 1.00 9.60 C -ATOM 692 CZ2 TRP A 87 12.340 16.716 40.994 1.00 11.45 C -ATOM 693 CZ3 TRP A 87 13.230 15.084 39.438 1.00 10.72 C -ATOM 694 CH2 TRP A 87 13.395 16.192 40.289 1.00 11.78 C -ATOM 695 N GLU A 88 8.954 12.040 36.064 1.00 9.93 N -ATOM 696 CA GLU A 88 8.526 10.807 35.416 1.00 11.30 C -ATOM 697 C GLU A 88 8.826 9.726 36.448 1.00 11.75 C -ATOM 698 O GLU A 88 8.068 8.784 36.623 1.00 12.78 O -ATOM 699 CB GLU A 88 9.337 10.541 34.156 1.00 13.50 C -ATOM 700 CG GLU A 88 8.917 9.261 33.454 1.00 18.67 C -ATOM 701 CD GLU A 88 9.756 8.958 32.226 1.00 23.49 C -ATOM 702 OE1 GLU A 88 9.581 9.650 31.205 1.00 26.53 O -ATOM 703 OE2 GLU A 88 10.587 8.025 32.276 1.00 26.54 O -ATOM 704 N SER A 89 9.972 9.870 37.103 1.00 11.49 N -ATOM 705 CA SER A 89 10.402 8.954 38.158 1.00 11.10 C -ATOM 706 C SER A 89 11.206 9.776 39.163 1.00 11.14 C -ATOM 707 O SER A 89 11.397 10.983 38.979 1.00 9.92 O -ATOM 708 CB SER A 89 11.221 7.778 37.604 1.00 12.43 C -ATOM 709 OG SER A 89 12.396 8.215 36.947 1.00 14.39 O -ATOM 710 N GLU A 90 11.674 9.130 40.227 1.00 10.17 N -ATOM 711 CA GLU A 90 12.433 9.826 41.254 1.00 10.83 C -ATOM 712 C GLU A 90 13.657 10.629 40.772 1.00 9.86 C -ATOM 713 O GLU A 90 13.932 11.715 41.289 1.00 10.30 O -ATOM 714 CB GLU A 90 12.858 8.846 42.348 1.00 11.92 C -ATOM 715 CG GLU A 90 13.536 9.572 43.487 1.00 16.53 C -ATOM 716 CD GLU A 90 13.912 8.671 44.644 1.00 19.80 C -ATOM 717 OE1 GLU A 90 14.122 7.464 44.426 1.00 21.18 O -ATOM 718 OE2 GLU A 90 14.012 9.187 45.774 1.00 22.91 O -ATOM 719 N ASN A 91 14.376 10.102 39.783 1.00 8.79 N -ATOM 720 CA ASN A 91 15.578 10.767 39.274 1.00 10.50 C -ATOM 721 C ASN A 91 15.455 11.289 37.855 1.00 9.69 C -ATOM 722 O ASN A 91 16.467 11.627 37.246 1.00 7.10 O -ATOM 723 CB ASN A 91 16.760 9.798 39.305 1.00 14.33 C -ATOM 724 CG ASN A 91 17.064 9.307 40.693 1.00 17.71 C -ATOM 725 OD1 ASN A 91 17.445 10.087 41.560 1.00 20.87 O -ATOM 726 ND2 ASN A 91 16.855 8.016 40.928 1.00 19.39 N -ATOM 727 N LYS A 92 14.230 11.387 37.352 1.00 8.60 N -ATOM 728 CA LYS A 92 14.016 11.835 35.981 1.00 8.88 C -ATOM 729 C LYS A 92 12.861 12.812 35.807 1.00 8.61 C -ATOM 730 O LYS A 92 11.721 12.511 36.168 1.00 8.95 O -ATOM 731 CB LYS A 92 13.781 10.626 35.078 1.00 9.10 C -ATOM 732 CG LYS A 92 13.566 10.996 33.618 1.00 11.95 C -ATOM 733 CD LYS A 92 13.467 9.762 32.759 1.00 14.04 C -ATOM 734 CE LYS A 92 13.333 10.124 31.299 1.00 16.33 C -ATOM 735 NZ LYS A 92 13.129 8.884 30.506 1.00 17.37 N -ATOM 736 N MET A 93 13.172 13.988 35.268 1.00 7.58 N -ATOM 737 CA MET A 93 12.159 14.985 34.995 1.00 8.21 C -ATOM 738 C MET A 93 11.915 15.038 33.496 1.00 9.18 C -ATOM 739 O MET A 93 12.833 14.838 32.690 1.00 7.74 O -ATOM 740 CB MET A 93 12.565 16.359 35.523 1.00 9.68 C -ATOM 741 CG MET A 93 13.826 16.925 34.937 1.00 13.16 C -ATOM 742 SD MET A 93 14.238 18.543 35.628 1.00 17.49 S -ATOM 743 CE MET A 93 15.009 18.106 37.076 1.00 18.53 C -ATOM 744 N VAL A 94 10.658 15.239 33.128 1.00 9.48 N -ATOM 745 CA VAL A 94 10.266 15.334 31.726 1.00 9.55 C -ATOM 746 C VAL A 94 9.516 16.639 31.528 1.00 10.10 C -ATOM 747 O VAL A 94 8.683 17.024 32.364 1.00 9.47 O -ATOM 748 CB VAL A 94 9.371 14.164 31.315 1.00 11.05 C -ATOM 749 CG1 VAL A 94 8.878 14.354 29.878 1.00 12.88 C -ATOM 750 CG2 VAL A 94 10.147 12.866 31.420 1.00 14.00 C -ATOM 751 N CYS A 95 9.802 17.312 30.413 1.00 9.49 N -ATOM 752 CA CYS A 95 9.169 18.582 30.094 1.00 8.82 C -ATOM 753 C CYS A 95 8.431 18.559 28.758 1.00 11.70 C -ATOM 754 O CYS A 95 9.014 18.215 27.723 1.00 12.29 O -ATOM 755 CB CYS A 95 10.229 19.679 30.059 1.00 8.79 C -ATOM 756 SG CYS A 95 9.620 21.322 29.690 1.00 10.97 S -ATOM 757 N GLU A 96 7.149 18.902 28.791 1.00 10.87 N -ATOM 758 CA GLU A 96 6.342 18.962 27.587 1.00 14.78 C -ATOM 759 C GLU A 96 6.267 20.439 27.182 1.00 13.83 C -ATOM 760 O GLU A 96 6.044 21.311 28.030 1.00 12.79 O -ATOM 761 CB GLU A 96 4.957 18.397 27.885 1.00 20.21 C -ATOM 762 CG GLU A 96 3.981 18.432 26.726 1.00 32.46 C -ATOM 763 CD GLU A 96 2.646 17.765 27.065 1.00 38.97 C -ATOM 764 OE1 GLU A 96 2.053 18.108 28.128 1.00 42.61 O -ATOM 765 OE2 GLU A 96 2.201 16.892 26.271 1.00 42.17 O -ATOM 766 N GLN A 97 6.513 20.725 25.903 1.00 13.39 N -ATOM 767 CA GLN A 97 6.489 22.100 25.402 1.00 13.55 C -ATOM 768 C GLN A 97 5.357 22.334 24.400 1.00 15.88 C -ATOM 769 O GLN A 97 5.013 21.455 23.591 1.00 16.25 O -ATOM 770 CB GLN A 97 7.823 22.465 24.747 1.00 12.20 C -ATOM 771 CG GLN A 97 9.033 22.324 25.650 1.00 12.55 C -ATOM 772 CD GLN A 97 10.321 22.613 24.927 1.00 14.20 C -ATOM 773 OE1 GLN A 97 10.478 22.288 23.749 1.00 12.94 O -ATOM 774 NE2 GLN A 97 11.260 23.235 25.627 1.00 14.75 N -ATOM 775 N LYS A 98 4.801 23.541 24.450 1.00 17.30 N -ATOM 776 CA LYS A 98 3.696 23.952 23.582 1.00 19.78 C -ATOM 777 C LYS A 98 3.990 25.340 23.019 1.00 18.56 C -ATOM 778 O LYS A 98 4.162 26.293 23.771 1.00 17.70 O -ATOM 779 CB LYS A 98 2.389 23.953 24.389 1.00 23.30 C -ATOM 780 CG LYS A 98 1.294 24.857 23.867 1.00 30.94 C -ATOM 781 CD LYS A 98 0.210 25.047 24.934 1.00 37.10 C -ATOM 782 CE LYS A 98 -0.849 26.072 24.520 1.00 39.73 C -ATOM 783 NZ LYS A 98 -0.326 27.476 24.541 1.00 42.46 N -ATOM 784 N LEU A 99 4.073 25.445 21.696 1.00 19.35 N -ATOM 785 CA LEU A 99 4.357 26.721 21.041 1.00 21.32 C -ATOM 786 C LEU A 99 3.307 27.770 21.351 1.00 22.86 C -ATOM 787 O LEU A 99 2.108 27.496 21.261 1.00 23.41 O -ATOM 788 CB LEU A 99 4.466 26.542 19.526 1.00 22.09 C -ATOM 789 CG LEU A 99 5.692 25.792 18.997 1.00 22.72 C -ATOM 790 CD1 LEU A 99 5.585 25.639 17.490 1.00 23.04 C -ATOM 791 CD2 LEU A 99 6.951 26.548 19.372 1.00 23.61 C -ATOM 792 N LEU A 100 3.767 28.962 21.722 1.00 24.11 N -ATOM 793 CA LEU A 100 2.879 30.070 22.051 1.00 27.59 C -ATOM 794 C LEU A 100 2.130 30.545 20.815 1.00 30.94 C -ATOM 795 O LEU A 100 0.951 30.908 20.877 1.00 31.34 O -ATOM 796 CB LEU A 100 3.680 31.227 22.640 1.00 25.50 C -ATOM 797 CG LEU A 100 4.254 30.947 24.020 1.00 24.80 C -ATOM 798 CD1 LEU A 100 4.960 32.171 24.542 1.00 26.59 C -ATOM 799 CD2 LEU A 100 3.141 30.554 24.935 1.00 24.80 C -ATOM 800 N LYS A 101 2.835 30.531 19.689 1.00 34.60 N -ATOM 801 CA LYS A 101 2.282 30.961 18.413 1.00 37.81 C -ATOM 802 C LYS A 101 2.847 30.088 17.292 1.00 37.39 C -ATOM 803 O LYS A 101 4.019 29.687 17.319 1.00 37.22 O -ATOM 804 CB LYS A 101 2.653 32.429 18.147 1.00 40.57 C -ATOM 805 CG LYS A 101 2.182 33.426 19.212 1.00 45.13 C -ATOM 806 CD LYS A 101 2.955 34.741 19.125 1.00 48.57 C -ATOM 807 CE LYS A 101 4.479 34.527 19.248 1.00 51.31 C -ATOM 808 NZ LYS A 101 4.917 33.952 20.559 1.00 51.14 N -ATOM 809 N GLY A 102 1.997 29.786 16.318 1.00 37.21 N -ATOM 810 CA GLY A 102 2.423 28.993 15.184 1.00 36.82 C -ATOM 811 C GLY A 102 2.333 27.494 15.344 1.00 36.36 C -ATOM 812 O GLY A 102 1.690 26.977 16.265 1.00 35.74 O -ATOM 813 N GLU A 103 2.954 26.803 14.395 1.00 35.74 N -ATOM 814 CA GLU A 103 2.988 25.348 14.377 1.00 35.50 C -ATOM 815 C GLU A 103 4.418 24.880 14.140 1.00 31.92 C -ATOM 816 O GLU A 103 5.281 25.654 13.723 1.00 31.61 O -ATOM 817 CB GLU A 103 2.077 24.784 13.274 1.00 39.37 C -ATOM 818 CG GLU A 103 0.652 24.422 13.712 1.00 45.52 C -ATOM 819 CD GLU A 103 -0.383 25.503 13.395 1.00 50.23 C -ATOM 820 OE1 GLU A 103 -0.130 26.346 12.499 1.00 53.12 O -ATOM 821 OE2 GLU A 103 -1.464 25.500 14.036 1.00 52.16 O -ATOM 822 N GLY A 104 4.653 23.604 14.414 1.00 28.97 N -ATOM 823 CA GLY A 104 5.967 23.024 14.231 1.00 25.41 C -ATOM 824 C GLY A 104 6.012 21.648 14.863 1.00 22.09 C -ATOM 825 O GLY A 104 4.987 21.160 15.347 1.00 21.89 O -ATOM 826 N PRO A 105 7.176 20.976 14.832 1.00 19.50 N -ATOM 827 CA PRO A 105 7.338 19.640 15.418 1.00 17.92 C -ATOM 828 C PRO A 105 7.020 19.664 16.914 1.00 15.61 C -ATOM 829 O PRO A 105 7.170 20.696 17.567 1.00 14.42 O -ATOM 830 CB PRO A 105 8.828 19.348 15.202 1.00 18.86 C -ATOM 831 CG PRO A 105 9.188 20.164 14.005 1.00 18.76 C -ATOM 832 CD PRO A 105 8.423 21.440 14.199 1.00 18.40 C -ATOM 833 N LYS A 106 6.552 18.541 17.444 1.00 16.02 N -ATOM 834 CA LYS A 106 6.255 18.453 18.868 1.00 16.93 C -ATOM 835 C LYS A 106 7.609 18.305 19.554 1.00 15.49 C -ATOM 836 O LYS A 106 8.397 17.437 19.183 1.00 14.76 O -ATOM 837 CB LYS A 106 5.387 17.229 19.174 1.00 20.98 C -ATOM 838 CG LYS A 106 5.015 17.097 20.662 1.00 27.98 C -ATOM 839 CD LYS A 106 4.463 18.433 21.229 1.00 33.23 C -ATOM 840 CE LYS A 106 4.250 18.417 22.764 1.00 35.21 C -ATOM 841 NZ LYS A 106 5.519 18.251 23.566 1.00 33.75 N -ATOM 842 N THR A 107 7.907 19.167 20.515 1.00 13.91 N -ATOM 843 CA THR A 107 9.203 19.086 21.190 1.00 12.14 C -ATOM 844 C THR A 107 9.083 18.819 22.681 1.00 11.66 C -ATOM 845 O THR A 107 8.061 19.120 23.295 1.00 10.59 O -ATOM 846 CB THR A 107 10.012 20.382 21.016 1.00 12.37 C -ATOM 847 OG1 THR A 107 9.263 21.480 21.547 1.00 12.36 O -ATOM 848 CG2 THR A 107 10.327 20.643 19.544 1.00 12.62 C -ATOM 849 N SER A 108 10.140 18.249 23.250 1.00 10.16 N -ATOM 850 CA SER A 108 10.192 17.975 24.681 1.00 9.98 C -ATOM 851 C SER A 108 11.649 17.774 25.081 1.00 9.90 C -ATOM 852 O SER A 108 12.549 17.774 24.227 1.00 8.48 O -ATOM 853 CB SER A 108 9.370 16.729 25.024 1.00 9.84 C -ATOM 854 OG SER A 108 9.844 15.601 24.313 1.00 13.87 O -ATOM 855 N TRP A 109 11.890 17.708 26.386 1.00 7.96 N -ATOM 856 CA TRP A 109 13.233 17.446 26.894 1.00 7.85 C -ATOM 857 C TRP A 109 13.109 16.693 28.209 1.00 7.56 C -ATOM 858 O TRP A 109 12.053 16.728 28.837 1.00 8.14 O -ATOM 859 CB TRP A 109 14.094 18.722 27.051 1.00 8.25 C -ATOM 860 CG TRP A 109 13.627 19.829 28.007 1.00 8.07 C -ATOM 861 CD1 TRP A 109 13.120 21.046 27.648 1.00 9.28 C -ATOM 862 CD2 TRP A 109 13.745 19.865 29.450 1.00 9.31 C -ATOM 863 NE1 TRP A 109 12.929 21.836 28.760 1.00 9.69 N -ATOM 864 CE2 TRP A 109 13.306 21.136 29.878 1.00 9.04 C -ATOM 865 CE3 TRP A 109 14.186 18.939 30.416 1.00 9.92 C -ATOM 866 CZ2 TRP A 109 13.286 21.515 31.228 1.00 9.72 C -ATOM 867 CZ3 TRP A 109 14.163 19.316 31.758 1.00 10.25 C -ATOM 868 CH2 TRP A 109 13.717 20.593 32.149 1.00 10.11 C -ATOM 869 N THR A 110 14.136 15.924 28.549 1.00 7.39 N -ATOM 870 CA THR A 110 14.168 15.176 29.808 1.00 6.23 C -ATOM 871 C THR A 110 15.577 15.334 30.395 1.00 7.40 C -ATOM 872 O THR A 110 16.558 15.563 29.652 1.00 6.43 O -ATOM 873 CB THR A 110 13.887 13.633 29.626 1.00 7.17 C -ATOM 874 OG1 THR A 110 15.000 13.002 28.973 1.00 7.49 O -ATOM 875 CG2 THR A 110 12.616 13.377 28.803 1.00 6.64 C -ATOM 876 N ARG A 111 15.669 15.293 31.727 1.00 6.72 N -ATOM 877 CA ARG A 111 16.966 15.356 32.425 1.00 6.27 C -ATOM 878 C ARG A 111 16.924 14.287 33.483 1.00 7.89 C -ATOM 879 O ARG A 111 15.928 14.156 34.193 1.00 8.35 O -ATOM 880 CB ARG A 111 17.240 16.722 33.068 1.00 6.20 C -ATOM 881 CG ARG A 111 17.703 17.765 32.060 1.00 7.38 C -ATOM 882 CD ARG A 111 18.100 19.072 32.727 1.00 8.70 C -ATOM 883 NE ARG A 111 18.783 19.965 31.784 1.00 9.83 N -ATOM 884 CZ ARG A 111 18.158 20.804 30.963 1.00 10.23 C -ATOM 885 NH1 ARG A 111 16.840 20.869 30.966 1.00 10.89 N -ATOM 886 NH2 ARG A 111 18.847 21.590 30.144 1.00 11.56 N -ATOM 887 N GLU A 112 17.957 13.464 33.534 1.00 7.64 N -ATOM 888 CA GLU A 112 17.977 12.402 34.527 1.00 10.31 C -ATOM 889 C GLU A 112 19.356 12.142 35.113 1.00 9.93 C -ATOM 890 O GLU A 112 20.367 12.273 34.425 1.00 7.92 O -ATOM 891 CB GLU A 112 17.401 11.118 33.940 1.00 14.05 C -ATOM 892 CG GLU A 112 18.213 10.489 32.836 1.00 20.37 C -ATOM 893 CD GLU A 112 17.484 9.325 32.177 1.00 25.09 C -ATOM 894 OE1 GLU A 112 17.223 8.308 32.883 1.00 22.36 O -ATOM 895 OE2 GLU A 112 17.175 9.443 30.955 1.00 25.10 O -ATOM 896 N LEU A 113 19.387 11.816 36.401 1.00 8.96 N -ATOM 897 CA LEU A 113 20.634 11.503 37.091 1.00 12.04 C -ATOM 898 C LEU A 113 20.789 9.991 37.081 1.00 12.06 C -ATOM 899 O LEU A 113 19.906 9.270 37.559 1.00 12.08 O -ATOM 900 CB LEU A 113 20.575 11.983 38.532 1.00 14.38 C -ATOM 901 CG LEU A 113 20.768 13.465 38.799 1.00 17.46 C -ATOM 902 CD1 LEU A 113 20.709 13.656 40.298 1.00 19.61 C -ATOM 903 CD2 LEU A 113 22.128 13.945 38.266 1.00 18.46 C -ATOM 904 N THR A 114 21.895 9.502 36.535 1.00 11.06 N -ATOM 905 CA THR A 114 22.110 8.062 36.452 1.00 11.74 C -ATOM 906 C THR A 114 22.816 7.522 37.686 1.00 11.41 C -ATOM 907 O THR A 114 23.327 8.282 38.501 1.00 11.47 O -ATOM 908 CB THR A 114 22.894 7.700 35.188 1.00 12.89 C -ATOM 909 OG1 THR A 114 24.109 8.451 35.164 1.00 15.50 O -ATOM 910 CG2 THR A 114 22.075 8.037 33.951 1.00 14.75 C -ATOM 911 N ASN A 115 22.834 6.202 37.808 1.00 13.23 N -ATOM 912 CA ASN A 115 23.441 5.538 38.951 1.00 16.19 C -ATOM 913 C ASN A 115 24.930 5.761 39.139 1.00 14.24 C -ATOM 914 O ASN A 115 25.432 5.626 40.256 1.00 14.74 O -ATOM 915 CB ASN A 115 23.123 4.047 38.918 1.00 21.89 C -ATOM 916 CG ASN A 115 21.703 3.754 39.357 1.00 29.77 C -ATOM 917 OD1 ASN A 115 20.955 3.046 38.669 1.00 34.83 O -ATOM 918 ND2 ASN A 115 21.313 4.310 40.516 1.00 32.90 N -ATOM 919 N ASP A 116 25.626 6.095 38.055 1.00 12.05 N -ATOM 920 CA ASP A 116 27.061 6.364 38.094 1.00 11.99 C -ATOM 921 C ASP A 116 27.424 7.821 38.397 1.00 11.45 C -ATOM 922 O ASP A 116 28.592 8.184 38.393 1.00 12.23 O -ATOM 923 CB ASP A 116 27.764 5.875 36.806 1.00 13.89 C -ATOM 924 CG ASP A 116 27.177 6.474 35.512 1.00 16.58 C -ATOM 925 OD1 ASP A 116 26.263 7.303 35.569 1.00 19.66 O -ATOM 926 OD2 ASP A 116 27.651 6.113 34.422 1.00 20.14 O -ATOM 927 N GLY A 117 26.420 8.647 38.675 1.00 10.58 N -ATOM 928 CA GLY A 117 26.669 10.042 38.997 1.00 9.83 C -ATOM 929 C GLY A 117 26.652 11.019 37.831 1.00 9.97 C -ATOM 930 O GLY A 117 26.945 12.192 38.019 1.00 10.45 O -ATOM 931 N GLU A 118 26.289 10.550 36.638 1.00 9.43 N -ATOM 932 CA GLU A 118 26.242 11.413 35.458 1.00 7.79 C -ATOM 933 C GLU A 118 24.834 11.955 35.213 1.00 7.60 C -ATOM 934 O GLU A 118 23.872 11.565 35.885 1.00 8.05 O -ATOM 935 CB GLU A 118 26.776 10.653 34.241 1.00 8.86 C -ATOM 936 CG GLU A 118 28.227 10.234 34.427 1.00 9.64 C -ATOM 937 CD GLU A 118 28.770 9.370 33.310 1.00 13.39 C -ATOM 938 OE1 GLU A 118 28.036 9.043 32.355 1.00 11.90 O -ATOM 939 OE2 GLU A 118 29.956 8.998 33.405 1.00 16.59 O -ATOM 940 N LEU A 119 24.732 12.884 34.269 1.00 7.57 N -ATOM 941 CA LEU A 119 23.467 13.513 33.917 1.00 6.94 C -ATOM 942 C LEU A 119 23.189 13.277 32.431 1.00 8.29 C -ATOM 943 O LEU A 119 24.070 13.506 31.593 1.00 8.23 O -ATOM 944 CB LEU A 119 23.556 15.023 34.184 1.00 7.83 C -ATOM 945 CG LEU A 119 22.417 15.972 33.810 1.00 9.54 C -ATOM 946 CD1 LEU A 119 21.213 15.661 34.618 1.00 11.05 C -ATOM 947 CD2 LEU A 119 22.822 17.421 34.066 1.00 12.54 C -ATOM 948 N ILE A 120 22.010 12.743 32.119 1.00 6.17 N -ATOM 949 CA ILE A 120 21.638 12.529 30.730 1.00 6.22 C -ATOM 950 C ILE A 120 20.527 13.511 30.354 1.00 7.47 C -ATOM 951 O ILE A 120 19.493 13.580 31.036 1.00 6.54 O -ATOM 952 CB ILE A 120 21.103 11.118 30.485 1.00 7.19 C -ATOM 953 CG1 ILE A 120 22.171 10.070 30.801 1.00 8.26 C -ATOM 954 CG2 ILE A 120 20.556 11.003 29.047 1.00 6.54 C -ATOM 955 CD1 ILE A 120 21.668 8.658 30.600 1.00 9.35 C -ATOM 956 N LEU A 121 20.771 14.301 29.306 1.00 6.41 N -ATOM 957 CA LEU A 121 19.783 15.236 28.779 1.00 6.25 C -ATOM 958 C LEU A 121 19.299 14.693 27.426 1.00 7.41 C -ATOM 959 O LEU A 121 20.115 14.242 26.619 1.00 6.01 O -ATOM 960 CB LEU A 121 20.400 16.624 28.526 1.00 7.37 C -ATOM 961 CG LEU A 121 19.607 17.580 27.597 1.00 7.96 C -ATOM 962 CD1 LEU A 121 18.340 18.117 28.290 1.00 7.91 C -ATOM 963 CD2 LEU A 121 20.501 18.739 27.151 1.00 7.96 C -ATOM 964 N THR A 122 17.988 14.607 27.222 1.00 6.71 N -ATOM 965 CA THR A 122 17.514 14.205 25.898 1.00 7.80 C -ATOM 966 C THR A 122 16.633 15.334 25.402 1.00 8.58 C -ATOM 967 O THR A 122 15.988 16.034 26.194 1.00 7.21 O -ATOM 968 CB THR A 122 16.754 12.843 25.832 1.00 7.51 C -ATOM 969 OG1 THR A 122 15.422 12.992 26.313 1.00 9.27 O -ATOM 970 CG2 THR A 122 17.484 11.759 26.622 1.00 7.86 C -ATOM 971 N MET A 123 16.732 15.613 24.110 1.00 7.87 N -ATOM 972 CA MET A 123 15.904 16.643 23.494 1.00 9.22 C -ATOM 973 C MET A 123 15.194 15.950 22.337 1.00 8.66 C -ATOM 974 O MET A 123 15.828 15.189 21.601 1.00 8.09 O -ATOM 975 CB MET A 123 16.760 17.818 23.019 1.00 9.37 C -ATOM 976 CG MET A 123 17.359 18.612 24.171 1.00 11.81 C -ATOM 977 SD MET A 123 18.325 20.048 23.658 1.00 16.59 S -ATOM 978 CE MET A 123 19.871 19.278 23.173 1.00 14.10 C -ATOM 979 N THR A 124 13.895 16.195 22.186 1.00 7.20 N -ATOM 980 CA THR A 124 13.133 15.534 21.134 1.00 9.54 C -ATOM 981 C THR A 124 12.407 16.513 20.222 1.00 10.12 C -ATOM 982 O THR A 124 11.941 17.563 20.665 1.00 9.54 O -ATOM 983 CB THR A 124 12.073 14.552 21.756 1.00 10.74 C -ATOM 984 OG1 THR A 124 12.740 13.544 22.535 1.00 11.99 O -ATOM 985 CG2 THR A 124 11.247 13.865 20.679 1.00 11.66 C -ATOM 986 N ALA A 125 12.346 16.167 18.935 1.00 11.06 N -ATOM 987 CA ALA A 125 11.634 16.962 17.923 1.00 11.63 C -ATOM 988 C ALA A 125 10.981 15.878 17.078 1.00 13.46 C -ATOM 989 O ALA A 125 11.669 15.144 16.352 1.00 13.11 O -ATOM 990 CB ALA A 125 12.603 17.786 17.091 1.00 13.16 C -ATOM 991 N ASP A 126 9.664 15.754 17.216 1.00 14.63 N -ATOM 992 CA ASP A 126 8.901 14.721 16.536 1.00 17.86 C -ATOM 993 C ASP A 126 9.512 13.364 16.905 1.00 18.66 C -ATOM 994 O ASP A 126 9.519 13.006 18.080 1.00 19.38 O -ATOM 995 CB ASP A 126 8.835 14.982 15.023 1.00 18.40 C -ATOM 996 CG ASP A 126 7.786 16.032 14.660 1.00 22.34 C -ATOM 997 OD1 ASP A 126 6.800 16.198 15.422 1.00 23.23 O -ATOM 998 OD2 ASP A 126 7.940 16.702 13.621 1.00 24.32 O -ATOM 999 N ASP A 127 10.064 12.629 15.945 1.00 20.19 N -ATOM 1000 CA ASP A 127 10.656 11.333 16.271 1.00 21.56 C -ATOM 1001 C ASP A 127 12.175 11.279 16.416 1.00 18.85 C -ATOM 1002 O ASP A 127 12.732 10.219 16.657 1.00 20.67 O -ATOM 1003 CB ASP A 127 10.178 10.263 15.303 1.00 26.47 C -ATOM 1004 CG ASP A 127 9.043 9.450 15.880 1.00 33.21 C -ATOM 1005 OD1 ASP A 127 7.892 9.959 15.934 1.00 36.08 O -ATOM 1006 OD2 ASP A 127 9.318 8.308 16.318 1.00 38.35 O -ATOM 1007 N VAL A 128 12.836 12.418 16.281 1.00 15.22 N -ATOM 1008 CA VAL A 128 14.286 12.486 16.407 1.00 12.83 C -ATOM 1009 C VAL A 128 14.681 12.843 17.835 1.00 11.58 C -ATOM 1010 O VAL A 128 14.176 13.811 18.408 1.00 9.74 O -ATOM 1011 CB VAL A 128 14.864 13.503 15.423 1.00 12.79 C -ATOM 1012 CG1 VAL A 128 16.338 13.757 15.706 1.00 12.93 C -ATOM 1013 CG2 VAL A 128 14.677 12.968 14.005 1.00 14.30 C -ATOM 1014 N VAL A 129 15.586 12.051 18.397 1.00 9.29 N -ATOM 1015 CA VAL A 129 16.054 12.257 19.761 1.00 7.95 C -ATOM 1016 C VAL A 129 17.558 12.546 19.842 1.00 7.49 C -ATOM 1017 O VAL A 129 18.374 11.816 19.276 1.00 8.73 O -ATOM 1018 CB VAL A 129 15.764 11.007 20.617 1.00 9.43 C -ATOM 1019 CG1 VAL A 129 16.153 11.253 22.076 1.00 9.09 C -ATOM 1020 CG2 VAL A 129 14.293 10.610 20.495 1.00 9.45 C -ATOM 1021 N CYS A 130 17.912 13.630 20.534 1.00 7.54 N -ATOM 1022 CA CYS A 130 19.305 14.010 20.756 1.00 6.47 C -ATOM 1023 C CYS A 130 19.670 13.627 22.200 1.00 6.61 C -ATOM 1024 O CYS A 130 18.955 13.992 23.135 1.00 7.53 O -ATOM 1025 CB CYS A 130 19.485 15.517 20.544 1.00 6.05 C -ATOM 1026 SG CYS A 130 21.063 16.183 21.077 1.00 8.82 S -ATOM 1027 N THR A 131 20.786 12.925 22.372 1.00 6.58 N -ATOM 1028 CA THR A 131 21.241 12.462 23.693 1.00 5.93 C -ATOM 1029 C THR A 131 22.569 13.102 24.054 1.00 6.18 C -ATOM 1030 O THR A 131 23.528 13.003 23.294 1.00 5.77 O -ATOM 1031 CB THR A 131 21.419 10.914 23.699 1.00 6.63 C -ATOM 1032 OG1 THR A 131 20.199 10.299 23.289 1.00 7.60 O -ATOM 1033 CG2 THR A 131 21.763 10.399 25.091 1.00 7.76 C -ATOM 1034 N ARG A 132 22.624 13.780 25.202 1.00 6.29 N -ATOM 1035 CA ARG A 132 23.853 14.429 25.660 1.00 7.67 C -ATOM 1036 C ARG A 132 24.108 13.960 27.093 1.00 7.19 C -ATOM 1037 O ARG A 132 23.184 13.895 27.902 1.00 8.65 O -ATOM 1038 CB ARG A 132 23.719 15.957 25.621 1.00 9.67 C -ATOM 1039 CG ARG A 132 22.945 16.470 24.429 1.00 15.02 C -ATOM 1040 CD ARG A 132 23.781 17.260 23.476 1.00 16.80 C -ATOM 1041 NE ARG A 132 24.140 18.580 23.984 1.00 12.48 N -ATOM 1042 CZ ARG A 132 25.030 19.377 23.395 1.00 12.93 C -ATOM 1043 NH1 ARG A 132 25.641 19.005 22.279 1.00 13.84 N -ATOM 1044 NH2 ARG A 132 25.398 20.506 23.973 1.00 11.57 N -ATOM 1045 N VAL A 133 25.359 13.633 27.397 1.00 5.99 N -ATOM 1046 CA VAL A 133 25.739 13.124 28.719 1.00 5.92 C -ATOM 1047 C VAL A 133 26.773 14.055 29.345 1.00 5.85 C -ATOM 1048 O VAL A 133 27.713 14.492 28.681 1.00 5.50 O -ATOM 1049 CB VAL A 133 26.333 11.698 28.608 1.00 6.37 C -ATOM 1050 CG1 VAL A 133 26.609 11.120 29.988 1.00 7.95 C -ATOM 1051 CG2 VAL A 133 25.385 10.782 27.832 1.00 6.46 C -ATOM 1052 N TYR A 134 26.619 14.337 30.635 1.00 5.35 N -ATOM 1053 CA TYR A 134 27.538 15.228 31.322 1.00 4.57 C -ATOM 1054 C TYR A 134 28.014 14.611 32.617 1.00 5.30 C -ATOM 1055 O TYR A 134 27.371 13.712 33.165 1.00 3.92 O -ATOM 1056 CB TYR A 134 26.846 16.550 31.686 1.00 6.84 C -ATOM 1057 CG TYR A 134 26.118 17.251 30.574 1.00 8.89 C -ATOM 1058 CD1 TYR A 134 24.901 16.762 30.122 1.00 10.29 C -ATOM 1059 CD2 TYR A 134 26.628 18.406 29.992 1.00 10.49 C -ATOM 1060 CE1 TYR A 134 24.212 17.386 29.133 1.00 13.03 C -ATOM 1061 CE2 TYR A 134 25.930 19.051 28.982 1.00 12.15 C -ATOM 1062 CZ TYR A 134 24.723 18.517 28.567 1.00 12.80 C -ATOM 1063 OH TYR A 134 23.991 19.082 27.567 1.00 18.07 O -ATOM 1064 N VAL A 135 29.113 15.158 33.119 1.00 6.63 N -ATOM 1065 CA VAL A 135 29.697 14.762 34.394 1.00 8.42 C -ATOM 1066 C VAL A 135 30.100 16.086 35.064 1.00 9.05 C -ATOM 1067 O VAL A 135 30.340 17.086 34.385 1.00 9.02 O -ATOM 1068 CB VAL A 135 30.925 13.815 34.204 1.00 8.05 C -ATOM 1069 CG1 VAL A 135 32.109 14.556 33.596 1.00 9.27 C -ATOM 1070 CG2 VAL A 135 31.304 13.151 35.533 1.00 10.37 C -ATOM 1071 N ARG A 136 30.117 16.133 36.390 1.00 9.57 N -ATOM 1072 CA ARG A 136 30.498 17.375 37.040 1.00 10.86 C -ATOM 1073 C ARG A 136 31.964 17.676 36.776 1.00 11.68 C -ATOM 1074 O ARG A 136 32.782 16.765 36.686 1.00 11.35 O -ATOM 1075 CB ARG A 136 30.221 17.319 38.536 1.00 11.99 C -ATOM 1076 CG ARG A 136 28.746 17.454 38.885 1.00 13.89 C -ATOM 1077 CD ARG A 136 28.576 17.533 40.382 1.00 15.85 C -ATOM 1078 NE ARG A 136 27.185 17.407 40.754 1.00 17.08 N -ATOM 1079 CZ ARG A 136 26.561 16.245 40.926 1.00 21.69 C -ATOM 1080 NH1 ARG A 136 27.217 15.102 40.754 1.00 23.26 N -ATOM 1081 NH2 ARG A 136 25.278 16.227 41.283 1.00 22.60 N -ATOM 1082 N GLU A 137 32.282 18.963 36.663 1.00 15.12 N -ATOM 1083 CA GLU A 137 33.641 19.430 36.400 1.00 18.00 C -ATOM 1084 C GLU A 137 34.615 19.038 37.493 1.00 18.96 C -ATOM 1085 O GLU A 137 34.221 19.175 38.659 1.00 17.37 O -ATOM 1086 CB GLU A 137 33.661 20.943 36.293 1.00 19.89 C -ATOM 1087 CG GLU A 137 33.092 21.492 35.035 1.00 28.03 C -ATOM 1088 CD GLU A 137 33.469 22.953 34.865 1.00 33.22 C -ATOM 1089 OE1 GLU A 137 34.630 23.217 34.473 1.00 37.31 O -ATOM 1090 OE2 GLU A 137 32.636 23.836 35.164 1.00 36.38 O -ATOM 1091 OXT GLU A 137 35.776 18.680 37.173 1.00 22.23 O -TER 1092 GLU A 137 -HETATM 1093 C1 REA A 200 21.972 29.831 16.739 1.00 15.25 C -HETATM 1094 C2 REA A 200 20.921 30.524 15.841 1.00 15.61 C -HETATM 1095 C3 REA A 200 20.245 29.635 14.848 1.00 16.19 C -HETATM 1096 C4 REA A 200 19.555 28.479 15.488 1.00 14.59 C -HETATM 1097 C5 REA A 200 20.389 27.812 16.587 1.00 14.10 C -HETATM 1098 C6 REA A 200 21.425 28.446 17.218 1.00 14.42 C -HETATM 1099 C7 REA A 200 22.242 27.851 18.297 1.00 13.89 C -HETATM 1100 C8 REA A 200 21.868 26.977 19.240 1.00 11.86 C -HETATM 1101 C9 REA A 200 22.705 26.434 20.286 1.00 10.87 C -HETATM 1102 C10 REA A 200 22.159 25.536 21.131 1.00 9.19 C -HETATM 1103 C11 REA A 200 22.875 24.924 22.234 1.00 10.35 C -HETATM 1104 C12 REA A 200 22.237 24.026 22.990 1.00 10.53 C -HETATM 1105 C13 REA A 200 22.856 23.377 24.125 1.00 10.91 C -HETATM 1106 C14 REA A 200 22.135 22.473 24.834 1.00 11.88 C -HETATM 1107 C15 REA A 200 22.563 21.710 26.016 1.00 14.86 C -HETATM 1108 C16 REA A 200 22.238 30.737 17.948 1.00 15.47 C -HETATM 1109 C17 REA A 200 23.292 29.620 15.948 1.00 13.42 C -HETATM 1110 C18 REA A 200 19.791 26.449 16.947 1.00 12.61 C -HETATM 1111 C19 REA A 200 24.181 26.841 20.385 1.00 10.08 C -HETATM 1112 C20 REA A 200 24.303 23.747 24.489 1.00 10.10 C -HETATM 1113 O1 REA A 200 23.640 21.075 25.978 1.00 13.29 O -HETATM 1114 O2 REA A 200 21.840 21.712 27.037 1.00 10.99 O -HETATM 1115 O HOH A 300 21.817 19.604 31.169 1.00 17.43 O -HETATM 1116 O HOH A 301 7.617 26.892 37.107 1.00 12.66 O -HETATM 1117 O HOH A 302 22.885 27.835 25.056 1.00 18.86 O -HETATM 1118 O HOH A 303 30.685 27.402 22.818 1.00 14.12 O -HETATM 1119 O HOH A 304 29.930 20.839 40.398 1.00 16.48 O -HETATM 1120 O HOH A 305 31.492 21.096 28.452 1.00 16.65 O -HETATM 1121 O HOH A 306 19.459 26.601 30.320 1.00 9.81 O -HETATM 1122 O HOH A 307 19.116 26.759 22.930 1.00 22.33 O -HETATM 1123 O HOH A 308 16.356 22.299 28.453 1.00 35.46 O -HETATM 1124 O HOH A 309 21.823 21.939 29.734 1.00 13.95 O -HETATM 1125 O HOH A 310 13.206 22.267 22.102 1.00 20.07 O -HETATM 1126 O HOH A 311 30.300 22.803 12.740 1.00 24.70 O -HETATM 1127 O HOH A 312 7.344 23.059 35.600 1.00 8.82 O -HETATM 1128 O HOH A 313 6.876 22.668 20.375 1.00 29.74 O -HETATM 1129 O HOH A 314 17.917 24.800 29.159 1.00 23.69 O -HETATM 1130 O HOH A 315 37.101 16.714 38.714 1.00 19.84 O -HETATM 1131 O HOH A 316 28.721 7.425 30.043 1.00 14.94 O -HETATM 1132 O HOH A 317 13.212 14.450 25.193 1.00 18.03 O -HETATM 1133 O HOH A 318 6.094 9.777 39.151 1.00 13.98 O -HETATM 1134 O HOH A 319 19.296 10.379 13.144 1.00 27.20 O -HETATM 1135 O HOH A 320 25.337 10.931 16.577 1.00 18.41 O -HETATM 1136 O HOH A 321 25.244 34.269 18.193 1.00 9.65 O -HETATM 1137 O HOH A 322 23.567 10.727 14.429 1.00 11.13 O -HETATM 1138 O HOH A 323 17.151 12.178 30.238 1.00 11.53 O -HETATM 1139 O HOH A 324 27.768 11.967 42.077 1.00 23.33 O -HETATM 1140 O HOH A 325 30.270 12.554 21.386 1.00 25.05 O -HETATM 1141 O HOH A 326 25.662 15.488 18.515 1.00 10.80 O -HETATM 1142 O HOH A 327 4.514 21.426 18.685 1.00 45.94 O -HETATM 1143 O HOH A 328 8.081 23.201 17.690 1.00 30.16 O -HETATM 1144 O HOH A 329 13.242 29.389 14.924 1.00 39.93 O -HETATM 1145 O HOH A 330 10.514 18.772 10.176 1.00 33.65 O -HETATM 1146 O HOH A 331 10.555 13.666 26.313 1.00 32.55 O -HETATM 1147 O HOH A 332 5.189 16.418 31.375 1.00 35.78 O -HETATM 1148 O HOH A 333 0.738 25.633 36.349 1.00 29.00 O -HETATM 1149 O HOH A 334 2.976 28.966 37.321 1.00 40.14 O -HETATM 1150 O HOH A 335 6.424 28.750 38.849 1.00 32.17 O -HETATM 1151 O HOH A 336 12.503 30.488 31.704 1.00 41.11 O -HETATM 1152 O HOH A 337 14.979 30.157 27.559 1.00 23.78 O -HETATM 1153 O HOH A 338 17.312 32.981 28.812 1.00 20.84 O -HETATM 1154 O HOH A 339 29.473 25.946 34.693 1.00 29.05 O -HETATM 1155 O HOH A 340 30.328 23.817 33.494 1.00 24.17 O -HETATM 1156 O HOH A 341 31.158 28.144 26.433 1.00 42.66 O -HETATM 1157 O HOH A 342 30.276 28.397 16.400 1.00 21.90 O -HETATM 1158 O HOH A 343 19.533 23.600 26.857 1.00 21.12 O -HETATM 1159 O HOH A 344 17.892 24.675 24.549 1.00 48.11 O -HETATM 1160 O HOH A 345 14.211 24.152 25.435 1.00 21.09 O -HETATM 1161 O HOH A 346 15.223 27.626 27.056 1.00 27.16 O -HETATM 1162 O HOH A 347 3.502 22.911 43.083 1.00 30.15 O -HETATM 1163 O HOH A 348 20.610 7.668 40.212 1.00 49.06 O -HETATM 1164 O HOH A 349 24.813 2.899 36.403 1.00 48.98 O -HETATM 1165 O HOH A 350 29.900 5.163 26.918 1.00 23.60 O -HETATM 1166 O HOH A 351 14.333 5.466 42.757 1.00 22.90 O -HETATM 1167 O HOH A 352 8.914 5.771 35.515 1.00 35.92 O -HETATM 1168 O HOH A 353 14.519 28.906 40.193 1.00 28.73 O -HETATM 1169 O HOH A 354 17.573 20.203 47.080 1.00 37.63 O -HETATM 1170 O HOH A 355 13.324 32.251 34.152 1.00 47.79 O -HETATM 1171 O HOH A 356 12.491 24.840 7.594 1.00 39.45 O -HETATM 1172 O HOH A 357 25.066 15.777 15.214 1.00 27.39 O -HETATM 1173 O HOH A 358 27.138 17.638 17.834 1.00 45.12 O -HETATM 1174 O HOH A 359 27.611 19.792 19.503 1.00 24.45 O -HETATM 1175 O HOH A 360 11.358 8.880 19.119 1.00 24.31 O -HETATM 1176 O HOH A 361 16.252 27.169 24.557 1.00 25.40 O -HETATM 1177 O HOH A 362 22.049 27.870 4.565 1.00 25.37 O -HETATM 1178 O HOH A 363 11.533 6.689 34.501 1.00 29.92 O -HETATM 1179 O HOH A 364 13.269 4.551 36.338 1.00 45.75 O -HETATM 1180 O HOH A 365 23.149 9.493 41.173 1.00 30.10 O -HETATM 1181 O HOH A 366 21.090 12.171 43.973 1.00 27.97 O -HETATM 1182 O HOH A 367 11.884 13.399 42.560 1.00 23.28 O -HETATM 1183 O HOH A 368 29.542 17.520 20.025 1.00 38.32 O -HETATM 1184 O HOH A 369 31.058 17.427 22.538 1.00 37.85 O -HETATM 1185 O HOH A 370 31.928 9.444 23.294 1.00 46.07 O -HETATM 1186 O HOH A 371 25.699 10.933 9.557 1.00 44.12 O -HETATM 1187 O HOH A 372 26.533 13.428 16.334 1.00 45.21 O -HETATM 1188 O HOH A 373 27.078 16.850 13.245 1.00 39.52 O -HETATM 1189 O HOH A 374 20.596 32.070 6.807 1.00 36.38 O -HETATM 1190 O HOH A 375 17.126 28.421 9.515 1.00 23.81 O -HETATM 1191 O HOH A 376 16.626 32.383 11.231 1.00 20.11 O -HETATM 1192 O HOH A 377 6.046 30.510 19.639 1.00 29.02 O -HETATM 1193 O HOH A 378 9.543 16.072 11.145 1.00 50.91 O -HETATM 1194 O HOH A 379 8.174 14.289 20.240 1.00 54.21 O -HETATM 1195 O HOH A 380 11.561 10.834 22.873 1.00 43.23 O -HETATM 1196 O HOH A 381 5.486 15.385 24.922 1.00 50.19 O -HETATM 1197 O HOH A 382 6.038 21.424 43.276 1.00 46.64 O -HETATM 1198 O HOH A 383 34.144 19.165 27.284 1.00 41.41 O -HETATM 1199 O HOH A 384 16.916 27.142 42.621 1.00 29.32 O -HETATM 1200 O HOH A 385 25.509 24.918 41.520 1.00 32.12 O -HETATM 1201 O HOH A 386 31.446 7.504 31.389 1.00 28.93 O -HETATM 1202 O HOH A 387 18.212 20.893 5.892 1.00 29.90 O -HETATM 1203 O HOH A 388 15.148 27.608 7.685 1.00 30.91 O -HETATM 1204 O HOH A 389 2.656 23.148 20.117 1.00 35.98 O -HETATM 1205 O HOH A 390 3.100 22.690 28.640 1.00 31.31 O -HETATM 1206 O HOH A 391 13.699 19.720 21.819 1.00 26.56 O -HETATM 1207 O HOH A 392 26.833 28.283 32.272 1.00 31.48 O -HETATM 1208 O HOH A 393 20.458 26.214 25.811 1.00 24.39 O -HETATM 1209 O HOH A 394 32.304 27.731 18.152 1.00 41.66 O -HETATM 1210 O HOH A 395 24.283 13.868 42.687 1.00 35.59 O -HETATM 1211 O HOH A 396 11.833 12.657 45.160 1.00 38.30 O -HETATM 1212 O HOH A 397 1.988 27.992 43.589 1.00 33.97 O -HETATM 1213 O HOH A 398 32.913 22.982 40.176 1.00 39.26 O -HETATM 1214 O HOH A 399 32.435 20.043 40.169 1.00 33.87 O -CONECT 1093 1094 1098 1108 1109 -CONECT 1094 1093 1095 -CONECT 1095 1094 1096 -CONECT 1096 1095 1097 -CONECT 1097 1096 1098 1110 -CONECT 1098 1093 1097 1099 -CONECT 1099 1098 1100 -CONECT 1100 1099 1101 -CONECT 1101 1100 1102 1111 -CONECT 1102 1101 1103 -CONECT 1103 1102 1104 -CONECT 1104 1103 1105 -CONECT 1105 1104 1106 1112 -CONECT 1106 1105 1107 -CONECT 1107 1106 1113 1114 -CONECT 1108 1093 -CONECT 1109 1093 -CONECT 1110 1097 -CONECT 1111 1101 -CONECT 1112 1105 -CONECT 1113 1107 -CONECT 1114 1107 -MASTER 264 0 1 2 10 0 3 6 1213 1 22 11 -END diff --git a/mode/examples/Demos/Graphics/Ribbons/data/2POR.pdb b/mode/examples/Demos/Graphics/Ribbons/data/2POR.pdb deleted file mode 100644 index 67a93b82e..000000000 --- a/mode/examples/Demos/Graphics/Ribbons/data/2POR.pdb +++ /dev/null @@ -1,3257 +0,0 @@ -HEADER INTEGRAL MEMBRANE PROTEIN PORIN 24-APR-92 2POR -TITLE STRUCTURE OF PORIN REFINED AT 1.8 ANGSTROMS RESOLUTION -COMPND MOL_ID: 1; -COMPND 2 MOLECULE: PORIN; -COMPND 3 CHAIN: A; -COMPND 4 ENGINEERED: YES -SOURCE MOL_ID: 1; -SOURCE 2 ORGANISM_SCIENTIFIC: RHODOBACTER CAPSULATUS; -SOURCE 3 ORGANISM_TAXID: 1061 -KEYWDS INTEGRAL MEMBRANE PROTEIN PORIN -EXPDTA X-RAY DIFFRACTION -AUTHOR M.S.WEISS,G.E.SCHULZ -REVDAT 3 24-FEB-09 2POR 1 VERSN -REVDAT 2 01-APR-03 2POR 1 JRNL -REVDAT 1 15-JUL-93 2POR 0 -JRNL AUTH M.S.WEISS,G.E.SCHULZ -JRNL TITL STRUCTURE OF PORIN REFINED AT 1.8 A RESOLUTION. -JRNL REF J.MOL.BIOL. V. 227 493 1992 -JRNL REFN ISSN 0022-2836 -JRNL PMID 1328651 -JRNL DOI 10.1016/0022-2836(92)90903-W -REMARK 1 -REMARK 1 REFERENCE 1 -REMARK 1 AUTH M.S.WEISS,U.ABELE,J.WECKESSER,W.WELTE,E.SCHILTZ, -REMARK 1 AUTH 2 G.E.SCHULZ -REMARK 1 TITL MOLECULAR ARCHITECTURE AND ELECTROSTATIC -REMARK 1 TITL 2 PROPERTIES OF A BACTERIAL PORIN -REMARK 1 REF SCIENCE V. 254 1627 1991 -REMARK 1 REFN ISSN 0036-8075 -REMARK 1 REFERENCE 2 -REMARK 1 AUTH E.SCHILTZ,A.KREUSCH,U.NESTEL,G.E.SCHULZ -REMARK 1 TITL PRIMARY STRUCTURE OF PORIN FROM RHODOBACTER -REMARK 1 TITL 2 CAPSULATUS -REMARK 1 REF EUR.J.BIOCHEM. V. 199 587 1991 -REMARK 1 REFN ISSN 0014-2956 -REMARK 1 REFERENCE 3 -REMARK 1 AUTH M.S.WEISS,A.KREUSCH,E.SCHILTZ,U.NESTEL,W.WELTE, -REMARK 1 AUTH 2 J.WECKESSER,G.E.SCHULZ -REMARK 1 TITL THE STRUCTURE OF PORIN FROM RHODOBACTER CAPSULATUS -REMARK 1 TITL 2 AT 1.8 ANGSTROMS RESOLUTION -REMARK 1 REF FEBS LETT. V. 280 379 1991 -REMARK 1 REFN ISSN 0014-5793 -REMARK 1 REFERENCE 4 -REMARK 1 AUTH A.KREUSCH,M.S.WEISS,W.WELTE,J.WECKESSER,G.E.SCHULZ -REMARK 1 TITL CRYSTALS OF AN INTEGRAL MEMBRANE PROTEIN -REMARK 1 TITL 2 DIFFRACTING TO 1.8 ANGSTROMS RESOLUTION -REMARK 1 REF J.MOL.BIOL. V. 217 9 1991 -REMARK 1 REFN ISSN 0022-2836 -REMARK 1 REFERENCE 5 -REMARK 1 AUTH M.S.WEISS,T.WACKER,J.WECKESSER,W.WELTE,G.E.SCHULZ -REMARK 1 TITL THE THREE-DIMENSIONAL STRUCTURE OF PORIN FROM -REMARK 1 TITL 2 RHODOBACTER CAPSULATUS AT 3 ANGSTROMS RESOLUTION -REMARK 1 REF FEBS LETT. V. 267 268 1990 -REMARK 1 REFN ISSN 0014-5793 -REMARK 1 REFERENCE 6 -REMARK 1 AUTH M.S.WEISS,T.WACKER,U.NESTEL,D.WOITZIK,J.WECKESSER, -REMARK 1 AUTH 2 W.KREUTZ,W.WELTE,G.E.SCHULZ -REMARK 1 TITL THE STRUCTURE OF PORIN FROM RHODOBACTER CAPSULATUS -REMARK 1 TITL 2 AT 0.6 NM RESOLUTION -REMARK 1 REF FEBS LETT. V. 256 143 1989 -REMARK 1 REFN ISSN 0014-5793 -REMARK 1 REFERENCE 7 -REMARK 1 AUTH U.NESTEL,T.WACKER,D.WOITZIK,J.WECKESSER,W.KREUTZ, -REMARK 1 AUTH 2 W.WELTE -REMARK 1 TITL CRYSTALLIZATION AND PRELIMINARY X-RAY ANALYSIS OF -REMARK 1 TITL 2 PORIN FROM RHODOBACTER CAPSULATUS -REMARK 1 REF FEBS LETT. V. 242 405 1989 -REMARK 1 REFN ISSN 0014-5793 -REMARK 2 -REMARK 2 RESOLUTION. 1.80 ANGSTROMS. -REMARK 3 -REMARK 3 REFINEMENT. -REMARK 3 PROGRAM : X-PLOR -REMARK 3 AUTHORS : BRUNGER -REMARK 3 -REMARK 3 DATA USED IN REFINEMENT. -REMARK 3 RESOLUTION RANGE HIGH (ANGSTROMS) : 1.80 -REMARK 3 RESOLUTION RANGE LOW (ANGSTROMS) : 10.00 -REMARK 3 DATA CUTOFF (SIGMA(F)) : NULL -REMARK 3 DATA CUTOFF HIGH (ABS(F)) : NULL -REMARK 3 DATA CUTOFF LOW (ABS(F)) : NULL -REMARK 3 COMPLETENESS (WORKING+TEST) (%) : NULL -REMARK 3 NUMBER OF REFLECTIONS : 42851 -REMARK 3 -REMARK 3 FIT TO DATA USED IN REFINEMENT. -REMARK 3 CROSS-VALIDATION METHOD : NULL -REMARK 3 FREE R VALUE TEST SET SELECTION : NULL -REMARK 3 R VALUE (WORKING SET) : 0.186 -REMARK 3 FREE R VALUE : NULL -REMARK 3 FREE R VALUE TEST SET SIZE (%) : NULL -REMARK 3 FREE R VALUE TEST SET COUNT : NULL -REMARK 3 ESTIMATED ERROR OF FREE R VALUE : NULL -REMARK 3 -REMARK 3 FIT IN THE HIGHEST RESOLUTION BIN. -REMARK 3 TOTAL NUMBER OF BINS USED : NULL -REMARK 3 BIN RESOLUTION RANGE HIGH (A) : NULL -REMARK 3 BIN RESOLUTION RANGE LOW (A) : NULL -REMARK 3 BIN COMPLETENESS (WORKING+TEST) (%) : NULL -REMARK 3 REFLECTIONS IN BIN (WORKING SET) : NULL -REMARK 3 BIN R VALUE (WORKING SET) : NULL -REMARK 3 BIN FREE R VALUE : NULL -REMARK 3 BIN FREE R VALUE TEST SET SIZE (%) : NULL -REMARK 3 BIN FREE R VALUE TEST SET COUNT : NULL -REMARK 3 ESTIMATED ERROR OF BIN FREE R VALUE : NULL -REMARK 3 -REMARK 3 NUMBER OF NON-HYDROGEN ATOMS USED IN REFINEMENT. -REMARK 3 PROTEIN ATOMS : 2228 -REMARK 3 NUCLEIC ACID ATOMS : 0 -REMARK 3 HETEROGEN ATOMS : 87 -REMARK 3 SOLVENT ATOMS : 274 -REMARK 3 -REMARK 3 B VALUES. -REMARK 3 FROM WILSON PLOT (A**2) : NULL -REMARK 3 MEAN B VALUE (OVERALL, A**2) : NULL -REMARK 3 OVERALL ANISOTROPIC B VALUE. -REMARK 3 B11 (A**2) : NULL -REMARK 3 B22 (A**2) : NULL -REMARK 3 B33 (A**2) : NULL -REMARK 3 B12 (A**2) : NULL -REMARK 3 B13 (A**2) : NULL -REMARK 3 B23 (A**2) : NULL -REMARK 3 -REMARK 3 ESTIMATED COORDINATE ERROR. -REMARK 3 ESD FROM LUZZATI PLOT (A) : NULL -REMARK 3 ESD FROM SIGMAA (A) : NULL -REMARK 3 LOW RESOLUTION CUTOFF (A) : NULL -REMARK 3 -REMARK 3 CROSS-VALIDATED ESTIMATED COORDINATE ERROR. -REMARK 3 ESD FROM C-V LUZZATI PLOT (A) : NULL -REMARK 3 ESD FROM C-V SIGMAA (A) : NULL -REMARK 3 -REMARK 3 RMS DEVIATIONS FROM IDEAL VALUES. -REMARK 3 BOND LENGTHS (A) : 0.015 -REMARK 3 BOND ANGLES (DEGREES) : 2.80 -REMARK 3 DIHEDRAL ANGLES (DEGREES) : NULL -REMARK 3 IMPROPER ANGLES (DEGREES) : NULL -REMARK 3 -REMARK 3 ISOTROPIC THERMAL MODEL : NULL -REMARK 3 -REMARK 3 ISOTROPIC THERMAL FACTOR RESTRAINTS. RMS SIGMA -REMARK 3 MAIN-CHAIN BOND (A**2) : NULL ; NULL -REMARK 3 MAIN-CHAIN ANGLE (A**2) : NULL ; NULL -REMARK 3 SIDE-CHAIN BOND (A**2) : NULL ; NULL -REMARK 3 SIDE-CHAIN ANGLE (A**2) : NULL ; NULL -REMARK 3 -REMARK 3 NCS MODEL : NULL -REMARK 3 -REMARK 3 NCS RESTRAINTS. RMS SIGMA/WEIGHT -REMARK 3 GROUP 1 POSITIONAL (A) : NULL ; NULL -REMARK 3 GROUP 1 B-FACTOR (A**2) : NULL ; NULL -REMARK 3 -REMARK 3 PARAMETER FILE 1 : NULL -REMARK 3 TOPOLOGY FILE 1 : NULL -REMARK 3 -REMARK 3 OTHER REFINEMENT REMARKS: THE CRYSTALS HAVE FORM *B* AS -REMARK 3 DESCRIBED IN THE *JRNL* REFERENCE. RESIDUE 545 HAS NOT BEEN -REMARK 3 UNAMBIGUOUSLY IDENTIFIED. IT HAS BEEN MODELED AS A DETERGENT N -REMARK 3 -OCTYLTETRAOXYETHYLENE -REMARK 4 -REMARK 4 2POR COMPLIES WITH FORMAT V. 3.15, 01-DEC-08 -REMARK 100 -REMARK 100 THIS ENTRY HAS BEEN PROCESSED BY BNL. -REMARK 200 -REMARK 200 EXPERIMENTAL DETAILS -REMARK 200 EXPERIMENT TYPE : X-RAY DIFFRACTION -REMARK 200 DATE OF DATA COLLECTION : NULL -REMARK 200 TEMPERATURE (KELVIN) : NULL -REMARK 200 PH : NULL -REMARK 200 NUMBER OF CRYSTALS USED : NULL -REMARK 200 -REMARK 200 SYNCHROTRON (Y/N) : NULL -REMARK 200 RADIATION SOURCE : NULL -REMARK 200 BEAMLINE : NULL -REMARK 200 X-RAY GENERATOR MODEL : NULL -REMARK 200 MONOCHROMATIC OR LAUE (M/L) : NULL -REMARK 200 WAVELENGTH OR RANGE (A) : NULL -REMARK 200 MONOCHROMATOR : NULL -REMARK 200 OPTICS : NULL -REMARK 200 -REMARK 200 DETECTOR TYPE : NULL -REMARK 200 DETECTOR MANUFACTURER : NULL -REMARK 200 INTENSITY-INTEGRATION SOFTWARE : NULL -REMARK 200 DATA SCALING SOFTWARE : NULL -REMARK 200 -REMARK 200 NUMBER OF UNIQUE REFLECTIONS : NULL -REMARK 200 RESOLUTION RANGE HIGH (A) : NULL -REMARK 200 RESOLUTION RANGE LOW (A) : NULL -REMARK 200 REJECTION CRITERIA (SIGMA(I)) : NULL -REMARK 200 -REMARK 200 OVERALL. -REMARK 200 COMPLETENESS FOR RANGE (%) : NULL -REMARK 200 DATA REDUNDANCY : NULL -REMARK 200 R MERGE (I) : NULL -REMARK 200 R SYM (I) : NULL -REMARK 200 FOR THE DATA SET : NULL -REMARK 200 -REMARK 200 IN THE HIGHEST RESOLUTION SHELL. -REMARK 200 HIGHEST RESOLUTION SHELL, RANGE HIGH (A) : NULL -REMARK 200 HIGHEST RESOLUTION SHELL, RANGE LOW (A) : NULL -REMARK 200 COMPLETENESS FOR SHELL (%) : NULL -REMARK 200 DATA REDUNDANCY IN SHELL : NULL -REMARK 200 R MERGE FOR SHELL (I) : NULL -REMARK 200 R SYM FOR SHELL (I) : NULL -REMARK 200 FOR SHELL : NULL -REMARK 200 -REMARK 200 DIFFRACTION PROTOCOL: NULL -REMARK 200 METHOD USED TO DETERMINE THE STRUCTURE: NULL -REMARK 200 SOFTWARE USED: NULL -REMARK 200 STARTING MODEL: NULL -REMARK 200 -REMARK 200 REMARK: NULL -REMARK 280 -REMARK 280 CRYSTAL -REMARK 280 SOLVENT CONTENT, VS (%): 67.61 -REMARK 280 MATTHEWS COEFFICIENT, VM (ANGSTROMS**3/DA): 3.80 -REMARK 280 -REMARK 280 CRYSTALLIZATION CONDITIONS: NULL -REMARK 290 -REMARK 290 CRYSTALLOGRAPHIC SYMMETRY -REMARK 290 SYMMETRY OPERATORS FOR SPACE GROUP: H 3 -REMARK 290 -REMARK 290 SYMOP SYMMETRY -REMARK 290 NNNMMM OPERATOR -REMARK 290 1555 X,Y,Z -REMARK 290 2555 -Y,X-Y,Z -REMARK 290 3555 -X+Y,-X,Z -REMARK 290 4555 X+2/3,Y+1/3,Z+1/3 -REMARK 290 5555 -Y+2/3,X-Y+1/3,Z+1/3 -REMARK 290 6555 -X+Y+2/3,-X+1/3,Z+1/3 -REMARK 290 7555 X+1/3,Y+2/3,Z+2/3 -REMARK 290 8555 -Y+1/3,X-Y+2/3,Z+2/3 -REMARK 290 9555 -X+Y+1/3,-X+2/3,Z+2/3 -REMARK 290 -REMARK 290 WHERE NNN -> OPERATOR NUMBER -REMARK 290 MMM -> TRANSLATION VECTOR -REMARK 290 -REMARK 290 CRYSTALLOGRAPHIC SYMMETRY TRANSFORMATIONS -REMARK 290 THE FOLLOWING TRANSFORMATIONS OPERATE ON THE ATOM/HETATM -REMARK 290 RECORDS IN THIS ENTRY TO PRODUCE CRYSTALLOGRAPHICALLY -REMARK 290 RELATED MOLECULES. -REMARK 290 SMTRY1 1 1.000000 0.000000 0.000000 0.00000 -REMARK 290 SMTRY2 1 0.000000 1.000000 0.000000 0.00000 -REMARK 290 SMTRY3 1 0.000000 0.000000 1.000000 0.00000 -REMARK 290 SMTRY1 2 -0.500000 -0.866025 0.000000 0.00000 -REMARK 290 SMTRY2 2 0.866025 -0.500000 0.000000 0.00000 -REMARK 290 SMTRY3 2 0.000000 0.000000 1.000000 0.00000 -REMARK 290 SMTRY1 3 -0.500000 0.866025 0.000000 0.00000 -REMARK 290 SMTRY2 3 -0.866025 -0.500000 0.000000 0.00000 -REMARK 290 SMTRY3 3 0.000000 0.000000 1.000000 0.00000 -REMARK 290 SMTRY1 4 1.000000 0.000000 0.000000 46.15000 -REMARK 290 SMTRY2 4 0.000000 1.000000 0.000000 26.64471 -REMARK 290 SMTRY3 4 0.000000 0.000000 1.000000 48.73333 -REMARK 290 SMTRY1 5 -0.500000 -0.866025 0.000000 46.15000 -REMARK 290 SMTRY2 5 0.866025 -0.500000 0.000000 26.64471 -REMARK 290 SMTRY3 5 0.000000 0.000000 1.000000 48.73333 -REMARK 290 SMTRY1 6 -0.500000 0.866025 0.000000 46.15000 -REMARK 290 SMTRY2 6 -0.866025 -0.500000 0.000000 26.64471 -REMARK 290 SMTRY3 6 0.000000 0.000000 1.000000 48.73333 -REMARK 290 SMTRY1 7 1.000000 0.000000 0.000000 0.00000 -REMARK 290 SMTRY2 7 0.000000 1.000000 0.000000 53.28943 -REMARK 290 SMTRY3 7 0.000000 0.000000 1.000000 97.46667 -REMARK 290 SMTRY1 8 -0.500000 -0.866025 0.000000 0.00000 -REMARK 290 SMTRY2 8 0.866025 -0.500000 0.000000 53.28943 -REMARK 290 SMTRY3 8 0.000000 0.000000 1.000000 97.46667 -REMARK 290 SMTRY1 9 -0.500000 0.866025 0.000000 0.00000 -REMARK 290 SMTRY2 9 -0.866025 -0.500000 0.000000 53.28943 -REMARK 290 SMTRY3 9 0.000000 0.000000 1.000000 97.46667 -REMARK 290 -REMARK 290 REMARK: NULL -REMARK 300 -REMARK 300 BIOMOLECULE: 1 -REMARK 300 SEE REMARK 350 FOR THE AUTHOR PROVIDED AND/OR PROGRAM -REMARK 300 GENERATED ASSEMBLY INFORMATION FOR THE STRUCTURE IN -REMARK 300 THIS ENTRY. THE REMARK MAY ALSO PROVIDE INFORMATION ON -REMARK 300 BURIED SURFACE AREA. -REMARK 350 -REMARK 350 COORDINATES FOR A COMPLETE MULTIMER REPRESENTING THE KNOWN -REMARK 350 BIOLOGICALLY SIGNIFICANT OLIGOMERIZATION STATE OF THE -REMARK 350 MOLECULE CAN BE GENERATED BY APPLYING BIOMT TRANSFORMATIONS -REMARK 350 GIVEN BELOW. BOTH NON-CRYSTALLOGRAPHIC AND -REMARK 350 CRYSTALLOGRAPHIC OPERATIONS ARE GIVEN. -REMARK 350 -REMARK 350 BIOMOLECULE: 1 -REMARK 350 AUTHOR DETERMINED BIOLOGICAL UNIT: TRIMERIC -REMARK 350 APPLY THE FOLLOWING TO CHAINS: A -REMARK 350 BIOMT1 1 1.000000 0.000000 0.000000 0.00000 -REMARK 350 BIOMT2 1 0.000000 1.000000 0.000000 0.00000 -REMARK 350 BIOMT3 1 0.000000 0.000000 1.000000 0.00000 -REMARK 350 BIOMT1 2 -0.500000 -0.866025 0.000000 0.00000 -REMARK 350 BIOMT2 2 0.866025 -0.500000 0.000000 0.00000 -REMARK 350 BIOMT3 2 0.000000 0.000000 1.000000 0.00000 -REMARK 350 BIOMT1 3 -0.500000 0.866025 0.000000 0.00000 -REMARK 350 BIOMT2 3 -0.866025 -0.500000 0.000000 0.00000 -REMARK 350 BIOMT3 3 0.000000 0.000000 1.000000 0.00000 -REMARK 375 -REMARK 375 SPECIAL POSITION -REMARK 375 THE FOLLOWING ATOMS ARE FOUND TO BE WITHIN 0.15 ANGSTROMS -REMARK 375 OF A SYMMETRY RELATED ATOM AND ARE ASSUMED TO BE ON SPECIAL -REMARK 375 POSITIONS. -REMARK 375 -REMARK 375 ATOM RES CSSEQI -REMARK 375 HOH A 361 LIES ON A SPECIAL POSITION. -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: COVALENT BOND LENGTHS -REMARK 500 -REMARK 500 THE STEREOCHEMICAL PARAMETERS OF THE FOLLOWING RESIDUES -REMARK 500 HAVE VALUES WHICH DEVIATE FROM EXPECTED VALUES BY MORE -REMARK 500 THAN 6*RMSD (M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN -REMARK 500 IDENTIFIER; SSEQ=SEQUENCE NUMBER; I=INSERTION CODE). -REMARK 500 -REMARK 500 STANDARD TABLE: -REMARK 500 FORMAT: (10X,I3,1X,2(A3,1X,A1,I4,A1,1X,A4,3X),1X,F6.3) -REMARK 500 -REMARK 500 EXPECTED VALUES PROTEIN: ENGH AND HUBER, 1999 -REMARK 500 EXPECTED VALUES NUCLEIC ACID: CLOWNEY ET AL 1996 -REMARK 500 -REMARK 500 M RES CSSEQI ATM1 RES CSSEQI ATM2 DEVIATION -REMARK 500 HIS A 229 NE2 HIS A 229 CD2 -0.067 -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: COVALENT BOND ANGLES -REMARK 500 -REMARK 500 THE STEREOCHEMICAL PARAMETERS OF THE FOLLOWING RESIDUES -REMARK 500 HAVE VALUES WHICH DEVIATE FROM EXPECTED VALUES BY MORE -REMARK 500 THAN 6*RMSD (M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN -REMARK 500 IDENTIFIER; SSEQ=SEQUENCE NUMBER; I=INSERTION CODE). -REMARK 500 -REMARK 500 STANDARD TABLE: -REMARK 500 FORMAT: (10X,I3,1X,A3,1X,A1,I4,A1,3(1X,A4,2X),12X,F5.1) -REMARK 500 -REMARK 500 EXPECTED VALUES PROTEIN: ENGH AND HUBER, 1999 -REMARK 500 EXPECTED VALUES NUCLEIC ACID: CLOWNEY ET AL 1996 -REMARK 500 -REMARK 500 M RES CSSEQI ATM1 ATM2 ATM3 -REMARK 500 ARG A 9 NE - CZ - NH2 ANGL. DEV. = -3.2 DEGREES -REMARK 500 TRP A 19 CD1 - CG - CD2 ANGL. DEV. = 6.6 DEGREES -REMARK 500 TRP A 19 CE2 - CD2 - CG ANGL. DEV. = -5.6 DEGREES -REMARK 500 ARG A 24 NE - CZ - NH1 ANGL. DEV. = 3.1 DEGREES -REMARK 500 ASP A 101 CB - CG - OD1 ANGL. DEV. = 7.3 DEGREES -REMARK 500 TYR A 123 CB - CG - CD1 ANGL. DEV. = -3.9 DEGREES -REMARK 500 ASP A 136 CB - CG - OD1 ANGL. DEV. = 6.2 DEGREES -REMARK 500 TYR A 167 CB - CG - CD2 ANGL. DEV. = -4.2 DEGREES -REMARK 500 TYR A 263 CB - CG - CD1 ANGL. DEV. = -4.4 DEGREES -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: TORSION ANGLES -REMARK 500 -REMARK 500 TORSION ANGLES OUTSIDE THE EXPECTED RAMACHANDRAN REGIONS: -REMARK 500 (M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN IDENTIFIER; -REMARK 500 SSEQ=SEQUENCE NUMBER; I=INSERTION CODE). -REMARK 500 -REMARK 500 STANDARD TABLE: -REMARK 500 FORMAT:(10X,I3,1X,A3,1X,A1,I4,A1,4X,F7.2,3X,F7.2) -REMARK 500 -REMARK 500 EXPECTED VALUES: GJ KLEYWEGT AND TA JONES (1996). PHI/PSI- -REMARK 500 CHOLOGY: RAMACHANDRAN REVISITED. STRUCTURE 4, 1395 - 1400 -REMARK 500 -REMARK 500 M RES CSSEQI PSI PHI -REMARK 500 ASP A 17 -37.35 -132.37 -REMARK 500 ASP A 93 83.99 64.70 -REMARK 500 THR A 256 -7.57 73.01 -REMARK 500 ILE A 257 -77.43 -108.97 -REMARK 500 SER A 289 112.52 -34.30 -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 525 -REMARK 525 SOLVENT -REMARK 525 -REMARK 525 THE SOLVENT MOLECULES HAVE CHAIN IDENTIFIERS THAT -REMARK 525 INDICATE THE POLYMER CHAIN WITH WHICH THEY ARE MOST -REMARK 525 CLOSELY ASSOCIATED. THE REMARK LISTS ALL THE SOLVENT -REMARK 525 MOLECULES WHICH ARE MORE THAN 5A AWAY FROM THE -REMARK 525 NEAREST POLYMER CHAIN (M = MODEL NUMBER; -REMARK 525 RES=RESIDUE NAME; C=CHAIN IDENTIFIER; SSEQ=SEQUENCE -REMARK 525 NUMBER; I=INSERTION CODE): -REMARK 525 -REMARK 525 M RES CSSEQI -REMARK 525 HOH A 446 DISTANCE = 5.96 ANGSTROMS -REMARK 525 HOH A 558 DISTANCE = 7.12 ANGSTROMS -REMARK 525 HOH A 565 DISTANCE = 6.72 ANGSTROMS -REMARK 525 HOH A 568 DISTANCE = 7.37 ANGSTROMS -REMARK 525 HOH A 571 DISTANCE = 5.80 ANGSTROMS -REMARK 525 HOH A 573 DISTANCE = 5.38 ANGSTROMS -REMARK 525 HOH A 582 DISTANCE = 5.49 ANGSTROMS -REMARK 600 -REMARK 600 HETEROGEN -REMARK 600 THIRTY FOUR DETERGENT FRAGMENTS HAVE BEEN MODELED AS WATERS -REMARK 620 -REMARK 620 METAL COORDINATION -REMARK 620 (M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN IDENTIFIER; -REMARK 620 SSEQ=SEQUENCE NUMBER; I=INSERTION CODE): -REMARK 620 -REMARK 620 COORDINATION ANGLES FOR: M RES CSSEQI METAL -REMARK 620 CA A 302 CA -REMARK 620 N RES CSSEQI ATOM -REMARK 620 1 HOH A 312 O -REMARK 620 2 HOH A 307 O 79.4 -REMARK 620 3 HOH A 339 O 86.7 74.4 -REMARK 620 4 GLU A 80 OE2 80.9 75.3 148.9 -REMARK 620 5 GLU A 80 OE1 92.0 125.5 159.5 50.2 -REMARK 620 6 ASP A 108 OD2 175.3 95.8 92.3 97.7 90.6 -REMARK 620 7 HOH A 305 O 86.9 150.3 78.6 128.6 80.9 97.5 -REMARK 620 N 1 2 3 4 5 6 -REMARK 620 -REMARK 620 COORDINATION ANGLES FOR: M RES CSSEQI METAL -REMARK 620 CA A 303 CA -REMARK 620 N RES CSSEQI ATOM -REMARK 620 1 ASP A 95 OD1 -REMARK 620 2 ASN A 100 OD1 73.7 -REMARK 620 3 ASP A 101 OD1 85.1 81.2 -REMARK 620 4 HOH A 331 O 150.5 76.9 93.2 -REMARK 620 5 ASP A 93 OD1 77.7 77.7 155.8 93.5 -REMARK 620 6 ASP A 93 OD2 113.9 122.8 151.9 80.1 52.3 -REMARK 620 7 ASP A 95 OD2 49.5 123.2 94.3 159.4 87.3 84.2 -REMARK 620 8 HOH A 327 O 126.7 146.6 75.5 80.8 128.6 76.5 82.6 -REMARK 620 N 1 2 3 4 5 6 7 -REMARK 620 -REMARK 620 COORDINATION ANGLES FOR: M RES CSSEQI METAL -REMARK 620 CA A 304 CA -REMARK 620 N RES CSSEQI ATOM -REMARK 620 1 ASN A 116 OD1 -REMARK 620 2 ASP A 136 OD2 103.7 -REMARK 620 3 LYS A 138 O 81.6 128.0 -REMARK 620 4 GLY A 140 O 95.7 145.2 82.9 -REMARK 620 5 HOH A 314 O 84.5 78.0 152.9 75.4 -REMARK 620 6 ASP A 136 OD1 89.8 52.3 76.4 157.5 126.9 -REMARK 620 7 ASN A 20 OD1 174.7 81.5 94.8 79.9 97.2 93.2 -REMARK 620 N 1 2 3 4 5 6 -REMARK 700 -REMARK 700 SHEET -REMARK 700 THE SHEET PRESENTED AS *S1* ON SHEET RECORDS BELOW IS -REMARK 700 ACTUALLY A SIXTEEN-STRANDED BETA-BARREL. THIS IS -REMARK 700 REPRESENTED AS A SEVENTEEN-STRANDED SHEET IN WHICH THE -REMARK 700 FIRST AND LAST STRANDS ARE IDENTICAL. -REMARK 800 -REMARK 800 SITE -REMARK 800 SITE_IDENTIFIER: AC1 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE CA A 302 -REMARK 800 SITE_IDENTIFIER: AC2 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE CA A 303 -REMARK 800 SITE_IDENTIFIER: AC3 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE CA A 304 -REMARK 800 SITE_IDENTIFIER: AC4 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE C8E A 545 -REMARK 800 SITE_IDENTIFIER: AC5 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE C8E A 546 -REMARK 800 SITE_IDENTIFIER: AC6 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE C8E A 548 -DBREF 2POR A 1 301 UNP P31243 PORI_RHOCA 1 301 -SEQRES 1 A 301 GLU VAL LYS LEU SER GLY ASP ALA ARG MET GLY VAL MET -SEQRES 2 A 301 TYR ASN GLY ASP ASP TRP ASN PHE SER SER ARG SER ARG -SEQRES 3 A 301 VAL LEU PHE THR MET SER GLY THR THR ASP SER GLY LEU -SEQRES 4 A 301 GLU PHE GLY ALA SER PHE LYS ALA HIS GLU SER VAL GLY -SEQRES 5 A 301 ALA GLU THR GLY GLU ASP GLY THR VAL PHE LEU SER GLY -SEQRES 6 A 301 ALA PHE GLY LYS ILE GLU MET GLY ASP ALA LEU GLY ALA -SEQRES 7 A 301 SER GLU ALA LEU PHE GLY ASP LEU TYR GLU VAL GLY TYR -SEQRES 8 A 301 THR ASP LEU ASP ASP ARG GLY GLY ASN ASP ILE PRO TYR -SEQRES 9 A 301 LEU THR GLY ASP GLU ARG LEU THR ALA GLU ASP ASN PRO -SEQRES 10 A 301 VAL LEU LEU TYR THR TYR SER ALA GLY ALA PHE SER VAL -SEQRES 11 A 301 ALA ALA SER MET SER ASP GLY LYS VAL GLY GLU THR SER -SEQRES 12 A 301 GLU ASP ASP ALA GLN GLU MET ALA VAL ALA ALA ALA TYR -SEQRES 13 A 301 THR PHE GLY ASN TYR THR VAL GLY LEU GLY TYR GLU LYS -SEQRES 14 A 301 ILE ASP SER PRO ASP THR ALA LEU MET ALA ASP MET GLU -SEQRES 15 A 301 GLN LEU GLU LEU ALA ALA ILE ALA LYS PHE GLY ALA THR -SEQRES 16 A 301 ASN VAL LYS ALA TYR TYR ALA ASP GLY GLU LEU ASP ARG -SEQRES 17 A 301 ASP PHE ALA ARG ALA VAL PHE ASP LEU THR PRO VAL ALA -SEQRES 18 A 301 ALA ALA ALA THR ALA VAL ASP HIS LYS ALA TYR GLY LEU -SEQRES 19 A 301 SER VAL ASP SER THR PHE GLY ALA THR THR VAL GLY GLY -SEQRES 20 A 301 TYR VAL GLN VAL LEU ASP ILE ASP THR ILE ASP ASP VAL -SEQRES 21 A 301 THR TYR TYR GLY LEU GLY ALA SER TYR ASP LEU GLY GLY -SEQRES 22 A 301 GLY ALA SER ILE VAL GLY GLY ILE ALA ASP ASN ASP LEU -SEQRES 23 A 301 PRO ASN SER ASP MET VAL ALA ASP LEU GLY VAL LYS PHE -SEQRES 24 A 301 LYS PHE -HET CA A 302 1 -HET CA A 303 1 -HET CA A 304 1 -HET C8E A 545 21 -HET C8E A 546 21 -HET C8E A 547 21 -HET C8E A 548 21 -HETNAM CA CALCIUM ION -HETNAM C8E (HYDROXYETHYLOXY)TRI(ETHYLOXY)OCTANE -FORMUL 2 CA 3(CA 2+) -FORMUL 5 C8E 4(C16 H34 O5) -FORMUL 9 HOH *274(H2 O) -HELIX 1 H1 SER A 50 GLU A 54 1 5 -HELIX 2 H2 GLY A 77 PHE A 83 1 7 -HELIX 3 H3 ARG A 208 VAL A 214 1 7 -SHEET 1 S117 GLU A 1 ASN A 15 0 -SHEET 2 S117 ASP A 18 THR A 35 -1 O ASP A 18 N ASN A 15 -SHEET 3 S117 LEU A 39 LYS A 46 -1 O LEU A 39 N THR A 35 -SHEET 4 S117 GLY A 59 GLY A 65 -1 N THR A 60 O SER A 44 -SHEET 5 S117 GLY A 68 ASP A 74 -1 N GLY A 68 O GLY A 65 -SHEET 6 S117 VAL A 118 ALA A 125 -1 N VAL A 118 O GLY A 73 -SHEET 7 S117 PHE A 128 SER A 135 -1 N PHE A 128 O ALA A 125 -SHEET 8 S117 GLN A 148 PHE A 158 -1 O GLU A 149 N SER A 135 -SHEET 9 S117 TYR A 161 ASP A 171 -1 N TYR A 161 O PHE A 158 -SHEET 10 S117 MET A 181 PHE A 192 -1 N MET A 181 O ILE A 170 -SHEET 11 S117 THR A 195 LEU A 206 -1 N THR A 195 O PHE A 192 -SHEET 12 S117 VAL A 227 PHE A 240 -1 N VAL A 227 O LEU A 206 -SHEET 13 S117 THR A 243 ILE A 254 -1 N THR A 243 O PHE A 240 -SHEET 14 S117 ASP A 258 LEU A 271 -1 N ASP A 258 O ILE A 254 -SHEET 15 S117 ALA A 275 ASP A 285 -1 O ALA A 275 N LEU A 271 -SHEET 16 S117 VAL A 292 PHE A 301 -1 N VAL A 292 O ALA A 282 -SHEET 17 S117 GLU A 1 ASN A 15 1 N GLY A 6 O PHE A 301 -LINK CA CA A 302 O HOH A 312 1555 1555 2.28 -LINK CA CA A 302 O HOH A 307 1555 1555 2.32 -LINK CA CA A 302 O HOH A 339 1555 1555 2.38 -LINK CA CA A 302 OE2 GLU A 80 1555 1555 2.48 -LINK CA CA A 302 OE1 GLU A 80 1555 1555 2.53 -LINK CA CA A 302 OD2 ASP A 108 1555 1555 2.24 -LINK CA CA A 302 O HOH A 305 1555 1555 2.43 -LINK CA CA A 303 OD1 ASP A 95 1555 1555 2.63 -LINK CA CA A 303 OD1 ASN A 100 1555 1555 2.31 -LINK CA CA A 303 OD1 ASP A 101 1555 1555 2.25 -LINK CA CA A 303 O HOH A 331 1555 1555 2.39 -LINK CA CA A 303 OD1 ASP A 93 1555 1555 2.33 -LINK CA CA A 303 OD2 ASP A 93 1555 1555 2.45 -LINK CA CA A 303 OD2 ASP A 95 1555 1555 2.40 -LINK CA CA A 303 O HOH A 327 1555 1555 2.24 -LINK CA CA A 304 OD1 ASN A 116 1555 1555 2.16 -LINK CA CA A 304 OD2 ASP A 136 1555 1555 2.39 -LINK CA CA A 304 O LYS A 138 1555 1555 2.55 -LINK CA CA A 304 O GLY A 140 1555 1555 2.18 -LINK CA CA A 304 O HOH A 314 1555 1555 2.35 -LINK CA CA A 304 OD1 ASP A 136 1555 1555 2.35 -LINK CA CA A 304 OD1 ASN A 20 1555 2555 2.18 -SITE 1 AC1 6 GLU A 80 ASP A 108 HOH A 305 HOH A 307 -SITE 2 AC1 6 HOH A 312 HOH A 339 -SITE 1 AC2 6 ASP A 93 ASP A 95 ASN A 100 ASP A 101 -SITE 2 AC2 6 HOH A 327 HOH A 331 -SITE 1 AC3 6 ASN A 20 ASN A 116 ASP A 136 LYS A 138 -SITE 2 AC3 6 GLY A 140 HOH A 314 -SITE 1 AC4 4 GLN A 183 VAL A 214 LEU A 286 ASN A 288 -SITE 1 AC5 4 TRP A 19 MET A 134 GLN A 148 GLY A 280 -SITE 1 AC6 4 TYR A 200 TYR A 232 VAL A 249 THR A 261 -CRYST1 92.300 92.300 146.200 90.00 90.00 120.00 H 3 9 -ORIGX1 1.000000 0.000000 0.000000 0.00000 -ORIGX2 0.000000 1.000000 0.000000 0.00000 -ORIGX3 0.000000 0.000000 1.000000 0.00000 -SCALE1 0.010834 0.006255 0.000000 0.00000 -SCALE2 0.000000 0.012510 0.000000 0.00000 -SCALE3 0.000000 0.000000 0.006840 0.00000 -ATOM 1 N GLU A 1 10.975 -2.428 6.735 1.00 27.59 N -ATOM 2 CA GLU A 1 9.566 -2.578 6.405 1.00 36.06 C -ATOM 3 C GLU A 1 8.689 -3.034 7.601 1.00 22.34 C -ATOM 4 O GLU A 1 9.156 -3.908 8.335 1.00 23.38 O -ATOM 5 CB GLU A 1 9.513 -3.583 5.273 1.00 27.56 C -ATOM 6 CG GLU A 1 8.120 -3.932 4.767 1.00 46.76 C -ATOM 7 CD GLU A 1 8.059 -5.151 3.839 1.00 78.17 C -ATOM 8 OE1 GLU A 1 8.986 -5.978 3.838 1.00 83.62 O -ATOM 9 OE2 GLU A 1 7.059 -5.270 3.122 1.00 88.58 O -ATOM 10 N VAL A 2 7.445 -2.564 7.760 1.00 24.91 N -ATOM 11 CA VAL A 2 6.554 -2.916 8.868 1.00 26.19 C -ATOM 12 C VAL A 2 5.235 -3.431 8.314 1.00 21.63 C -ATOM 13 O VAL A 2 4.554 -2.685 7.614 1.00 25.05 O -ATOM 14 CB VAL A 2 6.258 -1.672 9.795 1.00 21.80 C -ATOM 15 CG1 VAL A 2 5.414 -2.151 10.975 1.00 21.14 C -ATOM 16 CG2 VAL A 2 7.526 -1.022 10.328 1.00 21.61 C -ATOM 17 N LYS A 3 4.811 -4.658 8.584 1.00 17.35 N -ATOM 18 CA LYS A 3 3.536 -5.187 8.138 1.00 16.93 C -ATOM 19 C LYS A 3 2.611 -5.431 9.336 1.00 22.75 C -ATOM 20 O LYS A 3 3.086 -5.703 10.440 1.00 24.29 O -ATOM 21 CB LYS A 3 3.712 -6.524 7.421 1.00 20.86 C -ATOM 22 CG LYS A 3 4.477 -6.434 6.116 1.00 49.31 C -ATOM 23 CD LYS A 3 4.137 -7.645 5.248 1.00 66.30 C -ATOM 24 CE LYS A 3 4.389 -7.309 3.763 1.00 91.35 C -ATOM 25 NZ LYS A 3 3.660 -6.128 3.288 1.00 86.70 N -ATOM 26 N LEU A 4 1.317 -5.393 9.102 1.00 18.28 N -ATOM 27 CA LEU A 4 0.307 -5.586 10.089 1.00 17.20 C -ATOM 28 C LEU A 4 -0.511 -6.790 9.822 1.00 25.71 C -ATOM 29 O LEU A 4 -0.857 -7.096 8.688 1.00 22.60 O -ATOM 30 CB LEU A 4 -0.658 -4.425 10.135 1.00 17.62 C -ATOM 31 CG LEU A 4 -0.154 -3.047 10.591 1.00 25.02 C -ATOM 32 CD1 LEU A 4 -1.260 -2.032 10.663 1.00 27.49 C -ATOM 33 CD2 LEU A 4 0.342 -3.158 12.001 1.00 28.78 C -ATOM 34 N SER A 5 -0.858 -7.520 10.854 1.00 18.09 N -ATOM 35 CA SER A 5 -1.843 -8.581 10.759 1.00 16.56 C -ATOM 36 C SER A 5 -2.590 -8.569 12.107 1.00 21.22 C -ATOM 37 O SER A 5 -2.231 -7.755 12.976 1.00 17.63 O -ATOM 38 CB SER A 5 -1.182 -9.918 10.543 1.00 15.90 C -ATOM 39 OG SER A 5 -0.206 -10.289 11.503 1.00 22.45 O -ATOM 40 N GLY A 6 -3.582 -9.404 12.337 1.00 22.36 N -ATOM 41 CA GLY A 6 -4.313 -9.399 13.598 1.00 18.52 C -ATOM 42 C GLY A 6 -5.194 -10.590 13.711 1.00 20.43 C -ATOM 43 O GLY A 6 -5.272 -11.470 12.839 1.00 19.89 O -ATOM 44 N ASP A 7 -5.858 -10.676 14.845 1.00 17.75 N -ATOM 45 CA ASP A 7 -6.828 -11.730 15.071 1.00 14.63 C -ATOM 46 C ASP A 7 -7.839 -11.230 16.099 1.00 17.50 C -ATOM 47 O ASP A 7 -7.656 -10.162 16.698 1.00 17.10 O -ATOM 48 CB ASP A 7 -6.157 -13.038 15.557 1.00 15.83 C -ATOM 49 CG ASP A 7 -5.230 -12.906 16.760 1.00 23.05 C -ATOM 50 OD1 ASP A 7 -5.656 -12.431 17.801 1.00 20.15 O -ATOM 51 OD2 ASP A 7 -4.071 -13.234 16.640 1.00 25.78 O -ATOM 52 N ALA A 8 -8.944 -11.946 16.224 1.00 19.52 N -ATOM 53 CA ALA A 8 -10.035 -11.603 17.141 1.00 15.71 C -ATOM 54 C ALA A 8 -10.861 -12.858 17.357 1.00 19.05 C -ATOM 55 O ALA A 8 -10.682 -13.866 16.641 1.00 18.32 O -ATOM 56 CB ALA A 8 -10.945 -10.502 16.587 1.00 14.05 C -ATOM 57 N ARG A 9 -11.662 -12.914 18.432 1.00 16.33 N -ATOM 58 CA ARG A 9 -12.501 -14.065 18.709 1.00 13.95 C -ATOM 59 C ARG A 9 -13.651 -13.601 19.567 1.00 17.40 C -ATOM 60 O ARG A 9 -13.553 -12.536 20.208 1.00 18.39 O -ATOM 61 CB ARG A 9 -11.687 -15.156 19.410 1.00 15.94 C -ATOM 62 CG ARG A 9 -11.320 -14.825 20.843 1.00 16.00 C -ATOM 63 CD ARG A 9 -10.256 -15.772 21.276 1.00 19.18 C -ATOM 64 NE ARG A 9 -10.038 -15.564 22.699 1.00 20.39 N -ATOM 65 CZ ARG A 9 -8.998 -16.081 23.374 1.00 23.61 C -ATOM 66 NH1 ARG A 9 -8.039 -16.818 22.792 1.00 19.92 N -ATOM 67 NH2 ARG A 9 -8.922 -15.805 24.689 1.00 23.34 N -ATOM 68 N MET A 10 -14.789 -14.262 19.531 1.00 15.77 N -ATOM 69 CA MET A 10 -15.931 -13.891 20.365 1.00 19.06 C -ATOM 70 C MET A 10 -16.832 -15.099 20.499 1.00 24.44 C -ATOM 71 O MET A 10 -16.838 -15.965 19.620 1.00 18.02 O -ATOM 72 CB MET A 10 -16.723 -12.707 19.809 1.00 18.72 C -ATOM 73 CG MET A 10 -17.489 -12.938 18.541 1.00 25.28 C -ATOM 74 SD MET A 10 -18.482 -11.490 18.191 1.00 30.85 S -ATOM 75 CE MET A 10 -18.740 -12.010 16.541 1.00 33.80 C -ATOM 76 N GLY A 11 -17.502 -15.304 21.642 1.00 17.85 N -ATOM 77 CA GLY A 11 -18.325 -16.491 21.829 1.00 18.79 C -ATOM 78 C GLY A 11 -18.676 -16.572 23.288 1.00 25.94 C -ATOM 79 O GLY A 11 -18.702 -15.531 23.959 1.00 21.22 O -ATOM 80 N VAL A 12 -18.929 -17.776 23.769 1.00 22.43 N -ATOM 81 CA VAL A 12 -19.310 -18.051 25.177 1.00 22.84 C -ATOM 82 C VAL A 12 -18.421 -19.118 25.753 1.00 21.81 C -ATOM 83 O VAL A 12 -18.005 -20.034 25.037 1.00 20.69 O -ATOM 84 CB VAL A 12 -20.786 -18.518 25.319 1.00 23.09 C -ATOM 85 CG1 VAL A 12 -21.639 -17.287 25.071 1.00 21.02 C -ATOM 86 CG2 VAL A 12 -21.167 -19.632 24.355 1.00 22.56 C -ATOM 87 N MET A 13 -18.010 -18.982 27.018 1.00 16.86 N -ATOM 88 CA MET A 13 -17.066 -19.909 27.604 1.00 18.95 C -ATOM 89 C MET A 13 -17.695 -20.359 28.938 1.00 26.49 C -ATOM 90 O MET A 13 -18.277 -19.533 29.649 1.00 22.68 O -ATOM 91 CB MET A 13 -15.725 -19.176 27.821 1.00 19.57 C -ATOM 92 CG AMET A 13 -14.661 -20.018 28.553 0.51 33.28 C -ATOM 93 CG BMET A 13 -14.564 -19.969 28.448 0.49 31.07 C -ATOM 94 SD AMET A 13 -14.864 -20.093 30.362 0.51 18.59 S -ATOM 95 SD BMET A 13 -14.047 -19.495 30.135 0.49 33.60 S -ATOM 96 CE AMET A 13 -14.637 -18.365 30.663 0.51 14.41 C -ATOM 97 CE BMET A 13 -13.423 -21.075 30.594 0.49 12.77 C -ATOM 98 N TYR A 14 -17.572 -21.615 29.305 1.00 23.01 N -ATOM 99 CA TYR A 14 -18.178 -22.199 30.497 1.00 25.16 C -ATOM 100 C TYR A 14 -17.029 -22.485 31.428 1.00 23.22 C -ATOM 101 O TYR A 14 -16.171 -23.295 31.063 1.00 23.70 O -ATOM 102 CB TYR A 14 -18.841 -23.482 30.133 1.00 24.00 C -ATOM 103 CG TYR A 14 -19.541 -24.129 31.300 1.00 28.72 C -ATOM 104 CD1 TYR A 14 -20.727 -23.561 31.734 1.00 29.42 C -ATOM 105 CD2 TYR A 14 -19.017 -25.283 31.856 1.00 27.77 C -ATOM 106 CE1 TYR A 14 -21.430 -24.167 32.750 1.00 32.13 C -ATOM 107 CE2 TYR A 14 -19.717 -25.895 32.876 1.00 30.23 C -ATOM 108 CZ TYR A 14 -20.915 -25.329 33.305 1.00 32.81 C -ATOM 109 OH TYR A 14 -21.626 -25.944 34.326 1.00 50.72 O -ATOM 110 N ASN A 15 -17.000 -21.905 32.638 1.00 22.01 N -ATOM 111 CA ASN A 15 -15.841 -22.047 33.535 1.00 22.52 C -ATOM 112 C ASN A 15 -15.889 -23.250 34.484 1.00 31.39 C -ATOM 113 O ASN A 15 -15.038 -23.447 35.359 1.00 32.32 O -ATOM 114 CB ASN A 15 -15.660 -20.755 34.380 1.00 24.87 C -ATOM 115 CG ASN A 15 -16.856 -20.434 35.271 1.00 23.96 C -ATOM 116 OD1 ASN A 15 -17.708 -21.291 35.515 1.00 23.91 O -ATOM 117 ND2 ASN A 15 -17.090 -19.204 35.695 1.00 26.01 N -ATOM 118 N GLY A 16 -16.865 -24.119 34.303 1.00 26.28 N -ATOM 119 CA GLY A 16 -17.013 -25.246 35.198 1.00 33.32 C -ATOM 120 C GLY A 16 -18.353 -25.113 35.878 1.00 30.42 C -ATOM 121 O GLY A 16 -18.975 -26.124 36.199 1.00 36.69 O -ATOM 122 N ASP A 17 -18.860 -23.882 36.047 1.00 29.56 N -ATOM 123 CA ASP A 17 -20.141 -23.614 36.727 1.00 29.65 C -ATOM 124 C ASP A 17 -21.077 -22.659 35.981 1.00 32.17 C -ATOM 125 O ASP A 17 -22.304 -22.831 35.929 1.00 30.83 O -ATOM 126 CB ASP A 17 -19.849 -23.042 38.165 1.00 35.32 C -ATOM 127 CG ASP A 17 -18.950 -23.913 39.090 1.00 51.32 C -ATOM 128 OD1 ASP A 17 -19.361 -25.019 39.486 1.00 59.35 O -ATOM 129 OD2 ASP A 17 -17.822 -23.488 39.391 1.00 65.43 O -ATOM 130 N ASP A 18 -20.505 -21.638 35.336 1.00 24.80 N -ATOM 131 CA ASP A 18 -21.301 -20.661 34.621 1.00 23.22 C -ATOM 132 C ASP A 18 -20.689 -20.330 33.261 1.00 26.47 C -ATOM 133 O ASP A 18 -19.485 -20.520 33.049 1.00 25.52 O -ATOM 134 CB ASP A 18 -21.381 -19.351 35.370 1.00 25.98 C -ATOM 135 CG ASP A 18 -22.210 -19.562 36.608 1.00 43.16 C -ATOM 136 OD1 ASP A 18 -23.428 -19.634 36.500 1.00 41.16 O -ATOM 137 OD2 ASP A 18 -21.610 -19.689 37.666 1.00 33.11 O -ATOM 138 N TRP A 19 -21.570 -19.845 32.394 1.00 24.02 N -ATOM 139 CA TRP A 19 -21.228 -19.334 31.074 1.00 29.52 C -ATOM 140 C TRP A 19 -20.887 -17.850 31.201 1.00 34.72 C -ATOM 141 O TRP A 19 -21.489 -17.150 32.023 1.00 26.95 O -ATOM 142 CB TRP A 19 -22.413 -19.489 30.099 1.00 20.45 C -ATOM 143 CG TRP A 19 -22.600 -20.931 29.671 1.00 34.12 C -ATOM 144 CD1 TRP A 19 -23.521 -21.735 30.283 1.00 38.42 C -ATOM 145 CD2 TRP A 19 -21.879 -21.586 28.704 1.00 43.20 C -ATOM 146 NE1 TRP A 19 -23.378 -22.907 29.705 1.00 28.98 N -ATOM 147 CE2 TRP A 19 -22.416 -22.861 28.769 1.00 43.13 C -ATOM 148 CE3 TRP A 19 -20.869 -21.291 27.804 1.00 27.67 C -ATOM 149 CZ2 TRP A 19 -21.955 -23.858 27.942 1.00 37.29 C -ATOM 150 CZ3 TRP A 19 -20.404 -22.293 26.974 1.00 26.31 C -ATOM 151 CH2 TRP A 19 -20.947 -23.560 27.045 1.00 34.35 C -ATOM 152 N ASN A 20 -19.915 -17.345 30.439 1.00 20.14 N -ATOM 153 CA ASN A 20 -19.610 -15.934 30.363 1.00 20.63 C -ATOM 154 C ASN A 20 -19.325 -15.585 28.909 1.00 21.59 C -ATOM 155 O ASN A 20 -18.824 -16.452 28.179 1.00 20.91 O -ATOM 156 CB ASN A 20 -18.358 -15.571 31.135 1.00 19.26 C -ATOM 157 CG ASN A 20 -18.632 -15.209 32.594 1.00 16.94 C -ATOM 158 OD1 ASN A 20 -18.981 -14.061 32.912 1.00 19.32 O -ATOM 159 ND2 ASN A 20 -18.356 -16.193 33.429 1.00 18.90 N -ATOM 160 N PHE A 21 -19.579 -14.348 28.511 1.00 20.31 N -ATOM 161 CA PHE A 21 -19.123 -13.839 27.208 1.00 18.80 C -ATOM 162 C PHE A 21 -17.596 -13.740 27.273 1.00 29.01 C -ATOM 163 O PHE A 21 -17.046 -13.375 28.323 1.00 18.59 O -ATOM 164 CB PHE A 21 -19.693 -12.434 26.920 1.00 15.96 C -ATOM 165 CG PHE A 21 -21.210 -12.260 26.798 1.00 16.47 C -ATOM 166 CD1 PHE A 21 -22.038 -13.317 26.450 1.00 18.25 C -ATOM 167 CD2 PHE A 21 -21.730 -11.004 27.047 1.00 17.20 C -ATOM 168 CE1 PHE A 21 -23.387 -13.081 26.366 1.00 20.58 C -ATOM 169 CE2 PHE A 21 -23.088 -10.789 26.954 1.00 18.95 C -ATOM 170 CZ PHE A 21 -23.906 -11.831 26.615 1.00 18.40 C -ATOM 171 N SER A 22 -16.849 -14.072 26.211 1.00 16.37 N -ATOM 172 CA SER A 22 -15.406 -13.978 26.201 1.00 15.71 C -ATOM 173 C SER A 22 -14.989 -13.518 24.795 1.00 27.98 C -ATOM 174 O SER A 22 -15.346 -14.160 23.810 1.00 18.52 O -ATOM 175 CB SER A 22 -14.824 -15.314 26.508 1.00 13.95 C -ATOM 176 OG SER A 22 -13.431 -15.173 26.702 1.00 17.49 O -ATOM 177 N SER A 23 -14.273 -12.416 24.652 1.00 17.53 N -ATOM 178 CA SER A 23 -13.869 -11.906 23.350 1.00 21.71 C -ATOM 179 C SER A 23 -12.546 -11.168 23.448 1.00 27.30 C -ATOM 180 O SER A 23 -12.101 -10.859 24.561 1.00 18.45 O -ATOM 181 CB SER A 23 -14.984 -11.006 22.851 1.00 13.04 C -ATOM 182 OG SER A 23 -15.192 -9.821 23.590 1.00 17.20 O -ATOM 183 N ARG A 24 -11.805 -10.927 22.371 1.00 16.47 N -ATOM 184 CA ARG A 24 -10.586 -10.139 22.390 1.00 18.28 C -ATOM 185 C ARG A 24 -10.232 -9.787 20.944 1.00 21.67 C -ATOM 186 O ARG A 24 -10.765 -10.417 20.032 1.00 17.72 O -ATOM 187 CB ARG A 24 -9.384 -10.889 22.934 1.00 14.39 C -ATOM 188 CG ARG A 24 -8.805 -12.022 22.187 1.00 17.95 C -ATOM 189 CD ARG A 24 -7.506 -12.385 22.785 1.00 18.22 C -ATOM 190 NE ARG A 24 -6.965 -13.447 21.943 1.00 16.16 N -ATOM 191 CZ ARG A 24 -5.984 -14.286 22.251 1.00 22.92 C -ATOM 192 NH1 ARG A 24 -5.364 -14.285 23.426 1.00 23.47 N -ATOM 193 NH2 ARG A 24 -5.544 -15.105 21.299 1.00 24.06 N -ATOM 194 N SER A 25 -9.355 -8.836 20.719 1.00 19.57 N -ATOM 195 CA SER A 25 -8.788 -8.593 19.406 1.00 19.55 C -ATOM 196 C SER A 25 -7.354 -8.200 19.668 1.00 22.34 C -ATOM 197 O SER A 25 -7.009 -7.632 20.724 1.00 18.07 O -ATOM 198 CB SER A 25 -9.563 -7.488 18.650 1.00 15.96 C -ATOM 199 OG SER A 25 -9.822 -6.295 19.331 1.00 31.90 O -ATOM 200 N ARG A 26 -6.442 -8.524 18.741 1.00 16.42 N -ATOM 201 CA ARG A 26 -5.006 -8.261 18.856 1.00 14.69 C -ATOM 202 C ARG A 26 -4.472 -7.806 17.479 1.00 18.06 C -ATOM 203 O ARG A 26 -5.093 -8.135 16.455 1.00 16.70 O -ATOM 204 CB ARG A 26 -4.249 -9.528 19.261 1.00 15.19 C -ATOM 205 CG ARG A 26 -4.855 -10.136 20.527 1.00 18.12 C -ATOM 206 CD ARG A 26 -3.970 -11.208 21.079 1.00 19.43 C -ATOM 207 NE ARG A 26 -3.803 -12.232 20.097 1.00 17.77 N -ATOM 208 CZ ARG A 26 -2.963 -13.245 20.234 1.00 29.11 C -ATOM 209 NH1 ARG A 26 -2.202 -13.413 21.297 1.00 20.54 N -ATOM 210 NH2 ARG A 26 -2.829 -14.114 19.235 1.00 23.76 N -ATOM 211 N VAL A 27 -3.371 -7.074 17.436 1.00 18.18 N -ATOM 212 CA VAL A 27 -2.700 -6.649 16.202 1.00 17.02 C -ATOM 213 C VAL A 27 -1.254 -7.078 16.396 1.00 20.98 C -ATOM 214 O VAL A 27 -0.700 -6.935 17.506 1.00 18.90 O -ATOM 215 CB VAL A 27 -2.810 -5.120 16.021 1.00 13.14 C -ATOM 216 CG1 VAL A 27 -1.844 -4.555 14.983 1.00 20.80 C -ATOM 217 CG2 VAL A 27 -4.232 -4.852 15.560 1.00 18.48 C -ATOM 218 N LEU A 28 -0.669 -7.658 15.334 1.00 13.21 N -ATOM 219 CA LEU A 28 0.727 -8.028 15.294 1.00 12.34 C -ATOM 220 C LEU A 28 1.508 -7.115 14.333 1.00 16.60 C -ATOM 221 O LEU A 28 1.087 -6.828 13.211 1.00 19.12 O -ATOM 222 CB LEU A 28 0.834 -9.503 14.877 1.00 15.44 C -ATOM 223 CG LEU A 28 2.234 -10.063 14.618 1.00 17.29 C -ATOM 224 CD1 LEU A 28 3.075 -10.180 15.886 1.00 19.53 C -ATOM 225 CD2 LEU A 28 2.062 -11.434 14.044 1.00 18.79 C -ATOM 226 N PHE A 29 2.623 -6.562 14.779 1.00 14.46 N -ATOM 227 CA PHE A 29 3.533 -5.760 13.971 1.00 19.10 C -ATOM 228 C PHE A 29 4.627 -6.700 13.519 1.00 28.14 C -ATOM 229 O PHE A 29 5.273 -7.290 14.396 1.00 19.55 O -ATOM 230 CB PHE A 29 4.201 -4.663 14.773 1.00 14.05 C -ATOM 231 CG PHE A 29 3.203 -3.682 15.339 1.00 21.24 C -ATOM 232 CD1 PHE A 29 2.576 -2.776 14.523 1.00 17.81 C -ATOM 233 CD2 PHE A 29 2.900 -3.706 16.696 1.00 23.31 C -ATOM 234 CE1 PHE A 29 1.646 -1.902 15.054 1.00 26.27 C -ATOM 235 CE2 PHE A 29 1.972 -2.831 17.226 1.00 20.41 C -ATOM 236 CZ PHE A 29 1.340 -1.928 16.407 1.00 22.27 C -ATOM 237 N THR A 30 4.879 -6.914 12.210 1.00 18.98 N -ATOM 238 CA THR A 30 6.001 -7.751 11.761 1.00 17.37 C -ATOM 239 C THR A 30 6.950 -6.853 11.010 1.00 18.66 C -ATOM 240 O THR A 30 6.537 -6.160 10.078 1.00 21.64 O -ATOM 241 CB THR A 30 5.535 -8.820 10.853 1.00 16.98 C -ATOM 242 OG1 THR A 30 4.602 -9.605 11.567 1.00 23.49 O -ATOM 243 CG2 THR A 30 6.660 -9.675 10.412 1.00 20.20 C -ATOM 244 N MET A 31 8.199 -6.782 11.425 1.00 16.66 N -ATOM 245 CA MET A 31 9.149 -5.864 10.838 1.00 17.95 C -ATOM 246 C MET A 31 10.236 -6.670 10.197 1.00 20.41 C -ATOM 247 O MET A 31 10.633 -7.704 10.743 1.00 16.53 O -ATOM 248 CB MET A 31 9.738 -4.957 11.902 1.00 18.36 C -ATOM 249 CG MET A 31 8.614 -4.154 12.542 1.00 28.91 C -ATOM 250 SD MET A 31 9.221 -2.829 13.578 1.00 29.44 S -ATOM 251 CE MET A 31 9.642 -3.773 14.989 1.00 24.49 C -ATOM 252 N SER A 32 10.719 -6.278 9.007 1.00 18.58 N -ATOM 253 CA SER A 32 11.747 -7.076 8.317 1.00 18.25 C -ATOM 254 C SER A 32 12.663 -6.231 7.441 1.00 17.77 C -ATOM 255 O SER A 32 12.309 -5.074 7.116 1.00 21.99 O -ATOM 256 CB SER A 32 11.084 -8.169 7.454 1.00 21.16 C -ATOM 257 OG SER A 32 10.036 -7.595 6.687 1.00 36.32 O -ATOM 258 N GLY A 33 13.846 -6.810 7.214 1.00 18.75 N -ATOM 259 CA GLY A 33 14.879 -6.169 6.423 1.00 19.45 C -ATOM 260 C GLY A 33 15.928 -7.193 5.988 1.00 19.89 C -ATOM 261 O GLY A 33 15.912 -8.349 6.429 1.00 18.98 O -ATOM 262 N THR A 34 16.861 -6.765 5.111 1.00 20.70 N -ATOM 263 CA THR A 34 17.891 -7.609 4.533 1.00 18.70 C -ATOM 264 C THR A 34 19.122 -6.741 4.408 1.00 15.56 C -ATOM 265 O THR A 34 19.002 -5.588 3.989 1.00 22.55 O -ATOM 266 CB THR A 34 17.516 -8.091 3.111 1.00 23.51 C -ATOM 267 OG1 THR A 34 16.253 -8.696 3.212 1.00 25.34 O -ATOM 268 CG2 THR A 34 18.429 -9.157 2.563 1.00 21.14 C -ATOM 269 N THR A 35 20.302 -7.237 4.741 1.00 16.89 N -ATOM 270 CA THR A 35 21.478 -6.410 4.639 1.00 19.04 C -ATOM 271 C THR A 35 21.964 -6.602 3.189 1.00 31.99 C -ATOM 272 O THR A 35 21.482 -7.478 2.459 1.00 22.91 O -ATOM 273 CB THR A 35 22.529 -6.898 5.632 1.00 21.23 C -ATOM 274 OG1 THR A 35 22.879 -8.235 5.245 1.00 19.46 O -ATOM 275 CG2 THR A 35 21.993 -6.888 7.090 1.00 20.86 C -ATOM 276 N ASP A 36 22.997 -5.869 2.796 1.00 26.13 N -ATOM 277 CA ASP A 36 23.590 -5.924 1.463 1.00 25.73 C -ATOM 278 C ASP A 36 24.060 -7.327 1.137 1.00 25.09 C -ATOM 279 O ASP A 36 23.867 -7.777 0.000 1.00 31.82 O -ATOM 280 CB ASP A 36 24.735 -4.929 1.425 1.00 23.29 C -ATOM 281 CG ASP A 36 24.297 -3.456 1.398 1.00 29.35 C -ATOM 282 OD1 ASP A 36 23.086 -3.192 1.251 1.00 32.92 O -ATOM 283 OD2 ASP A 36 25.180 -2.587 1.538 1.00 36.59 O -ATOM 284 N SER A 37 24.590 -8.117 2.070 1.00 25.70 N -ATOM 285 CA SER A 37 24.981 -9.467 1.714 1.00 23.90 C -ATOM 286 C SER A 37 23.883 -10.508 1.852 1.00 22.34 C -ATOM 287 O SER A 37 24.157 -11.702 1.670 1.00 24.38 O -ATOM 288 CB SER A 37 26.190 -9.852 2.557 1.00 30.09 C -ATOM 289 OG SER A 37 25.867 -9.979 3.940 1.00 48.00 O -ATOM 290 N GLY A 38 22.646 -10.103 2.203 1.00 21.78 N -ATOM 291 CA GLY A 38 21.563 -11.054 2.307 1.00 18.40 C -ATOM 292 C GLY A 38 21.344 -11.680 3.691 1.00 21.34 C -ATOM 293 O GLY A 38 20.692 -12.732 3.780 1.00 22.81 O -ATOM 294 N LEU A 39 21.905 -11.117 4.777 1.00 21.84 N -ATOM 295 CA LEU A 39 21.498 -11.566 6.115 1.00 23.27 C -ATOM 296 C LEU A 39 20.097 -10.977 6.290 1.00 19.54 C -ATOM 297 O LEU A 39 19.805 -9.851 5.869 1.00 23.50 O -ATOM 298 CB LEU A 39 22.375 -10.994 7.207 1.00 22.31 C -ATOM 299 CG LEU A 39 23.816 -11.396 7.138 1.00 21.30 C -ATOM 300 CD1 LEU A 39 24.572 -10.776 8.272 1.00 28.69 C -ATOM 301 CD2 LEU A 39 23.898 -12.869 7.179 1.00 25.27 C -ATOM 302 N GLU A 40 19.151 -11.696 6.862 1.00 18.39 N -ATOM 303 CA GLU A 40 17.800 -11.215 7.032 1.00 18.96 C -ATOM 304 C GLU A 40 17.670 -10.825 8.514 1.00 26.64 C -ATOM 305 O GLU A 40 18.276 -11.448 9.393 1.00 22.66 O -ATOM 306 CB GLU A 40 16.815 -12.318 6.729 1.00 21.71 C -ATOM 307 CG GLU A 40 16.895 -12.947 5.330 1.00 36.43 C -ATOM 308 CD GLU A 40 16.532 -11.980 4.209 1.00 58.73 C -ATOM 309 OE1 GLU A 40 15.614 -11.176 4.367 1.00 52.82 O -ATOM 310 OE2 GLU A 40 17.172 -12.043 3.163 1.00 61.13 O -ATOM 311 N PHE A 41 16.903 -9.813 8.825 1.00 23.28 N -ATOM 312 CA PHE A 41 16.729 -9.397 10.204 1.00 20.43 C -ATOM 313 C PHE A 41 15.288 -9.003 10.392 1.00 33.11 C -ATOM 314 O PHE A 41 14.563 -8.770 9.407 1.00 17.55 O -ATOM 315 CB PHE A 41 17.694 -8.252 10.489 1.00 17.40 C -ATOM 316 CG PHE A 41 17.603 -6.962 9.670 1.00 19.97 C -ATOM 317 CD1 PHE A 41 16.752 -5.938 10.031 1.00 18.79 C -ATOM 318 CD2 PHE A 41 18.455 -6.794 8.582 1.00 24.90 C -ATOM 319 CE1 PHE A 41 16.740 -4.744 9.333 1.00 18.42 C -ATOM 320 CE2 PHE A 41 18.444 -5.600 7.882 1.00 18.53 C -ATOM 321 CZ PHE A 41 17.594 -4.583 8.257 1.00 20.56 C -ATOM 322 N GLY A 42 14.810 -8.936 11.626 1.00 16.60 N -ATOM 323 CA GLY A 42 13.432 -8.570 11.827 1.00 15.94 C -ATOM 324 C GLY A 42 13.130 -8.441 13.326 1.00 18.51 C -ATOM 325 O GLY A 42 14.038 -8.612 14.142 1.00 17.74 O -ATOM 326 N ALA A 43 11.882 -8.141 13.619 1.00 19.68 N -ATOM 327 CA ALA A 43 11.393 -8.009 14.983 1.00 19.54 C -ATOM 328 C ALA A 43 9.876 -8.122 14.929 1.00 25.22 C -ATOM 329 O ALA A 43 9.252 -7.819 13.898 1.00 20.81 O -ATOM 330 CB ALA A 43 11.797 -6.646 15.537 1.00 16.52 C -ATOM 331 N SER A 44 9.180 -8.631 15.949 1.00 17.32 N -ATOM 332 CA SER A 44 7.736 -8.545 15.971 1.00 13.95 C -ATOM 333 C SER A 44 7.250 -8.527 17.428 1.00 17.36 C -ATOM 334 O SER A 44 7.963 -9.025 18.307 1.00 16.29 O -ATOM 335 CB SER A 44 7.093 -9.733 15.268 1.00 18.32 C -ATOM 336 OG SER A 44 7.556 -10.959 15.751 1.00 28.70 O -ATOM 337 N PHE A 45 6.076 -7.971 17.629 1.00 18.21 N -ATOM 338 CA PHE A 45 5.403 -7.974 18.916 1.00 19.59 C -ATOM 339 C PHE A 45 3.972 -7.562 18.664 1.00 21.25 C -ATOM 340 O PHE A 45 3.681 -7.002 17.593 1.00 19.84 O -ATOM 341 CB PHE A 45 6.102 -6.994 19.881 1.00 12.80 C -ATOM 342 CG PHE A 45 6.124 -5.522 19.533 1.00 16.76 C -ATOM 343 CD1 PHE A 45 5.086 -4.685 19.910 1.00 13.03 C -ATOM 344 CD2 PHE A 45 7.207 -4.996 18.829 1.00 15.77 C -ATOM 345 CE1 PHE A 45 5.134 -3.325 19.575 1.00 18.11 C -ATOM 346 CE2 PHE A 45 7.242 -3.644 18.503 1.00 14.29 C -ATOM 347 CZ PHE A 45 6.208 -2.799 18.869 1.00 18.49 C -ATOM 348 N LYS A 46 3.049 -7.825 19.601 1.00 14.65 N -ATOM 349 CA LYS A 46 1.661 -7.465 19.434 1.00 13.19 C -ATOM 350 C LYS A 46 1.393 -6.162 20.108 1.00 16.83 C -ATOM 351 O LYS A 46 2.154 -5.743 20.989 1.00 18.21 O -ATOM 352 CB LYS A 46 0.738 -8.518 20.001 1.00 14.48 C -ATOM 353 CG LYS A 46 1.038 -9.835 19.322 1.00 19.35 C -ATOM 354 CD LYS A 46 -0.003 -10.886 19.568 1.00 22.07 C -ATOM 355 CE LYS A 46 0.414 -12.179 18.892 1.00 29.45 C -ATOM 356 NZ LYS A 46 1.569 -12.753 19.553 1.00 30.58 N -ATOM 357 N ALA A 47 0.308 -5.501 19.763 1.00 13.74 N -ATOM 358 CA ALA A 47 0.078 -4.159 20.218 1.00 14.51 C -ATOM 359 C ALA A 47 -0.066 -4.148 21.761 1.00 17.84 C -ATOM 360 O ALA A 47 0.398 -3.213 22.427 1.00 16.71 O -ATOM 361 CB ALA A 47 -1.210 -3.622 19.625 1.00 13.21 C -ATOM 362 N HIS A 48 -0.708 -5.145 22.361 1.00 18.81 N -ATOM 363 CA HIS A 48 -0.891 -5.162 23.828 1.00 17.50 C -ATOM 364 C HIS A 48 0.419 -5.424 24.553 1.00 22.24 C -ATOM 365 O HIS A 48 0.466 -5.259 25.766 1.00 17.89 O -ATOM 366 CB HIS A 48 -1.945 -6.227 24.217 1.00 11.96 C -ATOM 367 CG HIS A 48 -1.534 -7.665 24.011 1.00 19.24 C -ATOM 368 ND1 HIS A 48 -1.497 -8.384 22.895 1.00 19.50 N -ATOM 369 CD2 HIS A 48 -1.086 -8.486 25.013 1.00 18.37 C -ATOM 370 CE1 HIS A 48 -1.055 -9.584 23.167 1.00 20.35 C -ATOM 371 NE2 HIS A 48 -0.808 -9.640 24.459 1.00 20.64 N -ATOM 372 N GLU A 49 1.498 -5.770 23.833 1.00 14.70 N -ATOM 373 CA GLU A 49 2.792 -6.076 24.377 1.00 14.46 C -ATOM 374 C GLU A 49 3.721 -4.937 24.115 1.00 14.22 C -ATOM 375 O GLU A 49 4.926 -5.114 24.355 1.00 15.82 O -ATOM 376 CB GLU A 49 3.502 -7.231 23.733 1.00 15.73 C -ATOM 377 CG GLU A 49 2.678 -8.470 23.628 1.00 24.60 C -ATOM 378 CD GLU A 49 3.401 -9.595 22.894 1.00 32.30 C -ATOM 379 OE1 GLU A 49 3.947 -9.415 21.802 1.00 21.35 O -ATOM 380 OE2 GLU A 49 3.405 -10.693 23.434 1.00 21.91 O -ATOM 381 N SER A 50 3.267 -3.778 23.639 1.00 14.73 N -ATOM 382 CA SER A 50 4.225 -2.763 23.249 1.00 13.74 C -ATOM 383 C SER A 50 5.102 -2.232 24.381 1.00 20.29 C -ATOM 384 O SER A 50 6.283 -1.952 24.134 1.00 16.11 O -ATOM 385 CB ASER A 50 3.509 -1.575 22.648 0.60 12.78 C -ATOM 386 CB BSER A 50 3.508 -1.603 22.576 0.40 12.35 C -ATOM 387 OG ASER A 50 2.591 -1.903 21.621 0.60 15.12 O -ATOM 388 OG BSER A 50 2.465 -1.023 23.337 0.40 13.87 O -ATOM 389 N VAL A 51 4.593 -2.082 25.643 1.00 15.56 N -ATOM 390 CA VAL A 51 5.457 -1.647 26.754 1.00 16.90 C -ATOM 391 C VAL A 51 6.573 -2.640 27.042 1.00 10.27 C -ATOM 392 O VAL A 51 7.741 -2.242 27.190 1.00 17.77 O -ATOM 393 CB VAL A 51 4.552 -1.433 27.990 1.00 16.34 C -ATOM 394 CG1 VAL A 51 5.421 -1.112 29.187 1.00 18.56 C -ATOM 395 CG2 VAL A 51 3.614 -0.273 27.756 1.00 16.82 C -ATOM 396 N GLY A 52 6.229 -3.936 27.076 1.00 12.24 N -ATOM 397 CA GLY A 52 7.179 -4.995 27.308 1.00 13.64 C -ATOM 398 C GLY A 52 8.163 -5.141 26.173 1.00 15.14 C -ATOM 399 O GLY A 52 9.333 -5.412 26.407 1.00 15.99 O -ATOM 400 N ALA A 53 7.731 -4.935 24.916 1.00 18.76 N -ATOM 401 CA ALA A 53 8.646 -5.080 23.781 1.00 14.32 C -ATOM 402 C ALA A 53 9.731 -4.043 23.846 1.00 10.54 C -ATOM 403 O ALA A 53 10.860 -4.300 23.428 1.00 15.30 O -ATOM 404 CB ALA A 53 7.858 -4.926 22.504 1.00 14.72 C -ATOM 405 N GLU A 54 9.478 -2.845 24.408 1.00 13.35 N -ATOM 406 CA GLU A 54 10.494 -1.846 24.572 1.00 13.86 C -ATOM 407 C GLU A 54 11.561 -2.194 25.631 1.00 17.54 C -ATOM 408 O GLU A 54 12.581 -1.509 25.658 1.00 17.99 O -ATOM 409 CB GLU A 54 9.754 -0.556 24.867 1.00 16.36 C -ATOM 410 CG GLU A 54 10.604 0.728 24.700 1.00 19.98 C -ATOM 411 CD GLU A 54 11.242 1.324 25.973 1.00 33.77 C -ATOM 412 OE1 GLU A 54 10.752 1.040 27.063 1.00 26.33 O -ATOM 413 OE2 GLU A 54 12.220 2.070 25.890 1.00 28.75 O -ATOM 414 N THR A 55 11.475 -3.220 26.506 1.00 19.05 N -ATOM 415 CA THR A 55 12.551 -3.557 27.444 1.00 15.96 C -ATOM 416 C THR A 55 13.110 -4.947 27.155 1.00 17.46 C -ATOM 417 O THR A 55 14.042 -5.381 27.817 1.00 21.17 O -ATOM 418 CB THR A 55 12.005 -3.513 28.919 1.00 13.94 C -ATOM 419 OG1 THR A 55 11.287 -4.727 29.108 1.00 16.77 O -ATOM 420 CG2 THR A 55 11.073 -2.348 29.195 1.00 18.93 C -ATOM 421 N GLY A 56 12.570 -5.748 26.218 1.00 18.11 N -ATOM 422 CA GLY A 56 13.084 -7.088 25.925 1.00 14.36 C -ATOM 423 C GLY A 56 12.237 -8.176 26.524 1.00 14.53 C -ATOM 424 O GLY A 56 12.434 -9.374 26.329 1.00 19.77 O -ATOM 425 N GLU A 57 11.236 -7.772 27.302 1.00 17.95 N -ATOM 426 CA GLU A 57 10.388 -8.714 28.003 1.00 14.56 C -ATOM 427 C GLU A 57 9.399 -9.429 27.094 1.00 19.55 C -ATOM 428 O GLU A 57 8.985 -10.570 27.364 1.00 18.74 O -ATOM 429 CB GLU A 57 9.647 -7.937 29.080 1.00 15.25 C -ATOM 430 CG GLU A 57 8.695 -8.852 29.844 1.00 25.44 C -ATOM 431 CD GLU A 57 7.968 -8.238 31.032 1.00 32.41 C -ATOM 432 OE1 GLU A 57 7.965 -7.015 31.165 1.00 25.94 O -ATOM 433 OE2 GLU A 57 7.404 -9.005 31.819 1.00 40.55 O -ATOM 434 N ASP A 58 8.907 -8.711 26.061 1.00 16.20 N -ATOM 435 CA ASP A 58 7.928 -9.271 25.141 1.00 12.73 C -ATOM 436 C ASP A 58 8.437 -9.040 23.703 1.00 13.30 C -ATOM 437 O ASP A 58 9.261 -8.155 23.492 1.00 14.77 O -ATOM 438 CB ASP A 58 6.608 -8.577 25.263 1.00 14.67 C -ATOM 439 CG ASP A 58 5.857 -8.919 26.553 1.00 21.34 C -ATOM 440 OD1 ASP A 58 5.853 -10.077 26.968 1.00 21.30 O -ATOM 441 OD2 ASP A 58 5.266 -8.004 27.106 1.00 23.15 O -ATOM 442 N GLY A 59 7.926 -9.816 22.763 1.00 19.15 N -ATOM 443 CA GLY A 59 8.326 -9.704 21.358 1.00 17.18 C -ATOM 444 C GLY A 59 9.697 -10.284 21.149 1.00 19.54 C -ATOM 445 O GLY A 59 10.389 -10.660 22.106 1.00 19.80 O -ATOM 446 N THR A 60 10.154 -10.452 19.904 1.00 16.10 N -ATOM 447 CA THR A 60 11.516 -10.939 19.634 1.00 16.20 C -ATOM 448 C THR A 60 12.208 -10.120 18.533 1.00 19.22 C -ATOM 449 O THR A 60 11.492 -9.446 17.781 1.00 17.59 O -ATOM 450 CB THR A 60 11.550 -12.410 19.180 1.00 22.89 C -ATOM 451 OG1 THR A 60 10.585 -12.586 18.156 1.00 24.63 O -ATOM 452 CG2 THR A 60 11.269 -13.368 20.330 1.00 22.82 C -ATOM 453 N VAL A 61 13.543 -10.107 18.509 1.00 17.23 N -ATOM 454 CA VAL A 61 14.372 -9.452 17.504 1.00 19.01 C -ATOM 455 C VAL A 61 15.238 -10.597 16.937 1.00 26.28 C -ATOM 456 O VAL A 61 15.644 -11.502 17.696 1.00 18.85 O -ATOM 457 CB VAL A 61 15.254 -8.357 18.149 1.00 17.83 C -ATOM 458 CG1 VAL A 61 16.149 -7.691 17.106 1.00 18.08 C -ATOM 459 CG2 VAL A 61 14.370 -7.300 18.743 1.00 17.74 C -ATOM 460 N PHE A 62 15.514 -10.677 15.619 1.00 19.51 N -ATOM 461 CA PHE A 62 16.360 -11.751 15.103 1.00 17.61 C -ATOM 462 C PHE A 62 17.285 -11.275 13.976 1.00 21.17 C -ATOM 463 O PHE A 62 17.061 -10.220 13.354 1.00 17.39 O -ATOM 464 CB PHE A 62 15.511 -12.906 14.593 1.00 17.41 C -ATOM 465 CG PHE A 62 14.791 -12.663 13.262 1.00 22.01 C -ATOM 466 CD1 PHE A 62 15.435 -12.942 12.052 1.00 26.08 C -ATOM 467 CD2 PHE A 62 13.491 -12.194 13.274 1.00 20.41 C -ATOM 468 CE1 PHE A 62 14.763 -12.753 10.858 1.00 24.18 C -ATOM 469 CE2 PHE A 62 12.832 -12.009 12.065 1.00 39.24 C -ATOM 470 CZ PHE A 62 13.459 -12.287 10.860 1.00 26.42 C -ATOM 471 N LEU A 63 18.313 -12.091 13.770 1.00 21.61 N -ATOM 472 CA LEU A 63 19.300 -11.936 12.695 1.00 23.98 C -ATOM 473 C LEU A 63 19.526 -13.326 12.165 1.00 24.88 C -ATOM 474 O LEU A 63 19.743 -14.212 12.996 1.00 20.07 O -ATOM 475 CB LEU A 63 20.666 -11.435 13.169 1.00 23.98 C -ATOM 476 CG LEU A 63 21.744 -11.227 12.093 1.00 27.68 C -ATOM 477 CD1 LEU A 63 21.356 -10.091 11.154 1.00 22.99 C -ATOM 478 CD2 LEU A 63 23.025 -10.825 12.760 1.00 34.32 C -ATOM 479 N SER A 64 19.433 -13.609 10.848 1.00 21.19 N -ATOM 480 CA SER A 64 19.710 -14.943 10.320 1.00 18.57 C -ATOM 481 C SER A 64 20.561 -14.868 9.041 1.00 18.66 C -ATOM 482 O SER A 64 20.680 -13.840 8.382 1.00 22.26 O -ATOM 483 CB SER A 64 18.431 -15.690 10.024 1.00 18.27 C -ATOM 484 OG SER A 64 17.538 -15.009 9.176 1.00 24.76 O -ATOM 485 N GLY A 65 21.253 -15.940 8.800 1.00 21.15 N -ATOM 486 CA GLY A 65 22.140 -16.038 7.682 1.00 24.41 C -ATOM 487 C GLY A 65 22.359 -17.507 7.432 1.00 28.66 C -ATOM 488 O GLY A 65 21.615 -18.399 7.867 1.00 22.09 O -ATOM 489 N ALA A 66 23.471 -17.768 6.775 1.00 26.28 N -ATOM 490 CA ALA A 66 23.831 -19.125 6.445 1.00 25.46 C -ATOM 491 C ALA A 66 24.142 -19.955 7.687 1.00 26.02 C -ATOM 492 O ALA A 66 24.006 -21.176 7.675 1.00 27.00 O -ATOM 493 CB ALA A 66 25.052 -19.103 5.562 1.00 28.91 C -ATOM 494 N PHE A 67 24.560 -19.236 8.733 1.00 33.18 N -ATOM 495 CA PHE A 67 24.872 -19.766 10.064 1.00 33.95 C -ATOM 496 C PHE A 67 23.639 -20.176 10.879 1.00 35.16 C -ATOM 497 O PHE A 67 23.792 -20.833 11.897 1.00 30.66 O -ATOM 498 CB PHE A 67 25.670 -18.717 10.875 1.00 23.01 C -ATOM 499 CG PHE A 67 24.970 -17.367 11.142 1.00 45.98 C -ATOM 500 CD1 PHE A 67 24.078 -17.228 12.210 1.00 41.66 C -ATOM 501 CD2 PHE A 67 25.204 -16.287 10.294 1.00 34.67 C -ATOM 502 CE1 PHE A 67 23.430 -16.028 12.410 1.00 40.95 C -ATOM 503 CE2 PHE A 67 24.550 -15.087 10.505 1.00 32.83 C -ATOM 504 CZ PHE A 67 23.665 -14.960 11.562 1.00 35.21 C -ATOM 505 N GLY A 68 22.416 -19.819 10.532 1.00 20.84 N -ATOM 506 CA GLY A 68 21.265 -20.203 11.306 1.00 21.82 C -ATOM 507 C GLY A 68 20.642 -18.916 11.769 1.00 28.92 C -ATOM 508 O GLY A 68 20.925 -17.877 11.156 1.00 24.29 O -ATOM 509 N LYS A 69 19.851 -18.891 12.843 1.00 21.72 N -ATOM 510 CA LYS A 69 19.098 -17.707 13.231 1.00 18.84 C -ATOM 511 C LYS A 69 19.320 -17.462 14.730 1.00 23.51 C -ATOM 512 O LYS A 69 19.251 -18.415 15.506 1.00 20.90 O -ATOM 513 CB LYS A 69 17.634 -17.977 12.954 1.00 16.30 C -ATOM 514 CG LYS A 69 16.700 -16.815 13.294 1.00 16.85 C -ATOM 515 CD LYS A 69 15.304 -17.356 13.064 1.00 20.17 C -ATOM 516 CE LYS A 69 14.288 -16.324 13.436 1.00 31.92 C -ATOM 517 NZ LYS A 69 12.951 -16.787 13.098 1.00 46.73 N -ATOM 518 N ILE A 70 19.558 -16.242 15.121 1.00 19.45 N -ATOM 519 CA ILE A 70 19.738 -15.850 16.517 1.00 23.74 C -ATOM 520 C ILE A 70 18.550 -14.960 16.846 1.00 25.87 C -ATOM 521 O ILE A 70 18.354 -13.935 16.184 1.00 20.11 O -ATOM 522 CB ILE A 70 21.033 -15.053 16.665 1.00 25.58 C -ATOM 523 CG1 ILE A 70 22.222 -15.938 16.316 1.00 43.31 C -ATOM 524 CG2 ILE A 70 21.155 -14.549 18.101 1.00 33.44 C -ATOM 525 CD1 ILE A 70 23.489 -15.098 16.072 1.00 57.37 C -ATOM 526 N GLU A 71 17.762 -15.262 17.870 1.00 19.38 N -ATOM 527 CA GLU A 71 16.580 -14.500 18.236 1.00 17.37 C -ATOM 528 C GLU A 71 16.710 -14.081 19.723 1.00 24.39 C -ATOM 529 O GLU A 71 17.124 -14.941 20.523 1.00 20.85 O -ATOM 530 CB GLU A 71 15.440 -15.420 18.004 1.00 15.42 C -ATOM 531 CG GLU A 71 14.084 -14.781 18.104 1.00 22.29 C -ATOM 532 CD GLU A 71 12.943 -15.740 17.774 1.00 23.14 C -ATOM 533 OE1 GLU A 71 13.125 -16.928 17.975 1.00 42.67 O -ATOM 534 OE2 GLU A 71 11.889 -15.293 17.301 1.00 53.77 O -ATOM 535 N MET A 72 16.371 -12.852 20.135 1.00 19.50 N -ATOM 536 CA MET A 72 16.509 -12.441 21.530 1.00 17.32 C -ATOM 537 C MET A 72 15.222 -11.759 21.904 1.00 23.46 C -ATOM 538 O MET A 72 14.672 -11.008 21.078 1.00 19.57 O -ATOM 539 CB MET A 72 17.661 -11.496 21.646 1.00 18.57 C -ATOM 540 CG MET A 72 18.009 -11.158 23.111 1.00 19.11 C -ATOM 541 SD MET A 72 19.490 -10.156 23.277 1.00 23.42 S -ATOM 542 CE MET A 72 20.692 -11.366 22.863 1.00 18.32 C -ATOM 543 N GLY A 73 14.688 -12.049 23.105 1.00 17.35 N -ATOM 544 CA GLY A 73 13.504 -11.376 23.637 1.00 14.94 C -ATOM 545 C GLY A 73 12.683 -12.424 24.343 1.00 13.51 C -ATOM 546 O GLY A 73 13.232 -13.308 25.002 1.00 18.04 O -ATOM 547 N ASP A 74 11.386 -12.433 24.107 1.00 15.69 N -ATOM 548 CA ASP A 74 10.515 -13.406 24.681 1.00 17.65 C -ATOM 549 C ASP A 74 10.486 -14.603 23.728 1.00 22.75 C -ATOM 550 O ASP A 74 9.524 -14.828 23.003 1.00 21.21 O -ATOM 551 CB ASP A 74 9.137 -12.740 24.892 1.00 14.59 C -ATOM 552 CG ASP A 74 8.076 -13.590 25.598 1.00 19.98 C -ATOM 553 OD1 ASP A 74 8.318 -14.775 25.902 1.00 18.00 O -ATOM 554 OD2 ASP A 74 6.980 -13.063 25.837 1.00 24.40 O -ATOM 555 N ALA A 75 11.532 -15.419 23.750 1.00 18.50 N -ATOM 556 CA ALA A 75 11.713 -16.573 22.864 1.00 19.75 C -ATOM 557 C ALA A 75 11.337 -17.890 23.491 1.00 25.86 C -ATOM 558 O ALA A 75 11.278 -18.023 24.725 1.00 24.49 O -ATOM 559 CB ALA A 75 13.178 -16.655 22.429 1.00 15.70 C -ATOM 560 N LEU A 76 11.070 -18.878 22.664 1.00 18.04 N -ATOM 561 CA LEU A 76 10.802 -20.214 23.107 1.00 15.51 C -ATOM 562 C LEU A 76 12.092 -20.838 23.503 1.00 14.71 C -ATOM 563 O LEU A 76 13.152 -20.342 23.143 1.00 17.59 O -ATOM 564 CB LEU A 76 10.206 -21.060 22.015 1.00 16.00 C -ATOM 565 CG LEU A 76 8.883 -20.535 21.479 1.00 22.46 C -ATOM 566 CD1 LEU A 76 8.475 -21.434 20.341 1.00 21.79 C -ATOM 567 CD2 LEU A 76 7.799 -20.480 22.572 1.00 22.12 C -ATOM 568 N GLY A 77 12.076 -21.891 24.310 1.00 17.76 N -ATOM 569 CA GLY A 77 13.327 -22.567 24.572 1.00 17.10 C -ATOM 570 C GLY A 77 13.556 -23.559 23.419 1.00 17.15 C -ATOM 571 O GLY A 77 12.610 -23.809 22.655 1.00 18.35 O -ATOM 572 N ALA A 78 14.754 -24.139 23.296 1.00 20.25 N -ATOM 573 CA ALA A 78 15.128 -25.036 22.197 1.00 16.35 C -ATOM 574 C ALA A 78 14.198 -26.183 21.912 1.00 23.67 C -ATOM 575 O ALA A 78 13.814 -26.393 20.755 1.00 22.78 O -ATOM 576 CB ALA A 78 16.462 -25.588 22.481 1.00 18.71 C -ATOM 577 N SER A 79 13.714 -26.937 22.908 1.00 18.97 N -ATOM 578 CA SER A 79 12.786 -28.017 22.665 1.00 20.71 C -ATOM 579 C SER A 79 11.439 -27.556 22.153 1.00 27.48 C -ATOM 580 O SER A 79 10.922 -28.131 21.189 1.00 21.54 O -ATOM 581 CB SER A 79 12.560 -28.836 23.938 1.00 24.34 C -ATOM 582 OG SER A 79 13.824 -29.214 24.459 1.00 24.45 O -ATOM 583 N GLU A 80 10.819 -26.536 22.748 1.00 20.47 N -ATOM 584 CA GLU A 80 9.535 -26.056 22.298 1.00 18.48 C -ATOM 585 C GLU A 80 9.685 -25.501 20.868 1.00 15.64 C -ATOM 586 O GLU A 80 8.783 -25.769 20.080 1.00 21.68 O -ATOM 587 CB GLU A 80 9.069 -24.969 23.223 1.00 14.52 C -ATOM 588 CG GLU A 80 7.633 -24.660 22.893 1.00 19.36 C -ATOM 589 CD GLU A 80 6.848 -23.844 23.889 1.00 21.31 C -ATOM 590 OE1 GLU A 80 7.308 -23.565 24.990 1.00 23.28 O -ATOM 591 OE2 GLU A 80 5.698 -23.516 23.611 1.00 17.31 O -ATOM 592 N ALA A 81 10.788 -24.801 20.564 1.00 18.80 N -ATOM 593 CA ALA A 81 11.098 -24.231 19.243 1.00 19.97 C -ATOM 594 C ALA A 81 11.057 -25.363 18.192 1.00 25.91 C -ATOM 595 O ALA A 81 10.494 -25.167 17.108 1.00 26.82 O -ATOM 596 CB ALA A 81 12.488 -23.601 19.244 1.00 18.56 C -ATOM 597 N LEU A 82 11.536 -26.581 18.470 1.00 24.81 N -ATOM 598 CA LEU A 82 11.430 -27.667 17.504 1.00 20.49 C -ATOM 599 C LEU A 82 10.182 -28.507 17.592 1.00 30.61 C -ATOM 600 O LEU A 82 9.701 -28.908 16.531 1.00 30.38 O -ATOM 601 CB LEU A 82 12.645 -28.604 17.602 1.00 18.07 C -ATOM 602 CG LEU A 82 14.010 -27.947 17.469 1.00 23.91 C -ATOM 603 CD1 LEU A 82 15.093 -28.988 17.327 1.00 21.74 C -ATOM 604 CD2 LEU A 82 13.996 -27.023 16.282 1.00 22.55 C -ATOM 605 N PHE A 83 9.531 -28.797 18.743 1.00 23.86 N -ATOM 606 CA PHE A 83 8.420 -29.760 18.772 1.00 18.13 C -ATOM 607 C PHE A 83 7.055 -29.177 18.997 1.00 21.39 C -ATOM 608 O PHE A 83 6.075 -29.879 18.742 1.00 24.29 O -ATOM 609 CB PHE A 83 8.669 -30.868 19.847 1.00 20.46 C -ATOM 610 CG PHE A 83 10.096 -31.430 19.770 1.00 31.47 C -ATOM 611 CD1 PHE A 83 10.595 -31.925 18.569 1.00 36.76 C -ATOM 612 CD2 PHE A 83 10.920 -31.396 20.884 1.00 29.87 C -ATOM 613 CE1 PHE A 83 11.894 -32.359 18.508 1.00 29.95 C -ATOM 614 CE2 PHE A 83 12.217 -31.832 20.811 1.00 27.18 C -ATOM 615 CZ PHE A 83 12.701 -32.308 19.620 1.00 28.91 C -ATOM 616 N GLY A 84 6.950 -27.901 19.432 1.00 21.59 N -ATOM 617 CA GLY A 84 5.655 -27.273 19.633 1.00 19.54 C -ATOM 618 C GLY A 84 4.752 -27.918 20.688 1.00 20.13 C -ATOM 619 O GLY A 84 5.208 -28.576 21.628 1.00 24.79 O -ATOM 620 N ASP A 85 3.452 -27.708 20.541 1.00 18.15 N -ATOM 621 CA ASP A 85 2.428 -28.142 21.477 1.00 22.04 C -ATOM 622 C ASP A 85 1.488 -29.149 20.869 1.00 32.84 C -ATOM 623 O ASP A 85 1.564 -29.420 19.679 1.00 25.86 O -ATOM 624 CB ASP A 85 1.613 -26.922 21.969 1.00 21.66 C -ATOM 625 CG ASP A 85 2.469 -26.050 22.883 1.00 22.97 C -ATOM 626 OD1 ASP A 85 3.261 -26.564 23.668 1.00 22.67 O -ATOM 627 OD2 ASP A 85 2.388 -24.840 22.763 1.00 22.22 O -ATOM 628 N LEU A 86 0.563 -29.709 21.643 1.00 21.52 N -ATOM 629 CA LEU A 86 -0.397 -30.678 21.160 1.00 19.15 C -ATOM 630 C LEU A 86 -1.549 -29.874 20.579 1.00 18.35 C -ATOM 631 O LEU A 86 -1.559 -28.627 20.662 1.00 21.62 O -ATOM 632 CB LEU A 86 -0.857 -31.592 22.322 1.00 18.02 C -ATOM 633 CG LEU A 86 0.206 -32.397 23.057 1.00 21.20 C -ATOM 634 CD1 LEU A 86 -0.562 -33.296 24.012 1.00 24.06 C -ATOM 635 CD2 LEU A 86 1.083 -33.271 22.144 1.00 22.07 C -ATOM 636 N TYR A 87 -2.516 -30.554 19.969 1.00 20.03 N -ATOM 637 CA TYR A 87 -3.665 -29.918 19.323 1.00 23.10 C -ATOM 638 C TYR A 87 -4.395 -28.937 20.251 1.00 35.01 C -ATOM 639 O TYR A 87 -4.824 -29.313 21.327 1.00 21.25 O -ATOM 640 CB TYR A 87 -4.648 -31.014 18.836 1.00 22.33 C -ATOM 641 CG TYR A 87 -5.850 -30.450 18.083 1.00 24.26 C -ATOM 642 CD1 TYR A 87 -5.703 -29.865 16.826 1.00 29.11 C -ATOM 643 CD2 TYR A 87 -7.092 -30.502 18.680 1.00 25.25 C -ATOM 644 CE1 TYR A 87 -6.812 -29.336 16.187 1.00 24.19 C -ATOM 645 CE2 TYR A 87 -8.197 -29.969 18.054 1.00 23.60 C -ATOM 646 CZ TYR A 87 -8.038 -29.393 16.820 1.00 32.01 C -ATOM 647 OH TYR A 87 -9.141 -28.823 16.238 1.00 38.33 O -ATOM 648 N GLU A 88 -4.612 -27.696 19.830 1.00 24.04 N -ATOM 649 CA GLU A 88 -5.228 -26.664 20.628 1.00 23.00 C -ATOM 650 C GLU A 88 -6.711 -26.782 20.555 1.00 28.26 C -ATOM 651 O GLU A 88 -7.325 -26.777 19.487 1.00 25.13 O -ATOM 652 CB GLU A 88 -4.745 -25.312 20.120 1.00 19.61 C -ATOM 653 CG GLU A 88 -5.293 -24.187 20.941 1.00 19.84 C -ATOM 654 CD GLU A 88 -4.733 -22.814 20.603 1.00 19.96 C -ATOM 655 OE1 GLU A 88 -3.531 -22.588 20.634 1.00 22.24 O -ATOM 656 OE2 GLU A 88 -5.525 -21.927 20.345 1.00 28.96 O -ATOM 657 N VAL A 89 -7.293 -26.892 21.731 1.00 20.98 N -ATOM 658 CA VAL A 89 -8.725 -27.043 21.863 1.00 19.79 C -ATOM 659 C VAL A 89 -9.368 -25.772 22.381 1.00 21.24 C -ATOM 660 O VAL A 89 -8.820 -25.141 23.301 1.00 25.75 O -ATOM 661 CB VAL A 89 -8.985 -28.240 22.811 1.00 21.18 C -ATOM 662 CG1 VAL A 89 -10.471 -28.313 23.162 1.00 20.32 C -ATOM 663 CG2 VAL A 89 -8.500 -29.529 22.147 1.00 23.18 C -ATOM 664 N GLY A 90 -10.544 -25.508 21.775 1.00 18.46 N -ATOM 665 CA GLY A 90 -11.503 -24.447 22.072 1.00 17.42 C -ATOM 666 C GLY A 90 -11.182 -23.088 21.423 1.00 16.29 C -ATOM 667 O GLY A 90 -10.017 -22.772 21.178 1.00 21.52 O -ATOM 668 N TYR A 91 -12.170 -22.231 21.137 1.00 15.81 N -ATOM 669 CA TYR A 91 -11.894 -20.937 20.537 1.00 16.90 C -ATOM 670 C TYR A 91 -11.119 -20.046 21.479 1.00 20.78 C -ATOM 671 O TYR A 91 -10.452 -19.147 20.996 1.00 20.06 O -ATOM 672 CB TYR A 91 -13.201 -20.266 20.121 1.00 14.86 C -ATOM 673 CG TYR A 91 -13.911 -19.353 21.115 1.00 20.42 C -ATOM 674 CD1 TYR A 91 -13.614 -18.019 21.136 1.00 17.43 C -ATOM 675 CD2 TYR A 91 -14.866 -19.845 21.983 1.00 21.36 C -ATOM 676 CE1 TYR A 91 -14.268 -17.195 22.018 1.00 21.64 C -ATOM 677 CE2 TYR A 91 -15.536 -19.021 22.871 1.00 17.13 C -ATOM 678 CZ TYR A 91 -15.218 -17.704 22.874 1.00 16.53 C -ATOM 679 OH TYR A 91 -15.829 -16.860 23.749 1.00 19.49 O -ATOM 680 N THR A 92 -11.188 -20.209 22.824 1.00 22.98 N -ATOM 681 CA THR A 92 -10.447 -19.354 23.771 1.00 20.64 C -ATOM 682 C THR A 92 -9.123 -20.013 24.167 1.00 19.15 C -ATOM 683 O THR A 92 -8.362 -19.403 24.901 1.00 20.90 O -ATOM 684 CB THR A 92 -11.280 -19.076 25.084 1.00 15.66 C -ATOM 685 OG1 THR A 92 -11.525 -20.348 25.670 1.00 19.23 O -ATOM 686 CG2 THR A 92 -12.624 -18.457 24.881 1.00 13.61 C -ATOM 687 N ASP A 93 -8.787 -21.221 23.667 1.00 18.00 N -ATOM 688 CA ASP A 93 -7.643 -22.059 24.031 1.00 18.24 C -ATOM 689 C ASP A 93 -7.851 -22.464 25.485 1.00 25.81 C -ATOM 690 O ASP A 93 -7.377 -21.806 26.430 1.00 22.47 O -ATOM 691 CB ASP A 93 -6.291 -21.317 23.863 1.00 17.88 C -ATOM 692 CG ASP A 93 -5.053 -22.146 24.152 1.00 20.65 C -ATOM 693 OD1 ASP A 93 -5.084 -23.364 24.383 1.00 25.25 O -ATOM 694 OD2 ASP A 93 -3.957 -21.594 24.164 1.00 20.38 O -ATOM 695 N LEU A 94 -8.639 -23.527 25.668 1.00 23.49 N -ATOM 696 CA LEU A 94 -9.100 -23.935 27.007 1.00 22.32 C -ATOM 697 C LEU A 94 -8.008 -24.604 27.802 1.00 20.94 C -ATOM 698 O LEU A 94 -7.974 -25.821 27.928 1.00 22.40 O -ATOM 699 CB LEU A 94 -10.273 -24.902 26.917 1.00 24.80 C -ATOM 700 CG LEU A 94 -11.581 -24.375 26.447 1.00 24.83 C -ATOM 701 CD1 LEU A 94 -12.516 -25.561 26.131 1.00 24.63 C -ATOM 702 CD2 LEU A 94 -12.146 -23.440 27.488 1.00 23.77 C -ATOM 703 N ASP A 95 -7.099 -23.826 28.366 1.00 18.41 N -ATOM 704 CA ASP A 95 -6.002 -24.365 29.143 1.00 18.77 C -ATOM 705 C ASP A 95 -6.284 -24.434 30.644 1.00 24.15 C -ATOM 706 O ASP A 95 -5.442 -24.795 31.454 1.00 20.30 O -ATOM 707 CB ASP A 95 -4.809 -23.519 28.974 1.00 17.45 C -ATOM 708 CG ASP A 95 -4.129 -23.674 27.640 1.00 24.99 C -ATOM 709 OD1 ASP A 95 -4.161 -24.728 27.031 1.00 21.65 O -ATOM 710 OD2 ASP A 95 -3.530 -22.716 27.180 1.00 22.05 O -ATOM 711 N ASP A 96 -7.492 -24.085 31.012 1.00 20.70 N -ATOM 712 CA ASP A 96 -7.930 -23.954 32.391 1.00 32.92 C -ATOM 713 C ASP A 96 -7.735 -25.224 33.224 1.00 36.10 C -ATOM 714 O ASP A 96 -7.517 -25.108 34.428 1.00 35.21 O -ATOM 715 CB ASP A 96 -9.409 -23.549 32.372 1.00 30.21 C -ATOM 716 CG ASP A 96 -9.729 -22.319 31.536 1.00 59.42 C -ATOM 717 OD1 ASP A 96 -9.849 -22.388 30.298 1.00 30.49 O -ATOM 718 OD2 ASP A 96 -9.838 -21.277 32.168 1.00 41.87 O -ATOM 719 N ARG A 97 -7.799 -26.443 32.668 1.00 26.01 N -ATOM 720 CA ARG A 97 -7.645 -27.688 33.412 1.00 19.44 C -ATOM 721 C ARG A 97 -6.329 -28.368 33.142 1.00 21.06 C -ATOM 722 O ARG A 97 -6.125 -29.539 33.499 1.00 27.98 O -ATOM 723 CB ARG A 97 -8.821 -28.616 33.064 1.00 19.30 C -ATOM 724 CG ARG A 97 -10.199 -28.149 33.511 1.00 23.19 C -ATOM 725 CD ARG A 97 -10.293 -28.108 35.047 1.00 30.26 C -ATOM 726 NE ARG A 97 -11.599 -27.602 35.423 1.00 30.05 N -ATOM 727 CZ ARG A 97 -11.841 -26.321 35.774 1.00 29.77 C -ATOM 728 NH1 ARG A 97 -10.861 -25.427 35.835 1.00 40.21 N -ATOM 729 NH2 ARG A 97 -13.097 -25.868 35.956 1.00 29.73 N -ATOM 730 N GLY A 98 -5.379 -27.669 32.518 1.00 22.17 N -ATOM 731 CA GLY A 98 -4.081 -28.250 32.166 1.00 19.78 C -ATOM 732 C GLY A 98 -3.587 -27.777 30.785 1.00 21.06 C -ATOM 733 O GLY A 98 -2.408 -27.445 30.590 1.00 26.48 O -ATOM 734 N GLY A 99 -4.531 -27.865 29.847 1.00 26.61 N -ATOM 735 CA GLY A 99 -4.325 -27.364 28.504 1.00 26.18 C -ATOM 736 C GLY A 99 -3.553 -28.261 27.572 1.00 24.45 C -ATOM 737 O GLY A 99 -3.059 -29.334 27.906 1.00 23.54 O -ATOM 738 N ASN A 100 -3.380 -27.785 26.358 1.00 25.90 N -ATOM 739 CA ASN A 100 -2.760 -28.567 25.281 1.00 19.24 C -ATOM 740 C ASN A 100 -1.272 -28.389 25.247 1.00 19.02 C -ATOM 741 O ASN A 100 -0.561 -29.090 24.545 1.00 22.88 O -ATOM 742 CB ASN A 100 -3.383 -28.115 23.946 1.00 23.30 C -ATOM 743 CG ASN A 100 -3.047 -26.667 23.616 1.00 22.39 C -ATOM 744 OD1 ASN A 100 -3.379 -25.727 24.342 1.00 24.51 O -ATOM 745 ND2 ASN A 100 -2.335 -26.428 22.526 1.00 21.36 N -ATOM 746 N ASP A 101 -0.712 -27.422 25.954 1.00 21.84 N -ATOM 747 CA ASP A 101 0.699 -27.106 25.874 1.00 16.59 C -ATOM 748 C ASP A 101 1.559 -28.190 26.422 1.00 26.25 C -ATOM 749 O ASP A 101 1.207 -28.795 27.422 1.00 24.73 O -ATOM 750 CB ASP A 101 0.994 -25.823 26.639 1.00 17.86 C -ATOM 751 CG ASP A 101 0.141 -24.622 26.220 1.00 18.10 C -ATOM 752 OD1 ASP A 101 -1.064 -24.668 25.870 1.00 23.14 O -ATOM 753 OD2 ASP A 101 0.747 -23.573 26.231 1.00 23.00 O -ATOM 754 N ILE A 102 2.666 -28.500 25.798 1.00 19.76 N -ATOM 755 CA ILE A 102 3.537 -29.509 26.333 1.00 21.70 C -ATOM 756 C ILE A 102 4.321 -28.842 27.477 1.00 22.28 C -ATOM 757 O ILE A 102 4.686 -27.665 27.349 1.00 20.29 O -ATOM 758 CB ILE A 102 4.443 -30.043 25.154 1.00 19.72 C -ATOM 759 CG1 ILE A 102 3.599 -30.939 24.230 1.00 25.08 C -ATOM 760 CG2 ILE A 102 5.665 -30.807 25.682 1.00 18.10 C -ATOM 761 CD1 ILE A 102 4.422 -31.467 23.005 1.00 22.45 C -ATOM 762 N PRO A 103 4.621 -29.544 28.600 1.00 24.84 N -ATOM 763 CA PRO A 103 5.227 -28.946 29.789 1.00 28.04 C -ATOM 764 C PRO A 103 6.720 -28.787 29.684 1.00 25.87 C -ATOM 765 O PRO A 103 7.484 -29.523 30.324 1.00 26.05 O -ATOM 766 CB PRO A 103 4.775 -29.866 30.923 1.00 21.68 C -ATOM 767 CG PRO A 103 4.679 -31.225 30.267 1.00 24.38 C -ATOM 768 CD PRO A 103 4.108 -30.899 28.902 1.00 21.16 C -ATOM 769 N TYR A 104 7.182 -27.838 28.863 1.00 18.31 N -ATOM 770 CA TYR A 104 8.608 -27.635 28.761 1.00 18.73 C -ATOM 771 C TYR A 104 9.073 -26.921 30.023 1.00 20.07 C -ATOM 772 O TYR A 104 8.361 -26.098 30.593 1.00 21.70 O -ATOM 773 CB TYR A 104 8.971 -26.789 27.514 1.00 20.72 C -ATOM 774 CG TYR A 104 8.556 -27.514 26.228 1.00 20.99 C -ATOM 775 CD1 TYR A 104 9.331 -28.550 25.758 1.00 23.25 C -ATOM 776 CD2 TYR A 104 7.414 -27.137 25.529 1.00 21.35 C -ATOM 777 CE1 TYR A 104 8.951 -29.198 24.590 1.00 23.05 C -ATOM 778 CE2 TYR A 104 7.042 -27.786 24.360 1.00 18.76 C -ATOM 779 CZ TYR A 104 7.830 -28.816 23.914 1.00 22.33 C -ATOM 780 OH TYR A 104 7.505 -29.528 22.797 1.00 26.62 O -ATOM 781 N LEU A 105 10.287 -27.267 30.428 1.00 19.68 N -ATOM 782 CA LEU A 105 10.892 -26.687 31.606 1.00 27.46 C -ATOM 783 C LEU A 105 11.398 -25.269 31.384 1.00 24.74 C -ATOM 784 O LEU A 105 11.335 -24.466 32.314 1.00 18.69 O -ATOM 785 CB LEU A 105 12.060 -27.619 32.094 1.00 24.81 C -ATOM 786 CG LEU A 105 12.850 -27.282 33.414 1.00 23.54 C -ATOM 787 CD1 LEU A 105 11.903 -27.421 34.607 1.00 22.08 C -ATOM 788 CD2 LEU A 105 14.036 -28.212 33.581 1.00 19.57 C -ATOM 789 N THR A 106 11.939 -24.878 30.204 1.00 22.99 N -ATOM 790 CA THR A 106 12.566 -23.563 30.052 1.00 22.98 C -ATOM 791 C THR A 106 11.922 -22.739 28.921 1.00 18.20 C -ATOM 792 O THR A 106 11.066 -23.276 28.199 1.00 21.22 O -ATOM 793 CB THR A 106 14.132 -23.718 29.810 1.00 29.35 C -ATOM 794 OG1 THR A 106 14.327 -24.208 28.473 1.00 25.92 O -ATOM 795 CG2 THR A 106 14.823 -24.635 30.873 1.00 19.42 C -ATOM 796 N GLY A 107 12.329 -21.461 28.785 1.00 17.26 N -ATOM 797 CA GLY A 107 11.894 -20.551 27.729 1.00 18.97 C -ATOM 798 C GLY A 107 10.440 -20.263 27.925 1.00 27.01 C -ATOM 799 O GLY A 107 9.838 -20.634 28.939 1.00 22.34 O -ATOM 800 N ASP A 108 9.898 -19.520 26.977 1.00 18.09 N -ATOM 801 CA ASP A 108 8.489 -19.175 26.967 1.00 14.02 C -ATOM 802 C ASP A 108 8.007 -18.619 28.318 1.00 16.56 C -ATOM 803 O ASP A 108 7.084 -19.135 28.971 1.00 19.46 O -ATOM 804 CB ASP A 108 7.652 -20.396 26.617 1.00 14.02 C -ATOM 805 CG ASP A 108 6.232 -20.071 26.186 1.00 20.04 C -ATOM 806 OD1 ASP A 108 5.930 -18.919 25.882 1.00 22.75 O -ATOM 807 OD2 ASP A 108 5.399 -20.983 26.091 1.00 21.20 O -ATOM 808 N GLU A 109 8.764 -17.583 28.705 1.00 18.15 N -ATOM 809 CA GLU A 109 8.495 -16.749 29.872 1.00 24.76 C -ATOM 810 C GLU A 109 8.816 -17.406 31.222 1.00 28.53 C -ATOM 811 O GLU A 109 8.360 -16.907 32.248 1.00 24.18 O -ATOM 812 CB GLU A 109 7.031 -16.306 29.903 1.00 23.74 C -ATOM 813 CG GLU A 109 6.609 -15.513 28.685 1.00 39.02 C -ATOM 814 CD GLU A 109 5.164 -15.091 28.776 1.00 35.83 C -ATOM 815 OE1 GLU A 109 4.307 -15.965 28.666 1.00 42.26 O -ATOM 816 OE2 GLU A 109 4.922 -13.901 28.984 1.00 50.54 O -ATOM 817 N ARG A 110 9.587 -18.495 31.296 1.00 23.57 N -ATOM 818 CA ARG A 110 10.058 -19.072 32.572 1.00 25.84 C -ATOM 819 C ARG A 110 10.919 -18.036 33.304 1.00 30.43 C -ATOM 820 O ARG A 110 10.672 -17.724 34.475 1.00 24.85 O -ATOM 821 CB ARG A 110 10.883 -20.353 32.319 1.00 21.39 C -ATOM 822 CG ARG A 110 11.404 -21.078 33.569 1.00 23.85 C -ATOM 823 CD ARG A 110 10.161 -21.588 34.342 1.00 24.89 C -ATOM 824 NE ARG A 110 9.647 -22.774 33.671 1.00 27.06 N -ATOM 825 CZ ARG A 110 8.375 -23.149 33.571 1.00 24.00 C -ATOM 826 NH1 ARG A 110 7.435 -22.413 34.118 1.00 34.29 N -ATOM 827 NH2 ARG A 110 8.022 -24.277 32.956 1.00 26.57 N -ATOM 828 N LEU A 111 11.915 -17.438 32.657 1.00 17.88 N -ATOM 829 CA LEU A 111 12.745 -16.429 33.264 1.00 18.66 C -ATOM 830 C LEU A 111 12.707 -15.080 32.576 1.00 19.35 C -ATOM 831 O LEU A 111 13.309 -14.108 33.051 1.00 18.67 O -ATOM 832 CB LEU A 111 14.157 -16.942 33.296 1.00 19.31 C -ATOM 833 CG LEU A 111 14.430 -18.083 34.253 1.00 24.75 C -ATOM 834 CD1 LEU A 111 15.824 -18.593 34.125 1.00 28.02 C -ATOM 835 CD2 LEU A 111 14.261 -17.553 35.646 1.00 33.78 C -ATOM 836 N THR A 112 12.007 -14.963 31.439 1.00 18.03 N -ATOM 837 CA THR A 112 11.980 -13.716 30.682 1.00 18.21 C -ATOM 838 C THR A 112 11.282 -12.671 31.542 1.00 16.40 C -ATOM 839 O THR A 112 10.238 -12.982 32.125 1.00 21.37 O -ATOM 840 CB THR A 112 11.196 -13.930 29.365 1.00 20.52 C -ATOM 841 OG1 THR A 112 11.651 -15.180 28.849 1.00 21.48 O -ATOM 842 CG2 THR A 112 11.362 -12.778 28.399 1.00 16.54 C -ATOM 843 N ALA A 113 11.761 -11.438 31.610 1.00 17.64 N -ATOM 844 CA ALA A 113 11.156 -10.417 32.442 1.00 22.16 C -ATOM 845 C ALA A 113 11.625 -9.054 31.967 1.00 23.20 C -ATOM 846 O ALA A 113 12.433 -8.975 31.031 1.00 21.50 O -ATOM 847 CB ALA A 113 11.606 -10.647 33.900 1.00 20.45 C -ATOM 848 N GLU A 114 11.168 -7.983 32.636 1.00 17.56 N -ATOM 849 CA GLU A 114 11.550 -6.643 32.300 1.00 17.62 C -ATOM 850 C GLU A 114 13.050 -6.545 32.268 1.00 20.21 C -ATOM 851 O GLU A 114 13.744 -7.079 33.127 1.00 19.38 O -ATOM 852 CB GLU A 114 10.943 -5.731 33.326 1.00 21.43 C -ATOM 853 CG GLU A 114 11.353 -4.286 33.067 1.00 31.92 C -ATOM 854 CD GLU A 114 10.679 -3.178 33.891 1.00 50.58 C -ATOM 855 OE1 GLU A 114 9.970 -3.484 34.845 1.00 58.25 O -ATOM 856 OE2 GLU A 114 10.863 -1.999 33.570 1.00 57.25 O -ATOM 857 N ASP A 115 13.595 -5.983 31.191 1.00 18.34 N -ATOM 858 CA ASP A 115 15.035 -5.858 30.963 1.00 18.30 C -ATOM 859 C ASP A 115 15.803 -7.156 30.977 1.00 14.16 C -ATOM 860 O ASP A 115 17.021 -7.232 31.237 1.00 18.02 O -ATOM 861 CB ASP A 115 15.700 -4.964 32.002 1.00 19.01 C -ATOM 862 CG ASP A 115 15.275 -3.526 32.012 1.00 25.40 C -ATOM 863 OD1 ASP A 115 14.861 -3.002 30.973 1.00 28.95 O -ATOM 864 OD2 ASP A 115 15.386 -2.918 33.069 1.00 32.28 O -ATOM 865 N ASN A 116 15.080 -8.231 30.694 1.00 16.08 N -ATOM 866 CA ASN A 116 15.715 -9.515 30.775 1.00 21.18 C -ATOM 867 C ASN A 116 15.183 -10.408 29.648 1.00 17.53 C -ATOM 868 O ASN A 116 14.329 -11.285 29.847 1.00 18.38 O -ATOM 869 CB ASN A 116 15.462 -10.131 32.189 1.00 13.57 C -ATOM 870 CG ASN A 116 16.452 -11.274 32.370 1.00 13.13 C -ATOM 871 OD1 ASN A 116 17.716 -11.114 32.335 1.00 22.25 O -ATOM 872 ND2 ASN A 116 15.861 -12.462 32.579 1.00 17.70 N -ATOM 873 N PRO A 117 15.676 -10.216 28.405 1.00 19.89 N -ATOM 874 CA PRO A 117 15.360 -11.102 27.297 1.00 22.27 C -ATOM 875 C PRO A 117 16.088 -12.442 27.412 1.00 18.54 C -ATOM 876 O PRO A 117 17.132 -12.521 28.078 1.00 18.89 O -ATOM 877 CB PRO A 117 15.760 -10.264 26.087 1.00 15.27 C -ATOM 878 CG PRO A 117 16.976 -9.504 26.572 1.00 17.83 C -ATOM 879 CD PRO A 117 16.553 -9.125 27.988 1.00 17.26 C -ATOM 880 N VAL A 118 15.596 -13.518 26.766 1.00 16.16 N -ATOM 881 CA VAL A 118 16.341 -14.777 26.664 1.00 16.43 C -ATOM 882 C VAL A 118 16.766 -14.959 25.175 1.00 25.34 C -ATOM 883 O VAL A 118 16.320 -14.206 24.289 1.00 19.32 O -ATOM 884 CB VAL A 118 15.473 -16.017 27.179 1.00 18.45 C -ATOM 885 CG1 VAL A 118 15.247 -15.671 28.696 1.00 15.26 C -ATOM 886 CG2 VAL A 118 14.085 -16.264 26.552 1.00 15.58 C -ATOM 887 N LEU A 119 17.618 -15.929 24.877 1.00 20.33 N -ATOM 888 CA LEU A 119 18.212 -16.171 23.561 1.00 20.99 C -ATOM 889 C LEU A 119 17.806 -17.484 22.914 1.00 20.18 C -ATOM 890 O LEU A 119 17.746 -18.515 23.600 1.00 19.36 O -ATOM 891 CB LEU A 119 19.702 -16.108 23.761 1.00 19.83 C -ATOM 892 CG LEU A 119 20.525 -16.192 22.531 1.00 29.38 C -ATOM 893 CD1 LEU A 119 20.499 -14.841 21.877 1.00 33.62 C -ATOM 894 CD2 LEU A 119 21.929 -16.539 22.872 1.00 28.54 C -ATOM 895 N LEU A 120 17.509 -17.596 21.616 1.00 16.23 N -ATOM 896 CA LEU A 120 17.189 -18.885 21.005 1.00 12.16 C -ATOM 897 C LEU A 120 17.994 -18.923 19.717 1.00 23.81 C -ATOM 898 O LEU A 120 17.999 -17.948 18.969 1.00 18.46 O -ATOM 899 CB LEU A 120 15.739 -19.008 20.630 1.00 14.54 C -ATOM 900 CG LEU A 120 15.309 -20.190 19.798 1.00 17.59 C -ATOM 901 CD1 LEU A 120 15.600 -21.483 20.543 1.00 20.38 C -ATOM 902 CD2 LEU A 120 13.811 -20.074 19.496 1.00 15.97 C -ATOM 903 N TYR A 121 18.739 -19.971 19.482 1.00 22.12 N -ATOM 904 CA TYR A 121 19.505 -20.129 18.261 1.00 23.52 C -ATOM 905 C TYR A 121 18.888 -21.304 17.518 1.00 22.86 C -ATOM 906 O TYR A 121 18.665 -22.334 18.165 1.00 23.27 O -ATOM 907 CB TYR A 121 20.961 -20.421 18.590 1.00 22.24 C -ATOM 908 CG TYR A 121 21.739 -20.937 17.382 1.00 25.99 C -ATOM 909 CD1 TYR A 121 22.117 -20.087 16.352 1.00 34.91 C -ATOM 910 CD2 TYR A 121 21.999 -22.288 17.324 1.00 26.29 C -ATOM 911 CE1 TYR A 121 22.758 -20.613 15.256 1.00 27.38 C -ATOM 912 CE2 TYR A 121 22.633 -22.826 16.234 1.00 35.27 C -ATOM 913 CZ TYR A 121 23.005 -21.983 15.214 1.00 36.17 C -ATOM 914 OH TYR A 121 23.631 -22.562 14.125 1.00 35.43 O -ATOM 915 N THR A 122 18.599 -21.227 16.193 1.00 22.81 N -ATOM 916 CA THR A 122 18.112 -22.375 15.451 1.00 19.32 C -ATOM 917 C THR A 122 18.914 -22.461 14.151 1.00 27.70 C -ATOM 918 O THR A 122 19.473 -21.465 13.656 1.00 21.98 O -ATOM 919 CB THR A 122 16.640 -22.248 15.110 1.00 21.37 C -ATOM 920 OG1 THR A 122 16.478 -20.913 14.669 1.00 27.26 O -ATOM 921 CG2 THR A 122 15.706 -22.489 16.285 1.00 29.49 C -ATOM 922 N TYR A 123 18.931 -23.678 13.643 1.00 26.58 N -ATOM 923 CA TYR A 123 19.626 -23.982 12.406 1.00 28.58 C -ATOM 924 C TYR A 123 19.029 -25.198 11.750 1.00 30.09 C -ATOM 925 O TYR A 123 18.779 -26.203 12.416 1.00 26.30 O -ATOM 926 CB TYR A 123 21.060 -24.251 12.713 1.00 29.46 C -ATOM 927 CG TYR A 123 21.859 -24.701 11.507 1.00 31.07 C -ATOM 928 CD1 TYR A 123 22.355 -23.720 10.683 1.00 39.10 C -ATOM 929 CD2 TYR A 123 22.061 -26.048 11.277 1.00 34.75 C -ATOM 930 CE1 TYR A 123 23.083 -24.079 9.583 1.00 35.87 C -ATOM 931 CE2 TYR A 123 22.787 -26.421 10.180 1.00 42.57 C -ATOM 932 CZ TYR A 123 23.284 -25.427 9.354 1.00 47.35 C -ATOM 933 OH TYR A 123 24.014 -25.777 8.240 1.00 53.04 O -ATOM 934 N SER A 124 18.827 -25.167 10.444 1.00 29.07 N -ATOM 935 CA SER A 124 18.380 -26.360 9.780 1.00 25.74 C -ATOM 936 C SER A 124 19.212 -26.528 8.512 1.00 32.52 C -ATOM 937 O SER A 124 19.737 -25.560 7.954 1.00 28.10 O -ATOM 938 CB SER A 124 16.959 -26.266 9.361 1.00 29.36 C -ATOM 939 OG SER A 124 16.102 -26.031 10.448 1.00 40.97 O -ATOM 940 N ALA A 125 19.358 -27.755 8.074 1.00 38.12 N -ATOM 941 CA ALA A 125 20.047 -28.066 6.845 1.00 28.40 C -ATOM 942 C ALA A 125 19.350 -29.333 6.392 1.00 30.58 C -ATOM 943 O ALA A 125 19.430 -30.369 7.065 1.00 39.26 O -ATOM 944 CB ALA A 125 21.487 -28.341 7.146 1.00 24.99 C -ATOM 945 N GLY A 126 18.578 -29.298 5.319 1.00 37.02 N -ATOM 946 CA GLY A 126 17.941 -30.499 4.836 1.00 31.57 C -ATOM 947 C GLY A 126 16.898 -31.059 5.780 1.00 47.32 C -ATOM 948 O GLY A 126 15.877 -30.451 6.108 1.00 45.65 O -ATOM 949 N ALA A 127 17.180 -32.278 6.195 1.00 33.24 N -ATOM 950 CA ALA A 127 16.275 -33.037 7.039 1.00 42.64 C -ATOM 951 C ALA A 127 16.458 -32.822 8.549 1.00 33.08 C -ATOM 952 O ALA A 127 15.702 -33.301 9.402 1.00 40.51 O -ATOM 953 CB ALA A 127 16.490 -34.498 6.705 1.00 35.42 C -ATOM 954 N PHE A 128 17.468 -32.083 8.902 1.00 27.81 N -ATOM 955 CA PHE A 128 17.848 -32.020 10.258 1.00 28.97 C -ATOM 956 C PHE A 128 17.701 -30.613 10.786 1.00 40.19 C -ATOM 957 O PHE A 128 17.975 -29.634 10.085 1.00 29.96 O -ATOM 958 CB PHE A 128 19.218 -32.562 10.176 1.00 27.26 C -ATOM 959 CG PHE A 128 20.062 -32.313 11.399 1.00 62.21 C -ATOM 960 CD1 PHE A 128 19.988 -33.205 12.457 1.00 68.83 C -ATOM 961 CD2 PHE A 128 20.908 -31.200 11.430 1.00 68.66 C -ATOM 962 CE1 PHE A 128 20.783 -32.970 13.564 1.00 68.63 C -ATOM 963 CE2 PHE A 128 21.699 -30.972 12.540 1.00 72.56 C -ATOM 964 CZ PHE A 128 21.630 -31.866 13.601 1.00 71.50 C -ATOM 965 N SER A 129 17.331 -30.540 12.060 1.00 32.05 N -ATOM 966 CA SER A 129 17.219 -29.262 12.751 1.00 30.97 C -ATOM 967 C SER A 129 17.830 -29.309 14.144 1.00 26.59 C -ATOM 968 O SER A 129 17.736 -30.344 14.808 1.00 27.36 O -ATOM 969 CB SER A 129 15.772 -28.871 12.897 1.00 27.55 C -ATOM 970 OG SER A 129 15.072 -28.729 11.673 1.00 47.00 O -ATOM 971 N VAL A 130 18.521 -28.261 14.560 1.00 28.17 N -ATOM 972 CA VAL A 130 19.019 -28.143 15.916 1.00 29.20 C -ATOM 973 C VAL A 130 18.641 -26.796 16.512 1.00 40.17 C -ATOM 974 O VAL A 130 18.516 -25.799 15.787 1.00 25.40 O -ATOM 975 CB VAL A 130 20.511 -28.239 16.012 1.00 24.69 C -ATOM 976 CG1 VAL A 130 20.801 -29.679 15.851 1.00 34.50 C -ATOM 977 CG2 VAL A 130 21.225 -27.340 15.037 1.00 27.14 C -ATOM 978 N ALA A 131 18.434 -26.730 17.829 1.00 24.58 N -ATOM 979 CA ALA A 131 18.111 -25.468 18.511 1.00 21.75 C -ATOM 980 C ALA A 131 18.877 -25.407 19.842 1.00 27.70 C -ATOM 981 O ALA A 131 19.246 -26.460 20.409 1.00 27.02 O -ATOM 982 CB ALA A 131 16.591 -25.405 18.742 1.00 16.82 C -ATOM 983 N ALA A 132 19.238 -24.228 20.323 1.00 24.98 N -ATOM 984 CA ALA A 132 19.932 -24.098 21.596 1.00 25.03 C -ATOM 985 C ALA A 132 19.448 -22.801 22.221 1.00 34.14 C -ATOM 986 O ALA A 132 19.250 -21.814 21.513 1.00 20.34 O -ATOM 987 CB ALA A 132 21.444 -24.029 21.375 1.00 23.74 C -ATOM 988 N SER A 133 19.188 -22.737 23.518 1.00 21.23 N -ATOM 989 CA SER A 133 18.664 -21.524 24.131 1.00 18.46 C -ATOM 990 C SER A 133 19.284 -21.285 25.516 1.00 24.03 C -ATOM 991 O SER A 133 19.802 -22.239 26.115 1.00 22.23 O -ATOM 992 CB SER A 133 17.176 -21.672 24.250 1.00 14.79 C -ATOM 993 OG SER A 133 16.814 -22.952 24.768 1.00 19.72 O -ATOM 994 N MET A 134 19.303 -20.077 26.055 1.00 22.25 N -ATOM 995 CA MET A 134 19.802 -19.845 27.405 1.00 21.58 C -ATOM 996 C MET A 134 19.357 -18.485 27.899 1.00 33.98 C -ATOM 997 O MET A 134 18.998 -17.634 27.066 1.00 19.01 O -ATOM 998 CB MET A 134 21.317 -19.910 27.405 1.00 18.41 C -ATOM 999 CG MET A 134 21.955 -18.746 26.654 1.00 25.36 C -ATOM 1000 SD MET A 134 23.758 -18.772 26.669 1.00 35.96 S -ATOM 1001 CE MET A 134 24.092 -18.494 28.385 1.00 37.35 C -ATOM 1002 N SER A 135 19.314 -18.261 29.212 1.00 18.02 N -ATOM 1003 CA SER A 135 19.041 -16.944 29.746 1.00 16.76 C -ATOM 1004 C SER A 135 20.400 -16.477 30.208 1.00 16.94 C -ATOM 1005 O SER A 135 21.361 -17.253 30.182 1.00 20.09 O -ATOM 1006 CB SER A 135 18.034 -17.017 30.907 1.00 20.02 C -ATOM 1007 OG SER A 135 18.468 -17.881 31.957 1.00 20.86 O -ATOM 1008 N ASP A 136 20.575 -15.243 30.638 1.00 16.31 N -ATOM 1009 CA ASP A 136 21.896 -14.789 30.953 1.00 16.45 C -ATOM 1010 C ASP A 136 22.306 -14.956 32.433 1.00 22.62 C -ATOM 1011 O ASP A 136 23.431 -14.549 32.746 1.00 22.11 O -ATOM 1012 CB ASP A 136 22.008 -13.322 30.545 1.00 18.28 C -ATOM 1013 CG ASP A 136 21.118 -12.306 31.234 1.00 26.65 C -ATOM 1014 OD1 ASP A 136 20.599 -12.470 32.340 1.00 23.99 O -ATOM 1015 OD2 ASP A 136 20.891 -11.237 30.680 1.00 20.64 O -ATOM 1016 N GLY A 137 21.469 -15.440 33.377 1.00 24.48 N -ATOM 1017 CA GLY A 137 21.879 -15.654 34.775 1.00 23.91 C -ATOM 1018 C GLY A 137 21.825 -14.434 35.682 1.00 26.85 C -ATOM 1019 O GLY A 137 22.169 -14.569 36.854 1.00 25.96 O -ATOM 1020 N LYS A 138 21.421 -13.236 35.265 1.00 17.66 N -ATOM 1021 CA LYS A 138 21.367 -12.055 36.104 1.00 18.17 C -ATOM 1022 C LYS A 138 20.022 -11.408 35.986 1.00 30.18 C -ATOM 1023 O LYS A 138 19.466 -11.268 34.880 1.00 21.24 O -ATOM 1024 CB LYS A 138 22.372 -10.986 35.727 1.00 16.38 C -ATOM 1025 CG LYS A 138 23.792 -11.496 35.715 1.00 23.82 C -ATOM 1026 CD LYS A 138 24.140 -11.859 37.123 1.00 27.64 C -ATOM 1027 CE LYS A 138 25.533 -12.379 37.245 1.00 44.82 C -ATOM 1028 NZ LYS A 138 26.012 -11.923 38.538 1.00 46.52 N -ATOM 1029 N VAL A 139 19.474 -10.987 37.108 1.00 18.51 N -ATOM 1030 CA VAL A 139 18.174 -10.375 37.172 1.00 17.22 C -ATOM 1031 C VAL A 139 18.172 -9.096 36.379 1.00 17.48 C -ATOM 1032 O VAL A 139 19.123 -8.335 36.540 1.00 19.74 O -ATOM 1033 CB VAL A 139 17.788 -10.042 38.624 1.00 22.74 C -ATOM 1034 CG1 VAL A 139 16.425 -9.380 38.662 1.00 20.52 C -ATOM 1035 CG2 VAL A 139 17.643 -11.326 39.407 1.00 19.66 C -ATOM 1036 N GLY A 140 17.163 -8.830 35.530 1.00 20.23 N -ATOM 1037 CA GLY A 140 17.145 -7.617 34.718 1.00 18.19 C -ATOM 1038 C GLY A 140 18.483 -7.470 33.993 1.00 15.63 C -ATOM 1039 O GLY A 140 19.102 -8.463 33.521 1.00 24.74 O -ATOM 1040 N GLU A 141 18.944 -6.222 34.012 1.00 20.17 N -ATOM 1041 CA GLU A 141 20.259 -5.874 33.503 1.00 22.48 C -ATOM 1042 C GLU A 141 21.126 -5.535 34.696 1.00 27.63 C -ATOM 1043 O GLU A 141 22.035 -4.706 34.600 1.00 24.54 O -ATOM 1044 CB GLU A 141 20.171 -4.664 32.566 1.00 23.70 C -ATOM 1045 CG GLU A 141 19.722 -5.124 31.158 1.00 28.35 C -ATOM 1046 CD GLU A 141 19.280 -4.042 30.161 1.00 35.14 C -ATOM 1047 OE1 GLU A 141 19.521 -2.849 30.346 1.00 29.71 O -ATOM 1048 OE2 GLU A 141 18.647 -4.398 29.172 1.00 26.87 O -ATOM 1049 N THR A 142 20.874 -6.205 35.825 1.00 24.87 N -ATOM 1050 CA THR A 142 21.602 -5.920 37.045 1.00 26.14 C -ATOM 1051 C THR A 142 22.691 -6.951 37.228 1.00 26.00 C -ATOM 1052 O THR A 142 22.900 -7.827 36.391 1.00 26.49 O -ATOM 1053 CB THR A 142 20.652 -5.937 38.303 1.00 22.12 C -ATOM 1054 OG1 THR A 142 20.367 -7.309 38.664 1.00 23.47 O -ATOM 1055 CG2 THR A 142 19.428 -5.058 38.051 1.00 22.33 C -ATOM 1056 N SER A 143 23.421 -6.876 38.341 1.00 25.41 N -ATOM 1057 CA SER A 143 24.368 -7.911 38.667 1.00 24.21 C -ATOM 1058 C SER A 143 23.801 -8.929 39.653 1.00 29.13 C -ATOM 1059 O SER A 143 24.544 -9.831 40.060 1.00 29.64 O -ATOM 1060 CB SER A 143 25.611 -7.272 39.238 1.00 30.36 C -ATOM 1061 OG SER A 143 26.293 -6.538 38.236 1.00 34.01 O -ATOM 1062 N GLU A 144 22.512 -8.883 40.023 1.00 25.37 N -ATOM 1063 CA GLU A 144 21.989 -9.861 40.964 1.00 23.57 C -ATOM 1064 C GLU A 144 21.841 -11.232 40.318 1.00 32.22 C -ATOM 1065 O GLU A 144 21.251 -11.321 39.236 1.00 26.96 O -ATOM 1066 CB GLU A 144 20.651 -9.323 41.474 1.00 30.98 C -ATOM 1067 CG GLU A 144 20.131 -10.086 42.704 1.00 55.43 C -ATOM 1068 CD GLU A 144 18.655 -9.917 43.094 1.00 68.87 C -ATOM 1069 OE1 GLU A 144 18.059 -8.877 42.796 1.00 57.51 O -ATOM 1070 OE2 GLU A 144 18.102 -10.844 43.704 1.00 82.75 O -ATOM 1071 N ASP A 145 22.347 -12.300 40.937 1.00 24.45 N -ATOM 1072 CA ASP A 145 22.274 -13.644 40.397 1.00 23.62 C -ATOM 1073 C ASP A 145 20.885 -14.160 40.292 1.00 31.40 C -ATOM 1074 O ASP A 145 20.085 -13.976 41.211 1.00 27.58 O -ATOM 1075 CB ASP A 145 23.020 -14.680 41.223 1.00 27.22 C -ATOM 1076 CG ASP A 145 24.550 -14.597 41.158 1.00 43.72 C -ATOM 1077 OD1 ASP A 145 25.098 -14.301 40.098 1.00 55.35 O -ATOM 1078 OD2 ASP A 145 25.207 -14.860 42.168 1.00 70.49 O -ATOM 1079 N ASP A 146 20.597 -14.825 39.175 1.00 23.66 N -ATOM 1080 CA ASP A 146 19.260 -15.333 38.926 1.00 18.81 C -ATOM 1081 C ASP A 146 19.452 -16.804 38.675 1.00 10.77 C -ATOM 1082 O ASP A 146 20.572 -17.306 38.563 1.00 22.23 O -ATOM 1083 CB ASP A 146 18.641 -14.610 37.668 1.00 21.54 C -ATOM 1084 CG ASP A 146 17.119 -14.645 37.537 1.00 31.62 C -ATOM 1085 OD1 ASP A 146 16.459 -15.328 38.315 1.00 34.30 O -ATOM 1086 OD2 ASP A 146 16.552 -13.985 36.671 1.00 26.76 O -ATOM 1087 N ALA A 147 18.352 -17.567 38.662 1.00 16.46 N -ATOM 1088 CA ALA A 147 18.384 -18.938 38.146 1.00 23.36 C -ATOM 1089 C ALA A 147 18.787 -18.819 36.658 1.00 25.54 C -ATOM 1090 O ALA A 147 18.528 -17.764 36.053 1.00 21.29 O -ATOM 1091 CB ALA A 147 17.004 -19.572 38.198 1.00 18.36 C -ATOM 1092 N GLN A 148 19.417 -19.794 36.046 1.00 20.67 N -ATOM 1093 CA GLN A 148 19.780 -19.644 34.654 1.00 21.13 C -ATOM 1094 C GLN A 148 19.249 -20.829 33.907 1.00 28.17 C -ATOM 1095 O GLN A 148 19.476 -21.942 34.380 1.00 24.20 O -ATOM 1096 CB GLN A 148 21.233 -19.585 34.578 1.00 21.13 C -ATOM 1097 CG GLN A 148 21.619 -19.436 33.129 1.00 25.80 C -ATOM 1098 CD GLN A 148 23.080 -19.135 32.982 1.00 34.87 C -ATOM 1099 OE1 GLN A 148 23.490 -18.474 32.035 1.00 38.87 O -ATOM 1100 NE2 GLN A 148 23.954 -19.503 33.912 1.00 47.02 N -ATOM 1101 N GLU A 149 18.555 -20.666 32.777 1.00 17.81 N -ATOM 1102 CA GLU A 149 18.010 -21.814 32.074 1.00 17.51 C -ATOM 1103 C GLU A 149 18.825 -22.040 30.814 1.00 20.63 C -ATOM 1104 O GLU A 149 19.517 -21.103 30.376 1.00 18.55 O -ATOM 1105 CB GLU A 149 16.573 -21.597 31.681 1.00 19.12 C -ATOM 1106 CG GLU A 149 16.351 -20.335 30.838 1.00 18.36 C -ATOM 1107 CD GLU A 149 14.915 -19.997 30.523 1.00 20.39 C -ATOM 1108 OE1 GLU A 149 14.001 -20.666 31.017 1.00 21.55 O -ATOM 1109 OE2 GLU A 149 14.713 -19.031 29.780 1.00 21.49 O -ATOM 1110 N MET A 150 18.765 -23.266 30.310 1.00 18.17 N -ATOM 1111 CA MET A 150 19.475 -23.652 29.080 1.00 20.14 C -ATOM 1112 C MET A 150 18.815 -24.867 28.505 1.00 28.58 C -ATOM 1113 O MET A 150 18.294 -25.697 29.249 1.00 27.20 O -ATOM 1114 CB MET A 150 20.897 -24.106 29.266 1.00 27.78 C -ATOM 1115 CG MET A 150 21.860 -23.060 29.696 1.00 64.16 C -ATOM 1116 SD MET A 150 23.096 -23.853 30.745 1.00 78.93 S -ATOM 1117 CE MET A 150 24.207 -22.466 30.751 1.00 70.32 C -ATOM 1118 N ALA A 151 18.839 -25.057 27.189 1.00 21.76 N -ATOM 1119 CA ALA A 151 18.277 -26.257 26.591 1.00 22.34 C -ATOM 1120 C ALA A 151 18.943 -26.437 25.223 1.00 22.98 C -ATOM 1121 O ALA A 151 19.548 -25.489 24.661 1.00 20.23 O -ATOM 1122 CB ALA A 151 16.789 -26.128 26.374 1.00 15.31 C -ATOM 1123 N VAL A 152 18.928 -27.676 24.774 1.00 21.53 N -ATOM 1124 CA VAL A 152 19.474 -28.033 23.471 1.00 23.07 C -ATOM 1125 C VAL A 152 18.471 -29.062 22.924 1.00 29.71 C -ATOM 1126 O VAL A 152 17.850 -29.818 23.689 1.00 27.21 O -ATOM 1127 CB VAL A 152 20.971 -28.628 23.592 1.00 25.13 C -ATOM 1128 CG1AVAL A 152 21.917 -27.575 24.154 0.53 28.48 C -ATOM 1129 CG1BVAL A 152 21.452 -29.025 22.205 0.26 24.20 C -ATOM 1130 CG1CVAL A 152 21.013 -29.912 24.410 0.21 26.31 C -ATOM 1131 CG2AVAL A 152 20.993 -29.863 24.477 0.53 23.43 C -ATOM 1132 CG2BVAL A 152 21.950 -27.615 24.169 0.26 29.11 C -ATOM 1133 CG2CVAL A 152 21.509 -28.858 22.190 0.21 24.18 C -ATOM 1134 N ALA A 153 18.188 -29.091 21.614 1.00 27.54 N -ATOM 1135 CA ALA A 153 17.282 -30.081 21.038 1.00 23.02 C -ATOM 1136 C ALA A 153 17.694 -30.354 19.578 1.00 25.00 C -ATOM 1137 O ALA A 153 18.306 -29.478 18.939 1.00 23.08 O -ATOM 1138 CB ALA A 153 15.849 -29.557 21.074 1.00 20.58 C -ATOM 1139 N ALA A 154 17.409 -31.528 19.045 1.00 25.22 N -ATOM 1140 CA ALA A 154 17.720 -31.854 17.658 1.00 31.60 C -ATOM 1141 C ALA A 154 16.571 -32.634 17.111 1.00 28.50 C -ATOM 1142 O ALA A 154 15.874 -33.314 17.860 1.00 28.42 O -ATOM 1143 CB ALA A 154 18.932 -32.711 17.543 1.00 24.29 C -ATOM 1144 N ALA A 155 16.262 -32.535 15.825 1.00 26.24 N -ATOM 1145 CA ALA A 155 15.174 -33.295 15.245 1.00 31.59 C -ATOM 1146 C ALA A 155 15.619 -33.740 13.846 1.00 32.78 C -ATOM 1147 O ALA A 155 16.532 -33.181 13.226 1.00 27.08 O -ATOM 1148 CB ALA A 155 13.908 -32.446 15.078 1.00 29.48 C -ATOM 1149 N TYR A 156 14.961 -34.772 13.379 1.00 27.28 N -ATOM 1150 CA TYR A 156 15.207 -35.330 12.082 1.00 27.65 C -ATOM 1151 C TYR A 156 13.878 -35.745 11.455 1.00 25.30 C -ATOM 1152 O TYR A 156 13.049 -36.464 12.029 1.00 31.37 O -ATOM 1153 CB TYR A 156 16.168 -36.499 12.279 1.00 40.64 C -ATOM 1154 CG TYR A 156 16.505 -37.195 10.962 1.00 72.25 C -ATOM 1155 CD1 TYR A 156 17.270 -36.535 10.007 1.00 68.07 C -ATOM 1156 CD2 TYR A 156 15.995 -38.472 10.714 1.00 78.75 C -ATOM 1157 CE1 TYR A 156 17.511 -37.161 8.799 1.00 70.03 C -ATOM 1158 CE2 TYR A 156 16.239 -39.101 9.507 1.00 76.52 C -ATOM 1159 CZ TYR A 156 16.995 -38.430 8.559 1.00 81.42 C -ATOM 1160 OH TYR A 156 17.234 -39.034 7.335 1.00 98.25 O -ATOM 1161 N THR A 157 13.640 -35.245 10.249 1.00 33.54 N -ATOM 1162 CA THR A 157 12.446 -35.609 9.529 1.00 41.02 C -ATOM 1163 C THR A 157 12.781 -36.673 8.478 1.00 45.31 C -ATOM 1164 O THR A 157 13.782 -36.556 7.773 1.00 47.36 O -ATOM 1165 CB THR A 157 11.885 -34.354 8.890 1.00 31.49 C -ATOM 1166 OG1 THR A 157 11.816 -33.382 9.932 1.00 47.00 O -ATOM 1167 CG2 THR A 157 10.503 -34.583 8.279 1.00 34.86 C -ATOM 1168 N PHE A 158 12.016 -37.750 8.382 1.00 40.52 N -ATOM 1169 CA PHE A 158 12.155 -38.795 7.393 1.00 46.68 C -ATOM 1170 C PHE A 158 10.739 -39.174 7.005 1.00 44.70 C -ATOM 1171 O PHE A 158 9.926 -39.803 7.693 1.00 50.08 O -ATOM 1172 CB PHE A 158 12.915 -40.006 7.961 1.00 40.11 C -ATOM 1173 CG PHE A 158 12.415 -40.654 9.250 1.00 60.39 C -ATOM 1174 CD1 PHE A 158 12.675 -40.063 10.478 1.00 73.87 C -ATOM 1175 CD2 PHE A 158 11.701 -41.847 9.191 1.00 75.24 C -ATOM 1176 CE1 PHE A 158 12.219 -40.663 11.632 1.00 73.60 C -ATOM 1177 CE2 PHE A 158 11.249 -42.442 10.357 1.00 79.76 C -ATOM 1178 CZ PHE A 158 11.509 -41.848 11.575 1.00 79.46 C -ATOM 1179 N GLY A 159 10.399 -38.592 5.878 1.00 54.47 N -ATOM 1180 CA GLY A 159 9.112 -38.851 5.291 1.00 53.05 C -ATOM 1181 C GLY A 159 8.071 -38.135 6.113 1.00 50.28 C -ATOM 1182 O GLY A 159 8.189 -36.924 6.359 1.00 60.39 O -ATOM 1183 N ASN A 160 7.122 -38.958 6.579 1.00 40.08 N -ATOM 1184 CA ASN A 160 5.983 -38.481 7.367 1.00 58.74 C -ATOM 1185 C ASN A 160 6.321 -38.149 8.812 1.00 49.02 C -ATOM 1186 O ASN A 160 5.490 -37.547 9.498 1.00 47.25 O -ATOM 1187 CB ASN A 160 4.845 -39.503 7.494 1.00 63.82 C -ATOM 1188 CG ASN A 160 4.460 -40.322 6.266 1.00 89.40 C -ATOM 1189 OD1 ASN A 160 5.283 -41.093 5.758 1.00107.52 O -ATOM 1190 ND2 ASN A 160 3.234 -40.234 5.751 1.00 92.23 N -ATOM 1191 N TYR A 161 7.518 -38.572 9.221 1.00 38.38 N -ATOM 1192 CA TYR A 161 7.993 -38.571 10.582 1.00 39.40 C -ATOM 1193 C TYR A 161 9.020 -37.553 10.920 1.00 45.36 C -ATOM 1194 O TYR A 161 9.923 -37.343 10.126 1.00 41.06 O -ATOM 1195 CB TYR A 161 8.619 -39.886 10.939 1.00 34.37 C -ATOM 1196 CG TYR A 161 7.655 -40.974 10.566 1.00 57.59 C -ATOM 1197 CD1 TYR A 161 6.653 -41.311 11.450 1.00 69.71 C -ATOM 1198 CD2 TYR A 161 7.725 -41.562 9.317 1.00 70.14 C -ATOM 1199 CE1 TYR A 161 5.689 -42.237 11.087 1.00 73.90 C -ATOM 1200 CE2 TYR A 161 6.765 -42.487 8.947 1.00 73.04 C -ATOM 1201 CZ TYR A 161 5.750 -42.816 9.836 1.00 78.64 C -ATOM 1202 OH TYR A 161 4.758 -43.712 9.471 1.00 85.47 O -ATOM 1203 N THR A 162 8.891 -36.915 12.069 1.00 30.45 N -ATOM 1204 CA THR A 162 9.994 -36.168 12.600 1.00 27.25 C -ATOM 1205 C THR A 162 10.140 -36.784 13.950 1.00 35.32 C -ATOM 1206 O THR A 162 9.140 -37.069 14.615 1.00 33.92 O -ATOM 1207 CB THR A 162 9.703 -34.725 12.782 1.00 31.07 C -ATOM 1208 OG1 THR A 162 9.394 -34.238 11.483 1.00 39.71 O -ATOM 1209 CG2 THR A 162 10.889 -33.987 13.414 1.00 29.14 C -ATOM 1210 N VAL A 163 11.356 -37.105 14.293 1.00 27.12 N -ATOM 1211 CA VAL A 163 11.576 -37.553 15.642 1.00 37.49 C -ATOM 1212 C VAL A 163 12.619 -36.613 16.222 1.00 30.21 C -ATOM 1213 O VAL A 163 13.349 -35.952 15.479 1.00 33.78 O -ATOM 1214 CB VAL A 163 12.069 -39.057 15.742 1.00 34.36 C -ATOM 1215 CG1 VAL A 163 10.966 -39.939 15.165 1.00 32.38 C -ATOM 1216 CG2 VAL A 163 13.420 -39.271 15.075 1.00 43.54 C -ATOM 1217 N GLY A 164 12.688 -36.440 17.536 1.00 28.78 N -ATOM 1218 CA GLY A 164 13.703 -35.572 18.098 1.00 30.23 C -ATOM 1219 C GLY A 164 13.877 -35.769 19.601 1.00 28.31 C -ATOM 1220 O GLY A 164 13.120 -36.518 20.239 1.00 28.35 O -ATOM 1221 N LEU A 165 14.870 -35.075 20.147 1.00 24.05 N -ATOM 1222 CA LEU A 165 15.090 -35.081 21.571 1.00 31.20 C -ATOM 1223 C LEU A 165 15.630 -33.765 22.024 1.00 23.08 C -ATOM 1224 O LEU A 165 16.230 -33.001 21.279 1.00 27.04 O -ATOM 1225 CB LEU A 165 16.049 -36.185 21.995 1.00 40.23 C -ATOM 1226 CG LEU A 165 17.491 -36.359 21.615 1.00 55.61 C -ATOM 1227 CD1 LEU A 165 18.360 -36.288 22.871 1.00 64.27 C -ATOM 1228 CD2 LEU A 165 17.674 -37.743 20.975 1.00 58.44 C -ATOM 1229 N GLY A 166 15.339 -33.481 23.275 1.00 28.71 N -ATOM 1230 CA GLY A 166 15.723 -32.228 23.857 1.00 24.37 C -ATOM 1231 C GLY A 166 16.128 -32.454 25.298 1.00 22.71 C -ATOM 1232 O GLY A 166 15.752 -33.451 25.916 1.00 23.22 O -ATOM 1233 N TYR A 167 16.924 -31.547 25.782 1.00 22.54 N -ATOM 1234 CA TYR A 167 17.385 -31.601 27.114 1.00 21.68 C -ATOM 1235 C TYR A 167 17.386 -30.166 27.552 1.00 22.97 C -ATOM 1236 O TYR A 167 18.019 -29.272 26.994 1.00 25.70 O -ATOM 1237 CB TYR A 167 18.742 -32.178 27.097 1.00 19.60 C -ATOM 1238 CG TYR A 167 19.294 -32.136 28.482 1.00 30.51 C -ATOM 1239 CD1 TYR A 167 18.831 -33.005 29.458 1.00 31.48 C -ATOM 1240 CD2 TYR A 167 20.232 -31.163 28.747 1.00 35.86 C -ATOM 1241 CE1 TYR A 167 19.337 -32.873 30.737 1.00 34.71 C -ATOM 1242 CE2 TYR A 167 20.735 -31.024 30.022 1.00 45.09 C -ATOM 1243 CZ TYR A 167 20.279 -31.881 31.001 1.00 45.63 C -ATOM 1244 OH TYR A 167 20.781 -31.711 32.274 1.00 43.91 O -ATOM 1245 N GLU A 168 16.761 -30.020 28.698 1.00 25.32 N -ATOM 1246 CA GLU A 168 16.579 -28.730 29.323 1.00 22.85 C -ATOM 1247 C GLU A 168 17.031 -28.704 30.781 1.00 23.46 C -ATOM 1248 O GLU A 168 16.833 -29.685 31.510 1.00 21.97 O -ATOM 1249 CB GLU A 168 15.129 -28.374 29.303 1.00 23.96 C -ATOM 1250 CG GLU A 168 14.336 -28.524 28.005 1.00 18.08 C -ATOM 1251 CD GLU A 168 12.978 -27.879 28.137 1.00 17.37 C -ATOM 1252 OE1 GLU A 168 12.883 -26.660 28.050 1.00 19.97 O -ATOM 1253 OE2 GLU A 168 11.995 -28.566 28.325 1.00 21.50 O -ATOM 1254 N LYS A 169 17.600 -27.609 31.238 1.00 21.91 N -ATOM 1255 CA LYS A 169 17.934 -27.489 32.645 1.00 26.98 C -ATOM 1256 C LYS A 169 17.850 -26.074 33.211 1.00 33.90 C -ATOM 1257 O LYS A 169 17.944 -25.073 32.479 1.00 21.78 O -ATOM 1258 CB LYS A 169 19.311 -28.049 32.861 1.00 22.39 C -ATOM 1259 CG LYS A 169 20.349 -27.286 32.129 1.00 33.73 C -ATOM 1260 CD LYS A 169 21.591 -27.849 32.707 1.00 55.00 C -ATOM 1261 CE LYS A 169 22.497 -26.654 32.902 1.00 70.05 C -ATOM 1262 NZ LYS A 169 23.579 -27.016 33.806 1.00 76.45 N -ATOM 1263 N ILE A 170 17.570 -25.964 34.531 1.00 24.31 N -ATOM 1264 CA ILE A 170 17.564 -24.681 35.251 1.00 26.64 C -ATOM 1265 C ILE A 170 18.554 -24.824 36.423 1.00 22.64 C -ATOM 1266 O ILE A 170 18.462 -25.750 37.218 1.00 26.39 O -ATOM 1267 CB ILE A 170 16.144 -24.293 35.810 1.00 22.23 C -ATOM 1268 CG1 ILE A 170 15.068 -24.222 34.712 1.00 18.13 C -ATOM 1269 CG2 ILE A 170 16.296 -22.936 36.512 1.00 20.59 C -ATOM 1270 CD1 ILE A 170 13.666 -23.890 35.214 1.00 22.57 C -ATOM 1271 N ASP A 171 19.579 -24.004 36.473 1.00 21.42 N -ATOM 1272 CA ASP A 171 20.512 -23.901 37.562 1.00 22.65 C -ATOM 1273 C ASP A 171 20.069 -22.845 38.533 1.00 24.81 C -ATOM 1274 O ASP A 171 19.879 -21.676 38.196 1.00 25.52 O -ATOM 1275 CB ASP A 171 21.876 -23.496 37.110 1.00 24.09 C -ATOM 1276 CG ASP A 171 22.500 -24.534 36.202 1.00 37.12 C -ATOM 1277 OD1 ASP A 171 22.150 -25.716 36.302 1.00 39.08 O -ATOM 1278 OD2 ASP A 171 23.325 -24.134 35.385 1.00 63.64 O -ATOM 1279 N SER A 172 19.937 -23.309 39.769 1.00 28.50 N -ATOM 1280 CA SER A 172 19.500 -22.508 40.890 1.00 29.34 C -ATOM 1281 C SER A 172 20.603 -21.582 41.329 1.00 19.80 C -ATOM 1282 O SER A 172 21.745 -22.025 41.398 1.00 27.09 O -ATOM 1283 CB SER A 172 19.152 -23.383 42.069 1.00 25.55 C -ATOM 1284 OG SER A 172 18.727 -22.499 43.089 1.00 28.00 O -ATOM 1285 N PRO A 173 20.365 -20.329 41.698 1.00 23.04 N -ATOM 1286 CA PRO A 173 21.386 -19.495 42.291 1.00 24.44 C -ATOM 1287 C PRO A 173 21.652 -19.986 43.713 1.00 46.59 C -ATOM 1288 O PRO A 173 22.743 -19.708 44.184 1.00 45.87 O -ATOM 1289 CB PRO A 173 20.825 -18.111 42.244 1.00 21.93 C -ATOM 1290 CG PRO A 173 19.367 -18.345 42.486 1.00 24.05 C -ATOM 1291 CD PRO A 173 19.060 -19.699 41.802 1.00 23.65 C -ATOM 1292 N ASP A 174 20.755 -20.703 44.425 1.00 32.74 N -ATOM 1293 CA ASP A 174 21.015 -21.137 45.794 1.00 29.56 C -ATOM 1294 C ASP A 174 20.241 -22.413 46.005 1.00 19.81 C -ATOM 1295 O ASP A 174 19.009 -22.376 46.189 1.00 27.36 O -ATOM 1296 CB ASP A 174 20.540 -20.070 46.777 1.00 37.96 C -ATOM 1297 CG ASP A 174 20.907 -20.292 48.261 1.00 44.06 C -ATOM 1298 OD1 ASP A 174 21.200 -21.404 48.694 1.00 35.40 O -ATOM 1299 OD2 ASP A 174 20.893 -19.320 49.006 1.00 47.06 O -ATOM 1300 N THR A 175 20.975 -23.537 46.006 1.00 25.91 N -ATOM 1301 CA THR A 175 20.332 -24.837 46.136 1.00 31.18 C -ATOM 1302 C THR A 175 19.824 -25.196 47.551 1.00 37.44 C -ATOM 1303 O THR A 175 19.134 -26.220 47.700 1.00 34.89 O -ATOM 1304 CB THR A 175 21.284 -25.941 45.576 1.00 35.52 C -ATOM 1305 OG1 THR A 175 22.537 -25.807 46.225 1.00 41.72 O -ATOM 1306 CG2 THR A 175 21.422 -25.836 44.040 1.00 30.09 C -ATOM 1307 N ALA A 176 20.096 -24.349 48.577 1.00 36.77 N -ATOM 1308 CA ALA A 176 19.430 -24.459 49.880 1.00 34.55 C -ATOM 1309 C ALA A 176 18.005 -23.977 49.703 1.00 34.09 C -ATOM 1310 O ALA A 176 17.077 -24.499 50.335 1.00 32.18 O -ATOM 1311 CB ALA A 176 20.016 -23.557 50.947 1.00 29.40 C -ATOM 1312 N LEU A 177 17.824 -22.983 48.808 1.00 25.68 N -ATOM 1313 CA LEU A 177 16.506 -22.431 48.562 1.00 24.25 C -ATOM 1314 C LEU A 177 15.700 -23.029 47.398 1.00 30.49 C -ATOM 1315 O LEU A 177 14.464 -23.081 47.479 1.00 25.58 O -ATOM 1316 CB LEU A 177 16.683 -20.949 48.375 1.00 34.03 C -ATOM 1317 CG LEU A 177 17.151 -20.199 49.612 1.00 41.02 C -ATOM 1318 CD1 LEU A 177 17.335 -18.758 49.257 1.00 40.73 C -ATOM 1319 CD2 LEU A 177 16.116 -20.270 50.711 1.00 41.14 C -ATOM 1320 N MET A 178 16.328 -23.506 46.315 1.00 27.88 N -ATOM 1321 CA MET A 178 15.605 -24.068 45.157 1.00 24.64 C -ATOM 1322 C MET A 178 16.543 -25.061 44.535 1.00 15.20 C -ATOM 1323 O MET A 178 17.697 -24.725 44.299 1.00 22.04 O -ATOM 1324 CB MET A 178 15.272 -22.965 44.134 1.00 24.97 C -ATOM 1325 CG MET A 178 14.350 -23.526 43.050 1.00 37.40 C -ATOM 1326 SD MET A 178 14.025 -22.325 41.726 1.00 34.16 S -ATOM 1327 CE MET A 178 15.624 -22.293 40.939 1.00 28.69 C -ATOM 1328 N ALA A 179 16.135 -26.306 44.380 1.00 18.97 N -ATOM 1329 CA ALA A 179 16.960 -27.343 43.800 1.00 21.25 C -ATOM 1330 C ALA A 179 17.175 -27.052 42.312 1.00 32.90 C -ATOM 1331 O ALA A 179 16.345 -26.407 41.660 1.00 23.82 O -ATOM 1332 CB ALA A 179 16.276 -28.705 43.867 1.00 19.86 C -ATOM 1333 N ASP A 180 18.275 -27.497 41.758 1.00 25.51 N -ATOM 1334 CA ASP A 180 18.459 -27.512 40.305 1.00 29.77 C -ATOM 1335 C ASP A 180 17.437 -28.418 39.632 1.00 35.87 C -ATOM 1336 O ASP A 180 17.017 -29.425 40.230 1.00 25.57 O -ATOM 1337 CB ASP A 180 19.804 -28.048 39.948 1.00 22.82 C -ATOM 1338 CG ASP A 180 20.966 -27.176 40.326 1.00 19.28 C -ATOM 1339 OD1 ASP A 180 20.783 -25.984 40.534 1.00 24.24 O -ATOM 1340 OD2 ASP A 180 22.072 -27.706 40.385 1.00 34.46 O -ATOM 1341 N MET A 181 17.040 -28.135 38.384 1.00 21.42 N -ATOM 1342 CA MET A 181 16.020 -28.935 37.732 1.00 19.55 C -ATOM 1343 C MET A 181 16.540 -29.368 36.348 1.00 26.26 C -ATOM 1344 O MET A 181 17.428 -28.705 35.790 1.00 23.03 O -ATOM 1345 CB MET A 181 14.741 -28.115 37.558 1.00 20.30 C -ATOM 1346 CG MET A 181 14.208 -27.429 38.832 1.00 22.93 C -ATOM 1347 SD MET A 181 12.538 -26.784 38.747 1.00 27.32 S -ATOM 1348 CE MET A 181 13.039 -25.172 39.188 1.00 22.23 C -ATOM 1349 N GLU A 182 16.055 -30.464 35.782 1.00 23.25 N -ATOM 1350 CA GLU A 182 16.419 -30.849 34.433 1.00 28.22 C -ATOM 1351 C GLU A 182 15.314 -31.697 33.888 1.00 22.99 C -ATOM 1352 O GLU A 182 14.491 -32.218 34.658 1.00 23.60 O -ATOM 1353 CB GLU A 182 17.693 -31.633 34.372 1.00 27.70 C -ATOM 1354 CG GLU A 182 17.653 -32.917 35.150 1.00 39.91 C -ATOM 1355 CD GLU A 182 18.798 -33.865 34.827 1.00 49.50 C -ATOM 1356 OE1 GLU A 182 19.958 -33.436 34.775 1.00 46.27 O -ATOM 1357 OE2 GLU A 182 18.494 -35.043 34.614 1.00 81.45 O -ATOM 1358 N GLN A 183 15.218 -31.801 32.555 1.00 23.57 N -ATOM 1359 CA GLN A 183 14.186 -32.607 31.917 1.00 20.27 C -ATOM 1360 C GLN A 183 14.734 -33.027 30.559 1.00 24.71 C -ATOM 1361 O GLN A 183 15.397 -32.226 29.892 1.00 25.60 O -ATOM 1362 CB GLN A 183 12.923 -31.774 31.752 1.00 21.67 C -ATOM 1363 CG GLN A 183 11.739 -32.520 31.215 1.00 22.57 C -ATOM 1364 CD GLN A 183 10.536 -31.621 31.271 1.00 34.59 C -ATOM 1365 OE1 GLN A 183 10.031 -31.397 32.344 1.00 33.27 O -ATOM 1366 NE2 GLN A 183 9.947 -31.040 30.243 1.00 26.73 N -ATOM 1367 N LEU A 184 14.506 -34.276 30.212 1.00 25.90 N -ATOM 1368 CA LEU A 184 14.900 -34.830 28.935 1.00 25.47 C -ATOM 1369 C LEU A 184 13.623 -35.127 28.194 1.00 30.93 C -ATOM 1370 O LEU A 184 12.692 -35.640 28.813 1.00 29.59 O -ATOM 1371 CB LEU A 184 15.656 -36.119 29.106 1.00 30.36 C -ATOM 1372 CG LEU A 184 16.019 -36.860 27.796 1.00 53.58 C -ATOM 1373 CD1 LEU A 184 17.325 -36.325 27.169 1.00 41.36 C -ATOM 1374 CD2 LEU A 184 16.137 -38.333 28.120 1.00 61.50 C -ATOM 1375 N GLU A 185 13.503 -34.832 26.895 1.00 24.93 N -ATOM 1376 CA GLU A 185 12.284 -35.106 26.139 1.00 21.56 C -ATOM 1377 C GLU A 185 12.589 -35.929 24.871 1.00 20.96 C -ATOM 1378 O GLU A 185 13.661 -35.744 24.270 1.00 25.62 O -ATOM 1379 CB GLU A 185 11.596 -33.838 25.621 1.00 28.40 C -ATOM 1380 CG GLU A 185 11.036 -32.816 26.599 1.00 33.30 C -ATOM 1381 CD GLU A 185 11.903 -31.609 26.892 1.00 31.54 C -ATOM 1382 OE1 GLU A 185 12.775 -31.231 26.123 1.00 27.29 O -ATOM 1383 OE2 GLU A 185 11.691 -31.016 27.928 1.00 25.85 O -ATOM 1384 N LEU A 186 11.646 -36.789 24.489 1.00 24.15 N -ATOM 1385 CA LEU A 186 11.653 -37.500 23.212 1.00 28.00 C -ATOM 1386 C LEU A 186 10.327 -37.093 22.629 1.00 28.26 C -ATOM 1387 O LEU A 186 9.305 -37.108 23.330 1.00 29.09 O -ATOM 1388 CB LEU A 186 11.600 -39.020 23.305 1.00 30.48 C -ATOM 1389 CG LEU A 186 12.737 -39.599 24.072 1.00 49.76 C -ATOM 1390 CD1 LEU A 186 12.437 -41.058 24.322 1.00 56.71 C -ATOM 1391 CD2 LEU A 186 14.029 -39.335 23.332 1.00 41.46 C -ATOM 1392 N ALA A 187 10.310 -36.701 21.364 1.00 23.92 N -ATOM 1393 CA ALA A 187 9.078 -36.291 20.743 1.00 23.34 C -ATOM 1394 C ALA A 187 9.031 -36.945 19.363 1.00 27.75 C -ATOM 1395 O ALA A 187 10.069 -37.214 18.757 1.00 26.70 O -ATOM 1396 CB ALA A 187 9.074 -34.777 20.610 1.00 24.93 C -ATOM 1397 N ALA A 188 7.853 -37.216 18.873 1.00 25.88 N -ATOM 1398 CA ALA A 188 7.663 -37.789 17.563 1.00 34.01 C -ATOM 1399 C ALA A 188 6.512 -37.031 16.935 1.00 33.31 C -ATOM 1400 O ALA A 188 5.540 -36.744 17.644 1.00 29.55 O -ATOM 1401 CB ALA A 188 7.278 -39.264 17.674 1.00 26.52 C -ATOM 1402 N ILE A 189 6.550 -36.671 15.649 1.00 36.39 N -ATOM 1403 CA ILE A 189 5.415 -36.037 14.968 1.00 27.67 C -ATOM 1404 C ILE A 189 5.231 -36.770 13.625 1.00 37.92 C -ATOM 1405 O ILE A 189 6.221 -37.089 12.968 1.00 33.44 O -ATOM 1406 CB ILE A 189 5.690 -34.555 14.703 1.00 29.72 C -ATOM 1407 CG1 ILE A 189 5.971 -33.831 15.991 1.00 39.00 C -ATOM 1408 CG2 ILE A 189 4.471 -33.934 14.052 1.00 33.27 C -ATOM 1409 CD1 ILE A 189 7.077 -32.793 15.839 1.00 38.17 C -ATOM 1410 N ALA A 190 4.005 -37.054 13.215 1.00 34.42 N -ATOM 1411 CA ALA A 190 3.697 -37.834 12.044 1.00 33.15 C -ATOM 1412 C ALA A 190 2.509 -37.223 11.388 1.00 43.94 C -ATOM 1413 O ALA A 190 1.528 -36.880 12.068 1.00 36.50 O -ATOM 1414 CB ALA A 190 3.273 -39.248 12.368 1.00 29.97 C -ATOM 1415 N LYS A 191 2.600 -37.037 10.076 1.00 49.78 N -ATOM 1416 CA LYS A 191 1.414 -36.648 9.317 1.00 48.56 C -ATOM 1417 C LYS A 191 1.095 -37.790 8.400 1.00 51.68 C -ATOM 1418 O LYS A 191 1.979 -38.318 7.727 1.00 65.27 O -ATOM 1419 CB LYS A 191 1.596 -35.413 8.439 1.00 49.42 C -ATOM 1420 CG LYS A 191 2.988 -35.255 7.842 1.00 75.96 C -ATOM 1421 CD LYS A 191 3.450 -33.831 8.138 1.00 86.39 C -ATOM 1422 CE LYS A 191 3.796 -33.646 9.617 1.00 88.43 C -ATOM 1423 NZ LYS A 191 3.690 -32.249 10.002 1.00 91.69 N -ATOM 1424 N PHE A 192 -0.144 -38.241 8.423 1.00 57.59 N -ATOM 1425 CA PHE A 192 -0.631 -39.312 7.574 1.00 49.63 C -ATOM 1426 C PHE A 192 -1.764 -38.691 6.778 1.00 55.22 C -ATOM 1427 O PHE A 192 -2.963 -38.943 6.982 1.00 60.13 O -ATOM 1428 CB PHE A 192 -1.160 -40.470 8.406 1.00 52.90 C -ATOM 1429 CG PHE A 192 -0.106 -41.110 9.279 1.00 55.44 C -ATOM 1430 CD1 PHE A 192 1.159 -41.341 8.773 1.00 63.13 C -ATOM 1431 CD2 PHE A 192 -0.444 -41.441 10.573 1.00 62.68 C -ATOM 1432 CE1 PHE A 192 2.102 -41.910 9.584 1.00 71.79 C -ATOM 1433 CE2 PHE A 192 0.510 -42.012 11.376 1.00 64.06 C -ATOM 1434 CZ PHE A 192 1.776 -42.244 10.882 1.00 66.40 C -ATOM 1435 N GLY A 193 -1.361 -37.770 5.903 1.00 53.26 N -ATOM 1436 CA GLY A 193 -2.343 -37.079 5.097 1.00 64.96 C -ATOM 1437 C GLY A 193 -3.109 -36.029 5.906 1.00 72.86 C -ATOM 1438 O GLY A 193 -2.497 -35.117 6.471 1.00 83.89 O -ATOM 1439 N ALA A 194 -4.437 -36.170 6.010 1.00 65.54 N -ATOM 1440 CA ALA A 194 -5.274 -35.195 6.707 1.00 58.81 C -ATOM 1441 C ALA A 194 -5.139 -35.243 8.241 1.00 53.68 C -ATOM 1442 O ALA A 194 -5.696 -34.378 8.931 1.00 41.71 O -ATOM 1443 CB ALA A 194 -6.725 -35.456 6.319 1.00 56.03 C -ATOM 1444 N THR A 195 -4.446 -36.286 8.739 1.00 51.68 N -ATOM 1445 CA THR A 195 -4.191 -36.606 10.142 1.00 43.81 C -ATOM 1446 C THR A 195 -2.808 -36.267 10.679 1.00 45.19 C -ATOM 1447 O THR A 195 -1.786 -36.640 10.106 1.00 37.22 O -ATOM 1448 CB THR A 195 -4.464 -38.101 10.326 1.00 33.57 C -ATOM 1449 OG1 THR A 195 -5.800 -38.272 9.841 1.00 41.80 O -ATOM 1450 CG2 THR A 195 -4.342 -38.606 11.756 1.00 33.82 C -ATOM 1451 N ASN A 196 -2.749 -35.582 11.812 1.00 33.40 N -ATOM 1452 CA ASN A 196 -1.485 -35.230 12.428 1.00 34.17 C -ATOM 1453 C ASN A 196 -1.419 -35.980 13.746 1.00 26.07 C -ATOM 1454 O ASN A 196 -2.456 -36.072 14.427 1.00 31.07 O -ATOM 1455 CB ASN A 196 -1.462 -33.757 12.688 1.00 34.94 C -ATOM 1456 CG ASN A 196 -1.494 -32.946 11.405 1.00 37.97 C -ATOM 1457 OD1 ASN A 196 -0.518 -32.901 10.654 1.00 38.93 O -ATOM 1458 ND2 ASN A 196 -2.596 -32.276 11.098 1.00 35.68 N -ATOM 1459 N VAL A 197 -0.292 -36.559 14.121 1.00 27.67 N -ATOM 1460 CA VAL A 197 -0.188 -37.257 15.380 1.00 27.06 C -ATOM 1461 C VAL A 197 1.051 -36.667 16.017 1.00 32.58 C -ATOM 1462 O VAL A 197 2.038 -36.440 15.321 1.00 35.46 O -ATOM 1463 CB VAL A 197 -0.021 -38.766 15.163 1.00 26.96 C -ATOM 1464 CG1 VAL A 197 0.146 -39.477 16.495 1.00 31.44 C -ATOM 1465 CG2 VAL A 197 -1.285 -39.339 14.562 1.00 30.72 C -ATOM 1466 N LYS A 198 1.028 -36.336 17.304 1.00 28.97 N -ATOM 1467 CA LYS A 198 2.191 -35.794 17.991 1.00 23.59 C -ATOM 1468 C LYS A 198 2.177 -36.537 19.331 1.00 20.72 C -ATOM 1469 O LYS A 198 1.100 -36.798 19.904 1.00 25.42 O -ATOM 1470 CB LYS A 198 2.030 -34.282 18.191 1.00 22.91 C -ATOM 1471 CG LYS A 198 3.317 -33.727 18.781 1.00 31.46 C -ATOM 1472 CD LYS A 198 3.327 -32.223 18.990 1.00 27.19 C -ATOM 1473 CE LYS A 198 3.301 -31.529 17.642 1.00 27.71 C -ATOM 1474 NZ LYS A 198 3.444 -30.081 17.745 1.00 22.82 N -ATOM 1475 N ALA A 199 3.360 -36.920 19.792 1.00 23.92 N -ATOM 1476 CA ALA A 199 3.512 -37.643 21.050 1.00 29.51 C -ATOM 1477 C ALA A 199 4.826 -37.264 21.694 1.00 31.31 C -ATOM 1478 O ALA A 199 5.773 -36.903 20.976 1.00 27.54 O -ATOM 1479 CB ALA A 199 3.547 -39.137 20.831 1.00 29.98 C -ATOM 1480 N TYR A 200 4.948 -37.287 23.029 1.00 24.08 N -ATOM 1481 CA TYR A 200 6.232 -36.978 23.647 1.00 25.77 C -ATOM 1482 C TYR A 200 6.312 -37.781 24.957 1.00 19.77 C -ATOM 1483 O TYR A 200 5.285 -38.229 25.471 1.00 25.09 O -ATOM 1484 CB TYR A 200 6.366 -35.468 23.965 1.00 21.68 C -ATOM 1485 CG TYR A 200 5.449 -35.011 25.114 1.00 27.89 C -ATOM 1486 CD1 TYR A 200 4.100 -34.740 24.906 1.00 23.60 C -ATOM 1487 CD2 TYR A 200 5.979 -34.928 26.414 1.00 26.80 C -ATOM 1488 CE1 TYR A 200 3.280 -34.398 25.985 1.00 21.78 C -ATOM 1489 CE2 TYR A 200 5.167 -34.592 27.493 1.00 21.58 C -ATOM 1490 CZ TYR A 200 3.825 -34.331 27.276 1.00 29.96 C -ATOM 1491 OH TYR A 200 3.038 -34.016 28.377 1.00 24.28 O -ATOM 1492 N TYR A 201 7.499 -37.895 25.487 1.00 22.60 N -ATOM 1493 CA TYR A 201 7.706 -38.468 26.778 1.00 24.74 C -ATOM 1494 C TYR A 201 8.768 -37.559 27.381 1.00 26.88 C -ATOM 1495 O TYR A 201 9.741 -37.191 26.708 1.00 24.56 O -ATOM 1496 CB TYR A 201 8.194 -39.901 26.603 1.00 25.19 C -ATOM 1497 CG TYR A 201 8.675 -40.448 27.936 1.00 34.01 C -ATOM 1498 CD1 TYR A 201 7.727 -40.932 28.815 1.00 36.14 C -ATOM 1499 CD2 TYR A 201 10.031 -40.414 28.250 1.00 34.68 C -ATOM 1500 CE1 TYR A 201 8.137 -41.392 30.041 1.00 36.17 C -ATOM 1501 CE2 TYR A 201 10.442 -40.870 29.481 1.00 35.36 C -ATOM 1502 CZ TYR A 201 9.481 -41.356 30.357 1.00 36.59 C -ATOM 1503 OH TYR A 201 9.869 -41.825 31.601 1.00 56.03 O -ATOM 1504 N ALA A 202 8.630 -37.196 28.663 1.00 27.52 N -ATOM 1505 CA ALA A 202 9.600 -36.329 29.339 1.00 25.10 C -ATOM 1506 C ALA A 202 9.877 -36.931 30.722 1.00 25.08 C -ATOM 1507 O ALA A 202 8.982 -37.486 31.356 1.00 25.54 O -ATOM 1508 CB ALA A 202 9.058 -34.895 29.564 1.00 22.21 C -ATOM 1509 N ASP A 203 11.085 -36.782 31.198 1.00 24.00 N -ATOM 1510 CA ASP A 203 11.489 -37.363 32.447 1.00 28.68 C -ATOM 1511 C ASP A 203 12.535 -36.459 33.079 1.00 29.57 C -ATOM 1512 O ASP A 203 13.419 -35.951 32.363 1.00 32.82 O -ATOM 1513 CB ASP A 203 12.041 -38.754 32.119 1.00 37.41 C -ATOM 1514 CG ASP A 203 12.421 -39.547 33.336 1.00 48.02 C -ATOM 1515 OD1 ASP A 203 11.555 -40.148 33.968 1.00 75.41 O -ATOM 1516 OD2 ASP A 203 13.595 -39.536 33.663 1.00 67.85 O -ATOM 1517 N GLY A 204 12.517 -36.218 34.397 1.00 32.61 N -ATOM 1518 CA GLY A 204 13.595 -35.437 34.988 1.00 28.05 C -ATOM 1519 C GLY A 204 13.367 -35.210 36.468 1.00 28.93 C -ATOM 1520 O GLY A 204 12.778 -36.061 37.158 1.00 27.42 O -ATOM 1521 N GLU A 205 13.792 -34.049 36.946 1.00 23.03 N -ATOM 1522 CA GLU A 205 13.529 -33.721 38.332 1.00 27.54 C -ATOM 1523 C GLU A 205 13.293 -32.246 38.482 1.00 28.34 C -ATOM 1524 O GLU A 205 13.832 -31.424 37.742 1.00 25.57 O -ATOM 1525 CB GLU A 205 14.677 -34.139 39.236 1.00 27.61 C -ATOM 1526 CG GLU A 205 15.986 -33.454 38.992 1.00 43.67 C -ATOM 1527 CD GLU A 205 17.151 -34.034 39.790 1.00 51.38 C -ATOM 1528 OE1 GLU A 205 17.227 -35.262 39.922 1.00 51.17 O -ATOM 1529 OE2 GLU A 205 17.983 -33.235 40.248 1.00 66.67 O -ATOM 1530 N LEU A 206 12.434 -31.947 39.450 1.00 21.41 N -ATOM 1531 CA LEU A 206 11.951 -30.610 39.719 1.00 19.79 C -ATOM 1532 C LEU A 206 12.248 -30.216 41.161 1.00 33.84 C -ATOM 1533 O LEU A 206 12.428 -31.096 42.002 1.00 26.21 O -ATOM 1534 CB LEU A 206 10.459 -30.554 39.522 1.00 20.83 C -ATOM 1535 CG LEU A 206 9.898 -30.808 38.130 1.00 25.89 C -ATOM 1536 CD1 LEU A 206 8.383 -30.698 38.181 1.00 25.84 C -ATOM 1537 CD2 LEU A 206 10.522 -29.805 37.148 1.00 21.85 C -ATOM 1538 N ASP A 207 12.317 -28.920 41.474 1.00 24.31 N -ATOM 1539 CA ASP A 207 12.413 -28.443 42.833 1.00 26.55 C -ATOM 1540 C ASP A 207 11.104 -28.863 43.501 1.00 29.31 C -ATOM 1541 O ASP A 207 10.014 -28.742 42.920 1.00 22.97 O -ATOM 1542 CB ASP A 207 12.536 -26.942 42.841 1.00 22.03 C -ATOM 1543 CG ASP A 207 12.384 -26.355 44.241 1.00 23.24 C -ATOM 1544 OD1 ASP A 207 13.308 -26.532 45.038 1.00 24.98 O -ATOM 1545 OD2 ASP A 207 11.350 -25.751 44.519 1.00 24.03 O -ATOM 1546 N ARG A 208 11.204 -29.311 44.760 1.00 26.76 N -ATOM 1547 CA ARG A 208 10.052 -29.752 45.541 1.00 22.68 C -ATOM 1548 C ARG A 208 8.952 -28.731 45.619 1.00 17.48 C -ATOM 1549 O ARG A 208 7.799 -29.036 45.306 1.00 22.76 O -ATOM 1550 CB ARG A 208 10.450 -30.093 46.997 1.00 24.59 C -ATOM 1551 CG ARG A 208 9.280 -30.540 47.905 1.00 26.44 C -ATOM 1552 CD ARG A 208 9.711 -30.470 49.382 1.00 20.80 C -ATOM 1553 NE ARG A 208 9.912 -29.091 49.803 1.00 20.58 N -ATOM 1554 CZ ARG A 208 11.067 -28.707 50.348 1.00 17.56 C -ATOM 1555 NH1 ARG A 208 12.081 -29.547 50.557 1.00 22.76 N -ATOM 1556 NH2 ARG A 208 11.220 -27.432 50.651 1.00 19.37 N -ATOM 1557 N ASP A 209 9.283 -27.519 46.063 1.00 16.79 N -ATOM 1558 CA ASP A 209 8.224 -26.561 46.241 1.00 17.98 C -ATOM 1559 C ASP A 209 7.692 -26.008 44.913 1.00 25.82 C -ATOM 1560 O ASP A 209 6.514 -25.676 44.824 1.00 23.17 O -ATOM 1561 CB ASP A 209 8.746 -25.456 47.156 1.00 24.37 C -ATOM 1562 CG ASP A 209 8.958 -25.951 48.609 1.00 28.77 C -ATOM 1563 OD1 ASP A 209 8.332 -26.917 49.039 1.00 22.89 O -ATOM 1564 OD2 ASP A 209 9.773 -25.356 49.292 1.00 27.21 O -ATOM 1565 N PHE A 210 8.491 -25.966 43.857 1.00 24.91 N -ATOM 1566 CA PHE A 210 7.994 -25.609 42.515 1.00 27.45 C -ATOM 1567 C PHE A 210 6.967 -26.694 42.077 1.00 21.30 C -ATOM 1568 O PHE A 210 5.830 -26.381 41.667 1.00 22.41 O -ATOM 1569 CB PHE A 210 9.258 -25.511 41.609 1.00 24.74 C -ATOM 1570 CG PHE A 210 9.033 -25.362 40.108 1.00 36.77 C -ATOM 1571 CD1 PHE A 210 8.844 -26.489 39.318 1.00 36.73 C -ATOM 1572 CD2 PHE A 210 9.010 -24.107 39.535 1.00 48.62 C -ATOM 1573 CE1 PHE A 210 8.629 -26.361 37.958 1.00 42.01 C -ATOM 1574 CE2 PHE A 210 8.796 -23.984 38.169 1.00 38.96 C -ATOM 1575 CZ PHE A 210 8.605 -25.107 37.388 1.00 34.54 C -ATOM 1576 N ALA A 211 7.288 -27.989 42.248 1.00 18.70 N -ATOM 1577 CA ALA A 211 6.367 -29.070 41.962 1.00 17.41 C -ATOM 1578 C ALA A 211 5.078 -28.999 42.740 1.00 21.61 C -ATOM 1579 O ALA A 211 3.986 -29.206 42.197 1.00 23.50 O -ATOM 1580 CB ALA A 211 7.087 -30.370 42.259 1.00 20.52 C -ATOM 1581 N ARG A 212 5.119 -28.675 44.039 1.00 24.46 N -ATOM 1582 CA ARG A 212 3.907 -28.580 44.840 1.00 21.96 C -ATOM 1583 C ARG A 212 3.031 -27.442 44.354 1.00 20.18 C -ATOM 1584 O ARG A 212 1.803 -27.553 44.346 1.00 23.86 O -ATOM 1585 CB ARG A 212 4.259 -28.343 46.321 1.00 19.67 C -ATOM 1586 CG ARG A 212 5.020 -29.538 46.960 1.00 22.71 C -ATOM 1587 CD ARG A 212 5.446 -29.292 48.472 1.00 23.65 C -ATOM 1588 NE ARG A 212 4.273 -28.986 49.277 1.00 20.64 N -ATOM 1589 CZ ARG A 212 3.513 -29.926 49.838 1.00 19.45 C -ATOM 1590 NH1 ARG A 212 3.829 -31.205 49.748 1.00 22.61 N -ATOM 1591 NH2 ARG A 212 2.434 -29.615 50.517 1.00 22.43 N -ATOM 1592 N ALA A 213 3.637 -26.328 43.942 1.00 22.64 N -ATOM 1593 CA ALA A 213 2.875 -25.177 43.421 1.00 24.94 C -ATOM 1594 C ALA A 213 2.142 -25.528 42.113 1.00 28.90 C -ATOM 1595 O ALA A 213 1.063 -24.985 41.886 1.00 28.23 O -ATOM 1596 CB ALA A 213 3.804 -23.997 43.173 1.00 18.67 C -ATOM 1597 N VAL A 214 2.628 -26.470 41.272 1.00 27.53 N -ATOM 1598 CA VAL A 214 1.899 -26.961 40.096 1.00 24.66 C -ATOM 1599 C VAL A 214 0.549 -27.454 40.554 1.00 28.81 C -ATOM 1600 O VAL A 214 -0.439 -27.180 39.876 1.00 36.46 O -ATOM 1601 CB VAL A 214 2.580 -28.169 39.376 1.00 28.48 C -ATOM 1602 CG1 VAL A 214 1.708 -28.805 38.273 1.00 34.90 C -ATOM 1603 CG2 VAL A 214 3.853 -27.658 38.787 1.00 30.97 C -ATOM 1604 N PHE A 215 0.479 -28.167 41.701 1.00 30.95 N -ATOM 1605 CA PHE A 215 -0.780 -28.734 42.192 1.00 22.46 C -ATOM 1606 C PHE A 215 -1.475 -27.849 43.206 1.00 22.21 C -ATOM 1607 O PHE A 215 -2.456 -28.240 43.854 1.00 31.72 O -ATOM 1608 CB PHE A 215 -0.532 -30.139 42.785 1.00 25.11 C -ATOM 1609 CG PHE A 215 -0.220 -31.216 41.740 1.00 24.68 C -ATOM 1610 CD1 PHE A 215 -1.257 -31.912 41.157 1.00 29.63 C -ATOM 1611 CD2 PHE A 215 1.084 -31.461 41.357 1.00 33.02 C -ATOM 1612 CE1 PHE A 215 -0.979 -32.845 40.185 1.00 29.05 C -ATOM 1613 CE2 PHE A 215 1.353 -32.394 40.383 1.00 34.93 C -ATOM 1614 CZ PHE A 215 0.323 -33.079 39.802 1.00 28.48 C -ATOM 1615 N ASP A 216 -0.985 -26.613 43.281 1.00 21.70 N -ATOM 1616 CA ASP A 216 -1.535 -25.593 44.127 1.00 28.43 C -ATOM 1617 C ASP A 216 -1.438 -25.965 45.612 1.00 31.75 C -ATOM 1618 O ASP A 216 -2.385 -25.730 46.383 1.00 34.20 O -ATOM 1619 CB ASP A 216 -2.975 -25.386 43.685 1.00 30.70 C -ATOM 1620 CG ASP A 216 -3.447 -23.971 43.857 1.00 58.07 C -ATOM 1621 OD1 ASP A 216 -2.615 -23.066 43.765 1.00 71.62 O -ATOM 1622 OD2 ASP A 216 -4.644 -23.792 44.079 1.00 83.68 O -ATOM 1623 N LEU A 217 -0.302 -26.558 45.999 1.00 27.44 N -ATOM 1624 CA LEU A 217 -0.097 -27.045 47.363 1.00 27.84 C -ATOM 1625 C LEU A 217 0.868 -26.098 48.046 1.00 27.78 C -ATOM 1626 O LEU A 217 1.775 -25.587 47.365 1.00 26.69 O -ATOM 1627 CB LEU A 217 0.482 -28.462 47.339 1.00 22.43 C -ATOM 1628 CG LEU A 217 -0.368 -29.545 46.687 1.00 21.31 C -ATOM 1629 CD1 LEU A 217 0.425 -30.812 46.668 1.00 20.93 C -ATOM 1630 CD2 LEU A 217 -1.675 -29.707 47.397 1.00 24.17 C -ATOM 1631 N THR A 218 0.654 -25.760 49.335 1.00 24.26 N -ATOM 1632 CA THR A 218 1.603 -24.878 50.056 1.00 27.38 C -ATOM 1633 C THR A 218 2.998 -25.499 50.095 1.00 19.15 C -ATOM 1634 O THR A 218 3.123 -26.738 50.111 1.00 25.68 O -ATOM 1635 CB THR A 218 1.172 -24.558 51.583 1.00 30.12 C -ATOM 1636 OG1 THR A 218 0.441 -25.619 52.157 1.00 46.14 O -ATOM 1637 CG2 THR A 218 0.361 -23.302 51.629 1.00 61.20 C -ATOM 1638 N PRO A 219 4.068 -24.709 50.157 1.00 21.50 N -ATOM 1639 CA PRO A 219 5.423 -25.218 50.277 1.00 23.92 C -ATOM 1640 C PRO A 219 5.713 -25.861 51.643 1.00 32.60 C -ATOM 1641 O PRO A 219 4.957 -25.603 52.600 1.00 29.02 O -ATOM 1642 CB PRO A 219 6.264 -24.003 49.999 1.00 26.19 C -ATOM 1643 CG PRO A 219 5.428 -22.849 50.465 1.00 25.43 C -ATOM 1644 CD PRO A 219 4.030 -23.251 50.079 1.00 20.73 C -ATOM 1645 N VAL A 220 6.764 -26.694 51.739 1.00 33.44 N -ATOM 1646 CA VAL A 220 7.141 -27.212 53.041 1.00 28.14 C -ATOM 1647 C VAL A 220 8.321 -26.376 53.539 1.00 37.97 C -ATOM 1648 O VAL A 220 9.198 -25.938 52.775 1.00 26.48 O -ATOM 1649 CB VAL A 220 7.474 -28.788 53.044 1.00 32.32 C -ATOM 1650 CG1 VAL A 220 6.828 -29.437 51.860 1.00 24.32 C -ATOM 1651 CG2 VAL A 220 8.915 -29.093 53.141 1.00 34.39 C -ATOM 1652 N ALA A 221 8.313 -26.094 54.847 1.00 25.77 N -ATOM 1653 CA ALA A 221 9.325 -25.258 55.460 1.00 22.75 C -ATOM 1654 C ALA A 221 10.534 -26.080 55.804 1.00 34.19 C -ATOM 1655 O ALA A 221 10.722 -26.485 56.955 1.00 35.48 O -ATOM 1656 CB ALA A 221 8.750 -24.626 56.716 1.00 25.04 C -ATOM 1657 N ALA A 222 11.347 -26.358 54.787 1.00 25.99 N -ATOM 1658 CA ALA A 222 12.566 -27.158 54.881 1.00 20.53 C -ATOM 1659 C ALA A 222 13.474 -26.719 53.755 1.00 27.31 C -ATOM 1660 O ALA A 222 13.019 -25.985 52.869 1.00 32.70 O -ATOM 1661 CB ALA A 222 12.334 -28.656 54.664 1.00 17.91 C -ATOM 1662 N ALA A 223 14.750 -27.089 53.799 1.00 27.27 N -ATOM 1663 CA ALA A 223 15.696 -26.836 52.713 1.00 33.28 C -ATOM 1664 C ALA A 223 15.235 -27.607 51.455 1.00 43.31 C -ATOM 1665 O ALA A 223 14.658 -28.721 51.516 1.00 26.72 O -ATOM 1666 CB ALA A 223 17.090 -27.326 53.081 1.00 24.82 C -ATOM 1667 N ALA A 224 15.479 -26.956 50.312 1.00 32.68 N -ATOM 1668 CA ALA A 224 15.033 -27.446 49.021 1.00 27.30 C -ATOM 1669 C ALA A 224 15.546 -28.827 48.722 1.00 25.24 C -ATOM 1670 O ALA A 224 16.683 -29.196 49.031 1.00 29.56 O -ATOM 1671 CB ALA A 224 15.531 -26.539 47.921 1.00 25.05 C -ATOM 1672 N THR A 225 14.685 -29.618 48.132 1.00 24.13 N -ATOM 1673 CA THR A 225 15.074 -30.941 47.687 1.00 25.61 C -ATOM 1674 C THR A 225 14.543 -31.084 46.261 1.00 36.20 C -ATOM 1675 O THR A 225 13.669 -30.284 45.868 1.00 26.28 O -ATOM 1676 CB THR A 225 14.448 -32.041 48.615 1.00 32.35 C -ATOM 1677 OG1 THR A 225 13.015 -31.944 48.645 1.00 30.23 O -ATOM 1678 CG2 THR A 225 14.976 -31.857 50.034 1.00 42.70 C -ATOM 1679 N ALA A 226 15.011 -32.065 45.487 1.00 30.91 N -ATOM 1680 CA ALA A 226 14.462 -32.311 44.154 1.00 36.76 C -ATOM 1681 C ALA A 226 13.513 -33.515 44.156 1.00 34.85 C -ATOM 1682 O ALA A 226 13.738 -34.427 44.952 1.00 40.82 O -ATOM 1683 CB ALA A 226 15.588 -32.581 43.203 1.00 25.21 C -ATOM 1684 N VAL A 227 12.415 -33.564 43.381 1.00 31.55 N -ATOM 1685 CA VAL A 227 11.510 -34.715 43.239 1.00 25.98 C -ATOM 1686 C VAL A 227 11.584 -35.229 41.797 1.00 37.72 C -ATOM 1687 O VAL A 227 11.799 -34.425 40.888 1.00 30.25 O -ATOM 1688 CB VAL A 227 10.031 -34.368 43.536 1.00 26.42 C -ATOM 1689 CG1 VAL A 227 9.922 -34.313 45.040 1.00 35.42 C -ATOM 1690 CG2 VAL A 227 9.569 -33.052 42.897 1.00 24.43 C -ATOM 1691 N ASP A 228 11.438 -36.512 41.495 1.00 28.65 N -ATOM 1692 CA ASP A 228 11.515 -37.003 40.118 1.00 30.27 C -ATOM 1693 C ASP A 228 10.189 -36.852 39.473 1.00 27.49 C -ATOM 1694 O ASP A 228 9.171 -36.951 40.160 1.00 27.44 O -ATOM 1695 CB ASP A 228 11.888 -38.488 40.051 1.00 29.18 C -ATOM 1696 CG ASP A 228 13.287 -38.733 40.626 1.00 36.93 C -ATOM 1697 OD1 ASP A 228 14.240 -38.049 40.232 1.00 60.99 O -ATOM 1698 OD2 ASP A 228 13.419 -39.588 41.502 1.00 67.40 O -ATOM 1699 N HIS A 229 10.128 -36.639 38.165 1.00 27.81 N -ATOM 1700 CA HIS A 229 8.830 -36.503 37.511 1.00 27.57 C -ATOM 1701 C HIS A 229 8.896 -37.122 36.125 1.00 22.47 C -ATOM 1702 O HIS A 229 9.984 -37.331 35.560 1.00 25.44 O -ATOM 1703 CB HIS A 229 8.397 -35.013 37.341 1.00 24.81 C -ATOM 1704 CG HIS A 229 9.312 -34.181 36.403 1.00 25.52 C -ATOM 1705 ND1 HIS A 229 10.615 -33.896 36.508 1.00 26.06 N -ATOM 1706 CD2 HIS A 229 8.872 -33.550 35.242 1.00 26.80 C -ATOM 1707 CE1 HIS A 229 10.975 -33.137 35.493 1.00 31.27 C -ATOM 1708 NE2 HIS A 229 9.917 -32.942 34.749 1.00 24.74 N -ATOM 1709 N LYS A 230 7.707 -37.415 35.634 1.00 25.04 N -ATOM 1710 CA LYS A 230 7.595 -37.800 34.269 1.00 31.02 C -ATOM 1711 C LYS A 230 6.333 -37.202 33.715 1.00 29.49 C -ATOM 1712 O LYS A 230 5.422 -36.866 34.461 1.00 24.54 O -ATOM 1713 CB LYS A 230 7.587 -39.292 34.172 1.00 26.28 C -ATOM 1714 CG LYS A 230 6.388 -40.093 34.564 1.00 47.78 C -ATOM 1715 CD LYS A 230 6.930 -41.543 34.609 1.00 73.52 C -ATOM 1716 CE LYS A 230 8.071 -41.699 35.655 1.00 89.17 C -ATOM 1717 NZ LYS A 230 8.899 -42.887 35.501 1.00101.19 N -ATOM 1718 N ALA A 231 6.307 -36.988 32.407 1.00 28.59 N -ATOM 1719 CA ALA A 231 5.160 -36.419 31.722 1.00 23.31 C -ATOM 1720 C ALA A 231 5.135 -37.079 30.339 1.00 23.75 C -ATOM 1721 O ALA A 231 6.189 -37.406 29.764 1.00 27.95 O -ATOM 1722 CB ALA A 231 5.364 -34.920 31.575 1.00 23.08 C -ATOM 1723 N TYR A 232 3.972 -37.375 29.801 1.00 23.45 N -ATOM 1724 CA TYR A 232 3.874 -37.908 28.445 1.00 32.26 C -ATOM 1725 C TYR A 232 2.487 -37.605 27.895 1.00 29.25 C -ATOM 1726 O TYR A 232 1.550 -37.348 28.668 1.00 27.46 O -ATOM 1727 CB TYR A 232 4.162 -39.439 28.413 1.00 28.02 C -ATOM 1728 CG TYR A 232 3.494 -40.240 29.515 1.00 27.17 C -ATOM 1729 CD1 TYR A 232 4.167 -40.375 30.718 1.00 35.93 C -ATOM 1730 CD2 TYR A 232 2.236 -40.789 29.331 1.00 30.56 C -ATOM 1731 CE1 TYR A 232 3.571 -41.057 31.753 1.00 40.00 C -ATOM 1732 CE2 TYR A 232 1.634 -41.488 30.366 1.00 39.00 C -ATOM 1733 CZ TYR A 232 2.312 -41.611 31.573 1.00 38.48 C -ATOM 1734 OH TYR A 232 1.717 -42.278 32.642 1.00 56.10 O -ATOM 1735 N GLY A 233 2.285 -37.561 26.574 1.00 22.51 N -ATOM 1736 CA GLY A 233 0.985 -37.244 26.014 1.00 24.02 C -ATOM 1737 C GLY A 233 0.950 -37.507 24.514 1.00 26.25 C -ATOM 1738 O GLY A 233 1.941 -37.833 23.856 1.00 24.83 O -ATOM 1739 N LEU A 234 -0.223 -37.323 23.996 1.00 25.95 N -ATOM 1740 CA LEU A 234 -0.460 -37.640 22.618 1.00 24.03 C -ATOM 1741 C LEU A 234 -1.584 -36.777 22.103 1.00 28.04 C -ATOM 1742 O LEU A 234 -2.514 -36.506 22.890 1.00 28.24 O -ATOM 1743 CB LEU A 234 -0.866 -39.070 22.566 1.00 31.10 C -ATOM 1744 CG LEU A 234 -1.539 -39.544 21.317 1.00 41.38 C -ATOM 1745 CD1 LEU A 234 -0.480 -39.786 20.245 1.00 34.15 C -ATOM 1746 CD2 LEU A 234 -2.356 -40.751 21.648 1.00 42.03 C -ATOM 1747 N SER A 235 -1.534 -36.329 20.833 1.00 26.13 N -ATOM 1748 CA SER A 235 -2.724 -35.732 20.265 1.00 25.83 C -ATOM 1749 C SER A 235 -2.895 -36.213 18.836 1.00 25.93 C -ATOM 1750 O SER A 235 -1.899 -36.580 18.179 1.00 28.39 O -ATOM 1751 CB SER A 235 -2.699 -34.190 20.226 1.00 32.71 C -ATOM 1752 OG SER A 235 -1.734 -33.546 19.431 1.00 30.62 O -ATOM 1753 N VAL A 236 -4.162 -36.183 18.415 1.00 24.17 N -ATOM 1754 CA VAL A 236 -4.537 -36.596 17.082 1.00 35.92 C -ATOM 1755 C VAL A 236 -5.526 -35.562 16.575 1.00 30.98 C -ATOM 1756 O VAL A 236 -6.478 -35.231 17.299 1.00 29.40 O -ATOM 1757 CB VAL A 236 -5.242 -37.999 17.076 1.00 37.21 C -ATOM 1758 CG1 VAL A 236 -5.538 -38.410 15.632 1.00 36.84 C -ATOM 1759 CG2 VAL A 236 -4.348 -39.079 17.632 1.00 26.11 C -ATOM 1760 N ASP A 237 -5.348 -35.028 15.361 1.00 32.91 N -ATOM 1761 CA ASP A 237 -6.394 -34.211 14.758 1.00 25.51 C -ATOM 1762 C ASP A 237 -6.495 -34.598 13.289 1.00 35.12 C -ATOM 1763 O ASP A 237 -5.479 -35.003 12.696 1.00 26.89 O -ATOM 1764 CB ASP A 237 -6.092 -32.730 14.842 1.00 18.52 C -ATOM 1765 CG ASP A 237 -4.815 -32.240 14.216 1.00 30.05 C -ATOM 1766 OD1 ASP A 237 -3.766 -32.292 14.847 1.00 32.68 O -ATOM 1767 OD2 ASP A 237 -4.885 -31.769 13.090 1.00 32.21 O -ATOM 1768 N SER A 238 -7.670 -34.485 12.706 1.00 26.63 N -ATOM 1769 CA SER A 238 -7.842 -34.834 11.317 1.00 37.70 C -ATOM 1770 C SER A 238 -8.823 -33.890 10.690 1.00 32.20 C -ATOM 1771 O SER A 238 -9.807 -33.469 11.318 1.00 31.51 O -ATOM 1772 CB SER A 238 -8.377 -36.244 11.179 1.00 41.15 C -ATOM 1773 OG SER A 238 -8.165 -36.687 9.837 1.00 71.90 O -ATOM 1774 N THR A 239 -8.540 -33.586 9.431 1.00 36.96 N -ATOM 1775 CA THR A 239 -9.398 -32.696 8.670 1.00 32.71 C -ATOM 1776 C THR A 239 -10.155 -33.389 7.544 1.00 36.75 C -ATOM 1777 O THR A 239 -9.556 -34.067 6.710 1.00 49.53 O -ATOM 1778 CB THR A 239 -8.536 -31.582 8.106 1.00 32.24 C -ATOM 1779 OG1 THR A 239 -7.852 -30.961 9.187 1.00 37.41 O -ATOM 1780 CG2 THR A 239 -9.370 -30.533 7.409 1.00 43.12 C -ATOM 1781 N PHE A 240 -11.462 -33.214 7.506 1.00 32.39 N -ATOM 1782 CA PHE A 240 -12.341 -33.703 6.445 1.00 34.60 C -ATOM 1783 C PHE A 240 -13.163 -32.519 5.907 1.00 35.95 C -ATOM 1784 O PHE A 240 -14.186 -32.080 6.472 1.00 35.29 O -ATOM 1785 CB PHE A 240 -13.350 -34.771 6.926 1.00 44.97 C -ATOM 1786 CG PHE A 240 -13.345 -35.118 8.409 1.00 76.78 C -ATOM 1787 CD1 PHE A 240 -12.351 -35.948 8.916 1.00 80.80 C -ATOM 1788 CD2 PHE A 240 -14.340 -34.611 9.227 1.00 80.91 C -ATOM 1789 CE1 PHE A 240 -12.351 -36.280 10.251 1.00 68.89 C -ATOM 1790 CE2 PHE A 240 -14.331 -34.950 10.563 1.00 82.55 C -ATOM 1791 CZ PHE A 240 -13.340 -35.778 11.067 1.00 81.89 C -ATOM 1792 N GLY A 241 -12.680 -31.948 4.808 1.00 34.25 N -ATOM 1793 CA GLY A 241 -13.350 -30.824 4.204 1.00 33.96 C -ATOM 1794 C GLY A 241 -13.040 -29.537 4.968 1.00 29.52 C -ATOM 1795 O GLY A 241 -11.882 -29.126 5.127 1.00 42.22 O -ATOM 1796 N ALA A 242 -14.115 -28.897 5.419 1.00 36.46 N -ATOM 1797 CA ALA A 242 -14.010 -27.686 6.217 1.00 38.95 C -ATOM 1798 C ALA A 242 -13.882 -28.010 7.720 1.00 32.64 C -ATOM 1799 O ALA A 242 -13.627 -27.086 8.491 1.00 34.81 O -ATOM 1800 CB ALA A 242 -15.262 -26.850 5.969 1.00 29.62 C -ATOM 1801 N THR A 243 -14.038 -29.268 8.161 1.00 28.72 N -ATOM 1802 CA THR A 243 -14.065 -29.689 9.551 1.00 32.77 C -ATOM 1803 C THR A 243 -12.794 -30.303 10.043 1.00 38.01 C -ATOM 1804 O THR A 243 -12.331 -31.287 9.467 1.00 34.60 O -ATOM 1805 CB THR A 243 -15.173 -30.719 9.790 1.00 29.34 C -ATOM 1806 OG1 THR A 243 -16.361 -30.152 9.254 1.00 38.80 O -ATOM 1807 CG2 THR A 243 -15.431 -31.019 11.255 1.00 36.27 C -ATOM 1808 N THR A 244 -12.219 -29.739 11.095 1.00 27.70 N -ATOM 1809 CA THR A 244 -11.122 -30.407 11.774 1.00 21.95 C -ATOM 1810 C THR A 244 -11.688 -30.849 13.123 1.00 38.04 C -ATOM 1811 O THR A 244 -12.524 -30.149 13.726 1.00 29.47 O -ATOM 1812 CB THR A 244 -10.004 -29.457 11.967 1.00 27.11 C -ATOM 1813 OG1 THR A 244 -9.643 -29.054 10.641 1.00 30.63 O -ATOM 1814 CG2 THR A 244 -8.854 -30.056 12.776 1.00 22.16 C -ATOM 1815 N VAL A 245 -11.298 -32.053 13.533 1.00 32.84 N -ATOM 1816 CA VAL A 245 -11.691 -32.672 14.799 1.00 23.59 C -ATOM 1817 C VAL A 245 -10.380 -33.151 15.399 1.00 30.46 C -ATOM 1818 O VAL A 245 -9.480 -33.587 14.666 1.00 28.97 O -ATOM 1819 CB VAL A 245 -12.643 -33.860 14.564 1.00 26.50 C -ATOM 1820 CG1 VAL A 245 -12.936 -34.616 15.851 1.00 42.06 C -ATOM 1821 CG2 VAL A 245 -13.983 -33.313 14.105 1.00 29.56 C -ATOM 1822 N GLY A 246 -10.217 -32.981 16.715 1.00 30.97 N -ATOM 1823 CA GLY A 246 -8.989 -33.402 17.357 1.00 28.37 C -ATOM 1824 C GLY A 246 -9.056 -33.404 18.881 1.00 31.52 C -ATOM 1825 O GLY A 246 -10.015 -32.875 19.467 1.00 29.24 O -ATOM 1826 N GLY A 247 -8.033 -33.959 19.524 1.00 26.92 N -ATOM 1827 CA GLY A 247 -8.013 -34.006 20.963 1.00 25.58 C -ATOM 1828 C GLY A 247 -6.646 -34.406 21.421 1.00 36.99 C -ATOM 1829 O GLY A 247 -5.803 -34.741 20.587 1.00 25.32 O -ATOM 1830 N TYR A 248 -6.416 -34.408 22.735 1.00 23.62 N -ATOM 1831 CA TYR A 248 -5.115 -34.748 23.270 1.00 20.94 C -ATOM 1832 C TYR A 248 -5.325 -35.358 24.660 1.00 20.63 C -ATOM 1833 O TYR A 248 -6.406 -35.164 25.255 1.00 21.90 O -ATOM 1834 CB TYR A 248 -4.231 -33.486 23.387 1.00 21.56 C -ATOM 1835 CG TYR A 248 -4.760 -32.431 24.364 1.00 25.21 C -ATOM 1836 CD1 TYR A 248 -4.438 -32.548 25.708 1.00 27.92 C -ATOM 1837 CD2 TYR A 248 -5.615 -31.411 23.968 1.00 24.90 C -ATOM 1838 CE1 TYR A 248 -4.966 -31.665 26.639 1.00 26.26 C -ATOM 1839 CE2 TYR A 248 -6.151 -30.519 24.904 1.00 31.70 C -ATOM 1840 CZ TYR A 248 -5.819 -30.648 26.258 1.00 26.70 C -ATOM 1841 OH TYR A 248 -6.318 -29.797 27.251 1.00 25.24 O -ATOM 1842 N VAL A 249 -4.321 -36.040 25.195 1.00 24.77 N -ATOM 1843 CA VAL A 249 -4.367 -36.470 26.593 1.00 27.74 C -ATOM 1844 C VAL A 249 -2.923 -36.423 27.059 1.00 28.50 C -ATOM 1845 O VAL A 249 -1.975 -36.725 26.318 1.00 24.37 O -ATOM 1846 CB VAL A 249 -5.003 -37.894 26.729 1.00 30.76 C -ATOM 1847 CG1 VAL A 249 -4.158 -38.959 26.069 1.00 36.77 C -ATOM 1848 CG2 VAL A 249 -5.154 -38.207 28.211 1.00 29.16 C -ATOM 1849 N GLN A 250 -2.715 -35.905 28.269 1.00 22.78 N -ATOM 1850 CA GLN A 250 -1.387 -35.776 28.807 1.00 23.77 C -ATOM 1851 C GLN A 250 -1.468 -36.243 30.256 1.00 25.06 C -ATOM 1852 O GLN A 250 -2.549 -36.178 30.872 1.00 21.33 O -ATOM 1853 CB GLN A 250 -0.900 -34.339 28.864 1.00 23.22 C -ATOM 1854 CG GLN A 250 -1.124 -33.547 27.625 1.00 24.76 C -ATOM 1855 CD GLN A 250 -0.215 -32.353 27.600 1.00 18.99 C -ATOM 1856 OE1 GLN A 250 0.992 -32.480 27.720 1.00 23.92 O -ATOM 1857 NE2 GLN A 250 -0.707 -31.141 27.461 1.00 20.19 N -ATOM 1858 N VAL A 251 -0.358 -36.761 30.770 1.00 29.03 N -ATOM 1859 CA VAL A 251 -0.307 -37.017 32.189 1.00 26.98 C -ATOM 1860 C VAL A 251 1.015 -36.492 32.676 1.00 25.15 C -ATOM 1861 O VAL A 251 2.068 -36.481 32.014 1.00 26.27 O -ATOM 1862 CB VAL A 251 -0.510 -38.552 32.608 1.00 33.15 C -ATOM 1863 CG1 VAL A 251 -0.968 -39.355 31.434 1.00 26.27 C -ATOM 1864 CG2 VAL A 251 0.702 -39.104 33.283 1.00 32.70 C -ATOM 1865 N LEU A 252 0.873 -35.954 33.891 1.00 23.70 N -ATOM 1866 CA LEU A 252 2.023 -35.435 34.601 1.00 21.27 C -ATOM 1867 C LEU A 252 2.033 -36.219 35.906 1.00 26.27 C -ATOM 1868 O LEU A 252 0.990 -36.303 36.555 1.00 26.01 O -ATOM 1869 CB LEU A 252 1.825 -33.976 34.863 1.00 22.83 C -ATOM 1870 CG LEU A 252 2.836 -33.284 35.749 1.00 32.44 C -ATOM 1871 CD1 LEU A 252 4.251 -33.390 35.206 1.00 25.21 C -ATOM 1872 CD2 LEU A 252 2.333 -31.861 35.904 1.00 28.50 C -ATOM 1873 N ASP A 253 3.167 -36.799 36.251 1.00 25.12 N -ATOM 1874 CA ASP A 253 3.301 -37.651 37.415 1.00 34.71 C -ATOM 1875 C ASP A 253 4.503 -37.199 38.247 1.00 25.50 C -ATOM 1876 O ASP A 253 5.652 -37.463 37.851 1.00 26.91 O -ATOM 1877 CB ASP A 253 3.454 -39.066 36.865 1.00 31.51 C -ATOM 1878 CG ASP A 253 3.436 -40.240 37.841 1.00 52.04 C -ATOM 1879 OD1 ASP A 253 3.598 -40.015 39.040 1.00 49.77 O -ATOM 1880 OD2 ASP A 253 3.257 -41.381 37.389 1.00 67.89 O -ATOM 1881 N ILE A 254 4.327 -36.531 39.394 1.00 24.18 N -ATOM 1882 CA ILE A 254 5.467 -36.087 40.166 1.00 23.34 C -ATOM 1883 C ILE A 254 5.483 -36.909 41.440 1.00 30.07 C -ATOM 1884 O ILE A 254 4.540 -36.908 42.249 1.00 29.61 O -ATOM 1885 CB ILE A 254 5.378 -34.625 40.550 1.00 20.78 C -ATOM 1886 CG1 ILE A 254 5.120 -33.770 39.278 1.00 23.54 C -ATOM 1887 CG2 ILE A 254 6.696 -34.241 41.236 1.00 20.01 C -ATOM 1888 CD1 ILE A 254 4.936 -32.261 39.497 1.00 30.48 C -ATOM 1889 N ASP A 255 6.606 -37.585 41.539 1.00 27.10 N -ATOM 1890 CA ASP A 255 6.902 -38.482 42.630 1.00 37.11 C -ATOM 1891 C ASP A 255 6.845 -37.723 43.957 1.00 34.48 C -ATOM 1892 O ASP A 255 7.377 -36.618 44.107 1.00 33.20 O -ATOM 1893 CB ASP A 255 8.290 -39.064 42.417 1.00 36.96 C -ATOM 1894 CG ASP A 255 8.690 -40.163 43.403 1.00 61.77 C -ATOM 1895 OD1 ASP A 255 7.879 -41.053 43.678 1.00 63.74 O -ATOM 1896 OD2 ASP A 255 9.818 -40.132 43.893 1.00 54.70 O -ATOM 1897 N THR A 256 6.132 -38.389 44.869 1.00 38.04 N -ATOM 1898 CA THR A 256 5.860 -37.972 46.235 1.00 27.79 C -ATOM 1899 C THR A 256 4.849 -36.835 46.246 1.00 45.76 C -ATOM 1900 O THR A 256 4.408 -36.503 47.344 1.00 49.10 O -ATOM 1901 CB THR A 256 7.129 -37.485 47.075 1.00 37.48 C -ATOM 1902 OG1 THR A 256 7.491 -36.195 46.656 1.00 37.65 O -ATOM 1903 CG2 THR A 256 8.331 -38.390 46.918 1.00 36.65 C -ATOM 1904 N ILE A 257 4.398 -36.198 45.147 1.00 46.16 N -ATOM 1905 CA ILE A 257 3.436 -35.093 45.238 1.00 36.33 C -ATOM 1906 C ILE A 257 2.150 -35.643 44.702 1.00 45.12 C -ATOM 1907 O ILE A 257 1.300 -36.026 45.495 1.00 39.40 O -ATOM 1908 CB ILE A 257 3.835 -33.831 44.393 1.00 30.69 C -ATOM 1909 CG1 ILE A 257 5.261 -33.393 44.729 1.00 26.95 C -ATOM 1910 CG2 ILE A 257 2.776 -32.750 44.585 1.00 28.34 C -ATOM 1911 CD1 ILE A 257 5.617 -33.165 46.186 1.00 47.06 C -ATOM 1912 N ASP A 258 1.980 -35.772 43.386 1.00 26.70 N -ATOM 1913 CA ASP A 258 0.726 -36.235 42.834 1.00 20.95 C -ATOM 1914 C ASP A 258 0.900 -36.477 41.310 1.00 21.68 C -ATOM 1915 O ASP A 258 1.987 -36.248 40.781 1.00 25.33 O -ATOM 1916 CB ASP A 258 -0.359 -35.176 43.097 1.00 24.31 C -ATOM 1917 CG ASP A 258 -1.793 -35.738 43.188 1.00 39.02 C -ATOM 1918 OD1 ASP A 258 -2.027 -36.953 43.009 1.00 36.22 O -ATOM 1919 OD2 ASP A 258 -2.705 -34.944 43.447 1.00 49.23 O -ATOM 1920 N ASP A 259 -0.152 -36.966 40.657 1.00 32.03 N -ATOM 1921 CA ASP A 259 -0.230 -37.188 39.229 1.00 35.51 C -ATOM 1922 C ASP A 259 -1.548 -36.603 38.763 1.00 29.00 C -ATOM 1923 O ASP A 259 -2.461 -36.390 39.566 1.00 29.90 O -ATOM 1924 CB ASP A 259 -0.192 -38.674 38.860 1.00 29.16 C -ATOM 1925 CG ASP A 259 -1.224 -39.576 39.537 1.00 32.42 C -ATOM 1926 OD1 ASP A 259 -2.393 -39.544 39.181 1.00 53.80 O -ATOM 1927 OD2 ASP A 259 -0.846 -40.322 40.433 1.00 66.04 O -ATOM 1928 N VAL A 260 -1.665 -36.276 37.483 1.00 23.61 N -ATOM 1929 CA VAL A 260 -2.910 -35.780 36.928 1.00 21.31 C -ATOM 1930 C VAL A 260 -2.886 -36.211 35.452 1.00 25.64 C -ATOM 1931 O VAL A 260 -1.818 -36.338 34.836 1.00 25.09 O -ATOM 1932 CB VAL A 260 -2.958 -34.221 37.123 1.00 21.65 C -ATOM 1933 CG1 VAL A 260 -1.779 -33.495 36.460 1.00 22.43 C -ATOM 1934 CG2 VAL A 260 -4.300 -33.747 36.600 1.00 23.25 C -ATOM 1935 N THR A 261 -4.073 -36.529 34.953 1.00 26.37 N -ATOM 1936 CA THR A 261 -4.323 -36.788 33.551 1.00 29.83 C -ATOM 1937 C THR A 261 -5.306 -35.690 33.145 1.00 28.17 C -ATOM 1938 O THR A 261 -6.336 -35.465 33.799 1.00 27.71 O -ATOM 1939 CB THR A 261 -4.949 -38.190 33.349 1.00 28.09 C -ATOM 1940 OG1 THR A 261 -3.930 -39.126 33.734 1.00 29.64 O -ATOM 1941 CG2 THR A 261 -5.462 -38.417 31.908 1.00 25.84 C -ATOM 1942 N TYR A 262 -4.983 -34.982 32.066 1.00 29.21 N -ATOM 1943 CA TYR A 262 -5.785 -33.861 31.598 1.00 24.79 C -ATOM 1944 C TYR A 262 -5.915 -34.030 30.083 1.00 23.96 C -ATOM 1945 O TYR A 262 -5.044 -34.609 29.415 1.00 24.24 O -ATOM 1946 CB TYR A 262 -5.088 -32.537 31.993 1.00 24.82 C -ATOM 1947 CG TYR A 262 -3.579 -32.350 31.796 1.00 25.17 C -ATOM 1948 CD1 TYR A 262 -2.604 -33.061 32.501 1.00 21.56 C -ATOM 1949 CD2 TYR A 262 -3.159 -31.368 30.913 1.00 32.68 C -ATOM 1950 CE1 TYR A 262 -1.248 -32.785 32.330 1.00 28.66 C -ATOM 1951 CE2 TYR A 262 -1.802 -31.079 30.741 1.00 24.26 C -ATOM 1952 CZ TYR A 262 -0.855 -31.784 31.449 1.00 29.01 C -ATOM 1953 OH TYR A 262 0.468 -31.450 31.285 1.00 26.50 O -ATOM 1954 N TYR A 263 -7.042 -33.622 29.559 1.00 22.32 N -ATOM 1955 CA TYR A 263 -7.335 -33.906 28.175 1.00 30.67 C -ATOM 1956 C TYR A 263 -8.337 -32.893 27.616 1.00 32.19 C -ATOM 1957 O TYR A 263 -8.975 -32.135 28.353 1.00 24.76 O -ATOM 1958 CB TYR A 263 -7.857 -35.363 28.104 1.00 25.45 C -ATOM 1959 CG TYR A 263 -9.175 -35.513 28.819 1.00 36.72 C -ATOM 1960 CD1 TYR A 263 -10.316 -35.199 28.093 1.00 42.51 C -ATOM 1961 CD2 TYR A 263 -9.207 -35.844 30.165 1.00 40.64 C -ATOM 1962 CE1 TYR A 263 -11.539 -35.174 28.691 1.00 50.49 C -ATOM 1963 CE2 TYR A 263 -10.438 -35.822 30.778 1.00 36.33 C -ATOM 1964 CZ TYR A 263 -11.580 -35.477 30.032 1.00 50.61 C -ATOM 1965 OH TYR A 263 -12.823 -35.358 30.642 1.00 80.92 O -ATOM 1966 N GLY A 264 -8.571 -32.889 26.313 1.00 25.91 N -ATOM 1967 CA GLY A 264 -9.496 -31.983 25.661 1.00 21.27 C -ATOM 1968 C GLY A 264 -9.816 -32.541 24.276 1.00 23.07 C -ATOM 1969 O GLY A 264 -9.062 -33.344 23.705 1.00 25.86 O -ATOM 1970 N LEU A 265 -10.947 -32.088 23.794 1.00 23.56 N -ATOM 1971 CA LEU A 265 -11.537 -32.566 22.562 1.00 26.65 C -ATOM 1972 C LEU A 265 -12.237 -31.344 21.956 1.00 27.04 C -ATOM 1973 O LEU A 265 -13.041 -30.658 22.628 1.00 23.67 O -ATOM 1974 CB LEU A 265 -12.584 -33.655 22.879 1.00 27.27 C -ATOM 1975 CG LEU A 265 -12.649 -34.995 22.175 1.00 60.41 C -ATOM 1976 CD1 LEU A 265 -12.763 -34.816 20.658 1.00 50.33 C -ATOM 1977 CD2 LEU A 265 -11.395 -35.779 22.546 1.00 66.28 C -ATOM 1978 N GLY A 266 -11.951 -31.022 20.694 1.00 24.66 N -ATOM 1979 CA GLY A 266 -12.640 -29.907 20.061 1.00 28.90 C -ATOM 1980 C GLY A 266 -12.729 -30.028 18.549 1.00 30.41 C -ATOM 1981 O GLY A 266 -12.123 -30.912 17.929 1.00 27.92 O -ATOM 1982 N ALA A 267 -13.472 -29.113 17.964 1.00 24.95 N -ATOM 1983 CA ALA A 267 -13.627 -29.097 16.532 1.00 33.88 C -ATOM 1984 C ALA A 267 -13.626 -27.690 16.016 1.00 31.63 C -ATOM 1985 O ALA A 267 -13.943 -26.760 16.764 1.00 24.94 O -ATOM 1986 CB ALA A 267 -14.947 -29.688 16.119 1.00 24.74 C -ATOM 1987 N SER A 268 -13.311 -27.544 14.737 1.00 29.24 N -ATOM 1988 CA SER A 268 -13.505 -26.275 14.076 1.00 25.82 C -ATOM 1989 C SER A 268 -14.077 -26.503 12.695 1.00 31.52 C -ATOM 1990 O SER A 268 -13.861 -27.550 12.082 1.00 28.68 O -ATOM 1991 CB SER A 268 -12.188 -25.504 13.964 1.00 24.92 C -ATOM 1992 OG SER A 268 -11.044 -26.303 13.739 1.00 39.59 O -ATOM 1993 N TYR A 269 -14.763 -25.494 12.230 1.00 26.59 N -ATOM 1994 CA TYR A 269 -15.364 -25.502 10.940 1.00 25.66 C -ATOM 1995 C TYR A 269 -14.905 -24.252 10.228 1.00 25.81 C -ATOM 1996 O TYR A 269 -15.202 -23.132 10.648 1.00 25.05 O -ATOM 1997 CB TYR A 269 -16.841 -25.513 11.147 1.00 23.54 C -ATOM 1998 CG TYR A 269 -17.518 -25.612 9.808 1.00 33.37 C -ATOM 1999 CD1 TYR A 269 -17.639 -26.848 9.204 1.00 29.64 C -ATOM 2000 CD2 TYR A 269 -17.940 -24.462 9.180 1.00 39.37 C -ATOM 2001 CE1 TYR A 269 -18.189 -26.926 7.938 1.00 52.56 C -ATOM 2002 CE2 TYR A 269 -18.482 -24.534 7.916 1.00 51.57 C -ATOM 2003 CZ TYR A 269 -18.605 -25.768 7.301 1.00 58.86 C -ATOM 2004 OH TYR A 269 -19.150 -25.833 6.027 1.00 61.25 O -ATOM 2005 N ASP A 270 -14.225 -24.389 9.114 1.00 22.56 N -ATOM 2006 CA ASP A 270 -13.728 -23.239 8.392 1.00 20.61 C -ATOM 2007 C ASP A 270 -14.818 -22.578 7.539 1.00 29.68 C -ATOM 2008 O ASP A 270 -15.426 -23.238 6.697 1.00 34.39 O -ATOM 2009 CB ASP A 270 -12.550 -23.739 7.549 1.00 24.95 C -ATOM 2010 CG ASP A 270 -11.686 -22.678 6.877 1.00 33.53 C -ATOM 2011 OD1 ASP A 270 -12.079 -21.518 6.858 1.00 33.68 O -ATOM 2012 OD2 ASP A 270 -10.599 -23.005 6.391 1.00 54.40 O -ATOM 2013 N LEU A 271 -15.094 -21.291 7.724 1.00 24.09 N -ATOM 2014 CA LEU A 271 -16.068 -20.546 6.940 1.00 21.32 C -ATOM 2015 C LEU A 271 -15.387 -19.861 5.747 1.00 23.96 C -ATOM 2016 O LEU A 271 -16.039 -19.186 4.965 1.00 23.54 O -ATOM 2017 CB LEU A 271 -16.718 -19.450 7.764 1.00 19.85 C -ATOM 2018 CG LEU A 271 -17.482 -19.817 9.037 1.00 23.59 C -ATOM 2019 CD1 LEU A 271 -18.005 -18.566 9.724 1.00 24.13 C -ATOM 2020 CD2 LEU A 271 -18.614 -20.710 8.684 1.00 25.97 C -ATOM 2021 N GLY A 272 -14.077 -19.917 5.657 1.00 21.11 N -ATOM 2022 CA GLY A 272 -13.297 -19.265 4.646 1.00 20.61 C -ATOM 2023 C GLY A 272 -13.020 -17.808 4.960 1.00 23.49 C -ATOM 2024 O GLY A 272 -13.642 -17.214 5.841 1.00 26.07 O -ATOM 2025 N GLY A 273 -12.048 -17.183 4.294 1.00 16.10 N -ATOM 2026 CA GLY A 273 -11.850 -15.758 4.404 1.00 15.88 C -ATOM 2027 C GLY A 273 -11.120 -15.370 5.693 1.00 23.40 C -ATOM 2028 O GLY A 273 -10.858 -14.193 5.896 1.00 24.50 O -ATOM 2029 N GLY A 274 -10.716 -16.337 6.529 1.00 27.38 N -ATOM 2030 CA GLY A 274 -10.024 -16.087 7.796 1.00 27.44 C -ATOM 2031 C GLY A 274 -10.951 -16.319 9.003 1.00 31.13 C -ATOM 2032 O GLY A 274 -10.559 -15.962 10.109 1.00 26.17 O -ATOM 2033 N ALA A 275 -12.150 -16.880 8.849 1.00 21.61 N -ATOM 2034 CA ALA A 275 -13.084 -17.081 9.935 1.00 21.23 C -ATOM 2035 C ALA A 275 -13.397 -18.550 10.106 1.00 31.65 C -ATOM 2036 O ALA A 275 -13.438 -19.304 9.129 1.00 22.67 O -ATOM 2037 CB ALA A 275 -14.384 -16.338 9.664 1.00 16.02 C -ATOM 2038 N SER A 276 -13.567 -19.003 11.350 1.00 19.43 N -ATOM 2039 CA SER A 276 -13.933 -20.370 11.654 1.00 19.76 C -ATOM 2040 C SER A 276 -14.798 -20.406 12.926 1.00 25.83 C -ATOM 2041 O SER A 276 -14.736 -19.480 13.750 1.00 23.50 O -ATOM 2042 CB SER A 276 -12.659 -21.228 11.821 1.00 21.87 C -ATOM 2043 OG SER A 276 -11.650 -20.655 12.638 1.00 34.39 O -ATOM 2044 N ILE A 277 -15.679 -21.387 13.049 1.00 22.23 N -ATOM 2045 CA ILE A 277 -16.508 -21.592 14.227 1.00 22.99 C -ATOM 2046 C ILE A 277 -15.711 -22.641 14.979 1.00 28.21 C -ATOM 2047 O ILE A 277 -15.281 -23.638 14.373 1.00 23.58 O -ATOM 2048 CB ILE A 277 -17.884 -22.116 13.800 1.00 26.04 C -ATOM 2049 CG1 ILE A 277 -18.611 -21.066 13.027 1.00 28.06 C -ATOM 2050 CG2 ILE A 277 -18.730 -22.472 15.023 1.00 24.61 C -ATOM 2051 CD1 ILE A 277 -19.860 -21.684 12.370 1.00 28.49 C -ATOM 2052 N VAL A 278 -15.414 -22.462 16.276 1.00 24.26 N -ATOM 2053 CA VAL A 278 -14.525 -23.365 17.035 1.00 25.14 C -ATOM 2054 C VAL A 278 -15.179 -23.631 18.396 1.00 25.78 C -ATOM 2055 O VAL A 278 -15.724 -22.712 19.016 1.00 23.74 O -ATOM 2056 CB VAL A 278 -13.131 -22.725 17.291 1.00 22.54 C -ATOM 2057 CG1 VAL A 278 -12.205 -23.783 17.813 1.00 18.27 C -ATOM 2058 CG2 VAL A 278 -12.549 -22.120 16.040 1.00 24.97 C -ATOM 2059 N GLY A 279 -15.140 -24.844 18.907 1.00 22.69 N -ATOM 2060 CA GLY A 279 -15.720 -25.165 20.201 1.00 23.27 C -ATOM 2061 C GLY A 279 -14.945 -26.330 20.772 1.00 25.33 C -ATOM 2062 O GLY A 279 -14.236 -27.024 20.031 1.00 26.35 O -ATOM 2063 N GLY A 280 -15.009 -26.605 22.070 1.00 22.79 N -ATOM 2064 CA GLY A 280 -14.234 -27.694 22.641 1.00 23.14 C -ATOM 2065 C GLY A 280 -14.617 -27.915 24.096 1.00 20.25 C -ATOM 2066 O GLY A 280 -15.400 -27.157 24.669 1.00 22.34 O -ATOM 2067 N ILE A 281 -14.043 -28.956 24.637 1.00 18.86 N -ATOM 2068 CA ILE A 281 -14.332 -29.423 25.969 1.00 27.28 C -ATOM 2069 C ILE A 281 -12.965 -29.757 26.547 1.00 24.01 C -ATOM 2070 O ILE A 281 -12.083 -30.231 25.818 1.00 25.84 O -ATOM 2071 CB ILE A 281 -15.335 -30.615 25.721 1.00 34.33 C -ATOM 2072 CG1 ILE A 281 -16.473 -30.269 26.569 1.00 32.29 C -ATOM 2073 CG2 ILE A 281 -14.878 -32.035 26.009 1.00 32.21 C -ATOM 2074 CD1 ILE A 281 -17.453 -29.412 25.782 1.00 41.67 C -ATOM 2075 N ALA A 282 -12.689 -29.490 27.833 1.00 25.05 N -ATOM 2076 CA ALA A 282 -11.411 -29.873 28.421 1.00 21.98 C -ATOM 2077 C ALA A 282 -11.621 -30.175 29.916 1.00 30.82 C -ATOM 2078 O ALA A 282 -12.518 -29.625 30.583 1.00 25.28 O -ATOM 2079 CB ALA A 282 -10.373 -28.757 28.319 1.00 19.90 C -ATOM 2080 N ASP A 283 -10.792 -31.067 30.451 1.00 29.24 N -ATOM 2081 CA ASP A 283 -10.865 -31.448 31.852 1.00 27.15 C -ATOM 2082 C ASP A 283 -9.629 -32.154 32.344 1.00 28.94 C -ATOM 2083 O ASP A 283 -8.650 -32.367 31.612 1.00 25.65 O -ATOM 2084 CB ASP A 283 -12.056 -32.351 32.044 1.00 25.99 C -ATOM 2085 CG ASP A 283 -12.651 -32.316 33.442 1.00 44.57 C -ATOM 2086 OD1 ASP A 283 -12.188 -31.605 34.358 1.00 33.69 O -ATOM 2087 OD2 ASP A 283 -13.632 -33.032 33.566 1.00 35.12 O -ATOM 2088 N ASN A 284 -9.624 -32.469 33.630 1.00 25.13 N -ATOM 2089 CA ASN A 284 -8.575 -33.323 34.132 1.00 24.84 C -ATOM 2090 C ASN A 284 -9.281 -34.178 35.168 1.00 32.53 C -ATOM 2091 O ASN A 284 -10.446 -33.966 35.501 1.00 27.71 O -ATOM 2092 CB ASN A 284 -7.428 -32.531 34.784 1.00 22.73 C -ATOM 2093 CG ASN A 284 -7.841 -31.655 35.937 1.00 35.10 C -ATOM 2094 OD1 ASN A 284 -8.594 -32.043 36.830 1.00 32.48 O -ATOM 2095 ND2 ASN A 284 -7.398 -30.419 35.956 1.00 26.62 N -ATOM 2096 N ASP A 285 -8.571 -35.160 35.662 1.00 26.45 N -ATOM 2097 CA ASP A 285 -9.119 -36.062 36.668 1.00 41.39 C -ATOM 2098 C ASP A 285 -8.918 -35.651 38.136 1.00 38.31 C -ATOM 2099 O ASP A 285 -9.037 -36.477 39.045 1.00 41.71 O -ATOM 2100 CB ASP A 285 -8.515 -37.458 36.442 1.00 22.77 C -ATOM 2101 CG ASP A 285 -7.018 -37.619 36.682 1.00 23.18 C -ATOM 2102 OD1 ASP A 285 -6.299 -36.642 36.961 1.00 33.04 O -ATOM 2103 OD2 ASP A 285 -6.564 -38.760 36.574 1.00 41.33 O -ATOM 2104 N LEU A 286 -8.522 -34.433 38.464 1.00 31.53 N -ATOM 2105 CA LEU A 286 -8.375 -34.096 39.864 1.00 25.13 C -ATOM 2106 C LEU A 286 -9.781 -34.072 40.470 1.00 41.07 C -ATOM 2107 O LEU A 286 -10.786 -33.987 39.738 1.00 43.63 O -ATOM 2108 CB LEU A 286 -7.705 -32.751 39.998 1.00 27.21 C -ATOM 2109 CG LEU A 286 -6.270 -32.835 39.611 1.00 27.72 C -ATOM 2110 CD1 LEU A 286 -5.760 -31.443 39.694 1.00 35.20 C -ATOM 2111 CD2 LEU A 286 -5.476 -33.794 40.484 1.00 33.80 C -ATOM 2112 N PRO A 287 -9.877 -34.225 41.816 1.00 72.08 N -ATOM 2113 CA PRO A 287 -11.137 -34.283 42.564 1.00 57.25 C -ATOM 2114 C PRO A 287 -12.204 -33.202 42.339 1.00 55.50 C -ATOM 2115 O PRO A 287 -13.372 -33.508 42.071 1.00 64.32 O -ATOM 2116 CB PRO A 287 -10.653 -34.366 44.012 1.00 64.34 C -ATOM 2117 CG PRO A 287 -9.230 -33.836 43.996 1.00 69.23 C -ATOM 2118 CD PRO A 287 -8.755 -34.511 42.729 1.00 60.19 C -ATOM 2119 N ASN A 288 -11.828 -31.922 42.497 1.00 54.09 N -ATOM 2120 CA ASN A 288 -12.770 -30.799 42.318 1.00 73.15 C -ATOM 2121 C ASN A 288 -13.272 -30.582 40.876 1.00 74.10 C -ATOM 2122 O ASN A 288 -14.484 -30.447 40.665 1.00 75.41 O -ATOM 2123 CB ASN A 288 -12.090 -29.477 42.876 1.00 81.36 C -ATOM 2124 CG ASN A 288 -12.242 -28.127 42.121 1.00 97.42 C -ATOM 2125 OD1 ASN A 288 -13.325 -27.546 41.955 1.00 97.46 O -ATOM 2126 ND2 ASN A 288 -11.144 -27.539 41.643 1.00101.92 N -ATOM 2127 N SER A 289 -12.316 -30.570 39.928 1.00 69.19 N -ATOM 2128 CA SER A 289 -12.486 -30.226 38.533 1.00 50.17 C -ATOM 2129 C SER A 289 -13.769 -30.567 37.808 1.00 43.85 C -ATOM 2130 O SER A 289 -14.129 -31.734 37.591 1.00 46.69 O -ATOM 2131 CB SER A 289 -11.310 -30.821 37.778 1.00 52.12 C -ATOM 2132 OG SER A 289 -10.127 -30.246 38.340 1.00 71.82 O -ATOM 2133 N ASP A 290 -14.474 -29.478 37.467 1.00 38.06 N -ATOM 2134 CA ASP A 290 -15.638 -29.592 36.585 1.00 44.01 C -ATOM 2135 C ASP A 290 -15.048 -29.256 35.203 1.00 33.18 C -ATOM 2136 O ASP A 290 -14.076 -28.504 35.098 1.00 32.33 O -ATOM 2137 CB ASP A 290 -16.736 -28.563 36.815 1.00 56.50 C -ATOM 2138 CG ASP A 290 -16.866 -28.005 38.221 1.00 77.24 C -ATOM 2139 OD1 ASP A 290 -16.176 -27.018 38.549 1.00 84.59 O -ATOM 2140 OD2 ASP A 290 -17.688 -28.568 38.949 1.00 73.57 O -ATOM 2141 N MET A 291 -15.650 -29.801 34.153 1.00 36.97 N -ATOM 2142 CA MET A 291 -15.240 -29.609 32.773 1.00 34.70 C -ATOM 2143 C MET A 291 -15.491 -28.176 32.316 1.00 26.12 C -ATOM 2144 O MET A 291 -16.588 -27.636 32.596 1.00 28.32 O -ATOM 2145 CB MET A 291 -16.046 -30.548 31.941 1.00 33.14 C -ATOM 2146 CG MET A 291 -15.721 -30.633 30.469 1.00 52.66 C -ATOM 2147 SD MET A 291 -17.054 -31.586 29.705 1.00 48.22 S -ATOM 2148 CE MET A 291 -18.376 -30.408 29.816 1.00 41.88 C -ATOM 2149 N VAL A 292 -14.461 -27.601 31.653 1.00 30.89 N -ATOM 2150 CA VAL A 292 -14.602 -26.296 30.995 1.00 28.79 C -ATOM 2151 C VAL A 292 -15.001 -26.548 29.519 1.00 27.78 C -ATOM 2152 O VAL A 292 -14.798 -27.642 28.964 1.00 23.47 O -ATOM 2153 CB VAL A 292 -13.278 -25.451 31.060 1.00 21.26 C -ATOM 2154 CG1 VAL A 292 -13.068 -25.121 32.513 1.00 24.54 C -ATOM 2155 CG2 VAL A 292 -12.062 -26.151 30.493 1.00 17.97 C -ATOM 2156 N ALA A 293 -15.630 -25.598 28.853 1.00 24.90 N -ATOM 2157 CA ALA A 293 -16.075 -25.765 27.478 1.00 28.34 C -ATOM 2158 C ALA A 293 -16.194 -24.388 26.843 1.00 31.62 C -ATOM 2159 O ALA A 293 -16.271 -23.380 27.571 1.00 21.58 O -ATOM 2160 CB ALA A 293 -17.455 -26.411 27.425 1.00 21.46 C -ATOM 2161 N ASP A 294 -16.208 -24.253 25.507 1.00 20.79 N -ATOM 2162 CA ASP A 294 -16.521 -22.962 24.906 1.00 18.22 C -ATOM 2163 C ASP A 294 -17.085 -23.151 23.509 1.00 23.81 C -ATOM 2164 O ASP A 294 -16.994 -24.277 22.981 1.00 21.81 O -ATOM 2165 CB ASP A 294 -15.275 -22.092 24.862 1.00 16.80 C -ATOM 2166 CG ASP A 294 -14.135 -22.482 23.933 1.00 28.79 C -ATOM 2167 OD1 ASP A 294 -14.298 -23.157 22.922 1.00 23.51 O -ATOM 2168 OD2 ASP A 294 -13.027 -22.066 24.222 1.00 20.09 O -ATOM 2169 N LEU A 295 -17.630 -22.092 22.934 1.00 22.29 N -ATOM 2170 CA LEU A 295 -18.156 -22.143 21.590 1.00 23.66 C -ATOM 2171 C LEU A 295 -18.129 -20.735 21.068 1.00 20.00 C -ATOM 2172 O LEU A 295 -18.736 -19.833 21.657 1.00 18.17 O -ATOM 2173 CB LEU A 295 -19.584 -22.665 21.597 1.00 22.86 C -ATOM 2174 CG LEU A 295 -20.239 -22.727 20.174 1.00 36.71 C -ATOM 2175 CD1 LEU A 295 -19.494 -23.716 19.279 1.00 28.60 C -ATOM 2176 CD2 LEU A 295 -21.662 -23.194 20.270 1.00 32.46 C -ATOM 2177 N GLY A 296 -17.427 -20.481 19.963 1.00 17.67 N -ATOM 2178 CA GLY A 296 -17.406 -19.135 19.432 1.00 17.33 C -ATOM 2179 C GLY A 296 -16.815 -19.125 18.034 1.00 21.99 C -ATOM 2180 O GLY A 296 -16.764 -20.163 17.371 1.00 20.73 O -ATOM 2181 N VAL A 297 -16.360 -17.965 17.591 1.00 23.91 N -ATOM 2182 CA VAL A 297 -15.762 -17.790 16.259 1.00 24.04 C -ATOM 2183 C VAL A 297 -14.373 -17.194 16.384 1.00 27.04 C -ATOM 2184 O VAL A 297 -14.139 -16.389 17.291 1.00 20.84 O -ATOM 2185 CB VAL A 297 -16.662 -16.873 15.351 1.00 20.97 C -ATOM 2186 CG1 VAL A 297 -17.934 -17.628 15.031 1.00 27.35 C -ATOM 2187 CG2 VAL A 297 -17.101 -15.596 16.010 1.00 23.73 C -ATOM 2188 N LYS A 298 -13.401 -17.578 15.569 1.00 18.69 N -ATOM 2189 CA LYS A 298 -12.053 -17.027 15.608 1.00 16.67 C -ATOM 2190 C LYS A 298 -11.825 -16.348 14.264 1.00 23.47 C -ATOM 2191 O LYS A 298 -12.314 -16.874 13.261 1.00 24.58 O -ATOM 2192 CB LYS A 298 -11.017 -18.111 15.770 1.00 19.12 C -ATOM 2193 CG LYS A 298 -10.986 -18.627 17.195 1.00 21.33 C -ATOM 2194 CD LYS A 298 -10.117 -19.822 17.223 1.00 18.34 C -ATOM 2195 CE LYS A 298 -8.728 -19.349 17.070 1.00 21.34 C -ATOM 2196 NZ LYS A 298 -7.845 -20.499 17.110 1.00 30.35 N -ATOM 2197 N PHE A 299 -11.150 -15.210 14.187 1.00 18.24 N -ATOM 2198 CA PHE A 299 -10.953 -14.448 12.960 1.00 17.66 C -ATOM 2199 C PHE A 299 -9.485 -14.163 12.794 1.00 26.51 C -ATOM 2200 O PHE A 299 -8.769 -13.944 13.784 1.00 22.18 O -ATOM 2201 CB PHE A 299 -11.681 -13.135 13.055 1.00 14.69 C -ATOM 2202 CG PHE A 299 -13.179 -13.199 13.267 1.00 21.01 C -ATOM 2203 CD1 PHE A 299 -13.978 -14.058 12.533 1.00 22.78 C -ATOM 2204 CD2 PHE A 299 -13.765 -12.359 14.185 1.00 20.84 C -ATOM 2205 CE1 PHE A 299 -15.346 -14.077 12.712 1.00 23.54 C -ATOM 2206 CE2 PHE A 299 -15.137 -12.388 14.348 1.00 22.22 C -ATOM 2207 CZ PHE A 299 -15.934 -13.240 13.619 1.00 21.26 C -ATOM 2208 N LYS A 300 -8.952 -14.173 11.593 1.00 17.76 N -ATOM 2209 CA LYS A 300 -7.572 -13.787 11.346 1.00 17.46 C -ATOM 2210 C LYS A 300 -7.649 -12.631 10.356 1.00 24.16 C -ATOM 2211 O LYS A 300 -8.564 -12.607 9.499 1.00 26.46 O -ATOM 2212 CB LYS A 300 -6.813 -14.912 10.727 1.00 22.55 C -ATOM 2213 CG LYS A 300 -6.657 -16.072 11.650 1.00 34.41 C -ATOM 2214 CD LYS A 300 -5.385 -16.857 11.324 1.00 54.10 C -ATOM 2215 CE LYS A 300 -5.453 -17.720 10.063 1.00 75.73 C -ATOM 2216 NZ LYS A 300 -4.221 -18.486 9.901 1.00 84.85 N -ATOM 2217 N PHE A 301 -6.747 -11.655 10.457 1.00 19.50 N -ATOM 2218 CA PHE A 301 -6.819 -10.437 9.678 1.00 18.21 C -ATOM 2219 C PHE A 301 -5.466 -10.102 9.104 1.00 22.86 C -ATOM 2220 O PHE A 301 -4.454 -10.631 9.571 1.00 17.64 O -ATOM 2221 CB PHE A 301 -7.251 -9.193 10.471 1.00 18.80 C -ATOM 2222 CG PHE A 301 -8.614 -9.367 11.100 1.00 24.96 C -ATOM 2223 CD1 PHE A 301 -9.760 -9.256 10.344 1.00 18.68 C -ATOM 2224 CD2 PHE A 301 -8.718 -9.610 12.461 1.00 23.97 C -ATOM 2225 CE1 PHE A 301 -11.019 -9.379 10.920 1.00 19.16 C -ATOM 2226 CE2 PHE A 301 -9.983 -9.730 13.030 1.00 19.39 C -ATOM 2227 CZ PHE A 301 -11.135 -9.616 12.275 1.00 20.43 C -ATOM 2228 OXT PHE A 301 -5.445 -9.316 8.144 1.00 28.38 O -TER 2229 PHE A 301 -HETATM 2230 CA CA A 302 5.011 -23.190 25.968 1.00 21.26 CA -HETATM 2231 CA CA A 303 -2.860 -23.590 25.053 1.00 18.82 CA -HETATM 2232 CA CA A 304 19.713 -10.305 32.535 1.00 19.02 CA -HETATM 2233 C1 C8E A 545 8.213 -29.709 34.111 0.88 42.96 C -HETATM 2234 C2 C8E A 545 7.552 -28.411 34.504 0.88 41.67 C -HETATM 2235 C3 C8E A 545 6.087 -28.660 34.394 0.88 42.57 C -HETATM 2236 C4 C8E A 545 5.485 -27.321 34.709 0.88 43.55 C -HETATM 2237 C5 C8E A 545 4.152 -27.105 34.003 0.88 44.03 C -HETATM 2238 C6 C8E A 545 3.097 -28.172 34.277 0.88 42.16 C -HETATM 2239 C7 C8E A 545 1.680 -27.738 33.857 0.88 39.75 C -HETATM 2240 C8 C8E A 545 0.806 -28.916 34.194 0.88 37.75 C -HETATM 2241 O9 C8E A 545 -0.600 -28.806 34.267 0.88 38.94 O -HETATM 2242 C10 C8E A 545 -1.108 -29.343 35.484 0.88 40.72 C -HETATM 2243 C11 C8E A 545 -2.584 -29.539 35.411 0.88 45.43 C -HETATM 2244 O12 C8E A 545 -3.364 -29.456 36.593 0.88 54.18 O -HETATM 2245 C13 C8E A 545 -3.888 -28.142 36.821 0.88 63.79 C -HETATM 2246 C14 C8E A 545 -3.546 -27.475 38.160 0.88 72.45 C -HETATM 2247 O15 C8E A 545 -3.840 -28.181 39.385 0.88 79.05 O -HETATM 2248 C16 C8E A 545 -4.714 -27.481 40.299 0.88 84.79 C -HETATM 2249 C17 C8E A 545 -6.141 -28.045 40.520 0.88 88.54 C -HETATM 2250 O18 C8E A 545 -6.994 -27.791 41.671 0.88 91.31 O -HETATM 2251 C19 C8E A 545 -6.710 -28.672 42.798 0.88 93.11 C -HETATM 2252 C20 C8E A 545 -7.835 -29.597 43.315 0.88 93.71 C -HETATM 2253 O21 C8E A 545 -8.715 -29.939 42.235 0.88 93.34 O -HETATM 2254 C1 C8E A 546 -16.910 -30.948 20.987 0.83 50.61 C -HETATM 2255 C2 C8E A 546 -17.003 -29.492 20.487 0.83 51.77 C -HETATM 2256 C3 C8E A 546 -18.226 -28.681 20.944 0.83 50.98 C -HETATM 2257 C4 C8E A 546 -18.230 -28.157 22.386 0.83 51.13 C -HETATM 2258 C5 C8E A 546 -19.478 -27.295 22.528 0.83 52.63 C -HETATM 2259 C6 C8E A 546 -19.775 -26.873 23.954 0.83 55.60 C -HETATM 2260 C7 C8E A 546 -21.264 -26.522 24.126 0.83 60.07 C -HETATM 2261 C8 C8E A 546 -21.652 -25.072 23.799 0.83 64.27 C -HETATM 2262 O9 C8E A 546 -23.025 -24.744 23.463 0.83 66.21 O -HETATM 2263 C10 C8E A 546 -23.879 -24.185 24.492 0.83 66.45 C -HETATM 2264 C11 C8E A 546 -24.241 -22.690 24.589 0.83 65.91 C -HETATM 2265 O12 C8E A 546 -25.371 -22.371 25.423 0.83 65.26 O -HETATM 2266 C13 C8E A 546 -25.072 -21.784 26.706 0.83 65.04 C -HETATM 2267 C14 C8E A 546 -25.775 -20.508 27.231 0.83 64.60 C -HETATM 2268 O15 C8E A 546 -25.456 -19.172 26.782 0.83 63.35 O -HETATM 2269 C16 C8E A 546 -25.077 -18.304 27.864 0.83 61.87 C -HETATM 2270 C17 C8E A 546 -25.057 -16.798 27.655 0.83 60.37 C -HETATM 2271 O18 C8E A 546 -24.686 -15.946 28.736 0.83 60.64 O -HETATM 2272 C19 C8E A 546 -25.722 -14.991 28.972 0.83 62.75 C -HETATM 2273 C20 C8E A 546 -26.625 -15.182 30.187 0.83 65.74 C -HETATM 2274 O21 C8E A 546 -27.717 -14.265 30.253 0.83 68.59 O -HETATM 2275 C1 C8E A 547 -27.555 -14.778 24.966 0.69 53.41 C -HETATM 2276 C2 C8E A 547 -26.516 -15.667 24.244 0.69 52.85 C -HETATM 2277 C3 C8E A 547 -25.613 -14.788 23.406 0.69 51.32 C -HETATM 2278 C4 C8E A 547 -24.590 -15.611 22.646 0.69 50.00 C -HETATM 2279 C5 C8E A 547 -23.742 -14.660 21.812 0.69 48.73 C -HETATM 2280 C6 C8E A 547 -22.770 -15.402 20.910 0.69 49.05 C -HETATM 2281 C7 C8E A 547 -21.887 -14.406 20.188 0.69 50.17 C -HETATM 2282 C8 C8E A 547 -20.855 -15.059 19.282 0.69 51.75 C -HETATM 2283 O9 C8E A 547 -21.254 -15.638 18.040 0.69 53.80 O -HETATM 2284 C10 C8E A 547 -20.727 -16.961 17.815 0.69 55.39 C -HETATM 2285 C11 C8E A 547 -21.412 -18.239 18.340 0.69 57.31 C -HETATM 2286 O12 C8E A 547 -20.997 -19.520 17.825 0.69 59.43 O -HETATM 2287 C13 C8E A 547 -21.900 -20.072 16.839 0.69 62.71 C -HETATM 2288 C14 C8E A 547 -21.762 -19.847 15.315 0.69 66.12 C -HETATM 2289 O15 C8E A 547 -21.863 -18.520 14.749 0.69 68.53 O -HETATM 2290 C16 C8E A 547 -21.503 -18.438 13.354 0.69 69.38 C -HETATM 2291 C17 C8E A 547 -22.432 -17.855 12.267 0.69 69.19 C -HETATM 2292 O18 C8E A 547 -23.574 -18.559 11.772 0.69 69.55 O -HETATM 2293 C19 C8E A 547 -23.224 -19.417 10.680 0.69 71.17 C -HETATM 2294 C20 C8E A 547 -23.699 -19.093 9.256 0.69 73.02 C -HETATM 2295 O21 C8E A 547 -23.190 -19.997 8.271 0.69 74.35 O -HETATM 2296 C1 C8E A 548 8.635 -40.960 22.015 0.66 38.33 C -HETATM 2297 C2 C8E A 548 7.129 -40.823 22.217 0.66 39.82 C -HETATM 2298 C3 C8E A 548 6.553 -41.828 23.201 0.66 42.86 C -HETATM 2299 C4 C8E A 548 5.132 -41.410 23.650 0.66 46.04 C -HETATM 2300 C5 C8E A 548 4.404 -42.484 24.470 0.66 48.47 C -HETATM 2301 C6 C8E A 548 3.158 -42.049 25.250 0.66 49.60 C -HETATM 2302 C7 C8E A 548 1.937 -41.675 24.427 0.66 50.98 C -HETATM 2303 C8 C8E A 548 0.665 -42.117 25.157 0.66 53.35 C -HETATM 2304 O9 C8E A 548 0.300 -41.619 26.461 0.66 56.73 O -HETATM 2305 C10 C8E A 548 -1.055 -41.115 26.530 0.66 60.75 C -HETATM 2306 C11 C8E A 548 -1.893 -41.075 27.835 0.66 64.78 C -HETATM 2307 O12 C8E A 548 -2.307 -42.251 28.554 0.66 68.03 O -HETATM 2308 C13 C8E A 548 -3.602 -42.750 28.183 0.66 70.92 C -HETATM 2309 C14 C8E A 548 -4.589 -43.152 29.296 0.66 73.54 C -HETATM 2310 O15 C8E A 548 -5.324 -42.194 30.083 0.66 75.50 O -HETATM 2311 C16 C8E A 548 -6.755 -42.418 30.010 0.66 77.12 C -HETATM 2312 C17 C8E A 548 -7.846 -41.611 30.782 0.66 78.17 C -HETATM 2313 O18 C8E A 548 -8.228 -40.241 30.482 0.66 78.30 O -HETATM 2314 C19 C8E A 548 -9.532 -40.067 29.908 0.66 78.18 C -HETATM 2315 C20 C8E A 548 -9.622 -39.737 28.426 0.66 78.11 C -HETATM 2316 O21 C8E A 548 -10.967 -39.509 28.017 0.66 79.53 O -HETATM 2317 O HOH A 305 6.190 -23.830 27.989 1.00 20.83 O -HETATM 2318 O HOH A 306 -2.513 -6.904 20.688 1.00 16.79 O -HETATM 2319 O HOH A 307 3.039 -23.016 24.751 1.00 20.86 O -HETATM 2320 O HOH A 308 17.950 -13.715 34.357 1.00 19.18 O -HETATM 2321 O HOH A 309 -4.859 -6.074 21.898 1.00 17.25 O -HETATM 2322 O HOH A 310 6.039 -11.790 23.498 1.00 19.05 O -HETATM 2323 O HOH A 311 18.294 -13.615 30.404 1.00 18.03 O -HETATM 2324 O HOH A 312 4.466 -25.396 25.736 1.00 18.77 O -HETATM 2325 O HOH A 313 -6.309 -26.069 24.210 1.00 19.97 O -HETATM 2326 O HOH A 314 19.069 -8.882 30.781 1.00 16.16 O -HETATM 2327 O HOH A 315 18.817 -16.108 33.989 1.00 22.41 O -HETATM 2328 O HOH A 316 10.011 -23.278 25.760 1.00 19.18 O -HETATM 2329 O HOH A 317 18.991 -18.503 7.840 1.00 26.78 O -HETATM 2330 O HOH A 318 -7.473 -27.703 26.057 1.00 23.41 O -HETATM 2331 O HOH A 319 -13.465 -11.566 27.451 1.00 17.66 O -HETATM 2332 O HOH A 320 11.714 -25.598 25.532 1.00 19.10 O -HETATM 2333 O HOH A 321 13.702 -8.194 22.282 1.00 17.80 O -HETATM 2334 O HOH A 322 -2.605 -12.728 24.049 1.00 21.07 O -HETATM 2335 O HOH A 323 -7.669 -27.382 30.103 1.00 21.64 O -HETATM 2336 O HOH A 324 8.492 -23.381 29.404 1.00 23.75 O -HETATM 2337 O HOH A 325 -11.446 -14.377 24.890 1.00 23.49 O -HETATM 2338 O HOH A 326 -7.805 -13.385 19.252 1.00 21.15 O -HETATM 2339 O HOH A 327 -1.282 -22.004 25.223 1.00 26.61 O -HETATM 2340 O HOH A 328 10.411 -16.311 26.801 1.00 17.22 O -HETATM 2341 O HOH A 329 16.385 -22.562 27.462 1.00 18.42 O -HETATM 2342 O HOH A 330 15.053 -19.043 24.819 1.00 21.28 O -HETATM 2343 O HOH A 331 -2.033 -23.630 22.810 1.00 20.17 O -HETATM 2344 O HOH A 332 16.071 -18.702 16.398 1.00 23.35 O -HETATM 2345 O HOH A 333 11.348 -6.919 22.129 1.00 20.95 O -HETATM 2346 O HOH A 334 10.900 -18.006 19.817 1.00 19.73 O -HETATM 2347 O HOH A 335 2.111 -8.782 11.097 1.00 21.76 O -HETATM 2348 O HOH A 336 15.747 -19.876 27.405 1.00 21.38 O -HETATM 2349 O HOH A 337 8.435 0.102 28.114 1.00 20.97 O -HETATM 2350 O HOH A 338 14.119 -13.294 35.691 1.00 24.59 O -HETATM 2351 O HOH A 339 3.274 -23.071 27.583 1.00 22.54 O -HETATM 2352 O HOH A 340 3.727 -5.504 27.684 1.00 30.10 O -HETATM 2353 O HOH A 341 20.299 -15.296 4.898 1.00 27.64 O -HETATM 2354 O HOH A 342 -7.206 -29.986 29.888 1.00 24.28 O -HETATM 2355 O HOH A 343 -7.959 -18.152 20.294 1.00 28.57 O -HETATM 2356 O HOH A 344 8.762 -4.598 30.296 1.00 31.66 O -HETATM 2357 O HOH A 345 -7.654 -16.035 18.504 1.00 27.53 O -HETATM 2358 O HOH A 346 5.672 -25.355 30.536 1.00 33.44 O -HETATM 2359 O HOH A 347 7.619 -6.968 7.308 1.00 28.72 O -HETATM 2360 O HOH A 348 12.106 -27.183 47.407 1.00 24.32 O -HETATM 2361 O HOH A 349 0.478 -23.170 21.728 1.00 32.87 O -HETATM 2362 O HOH A 350 18.157 -15.935 6.506 1.00 25.47 O -HETATM 2363 O HOH A 351 12.279 -17.795 29.840 1.00 20.42 O -HETATM 2364 O HOH A 352 14.939 -10.637 35.420 1.00 23.31 O -HETATM 2365 O HOH A 353 -17.331 -18.796 32.329 1.00 28.26 O -HETATM 2366 O HOH A 354 -10.692 -19.212 6.721 1.00 31.00 O -HETATM 2367 O HOH A 355 -10.459 -12.836 28.783 1.00 28.25 O -HETATM 2368 O HOH A 356 -11.477 -26.875 19.463 1.00 29.65 O -HETATM 2369 O HOH A 357 16.141 -3.886 4.277 1.00 31.85 O -HETATM 2370 O HOH A 358 4.524 -23.752 21.031 1.00 29.74 O -HETATM 2371 O HOH A 359 -10.030 -18.674 11.768 1.00 26.75 O -HETATM 2372 O HOH A 360 -24.381 -19.610 33.507 1.00 42.24 O -HETATM 2373 O HOH A 361 0.000 0.000 29.011 1.00 48.27 O -HETATM 2374 O HOH A 362 4.589 -24.630 46.774 1.00 32.73 O -HETATM 2375 O HOH A 363 6.578 -32.633 49.463 1.00 37.66 O -HETATM 2376 O HOH A 364 25.694 -6.688 4.569 1.00 40.03 O -HETATM 2377 O HOH A 365 1.755 -2.930 26.627 1.00 29.16 O -HETATM 2378 O HOH A 366 -5.526 -19.104 20.325 1.00 43.77 O -HETATM 2379 O HOH A 367 -7.843 -16.280 15.397 1.00 34.97 O -HETATM 2380 O HOH A 368 19.857 -29.108 43.670 1.00 37.84 O -HETATM 2381 O HOH A 369 -11.211 -17.107 28.043 1.00 35.39 O -HETATM 2382 O HOH A 370 14.990 0.034 26.464 1.00 36.44 O -HETATM 2383 O HOH A 371 -8.092 -22.145 19.499 1.00 36.57 O -HETATM 2384 O HOH A 372 10.405 -22.698 48.281 1.00 43.83 O -HETATM 2385 O HOH A 373 11.850 -23.603 46.017 1.00 33.68 O -HETATM 2386 O HOH A 374 4.425 -11.538 20.182 1.00 35.76 O -HETATM 2387 O HOH A 375 7.444 -13.328 21.435 1.00 32.10 O -HETATM 2388 O HOH A 376 -2.266 -33.722 16.734 1.00 27.51 O -HETATM 2389 O HOH A 377 6.830 -21.304 30.790 1.00 40.21 O -HETATM 2390 O HOH A 378 -2.927 -15.540 24.275 1.00 47.68 O -HETATM 2391 O HOH A 379 -10.545 -20.059 28.206 1.00 34.03 O -HETATM 2392 O HOH A 380 -1.346 -12.314 13.279 1.00 43.15 O -HETATM 2393 O HOH A 381 13.767 -31.917 11.168 1.00 41.20 O -HETATM 2394 O HOH A 382 17.255 -3.976 35.357 1.00 36.40 O -HETATM 2395 O HOH A 383 0.396 -4.333 6.326 1.00 39.85 O -HETATM 2396 O HOH A 384 -12.123 -22.655 35.807 1.00 48.67 O -HETATM 2397 O HOH A 385 23.092 -24.324 40.946 1.00 47.58 O -HETATM 2398 O HOH A 386 25.532 -15.924 6.357 1.00 40.32 O -HETATM 2399 O HOH A 387 13.903 -23.443 52.205 1.00 38.71 O -HETATM 2400 O HOH A 388 0.585 -6.342 28.179 1.00 38.73 O -HETATM 2401 O HOH A 389 -6.137 -17.395 25.246 1.00 39.55 O -HETATM 2402 O HOH A 390 -11.281 -26.866 9.706 1.00 44.19 O -HETATM 2403 O HOH A 391 15.765 -28.449 56.448 1.00 44.93 O -HETATM 2404 O HOH A 392 9.171 -8.256 34.890 1.00 41.01 O -HETATM 2405 O HOH A 393 -6.013 -32.205 10.535 1.00 37.42 O -HETATM 2406 O HOH A 394 18.746 -31.079 42.115 1.00 49.33 O -HETATM 2407 O HOH A 395 6.332 -11.876 18.420 1.00 53.49 O -HETATM 2408 O HOH A 396 8.026 -2.478 31.687 1.00 46.06 O -HETATM 2409 O HOH A 397 -0.055 -34.380 47.695 1.00 50.52 O -HETATM 2410 O HOH A 398 21.271 -25.134 5.337 1.00 44.63 O -HETATM 2411 O HOH A 399 -9.488 -22.353 13.924 1.00 46.80 O -HETATM 2412 O HOH A 400 15.734 -19.165 9.159 1.00 56.53 O -HETATM 2413 O HOH A 401 2.338 -26.278 18.066 1.00 41.82 O -HETATM 2414 O HOH A 402 10.433 -23.644 51.740 1.00 40.08 O -HETATM 2415 O HOH A 403 12.597 -21.278 37.850 1.00 51.56 O -HETATM 2416 O HOH A 404 -25.186 -24.967 30.656 1.00 54.32 O -HETATM 2417 O HOH A 405 18.299 -6.839 40.824 1.00 44.63 O -HETATM 2418 O HOH A 406 4.650 -23.154 18.361 1.00 75.55 O -HETATM 2419 O HOH A 407 -0.008 -4.901 30.754 1.00 49.18 O -HETATM 2420 O HOH A 408 1.872 -33.925 49.640 1.00 57.48 O -HETATM 2421 O HOH A 409 7.040 -24.438 17.754 1.00 42.07 O -HETATM 2422 O HOH A 410 -3.254 -13.637 11.943 1.00 48.26 O -HETATM 2423 O HOH A 411 18.028 -20.224 9.740 1.00 48.76 O -HETATM 2424 O HOH A 412 25.458 -8.685 6.151 1.00 61.69 O -HETATM 2425 O HOH A 413 12.316 1.336 29.307 1.00 45.17 O -HETATM 2426 O HOH A 414 -12.699 -18.312 34.507 1.00 42.63 O -HETATM 2427 O HOH A 415 16.663 -21.820 11.396 1.00 53.03 O -HETATM 2428 O HOH A 416 7.348 -12.211 28.736 1.00 39.48 O -HETATM 2429 O HOH A 417 10.478 -12.015 14.973 1.00 46.65 O -HETATM 2430 O HOH A 418 -5.879 -30.859 46.808 1.00 48.30 O -HETATM 2431 O HOH A 419 13.821 -10.350 6.801 1.00 53.86 O -HETATM 2432 O HOH A 420 10.873 -19.767 38.963 1.00 68.06 O -HETATM 2433 O HOH A 421 -3.553 -27.075 16.792 1.00 49.89 O -HETATM 2434 O HOH A 422 -4.659 -28.801 12.842 1.00 61.39 O -HETATM 2435 O HOH A 423 4.059 -19.738 23.834 1.00 57.43 O -HETATM 2436 O HOH A 424 0.410 -28.151 30.141 1.00 41.42 O -HETATM 2437 O HOH A 425 7.366 -39.760 38.638 1.00 50.68 O -HETATM 2438 O HOH A 426 1.421 -2.870 29.704 1.00 45.66 O -HETATM 2439 O HOH A 427 -7.977 -18.799 13.558 1.00 51.14 O -HETATM 2440 O HOH A 428 -9.936 -18.793 30.658 1.00 40.22 O -HETATM 2441 O HOH A 429 -0.583 -26.657 18.732 1.00 42.31 O -HETATM 2442 O HOH A 430 9.412 -14.531 34.411 1.00 46.27 O -HETATM 2443 O HOH A 431 -11.155 -17.058 32.393 1.00 49.31 O -HETATM 2444 O HOH A 432 4.672 -9.906 30.002 1.00 51.14 O -HETATM 2445 O HOH A 433 9.764 -22.104 43.517 1.00 61.72 O -HETATM 2446 O HOH A 434 3.091 -25.536 29.792 1.00 54.50 O -HETATM 2447 O HOH A 435 -3.234 -19.131 23.927 1.00 48.27 O -HETATM 2448 O HOH A 436 7.747 -11.972 31.658 1.00 44.09 O -HETATM 2449 O HOH A 437 -21.260 -27.979 29.311 1.00 52.83 O -HETATM 2450 O HOH A 438 -3.320 -15.277 14.229 1.00 60.95 O -HETATM 2451 O HOH A 439 -3.236 -23.883 48.320 1.00 57.64 O -HETATM 2452 O HOH A 440 6.985 -0.498 5.672 1.00 55.03 O -HETATM 2453 O HOH A 441 13.244 -18.776 16.145 1.00 47.33 O -HETATM 2454 O HOH A 442 12.435 -24.416 49.444 1.00 42.38 O -HETATM 2455 O HOH A 443 11.545 -34.010 48.466 1.00 47.66 O -HETATM 2456 O HOH A 444 7.079 -16.967 24.430 1.00 44.53 O -HETATM 2457 O HOH A 445 -13.286 -27.152 39.025 1.00 62.40 O -HETATM 2458 O HOH A 446 5.906 -18.733 19.699 1.00 74.18 O -HETATM 2459 O HOH A 447 23.374 -11.624 43.898 1.00 50.06 O -HETATM 2460 O HOH A 448 8.721 0.013 30.916 1.00 39.51 O -HETATM 2461 O HOH A 449 -3.066 -8.233 6.997 1.00 53.63 O -HETATM 2462 O HOH A 450 -7.364 -20.734 29.488 1.00 37.68 O -HETATM 2463 O HOH A 451 5.654 -12.347 12.613 1.00 53.20 O -HETATM 2464 O HOH A 452 -8.412 -26.868 14.398 1.00 47.15 O -HETATM 2465 O HOH A 453 4.183 -22.036 46.452 1.00 58.11 O -HETATM 2466 O HOH A 454 -16.832 -30.212 5.669 1.00 66.31 O -HETATM 2467 O HOH A 455 18.868 -33.707 4.064 1.00 70.96 O -HETATM 2468 O HOH A 456 -3.664 -39.512 36.539 1.00 51.90 O -HETATM 2469 O HOH A 457 27.016 -12.573 5.049 1.00 76.94 O -HETATM 2470 O HOH A 458 -25.119 -23.325 33.171 1.00 75.09 O -HETATM 2471 O HOH A 459 -1.458 -7.896 28.585 1.00 56.50 O -HETATM 2472 O HOH A 460 11.504 -38.042 43.991 1.00 45.95 O -HETATM 2473 O HOH A 461 -11.171 -18.623 1.902 1.00 59.14 O -HETATM 2474 O HOH A 462 10.010 -10.532 10.832 1.00 52.16 O -HETATM 2475 O HOH A 463 13.737 -7.752 35.913 1.00 35.27 O -HETATM 2476 O HOH A 464 25.692 -15.689 34.348 1.00 67.65 O -HETATM 2477 O HOH A 465 15.408 -35.291 2.794 1.00 73.43 O -HETATM 2478 O HOH A 466 8.907 -34.814 48.496 1.00 57.98 O -HETATM 2479 O HOH A 467 4.516 -34.612 49.401 1.00 72.32 O -HETATM 2480 O HOH A 468 -9.019 -15.380 28.445 1.00 70.17 O -HETATM 2481 O HOH A 469 -10.223 -12.395 26.157 1.00 36.34 O -HETATM 2482 O HOH A 470 -5.859 -25.485 16.336 1.00 56.33 O -HETATM 2483 O HOH A 471 13.126 -33.897 4.119 1.00 75.50 O -HETATM 2484 O HOH A 472 -1.899 -19.466 26.293 1.00 66.81 O -HETATM 2485 O HOH A 473 -5.232 -26.610 46.500 1.00 54.10 O -HETATM 2486 O HOH A 474 3.194 -39.452 42.635 1.00 58.95 O -HETATM 2487 O HOH A 475 5.417 -19.041 32.998 1.00 64.71 O -HETATM 2488 O HOH A 476 -5.159 -20.076 27.294 1.00 53.66 O -HETATM 2489 O HOH A 477 -7.560 -20.565 33.886 1.00 74.59 O -HETATM 2490 O HOH A 478 14.733 -29.399 8.426 1.00 52.60 O -HETATM 2491 O HOH A 479 12.989 -5.891 3.303 1.00 73.28 O -HETATM 2492 O HOH A 480 11.888 -4.745 37.090 1.00 79.45 O -HETATM 2493 O HOH A 481 -9.719 -33.018 3.473 1.00 79.74 O -HETATM 2494 O HOH A 482 -4.477 -30.281 44.408 1.00 55.45 O -HETATM 2495 O HOH A 483 23.282 -4.364 40.147 1.00 62.96 O -HETATM 2496 O HOH A 484 -2.579 -20.233 21.451 1.00 54.07 O -HETATM 2497 O HOH A 485 -0.965 -23.721 18.378 1.00 69.32 O -HETATM 2498 O HOH A 486 4.489 -3.984 31.120 1.00 70.03 O -HETATM 2499 O HOH A 487 8.811 -22.700 16.234 1.00 66.77 O -HETATM 2500 O HOH A 488 2.660 -12.859 10.427 1.00 58.10 O -HETATM 2501 O HOH A 489 -1.387 -22.273 29.103 1.00 65.27 O -HETATM 2502 O HOH A 490 -24.219 -16.069 32.703 1.00 56.86 O -HETATM 2503 O HOH A 491 13.243 -24.599 13.470 1.00 56.42 O -HETATM 2504 O HOH A 492 12.805 -39.013 36.774 1.00 56.25 O -HETATM 2505 O HOH A 493 -9.880 -19.986 9.385 1.00 49.66 O -HETATM 2506 O HOH A 494 13.601 -14.414 38.762 1.00 62.01 O -HETATM 2507 O HOH A 495 -3.474 -42.227 33.006 1.00 61.29 O -HETATM 2508 O HOH A 496 10.775 -20.406 17.335 1.00 61.82 O -HETATM 2509 O HOH A 497 -16.983 -22.582 4.035 1.00 81.82 O -HETATM 2510 O HOH A 498 -0.061 -32.045 16.343 1.00 52.03 O -HETATM 2511 O HOH A 499 1.700 -8.945 27.927 1.00 55.91 O -HETATM 2512 O HOH A 500 6.985 -35.205 10.094 1.00 54.60 O -HETATM 2513 O HOH A 501 -18.744 -29.204 33.911 1.00 62.48 O -HETATM 2514 O HOH A 502 -3.013 -32.508 44.619 1.00 56.15 O -HETATM 2515 O HOH A 503 -9.599 -26.433 17.708 1.00 47.52 O -HETATM 2516 O HOH A 504 23.100 -23.126 5.577 1.00 66.96 O -HETATM 2517 O HOH A 505 -9.245 -18.936 35.479 1.00 88.14 O -HETATM 2518 O HOH A 506 2.537 -11.203 26.087 1.00 70.57 O -HETATM 2519 O HOH A 507 25.103 -27.995 42.947 1.00 77.52 O -HETATM 2520 O HOH A 508 10.413 -40.233 37.531 1.00 68.06 O -HETATM 2521 O HOH A 509 -0.334 -29.010 17.030 1.00 60.83 O -HETATM 2522 O HOH A 510 -9.223 -11.719 6.742 1.00 43.72 O -HETATM 2523 O HOH A 511 -1.417 -2.836 32.189 1.00 64.23 O -HETATM 2524 O HOH A 512 2.862 -14.652 12.746 1.00 67.86 O -HETATM 2525 O HOH A 513 -1.741 -11.688 16.055 1.00 48.46 O -HETATM 2526 O HOH A 514 1.544 -22.784 46.295 1.00 58.53 O -HETATM 2527 O HOH A 515 18.967 -28.869 46.391 1.00 49.61 O -HETATM 2528 O HOH A 516 18.900 -1.671 35.946 1.00 63.03 O -HETATM 2529 O HOH A 517 25.588 -9.757 43.162 1.00 70.54 O -HETATM 2530 O HOH A 518 -5.187 -16.800 15.371 1.00 71.25 O -HETATM 2531 O HOH A 519 23.680 -16.891 38.002 1.00 49.95 O -HETATM 2532 O HOH A 520 22.376 -19.370 38.400 1.00 48.64 O -HETATM 2533 O HOH A 521 3.024 -14.199 16.344 1.00 66.81 O -HETATM 2534 O HOH A 522 -20.871 -27.856 37.688 1.00 77.42 O -HETATM 2535 O HOH A 523 14.349 -31.425 53.433 1.00 76.39 O -HETATM 2536 O HOH A 524 25.962 -3.949 39.123 1.00 73.03 O -HETATM 2537 O HOH A 525 -1.900 -17.739 19.749 1.00 77.39 O -HETATM 2538 O HOH A 526 15.300 -15.636 5.977 1.00 67.58 O -HETATM 2539 O HOH A 527 14.023 -21.234 12.521 1.00 62.67 O -HETATM 2540 O HOH A 528 -2.577 -33.369 47.317 1.00 67.32 O -HETATM 2541 O HOH A 529 3.580 -21.150 21.484 1.00 76.35 O -HETATM 2542 O HOH A 530 13.429 -0.224 31.429 1.00 66.81 O -HETATM 2543 O HOH A 531 24.396 -18.463 40.400 1.00 71.46 O -HETATM 2544 O HOH A 532 8.064 -11.657 35.360 1.00 79.97 O -HETATM 2545 O HOH A 533 4.163 -19.214 29.519 1.00 65.18 O -HETATM 2546 O HOH A 534 16.247 -4.931 40.302 1.00 66.98 O -HETATM 2547 O HOH A 535 -12.361 -20.969 33.706 1.00 57.49 O -HETATM 2548 O HOH A 536 2.542 -10.157 8.311 1.00 63.19 O -HETATM 2549 O HOH A 537 -10.391 -21.350 3.340 1.00 61.09 O -HETATM 2550 O HOH A 538 22.816 -29.263 43.850 1.00 71.51 O -HETATM 2551 O HOH A 539 1.548 -32.124 14.108 1.00 65.27 O -HETATM 2552 O HOH A 540 4.442 -14.466 22.488 1.00 66.67 O -HETATM 2553 O HOH A 541 14.949 -15.727 9.137 1.00 57.15 O -HETATM 2554 O HOH A 542 -3.841 -17.336 21.933 1.00 73.37 O -HETATM 2555 O HOH A 543 0.148 -1.579 25.046 1.00 57.28 O -HETATM 2556 O HOH A 544 1.772 -33.983 12.170 1.00 64.62 O -HETATM 2557 O HOH A 549 -17.923 -26.775 15.606 1.00 45.08 O -HETATM 2558 O HOH A 550 23.530 -24.401 25.957 1.00 57.73 O -HETATM 2559 O HOH A 551 26.759 -24.207 11.635 1.00 54.12 O -HETATM 2560 O HOH A 552 23.462 -20.651 22.231 1.00 49.12 O -HETATM 2561 O HOH A 553 -23.391 -27.104 30.643 1.00 53.13 O -HETATM 2562 O HOH A 554 3.998 -44.799 28.989 1.00 65.70 O -HETATM 2563 O HOH A 555 -8.344 -38.052 23.422 1.00 51.43 O -HETATM 2564 O HOH A 556 -19.689 -30.737 11.462 1.00 74.75 O -HETATM 2565 O HOH A 557 23.241 -22.420 24.265 1.00 58.01 O -HETATM 2566 O HOH A 558 20.793 -38.159 27.686 1.00 76.00 O -HETATM 2567 O HOH A 559 25.724 -26.198 13.506 1.00 63.30 O -HETATM 2568 O HOH A 560 28.575 -20.254 8.172 1.00 78.96 O -HETATM 2569 O HOH A 561 -6.785 -38.481 21.333 1.00 56.46 O -HETATM 2570 O HOH A 562 -8.442 -40.548 13.066 1.00 74.14 O -HETATM 2571 O HOH A 563 5.420 -44.518 31.307 1.00 72.99 O -HETATM 2572 O HOH A 564 -9.958 -37.743 18.331 1.00 62.33 O -HETATM 2573 O HOH A 565 -18.589 -32.618 15.228 1.00 72.81 O -HETATM 2574 O HOH A 566 18.004 -36.417 16.015 1.00 60.73 O -HETATM 2575 O HOH A 567 -20.827 -28.396 26.744 1.00 60.68 O -HETATM 2576 O HOH A 568 18.980 -40.765 25.192 1.00 66.66 O -HETATM 2577 O HOH A 569 20.580 -34.799 24.845 1.00 69.04 O -HETATM 2578 O HOH A 570 -9.200 -42.458 17.427 1.00 71.01 O -HETATM 2579 O HOH A 571 9.238 -44.707 26.611 1.00 69.97 O -HETATM 2580 O HOH A 572 -7.335 -42.291 15.281 1.00 83.29 O -HETATM 2581 O HOH A 573 -23.107 -27.093 18.628 1.00 74.27 O -HETATM 2582 O HOH A 574 -4.629 -42.624 14.481 1.00 69.37 O -HETATM 2583 O HOH A 575 20.398 -33.206 22.405 1.00 58.19 O -HETATM 2584 O HOH A 576 -9.431 -37.868 15.541 1.00 74.36 O -HETATM 2585 O HOH A 577 -17.338 -34.648 10.071 1.00 89.58 O -HETATM 2586 O HOH A 578 22.986 -33.974 26.496 1.00 75.72 O -HETATM 2587 O HOH A 579 22.497 -27.333 27.869 1.00 68.59 O -HETATM 2588 O HOH A 580 -10.506 -37.902 25.211 1.00 58.90 O -HETATM 2589 O HOH A 581 5.670 -43.729 27.194 1.00 69.01 O -HETATM 2590 O HOH A 582 -22.243 -24.640 11.035 1.00 82.74 O -CONECT 590 2230 -CONECT 591 2230 -CONECT 693 2231 -CONECT 694 2231 -CONECT 709 2231 -CONECT 710 2231 -CONECT 744 2231 -CONECT 752 2231 -CONECT 807 2230 -CONECT 871 2232 -CONECT 1014 2232 -CONECT 1015 2232 -CONECT 1023 2232 -CONECT 1039 2232 -CONECT 2230 590 591 807 2317 -CONECT 2230 2319 2324 2351 -CONECT 2231 693 694 709 710 -CONECT 2231 744 752 2339 2343 -CONECT 2232 871 1014 1015 1023 -CONECT 2232 1039 2326 -CONECT 2233 2234 -CONECT 2234 2233 2235 -CONECT 2235 2234 2236 -CONECT 2236 2235 2237 -CONECT 2237 2236 2238 -CONECT 2238 2237 2239 -CONECT 2239 2238 2240 -CONECT 2240 2239 2241 -CONECT 2241 2240 2242 -CONECT 2242 2241 2243 -CONECT 2243 2242 2244 -CONECT 2244 2243 2245 -CONECT 2245 2244 2246 -CONECT 2246 2245 2247 -CONECT 2247 2246 2248 -CONECT 2248 2247 2249 -CONECT 2249 2248 2250 -CONECT 2250 2249 2251 -CONECT 2251 2250 2252 -CONECT 2252 2251 2253 -CONECT 2253 2252 -CONECT 2254 2255 -CONECT 2255 2254 2256 -CONECT 2256 2255 2257 -CONECT 2257 2256 2258 -CONECT 2258 2257 2259 -CONECT 2259 2258 2260 -CONECT 2260 2259 2261 -CONECT 2261 2260 2262 -CONECT 2262 2261 2263 -CONECT 2263 2262 2264 -CONECT 2264 2263 2265 -CONECT 2265 2264 2266 -CONECT 2266 2265 2267 -CONECT 2267 2266 2268 -CONECT 2268 2267 2269 -CONECT 2269 2268 2270 -CONECT 2270 2269 2271 -CONECT 2271 2270 2272 -CONECT 2272 2271 2273 -CONECT 2273 2272 2274 -CONECT 2274 2273 -CONECT 2275 2276 -CONECT 2276 2275 2277 -CONECT 2277 2276 2278 -CONECT 2278 2277 2279 -CONECT 2279 2278 2280 -CONECT 2280 2279 2281 -CONECT 2281 2280 2282 -CONECT 2282 2281 2283 -CONECT 2283 2282 2284 -CONECT 2284 2283 2285 -CONECT 2285 2284 2286 -CONECT 2286 2285 2287 -CONECT 2287 2286 2288 -CONECT 2288 2287 2289 -CONECT 2289 2288 2290 -CONECT 2290 2289 2291 -CONECT 2291 2290 2292 -CONECT 2292 2291 2293 -CONECT 2293 2292 2294 -CONECT 2294 2293 2295 -CONECT 2295 2294 -CONECT 2296 2297 -CONECT 2297 2296 2298 -CONECT 2298 2297 2299 -CONECT 2299 2298 2300 -CONECT 2300 2299 2301 -CONECT 2301 2300 2302 -CONECT 2302 2301 2303 -CONECT 2303 2302 2304 -CONECT 2304 2303 2305 -CONECT 2305 2304 2306 -CONECT 2306 2305 2307 -CONECT 2307 2306 2308 -CONECT 2308 2307 2309 -CONECT 2309 2308 2310 -CONECT 2310 2309 2311 -CONECT 2311 2310 2312 -CONECT 2312 2311 2313 -CONECT 2313 2312 2314 -CONECT 2314 2313 2315 -CONECT 2315 2314 2316 -CONECT 2316 2315 -CONECT 2317 2230 -CONECT 2319 2230 -CONECT 2324 2230 -CONECT 2326 2232 -CONECT 2339 2231 -CONECT 2343 2231 -CONECT 2351 2230 -MASTER 438 4 7 3 17 17 9 6 2589 1 111 24 -END diff --git a/mode/examples/Demos/Graphics/Ribbons/data/4HHB.pdb b/mode/examples/Demos/Graphics/Ribbons/data/4HHB.pdb deleted file mode 100644 index 8a55a2886..000000000 --- a/mode/examples/Demos/Graphics/Ribbons/data/4HHB.pdb +++ /dev/null @@ -1,5991 +0,0 @@ -HEADER OXYGEN TRANSPORT 07-MAR-84 4HHB -TITLE THE CRYSTAL STRUCTURE OF HUMAN DEOXYHAEMOGLOBIN AT 1.74 -TITLE 2 ANGSTROMS RESOLUTION -COMPND MOL_ID: 1; -COMPND 2 MOLECULE: HEMOGLOBIN (DEOXY) (ALPHA CHAIN); -COMPND 3 CHAIN: A, C; -COMPND 4 ENGINEERED: YES; -COMPND 5 MOL_ID: 2; -COMPND 6 MOLECULE: HEMOGLOBIN (DEOXY) (BETA CHAIN); -COMPND 7 CHAIN: B, D; -COMPND 8 ENGINEERED: YES -SOURCE MOL_ID: 1; -SOURCE 2 ORGANISM_SCIENTIFIC: HOMO SAPIENS; -SOURCE 3 ORGANISM_COMMON: HUMAN; -SOURCE 4 ORGANISM_TAXID: 9606; -SOURCE 5 MOL_ID: 2; -SOURCE 6 ORGANISM_SCIENTIFIC: HOMO SAPIENS; -SOURCE 7 ORGANISM_COMMON: HUMAN; -SOURCE 8 ORGANISM_TAXID: 9606 -KEYWDS OXYGEN TRANSPORT -EXPDTA X-RAY DIFFRACTION -AUTHOR G.FERMI,M.F.PERUTZ -REVDAT 4 24-FEB-09 4HHB 1 VERSN -REVDAT 3 01-APR-03 4HHB 1 JRNL -REVDAT 2 15-OCT-89 4HHB 3 MTRIX -REVDAT 1 17-JUL-84 4HHB 0 -SPRSDE 17-JUL-84 4HHB 1HHB -JRNL AUTH G.FERMI,M.F.PERUTZ,B.SHAANAN,R.FOURME -JRNL TITL THE CRYSTAL STRUCTURE OF HUMAN DEOXYHAEMOGLOBIN AT -JRNL TITL 2 1.74 A RESOLUTION -JRNL REF J.MOL.BIOL. V. 175 159 1984 -JRNL REFN ISSN 0022-2836 -JRNL PMID 6726807 -JRNL DOI 10.1016/0022-2836(84)90472-8 -REMARK 1 -REMARK 1 REFERENCE 1 -REMARK 1 AUTH M.F.PERUTZ,S.S.HASNAIN,P.J.DUKE,J.L.SESSLER, -REMARK 1 AUTH 2 J.E.HAHN -REMARK 1 TITL STEREOCHEMISTRY OF IRON IN DEOXYHAEMOGLOBIN -REMARK 1 REF NATURE V. 295 535 1982 -REMARK 1 REFN ISSN 0028-0836 -REMARK 1 REFERENCE 2 -REMARK 1 AUTH G.FERMI,M.F.PERUTZ -REMARK 1 REF HAEMOGLOBIN AND MYOGLOBIN. V. 2 1981 -REMARK 1 REF 2 ATLAS OF MOLECULAR -REMARK 1 REF 3 STRUCTURES IN BIOLOGY -REMARK 1 PUBL OXFORD UNIVERSITY PRESS -REMARK 1 REFN -REMARK 1 REFERENCE 3 -REMARK 1 AUTH M.F.PERUTZ -REMARK 1 TITL REGULATION OF OXYGEN AFFINITY OF HEMOGLOBIN. -REMARK 1 TITL 2 INFLUENCE OF STRUCTURE OF THE GLOBIN ON THE HEME -REMARK 1 TITL 3 IRON -REMARK 1 REF ANNU.REV.BIOCHEM. V. 48 327 1979 -REMARK 1 REFN ISSN 0066-4154 -REMARK 1 REFERENCE 4 -REMARK 1 AUTH L.F.TENEYCK,A.ARNONE -REMARK 1 TITL THREE-DIMENSIONAL FOURIER SYNTHESIS OF HUMAN -REMARK 1 TITL 2 DEOXYHEMOGLOBIN AT 2.5 ANGSTROMS RESOLUTION, -REMARK 1 TITL 3 I.X-RAY ANALYSIS -REMARK 1 REF J.MOL.BIOL. V. 100 3 1976 -REMARK 1 REFN ISSN 0022-2836 -REMARK 1 REFERENCE 5 -REMARK 1 AUTH G.FERMI -REMARK 1 TITL THREE-DIMENSIONAL FOURIER SYNTHESIS OF HUMAN -REMARK 1 TITL 2 DEOXYHAEMOGLOBIN AT 2.5 ANGSTROMS RESOLUTION, -REMARK 1 TITL 3 REFINEMENT OF THE ATOMIC MODEL -REMARK 1 REF J.MOL.BIOL. V. 97 237 1975 -REMARK 1 REFN ISSN 0022-2836 -REMARK 1 REFERENCE 6 -REMARK 1 AUTH H.MUIRHEAD,J.GREER -REMARK 1 TITL THREE-DIMENSIONAL FOURIER SYNTHESIS OF HUMAN -REMARK 1 TITL 2 DEOXYHAEMOGLOBIN AT 3.5 ANGSTROMS RESOLUTION -REMARK 1 REF NATURE V. 228 516 1970 -REMARK 1 REFN ISSN 0028-0836 -REMARK 1 REFERENCE 7 -REMARK 1 EDIT M.O.DAYHOFF -REMARK 1 REF ATLAS OF PROTEIN SEQUENCE V. 5 56 1972 -REMARK 1 REF 2 AND STRUCTURE (DATA SECTION) -REMARK 1 PUBL NATIONAL BIOMEDICAL RESEARCH FOUNDATION, SILVER -REMARK 1 PUBL 2 SPRING,MD. -REMARK 1 REFN -REMARK 1 REFERENCE 8 -REMARK 1 EDIT M.O.DAYHOFF -REMARK 1 REF ATLAS OF PROTEIN SEQUENCE V. 5 64 1972 -REMARK 1 REF 2 AND STRUCTURE (DATA SECTION) -REMARK 1 PUBL NATIONAL BIOMEDICAL RESEARCH FOUNDATION, SILVER -REMARK 1 PUBL 2 SPRING,MD. -REMARK 1 REFN -REMARK 2 -REMARK 2 RESOLUTION. 1.74 ANGSTROMS. -REMARK 3 -REMARK 3 REFINEMENT. -REMARK 3 PROGRAM : NULL -REMARK 3 AUTHORS : NULL -REMARK 3 -REMARK 3 DATA USED IN REFINEMENT. -REMARK 3 RESOLUTION RANGE HIGH (ANGSTROMS) : 1.74 -REMARK 3 RESOLUTION RANGE LOW (ANGSTROMS) : NULL -REMARK 3 DATA CUTOFF (SIGMA(F)) : NULL -REMARK 3 DATA CUTOFF HIGH (ABS(F)) : NULL -REMARK 3 DATA CUTOFF LOW (ABS(F)) : NULL -REMARK 3 COMPLETENESS (WORKING+TEST) (%) : NULL -REMARK 3 NUMBER OF REFLECTIONS : NULL -REMARK 3 -REMARK 3 FIT TO DATA USED IN REFINEMENT. -REMARK 3 CROSS-VALIDATION METHOD : NULL -REMARK 3 FREE R VALUE TEST SET SELECTION : NULL -REMARK 3 R VALUE (WORKING SET) : 0.135 -REMARK 3 FREE R VALUE : NULL -REMARK 3 FREE R VALUE TEST SET SIZE (%) : NULL -REMARK 3 FREE R VALUE TEST SET COUNT : NULL -REMARK 3 ESTIMATED ERROR OF FREE R VALUE : NULL -REMARK 3 -REMARK 3 FIT IN THE HIGHEST RESOLUTION BIN. -REMARK 3 TOTAL NUMBER OF BINS USED : NULL -REMARK 3 BIN RESOLUTION RANGE HIGH (A) : NULL -REMARK 3 BIN RESOLUTION RANGE LOW (A) : NULL -REMARK 3 BIN COMPLETENESS (WORKING+TEST) (%) : NULL -REMARK 3 REFLECTIONS IN BIN (WORKING SET) : NULL -REMARK 3 BIN R VALUE (WORKING SET) : NULL -REMARK 3 BIN FREE R VALUE : NULL -REMARK 3 BIN FREE R VALUE TEST SET SIZE (%) : NULL -REMARK 3 BIN FREE R VALUE TEST SET COUNT : NULL -REMARK 3 ESTIMATED ERROR OF BIN FREE R VALUE : NULL -REMARK 3 -REMARK 3 NUMBER OF NON-HYDROGEN ATOMS USED IN REFINEMENT. -REMARK 3 PROTEIN ATOMS : 4384 -REMARK 3 NUCLEIC ACID ATOMS : 0 -REMARK 3 HETEROGEN ATOMS : 174 -REMARK 3 SOLVENT ATOMS : 221 -REMARK 3 -REMARK 3 B VALUES. -REMARK 3 FROM WILSON PLOT (A**2) : NULL -REMARK 3 MEAN B VALUE (OVERALL, A**2) : NULL -REMARK 3 OVERALL ANISOTROPIC B VALUE. -REMARK 3 B11 (A**2) : NULL -REMARK 3 B22 (A**2) : NULL -REMARK 3 B33 (A**2) : NULL -REMARK 3 B12 (A**2) : NULL -REMARK 3 B13 (A**2) : NULL -REMARK 3 B23 (A**2) : NULL -REMARK 3 -REMARK 3 ESTIMATED COORDINATE ERROR. -REMARK 3 ESD FROM LUZZATI PLOT (A) : NULL -REMARK 3 ESD FROM SIGMAA (A) : NULL -REMARK 3 LOW RESOLUTION CUTOFF (A) : NULL -REMARK 3 -REMARK 3 CROSS-VALIDATED ESTIMATED COORDINATE ERROR. -REMARK 3 ESD FROM C-V LUZZATI PLOT (A) : NULL -REMARK 3 ESD FROM C-V SIGMAA (A) : NULL -REMARK 3 -REMARK 3 RMS DEVIATIONS FROM IDEAL VALUES. -REMARK 3 BOND LENGTHS (A) : NULL -REMARK 3 BOND ANGLES (DEGREES) : NULL -REMARK 3 DIHEDRAL ANGLES (DEGREES) : NULL -REMARK 3 IMPROPER ANGLES (DEGREES) : NULL -REMARK 3 -REMARK 3 ISOTROPIC THERMAL MODEL : NULL -REMARK 3 -REMARK 3 ISOTROPIC THERMAL FACTOR RESTRAINTS. RMS SIGMA -REMARK 3 MAIN-CHAIN BOND (A**2) : NULL ; NULL -REMARK 3 MAIN-CHAIN ANGLE (A**2) : NULL ; NULL -REMARK 3 SIDE-CHAIN BOND (A**2) : NULL ; NULL -REMARK 3 SIDE-CHAIN ANGLE (A**2) : NULL ; NULL -REMARK 3 -REMARK 3 NCS MODEL : NULL -REMARK 3 -REMARK 3 NCS RESTRAINTS. RMS SIGMA/WEIGHT -REMARK 3 GROUP 1 POSITIONAL (A) : NULL ; NULL -REMARK 3 GROUP 1 B-FACTOR (A**2) : NULL ; NULL -REMARK 3 -REMARK 3 PARAMETER FILE 1 : NULL -REMARK 3 TOPOLOGY FILE 1 : NULL -REMARK 3 -REMARK 3 OTHER REFINEMENT REMARKS: THE COORDINATES GIVEN HERE ARE IN -REMARK 3 THE ORTHOGONAL ANGSTROM SYSTEM STANDARD FOR HEMOGLOBINS. THE Y -REMARK 3 AXIS IS THE (NON CRYSTALLOGRAPHIC) MOLECULAR DIAD AND THE X -REMARK 3 AXIS IS THE PSEUDO DIAD WHICH RELATES THE ALPHA-1 AND BETA-1 -REMARK 3 CHAINS. THE TRANSFORMATION GIVEN IN THE *MTRIX* RECORDS BELOW -REMARK 3 WILL GENERATE COORDINATES FOR THE *C* AND *D* CHAINS FROM THE -REMARK 3 *A* AND *B* CHAINS RESPECTIVELY. -REMARK 4 -REMARK 4 4HHB COMPLIES WITH FORMAT V. 3.15, 01-DEC-08 -REMARK 100 -REMARK 100 THIS ENTRY HAS BEEN PROCESSED BY BNL. -REMARK 200 -REMARK 200 EXPERIMENTAL DETAILS -REMARK 200 EXPERIMENT TYPE : X-RAY DIFFRACTION -REMARK 200 DATE OF DATA COLLECTION : NULL -REMARK 200 TEMPERATURE (KELVIN) : NULL -REMARK 200 PH : NULL -REMARK 200 NUMBER OF CRYSTALS USED : NULL -REMARK 200 -REMARK 200 SYNCHROTRON (Y/N) : NULL -REMARK 200 RADIATION SOURCE : NULL -REMARK 200 BEAMLINE : NULL -REMARK 200 X-RAY GENERATOR MODEL : NULL -REMARK 200 MONOCHROMATIC OR LAUE (M/L) : NULL -REMARK 200 WAVELENGTH OR RANGE (A) : NULL -REMARK 200 MONOCHROMATOR : NULL -REMARK 200 OPTICS : NULL -REMARK 200 -REMARK 200 DETECTOR TYPE : NULL -REMARK 200 DETECTOR MANUFACTURER : NULL -REMARK 200 INTENSITY-INTEGRATION SOFTWARE : NULL -REMARK 200 DATA SCALING SOFTWARE : NULL -REMARK 200 -REMARK 200 NUMBER OF UNIQUE REFLECTIONS : NULL -REMARK 200 RESOLUTION RANGE HIGH (A) : NULL -REMARK 200 RESOLUTION RANGE LOW (A) : NULL -REMARK 200 REJECTION CRITERIA (SIGMA(I)) : NULL -REMARK 200 -REMARK 200 OVERALL. -REMARK 200 COMPLETENESS FOR RANGE (%) : NULL -REMARK 200 DATA REDUNDANCY : NULL -REMARK 200 R MERGE (I) : NULL -REMARK 200 R SYM (I) : NULL -REMARK 200 FOR THE DATA SET : NULL -REMARK 200 -REMARK 200 IN THE HIGHEST RESOLUTION SHELL. -REMARK 200 HIGHEST RESOLUTION SHELL, RANGE HIGH (A) : NULL -REMARK 200 HIGHEST RESOLUTION SHELL, RANGE LOW (A) : NULL -REMARK 200 COMPLETENESS FOR SHELL (%) : NULL -REMARK 200 DATA REDUNDANCY IN SHELL : NULL -REMARK 200 R MERGE FOR SHELL (I) : NULL -REMARK 200 R SYM FOR SHELL (I) : NULL -REMARK 200 FOR SHELL : NULL -REMARK 200 -REMARK 200 DIFFRACTION PROTOCOL: NULL -REMARK 200 METHOD USED TO DETERMINE THE STRUCTURE: NULL -REMARK 200 SOFTWARE USED: NULL -REMARK 200 STARTING MODEL: NULL -REMARK 200 -REMARK 200 REMARK: NULL -REMARK 280 -REMARK 280 CRYSTAL -REMARK 280 SOLVENT CONTENT, VS (%): 45.48 -REMARK 280 MATTHEWS COEFFICIENT, VM (ANGSTROMS**3/DA): 2.26 -REMARK 280 -REMARK 280 CRYSTALLIZATION CONDITIONS: NULL -REMARK 290 -REMARK 290 CRYSTALLOGRAPHIC SYMMETRY -REMARK 290 SYMMETRY OPERATORS FOR SPACE GROUP: P 1 21 1 -REMARK 290 -REMARK 290 SYMOP SYMMETRY -REMARK 290 NNNMMM OPERATOR -REMARK 290 1555 X,Y,Z -REMARK 290 2555 -X,Y+1/2,-Z -REMARK 290 -REMARK 290 WHERE NNN -> OPERATOR NUMBER -REMARK 290 MMM -> TRANSLATION VECTOR -REMARK 290 -REMARK 290 CRYSTALLOGRAPHIC SYMMETRY TRANSFORMATIONS -REMARK 290 THE FOLLOWING TRANSFORMATIONS OPERATE ON THE ATOM/HETATM -REMARK 290 RECORDS IN THIS ENTRY TO PRODUCE CRYSTALLOGRAPHICALLY -REMARK 290 RELATED MOLECULES. -REMARK 290 SMTRY1 1 1.000000 0.000000 0.000000 0.00000 -REMARK 290 SMTRY2 1 0.000000 1.000000 0.000000 0.00000 -REMARK 290 SMTRY3 1 0.000000 0.000000 1.000000 0.00000 -REMARK 290 SMTRY1 2 -0.949456 -0.312801 -0.025883 -6.64347 -REMARK 290 SMTRY2 2 -0.312858 0.936202 0.160212 41.12228 -REMARK 290 SMTRY3 2 -0.025884 0.160188 -0.986745 3.40218 -REMARK 290 -REMARK 290 REMARK: NULL -REMARK 300 -REMARK 300 BIOMOLECULE: 1 -REMARK 300 SEE REMARK 350 FOR THE AUTHOR PROVIDED AND/OR PROGRAM -REMARK 300 GENERATED ASSEMBLY INFORMATION FOR THE STRUCTURE IN -REMARK 300 THIS ENTRY. THE REMARK MAY ALSO PROVIDE INFORMATION ON -REMARK 300 BURIED SURFACE AREA. -REMARK 350 -REMARK 350 COORDINATES FOR A COMPLETE MULTIMER REPRESENTING THE KNOWN -REMARK 350 BIOLOGICALLY SIGNIFICANT OLIGOMERIZATION STATE OF THE -REMARK 350 MOLECULE CAN BE GENERATED BY APPLYING BIOMT TRANSFORMATIONS -REMARK 350 GIVEN BELOW. BOTH NON-CRYSTALLOGRAPHIC AND -REMARK 350 CRYSTALLOGRAPHIC OPERATIONS ARE GIVEN. -REMARK 350 -REMARK 350 BIOMOLECULE: 1 -REMARK 350 AUTHOR DETERMINED BIOLOGICAL UNIT: TETRAMERIC -REMARK 350 SOFTWARE DETERMINED QUATERNARY STRUCTURE: TETRAMERIC -REMARK 350 SOFTWARE USED: PISA -REMARK 350 TOTAL BURIED SURFACE AREA: 11630 ANGSTROM**2 -REMARK 350 SURFACE AREA OF THE COMPLEX: 24010 ANGSTROM**2 -REMARK 350 CHANGE IN SOLVENT FREE ENERGY: -98.0 KCAL/MOL -REMARK 350 APPLY THE FOLLOWING TO CHAINS: A, B, C, D -REMARK 350 BIOMT1 1 1.000000 0.000000 0.000000 0.00000 -REMARK 350 BIOMT2 1 0.000000 1.000000 0.000000 0.00000 -REMARK 350 BIOMT3 1 0.000000 0.000000 1.000000 0.00000 -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: CLOSE CONTACTS IN SAME ASYMMETRIC UNIT -REMARK 500 -REMARK 500 THE FOLLOWING ATOMS ARE IN CLOSE CONTACT. -REMARK 500 -REMARK 500 ATM1 RES C SSEQI ATM2 RES C SSEQI DISTANCE -REMARK 500 CB THR D 4 OE2 GLU D 6 2.00 -REMARK 500 NZ LYS D 66 O1A HEM D 148 2.06 -REMARK 500 OD2 ASP D 73 O HOH D 174 2.10 -REMARK 500 OG1 THR D 4 OE2 GLU D 6 2.19 -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: CLOSE CONTACTS -REMARK 500 -REMARK 500 THE FOLLOWING ATOMS THAT ARE RELATED BY CRYSTALLOGRAPHIC -REMARK 500 SYMMETRY ARE IN CLOSE CONTACT. AN ATOM LOCATED WITHIN 0.15 -REMARK 500 ANGSTROMS OF A SYMMETRY RELATED ATOM IS ASSUMED TO BE ON A -REMARK 500 SPECIAL POSITION AND IS, THEREFORE, LISTED IN REMARK 375 -REMARK 500 INSTEAD OF REMARK 500. ATOMS WITH NON-BLANK ALTERNATE -REMARK 500 LOCATION INDICATORS ARE NOT INCLUDED IN THE CALCULATIONS. -REMARK 500 -REMARK 500 DISTANCE CUTOFF: -REMARK 500 2.2 ANGSTROMS FOR CONTACTS NOT INVOLVING HYDROGEN ATOMS -REMARK 500 1.6 ANGSTROMS FOR CONTACTS INVOLVING HYDROGEN ATOMS -REMARK 500 -REMARK 500 ATM1 RES C SSEQI ATM2 RES C SSEQI SSYMOP DISTANCE -REMARK 500 OD2 ASP C 85 O HOH B 204 2657 1.41 -REMARK 500 O HOH B 204 O HOH C 161 2647 2.02 -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: COVALENT BOND LENGTHS -REMARK 500 -REMARK 500 THE STEREOCHEMICAL PARAMETERS OF THE FOLLOWING RESIDUES -REMARK 500 HAVE VALUES WHICH DEVIATE FROM EXPECTED VALUES BY MORE -REMARK 500 THAN 6*RMSD (M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN -REMARK 500 IDENTIFIER; SSEQ=SEQUENCE NUMBER; I=INSERTION CODE). -REMARK 500 -REMARK 500 STANDARD TABLE: -REMARK 500 FORMAT: (10X,I3,1X,2(A3,1X,A1,I4,A1,1X,A4,3X),1X,F6.3) -REMARK 500 -REMARK 500 EXPECTED VALUES PROTEIN: ENGH AND HUBER, 1999 -REMARK 500 EXPECTED VALUES NUCLEIC ACID: CLOWNEY ET AL 1996 -REMARK 500 -REMARK 500 M RES CSSEQI ATM1 RES CSSEQI ATM2 DEVIATION -REMARK 500 VAL A 1 N VAL A 1 CA -0.295 -REMARK 500 VAL A 1 CA VAL A 1 CB 0.299 -REMARK 500 VAL A 1 CB VAL A 1 CG1 -0.206 -REMARK 500 VAL A 1 CB VAL A 1 CG2 -0.283 -REMARK 500 LEU A 2 CA LEU A 2 C 0.249 -REMARK 500 SER A 3 N SER A 3 CA 0.167 -REMARK 500 SER A 3 CB SER A 3 OG -0.132 -REMARK 500 LEU A 2 C SER A 3 N -0.320 -REMARK 500 PRO A 4 N PRO A 4 CA -0.149 -REMARK 500 PRO A 4 CA PRO A 4 CB 0.200 -REMARK 500 SER A 3 C PRO A 4 N 0.282 -REMARK 500 ALA A 5 N ALA A 5 CA -0.130 -REMARK 500 ALA A 5 CA ALA A 5 CB 0.247 -REMARK 500 PRO A 4 C ALA A 5 N 0.257 -REMARK 500 LYS A 7 N LYS A 7 CA 0.157 -REMARK 500 THR A 8 CA THR A 8 CB 0.178 -REMARK 500 THR A 8 CB THR A 8 OG1 -0.173 -REMARK 500 THR A 8 CB THR A 8 CG2 -0.245 -REMARK 500 THR A 8 CA THR A 8 C -0.174 -REMARK 500 LYS A 7 C THR A 8 N 0.258 -REMARK 500 THR A 8 C ASN A 9 N 0.179 -REMARK 500 VAL A 10 CB VAL A 10 CG2 -0.179 -REMARK 500 VAL A 10 CA VAL A 10 C 0.160 -REMARK 500 LYS A 11 N LYS A 11 CA 0.131 -REMARK 500 LYS A 11 CA LYS A 11 CB -0.137 -REMARK 500 LYS A 11 CB LYS A 11 CG -0.196 -REMARK 500 LYS A 11 CG LYS A 11 CD -0.206 -REMARK 500 LYS A 11 CD LYS A 11 CE 0.454 -REMARK 500 ALA A 12 N ALA A 12 CA -0.133 -REMARK 500 ALA A 12 C ALA A 12 O 0.225 -REMARK 500 ALA A 13 CA ALA A 13 C 0.201 -REMARK 500 TRP A 14 CA TRP A 14 CB 0.291 -REMARK 500 TRP A 14 CB TRP A 14 CG -0.274 -REMARK 500 TRP A 14 CG TRP A 14 CD1 0.306 -REMARK 500 TRP A 14 CD1 TRP A 14 NE1 0.158 -REMARK 500 TRP A 14 NE1 TRP A 14 CE2 -0.234 -REMARK 500 TRP A 14 CE2 TRP A 14 CZ2 -0.243 -REMARK 500 TRP A 14 CE2 TRP A 14 CD2 0.221 -REMARK 500 TRP A 14 CH2 TRP A 14 CZ2 -0.217 -REMARK 500 GLY A 15 CA GLY A 15 C 0.182 -REMARK 500 GLY A 15 C GLY A 15 O 0.437 -REMARK 500 LYS A 16 CB LYS A 16 CG 0.164 -REMARK 500 LYS A 16 CG LYS A 16 CD 0.488 -REMARK 500 LYS A 16 CD LYS A 16 CE 0.410 -REMARK 500 LYS A 16 C LYS A 16 O -0.149 -REMARK 500 GLY A 15 C LYS A 16 N -0.418 -REMARK 500 VAL A 17 N VAL A 17 CA -0.191 -REMARK 500 VAL A 17 CA VAL A 17 CB -0.168 -REMARK 500 VAL A 17 CA VAL A 17 C 0.432 -REMARK 500 VAL A 17 C VAL A 17 O -0.483 -REMARK 500 -REMARK 500 THIS ENTRY HAS 1277 BOND DEVIATIONS. -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: COVALENT BOND ANGLES -REMARK 500 -REMARK 500 THE STEREOCHEMICAL PARAMETERS OF THE FOLLOWING RESIDUES -REMARK 500 HAVE VALUES WHICH DEVIATE FROM EXPECTED VALUES BY MORE -REMARK 500 THAN 6*RMSD (M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN -REMARK 500 IDENTIFIER; SSEQ=SEQUENCE NUMBER; I=INSERTION CODE). -REMARK 500 -REMARK 500 STANDARD TABLE: -REMARK 500 FORMAT: (10X,I3,1X,A3,1X,A1,I4,A1,3(1X,A4,2X),12X,F5.1) -REMARK 500 -REMARK 500 EXPECTED VALUES PROTEIN: ENGH AND HUBER, 1999 -REMARK 500 EXPECTED VALUES NUCLEIC ACID: CLOWNEY ET AL 1996 -REMARK 500 -REMARK 500 M RES CSSEQI ATM1 ATM2 ATM3 -REMARK 500 VAL A 1 CG1 - CB - CG2 ANGL. DEV. = 27.5 DEGREES -REMARK 500 VAL A 1 CA - CB - CG2 ANGL. DEV. = -25.9 DEGREES -REMARK 500 LEU A 2 N - CA - CB ANGL. DEV. = -17.9 DEGREES -REMARK 500 LEU A 2 CB - CG - CD1 ANGL. DEV. = 13.0 DEGREES -REMARK 500 LEU A 2 CA - C - O ANGL. DEV. = -21.8 DEGREES -REMARK 500 VAL A 1 CA - C - N ANGL. DEV. = -13.3 DEGREES -REMARK 500 VAL A 1 O - C - N ANGL. DEV. = 12.7 DEGREES -REMARK 500 LEU A 2 C - N - CA ANGL. DEV. = -20.6 DEGREES -REMARK 500 SER A 3 N - CA - CB ANGL. DEV. = -9.7 DEGREES -REMARK 500 SER A 3 CA - C - O ANGL. DEV. = 15.9 DEGREES -REMARK 500 LEU A 2 O - C - N ANGL. DEV. = 30.2 DEGREES -REMARK 500 PRO A 4 CB - CA - C ANGL. DEV. = -30.7 DEGREES -REMARK 500 PRO A 4 CA - CB - CG ANGL. DEV. = -14.9 DEGREES -REMARK 500 PRO A 4 N - CD - CG ANGL. DEV. = -12.4 DEGREES -REMARK 500 SER A 3 O - C - N ANGL. DEV. = -14.6 DEGREES -REMARK 500 PRO A 4 C - N - CA ANGL. DEV. = -14.1 DEGREES -REMARK 500 ALA A 5 CB - CA - C ANGL. DEV. = -10.8 DEGREES -REMARK 500 PRO A 4 O - C - N ANGL. DEV. = -9.9 DEGREES -REMARK 500 ASP A 6 CB - CG - OD1 ANGL. DEV. = 6.5 DEGREES -REMARK 500 ASP A 6 CB - CG - OD2 ANGL. DEV. = -8.8 DEGREES -REMARK 500 LYS A 7 N - CA - CB ANGL. DEV. = -13.5 DEGREES -REMARK 500 LYS A 7 CD - CE - NZ ANGL. DEV. = -27.4 DEGREES -REMARK 500 LYS A 7 N - CA - C ANGL. DEV. = 22.1 DEGREES -REMARK 500 ASP A 6 O - C - N ANGL. DEV. = 14.8 DEGREES -REMARK 500 LYS A 7 C - N - CA ANGL. DEV. = -20.2 DEGREES -REMARK 500 THR A 8 CA - CB - CG2 ANGL. DEV. = -10.7 DEGREES -REMARK 500 THR A 8 CA - C - O ANGL. DEV. = 21.3 DEGREES -REMARK 500 LYS A 7 CA - C - N ANGL. DEV. = -20.1 DEGREES -REMARK 500 THR A 8 C - N - CA ANGL. DEV. = -15.7 DEGREES -REMARK 500 VAL A 10 O - C - N ANGL. DEV. = 11.4 DEGREES -REMARK 500 ALA A 12 CB - CA - C ANGL. DEV. = -29.5 DEGREES -REMARK 500 ALA A 12 N - CA - CB ANGL. DEV. = -14.5 DEGREES -REMARK 500 ALA A 12 C - N - CA ANGL. DEV. = -22.9 DEGREES -REMARK 500 ALA A 12 O - C - N ANGL. DEV. = -25.9 DEGREES -REMARK 500 TRP A 14 CA - CB - CG ANGL. DEV. = -22.4 DEGREES -REMARK 500 TRP A 14 CG - CD1 - NE1 ANGL. DEV. = -13.5 DEGREES -REMARK 500 TRP A 14 CD1 - NE1 - CE2 ANGL. DEV. = 19.8 DEGREES -REMARK 500 TRP A 14 NE1 - CE2 - CZ2 ANGL. DEV. = 11.2 DEGREES -REMARK 500 TRP A 14 CH2 - CZ2 - CE2 ANGL. DEV. = 13.2 DEGREES -REMARK 500 ALA A 13 O - C - N ANGL. DEV. = 13.6 DEGREES -REMARK 500 GLY A 15 N - CA - C ANGL. DEV. = -24.3 DEGREES -REMARK 500 GLY A 15 CA - C - O ANGL. DEV. = -21.6 DEGREES -REMARK 500 GLY A 15 C - N - CA ANGL. DEV. = -19.0 DEGREES -REMARK 500 LYS A 16 N - CA - CB ANGL. DEV. = 14.8 DEGREES -REMARK 500 LYS A 16 CG - CD - CE ANGL. DEV. = -48.6 DEGREES -REMARK 500 LYS A 16 CD - CE - NZ ANGL. DEV. = 17.9 DEGREES -REMARK 500 GLY A 15 CA - C - N ANGL. DEV. = 25.6 DEGREES -REMARK 500 GLY A 15 O - C - N ANGL. DEV. = -10.0 DEGREES -REMARK 500 LYS A 16 C - N - CA ANGL. DEV. = 15.1 DEGREES -REMARK 500 VAL A 17 N - CA - CB ANGL. DEV. = 15.3 DEGREES -REMARK 500 -REMARK 500 THIS ENTRY HAS 1473 ANGLE DEVIATIONS. -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: TORSION ANGLES -REMARK 500 -REMARK 500 TORSION ANGLES OUTSIDE THE EXPECTED RAMACHANDRAN REGIONS: -REMARK 500 (M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN IDENTIFIER; -REMARK 500 SSEQ=SEQUENCE NUMBER; I=INSERTION CODE). -REMARK 500 -REMARK 500 STANDARD TABLE: -REMARK 500 FORMAT:(10X,I3,1X,A3,1X,A1,I4,A1,4X,F7.2,3X,F7.2) -REMARK 500 -REMARK 500 EXPECTED VALUES: GJ KLEYWEGT AND TA JONES (1996). PHI/PSI- -REMARK 500 CHOLOGY: RAMACHANDRAN REVISITED. STRUCTURE 4, 1395 - 1400 -REMARK 500 -REMARK 500 M RES CSSEQI PSI PHI -REMARK 500 SER A 3 -176.01 -60.80 -REMARK 500 LYS A 16 -55.41 -1.55 -REMARK 500 ALA A 21 -76.55 -47.40 -REMARK 500 LEU A 48 40.81 -103.90 -REMARK 500 SER A 52 150.87 -47.80 -REMARK 500 HIS A 122 -70.12 -41.02 -REMARK 500 THR B 4 -176.32 -55.07 -REMARK 500 GLU B 7 -71.39 -64.26 -REMARK 500 PHE B 45 -9.16 -52.07 -REMARK 500 ASN B 80 59.72 -142.35 -REMARK 500 TYR B 145 130.62 -35.71 -REMARK 500 SER C 3 172.94 -57.29 -REMARK 500 VAL C 17 -70.34 -65.44 -REMARK 500 LEU C 48 32.06 -92.63 -REMARK 500 ASP C 75 72.45 -151.27 -REMARK 500 LYS C 90 -77.18 -122.52 -REMARK 500 LEU C 113 71.25 -107.78 -REMARK 500 LEU D 3 -163.80 -100.24 -REMARK 500 ASN D 19 94.43 -63.05 -REMARK 500 GLN D 39 0.49 -67.48 -REMARK 500 SER D 72 -71.73 -40.75 -REMARK 500 ASP D 73 -43.09 -22.67 -REMARK 500 ALA D 76 7.73 -63.28 -REMARK 500 HIS D 77 62.58 -172.71 -REMARK 500 LEU D 78 -50.86 -25.69 -REMARK 500 ASN D 80 85.05 -167.04 -REMARK 500 HIS D 97 35.26 76.08 -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: NON-CIS, NON-TRANS -REMARK 500 -REMARK 500 THE FOLLOWING PEPTIDE BONDS DEVIATE SIGNIFICANTLY FROM BOTH -REMARK 500 CIS AND TRANS CONFORMATION. CIS BONDS, IF ANY, ARE LISTED -REMARK 500 ON CISPEP RECORDS. TRANS IS DEFINED AS 180 +/- 30 AND -REMARK 500 CIS IS DEFINED AS 0 +/- 30 DEGREES. -REMARK 500 MODEL OMEGA -REMARK 500 GLY A 18 ALA A 19 -145.49 -REMARK 500 SER B 49 THR B 50 113.74 -REMARK 500 LEU D 3 THR D 4 148.65 -REMARK 500 VAL D 18 ASN D 19 148.41 -REMARK 500 LEU D 48 SER D 49 -144.37 -REMARK 500 SER D 49 THR D 50 143.57 -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: PLANAR GROUPS -REMARK 500 -REMARK 500 PLANAR GROUPS IN THE FOLLOWING RESIDUES HAVE A TOTAL -REMARK 500 RMS DISTANCE OF ALL ATOMS FROM THE BEST-FIT PLANE -REMARK 500 BY MORE THAN AN EXPECTED VALUE OF 6*RMSD, WITH AN -REMARK 500 RMSD 0.02 ANGSTROMS, OR AT LEAST ONE ATOM HAS -REMARK 500 AN RMSD GREATER THAN THIS VALUE -REMARK 500 (M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN IDENTIFIER; -REMARK 500 SSEQ=SEQUENCE NUMBER; I=INSERTION CODE). -REMARK 500 -REMARK 500 M RES CSSEQI RMS TYPE -REMARK 500 HIS A 20 0.17 SIDE_CHAIN -REMARK 500 GLU A 23 0.25 SIDE_CHAIN -REMARK 500 TYR A 24 0.10 SIDE_CHAIN -REMARK 500 PHE A 36 0.09 SIDE_CHAIN -REMARK 500 HIS A 45 0.11 SIDE_CHAIN -REMARK 500 HIS A 50 0.20 SIDE_CHAIN -REMARK 500 GLN A 54 0.10 SIDE_CHAIN -REMARK 500 ASP A 64 0.14 SIDE_CHAIN -REMARK 500 HIS A 72 0.24 SIDE_CHAIN -REMARK 500 ASN A 78 0.08 SIDE_CHAIN -REMARK 500 ASP A 85 0.09 SIDE_CHAIN -REMARK 500 ARG A 92 0.08 SIDE_CHAIN -REMARK 500 ASP A 126 0.10 SIDE_CHAIN -REMARK 500 ARG A 141 0.08 SIDE_CHAIN -REMARK 500 HIS B 2 0.16 SIDE_CHAIN -REMARK 500 GLU B 6 0.16 SIDE_CHAIN -REMARK 500 ASN B 19 0.08 SIDE_CHAIN -REMARK 500 ASP B 21 0.15 SIDE_CHAIN -REMARK 500 GLU B 22 0.51 SIDE_CHAIN -REMARK 500 GLU B 26 0.38 SIDE_CHAIN -REMARK 500 ASP B 47 0.14 SIDE_CHAIN -REMARK 500 ASP B 52 0.19 SIDE_CHAIN -REMARK 500 HIS B 63 0.11 SIDE_CHAIN -REMARK 500 ASP B 79 0.11 SIDE_CHAIN -REMARK 500 ASN B 80 0.20 SIDE_CHAIN -REMARK 500 GLU B 90 0.15 SIDE_CHAIN -REMARK 500 ARG B 104 0.39 SIDE_CHAIN -REMARK 500 HIS B 117 0.22 SIDE_CHAIN -REMARK 500 PHE B 118 0.13 SIDE_CHAIN -REMARK 500 GLU B 121 0.26 SIDE_CHAIN -REMARK 500 HIS B 143 0.10 SIDE_CHAIN -REMARK 500 HIS B 146 0.31 SIDE_CHAIN -REMARK 500 ASN C 9 0.08 SIDE_CHAIN -REMARK 500 HIS C 20 0.14 SIDE_CHAIN -REMARK 500 GLU C 23 0.30 SIDE_CHAIN -REMARK 500 HIS C 45 0.10 SIDE_CHAIN -REMARK 500 PHE C 46 0.10 SIDE_CHAIN -REMARK 500 ASP C 47 0.15 SIDE_CHAIN -REMARK 500 ASP C 64 0.08 SIDE_CHAIN -REMARK 500 ASP C 75 0.07 SIDE_CHAIN -REMARK 500 ASN C 78 0.11 SIDE_CHAIN -REMARK 500 ARG C 92 0.20 SIDE_CHAIN -REMARK 500 GLU C 116 0.09 SIDE_CHAIN -REMARK 500 ASP C 126 0.11 SIDE_CHAIN -REMARK 500 ARG C 141 0.08 SIDE_CHAIN -REMARK 500 HIS D 2 0.10 SIDE_CHAIN -REMARK 500 GLU D 6 0.17 SIDE_CHAIN -REMARK 500 GLU D 7 0.10 SIDE_CHAIN -REMARK 500 ASN D 19 0.38 SIDE_CHAIN -REMARK 500 ASP D 21 0.18 SIDE_CHAIN -REMARK 500 GLU D 22 0.21 SIDE_CHAIN -REMARK 500 GLU D 26 0.54 SIDE_CHAIN -REMARK 500 ARG D 40 0.12 SIDE_CHAIN -REMARK 500 GLU D 43 0.15 SIDE_CHAIN -REMARK 500 ASP D 52 0.33 SIDE_CHAIN -REMARK 500 HIS D 63 0.18 SIDE_CHAIN -REMARK 500 HIS D 77 0.14 SIDE_CHAIN -REMARK 500 ASP D 79 0.33 SIDE_CHAIN -REMARK 500 GLU D 90 0.34 SIDE_CHAIN -REMARK 500 HIS D 92 0.08 SIDE_CHAIN -REMARK 500 ASP D 94 0.08 SIDE_CHAIN -REMARK 500 GLU D 101 0.10 SIDE_CHAIN -REMARK 500 ARG D 104 0.29 SIDE_CHAIN -REMARK 500 ASN D 108 0.10 SIDE_CHAIN -REMARK 500 HIS D 117 0.08 SIDE_CHAIN -REMARK 500 PHE D 118 0.10 SIDE_CHAIN -REMARK 500 GLU D 121 0.32 SIDE_CHAIN -REMARK 500 GLN D 127 0.07 SIDE_CHAIN -REMARK 500 ASN D 139 0.21 SIDE_CHAIN -REMARK 500 HIS D 143 0.09 SIDE_CHAIN -REMARK 500 HIS D 146 0.10 SIDE_CHAIN -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: MAIN CHAIN PLANARITY -REMARK 500 -REMARK 500 THE FOLLOWING RESIDUES HAVE A PSEUDO PLANARITY -REMARK 500 TORSION, C(I) - CA(I) - N(I+1) - O(I), GREATER -REMARK 500 10.0 DEGREES. (M=MODEL NUMBER; RES=RESIDUE NAME; -REMARK 500 C=CHAIN IDENTIFIER; SSEQ=SEQUENCE NUMBER; -REMARK 500 I=INSERTION CODE). -REMARK 500 -REMARK 500 M RES CSSEQI ANGLE -REMARK 500 VAL A 1 -12.66 -REMARK 500 SER A 3 -13.96 -REMARK 500 PRO A 4 -17.06 -REMARK 500 ASN A 9 10.02 -REMARK 500 LYS A 11 -14.58 -REMARK 500 ALA A 12 -29.94 -REMARK 500 GLY A 15 25.08 -REMARK 500 ALA A 19 -16.87 -REMARK 500 ALA A 21 26.61 -REMARK 500 GLY A 22 15.67 -REMARK 500 THR A 41 10.65 -REMARK 500 PHE A 46 -10.97 -REMARK 500 LEU A 48 -25.01 -REMARK 500 SER A 52 -10.23 -REMARK 500 LYS A 56 14.67 -REMARK 500 GLY A 59 -10.71 -REMARK 500 LYS A 61 -11.09 -REMARK 500 ALA A 63 -17.65 -REMARK 500 ASP A 74 18.25 -REMARK 500 ASP A 75 -17.02 -REMARK 500 MET A 76 -10.23 -REMARK 500 ASN A 78 -10.93 -REMARK 500 SER A 81 -10.91 -REMARK 500 ALA A 82 11.29 -REMARK 500 LEU A 83 -10.53 -REMARK 500 ASP A 85 -12.19 -REMARK 500 ALA A 88 11.87 -REMARK 500 LYS A 90 -14.75 -REMARK 500 ASN A 97 -10.48 -REMARK 500 LYS A 99 -15.40 -REMARK 500 LEU A 101 -10.99 -REMARK 500 LEU A 106 -10.02 -REMARK 500 ALA A 111 10.63 -REMARK 500 PRO A 114 -12.36 -REMARK 500 THR A 118 -18.84 -REMARK 500 HIS A 122 17.52 -REMARK 500 VAL B 1 34.93 -REMARK 500 LEU B 3 14.19 -REMARK 500 THR B 4 -16.98 -REMARK 500 GLU B 7 12.85 -REMARK 500 LEU B 14 12.16 -REMARK 500 ASP B 21 -10.62 -REMARK 500 THR B 38 14.87 -REMARK 500 GLU B 43 -24.15 -REMARK 500 SER B 44 54.71 -REMARK 500 ASP B 47 16.36 -REMARK 500 SER B 49 -74.55 -REMARK 500 GLY B 56 -31.39 -REMARK 500 LYS B 59 -12.59 -REMARK 500 VAL B 60 10.98 -REMARK 500 LYS B 61 -15.00 -REMARK 500 ALA B 62 10.49 -REMARK 500 HIS B 63 -10.22 -REMARK 500 LEU B 78 -25.59 -REMARK 500 ASP B 79 22.50 -REMARK 500 ASN B 80 -11.76 -REMARK 500 LEU B 81 11.29 -REMARK 500 THR B 84 10.62 -REMARK 500 GLU B 90 -10.55 -REMARK 500 PRO B 100 -11.02 -REMARK 500 GLU B 101 -10.37 -REMARK 500 LEU B 114 12.32 -REMARK 500 THR B 123 -10.84 -REMARK 500 VAL B 126 -11.54 -REMARK 500 GLN B 131 -10.69 -REMARK 500 ASN B 139 -17.46 -REMARK 500 LEU B 141 16.07 -REMARK 500 SER C 3 -11.99 -REMARK 500 ALA C 5 12.77 -REMARK 500 TRP C 14 -12.14 -REMARK 500 VAL C 17 12.38 -REMARK 500 GLY C 18 -13.67 -REMARK 500 ALA C 21 -14.14 -REMARK 500 GLY C 25 -12.75 -REMARK 500 PRO C 44 -13.45 -REMARK 500 HIS C 45 12.45 -REMARK 500 PHE C 46 -11.87 -REMARK 500 ASP C 47 19.24 -REMARK 500 LEU C 48 -13.66 -REMARK 500 ALA C 69 11.81 -REMARK 500 ALA C 71 22.14 -REMARK 500 HIS C 72 13.20 -REMARK 500 ASP C 74 12.29 -REMARK 500 ASP C 75 -23.66 -REMARK 500 LEU C 80 -11.12 -REMARK 500 LEU C 83 -10.01 -REMARK 500 ALA C 88 13.88 -REMARK 500 PRO C 95 -13.42 -REMARK 500 LEU C 109 16.42 -REMARK 500 ALA C 110 13.99 -REMARK 500 ALA C 111 15.47 -REMARK 500 HIS C 112 15.18 -REMARK 500 LEU C 113 -20.94 -REMARK 500 PRO C 114 -32.91 -REMARK 500 GLU C 116 -12.30 -REMARK 500 PRO C 119 11.39 -REMARK 500 LEU C 125 -10.17 -REMARK 500 VAL C 135 14.71 -REMARK 500 SER C 138 10.64 -REMARK 500 VAL D 1 -18.79 -REMARK 500 HIS D 2 -12.81 -REMARK 500 LEU D 3 -69.40 -REMARK 500 PRO D 5 -10.95 -REMARK 500 LYS D 8 -16.56 -REMARK 500 LYS D 17 10.52 -REMARK 500 ASP D 21 -17.88 -REMARK 500 GLU D 22 23.39 -REMARK 500 VAL D 33 11.00 -REMARK 500 VAL D 34 11.48 -REMARK 500 PHE D 42 10.18 -REMARK 500 GLY D 46 -18.80 -REMARK 500 LEU D 48 13.68 -REMARK 500 SER D 49 -21.45 -REMARK 500 ASP D 52 12.37 -REMARK 500 GLY D 56 17.16 -REMARK 500 VAL D 60 10.39 -REMARK 500 GLY D 64 -10.31 -REMARK 500 LYS D 66 16.91 -REMARK 500 ASP D 73 -11.34 -REMARK 500 LEU D 75 15.44 -REMARK 500 ALA D 76 -28.12 -REMARK 500 ASP D 79 -15.13 -REMARK 500 ASN D 80 -17.79 -REMARK 500 GLY D 83 -24.24 -REMARK 500 THR D 84 23.01 -REMARK 500 HIS D 92 -12.19 -REMARK 500 LEU D 96 11.44 -REMARK 500 HIS D 117 12.17 -REMARK 500 LYS D 120 -25.33 -REMARK 500 VAL D 137 -19.82 -REMARK 500 LYS D 144 17.08 -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 500 -REMARK 500 GEOMETRY AND STEREOCHEMISTRY -REMARK 500 SUBTOPIC: CHIRAL CENTERS -REMARK 500 -REMARK 500 UNEXPECTED CONFIGURATION OF THE FOLLOWING CHIRAL -REMARK 500 CENTER(S) USING IMPROPER CA--C--CB--N CHIRALITY -REMARK 500 M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN -REMARK 500 IDENTIFIER; SSEQ=SEQUENCE NUMBER; I=INSERTION CODE -REMARK 500 -REMARK 500 STANDARD TABLE: -REMARK 500 FORMAT: (11X,I3,1X,A3,1X,A1,I4,A1,6X,F5.1,6X,A1,10X,A1,3X,A16) -REMARK 500 -REMARK 500 M RES CSSEQI IMPROPER EXPECTED FOUND DETAILS -REMARK 500 SER A 3 47.5 L L OUTSIDE RANGE -REMARK 500 LYS A 7 22.9 L L OUTSIDE RANGE -REMARK 500 LYS A 16 14.6 L L OUTSIDE RANGE -REMARK 500 VAL A 17 18.2 L L OUTSIDE RANGE -REMARK 500 ALA A 26 18.6 L L OUTSIDE RANGE -REMARK 500 PHE A 33 25.0 L L OUTSIDE RANGE -REMARK 500 SER A 49 47.6 L L OUTSIDE RANGE -REMARK 500 LYS A 56 14.8 L L OUTSIDE RANGE -REMARK 500 LYS A 60 22.7 L L OUTSIDE RANGE -REMARK 500 ALA A 71 48.3 L L OUTSIDE RANGE -REMARK 500 PRO A 77 16.7 L L OUTSIDE RANGE -REMARK 500 SER A 84 23.0 L L OUTSIDE RANGE -REMARK 500 HIS A 89 23.9 L L OUTSIDE RANGE -REMARK 500 LYS A 90 17.4 L L OUTSIDE RANGE -REMARK 500 HIS A 103 22.3 L L OUTSIDE RANGE -REMARK 500 ALA A 111 21.3 L L OUTSIDE RANGE -REMARK 500 PRO A 114 49.5 L L OUTSIDE RANGE -REMARK 500 PHE A 117 21.9 L L OUTSIDE RANGE -REMARK 500 ALA A 120 20.3 L L OUTSIDE RANGE -REMARK 500 HIS A 122 46.2 L L OUTSIDE RANGE -REMARK 500 TYR A 140 23.5 L L OUTSIDE RANGE -REMARK 500 PRO B 5 18.3 L L OUTSIDE RANGE -REMARK 500 SER B 9 13.0 L L OUTSIDE RANGE -REMARK 500 ALA B 13 23.4 L L OUTSIDE RANGE -REMARK 500 LEU B 28 16.4 L L OUTSIDE RANGE -REMARK 500 THR B 38 24.4 L L OUTSIDE RANGE -REMARK 500 GLU B 43 46.6 L L OUTSIDE RANGE -REMARK 500 ASP B 47 45.8 L L OUTSIDE RANGE -REMARK 500 SER B 49 53.4 L L OUTSIDE RANGE -REMARK 500 VAL B 60 24.9 L L OUTSIDE RANGE -REMARK 500 LYS B 65 20.6 L L OUTSIDE RANGE -REMARK 500 HIS B 77 47.6 L L OUTSIDE RANGE -REMARK 500 ASP B 79 51.3 L L OUTSIDE RANGE -REMARK 500 ASN B 80 45.3 L L OUTSIDE RANGE -REMARK 500 LYS B 82 47.0 L L OUTSIDE RANGE -REMARK 500 THR B 84 23.8 L L OUTSIDE RANGE -REMARK 500 GLU B 90 11.1 L L OUTSIDE RANGE -REMARK 500 LEU B 96 22.2 L L OUTSIDE RANGE -REMARK 500 ASP B 99 47.0 L L OUTSIDE RANGE -REMARK 500 HIS B 117 22.8 L L OUTSIDE RANGE -REMARK 500 GLN B 127 23.5 L L OUTSIDE RANGE -REMARK 500 VAL B 134 20.6 L L OUTSIDE RANGE -REMARK 500 TYR B 145 13.6 L L OUTSIDE RANGE -REMARK 500 VAL C 1 85.9 L L OUTSIDE RANGE -REMARK 500 ALA C 5 23.1 L L OUTSIDE RANGE -REMARK 500 ALA C 12 13.9 L L OUTSIDE RANGE -REMARK 500 LYS C 16 18.8 L L OUTSIDE RANGE -REMARK 500 VAL C 17 23.9 L L OUTSIDE RANGE -REMARK 500 TYR C 24 23.1 L L OUTSIDE RANGE -REMARK 500 ALA C 26 24.5 L L OUTSIDE RANGE -REMARK 500 PRO C 44 49.8 L L OUTSIDE RANGE -REMARK 500 ALA C 53 18.8 L L OUTSIDE RANGE -REMARK 500 HIS C 72 10.8 L L OUTSIDE RANGE -REMARK 500 VAL C 73 21.3 L L OUTSIDE RANGE -REMARK 500 ASP C 75 50.5 L L OUTSIDE RANGE -REMARK 500 PRO C 77 23.1 L L OUTSIDE RANGE -REMARK 500 ASN C 78 7.6 L D EXPECTING SP3 -REMARK 500 SER C 84 22.3 L L OUTSIDE RANGE -REMARK 500 ALA C 88 23.4 L L OUTSIDE RANGE -REMARK 500 HIS C 89 24.6 L L OUTSIDE RANGE -REMARK 500 LYS C 90 16.1 L L OUTSIDE RANGE -REMARK 500 LYS C 99 23.5 L L OUTSIDE RANGE -REMARK 500 VAL C 107 23.4 L L OUTSIDE RANGE -REMARK 500 PRO C 114 58.4 L L OUTSIDE RANGE -REMARK 500 ALA C 115 17.3 L L OUTSIDE RANGE -REMARK 500 ARG C 141 24.7 L L OUTSIDE RANGE -REMARK 500 HIS D 2 0.2 L D EXPECTING SP3 -REMARK 500 THR D 4 19.6 L L OUTSIDE RANGE -REMARK 500 ALA D 10 48.1 L L OUTSIDE RANGE -REMARK 500 ALA D 13 16.1 L L OUTSIDE RANGE -REMARK 500 LYS D 17 21.9 L L OUTSIDE RANGE -REMARK 500 ASN D 19 20.8 L L OUTSIDE RANGE -REMARK 500 VAL D 20 14.8 L L OUTSIDE RANGE -REMARK 500 ASP D 21 18.2 L L OUTSIDE RANGE -REMARK 500 LEU D 31 23.7 L L OUTSIDE RANGE -REMARK 500 ASP D 47 70.5 L L OUTSIDE RANGE -REMARK 500 ASP D 52 59.4 L L OUTSIDE RANGE -REMARK 500 ALA D 53 24.1 L L OUTSIDE RANGE -REMARK 500 LYS D 59 23.2 L L OUTSIDE RANGE -REMARK 500 SER D 72 4.3 L D EXPECTING SP3 -REMARK 500 ASP D 73 7.4 L D EXPECTING SP3 -REMARK 500 ALA D 76 83.0 L L OUTSIDE RANGE -REMARK 500 LEU D 78 -0.1 L D EXPECTING SP3 -REMARK 500 HIS D 92 48.8 L L OUTSIDE RANGE -REMARK 500 ASP D 94 47.8 L L OUTSIDE RANGE -REMARK 500 PRO D 100 22.6 L L OUTSIDE RANGE -REMARK 500 CYS D 112 22.5 L L OUTSIDE RANGE -REMARK 500 PHE D 122 45.5 L L OUTSIDE RANGE -REMARK 500 GLN D 131 24.7 L L OUTSIDE RANGE -REMARK 500 VAL D 137 22.8 L L OUTSIDE RANGE -REMARK 500 HIS D 143 24.9 L L OUTSIDE RANGE -REMARK 500 LYS D 144 3.0 L D EXPECTING SP3 -REMARK 500 TYR D 145 23.9 L L OUTSIDE RANGE -REMARK 500 HIS D 146 48.0 L L OUTSIDE RANGE -REMARK 500 -REMARK 500 REMARK: NULL -REMARK 610 -REMARK 610 MISSING HETEROATOM -REMARK 610 THE FOLLOWING RESIDUES HAVE MISSING ATOMS (M=MODEL NUMBER; -REMARK 610 RES=RESIDUE NAME; C=CHAIN IDENTIFIER; SSEQ=SEQUENCE NUMBER; -REMARK 610 I=INSERTION CODE): -REMARK 610 M RES C SSEQI -REMARK 610 PO4 D 147 -REMARK 610 PO4 B 147 -REMARK 800 -REMARK 800 SITE -REMARK 800 SITE_IDENTIFIER: AC1 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE PO4 D 147 -REMARK 800 SITE_IDENTIFIER: AC2 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE PO4 B 147 -REMARK 800 SITE_IDENTIFIER: AC3 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE HEM A 142 -REMARK 800 SITE_IDENTIFIER: AC4 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE HEM B 148 -REMARK 800 SITE_IDENTIFIER: AC5 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE HEM C 142 -REMARK 800 SITE_IDENTIFIER: AC6 -REMARK 800 EVIDENCE_CODE: SOFTWARE -REMARK 800 SITE_DESCRIPTION: BINDING SITE FOR RESIDUE HEM D 148 -REMARK 900 -REMARK 900 RELATED ENTRIES -REMARK 900 RELATED ID: 2HHB RELATED DB: PDB -REMARK 900 REFINED BY THE METHOD OF JACK AND LEVITT. THIS ENTRY -REMARK 900 PRESENTS THE BEST ESTIMATE OF THE COORDINATES. -REMARK 900 RELATED ID: 3HHB RELATED DB: PDB -REMARK 900 SYMMETRY AVERAGED ABOUT THE (NON-CRYSTALLOGRAPHIC) -REMARK 900 MOLECULAR AXIS AND THEN RE-REGULARIZED BY THE ENERGY -REMARK 900 REFINEMENT METHOD OF LEVITT. THIS ENTRY PRESENTS -REMARK 900 COORDINATES THAT ARE ADEQUATE FOR MOST PURPOSES, SUCH AS -REMARK 900 COMPARISON WITH OTHER STRUCTURES. -REMARK 900 RELATED ID: 1GLI RELATED DB: PDB -DBREF 4HHB A 1 141 UNP P69905 HBA_HUMAN 1 141 -DBREF 4HHB B 1 146 UNP P68871 HBB_HUMAN 1 146 -DBREF 4HHB C 1 141 UNP P69905 HBA_HUMAN 1 141 -DBREF 4HHB D 1 146 UNP P68871 HBB_HUMAN 1 146 -SEQRES 1 A 141 VAL LEU SER PRO ALA ASP LYS THR ASN VAL LYS ALA ALA -SEQRES 2 A 141 TRP GLY LYS VAL GLY ALA HIS ALA GLY GLU TYR GLY ALA -SEQRES 3 A 141 GLU ALA LEU GLU ARG MET PHE LEU SER PHE PRO THR THR -SEQRES 4 A 141 LYS THR TYR PHE PRO HIS PHE ASP LEU SER HIS GLY SER -SEQRES 5 A 141 ALA GLN VAL LYS GLY HIS GLY LYS LYS VAL ALA ASP ALA -SEQRES 6 A 141 LEU THR ASN ALA VAL ALA HIS VAL ASP ASP MET PRO ASN -SEQRES 7 A 141 ALA LEU SER ALA LEU SER ASP LEU HIS ALA HIS LYS LEU -SEQRES 8 A 141 ARG VAL ASP PRO VAL ASN PHE LYS LEU LEU SER HIS CYS -SEQRES 9 A 141 LEU LEU VAL THR LEU ALA ALA HIS LEU PRO ALA GLU PHE -SEQRES 10 A 141 THR PRO ALA VAL HIS ALA SER LEU ASP LYS PHE LEU ALA -SEQRES 11 A 141 SER VAL SER THR VAL LEU THR SER LYS TYR ARG -SEQRES 1 B 146 VAL HIS LEU THR PRO GLU GLU LYS SER ALA VAL THR ALA -SEQRES 2 B 146 LEU TRP GLY LYS VAL ASN VAL ASP GLU VAL GLY GLY GLU -SEQRES 3 B 146 ALA LEU GLY ARG LEU LEU VAL VAL TYR PRO TRP THR GLN -SEQRES 4 B 146 ARG PHE PHE GLU SER PHE GLY ASP LEU SER THR PRO ASP -SEQRES 5 B 146 ALA VAL MET GLY ASN PRO LYS VAL LYS ALA HIS GLY LYS -SEQRES 6 B 146 LYS VAL LEU GLY ALA PHE SER ASP GLY LEU ALA HIS LEU -SEQRES 7 B 146 ASP ASN LEU LYS GLY THR PHE ALA THR LEU SER GLU LEU -SEQRES 8 B 146 HIS CYS ASP LYS LEU HIS VAL ASP PRO GLU ASN PHE ARG -SEQRES 9 B 146 LEU LEU GLY ASN VAL LEU VAL CYS VAL LEU ALA HIS HIS -SEQRES 10 B 146 PHE GLY LYS GLU PHE THR PRO PRO VAL GLN ALA ALA TYR -SEQRES 11 B 146 GLN LYS VAL VAL ALA GLY VAL ALA ASN ALA LEU ALA HIS -SEQRES 12 B 146 LYS TYR HIS -SEQRES 1 C 141 VAL LEU SER PRO ALA ASP LYS THR ASN VAL LYS ALA ALA -SEQRES 2 C 141 TRP GLY LYS VAL GLY ALA HIS ALA GLY GLU TYR GLY ALA -SEQRES 3 C 141 GLU ALA LEU GLU ARG MET PHE LEU SER PHE PRO THR THR -SEQRES 4 C 141 LYS THR TYR PHE PRO HIS PHE ASP LEU SER HIS GLY SER -SEQRES 5 C 141 ALA GLN VAL LYS GLY HIS GLY LYS LYS VAL ALA ASP ALA -SEQRES 6 C 141 LEU THR ASN ALA VAL ALA HIS VAL ASP ASP MET PRO ASN -SEQRES 7 C 141 ALA LEU SER ALA LEU SER ASP LEU HIS ALA HIS LYS LEU -SEQRES 8 C 141 ARG VAL ASP PRO VAL ASN PHE LYS LEU LEU SER HIS CYS -SEQRES 9 C 141 LEU LEU VAL THR LEU ALA ALA HIS LEU PRO ALA GLU PHE -SEQRES 10 C 141 THR PRO ALA VAL HIS ALA SER LEU ASP LYS PHE LEU ALA -SEQRES 11 C 141 SER VAL SER THR VAL LEU THR SER LYS TYR ARG -SEQRES 1 D 146 VAL HIS LEU THR PRO GLU GLU LYS SER ALA VAL THR ALA -SEQRES 2 D 146 LEU TRP GLY LYS VAL ASN VAL ASP GLU VAL GLY GLY GLU -SEQRES 3 D 146 ALA LEU GLY ARG LEU LEU VAL VAL TYR PRO TRP THR GLN -SEQRES 4 D 146 ARG PHE PHE GLU SER PHE GLY ASP LEU SER THR PRO ASP -SEQRES 5 D 146 ALA VAL MET GLY ASN PRO LYS VAL LYS ALA HIS GLY LYS -SEQRES 6 D 146 LYS VAL LEU GLY ALA PHE SER ASP GLY LEU ALA HIS LEU -SEQRES 7 D 146 ASP ASN LEU LYS GLY THR PHE ALA THR LEU SER GLU LEU -SEQRES 8 D 146 HIS CYS ASP LYS LEU HIS VAL ASP PRO GLU ASN PHE ARG -SEQRES 9 D 146 LEU LEU GLY ASN VAL LEU VAL CYS VAL LEU ALA HIS HIS -SEQRES 10 D 146 PHE GLY LYS GLU PHE THR PRO PRO VAL GLN ALA ALA TYR -SEQRES 11 D 146 GLN LYS VAL VAL ALA GLY VAL ALA ASN ALA LEU ALA HIS -SEQRES 12 D 146 LYS TYR HIS -HET PO4 D 147 1 -HET PO4 B 147 1 -HET HEM A 142 43 -HET HEM B 148 43 -HET HEM C 142 43 -HET HEM D 148 43 -HETNAM PO4 PHOSPHATE ION -HETNAM HEM PROTOPORPHYRIN IX CONTAINING FE -HETSYN HEM HEME -FORMUL 5 PO4 2(O4 P 3-) -FORMUL 7 HEM 4(C34 H32 FE N4 O4) -FORMUL 11 HOH *221(H2 O) -HELIX 1 AA SER A 3 GLY A 18 1 16 -HELIX 2 AB HIS A 20 SER A 35 1 16 -HELIX 3 AC PHE A 36 TYR A 42 1 7 -HELIX 4 AD HIS A 50 GLY A 51 1DEGEN 2 RES HLX RETAIN HOMOL 2 -HELIX 5 AE SER A 52 ALA A 71 1 20 -HELIX 6 AF LEU A 80 ALA A 88 1 9 -HELIX 7 AG ASP A 94 HIS A 112 1 19 -HELIX 8 AH THR A 118 SER A 138 1 21 -HELIX 9 BA THR B 4 VAL B 18 1 15 -HELIX 10 BB ASN B 19 VAL B 34 1 16 -HELIX 11 BC TYR B 35 PHE B 41 1 7 -HELIX 12 BD THR B 50 GLY B 56 1 7 -HELIX 13 BE ASN B 57 ALA B 76 1 20 -HELIX 14 BF PHE B 85 CYS B 93 1 9 -HELIX 15 BG ASP B 99 HIS B 117 1 19 -HELIX 16 BH THR B 123 HIS B 143 1 21 -HELIX 17 CA SER C 3 GLY C 18 1 16 -HELIX 18 CB HIS C 20 SER C 35 1 16 -HELIX 19 CC PHE C 36 TYR C 42 1 7 -HELIX 20 CD HIS C 50 GLY C 51 1DEGEN 2 RES HLX RETAIN HOMOL 2 -HELIX 21 CE SER C 52 ALA C 71 1 20 -HELIX 22 CF LEU C 80 ALA C 88 1 9 -HELIX 23 CG ASP C 94 HIS C 112 1 19 -HELIX 24 CH THR C 118 SER C 138 1 21 -HELIX 25 DA THR D 4 VAL D 18 1 15 -HELIX 26 DB ASN D 19 VAL D 34 1 16 -HELIX 27 DC TYR D 35 PHE D 41 1 7 -HELIX 28 DD THR D 50 GLY D 56 1 7 -HELIX 29 DE ASN D 57 ALA D 76 1 20 -HELIX 30 DF PHE D 85 CYS D 93 1 9 -HELIX 31 DG ASP D 99 HIS D 117 1 19 -HELIX 32 DH THR D 123 HIS D 143 1 21 -LINK NE2 HIS A 87 FE HEM A 142 1555 1555 2.14 -LINK NE2 HIS B 92 FE HEM B 148 1555 1555 2.22 -LINK NE2 HIS C 87 FE HEM C 142 1555 1555 2.26 -LINK NE2 HIS D 92 FE HEM D 148 1555 1555 1.98 -SITE 1 AC1 1 VAL D 1 -SITE 1 AC2 1 HOH B 197 -SITE 1 AC3 16 TYR A 42 PHE A 43 HIS A 45 PHE A 46 -SITE 2 AC3 16 HIS A 58 LYS A 61 LEU A 86 HIS A 87 -SITE 3 AC3 16 LEU A 91 VAL A 93 ASN A 97 PHE A 98 -SITE 4 AC3 16 LEU A 101 LEU A 136 HOH A 144 HOH A 159 -SITE 1 AC4 13 ALA A 53 HOH A 145 PHE B 41 HIS B 63 -SITE 2 AC4 13 LYS B 66 VAL B 67 HIS B 92 LEU B 96 -SITE 3 AC4 13 ASN B 102 PHE B 103 LEU B 141 HOH B 175 -SITE 4 AC4 13 HOH B 193 -SITE 1 AC5 15 TYR C 42 PHE C 43 HIS C 45 HIS C 58 -SITE 2 AC5 15 LYS C 61 LEU C 83 LEU C 86 HIS C 87 -SITE 3 AC5 15 LEU C 91 VAL C 93 ASN C 97 PHE C 98 -SITE 4 AC5 15 LEU C 136 HOH C 149 HOH C 164 -SITE 1 AC6 7 HIS D 63 LYS D 66 VAL D 67 HIS D 92 -SITE 2 AC6 7 LEU D 96 ASN D 102 LEU D 141 -CRYST1 63.150 83.590 53.800 90.00 99.34 90.00 P 1 21 1 4 -ORIGX1 0.963457 0.136613 0.230424 16.61000 -ORIGX2 -0.158977 0.983924 0.081383 13.72000 -ORIGX3 -0.215598 -0.115048 0.969683 37.65000 -SCALE1 0.015462 0.002192 0.003698 0.26656 -SCALE2 -0.001902 0.011771 0.000974 0.16413 -SCALE3 -0.001062 -0.001721 0.018728 0.75059 -MTRIX1 1 -1.000000 0.000000 0.000000 0.00001 1 -MTRIX2 1 0.000000 1.000000 0.000000 0.00002 1 -MTRIX3 1 0.000000 0.000000 -1.000000 0.00002 1 -ATOM 1 N VAL A 1 6.204 16.869 4.854 1.00 49.05 N -ATOM 2 CA VAL A 1 6.913 17.759 4.607 1.00 43.14 C -ATOM 3 C VAL A 1 8.504 17.378 4.797 1.00 24.80 C -ATOM 4 O VAL A 1 8.805 17.011 5.943 1.00 37.68 O -ATOM 5 CB VAL A 1 6.369 19.044 5.810 1.00 72.12 C -ATOM 6 CG1 VAL A 1 7.009 20.127 5.418 1.00 61.79 C -ATOM 7 CG2 VAL A 1 5.246 18.533 5.681 1.00 80.12 C -ATOM 8 N LEU A 2 9.096 18.040 3.857 1.00 26.44 N -ATOM 9 CA LEU A 2 10.600 17.889 4.283 1.00 26.32 C -ATOM 10 C LEU A 2 11.265 19.184 5.297 1.00 32.96 C -ATOM 11 O LEU A 2 10.813 20.177 4.647 1.00 31.90 O -ATOM 12 CB LEU A 2 11.099 18.007 2.815 1.00 29.23 C -ATOM 13 CG LEU A 2 11.322 16.956 1.934 1.00 37.71 C -ATOM 14 CD1 LEU A 2 11.468 15.596 2.337 1.00 39.10 C -ATOM 15 CD2 LEU A 2 11.423 17.268 0.300 1.00 37.47 C -ATOM 16 N SER A 3 11.584 18.730 6.148 1.00 28.01 N -ATOM 17 CA SER A 3 12.263 19.871 7.087 1.00 26.03 C -ATOM 18 C SER A 3 13.304 20.329 6.300 1.00 25.99 C -ATOM 19 O SER A 3 14.085 19.818 5.364 1.00 25.98 O -ATOM 20 CB SER A 3 12.744 19.045 8.223 1.00 23.41 C -ATOM 21 OG SER A 3 13.781 18.286 8.179 1.00 30.00 O -ATOM 22 N PRO A 4 14.196 21.422 7.097 1.00 37.49 N -ATOM 23 CA PRO A 4 15.048 21.890 6.206 1.00 38.81 C -ATOM 24 C PRO A 4 16.464 21.282 6.288 1.00 25.63 C -ATOM 25 O PRO A 4 17.212 20.899 5.409 1.00 34.38 O -ATOM 26 CB PRO A 4 15.814 23.113 7.166 1.00 50.44 C -ATOM 27 CG PRO A 4 14.493 23.536 7.638 1.00 43.42 C -ATOM 28 CD PRO A 4 13.298 22.523 7.651 1.00 42.77 C -ATOM 29 N ALA A 5 16.399 20.279 7.524 1.00 24.33 N -ATOM 30 CA ALA A 5 17.552 19.622 7.588 1.00 24.06 C -ATOM 31 C ALA A 5 17.376 18.283 6.601 1.00 20.01 C -ATOM 32 O ALA A 5 18.422 17.849 6.010 1.00 24.46 O -ATOM 33 CB ALA A 5 17.454 18.830 9.164 1.00 28.15 C -ATOM 34 N ASP A 6 16.050 17.799 6.298 1.00 21.19 N -ATOM 35 CA ASP A 6 15.881 16.887 5.120 1.00 23.14 C -ATOM 36 C ASP A 6 16.573 17.497 3.915 1.00 15.75 C -ATOM 37 O ASP A 6 17.240 16.611 3.235 1.00 18.92 O -ATOM 38 CB ASP A 6 14.530 16.515 4.983 1.00 18.68 C -ATOM 39 CG ASP A 6 13.966 15.638 6.125 1.00 21.70 C -ATOM 40 OD1 ASP A 6 14.573 14.751 6.678 1.00 19.76 O -ATOM 41 OD2 ASP A 6 12.734 15.931 6.321 1.00 21.26 O -ATOM 42 N LYS A 7 16.082 18.800 3.719 1.00 15.62 N -ATOM 43 CA LYS A 7 16.897 19.255 2.400 1.00 26.74 C -ATOM 44 C LYS A 7 18.354 19.319 2.072 1.00 24.82 C -ATOM 45 O LYS A 7 18.858 18.855 1.145 1.00 21.36 O -ATOM 46 CB LYS A 7 16.022 20.503 2.054 1.00 28.73 C -ATOM 47 CG LYS A 7 14.518 20.443 2.287 1.00 34.11 C -ATOM 48 CD LYS A 7 13.833 21.967 2.124 1.00 46.50 C -ATOM 49 CE LYS A 7 12.524 21.830 2.733 1.00 40.75 C -ATOM 50 NZ LYS A 7 12.310 23.286 2.231 1.00 50.05 N -ATOM 51 N THR A 8 18.879 19.583 3.554 1.00 20.80 N -ATOM 52 CA THR A 8 20.359 19.452 3.495 1.00 23.21 C -ATOM 53 C THR A 8 21.000 18.322 3.125 1.00 17.85 C -ATOM 54 O THR A 8 21.907 17.957 2.500 1.00 20.04 O -ATOM 55 CB THR A 8 20.762 20.269 4.939 1.00 31.90 C -ATOM 56 OG1 THR A 8 20.363 21.458 4.886 1.00 31.01 O -ATOM 57 CG2 THR A 8 22.026 20.115 4.978 1.00 43.78 C -ATOM 58 N ASN A 9 20.249 17.203 3.818 1.00 16.13 N -ATOM 59 CA ASN A 9 20.591 15.889 3.728 1.00 17.84 C -ATOM 60 C ASN A 9 20.630 15.286 2.184 1.00 14.45 C -ATOM 61 O ASN A 9 21.319 14.475 1.822 1.00 21.78 O -ATOM 62 CB ASN A 9 19.836 14.946 4.644 1.00 20.10 C -ATOM 63 CG ASN A 9 20.193 15.272 6.089 1.00 34.82 C -ATOM 64 OD1 ASN A 9 21.294 15.680 6.444 1.00 26.93 O -ATOM 65 ND2 ASN A 9 19.527 14.719 6.950 1.00 28.08 N -ATOM 66 N VAL A 10 19.435 15.546 1.583 1.00 19.64 N -ATOM 67 CA VAL A 10 19.157 15.110 0.179 1.00 13.04 C -ATOM 68 C VAL A 10 20.341 15.904 -0.719 1.00 18.71 C -ATOM 69 O VAL A 10 20.832 15.221 -1.618 1.00 22.34 O -ATOM 70 CB VAL A 10 17.776 15.394 -0.119 1.00 19.07 C -ATOM 71 CG1 VAL A 10 17.623 15.138 -1.549 1.00 21.59 C -ATOM 72 CG2 VAL A 10 16.816 14.756 0.575 1.00 22.75 C -ATOM 73 N LYS A 11 20.392 17.201 -0.404 1.00 18.31 N -ATOM 74 CA LYS A 11 21.297 18.030 -1.415 1.00 24.80 C -ATOM 75 C LYS A 11 22.762 17.451 -1.066 1.00 19.51 C -ATOM 76 O LYS A 11 23.584 17.190 -2.069 1.00 22.33 O -ATOM 77 CB LYS A 11 21.334 19.381 -1.059 1.00 39.77 C -ATOM 78 CG LYS A 11 20.229 20.052 -1.350 1.00 34.41 C -ATOM 79 CD LYS A 11 20.256 21.365 -1.389 1.00 46.95 C -ATOM 80 CE LYS A 11 18.633 21.891 -2.358 1.00 49.55 C -ATOM 81 NZ LYS A 11 18.398 23.088 -1.720 1.00 78.67 N -ATOM 82 N ALA A 12 23.031 16.766 0.069 1.00 20.60 N -ATOM 83 CA ALA A 12 24.347 16.671 -0.059 1.00 25.98 C -ATOM 84 C ALA A 12 24.529 15.278 -0.129 1.00 38.04 C -ATOM 85 O ALA A 12 25.505 14.711 -1.045 1.00 31.19 O -ATOM 86 CB ALA A 12 24.641 16.359 1.529 1.00 28.13 C -ATOM 87 N ALA A 13 23.581 14.281 -0.261 1.00 21.69 N -ATOM 88 CA ALA A 13 23.822 13.010 -0.701 1.00 19.11 C -ATOM 89 C ALA A 13 23.807 12.890 -2.423 1.00 22.93 C -ATOM 90 O ALA A 13 24.517 12.116 -2.938 1.00 24.98 O -ATOM 91 CB ALA A 13 22.612 12.109 -0.160 1.00 23.17 C -ATOM 92 N TRP A 14 22.807 13.763 -2.832 1.00 22.14 N -ATOM 93 CA TRP A 14 22.715 13.681 -4.311 1.00 21.27 C -ATOM 94 C TRP A 14 24.007 14.453 -5.015 1.00 28.97 C -ATOM 95 O TRP A 14 24.452 13.999 -6.086 1.00 27.61 O -ATOM 96 CB TRP A 14 21.129 14.484 -4.728 1.00 29.00 C -ATOM 97 CG TRP A 14 21.116 13.951 -5.830 1.00 25.79 C -ATOM 98 CD1 TRP A 14 21.182 14.904 -7.199 1.00 22.38 C -ATOM 99 CD2 TRP A 14 20.358 12.768 -6.306 1.00 20.46 C -ATOM 100 NE1 TRP A 14 20.545 13.886 -8.152 1.00 29.74 N -ATOM 101 CE2 TRP A 14 20.127 12.855 -7.917 1.00 27.75 C -ATOM 102 CE3 TRP A 14 19.993 11.556 -5.760 1.00 34.00 C -ATOM 103 CZ2 TRP A 14 19.685 11.924 -8.428 1.00 34.81 C -ATOM 104 CZ3 TRP A 14 19.443 10.605 -6.677 1.00 42.11 C -ATOM 105 CH2 TRP A 14 19.361 10.910 -7.988 1.00 47.54 C -ATOM 106 N GLY A 15 24.563 15.294 -4.064 1.00 40.92 N -ATOM 107 CA GLY A 15 25.545 16.032 -4.810 1.00 38.97 C -ATOM 108 C GLY A 15 26.606 14.720 -4.643 1.00 34.61 C -ATOM 109 O GLY A 15 27.532 14.956 -6.011 1.00 36.24 O -ATOM 110 N LYS A 16 27.023 14.192 -4.019 1.00 35.37 N -ATOM 111 CA LYS A 16 27.691 12.809 -3.990 1.00 29.09 C -ATOM 112 C LYS A 16 27.692 11.980 -5.322 1.00 27.28 C -ATOM 113 O LYS A 16 28.444 11.335 -5.752 1.00 36.62 O -ATOM 114 CB LYS A 16 27.773 11.881 -2.758 1.00 30.47 C -ATOM 115 CG LYS A 16 29.128 10.897 -2.949 1.00 47.02 C -ATOM 116 CD LYS A 16 30.512 12.265 -2.454 1.00 66.41 C -ATOM 117 CE LYS A 16 31.160 10.590 -3.127 1.00 65.00 C -ATOM 118 NZ LYS A 16 31.293 9.343 -2.468 1.00 69.28 N -ATOM 119 N VAL A 17 26.231 11.894 -5.716 1.00 40.63 N -ATOM 120 CA VAL A 17 25.763 11.093 -6.580 1.00 32.19 C -ATOM 121 C VAL A 17 26.644 11.417 -8.297 1.00 51.53 C -ATOM 122 O VAL A 17 27.090 10.850 -8.486 1.00 36.95 O -ATOM 123 CB VAL A 17 24.455 10.688 -6.704 1.00 24.77 C -ATOM 124 CG1 VAL A 17 24.024 10.418 -8.088 1.00 21.73 C -ATOM 125 CG2 VAL A 17 23.718 9.922 -5.546 1.00 23.90 C -ATOM 126 N GLY A 18 26.340 12.947 -7.963 1.00 36.07 N -ATOM 127 CA GLY A 18 27.063 13.723 -8.931 1.00 37.64 C -ATOM 128 C GLY A 18 26.574 12.969 -10.560 1.00 27.84 C -ATOM 129 O GLY A 18 25.253 13.110 -10.707 1.00 34.16 O -ATOM 130 N ALA A 19 27.657 12.515 -11.022 1.00 35.70 N -ATOM 131 CA ALA A 19 27.728 12.613 -12.429 1.00 37.59 C -ATOM 132 C ALA A 19 27.500 10.976 -12.552 1.00 34.69 C -ATOM 133 O ALA A 19 27.084 10.420 -13.842 1.00 48.59 O -ATOM 134 CB ALA A 19 29.012 12.664 -13.280 1.00 46.19 C -ATOM 135 N HIS A 20 27.156 10.119 -11.606 1.00 20.24 N -ATOM 136 CA HIS A 20 26.883 8.665 -11.713 1.00 19.03 C -ATOM 137 C HIS A 20 25.297 8.749 -11.742 1.00 17.82 C -ATOM 138 O HIS A 20 24.744 7.547 -11.745 1.00 20.59 O -ATOM 139 CB HIS A 20 27.211 8.007 -10.561 1.00 31.92 C -ATOM 140 CG HIS A 20 28.495 7.629 -10.284 1.00 45.35 C -ATOM 141 ND1 HIS A 20 29.488 7.023 -11.531 1.00 52.86 N -ATOM 142 CD2 HIS A 20 29.445 8.698 -9.743 1.00 43.12 C -ATOM 143 CE1 HIS A 20 30.546 7.246 -10.801 1.00 68.75 C -ATOM 144 NE2 HIS A 20 30.729 7.865 -10.003 1.00 55.89 N -ATOM 145 N ALA A 21 24.687 9.784 -11.799 1.00 29.55 N -ATOM 146 CA ALA A 21 23.159 9.917 -11.488 1.00 29.36 C -ATOM 147 C ALA A 21 22.579 8.284 -12.650 1.00 46.23 C -ATOM 148 O ALA A 21 21.659 8.109 -12.129 1.00 27.88 O -ATOM 149 CB ALA A 21 22.561 11.174 -11.335 1.00 28.64 C -ATOM 150 N GLY A 22 22.741 9.029 -13.713 1.00 27.74 N -ATOM 151 CA GLY A 22 22.302 7.955 -14.644 1.00 29.10 C -ATOM 152 C GLY A 22 22.405 6.768 -14.523 1.00 40.30 C -ATOM 153 O GLY A 22 21.884 5.714 -14.971 1.00 33.08 O -ATOM 154 N GLU A 23 23.751 6.163 -14.331 1.00 22.76 N -ATOM 155 CA GLU A 23 24.084 4.748 -14.144 1.00 14.60 C -ATOM 156 C GLU A 23 23.211 4.210 -12.893 1.00 13.41 C -ATOM 157 O GLU A 23 22.937 3.039 -12.842 1.00 16.24 O -ATOM 158 CB GLU A 23 25.664 4.939 -13.797 1.00 20.16 C -ATOM 159 CG GLU A 23 26.201 3.519 -13.776 1.00 40.65 C -ATOM 160 CD GLU A 23 28.243 3.900 -13.483 1.00 70.75 C -ATOM 161 OE1 GLU A 23 27.931 3.380 -11.875 1.00 57.57 O -ATOM 162 OE2 GLU A 23 28.452 5.212 -13.971 1.00 57.46 O -ATOM 163 N TYR A 24 23.179 5.044 -11.863 1.00 18.60 N -ATOM 164 CA TYR A 24 22.505 4.593 -10.679 1.00 26.35 C -ATOM 165 C TYR A 24 21.016 4.562 -11.095 1.00 17.67 C -ATOM 166 O TYR A 24 20.360 3.603 -10.478 1.00 17.15 O -ATOM 167 CB TYR A 24 22.464 5.807 -9.581 1.00 21.47 C -ATOM 168 CG TYR A 24 23.992 5.643 -8.868 1.00 17.94 C -ATOM 169 CD1 TYR A 24 24.282 6.445 -7.897 1.00 25.54 C -ATOM 170 CD2 TYR A 24 24.950 4.858 -9.353 1.00 18.41 C -ATOM 171 CE1 TYR A 24 25.677 6.369 -7.422 1.00 27.77 C -ATOM 172 CE2 TYR A 24 26.305 4.768 -8.960 1.00 24.84 C -ATOM 173 CZ TYR A 24 26.528 5.702 -7.748 1.00 28.92 C -ATOM 174 OH TYR A 24 27.827 5.849 -7.564 1.00 33.79 O -ATOM 175 N GLY A 25 20.378 5.478 -11.759 1.00 17.58 N -ATOM 176 CA GLY A 25 19.016 5.420 -12.390 1.00 16.95 C -ATOM 177 C GLY A 25 18.833 4.130 -12.941 1.00 12.93 C -ATOM 178 O GLY A 25 17.819 3.343 -12.872 1.00 14.53 O -ATOM 179 N ALA A 26 19.615 3.604 -13.915 1.00 15.78 N -ATOM 180 CA ALA A 26 19.582 2.579 -14.539 1.00 18.05 C -ATOM 181 C ALA A 26 19.480 1.089 -13.772 1.00 13.38 C -ATOM 182 O ALA A 26 18.901 0.084 -13.805 1.00 13.68 O -ATOM 183 CB ALA A 26 20.556 2.124 -15.501 1.00 21.17 C -ATOM 184 N GLU A 27 20.535 1.124 -12.715 1.00 13.26 N -ATOM 185 CA GLU A 27 20.575 0.021 -11.753 1.00 15.73 C -ATOM 186 C GLU A 27 19.308 -0.043 -10.886 1.00 9.69 C -ATOM 187 O GLU A 27 18.918 -1.164 -10.735 1.00 13.70 O -ATOM 188 CB GLU A 27 21.903 0.397 -10.962 1.00 17.47 C -ATOM 189 CG GLU A 27 21.998 -0.702 -9.888 1.00 16.72 C -ATOM 190 CD GLU A 27 23.378 -0.554 -8.914 1.00 28.34 C -ATOM 191 OE1 GLU A 27 23.164 -0.938 -7.844 1.00 20.53 O -ATOM 192 OE2 GLU A 27 24.282 0.068 -9.385 1.00 20.32 O -ATOM 193 N ALA A 28 18.802 1.101 -10.459 1.00 11.71 N -ATOM 194 CA ALA A 28 17.589 1.092 -9.707 1.00 14.08 C -ATOM 195 C ALA A 28 16.437 0.281 -10.410 1.00 18.50 C -ATOM 196 O ALA A 28 15.609 -0.358 -10.010 1.00 12.43 O -ATOM 197 CB ALA A 28 17.166 2.432 -9.252 1.00 19.09 C -ATOM 198 N LEU A 29 16.400 0.918 -11.698 1.00 12.19 N -ATOM 199 CA LEU A 29 15.328 0.075 -12.594 1.00 17.48 C -ATOM 200 C LEU A 29 15.559 -1.439 -12.734 1.00 9.74 C -ATOM 201 O LEU A 29 14.606 -2.189 -12.644 1.00 10.80 O -ATOM 202 CB LEU A 29 15.302 0.859 -14.203 1.00 12.13 C -ATOM 203 CG LEU A 29 14.894 2.291 -14.067 1.00 14.66 C -ATOM 204 CD1 LEU A 29 15.261 2.690 -15.515 1.00 16.80 C -ATOM 205 CD2 LEU A 29 13.402 2.225 -13.944 1.00 18.58 C -ATOM 206 N GLU A 30 16.843 -1.859 -13.083 1.00 9.20 N -ATOM 207 CA GLU A 30 17.065 -3.260 -13.067 1.00 11.66 C -ATOM 208 C GLU A 30 16.682 -4.043 -11.806 1.00 13.48 C -ATOM 209 O GLU A 30 16.222 -5.112 -11.842 1.00 17.00 O -ATOM 210 CB GLU A 30 18.445 -3.450 -13.556 1.00 19.11 C -ATOM 211 CG GLU A 30 18.613 -4.789 -13.421 1.00 27.23 C -ATOM 212 CD GLU A 30 20.397 -5.050 -14.290 1.00 43.77 C -ATOM 213 OE1 GLU A 30 21.034 -4.018 -14.191 1.00 45.21 O -ATOM 214 OE2 GLU A 30 20.320 -6.204 -14.925 1.00 45.13 O -ATOM 215 N ARG A 31 17.074 -3.325 -10.709 1.00 11.70 N -ATOM 216 CA ARG A 31 16.706 -3.885 -9.384 1.00 13.69 C -ATOM 217 C ARG A 31 15.116 -4.077 -9.266 1.00 13.95 C -ATOM 218 O ARG A 31 14.772 -5.201 -8.729 1.00 16.42 O -ATOM 219 CB ARG A 31 17.207 -3.143 -8.212 1.00 9.32 C -ATOM 220 CG ARG A 31 18.786 -3.298 -8.162 1.00 14.85 C -ATOM 221 CD ARG A 31 19.223 -2.383 -7.101 1.00 20.12 C -ATOM 222 NE ARG A 31 20.863 -2.372 -6.759 1.00 14.83 N -ATOM 223 CZ ARG A 31 21.361 -3.431 -6.210 1.00 13.22 C -ATOM 224 NH1 ARG A 31 20.746 -4.460 -5.716 1.00 11.40 N -ATOM 225 NH2 ARG A 31 22.719 -3.344 -6.301 1.00 17.34 N -ATOM 226 N MET A 32 14.439 -3.020 -9.681 1.00 11.37 N -ATOM 227 CA MET A 32 13.032 -3.139 -9.600 1.00 10.16 C -ATOM 228 C MET A 32 12.471 -4.206 -10.484 1.00 12.10 C -ATOM 229 O MET A 32 11.562 -5.027 -10.075 1.00 12.78 O -ATOM 230 CB MET A 32 12.387 -1.842 -9.978 1.00 12.48 C -ATOM 231 CG MET A 32 10.889 -1.620 -9.930 1.00 17.73 C -ATOM 232 SD MET A 32 10.285 -0.089 -10.543 1.00 15.12 S -ATOM 233 CE MET A 32 10.633 -0.449 -12.284 1.00 11.32 C -ATOM 234 N PHE A 33 12.859 -4.341 -11.658 1.00 13.98 N -ATOM 235 CA PHE A 33 12.423 -5.476 -12.584 1.00 16.07 C -ATOM 236 C PHE A 33 12.551 -6.737 -12.305 1.00 12.29 C -ATOM 237 O PHE A 33 11.788 -7.686 -12.349 1.00 14.84 O -ATOM 238 CB PHE A 33 12.947 -5.237 -13.990 1.00 11.16 C -ATOM 239 CG PHE A 33 12.536 -3.998 -14.641 1.00 10.01 C -ATOM 240 CD1 PHE A 33 11.466 -3.383 -14.673 1.00 13.62 C -ATOM 241 CD2 PHE A 33 13.679 -3.464 -15.536 1.00 19.46 C -ATOM 242 CE1 PHE A 33 11.074 -2.180 -15.483 1.00 17.65 C -ATOM 243 CE2 PHE A 33 13.177 -2.070 -16.087 1.00 14.83 C -ATOM 244 CZ PHE A 33 12.158 -1.591 -16.095 1.00 12.93 C -ATOM 245 N LEU A 34 13.735 -6.963 -11.432 1.00 16.04 N -ATOM 246 CA LEU A 34 14.079 -8.337 -11.022 1.00 14.57 C -ATOM 247 C LEU A 34 13.293 -8.578 -9.676 1.00 17.64 C -ATOM 248 O LEU A 34 12.997 -9.724 -9.442 1.00 18.98 O -ATOM 249 CB LEU A 34 15.453 -8.526 -10.814 1.00 18.08 C -ATOM 250 CG LEU A 34 16.401 -8.680 -11.761 1.00 28.60 C -ATOM 251 CD1 LEU A 34 17.957 -8.573 -11.703 1.00 25.37 C -ATOM 252 CD2 LEU A 34 15.936 -9.330 -12.871 1.00 34.83 C -ATOM 253 N SER A 35 13.220 -7.510 -8.706 1.00 15.41 N -ATOM 254 CA SER A 35 12.815 -7.908 -7.502 1.00 14.95 C -ATOM 255 C SER A 35 11.238 -7.909 -7.418 1.00 15.69 C -ATOM 256 O SER A 35 10.517 -8.531 -6.585 1.00 14.29 O -ATOM 257 CB SER A 35 13.131 -6.749 -6.442 1.00 13.14 C -ATOM 258 OG SER A 35 14.485 -7.014 -6.085 1.00 17.78 O -ATOM 259 N PHE A 36 10.680 -7.033 -8.262 1.00 13.54 N -ATOM 260 CA PHE A 36 9.195 -6.850 -8.454 1.00 13.46 C -ATOM 261 C PHE A 36 8.843 -6.910 -9.927 1.00 8.62 C -ATOM 262 O PHE A 36 8.478 -5.788 -10.556 1.00 14.12 O -ATOM 263 CB PHE A 36 8.936 -5.457 -7.919 1.00 16.50 C -ATOM 264 CG PHE A 36 9.418 -4.974 -6.493 1.00 13.63 C -ATOM 265 CD1 PHE A 36 10.591 -4.292 -6.329 1.00 11.92 C -ATOM 266 CD2 PHE A 36 8.828 -5.831 -5.362 1.00 19.28 C -ATOM 267 CE1 PHE A 36 11.048 -4.090 -5.054 1.00 15.75 C -ATOM 268 CE2 PHE A 36 9.372 -5.629 -4.112 1.00 13.78 C -ATOM 269 CZ PHE A 36 10.535 -4.872 -4.007 1.00 15.33 C -ATOM 270 N PRO A 37 8.621 -8.156 -10.145 1.00 14.18 N -ATOM 271 CA PRO A 37 8.292 -8.333 -11.715 1.00 17.12 C -ATOM 272 C PRO A 37 7.088 -7.804 -12.224 1.00 17.85 C -ATOM 273 O PRO A 37 6.976 -7.542 -13.453 1.00 18.50 O -ATOM 274 CB PRO A 37 8.433 -9.844 -11.897 1.00 23.37 C -ATOM 275 CG PRO A 37 8.573 -10.410 -10.572 1.00 28.27 C -ATOM 276 CD PRO A 37 8.857 -9.204 -9.532 1.00 20.43 C -ATOM 277 N THR A 38 6.105 -7.481 -11.322 1.00 18.86 N -ATOM 278 CA THR A 38 4.849 -6.949 -11.938 1.00 14.66 C -ATOM 279 C THR A 38 5.134 -5.609 -12.568 1.00 12.72 C -ATOM 280 O THR A 38 4.433 -5.064 -13.326 1.00 15.75 O -ATOM 281 CB THR A 38 3.879 -6.749 -10.732 1.00 19.10 C -ATOM 282 OG1 THR A 38 4.340 -6.112 -9.661 1.00 18.82 O -ATOM 283 CG2 THR A 38 3.543 -8.224 -10.416 1.00 22.69 C -ATOM 284 N THR A 39 6.269 -4.882 -12.154 1.00 14.27 N -ATOM 285 CA THR A 39 6.491 -3.556 -12.776 1.00 10.19 C -ATOM 286 C THR A 39 6.886 -3.690 -14.302 1.00 10.17 C -ATOM 287 O THR A 39 6.836 -2.719 -14.886 1.00 14.01 O -ATOM 288 CB THR A 39 7.510 -2.917 -11.996 1.00 15.56 C -ATOM 289 OG1 THR A 39 8.881 -3.562 -11.937 1.00 14.68 O -ATOM 290 CG2 THR A 39 7.258 -2.652 -10.511 1.00 20.52 C -ATOM 291 N LYS A 40 7.174 -4.831 -14.593 1.00 14.72 N -ATOM 292 CA LYS A 40 7.574 -4.871 -15.954 1.00 15.89 C -ATOM 293 C LYS A 40 6.392 -4.785 -17.012 1.00 21.37 C -ATOM 294 O LYS A 40 6.437 -4.614 -18.103 1.00 15.72 O -ATOM 295 CB LYS A 40 8.145 -6.482 -16.338 1.00 11.64 C -ATOM 296 CG LYS A 40 9.529 -6.584 -15.725 1.00 16.19 C -ATOM 297 CD LYS A 40 10.167 -7.889 -16.138 1.00 23.35 C -ATOM 298 CE LYS A 40 9.677 -9.033 -15.597 1.00 24.42 C -ATOM 299 NZ LYS A 40 10.352 -10.362 -15.922 1.00 19.04 N -ATOM 300 N THR A 41 5.127 -4.865 -16.397 1.00 13.16 N -ATOM 301 CA THR A 41 3.875 -4.707 -17.174 1.00 14.78 C -ATOM 302 C THR A 41 3.932 -3.487 -17.746 1.00 15.32 C -ATOM 303 O THR A 41 3.044 -3.054 -18.672 1.00 15.67 O -ATOM 304 CB THR A 41 2.612 -5.037 -16.228 1.00 15.38 C -ATOM 305 OG1 THR A 41 2.526 -4.071 -15.248 1.00 14.93 O -ATOM 306 CG2 THR A 41 2.578 -6.405 -15.884 1.00 16.57 C -ATOM 307 N TYR A 42 4.610 -2.356 -17.311 1.00 10.46 N -ATOM 308 CA TYR A 42 4.398 -1.015 -17.861 1.00 12.73 C -ATOM 309 C TYR A 42 5.571 -0.792 -19.101 1.00 7.07 C -ATOM 310 O TYR A 42 5.611 0.312 -19.642 1.00 12.11 O -ATOM 311 CB TYR A 42 4.898 -0.049 -16.794 1.00 14.67 C -ATOM 312 CG TYR A 42 3.618 0.026 -15.875 1.00 13.54 C -ATOM 313 CD1 TYR A 42 2.437 0.794 -16.095 1.00 19.68 C -ATOM 314 CD2 TYR A 42 3.661 -0.765 -14.634 1.00 18.38 C -ATOM 315 CE1 TYR A 42 1.433 0.570 -15.142 1.00 23.98 C -ATOM 316 CE2 TYR A 42 2.601 -0.739 -13.758 1.00 13.41 C -ATOM 317 CZ TYR A 42 1.469 -0.048 -14.033 1.00 18.96 C -ATOM 318 OH TYR A 42 0.436 -0.054 -13.115 1.00 19.81 O -ATOM 319 N PHE A 43 6.476 -1.826 -19.154 1.00 17.11 N -ATOM 320 CA PHE A 43 7.621 -1.843 -20.115 1.00 18.18 C -ATOM 321 C PHE A 43 7.472 -2.895 -21.133 1.00 24.86 C -ATOM 322 O PHE A 43 8.506 -3.413 -21.456 1.00 22.13 O -ATOM 323 CB PHE A 43 8.883 -1.731 -19.445 1.00 15.44 C -ATOM 324 CG PHE A 43 9.117 -0.406 -18.576 1.00 14.36 C -ATOM 325 CD1 PHE A 43 8.554 -0.479 -17.198 1.00 14.47 C -ATOM 326 CD2 PHE A 43 9.564 0.739 -18.886 1.00 16.54 C -ATOM 327 CE1 PHE A 43 8.777 0.624 -16.478 1.00 20.56 C -ATOM 328 CE2 PHE A 43 9.747 1.973 -18.107 1.00 17.61 C -ATOM 329 CZ PHE A 43 9.344 1.707 -16.778 1.00 18.88 C -ATOM 330 N PRO A 44 6.315 -3.239 -21.641 1.00 18.09 N -ATOM 331 CA PRO A 44 6.381 -4.414 -22.439 1.00 22.24 C -ATOM 332 C PRO A 44 7.028 -3.933 -24.077 1.00 24.15 C -ATOM 333 O PRO A 44 7.495 -4.754 -24.733 1.00 24.01 O -ATOM 334 CB PRO A 44 5.048 -4.531 -22.752 1.00 28.44 C -ATOM 335 CG PRO A 44 4.370 -3.210 -22.675 1.00 24.77 C -ATOM 336 CD PRO A 44 5.151 -2.594 -21.501 1.00 21.37 C -ATOM 337 N HIS A 45 7.181 -2.759 -24.200 1.00 22.61 N -ATOM 338 CA HIS A 45 7.861 -2.190 -25.416 1.00 32.33 C -ATOM 339 C HIS A 45 9.330 -2.042 -25.421 1.00 27.50 C -ATOM 340 O HIS A 45 9.974 -1.539 -26.257 1.00 22.34 O -ATOM 341 CB HIS A 45 7.358 -0.919 -25.693 1.00 28.91 C -ATOM 342 CG HIS A 45 7.192 0.375 -24.801 1.00 24.48 C -ATOM 343 ND1 HIS A 45 6.886 -0.058 -23.407 1.00 28.61 N -ATOM 344 CD2 HIS A 45 7.956 1.463 -24.795 1.00 25.11 C -ATOM 345 CE1 HIS A 45 7.011 1.085 -22.716 1.00 26.97 C -ATOM 346 NE2 HIS A 45 7.765 2.042 -23.628 1.00 30.40 N -ATOM 347 N PHE A 46 10.122 -2.386 -24.054 1.00 17.28 N -ATOM 348 CA PHE A 46 11.455 -2.262 -23.909 1.00 16.89 C -ATOM 349 C PHE A 46 12.005 -3.636 -24.127 1.00 16.17 C -ATOM 350 O PHE A 46 11.604 -4.686 -23.635 1.00 18.14 O -ATOM 351 CB PHE A 46 11.684 -1.700 -22.434 1.00 19.02 C -ATOM 352 CG PHE A 46 11.699 -0.399 -22.451 1.00 24.73 C -ATOM 353 CD1 PHE A 46 12.430 0.377 -21.434 1.00 19.60 C -ATOM 354 CD2 PHE A 46 11.298 0.412 -23.118 1.00 32.07 C -ATOM 355 CE1 PHE A 46 12.410 1.666 -21.260 1.00 16.62 C -ATOM 356 CE2 PHE A 46 11.265 1.969 -23.113 1.00 32.95 C -ATOM 357 CZ PHE A 46 11.777 2.738 -22.175 1.00 26.82 C -ATOM 358 N ASP A 47 13.392 -3.464 -24.534 1.00 19.28 N -ATOM 359 CA ASP A 47 14.201 -4.676 -24.267 1.00 21.11 C -ATOM 360 C ASP A 47 14.839 -4.498 -22.659 1.00 19.86 C -ATOM 361 O ASP A 47 15.431 -3.489 -22.547 1.00 21.26 O -ATOM 362 CB ASP A 47 15.523 -4.420 -25.240 1.00 18.49 C -ATOM 363 CG ASP A 47 16.401 -5.761 -25.037 1.00 31.25 C -ATOM 364 OD1 ASP A 47 16.311 -6.607 -24.275 1.00 29.75 O -ATOM 365 OD2 ASP A 47 17.439 -5.328 -25.588 1.00 43.41 O -ATOM 366 N LEU A 48 14.368 -5.324 -22.041 1.00 24.03 N -ATOM 367 CA LEU A 48 14.753 -5.341 -20.734 1.00 18.27 C -ATOM 368 C LEU A 48 15.791 -6.404 -20.198 1.00 36.02 C -ATOM 369 O LEU A 48 16.171 -6.209 -19.141 1.00 39.74 O -ATOM 370 CB LEU A 48 13.415 -5.610 -19.721 1.00 19.69 C -ATOM 371 CG LEU A 48 12.489 -4.486 -19.789 1.00 21.82 C -ATOM 372 CD1 LEU A 48 11.174 -5.208 -18.951 1.00 33.27 C -ATOM 373 CD2 LEU A 48 12.620 -3.262 -19.549 1.00 24.10 C -ATOM 374 N SER A 49 16.783 -6.499 -21.225 1.00 29.95 N -ATOM 375 CA SER A 49 18.122 -7.384 -21.060 1.00 36.57 C -ATOM 376 C SER A 49 18.846 -6.374 -20.277 1.00 27.84 C -ATOM 377 O SER A 49 19.000 -5.086 -20.358 1.00 22.88 O -ATOM 378 CB SER A 49 18.154 -8.122 -22.211 1.00 37.22 C -ATOM 379 OG SER A 49 18.651 -7.428 -22.904 1.00 43.53 O -ATOM 380 N HIS A 50 19.910 -7.126 -19.381 1.00 28.70 N -ATOM 381 CA HIS A 50 20.458 -5.929 -18.816 1.00 33.73 C -ATOM 382 C HIS A 50 21.497 -5.179 -19.493 1.00 26.32 C -ATOM 383 O HIS A 50 22.162 -5.918 -20.594 1.00 31.00 O -ATOM 384 CB HIS A 50 21.839 -7.147 -17.996 1.00 52.72 C -ATOM 385 CG HIS A 50 22.748 -6.326 -17.477 1.00 44.40 C -ATOM 386 ND1 HIS A 50 22.626 -5.701 -16.215 1.00 33.80 N -ATOM 387 CD2 HIS A 50 24.218 -6.937 -17.247 1.00 47.43 C -ATOM 388 CE1 HIS A 50 23.812 -5.042 -15.891 1.00 41.56 C -ATOM 389 NE2 HIS A 50 24.721 -5.696 -16.698 1.00 46.05 N -ATOM 390 N GLY A 51 21.750 -4.254 -19.494 1.00 24.77 N -ATOM 391 CA GLY A 51 22.455 -3.151 -20.084 1.00 47.57 C -ATOM 392 C GLY A 51 21.857 -2.536 -21.373 1.00 38.90 C -ATOM 393 O GLY A 51 22.594 -2.038 -22.085 1.00 36.29 O -ATOM 394 N SER A 52 20.675 -3.017 -21.484 1.00 31.32 N -ATOM 395 CA SER A 52 19.963 -2.196 -22.851 1.00 26.23 C -ATOM 396 C SER A 52 20.134 -0.997 -22.782 1.00 16.57 C -ATOM 397 O SER A 52 19.933 -0.129 -21.983 1.00 20.02 O -ATOM 398 CB SER A 52 18.619 -2.881 -22.964 1.00 27.24 C -ATOM 399 OG SER A 52 17.746 -2.046 -22.388 1.00 23.82 O -ATOM 400 N ALA A 53 20.194 -0.382 -24.103 1.00 17.74 N -ATOM 401 CA ALA A 53 20.270 0.998 -24.154 1.00 23.86 C -ATOM 402 C ALA A 53 18.923 1.773 -23.848 1.00 16.18 C -ATOM 403 O ALA A 53 18.953 2.849 -23.330 1.00 19.42 O -ATOM 404 CB ALA A 53 20.303 1.395 -25.787 1.00 25.47 C -ATOM 405 N GLN A 54 17.736 0.981 -23.874 1.00 20.85 N -ATOM 406 CA GLN A 54 16.512 1.657 -23.573 1.00 13.59 C -ATOM 407 C GLN A 54 16.574 1.828 -21.914 1.00 19.26 C -ATOM 408 O GLN A 54 15.942 2.867 -21.609 1.00 20.48 O -ATOM 409 CB GLN A 54 15.353 0.611 -23.904 1.00 15.39 C -ATOM 410 CG GLN A 54 14.983 0.803 -25.364 1.00 20.40 C -ATOM 411 CD GLN A 54 14.209 -0.311 -25.782 1.00 15.48 C -ATOM 412 OE1 GLN A 54 14.579 -1.521 -25.849 1.00 23.45 O -ATOM 413 NE2 GLN A 54 13.268 -0.063 -26.856 1.00 19.86 N -ATOM 414 N VAL A 55 16.964 0.770 -21.300 1.00 16.87 N -ATOM 415 CA VAL A 55 17.057 0.967 -19.825 1.00 16.48 C -ATOM 416 C VAL A 55 17.956 2.003 -19.318 1.00 17.36 C -ATOM 417 O VAL A 55 17.791 2.873 -18.570 1.00 18.40 O -ATOM 418 CB VAL A 55 17.306 -0.514 -19.268 1.00 14.78 C -ATOM 419 CG1 VAL A 55 17.609 -0.401 -17.796 1.00 21.77 C -ATOM 420 CG2 VAL A 55 16.107 -1.297 -19.446 1.00 16.83 C -ATOM 421 N LYS A 56 19.228 1.986 -19.953 1.00 16.43 N -ATOM 422 CA LYS A 56 20.094 3.039 -19.797 1.00 16.52 C -ATOM 423 C LYS A 56 19.566 4.272 -19.699 1.00 21.58 C -ATOM 424 O LYS A 56 19.825 5.350 -19.163 1.00 20.11 O -ATOM 425 CB LYS A 56 21.563 2.786 -20.316 1.00 18.35 C -ATOM 426 CG LYS A 56 21.968 1.412 -19.848 1.00 28.49 C -ATOM 427 CD LYS A 56 23.832 1.798 -20.631 1.00 44.71 C -ATOM 428 CE LYS A 56 24.647 0.185 -20.276 1.00 47.65 C -ATOM 429 NZ LYS A 56 26.042 0.618 -20.926 1.00 52.31 N -ATOM 430 N GLY A 57 19.018 4.549 -21.123 1.00 17.21 N -ATOM 431 CA GLY A 57 18.386 5.829 -21.439 1.00 25.10 C -ATOM 432 C GLY A 57 17.163 6.322 -20.441 1.00 19.44 C -ATOM 433 O GLY A 57 17.339 7.478 -20.078 1.00 20.54 O -ATOM 434 N HIS A 58 16.465 5.322 -20.170 1.00 18.79 N -ATOM 435 CA HIS A 58 15.350 5.701 -19.218 1.00 20.27 C -ATOM 436 C HIS A 58 15.995 6.080 -17.623 1.00 13.51 C -ATOM 437 O HIS A 58 15.432 7.056 -17.182 1.00 17.47 O -ATOM 438 CB HIS A 58 14.449 4.447 -19.262 1.00 17.90 C -ATOM 439 CG HIS A 58 13.058 4.996 -18.478 1.00 15.76 C -ATOM 440 ND1 HIS A 58 12.287 6.114 -18.800 1.00 20.40 N -ATOM 441 CD2 HIS A 58 12.522 4.394 -17.450 1.00 20.31 C -ATOM 442 CE1 HIS A 58 11.473 6.092 -17.719 1.00 20.13 C -ATOM 443 NE2 HIS A 58 11.497 5.103 -17.065 1.00 21.08 N -ATOM 444 N GLY A 59 16.881 5.222 -17.443 1.00 14.95 N -ATOM 445 CA GLY A 59 17.562 5.623 -16.096 1.00 18.11 C -ATOM 446 C GLY A 59 18.124 6.806 -15.942 1.00 19.85 C -ATOM 447 O GLY A 59 17.932 7.718 -15.003 1.00 15.36 O -ATOM 448 N LYS A 60 18.701 7.399 -17.074 1.00 17.17 N -ATOM 449 CA LYS A 60 19.105 8.846 -17.109 1.00 18.34 C -ATOM 450 C LYS A 60 18.266 9.905 -16.940 1.00 18.03 C -ATOM 451 O LYS A 60 18.249 10.847 -16.377 1.00 18.72 O -ATOM 452 CB LYS A 60 20.142 9.096 -18.402 1.00 30.65 C -ATOM 453 CG LYS A 60 20.617 10.355 -18.546 1.00 41.57 C -ATOM 454 CD LYS A 60 21.486 10.272 -19.721 1.00 63.44 C -ATOM 455 CE LYS A 60 22.042 12.123 -19.760 1.00 44.10 C -ATOM 456 NZ LYS A 60 23.253 10.931 -21.838 1.00 49.08 N -ATOM 457 N LYS A 61 17.057 9.480 -17.740 1.00 16.33 N -ATOM 458 CA LYS A 61 15.986 10.442 -17.612 1.00 17.87 C -ATOM 459 C LYS A 61 15.127 10.479 -16.158 1.00 14.89 C -ATOM 460 O LYS A 61 14.981 11.608 -15.829 1.00 19.71 O -ATOM 461 CB LYS A 61 14.717 10.033 -18.529 1.00 25.67 C -ATOM 462 CG LYS A 61 14.971 10.361 -20.143 1.00 41.04 C -ATOM 463 CD LYS A 61 13.959 9.646 -21.043 1.00 54.25 C -ATOM 464 CE LYS A 61 14.061 9.666 -21.851 1.00 78.95 C -ATOM 465 NZ LYS A 61 13.029 9.011 -23.092 1.00 43.58 N -ATOM 466 N VAL A 62 15.316 9.304 -15.709 1.00 15.10 N -ATOM 467 CA VAL A 62 14.699 9.322 -14.234 1.00 16.18 C -ATOM 468 C VAL A 62 15.686 10.200 -13.093 1.00 18.93 C -ATOM 469 O VAL A 62 15.095 11.051 -12.555 1.00 16.64 O -ATOM 470 CB VAL A 62 14.660 7.890 -13.835 1.00 13.59 C -ATOM 471 CG1 VAL A 62 14.141 7.704 -12.419 1.00 20.28 C -ATOM 472 CG2 VAL A 62 13.407 7.365 -14.552 1.00 17.24 C -ATOM 473 N ALA A 63 16.863 9.822 -13.546 1.00 18.60 N -ATOM 474 CA ALA A 63 17.806 10.661 -12.634 1.00 14.91 C -ATOM 475 C ALA A 63 18.050 11.967 -12.922 1.00 18.47 C -ATOM 476 O ALA A 63 17.940 12.889 -11.976 1.00 18.58 O -ATOM 477 CB ALA A 63 19.170 9.768 -12.782 1.00 37.76 C -ATOM 478 N ASP A 64 17.821 12.573 -14.198 1.00 16.80 N -ATOM 479 CA ASP A 64 17.733 13.912 -14.174 1.00 24.74 C -ATOM 480 C ASP A 64 16.549 14.773 -13.697 1.00 17.12 C -ATOM 481 O ASP A 64 16.672 15.717 -13.116 1.00 22.08 O -ATOM 482 CB ASP A 64 17.603 14.212 -15.737 1.00 35.97 C -ATOM 483 CG ASP A 64 19.349 14.293 -16.612 1.00 31.06 C -ATOM 484 OD1 ASP A 64 20.156 13.672 -15.497 1.00 35.72 O -ATOM 485 OD2 ASP A 64 18.977 14.172 -17.839 1.00 43.58 O -ATOM 486 N ALA A 65 15.332 13.912 -13.869 1.00 13.28 N -ATOM 487 CA ALA A 65 14.329 14.415 -13.017 1.00 17.27 C -ATOM 488 C ALA A 65 14.445 14.482 -11.415 1.00 13.03 C -ATOM 489 O ALA A 65 13.989 15.536 -11.013 1.00 17.77 O -ATOM 490 CB ALA A 65 12.982 13.578 -13.361 1.00 23.35 C -ATOM 491 N LEU A 66 15.162 13.498 -11.063 1.00 15.51 N -ATOM 492 CA LEU A 66 15.339 13.706 -9.605 1.00 11.63 C -ATOM 493 C LEU A 66 16.337 14.754 -9.333 1.00 19.15 C -ATOM 494 O LEU A 66 16.146 15.585 -8.334 1.00 19.52 O -ATOM 495 CB LEU A 66 15.829 12.371 -9.144 1.00 13.76 C -ATOM 496 CG LEU A 66 14.823 11.115 -8.963 1.00 19.82 C -ATOM 497 CD1 LEU A 66 15.489 9.880 -8.746 1.00 18.79 C -ATOM 498 CD2 LEU A 66 13.658 11.434 -8.143 1.00 21.54 C -ATOM 499 N THR A 67 17.286 14.890 -10.137 1.00 15.35 N -ATOM 500 CA THR A 67 18.223 15.978 -10.096 1.00 19.22 C -ATOM 501 C THR A 67 17.538 17.420 -10.103 1.00 19.35 C -ATOM 502 O THR A 67 17.647 18.426 -9.135 1.00 25.50 O -ATOM 503 CB THR A 67 19.391 15.815 -10.975 1.00 27.92 C -ATOM 504 OG1 THR A 67 20.048 14.951 -10.890 1.00 31.77 O -ATOM 505 CG2 THR A 67 20.007 17.263 -11.105 1.00 31.55 C -ATOM 506 N ASN A 68 16.575 17.470 -11.016 1.00 18.73 N -ATOM 507 CA ASN A 68 15.744 18.747 -11.028 1.00 18.68 C -ATOM 508 C ASN A 68 14.923 18.912 -9.894 1.00 24.52 C -ATOM 509 O ASN A 68 14.765 20.137 -9.247 1.00 25.75 O -ATOM 510 CB ASN A 68 14.756 18.608 -12.121 1.00 25.79 C -ATOM 511 CG ASN A 68 13.735 19.831 -12.299 1.00 36.65 C -ATOM 512 OD1 ASN A 68 14.126 20.875 -12.151 1.00 38.63 O -ATOM 513 ND2 ASN A 68 12.596 19.698 -13.037 1.00 39.67 N -ATOM 514 N ALA A 69 14.365 17.791 -9.099 1.00 17.85 N -ATOM 515 CA ALA A 69 13.480 18.120 -7.964 1.00 16.12 C -ATOM 516 C ALA A 69 14.454 18.477 -6.733 1.00 15.28 C -ATOM 517 O ALA A 69 14.055 19.178 -5.996 1.00 20.90 O -ATOM 518 CB ALA A 69 13.019 16.796 -7.635 1.00 21.91 C -ATOM 519 N VAL A 70 15.742 17.807 -6.739 1.00 18.42 N -ATOM 520 CA VAL A 70 16.670 18.320 -5.560 1.00 18.79 C -ATOM 521 C VAL A 70 17.052 19.774 -5.743 1.00 21.40 C -ATOM 522 O VAL A 70 16.986 20.472 -4.749 1.00 22.44 O -ATOM 523 CB VAL A 70 17.782 17.521 -5.616 1.00 19.75 C -ATOM 524 CG1 VAL A 70 19.021 17.739 -4.714 1.00 24.49 C -ATOM 525 CG2 VAL A 70 17.476 16.043 -5.206 1.00 30.23 C -ATOM 526 N ALA A 71 17.156 20.293 -6.971 1.00 20.17 N -ATOM 527 CA ALA A 71 17.389 21.815 -7.308 1.00 23.56 C -ATOM 528 C ALA A 71 16.370 22.294 -6.912 1.00 25.98 C -ATOM 529 O ALA A 71 16.635 23.655 -6.511 1.00 33.09 O -ATOM 530 CB ALA A 71 17.654 21.789 -8.655 1.00 32.78 C -ATOM 531 N HIS A 72 15.081 22.080 -6.888 1.00 23.78 N -ATOM 532 CA HIS A 72 13.997 22.837 -6.617 1.00 21.95 C -ATOM 533 C HIS A 72 13.181 22.411 -5.617 1.00 20.17 C -ATOM 534 O HIS A 72 11.897 22.212 -5.613 1.00 23.99 O -ATOM 535 CB HIS A 72 12.821 22.953 -7.947 1.00 35.07 C -ATOM 536 CG HIS A 72 13.866 23.277 -8.689 1.00 34.89 C -ATOM 537 ND1 HIS A 72 13.873 24.932 -9.510 1.00 43.74 N -ATOM 538 CD2 HIS A 72 14.464 23.117 -10.031 1.00 29.96 C -ATOM 539 CE1 HIS A 72 15.153 25.255 -9.959 1.00 41.69 C -ATOM 540 NE2 HIS A 72 15.223 24.225 -10.948 1.00 44.85 N -ATOM 541 N VAL A 73 13.752 21.857 -4.446 1.00 23.31 N -ATOM 542 CA VAL A 73 13.057 21.077 -3.315 1.00 23.32 C -ATOM 543 C VAL A 73 12.075 21.651 -2.904 1.00 32.07 C -ATOM 544 O VAL A 73 10.955 21.485 -2.533 1.00 42.18 O -ATOM 545 CB VAL A 73 13.998 20.556 -2.485 1.00 41.19 C -ATOM 546 CG1 VAL A 73 14.923 21.399 -1.795 1.00 52.76 C -ATOM 547 CG2 VAL A 73 13.799 19.262 -2.036 1.00 47.91 C -ATOM 548 N ASP A 74 12.275 23.065 -2.789 1.00 30.40 N -ATOM 549 CA ASP A 74 11.145 24.002 -2.142 1.00 34.95 C -ATOM 550 C ASP A 74 10.049 24.015 -3.350 1.00 50.97 C -ATOM 551 O ASP A 74 9.132 24.778 -2.717 1.00 49.62 O -ATOM 552 CB ASP A 74 11.678 25.422 -2.020 1.00 42.77 C -ATOM 553 CG ASP A 74 12.830 25.304 -0.645 1.00 52.01 C -ATOM 554 OD1 ASP A 74 12.752 24.865 0.015 1.00 49.67 O -ATOM 555 OD2 ASP A 74 14.337 25.661 -0.918 1.00 51.46 O -ATOM 556 N ASP A 75 9.922 23.915 -4.261 1.00 36.55 N -ATOM 557 CA ASP A 75 8.668 23.936 -5.208 1.00 36.46 C -ATOM 558 C ASP A 75 8.874 22.788 -6.315 1.00 19.07 C -ATOM 559 O ASP A 75 8.567 23.036 -7.581 1.00 22.77 O -ATOM 560 CB ASP A 75 9.451 25.163 -6.540 1.00 64.13 C -ATOM 561 CG ASP A 75 8.868 25.436 -6.330 1.00 74.46 C -ATOM 562 OD1 ASP A 75 7.314 26.337 -6.605 1.00 47.43 O -ATOM 563 OD2 ASP A 75 8.881 25.994 -8.289 1.00 60.83 O -ATOM 564 N MET A 76 8.625 21.775 -5.634 1.00 28.83 N -ATOM 565 CA MET A 76 8.674 20.530 -6.647 1.00 25.75 C -ATOM 566 C MET A 76 7.271 20.288 -7.401 1.00 26.47 C -ATOM 567 O MET A 76 7.358 19.996 -8.579 1.00 25.06 O -ATOM 568 CB MET A 76 8.643 19.305 -5.552 1.00 26.87 C -ATOM 569 CG MET A 76 9.740 19.092 -5.553 1.00 44.91 C -ATOM 570 SD MET A 76 10.207 17.317 -4.716 1.00 43.69 S -ATOM 571 CE MET A 76 10.186 17.272 -3.278 1.00 47.45 C -ATOM 572 N PRO A 77 6.289 20.734 -6.858 1.00 24.72 N -ATOM 573 CA PRO A 77 5.288 21.011 -7.720 1.00 32.25 C -ATOM 574 C PRO A 77 5.404 21.500 -8.895 1.00 33.71 C -ATOM 575 O PRO A 77 4.843 20.983 -10.107 1.00 27.50 O -ATOM 576 CB PRO A 77 3.868 21.504 -6.885 1.00 35.42 C -ATOM 577 CG PRO A 77 4.538 21.027 -5.570 1.00 42.65 C -ATOM 578 CD PRO A 77 5.873 20.979 -5.490 1.00 26.77 C -ATOM 579 N ASN A 78 5.832 22.745 -9.066 1.00 28.71 N -ATOM 580 CA ASN A 78 5.931 23.542 -10.146 1.00 29.25 C -ATOM 581 C ASN A 78 7.105 22.960 -10.923 1.00 25.30 C -ATOM 582 O ASN A 78 7.043 22.562 -12.258 1.00 31.49 O -ATOM 583 CB ASN A 78 6.292 25.075 -10.189 1.00 52.85 C -ATOM 584 CG ASN A 78 5.615 25.627 -10.060 1.00 62.76 C -ATOM 585 OD1 ASN A 78 4.765 26.184 -8.258 1.00 71.55 O -ATOM 586 ND2 ASN A 78 4.594 25.811 -10.486 1.00 72.60 N -ATOM 587 N ALA A 79 8.114 22.456 -10.315 1.00 21.06 N -ATOM 588 CA ALA A 79 9.264 21.897 -10.989 1.00 28.88 C -ATOM 589 C ALA A 79 8.963 20.522 -11.944 1.00 27.69 C -ATOM 590 O ALA A 79 9.465 20.431 -13.022 1.00 25.51 O -ATOM 591 CB ALA A 79 10.294 21.701 -10.105 1.00 35.64 C -ATOM 592 N LEU A 80 8.232 19.781 -11.312 1.00 22.21 N -ATOM 593 CA LEU A 80 7.767 18.341 -11.815 1.00 24.91 C -ATOM 594 C LEU A 80 6.510 18.562 -12.698 1.00 29.49 C -ATOM 595 O LEU A 80 5.875 17.479 -12.950 1.00 21.47 O -ATOM 596 CB LEU A 80 7.734 17.285 -10.765 1.00 17.03 C -ATOM 597 CG LEU A 80 9.126 17.077 -10.078 1.00 26.04 C -ATOM 598 CD1 LEU A 80 8.930 16.109 -9.016 1.00 30.97 C -ATOM 599 CD2 LEU A 80 10.040 16.545 -11.282 1.00 40.31 C -ATOM 600 N SER A 81 5.857 19.827 -12.942 1.00 21.07 N -ATOM 601 CA SER A 81 4.431 19.687 -13.335 1.00 18.09 C -ATOM 602 C SER A 81 4.363 19.087 -14.671 1.00 20.48 C -ATOM 603 O SER A 81 3.314 18.257 -14.890 1.00 25.77 O -ATOM 604 CB SER A 81 4.467 21.619 -13.861 1.00 32.64 C -ATOM 605 OG SER A 81 2.994 21.456 -13.913 1.00 44.30 O -ATOM 606 N ALA A 82 5.219 18.957 -15.594 1.00 23.80 N -ATOM 607 CA ALA A 82 5.295 18.397 -16.849 1.00 21.23 C -ATOM 608 C ALA A 82 5.047 16.984 -16.596 1.00 19.91 C -ATOM 609 O ALA A 82 4.419 16.133 -17.266 1.00 24.36 O -ATOM 610 CB ALA A 82 6.433 18.664 -17.830 1.00 22.94 C -ATOM 611 N LEU A 83 6.039 16.444 -15.755 1.00 18.35 N -ATOM 612 CA LEU A 83 5.983 14.900 -15.664 1.00 19.01 C -ATOM 613 C LEU A 83 4.967 14.491 -14.735 1.00 18.91 C -ATOM 614 O LEU A 83 4.393 13.347 -14.967 1.00 18.17 O -ATOM 615 CB LEU A 83 7.250 14.624 -14.735 1.00 22.27 C -ATOM 616 CG LEU A 83 8.130 13.821 -15.009 1.00 34.66 C -ATOM 617 CD1 LEU A 83 8.449 13.918 -16.558 1.00 28.24 C -ATOM 618 CD2 LEU A 83 9.756 14.153 -14.680 1.00 38.79 C -ATOM 619 N SER A 84 4.321 15.210 -13.869 1.00 13.22 N -ATOM 620 CA SER A 84 3.091 14.769 -13.309 1.00 14.54 C -ATOM 621 C SER A 84 1.806 14.643 -14.240 1.00 13.50 C -ATOM 622 O SER A 84 1.081 13.802 -14.037 1.00 20.19 O -ATOM 623 CB SER A 84 2.316 15.701 -11.953 1.00 25.45 C -ATOM 624 OG SER A 84 3.028 16.684 -12.075 1.00 36.19 O -ATOM 625 N ASP A 85 1.894 15.645 -15.194 1.00 15.99 N -ATOM 626 CA ASP A 85 0.657 15.457 -16.246 1.00 18.10 C -ATOM 627 C ASP A 85 0.872 14.320 -17.117 1.00 20.71 C -ATOM 628 O ASP A 85 0.085 13.524 -17.249 1.00 20.01 O -ATOM 629 CB ASP A 85 0.847 16.636 -17.207 1.00 30.89 C -ATOM 630 CG ASP A 85 0.240 17.791 -16.350 1.00 57.00 C -ATOM 631 OD1 ASP A 85 -0.408 17.890 -15.984 1.00 51.34 O -ATOM 632 OD2 ASP A 85 0.645 19.250 -17.189 1.00 50.68 O -ATOM 633 N LEU A 86 2.217 13.883 -17.444 1.00 20.13 N -ATOM 634 CA LEU A 86 2.516 12.802 -18.225 1.00 17.03 C -ATOM 635 C LEU A 86 2.094 11.499 -17.604 1.00 14.48 C -ATOM 636 O LEU A 86 1.613 10.536 -18.155 1.00 18.46 O -ATOM 637 CB LEU A 86 4.085 12.859 -18.555 1.00 16.01 C -ATOM 638 CG LEU A 86 4.479 11.856 -19.204 1.00 23.66 C -ATOM 639 CD1 LEU A 86 4.217 11.927 -20.682 1.00 40.43 C -ATOM 640 CD2 LEU A 86 6.063 11.399 -19.455 1.00 33.72 C -ATOM 641 N HIS A 87 2.488 11.534 -16.185 1.00 12.17 N -ATOM 642 CA HIS A 87 2.237 10.125 -15.649 1.00 12.85 C -ATOM 643 C HIS A 87 0.524 10.055 -15.280 1.00 15.39 C -ATOM 644 O HIS A 87 0.114 8.957 -15.394 1.00 15.03 O -ATOM 645 CB HIS A 87 2.873 10.043 -14.177 1.00 13.63 C -ATOM 646 CG HIS A 87 4.357 9.531 -14.510 1.00 14.91 C -ATOM 647 ND1 HIS A 87 5.315 10.638 -14.847 1.00 15.35 N -ATOM 648 CD2 HIS A 87 5.128 8.461 -14.450 1.00 17.85 C -ATOM 649 CE1 HIS A 87 6.425 9.938 -15.110 1.00 15.29 C -ATOM 650 NE2 HIS A 87 6.410 8.672 -14.776 1.00 15.64 N -ATOM 651 N ALA A 88 0.070 11.240 -15.092 1.00 19.56 N -ATOM 652 CA ALA A 88 -1.450 11.245 -14.731 1.00 16.45 C -ATOM 653 C ALA A 88 -2.307 10.782 -16.164 1.00 28.29 C -ATOM 654 O ALA A 88 -3.217 10.321 -15.884 1.00 25.27 O -ATOM 655 CB ALA A 88 -1.985 12.408 -13.954 1.00 17.34 C -ATOM 656 N HIS A 89 -1.856 11.542 -17.115 1.00 21.56 N -ATOM 657 CA HIS A 89 -2.652 11.471 -18.284 1.00 29.42 C -ATOM 658 C HIS A 89 -2.430 10.590 -19.375 1.00 27.17 C -ATOM 659 O HIS A 89 -3.237 9.974 -20.183 1.00 22.35 O -ATOM 660 CB HIS A 89 -2.855 12.836 -18.839 1.00 26.26 C -ATOM 661 CG HIS A 89 -3.474 13.775 -17.933 1.00 44.45 C -ATOM 662 ND1 HIS A 89 -4.582 13.545 -17.082 1.00 45.59 N -ATOM 663 CD2 HIS A 89 -3.036 15.133 -17.376 1.00 45.61 C -ATOM 664 CE1 HIS A 89 -4.931 14.373 -15.965 1.00 42.72 C -ATOM 665 NE2 HIS A 89 -3.969 15.212 -16.507 1.00 43.49 N -ATOM 666 N LYS A 90 -1.237 10.085 -19.553 1.00 18.65 N -ATOM 667 CA LYS A 90 -0.701 9.212 -20.311 1.00 28.92 C -ATOM 668 C LYS A 90 -0.235 7.836 -20.094 1.00 28.09 C -ATOM 669 O LYS A 90 -0.814 6.865 -20.213 1.00 25.04 O -ATOM 670 CB LYS A 90 0.483 9.973 -21.248 1.00 32.47 C -ATOM 671 CG LYS A 90 -0.258 11.271 -22.102 1.00 49.97 C -ATOM 672 CD LYS A 90 -1.161 11.150 -22.865 1.00 58.54 C -ATOM 673 CE LYS A 90 -0.717 12.584 -23.928 1.00 66.22 C -ATOM 674 NZ LYS A 90 -3.148 11.648 -24.501 1.00 63.54 N -ATOM 675 N LEU A 91 0.684 7.834 -19.083 1.00 17.50 N -ATOM 676 CA LEU A 91 1.357 6.678 -18.728 1.00 15.47 C -ATOM 677 C LEU A 91 0.469 5.814 -17.729 1.00 18.54 C -ATOM 678 O LEU A 91 0.360 4.623 -17.933 1.00 17.03 O -ATOM 679 CB LEU A 91 2.810 6.867 -17.956 1.00 13.84 C -ATOM 680 CG LEU A 91 3.828 7.564 -18.848 1.00 16.01 C -ATOM 681 CD1 LEU A 91 4.943 7.934 -18.256 1.00 18.27 C -ATOM 682 CD2 LEU A 91 3.998 6.811 -20.081 1.00 22.12 C -ATOM 683 N ARG A 92 -0.013 6.544 -16.785 1.00 18.03 N -ATOM 684 CA ARG A 92 -1.120 5.962 -15.831 1.00 14.41 C -ATOM 685 C ARG A 92 -0.663 4.876 -15.136 1.00 15.84 C -ATOM 686 O ARG A 92 -1.280 3.746 -14.964 1.00 17.92 O -ATOM 687 CB ARG A 92 -2.457 5.762 -16.768 1.00 18.61 C -ATOM 688 CG ARG A 92 -3.108 6.901 -17.068 1.00 25.14 C -ATOM 689 CD ARG A 92 -3.735 6.578 -19.206 1.00 53.25 C -ATOM 690 NE ARG A 92 -4.375 7.010 -18.108 1.00 51.61 N -ATOM 691 CZ ARG A 92 -5.273 6.721 -20.498 1.00 59.18 C -ATOM 692 NH1 ARG A 92 -4.092 6.059 -21.138 1.00 31.30 N -ATOM 693 NH2 ARG A 92 -6.080 6.715 -20.222 1.00 36.70 N -ATOM 694 N VAL A 93 0.444 4.876 -14.510 1.00 14.32 N -ATOM 695 CA VAL A 93 1.119 3.933 -13.665 1.00 16.19 C -ATOM 696 C VAL A 93 0.472 3.844 -12.448 1.00 13.83 C -ATOM 697 O VAL A 93 0.272 4.879 -11.643 1.00 14.88 O -ATOM 698 CB VAL A 93 2.564 4.273 -13.453 1.00 12.60 C -ATOM 699 CG1 VAL A 93 3.153 3.301 -12.513 1.00 15.68 C -ATOM 700 CG2 VAL A 93 3.314 4.342 -14.815 1.00 15.91 C -ATOM 701 N ASP A 94 0.015 2.696 -11.867 1.00 14.66 N -ATOM 702 CA ASP A 94 -0.813 2.633 -10.611 1.00 11.73 C -ATOM 703 C ASP A 94 0.271 3.244 -9.468 1.00 12.54 C -ATOM 704 O ASP A 94 1.339 2.859 -9.516 1.00 16.42 O -ATOM 705 CB ASP A 94 -1.010 1.197 -10.262 1.00 12.92 C -ATOM 706 CG ASP A 94 -1.972 1.228 -9.080 1.00 22.91 C -ATOM 707 OD1 ASP A 94 -3.187 1.146 -9.201 1.00 22.17 O -ATOM 708 OD2 ASP A 94 -1.457 1.316 -7.935 1.00 19.01 O -ATOM 709 N PRO A 95 -0.249 3.901 -8.527 1.00 16.46 N -ATOM 710 CA PRO A 95 0.567 4.636 -7.596 1.00 14.67 C -ATOM 711 C PRO A 95 1.260 3.622 -6.816 1.00 17.74 C -ATOM 712 O PRO A 95 2.400 4.046 -6.219 1.00 22.38 O -ATOM 713 CB PRO A 95 -0.368 5.238 -6.654 1.00 22.16 C -ATOM 714 CG PRO A 95 -1.377 5.777 -7.565 1.00 21.38 C -ATOM 715 CD PRO A 95 -1.576 4.623 -8.536 1.00 20.78 C -ATOM 716 N VAL A 96 0.927 2.374 -6.618 1.00 13.01 N -ATOM 717 CA VAL A 96 1.730 1.539 -5.762 1.00 11.93 C -ATOM 718 C VAL A 96 3.098 1.350 -6.142 1.00 21.27 C -ATOM 719 O VAL A 96 4.069 1.031 -5.537 1.00 16.07 O -ATOM 720 CB VAL A 96 0.857 0.099 -5.620 1.00 29.83 C -ATOM 721 CG1 VAL A 96 0.923 -0.687 -6.401 1.00 48.43 C -ATOM 722 CG2 VAL A 96 1.322 -0.240 -4.779 1.00 70.91 C -ATOM 723 N ASN A 97 3.269 1.470 -7.559 1.00 15.63 N -ATOM 724 CA ASN A 97 4.615 1.047 -8.098 1.00 10.10 C -ATOM 725 C ASN A 97 5.675 2.262 -7.895 1.00 4.91 C -ATOM 726 O ASN A 97 6.828 1.839 -7.860 1.00 9.67 O -ATOM 727 CB ASN A 97 4.581 0.892 -9.670 1.00 13.43 C -ATOM 728 CG ASN A 97 3.716 -0.282 -9.938 1.00 17.91 C -ATOM 729 OD1 ASN A 97 4.086 -1.378 -9.937 1.00 10.92 O -ATOM 730 ND2 ASN A 97 2.339 0.119 -10.294 1.00 21.96 N -ATOM 731 N PHE A 98 5.251 3.390 -7.458 1.00 9.20 N -ATOM 732 CA PHE A 98 6.132 4.482 -7.110 1.00 12.10 C -ATOM 733 C PHE A 98 6.958 4.075 -5.773 1.00 12.02 C -ATOM 734 O PHE A 98 8.240 4.323 -5.676 1.00 11.50 O -ATOM 735 CB PHE A 98 5.590 5.923 -6.936 1.00 16.66 C -ATOM 736 CG PHE A 98 5.051 6.336 -8.208 1.00 14.23 C -ATOM 737 CD1 PHE A 98 5.894 7.220 -8.806 1.00 16.70 C -ATOM 738 CD2 PHE A 98 3.842 5.962 -8.759 1.00 12.76 C -ATOM 739 CE1 PHE A 98 5.529 7.688 -9.904 1.00 23.57 C -ATOM 740 CE2 PHE A 98 3.513 6.440 -10.107 1.00 15.74 C -ATOM 741 CZ PHE A 98 4.374 7.231 -10.516 1.00 17.50 C -ATOM 742 N LYS A 99 6.362 3.356 -4.846 1.00 13.69 N -ATOM 743 CA LYS A 99 7.109 2.770 -3.687 1.00 13.57 C -ATOM 744 C LYS A 99 7.912 1.744 -3.941 1.00 14.35 C -ATOM 745 O LYS A 99 9.044 1.864 -3.350 1.00 13.29 O -ATOM 746 CB LYS A 99 5.909 2.378 -2.665 1.00 22.01 C -ATOM 747 CG LYS A 99 5.016 2.967 -2.454 1.00 54.35 C -ATOM 748 CD LYS A 99 4.488 3.000 -1.609 1.00 72.56 C -ATOM 749 CE LYS A 99 2.959 1.795 -1.600 1.00 73.99 C -ATOM 750 NZ LYS A 99 1.741 2.896 -0.134 1.00 80.12 N -ATOM 751 N LEU A 100 7.785 1.013 -5.037 1.00 9.89 N -ATOM 752 CA LEU A 100 8.665 -0.028 -5.354 1.00 8.80 C -ATOM 753 C LEU A 100 9.884 0.546 -6.019 1.00 9.28 C -ATOM 754 O LEU A 100 11.014 0.165 -5.616 1.00 12.09 O -ATOM 755 CB LEU A 100 8.009 -1.084 -6.185 1.00 11.00 C -ATOM 756 CG LEU A 100 6.724 -1.520 -5.691 1.00 16.83 C -ATOM 757 CD1 LEU A 100 6.069 -2.688 -6.703 1.00 20.94 C -ATOM 758 CD2 LEU A 100 7.065 -2.491 -4.548 1.00 18.49 C -ATOM 759 N LEU A 101 9.812 1.484 -6.927 1.00 8.39 N -ATOM 760 CA LEU A 101 10.986 2.076 -7.511 1.00 10.30 C -ATOM 761 C LEU A 101 11.701 2.979 -6.551 1.00 14.49 C -ATOM 762 O LEU A 101 12.986 2.948 -6.333 1.00 16.14 O -ATOM 763 CB LEU A 101 10.485 2.971 -8.570 1.00 11.44 C -ATOM 764 CG LEU A 101 11.708 3.704 -9.282 1.00 15.06 C -ATOM 765 CD1 LEU A 101 12.805 2.937 -9.771 1.00 17.72 C -ATOM 766 CD2 LEU A 101 11.060 4.651 -10.427 1.00 19.38 C -ATOM 767 N SER A 102 11.019 3.662 -5.475 1.00 15.17 N -ATOM 768 CA SER A 102 11.653 4.426 -4.454 1.00 9.19 C -ATOM 769 C SER A 102 12.577 3.423 -3.620 1.00 9.91 C -ATOM 770 O SER A 102 13.768 3.831 -3.267 1.00 14.07 O -ATOM 771 CB SER A 102 10.597 5.003 -3.570 1.00 12.36 C -ATOM 772 OG SER A 102 9.919 6.079 -4.248 1.00 16.52 O -ATOM 773 N HIS A 103 12.034 2.275 -3.168 1.00 12.27 N -ATOM 774 CA HIS A 103 12.685 1.217 -2.471 1.00 10.16 C -ATOM 775 C HIS A 103 14.063 1.009 -3.068 1.00 13.13 C -ATOM 776 O HIS A 103 15.226 0.862 -2.602 1.00 13.37 O -ATOM 777 CB HIS A 103 11.949 0.073 -2.013 1.00 12.31 C -ATOM 778 CG HIS A 103 12.674 -1.002 -1.380 1.00 10.33 C -ATOM 779 ND1 HIS A 103 12.899 -2.229 -2.007 1.00 10.01 N -ATOM 780 CD2 HIS A 103 13.318 -0.937 -0.179 1.00 9.56 C -ATOM 781 CE1 HIS A 103 13.687 -2.798 -1.043 1.00 12.63 C -ATOM 782 NE2 HIS A 103 14.053 -2.093 0.083 1.00 10.77 N -ATOM 783 N CYS A 104 13.914 0.657 -4.439 1.00 11.06 N -ATOM 784 CA CYS A 104 15.233 0.205 -5.307 1.00 11.72 C -ATOM 785 C CYS A 104 16.049 1.418 -5.518 1.00 9.58 C -ATOM 786 O CYS A 104 17.228 1.081 -5.567 1.00 14.10 O -ATOM 787 CB CYS A 104 14.671 -0.439 -6.552 1.00 16.81 C -ATOM 788 SG CYS A 104 13.797 -1.958 -6.414 1.00 14.76 S -ATOM 789 N LEU A 105 15.618 2.594 -5.516 1.00 7.99 N -ATOM 790 CA LEU A 105 16.723 3.634 -5.593 1.00 10.43 C -ATOM 791 C LEU A 105 17.448 3.890 -4.202 1.00 11.96 C -ATOM 792 O LEU A 105 18.594 3.985 -4.326 1.00 15.19 O -ATOM 793 CB LEU A 105 15.765 4.895 -6.092 1.00 16.93 C -ATOM 794 CG LEU A 105 15.765 5.438 -7.260 1.00 44.57 C -ATOM 795 CD1 LEU A 105 14.641 6.498 -7.442 1.00 40.98 C -ATOM 796 CD2 LEU A 105 16.687 5.564 -8.008 1.00 33.21 C -ATOM 797 N LEU A 106 16.617 3.676 -3.143 1.00 10.40 N -ATOM 798 CA LEU A 106 17.322 3.635 -1.869 1.00 15.02 C -ATOM 799 C LEU A 106 18.190 2.641 -1.668 1.00 13.79 C -ATOM 800 O LEU A 106 19.481 2.857 -1.263 1.00 13.12 O -ATOM 801 CB LEU A 106 16.241 3.634 -0.757 1.00 16.59 C -ATOM 802 CG LEU A 106 15.821 4.348 0.036 1.00 26.87 C -ATOM 803 CD1 LEU A 106 14.832 4.036 0.973 1.00 28.01 C -ATOM 804 CD2 LEU A 106 16.399 5.824 0.153 1.00 18.73 C -ATOM 805 N VAL A 107 18.054 1.391 -2.126 1.00 9.58 N -ATOM 806 CA VAL A 107 18.953 0.372 -2.172 1.00 10.69 C -ATOM 807 C VAL A 107 20.116 0.640 -3.008 1.00 12.39 C -ATOM 808 O VAL A 107 21.316 0.322 -2.651 1.00 13.09 O -ATOM 809 CB VAL A 107 18.301 -0.968 -2.671 1.00 14.48 C -ATOM 810 CG1 VAL A 107 19.286 -1.955 -2.913 1.00 19.64 C -ATOM 811 CG2 VAL A 107 17.236 -1.532 -1.566 1.00 13.81 C -ATOM 812 N THR A 108 19.963 1.288 -4.127 1.00 12.66 N -ATOM 813 CA THR A 108 21.110 1.595 -5.027 1.00 11.04 C -ATOM 814 C THR A 108 21.986 2.516 -4.350 1.00 11.25 C -ATOM 815 O THR A 108 23.209 2.402 -4.407 1.00 13.68 O -ATOM 816 CB THR A 108 20.373 2.089 -6.467 1.00 8.55 C -ATOM 817 OG1 THR A 108 19.740 1.009 -7.110 1.00 9.51 O -ATOM 818 CG2 THR A 108 21.547 2.322 -7.342 1.00 15.85 C -ATOM 819 N LEU A 109 21.371 3.638 -3.771 1.00 11.20 N -ATOM 820 CA LEU A 109 22.189 4.682 -3.080 1.00 12.61 C -ATOM 821 C LEU A 109 23.015 3.976 -1.882 1.00 16.09 C -ATOM 822 O LEU A 109 24.210 4.291 -1.739 1.00 14.60 O -ATOM 823 CB LEU A 109 21.280 5.707 -2.657 1.00 17.08 C -ATOM 824 CG LEU A 109 20.748 6.795 -3.713 1.00 24.50 C -ATOM 825 CD1 LEU A 109 19.679 7.424 -3.306 1.00 22.52 C -ATOM 826 CD2 LEU A 109 21.379 6.943 -4.782 1.00 32.08 C -ATOM 827 N ALA A 110 22.243 3.090 -1.228 1.00 13.55 N -ATOM 828 CA ALA A 110 22.985 2.551 -0.107 1.00 19.86 C -ATOM 829 C ALA A 110 24.128 1.797 -0.396 1.00 18.59 C -ATOM 830 O ALA A 110 25.285 1.654 0.094 1.00 14.76 O -ATOM 831 CB ALA A 110 21.957 1.572 0.573 1.00 17.34 C -ATOM 832 N ALA A 111 24.211 0.998 -1.558 1.00 15.15 N -ATOM 833 CA ALA A 111 25.062 0.161 -2.216 1.00 13.42 C -ATOM 834 C ALA A 111 26.376 1.017 -2.643 1.00 16.84 C -ATOM 835 O ALA A 111 27.331 0.420 -2.883 1.00 21.50 O -ATOM 836 CB ALA A 111 24.726 -0.813 -3.252 1.00 16.85 C -ATOM 837 N HIS A 112 26.089 2.220 -3.063 1.00 17.71 N -ATOM 838 CA HIS A 112 27.174 3.032 -3.686 1.00 25.83 C -ATOM 839 C HIS A 112 27.556 4.174 -2.656 1.00 21.86 C -ATOM 840 O HIS A 112 28.710 4.609 -3.162 1.00 23.07 O -ATOM 841 CB HIS A 112 26.642 3.736 -5.093 1.00 17.12 C -ATOM 842 CG HIS A 112 26.500 2.730 -6.083 1.00 18.91 C -ATOM 843 ND1 HIS A 112 27.696 2.669 -6.792 1.00 20.25 N -ATOM 844 CD2 HIS A 112 25.457 2.082 -6.643 1.00 13.97 C -ATOM 845 CE1 HIS A 112 27.065 1.572 -7.791 1.00 16.16 C -ATOM 846 NE2 HIS A 112 25.728 1.142 -7.624 1.00 16.17 N -ATOM 847 N LEU A 113 26.962 4.473 -1.633 1.00 16.18 N -ATOM 848 CA LEU A 113 27.430 5.708 -0.856 1.00 18.52 C -ATOM 849 C LEU A 113 27.676 5.161 0.490 1.00 15.09 C -ATOM 850 O LEU A 113 26.991 5.652 1.418 1.00 22.00 O -ATOM 851 CB LEU A 113 26.385 6.569 -0.567 1.00 26.60 C -ATOM 852 CG LEU A 113 25.991 7.546 -1.915 1.00 26.91 C -ATOM 853 CD1 LEU A 113 25.025 8.844 -1.799 1.00 38.78 C -ATOM 854 CD2 LEU A 113 27.117 7.882 -2.870 1.00 35.29 C -ATOM 855 N PRO A 114 28.523 4.242 0.795 1.00 18.92 N -ATOM 856 CA PRO A 114 28.714 3.528 2.218 1.00 24.61 C -ATOM 857 C PRO A 114 29.102 4.799 3.218 1.00 23.92 C -ATOM 858 O PRO A 114 28.415 4.826 4.106 1.00 21.99 O -ATOM 859 CB PRO A 114 30.033 2.940 1.849 1.00 23.94 C -ATOM 860 CG PRO A 114 30.698 3.344 0.612 1.00 18.92 C -ATOM 861 CD PRO A 114 29.469 3.904 -0.168 1.00 16.59 C -ATOM 862 N ALA A 115 29.794 5.877 2.767 1.00 18.42 N -ATOM 863 CA ALA A 115 30.159 6.863 3.921 1.00 21.98 C -ATOM 864 C ALA A 115 28.895 7.716 4.285 1.00 22.41 C -ATOM 865 O ALA A 115 28.703 8.192 5.284 1.00 22.94 O -ATOM 866 CB ALA A 115 31.247 7.657 3.369 1.00 30.20 C -ATOM 867 N GLU A 116 28.136 8.035 3.290 1.00 15.58 N -ATOM 868 CA GLU A 116 27.073 9.160 3.429 1.00 17.43 C -ATOM 869 C GLU A 116 25.648 8.548 3.788 1.00 15.97 C -ATOM 870 O GLU A 116 24.768 9.367 4.171 1.00 23.49 O -ATOM 871 CB GLU A 116 26.875 9.750 1.910 1.00 21.21 C -ATOM 872 CG GLU A 116 27.948 10.674 1.482 1.00 24.18 C -ATOM 873 CD GLU A 116 28.950 9.665 0.967 1.00 26.12 C -ATOM 874 OE1 GLU A 116 28.992 8.438 0.543 1.00 28.16 O -ATOM 875 OE2 GLU A 116 30.132 10.301 0.462 1.00 33.82 O -ATOM 876 N PHE A 117 25.414 7.310 3.661 1.00 16.62 N -ATOM 877 CA PHE A 117 24.245 6.614 3.985 1.00 14.17 C -ATOM 878 C PHE A 117 23.918 6.335 5.559 1.00 17.74 C -ATOM 879 O PHE A 117 23.649 5.222 5.819 1.00 19.92 O -ATOM 880 CB PHE A 117 23.936 5.421 3.086 1.00 12.47 C -ATOM 881 CG PHE A 117 22.448 4.906 2.825 1.00 9.61 C -ATOM 882 CD1 PHE A 117 21.681 5.713 2.037 1.00 15.09 C -ATOM 883 CD2 PHE A 117 22.071 3.807 3.568 1.00 15.73 C -ATOM 884 CE1 PHE A 117 20.396 5.197 1.858 1.00 17.90 C -ATOM 885 CE2 PHE A 117 20.593 3.448 3.517 1.00 23.05 C -ATOM 886 CZ PHE A 117 19.914 4.171 2.606 1.00 14.00 C -ATOM 887 N THR A 118 23.856 7.434 6.252 1.00 11.56 N -ATOM 888 CA THR A 118 23.660 7.280 7.655 1.00 10.93 C -ATOM 889 C THR A 118 22.259 6.982 7.820 1.00 15.34 C -ATOM 890 O THR A 118 21.447 7.435 7.051 1.00 14.33 O -ATOM 891 CB THR A 118 23.982 8.621 8.138 1.00 22.78 C -ATOM 892 OG1 THR A 118 23.375 9.780 7.827 1.00 25.00 O -ATOM 893 CG2 THR A 118 25.586 8.842 8.226 1.00 25.00 C -ATOM 894 N PRO A 119 21.833 6.884 9.086 1.00 16.93 N -ATOM 895 CA PRO A 119 20.398 6.708 9.436 1.00 7.97 C -ATOM 896 C PRO A 119 19.633 7.821 9.121 1.00 9.71 C -ATOM 897 O PRO A 119 18.484 7.899 8.632 1.00 13.14 O -ATOM 898 CB PRO A 119 20.352 6.336 10.909 1.00 15.02 C -ATOM 899 CG PRO A 119 21.556 5.500 11.105 1.00 20.08 C -ATOM 900 CD PRO A 119 22.686 6.188 10.125 1.00 23.85 C -ATOM 901 N ALA A 120 20.184 9.026 9.484 1.00 18.30 N -ATOM 902 CA ALA A 120 19.624 10.215 9.304 1.00 20.48 C -ATOM 903 C ALA A 120 19.441 10.650 7.769 1.00 11.11 C -ATOM 904 O ALA A 120 18.342 11.025 7.255 1.00 14.90 O -ATOM 905 CB ALA A 120 20.042 11.527 10.014 1.00 21.25 C -ATOM 906 N VAL A 121 20.278 10.312 7.027 1.00 15.02 N -ATOM 907 CA VAL A 121 20.243 10.488 5.614 1.00 11.64 C -ATOM 908 C VAL A 121 19.214 9.526 4.899 1.00 13.80 C -ATOM 909 O VAL A 121 18.469 9.919 4.066 1.00 15.60 O -ATOM 910 CB VAL A 121 21.606 10.473 4.939 1.00 16.28 C -ATOM 911 CG1 VAL A 121 21.595 10.524 3.309 1.00 17.80 C -ATOM 912 CG2 VAL A 121 22.496 11.659 5.330 1.00 19.30 C -ATOM 913 N HIS A 122 19.312 8.350 5.306 1.00 15.45 N -ATOM 914 CA HIS A 122 18.254 7.136 4.913 1.00 11.57 C -ATOM 915 C HIS A 122 16.950 7.952 5.022 1.00 13.88 C -ATOM 916 O HIS A 122 16.085 7.716 4.230 1.00 13.87 O -ATOM 917 CB HIS A 122 18.754 5.950 5.667 1.00 12.36 C -ATOM 918 CG HIS A 122 17.848 4.887 5.471 1.00 15.49 C -ATOM 919 ND1 HIS A 122 18.318 3.588 6.013 1.00 14.41 N -ATOM 920 CD2 HIS A 122 16.770 4.643 4.716 1.00 16.00 C -ATOM 921 CE1 HIS A 122 17.238 2.617 5.530 1.00 20.76 C -ATOM 922 NE2 HIS A 122 16.304 3.230 4.756 1.00 17.17 N -ATOM 923 N ALA A 123 16.659 8.268 6.248 1.00 12.31 N -ATOM 924 CA ALA A 123 15.409 8.791 6.637 1.00 12.34 C -ATOM 925 C ALA A 123 14.961 9.969 5.694 1.00 12.36 C -ATOM 926 O ALA A 123 13.756 10.012 5.125 1.00 16.22 O -ATOM 927 CB ALA A 123 15.295 9.229 8.074 1.00 18.20 C -ATOM 928 N SER A 124 15.970 10.909 5.411 1.00 11.72 N -ATOM 929 CA SER A 124 15.641 12.024 4.678 1.00 15.71 C -ATOM 930 C SER A 124 15.409 11.594 3.146 1.00 11.97 C -ATOM 931 O SER A 124 14.491 12.176 2.530 1.00 13.78 O -ATOM 932 CB SER A 124 16.719 13.075 4.649 1.00 17.31 C -ATOM 933 OG SER A 124 16.856 13.618 5.975 1.00 19.36 O -ATOM 934 N LEU A 125 16.244 10.663 2.745 1.00 11.45 N -ATOM 935 CA LEU A 125 16.012 10.336 1.348 1.00 9.77 C -ATOM 936 C LEU A 125 14.814 9.607 1.165 1.00 13.87 C -ATOM 937 O LEU A 125 14.134 9.697 0.072 1.00 12.03 O -ATOM 938 CB LEU A 125 17.131 9.446 0.945 1.00 14.61 C -ATOM 939 CG LEU A 125 18.555 9.965 0.565 1.00 15.39 C -ATOM 940 CD1 LEU A 125 19.590 8.976 0.528 1.00 26.84 C -ATOM 941 CD2 LEU A 125 18.455 10.851 -0.577 1.00 19.46 C -ATOM 942 N ASP A 126 14.277 8.735 2.034 1.00 13.89 N -ATOM 943 CA ASP A 126 13.042 7.997 2.040 1.00 14.28 C -ATOM 944 C ASP A 126 11.977 8.930 1.898 1.00 13.60 C -ATOM 945 O ASP A 126 10.911 8.959 1.188 1.00 12.25 O -ATOM 946 CB ASP A 126 12.901 7.025 3.127 1.00 9.77 C -ATOM 947 CG ASP A 126 11.751 5.958 3.086 1.00 17.51 C -ATOM 948 OD1 ASP A 126 11.597 5.517 1.933 1.00 22.67 O -ATOM 949 OD2 ASP A 126 10.812 6.013 3.738 1.00 20.83 O -ATOM 950 N LYS A 127 11.945 10.077 2.732 1.00 11.87 N -ATOM 951 CA LYS A 127 11.051 11.143 2.756 1.00 11.94 C -ATOM 952 C LYS A 127 11.080 11.794 1.382 1.00 16.34 C -ATOM 953 O LYS A 127 9.925 12.173 0.922 1.00 15.26 O -ATOM 954 CB LYS A 127 11.131 11.830 4.210 1.00 27.23 C -ATOM 955 CG LYS A 127 10.719 12.405 4.298 1.00 41.38 C -ATOM 956 CD LYS A 127 10.893 12.716 6.240 1.00 22.35 C -ATOM 957 CE LYS A 127 10.245 13.990 6.093 1.00 24.85 C -ATOM 958 NZ LYS A 127 10.431 14.893 7.319 1.00 27.43 N -ATOM 959 N PHE A 128 12.109 12.155 0.978 1.00 9.60 N -ATOM 960 CA PHE A 128 12.219 12.896 -0.315 1.00 9.45 C -ATOM 961 C PHE A 128 11.648 12.055 -1.437 1.00 11.35 C -ATOM 962 O PHE A 128 10.825 12.624 -2.222 1.00 13.72 O -ATOM 963 CB PHE A 128 13.691 13.118 -0.597 1.00 10.04 C -ATOM 964 CG PHE A 128 13.845 13.645 -2.016 1.00 12.71 C -ATOM 965 CD1 PHE A 128 13.433 15.022 -2.350 1.00 22.47 C -ATOM 966 CD2 PHE A 128 14.442 12.953 -2.821 1.00 15.10 C -ATOM 967 CE1 PHE A 128 13.646 15.369 -3.684 1.00 21.90 C -ATOM 968 CE2 PHE A 128 15.006 13.229 -4.197 1.00 24.41 C -ATOM 969 CZ PHE A 128 14.491 14.511 -4.397 1.00 19.00 C -ATOM 970 N LEU A 129 11.863 10.701 -1.438 1.00 10.92 N -ATOM 971 CA LEU A 129 11.247 9.983 -2.588 1.00 8.59 C -ATOM 972 C LEU A 129 9.888 9.762 -2.445 1.00 15.58 C -ATOM 973 O LEU A 129 9.123 9.780 -3.420 1.00 12.33 O -ATOM 974 CB LEU A 129 11.971 8.639 -2.709 1.00 11.08 C -ATOM 975 CG LEU A 129 13.553 8.574 -3.067 1.00 16.43 C -ATOM 976 CD1 LEU A 129 14.162 7.385 -2.920 1.00 21.21 C -ATOM 977 CD2 LEU A 129 13.509 9.197 -4.648 1.00 24.11 C -ATOM 978 N ALA A 130 9.315 9.777 -1.285 1.00 13.59 N -ATOM 979 CA ALA A 130 7.861 9.751 -0.992 1.00 12.80 C -ATOM 980 C ALA A 130 7.198 11.000 -1.487 1.00 13.10 C -ATOM 981 O ALA A 130 6.124 11.123 -2.087 1.00 16.72 O -ATOM 982 CB ALA A 130 7.566 9.549 0.507 1.00 11.70 C -ATOM 983 N SER A 131 7.929 12.205 -1.316 1.00 12.15 N -ATOM 984 CA SER A 131 7.318 13.421 -1.788 1.00 17.97 C -ATOM 985 C SER A 131 7.403 13.484 -3.383 1.00 14.23 C -ATOM 986 O SER A 131 6.313 14.078 -3.819 1.00 17.89 O -ATOM 987 CB SER A 131 8.230 14.652 -1.217 1.00 19.09 C -ATOM 988 OG SER A 131 7.985 14.599 -0.027 1.00 34.89 O -ATOM 989 N VAL A 132 8.509 13.092 -3.817 1.00 11.02 N -ATOM 990 CA VAL A 132 8.474 13.187 -5.332 1.00 13.44 C -ATOM 991 C VAL A 132 7.379 12.239 -5.739 1.00 13.26 C -ATOM 992 O VAL A 132 6.574 12.766 -6.727 1.00 14.28 O -ATOM 993 CB VAL A 132 9.676 12.669 -5.775 1.00 17.47 C -ATOM 994 CG1 VAL A 132 9.886 12.366 -7.268 1.00 23.96 C -ATOM 995 CG2 VAL A 132 10.893 13.605 -5.556 1.00 15.24 C -ATOM 996 N SER A 133 7.084 11.034 -5.279 1.00 11.44 N -ATOM 997 CA SER A 133 6.003 10.145 -5.616 1.00 14.28 C -ATOM 998 C SER A 133 4.653 10.824 -5.346 1.00 22.70 C -ATOM 999 O SER A 133 3.857 10.661 -6.312 1.00 18.73 O -ATOM 1000 CB SER A 133 6.206 8.913 -4.797 1.00 14.07 C -ATOM 1001 OG SER A 133 7.326 8.157 -5.136 1.00 16.41 O -ATOM 1002 N THR A 134 4.415 11.603 -4.390 1.00 14.75 N -ATOM 1003 CA THR A 134 3.185 12.188 -4.293 1.00 11.93 C -ATOM 1004 C THR A 134 3.018 13.180 -5.135 1.00 12.33 C -ATOM 1005 O THR A 134 1.906 13.411 -5.657 1.00 15.87 O -ATOM 1006 CB THR A 134 3.337 12.691 -2.840 1.00 23.98 C -ATOM 1007 OG1 THR A 134 3.226 11.963 -1.926 1.00 24.65 O -ATOM 1008 CG2 THR A 134 2.127 13.740 -2.527 1.00 35.48 C -ATOM 1009 N VAL A 135 3.914 14.063 -5.633 1.00 16.85 N -ATOM 1010 CA VAL A 135 3.773 15.122 -6.561 1.00 15.02 C -ATOM 1011 C VAL A 135 3.692 14.401 -7.901 1.00 18.49 C -ATOM 1012 O VAL A 135 2.676 14.854 -8.623 1.00 17.84 O -ATOM 1013 CB VAL A 135 5.097 16.044 -6.643 1.00 21.41 C -ATOM 1014 CG1 VAL A 135 5.125 16.829 -7.908 1.00 28.88 C -ATOM 1015 CG2 VAL A 135 5.265 16.767 -5.381 1.00 18.54 C -ATOM 1016 N LEU A 136 4.254 13.322 -8.291 1.00 15.13 N -ATOM 1017 CA LEU A 136 3.951 12.616 -9.538 1.00 14.14 C -ATOM 1018 C LEU A 136 2.480 12.083 -9.717 1.00 16.82 C -ATOM 1019 O LEU A 136 2.071 11.725 -10.914 1.00 16.56 O -ATOM 1020 CB LEU A 136 5.082 11.671 -9.878 1.00 19.05 C -ATOM 1021 CG LEU A 136 6.468 12.174 -10.486 1.00 19.99 C -ATOM 1022 CD1 LEU A 136 7.357 11.046 -10.401 1.00 23.33 C -ATOM 1023 CD2 LEU A 136 6.502 13.371 -11.272 1.00 20.84 C -ATOM 1024 N THR A 137 1.951 11.790 -8.618 1.00 14.14 N -ATOM 1025 CA THR A 137 0.509 10.996 -8.584 1.00 17.11 C -ATOM 1026 C THR A 137 -0.385 12.070 -8.267 1.00 15.43 C -ATOM 1027 O THR A 137 -1.637 11.700 -8.230 1.00 15.99 O -ATOM 1028 CB THR A 137 0.560 9.964 -6.978 1.00 17.27 C -ATOM 1029 OG1 THR A 137 1.278 8.939 -8.074 1.00 28.37 O -ATOM 1030 CG2 THR A 137 1.320 10.263 -6.388 1.00 47.04 C -ATOM 1031 N SER A 138 -0.164 13.266 -8.168 1.00 16.91 N -ATOM 1032 CA SER A 138 -0.947 14.363 -7.753 1.00 23.51 C -ATOM 1033 C SER A 138 -2.266 14.743 -8.597 1.00 23.60 C -ATOM 1034 O SER A 138 -3.250 14.937 -8.017 1.00 27.80 O -ATOM 1035 CB SER A 138 0.046 16.222 -7.976 1.00 22.76 C -ATOM 1036 OG SER A 138 -0.261 15.617 -6.862 1.00 45.85 O -ATOM 1037 N LYS A 139 -2.026 14.453 -9.807 1.00 19.13 N -ATOM 1038 CA LYS A 139 -3.058 14.995 -10.892 1.00 21.43 C -ATOM 1039 C LYS A 139 -3.804 13.721 -11.284 1.00 18.35 C -ATOM 1040 O LYS A 139 -4.384 13.814 -12.266 1.00 22.16 O -ATOM 1041 CB LYS A 139 -2.474 15.794 -11.975 1.00 24.13 C -ATOM 1042 CG LYS A 139 -1.839 16.973 -11.481 1.00 28.98 C -ATOM 1043 CD LYS A 139 -0.886 17.619 -12.549 1.00 33.18 C -ATOM 1044 CE LYS A 139 -0.495 18.885 -12.192 1.00 52.82 C -ATOM 1045 NZ LYS A 139 0.788 19.253 -13.621 1.00 55.02 N -ATOM 1046 N TYR A 140 -3.715 12.530 -10.777 1.00 17.12 N -ATOM 1047 CA TYR A 140 -4.275 11.374 -11.162 1.00 22.48 C -ATOM 1048 C TYR A 140 -5.830 11.291 -11.160 1.00 18.75 C -ATOM 1049 O TYR A 140 -6.423 10.704 -12.162 1.00 22.47 O -ATOM 1050 CB TYR A 140 -3.896 10.028 -10.426 1.00 23.15 C -ATOM 1051 CG TYR A 140 -2.655 9.444 -11.006 1.00 15.57 C -ATOM 1052 CD1 TYR A 140 -2.495 7.940 -11.096 1.00 16.98 C -ATOM 1053 CD2 TYR A 140 -1.471 10.093 -11.392 1.00 18.11 C -ATOM 1054 CE1 TYR A 140 -1.296 7.400 -11.625 1.00 19.97 C -ATOM 1055 CE2 TYR A 140 -0.267 9.379 -11.806 1.00 14.94 C -ATOM 1056 CZ TYR A 140 -0.246 7.948 -11.911 1.00 17.89 C -ATOM 1057 OH TYR A 140 0.808 7.493 -12.283 1.00 18.05 O -ATOM 1058 N ARG A 141 -6.399 12.034 -10.391 1.00 17.59 N -ATOM 1059 CA ARG A 141 -8.000 12.137 -10.191 1.00 24.58 C -ATOM 1060 C ARG A 141 -8.327 13.610 -9.572 1.00 44.44 C -ATOM 1061 O ARG A 141 -7.492 14.016 -8.882 1.00 21.81 O -ATOM 1062 CB ARG A 141 -8.478 10.914 -9.869 1.00 33.40 C -ATOM 1063 CG ARG A 141 -8.068 10.650 -8.145 1.00 17.28 C -ATOM 1064 CD ARG A 141 -9.053 9.446 -7.867 1.00 14.66 C -ATOM 1065 NE ARG A 141 -8.372 9.269 -6.610 1.00 22.73 N -ATOM 1066 CZ ARG A 141 -9.233 8.420 -5.781 1.00 26.88 C -ATOM 1067 NH1 ARG A 141 -10.147 7.455 -6.079 1.00 23.24 N -ATOM 1068 NH2 ARG A 141 -8.672 8.328 -4.506 1.00 33.34 N -ATOM 1069 OXT ARG A 141 -9.474 13.682 -9.742 1.00 31.52 O -TER 1070 ARG A 141 -ATOM 1071 N VAL B 1 9.223 -20.614 1.365 1.00 46.08 N -ATOM 1072 CA VAL B 1 8.694 -20.026 -0.123 1.00 70.96 C -ATOM 1073 C VAL B 1 9.668 -21.068 -1.645 1.00 69.74 C -ATOM 1074 O VAL B 1 9.370 -22.612 -0.994 1.00 71.82 O -ATOM 1075 CB VAL B 1 9.283 -18.281 -0.381 1.00 59.18 C -ATOM 1076 CG1 VAL B 1 7.449 -17.518 -0.791 1.00 57.89 C -ATOM 1077 CG2 VAL B 1 10.416 -18.038 0.066 1.00 44.20 C -ATOM 1078 N HIS B 2 9.270 -20.650 -2.180 1.00 53.55 N -ATOM 1079 CA HIS B 2 10.245 -21.378 -3.143 1.00 62.62 C -ATOM 1080 C HIS B 2 11.419 -20.331 -4.099 1.00 51.71 C -ATOM 1081 O HIS B 2 11.252 -19.250 -5.024 1.00 48.42 O -ATOM 1082 CB HIS B 2 9.225 -20.955 -4.825 1.00 62.58 C -ATOM 1083 CG HIS B 2 9.378 -21.082 -5.634 1.00 73.96 C -ATOM 1084 ND1 HIS B 2 9.645 -19.683 -6.869 1.00 80.12 N -ATOM 1085 CD2 HIS B 2 10.077 -22.950 -6.116 1.00 63.02 C -ATOM 1086 CE1 HIS B 2 10.672 -21.165 -8.087 1.00 76.40 C -ATOM 1087 NE2 HIS B 2 11.344 -22.584 -7.734 1.00 62.86 N -ATOM 1088 N LEU B 3 12.365 -20.722 -3.649 1.00 43.89 N -ATOM 1089 CA LEU B 3 13.611 -20.183 -4.477 1.00 43.79 C -ATOM 1090 C LEU B 3 14.557 -21.356 -5.125 1.00 32.77 C -ATOM 1091 O LEU B 3 14.340 -22.536 -4.780 1.00 41.84 O -ATOM 1092 CB LEU B 3 14.522 -19.852 -2.996 1.00 28.80 C -ATOM 1093 CG LEU B 3 13.980 -18.598 -2.183 1.00 28.70 C -ATOM 1094 CD1 LEU B 3 14.846 -18.445 -1.199 1.00 63.39 C -ATOM 1095 CD2 LEU B 3 14.509 -17.517 -3.001 1.00 32.10 C -ATOM 1096 N THR B 4 14.840 -20.756 -6.280 1.00 42.35 N -ATOM 1097 CA THR B 4 15.864 -21.825 -6.744 1.00 41.74 C -ATOM 1098 C THR B 4 16.873 -22.187 -6.071 1.00 36.91 C -ATOM 1099 O THR B 4 17.370 -21.395 -5.237 1.00 31.57 O -ATOM 1100 CB THR B 4 15.949 -21.050 -8.090 1.00 38.91 C -ATOM 1101 OG1 THR B 4 16.952 -20.015 -8.082 1.00 52.85 O -ATOM 1102 CG2 THR B 4 14.967 -20.467 -9.056 1.00 56.94 C -ATOM 1103 N PRO B 5 17.854 -23.111 -6.524 1.00 45.56 N -ATOM 1104 CA PRO B 5 18.731 -23.731 -6.023 1.00 47.54 C -ATOM 1105 C PRO B 5 19.935 -22.444 -5.760 1.00 37.80 C -ATOM 1106 O PRO B 5 20.658 -22.372 -4.793 1.00 33.06 O -ATOM 1107 CB PRO B 5 19.534 -24.900 -6.291 1.00 62.12 C -ATOM 1108 CG PRO B 5 18.296 -25.318 -7.157 1.00 42.55 C -ATOM 1109 CD PRO B 5 17.186 -24.560 -7.385 1.00 48.08 C -ATOM 1110 N GLU B 6 19.819 -21.815 -6.978 1.00 27.00 N -ATOM 1111 CA GLU B 6 20.898 -20.991 -7.230 1.00 34.37 C -ATOM 1112 C GLU B 6 20.521 -19.635 -6.155 1.00 23.02 C -ATOM 1113 O GLU B 6 21.687 -18.920 -5.617 1.00 28.54 O -ATOM 1114 CB GLU B 6 20.842 -20.165 -8.661 1.00 37.20 C -ATOM 1115 CG GLU B 6 20.141 -19.957 -9.396 1.00 66.65 C -ATOM 1116 CD GLU B 6 19.153 -21.597 -10.181 1.00 60.44 C -ATOM 1117 OE1 GLU B 6 20.183 -22.830 -9.731 1.00 63.16 O -ATOM 1118 OE2 GLU B 6 18.299 -21.975 -10.007 1.00 70.62 O -ATOM 1119 N GLU B 7 19.362 -19.413 -5.964 1.00 31.47 N -ATOM 1120 CA GLU B 7 18.560 -18.284 -5.124 1.00 34.08 C -ATOM 1121 C GLU B 7 19.160 -18.789 -3.682 1.00 21.49 C -ATOM 1122 O GLU B 7 19.620 -17.847 -3.008 1.00 27.04 O -ATOM 1123 CB GLU B 7 17.625 -18.097 -5.359 1.00 35.55 C -ATOM 1124 CG GLU B 7 17.103 -17.196 -6.791 1.00 33.74 C -ATOM 1125 CD GLU B 7 15.759 -16.911 -6.659 1.00 31.89 C -ATOM 1126 OE1 GLU B 7 15.476 -15.756 -7.225 1.00 52.51 O -ATOM 1127 OE2 GLU B 7 14.748 -17.803 -6.419 1.00 32.56 O -ATOM 1128 N LYS B 8 18.747 -19.865 -3.237 1.00 26.08 N -ATOM 1129 CA LYS B 8 19.026 -20.305 -2.016 1.00 32.23 C -ATOM 1130 C LYS B 8 20.466 -20.216 -1.796 1.00 26.59 C -ATOM 1131 O LYS B 8 21.162 -19.731 -0.601 1.00 26.11 O -ATOM 1132 CB LYS B 8 18.395 -21.925 -1.875 1.00 36.34 C -ATOM 1133 CG LYS B 8 18.802 -22.252 -1.182 1.00 64.20 C -ATOM 1134 CD LYS B 8 18.769 -23.771 -0.248 1.00 73.64 C -ATOM 1135 CE LYS B 8 19.461 -24.137 0.849 1.00 79.30 C -ATOM 1136 NZ LYS B 8 19.874 -26.365 1.034 1.00 66.73 N -ATOM 1137 N SER B 9 21.467 -20.675 -2.533 1.00 23.88 N -ATOM 1138 CA SER B 9 22.559 -20.677 -2.426 1.00 36.76 C -ATOM 1139 C SER B 9 23.490 -19.070 -2.230 1.00 37.61 C -ATOM 1140 O SER B 9 24.284 -18.831 -1.430 1.00 28.84 O -ATOM 1141 CB SER B 9 23.619 -21.853 -3.256 1.00 36.63 C -ATOM 1142 OG SER B 9 23.958 -20.627 -4.033 1.00 64.02 O -ATOM 1143 N ALA B 10 22.719 -18.196 -3.034 1.00 21.54 N -ATOM 1144 CA ALA B 10 23.262 -17.029 -2.963 1.00 32.77 C -ATOM 1145 C ALA B 10 22.792 -16.202 -1.459 1.00 23.64 C -ATOM 1146 O ALA B 10 23.628 -15.408 -0.898 1.00 26.26 O -ATOM 1147 CB ALA B 10 22.504 -16.176 -3.856 1.00 30.88 C -ATOM 1148 N VAL B 11 21.589 -16.575 -0.940 1.00 22.75 N -ATOM 1149 CA VAL B 11 21.174 -16.108 0.417 1.00 18.12 C -ATOM 1150 C VAL B 11 22.242 -16.512 1.434 1.00 18.13 C -ATOM 1151 O VAL B 11 22.655 -15.680 2.245 1.00 19.40 O -ATOM 1152 CB VAL B 11 19.853 -16.542 0.518 1.00 19.48 C -ATOM 1153 CG1 VAL B 11 19.403 -16.415 1.946 1.00 26.15 C -ATOM 1154 CG2 VAL B 11 18.815 -15.702 -0.276 1.00 23.37 C -ATOM 1155 N THR B 12 22.386 -17.775 1.358 1.00 19.01 N -ATOM 1156 CA THR B 12 23.153 -18.592 2.377 1.00 25.04 C -ATOM 1157 C THR B 12 24.569 -18.098 2.437 1.00 20.68 C -ATOM 1158 O THR B 12 25.254 -17.692 3.335 1.00 23.87 O -ATOM 1159 CB THR B 12 23.196 -20.284 2.185 1.00 42.63 C -ATOM 1160 OG1 THR B 12 22.010 -20.433 2.444 1.00 42.78 O -ATOM 1161 CG2 THR B 12 23.729 -20.348 1.974 1.00 67.38 C -ATOM 1162 N ALA B 13 25.190 -17.913 1.267 1.00 22.79 N -ATOM 1163 CA ALA B 13 26.401 -17.387 1.166 1.00 26.66 C -ATOM 1164 C ALA B 13 26.828 -16.135 1.582 1.00 26.26 C -ATOM 1165 O ALA B 13 27.614 -15.809 2.378 1.00 27.07 O -ATOM 1166 CB ALA B 13 26.857 -17.378 -0.445 1.00 26.35 C -ATOM 1167 N LEU B 14 25.928 -14.999 1.236 1.00 15.70 N -ATOM 1168 CA LEU B 14 26.092 -13.737 1.994 1.00 15.10 C -ATOM 1169 C LEU B 14 25.996 -13.791 3.419 1.00 17.25 C -ATOM 1170 O LEU B 14 26.440 -13.013 4.127 1.00 15.43 O -ATOM 1171 CB LEU B 14 25.023 -12.816 1.145 1.00 16.82 C -ATOM 1172 CG LEU B 14 25.284 -11.388 1.257 1.00 27.27 C -ATOM 1173 CD1 LEU B 14 26.470 -10.984 0.911 1.00 40.43 C -ATOM 1174 CD2 LEU B 14 23.923 -10.655 1.151 1.00 24.81 C -ATOM 1175 N TRP B 15 24.847 -14.542 3.847 1.00 17.75 N -ATOM 1176 CA TRP B 15 24.543 -14.533 5.293 1.00 20.73 C -ATOM 1177 C TRP B 15 25.779 -15.040 6.144 1.00 17.66 C -ATOM 1178 O TRP B 15 25.791 -14.500 7.295 1.00 18.75 O -ATOM 1179 CB TRP B 15 23.337 -15.255 5.477 1.00 17.11 C -ATOM 1180 CG TRP B 15 22.785 -14.972 6.964 1.00 17.91 C -ATOM 1181 CD1 TRP B 15 22.809 -15.647 8.020 1.00 21.87 C -ATOM 1182 CD2 TRP B 15 21.992 -13.854 7.213 1.00 17.58 C -ATOM 1183 NE1 TRP B 15 22.135 -15.153 9.079 1.00 18.04 N -ATOM 1184 CE2 TRP B 15 21.659 -13.824 8.669 1.00 16.29 C -ATOM 1185 CE3 TRP B 15 21.610 -12.684 6.475 1.00 16.29 C -ATOM 1186 CZ2 TRP B 15 20.847 -12.810 9.252 1.00 25.87 C -ATOM 1187 CZ3 TRP B 15 20.839 -11.689 7.176 1.00 17.96 C -ATOM 1188 CH2 TRP B 15 20.450 -11.898 8.453 1.00 24.12 C -ATOM 1189 N GLY B 16 26.491 -15.885 5.456 1.00 18.59 N -ATOM 1190 CA GLY B 16 27.793 -16.367 6.203 1.00 18.72 C -ATOM 1191 C GLY B 16 28.640 -15.293 6.479 1.00 24.14 C -ATOM 1192 O GLY B 16 29.526 -15.462 7.418 1.00 24.08 O -ATOM 1193 N LYS B 17 28.533 -14.214 5.902 1.00 16.20 N -ATOM 1194 CA LYS B 17 29.341 -13.100 6.055 1.00 17.17 C -ATOM 1195 C LYS B 17 28.732 -12.165 6.877 1.00 17.84 C -ATOM 1196 O LYS B 17 29.459 -11.044 7.345 1.00 23.03 O -ATOM 1197 CB LYS B 17 29.636 -12.212 4.866 1.00 27.63 C -ATOM 1198 CG LYS B 17 30.260 -13.332 3.793 1.00 26.84 C -ATOM 1199 CD LYS B 17 30.681 -12.758 2.663 1.00 36.92 C -ATOM 1200 CE LYS B 17 31.201 -13.748 1.394 1.00 48.09 C -ATOM 1201 NZ LYS B 17 31.749 -12.471 0.760 1.00 51.60 N -ATOM 1202 N VAL B 18 27.632 -12.163 7.561 1.00 19.79 N -ATOM 1203 CA VAL B 18 26.839 -11.228 8.296 1.00 15.59 C -ATOM 1204 C VAL B 18 27.221 -11.355 9.806 1.00 24.20 C -ATOM 1205 O VAL B 18 27.181 -12.396 10.461 1.00 22.49 O -ATOM 1206 CB VAL B 18 25.375 -11.611 8.249 1.00 13.43 C -ATOM 1207 CG1 VAL B 18 24.680 -10.797 9.203 1.00 20.38 C -ATOM 1208 CG2 VAL B 18 25.124 -10.816 6.753 1.00 25.54 C -ATOM 1209 N ASN B 19 27.508 -10.243 10.525 1.00 20.52 N -ATOM 1210 CA ASN B 19 27.647 -10.334 12.056 1.00 15.58 C -ATOM 1211 C ASN B 19 26.161 -10.008 12.553 1.00 13.56 C -ATOM 1212 O ASN B 19 25.706 -8.798 12.411 1.00 14.77 O -ATOM 1213 CB ASN B 19 28.532 -9.065 12.579 1.00 26.08 C -ATOM 1214 CG ASN B 19 28.340 -8.916 14.065 1.00 29.11 C -ATOM 1215 OD1 ASN B 19 27.732 -9.412 14.784 1.00 27.77 O -ATOM 1216 ND2 ASN B 19 29.702 -8.401 14.383 1.00 33.88 N -ATOM 1217 N VAL B 20 25.621 -11.024 13.009 1.00 18.83 N -ATOM 1218 CA VAL B 20 24.087 -11.031 13.284 1.00 19.05 C -ATOM 1219 C VAL B 20 23.851 -10.149 14.214 1.00 20.02 C -ATOM 1220 O VAL B 20 22.901 -9.142 14.245 1.00 17.50 O -ATOM 1221 CB VAL B 20 23.694 -12.517 13.598 1.00 25.16 C -ATOM 1222 CG1 VAL B 20 22.215 -12.356 13.912 1.00 29.32 C -ATOM 1223 CG2 VAL B 20 23.748 -13.338 12.333 1.00 21.26 C -ATOM 1224 N ASP B 21 24.547 -9.725 15.239 1.00 19.64 N -ATOM 1225 CA ASP B 21 24.274 -8.816 16.395 1.00 20.67 C -ATOM 1226 C ASP B 21 24.562 -7.492 15.870 1.00 18.97 C -ATOM 1227 O ASP B 21 23.606 -6.622 16.080 1.00 21.29 O -ATOM 1228 CB ASP B 21 25.312 -9.108 17.415 1.00 34.10 C -ATOM 1229 CG ASP B 21 25.029 -10.570 18.492 1.00 53.28 C -ATOM 1230 OD1 ASP B 21 23.848 -10.805 18.323 1.00 40.86 O -ATOM 1231 OD2 ASP B 21 25.861 -10.240 19.644 1.00 50.69 O -ATOM 1232 N GLU B 22 25.464 -7.225 14.999 1.00 17.77 N -ATOM 1233 CA GLU B 22 25.739 -5.702 14.538 1.00 21.32 C -ATOM 1234 C GLU B 22 24.523 -5.287 13.546 1.00 17.53 C -ATOM 1235 O GLU B 22 23.957 -4.290 13.703 1.00 21.51 O -ATOM 1236 CB GLU B 22 27.018 -5.846 13.812 1.00 24.38 C -ATOM 1237 CG GLU B 22 27.214 -4.730 13.144 1.00 38.60 C -ATOM 1238 CD GLU B 22 28.169 -3.862 11.812 1.00 75.75 C -ATOM 1239 OE1 GLU B 22 28.555 -5.400 11.034 1.00 53.89 O -ATOM 1240 OE2 GLU B 22 29.808 -4.745 12.821 1.00 65.14 O -ATOM 1241 N VAL B 23 24.347 -6.274 12.578 1.00 19.15 N -ATOM 1242 CA VAL B 23 23.303 -6.039 11.518 1.00 16.52 C -ATOM 1243 C VAL B 23 21.857 -5.985 12.342 1.00 19.25 C -ATOM 1244 O VAL B 23 20.964 -5.128 11.822 1.00 16.10 O -ATOM 1245 CB VAL B 23 23.294 -7.123 10.403 1.00 21.83 C -ATOM 1246 CG1 VAL B 23 22.065 -7.019 9.672 1.00 26.98 C -ATOM 1247 CG2 VAL B 23 24.689 -6.722 9.825 1.00 24.14 C -ATOM 1248 N GLY B 24 21.684 -6.753 13.284 1.00 11.83 N -ATOM 1249 CA GLY B 24 20.512 -6.666 14.003 1.00 15.96 C -ATOM 1250 C GLY B 24 20.131 -5.391 14.689 1.00 15.32 C -ATOM 1251 O GLY B 24 19.133 -4.694 14.628 1.00 13.59 O -ATOM 1252 N GLY B 25 21.093 -4.853 15.395 1.00 19.52 N -ATOM 1253 CA GLY B 25 21.202 -3.549 15.972 1.00 15.79 C -ATOM 1254 C GLY B 25 20.921 -2.401 14.917 1.00 12.82 C -ATOM 1255 O GLY B 25 20.200 -1.481 15.135 1.00 18.05 O -ATOM 1256 N GLU B 26 21.598 -2.510 13.849 1.00 12.16 N -ATOM 1257 CA GLU B 26 21.567 -1.493 12.736 1.00 11.32 C -ATOM 1258 C GLU B 26 20.042 -1.534 12.176 1.00 13.79 C -ATOM 1259 O GLU B 26 19.605 -0.362 11.944 1.00 14.59 O -ATOM 1260 CB GLU B 26 22.564 -1.757 11.778 1.00 13.18 C -ATOM 1261 CG GLU B 26 23.022 -0.301 10.974 1.00 29.90 C -ATOM 1262 CD GLU B 26 23.535 0.894 10.508 1.00 51.34 C -ATOM 1263 OE1 GLU B 26 23.767 -0.209 7.916 1.00 54.93 O -ATOM 1264 OE2 GLU B 26 24.549 -1.302 10.298 1.00 37.93 O -ATOM 1265 N ALA B 27 19.659 -2.698 11.904 1.00 13.14 N -ATOM 1266 CA ALA B 27 18.339 -2.622 11.197 1.00 9.05 C -ATOM 1267 C ALA B 27 17.188 -2.188 12.064 1.00 10.83 C -ATOM 1268 O ALA B 27 16.247 -1.538 11.698 1.00 11.12 O -ATOM 1269 CB ALA B 27 18.124 -4.039 10.850 1.00 14.07 C -ATOM 1270 N LEU B 28 17.097 -2.654 13.364 1.00 11.19 N -ATOM 1271 CA LEU B 28 16.289 -2.225 14.403 1.00 14.47 C -ATOM 1272 C LEU B 28 16.216 -0.842 14.498 1.00 12.13 C -ATOM 1273 O LEU B 28 15.292 -0.024 14.599 1.00 12.32 O -ATOM 1274 CB LEU B 28 16.089 -3.101 15.599 1.00 9.21 C -ATOM 1275 CG LEU B 28 14.602 -2.613 16.344 1.00 20.67 C -ATOM 1276 CD1 LEU B 28 13.558 -3.287 15.723 1.00 17.60 C -ATOM 1277 CD2 LEU B 28 15.036 -3.349 17.556 1.00 34.99 C -ATOM 1278 N GLY B 29 17.488 -0.244 14.733 1.00 10.00 N -ATOM 1279 CA GLY B 29 17.555 1.107 14.942 1.00 15.27 C -ATOM 1280 C GLY B 29 17.147 1.979 13.686 1.00 10.88 C -ATOM 1281 O GLY B 29 16.406 2.945 13.855 1.00 14.42 O -ATOM 1282 N ARG B 30 17.503 1.503 12.514 1.00 11.39 N -ATOM 1283 CA ARG B 30 17.138 2.392 11.410 1.00 14.49 C -ATOM 1284 C ARG B 30 15.517 2.168 11.180 1.00 10.79 C -ATOM 1285 O ARG B 30 14.997 3.218 10.749 1.00 13.81 O -ATOM 1286 CB ARG B 30 17.883 1.854 10.134 1.00 19.88 C -ATOM 1287 CG ARG B 30 19.264 2.550 9.848 1.00 16.11 C -ATOM 1288 CD ARG B 30 19.816 1.919 8.615 1.00 14.71 C -ATOM 1289 NE ARG B 30 21.229 2.190 8.567 1.00 21.05 N -ATOM 1290 CZ ARG B 30 21.899 3.048 7.943 1.00 18.56 C -ATOM 1291 NH1 ARG B 30 21.169 3.859 7.078 1.00 19.13 N -ATOM 1292 NH2 ARG B 30 23.126 3.441 7.930 1.00 19.91 N -ATOM 1293 N LEU B 31 14.954 1.034 11.546 1.00 12.04 N -ATOM 1294 CA LEU B 31 13.557 0.954 11.581 1.00 10.54 C -ATOM 1295 C LEU B 31 13.079 2.129 12.312 1.00 13.93 C -ATOM 1296 O LEU B 31 12.053 2.837 11.993 1.00 14.67 O -ATOM 1297 CB LEU B 31 12.999 -0.394 11.933 1.00 12.99 C -ATOM 1298 CG LEU B 31 11.476 -0.524 12.150 1.00 10.97 C -ATOM 1299 CD1 LEU B 31 11.036 -0.535 10.722 1.00 19.46 C -ATOM 1300 CD2 LEU B 31 11.106 -1.700 13.040 1.00 13.98 C -ATOM 1301 N LEU B 32 13.531 2.329 13.530 1.00 10.13 N -ATOM 1302 CA LEU B 32 12.882 3.156 14.401 1.00 11.52 C -ATOM 1303 C LEU B 32 13.149 4.616 14.057 1.00 12.11 C -ATOM 1304 O LEU B 32 12.467 5.633 14.438 1.00 15.31 O -ATOM 1305 CB LEU B 32 13.453 3.038 15.919 1.00 11.75 C -ATOM 1306 CG LEU B 32 12.805 1.940 16.581 1.00 16.68 C -ATOM 1307 CD1 LEU B 32 12.104 0.941 16.260 1.00 22.26 C -ATOM 1308 CD2 LEU B 32 13.566 1.603 17.835 1.00 28.90 C -ATOM 1309 N VAL B 33 14.250 4.899 13.351 1.00 10.32 N -ATOM 1310 CA VAL B 33 14.628 6.174 12.868 1.00 11.98 C -ATOM 1311 C VAL B 33 13.704 6.548 11.535 1.00 12.10 C -ATOM 1312 O VAL B 33 13.345 7.771 11.481 1.00 13.28 O -ATOM 1313 CB VAL B 33 16.139 6.304 12.522 1.00 14.87 C -ATOM 1314 CG1 VAL B 33 16.518 7.591 11.880 1.00 11.54 C -ATOM 1315 CG2 VAL B 33 16.745 6.275 13.788 1.00 16.57 C -ATOM 1316 N VAL B 34 13.820 5.650 10.638 1.00 13.66 N -ATOM 1317 CA VAL B 34 13.156 6.096 9.258 1.00 9.59 C -ATOM 1318 C VAL B 34 11.591 6.042 9.368 1.00 8.72 C -ATOM 1319 O VAL B 34 11.052 6.910 8.763 1.00 9.42 O -ATOM 1320 CB VAL B 34 13.681 5.042 8.326 1.00 9.09 C -ATOM 1321 CG1 VAL B 34 13.079 5.328 6.958 1.00 9.82 C -ATOM 1322 CG2 VAL B 34 15.076 5.133 8.253 1.00 17.00 C -ATOM 1323 N TYR B 35 11.088 5.155 10.260 1.00 10.80 N -ATOM 1324 CA TYR B 35 9.613 5.019 10.405 1.00 13.73 C -ATOM 1325 C TYR B 35 9.249 5.241 11.959 1.00 14.87 C -ATOM 1326 O TYR B 35 9.056 4.156 12.514 1.00 16.30 O -ATOM 1327 CB TYR B 35 9.162 3.628 9.962 1.00 14.97 C -ATOM 1328 CG TYR B 35 9.590 3.397 8.554 1.00 16.57 C -ATOM 1329 CD1 TYR B 35 9.059 4.138 7.400 1.00 17.11 C -ATOM 1330 CD2 TYR B 35 10.495 2.446 8.096 1.00 21.02 C -ATOM 1331 CE1 TYR B 35 9.473 3.862 6.085 1.00 16.53 C -ATOM 1332 CE2 TYR B 35 10.987 2.455 6.905 1.00 21.07 C -ATOM 1333 CZ TYR B 35 10.434 2.948 5.860 1.00 16.91 C -ATOM 1334 OH TYR B 35 11.073 2.851 4.537 1.00 21.07 O -ATOM 1335 N PRO B 36 9.337 6.384 12.381 1.00 18.32 N -ATOM 1336 CA PRO B 36 9.299 6.665 13.797 1.00 15.72 C -ATOM 1337 C PRO B 36 8.010 6.232 14.403 1.00 27.07 C -ATOM 1338 O PRO B 36 8.028 5.977 15.694 1.00 15.67 O -ATOM 1339 CB PRO B 36 9.448 8.143 14.056 1.00 16.26 C -ATOM 1340 CG PRO B 36 9.504 8.813 12.839 1.00 21.27 C -ATOM 1341 CD PRO B 36 9.498 7.681 11.841 1.00 25.93 C -ATOM 1342 N TRP B 37 6.917 5.884 13.840 1.00 14.10 N -ATOM 1343 CA TRP B 37 5.821 5.395 14.601 1.00 12.74 C -ATOM 1344 C TRP B 37 5.965 3.976 15.036 1.00 15.06 C -ATOM 1345 O TRP B 37 5.268 3.465 15.926 1.00 15.27 O -ATOM 1346 CB TRP B 37 4.670 5.475 13.490 1.00 19.41 C -ATOM 1347 CG TRP B 37 4.766 4.831 12.253 1.00 14.79 C -ATOM 1348 CD1 TRP B 37 4.298 3.513 11.774 1.00 18.82 C -ATOM 1349 CD2 TRP B 37 5.265 5.442 10.984 1.00 18.23 C -ATOM 1350 NE1 TRP B 37 4.669 3.435 10.535 1.00 23.72 N -ATOM 1351 CE2 TRP B 37 5.184 4.400 9.923 1.00 22.13 C -ATOM 1352 CE3 TRP B 37 5.947 6.691 10.672 1.00 21.52 C -ATOM 1353 CZ2 TRP B 37 5.584 4.556 8.589 1.00 18.19 C -ATOM 1354 CZ3 TRP B 37 6.183 6.773 9.398 1.00 31.71 C -ATOM 1355 CH2 TRP B 37 6.069 5.844 8.520 1.00 14.12 C -ATOM 1356 N THR B 38 7.039 3.221 14.646 1.00 14.17 N -ATOM 1357 CA THR B 38 7.466 1.912 14.979 1.00 13.46 C -ATOM 1358 C THR B 38 7.760 1.960 16.519 1.00 16.65 C -ATOM 1359 O THR B 38 8.073 0.918 17.118 1.00 18.86 O -ATOM 1360 CB THR B 38 8.456 1.107 14.212 1.00 12.74 C -ATOM 1361 OG1 THR B 38 9.507 1.962 14.105 1.00 14.09 O -ATOM 1362 CG2 THR B 38 7.863 1.128 12.798 1.00 15.42 C -ATOM 1363 N GLN B 39 8.203 3.108 16.922 1.00 19.91 N -ATOM 1364 CA GLN B 39 8.656 3.567 18.379 1.00 23.22 C -ATOM 1365 C GLN B 39 7.604 3.201 19.358 1.00 19.19 C -ATOM 1366 O GLN B 39 7.968 2.987 20.495 1.00 19.29 O -ATOM 1367 CB GLN B 39 9.277 4.878 18.529 1.00 24.35 C -ATOM 1368 CG GLN B 39 10.405 5.137 17.759 1.00 25.27 C -ATOM 1369 CD GLN B 39 10.983 6.633 17.918 1.00 24.35 C -ATOM 1370 OE1 GLN B 39 10.480 7.189 18.922 1.00 26.75 O -ATOM 1371 NE2 GLN B 39 11.852 7.006 16.956 1.00 30.18 N -ATOM 1372 N ARG B 40 6.347 3.079 18.900 1.00 20.02 N -ATOM 1373 CA ARG B 40 5.184 2.850 19.816 1.00 21.80 C -ATOM 1374 C ARG B 40 5.511 1.455 20.630 1.00 29.36 C -ATOM 1375 O ARG B 40 4.888 1.619 21.749 1.00 24.42 O -ATOM 1376 CB ARG B 40 3.944 2.700 18.938 1.00 16.52 C -ATOM 1377 CG ARG B 40 3.694 1.420 18.404 1.00 20.34 C -ATOM 1378 CD ARG B 40 2.451 1.519 17.302 1.00 25.31 C -ATOM 1379 NE ARG B 40 1.370 1.856 17.810 1.00 29.70 N -ATOM 1380 CZ ARG B 40 0.400 1.022 18.648 1.00 34.46 C -ATOM 1381 NH1 ARG B 40 0.678 -0.097 18.556 1.00 31.34 N -ATOM 1382 NH2 ARG B 40 -0.783 2.010 18.877 1.00 39.12 N -ATOM 1383 N PHE B 41 6.149 0.541 20.453 1.00 19.21 N -ATOM 1384 CA PHE B 41 6.133 -0.730 21.151 1.00 16.53 C -ATOM 1385 C PHE B 41 7.442 -0.621 22.343 1.00 21.34 C -ATOM 1386 O PHE B 41 7.412 -1.538 22.897 1.00 23.45 O -ATOM 1387 CB PHE B 41 6.675 -1.804 20.080 1.00 10.39 C -ATOM 1388 CG PHE B 41 5.553 -1.984 19.152 1.00 13.84 C -ATOM 1389 CD1 PHE B 41 5.763 -1.448 17.828 1.00 17.38 C -ATOM 1390 CD2 PHE B 41 4.239 -2.655 19.578 1.00 25.55 C -ATOM 1391 CE1 PHE B 41 4.713 -1.720 16.922 1.00 15.72 C -ATOM 1392 CE2 PHE B 41 3.272 -2.680 18.459 1.00 21.40 C -ATOM 1393 CZ PHE B 41 3.586 -2.146 17.207 1.00 13.46 C -ATOM 1394 N PHE B 42 8.072 0.397 22.159 1.00 18.41 N -ATOM 1395 CA PHE B 42 9.433 0.476 22.639 1.00 17.88 C -ATOM 1396 C PHE B 42 9.683 1.552 23.631 1.00 26.28 C -ATOM 1397 O PHE B 42 10.712 1.963 24.025 1.00 30.16 O -ATOM 1398 CB PHE B 42 10.561 0.553 21.602 1.00 16.57 C -ATOM 1399 CG PHE B 42 10.524 -0.621 20.906 1.00 18.87 C -ATOM 1400 CD1 PHE B 42 10.208 -0.431 19.261 1.00 17.08 C -ATOM 1401 CD2 PHE B 42 10.804 -1.937 21.065 1.00 17.75 C -ATOM 1402 CE1 PHE B 42 10.137 -1.716 18.672 1.00 12.34 C -ATOM 1403 CE2 PHE B 42 10.625 -2.998 20.314 1.00 16.32 C -ATOM 1404 CZ PHE B 42 10.370 -2.870 18.826 1.00 14.29 C -ATOM 1405 N GLU B 43 8.703 2.022 24.176 1.00 32.94 N -ATOM 1406 CA GLU B 43 9.021 3.274 25.060 1.00 42.17 C -ATOM 1407 C GLU B 43 9.315 2.924 26.617 1.00 21.09 C -ATOM 1408 O GLU B 43 10.204 3.362 27.291 1.00 37.55 O -ATOM 1409 CB GLU B 43 7.798 3.586 25.059 1.00 73.91 C -ATOM 1410 CG GLU B 43 6.528 3.291 25.915 1.00 61.81 C -ATOM 1411 CD GLU B 43 4.777 4.930 25.558 1.00 78.77 C -ATOM 1412 OE1 GLU B 43 5.276 5.543 25.252 1.00 63.33 O -ATOM 1413 OE2 GLU B 43 4.274 3.783 26.403 1.00 59.41 O -ATOM 1414 N SER B 44 9.424 1.477 26.805 1.00 22.68 N -ATOM 1415 CA SER B 44 10.261 0.951 28.039 1.00 28.45 C -ATOM 1416 C SER B 44 11.527 1.680 27.935 1.00 36.10 C -ATOM 1417 O SER B 44 12.578 0.776 28.511 1.00 25.24 O -ATOM 1418 CB SER B 44 9.957 -0.409 28.119 1.00 27.61 C -ATOM 1419 OG SER B 44 10.204 -1.503 27.766 1.00 37.26 O -ATOM 1420 N PHE B 45 12.292 1.349 26.626 1.00 28.36 N -ATOM 1421 CA PHE B 45 13.648 1.329 26.186 1.00 25.47 C -ATOM 1422 C PHE B 45 14.197 2.590 26.508 1.00 26.28 C -ATOM 1423 O PHE B 45 15.451 2.670 26.190 1.00 31.39 O -ATOM 1424 CB PHE B 45 13.618 0.947 24.623 1.00 22.10 C -ATOM 1425 CG PHE B 45 13.541 -0.652 24.249 1.00 18.85 C -ATOM 1426 CD1 PHE B 45 13.939 -0.880 22.983 1.00 29.27 C -ATOM 1427 CD2 PHE B 45 12.982 -1.450 24.626 1.00 31.57 C -ATOM 1428 CE1 PHE B 45 13.682 -2.441 22.618 1.00 29.02 C -ATOM 1429 CE2 PHE B 45 12.642 -2.810 24.625 1.00 30.34 C -ATOM 1430 CZ PHE B 45 13.202 -2.999 23.312 1.00 36.33 C -ATOM 1431 N GLY B 46 13.772 3.730 26.937 1.00 39.28 N -ATOM 1432 CA GLY B 46 14.529 4.785 27.301 1.00 46.90 C -ATOM 1433 C GLY B 46 14.720 5.977 26.137 1.00 45.06 C -ATOM 1434 O GLY B 46 13.492 6.152 25.410 1.00 36.42 O -ATOM 1435 N ASP B 47 15.717 6.365 26.037 1.00 38.00 N -ATOM 1436 CA ASP B 47 15.729 7.801 25.184 1.00 38.15 C -ATOM 1437 C ASP B 47 16.096 7.362 23.534 1.00 25.86 C -ATOM 1438 O ASP B 47 16.860 6.380 23.281 1.00 25.46 O -ATOM 1439 CB ASP B 47 17.237 8.136 25.516 1.00 44.07 C -ATOM 1440 CG ASP B 47 17.345 9.494 25.209 1.00 52.06 C -ATOM 1441 OD1 ASP B 47 18.506 10.069 24.917 1.00 44.54 O -ATOM 1442 OD2 ASP B 47 16.192 10.248 24.076 1.00 35.33 O -ATOM 1443 N LEU B 48 14.758 7.696 22.981 1.00 25.27 N -ATOM 1444 CA LEU B 48 14.475 7.473 21.435 1.00 28.75 C -ATOM 1445 C LEU B 48 14.468 8.903 20.740 1.00 27.19 C -ATOM 1446 O LEU B 48 13.953 8.921 19.724 1.00 27.20 O -ATOM 1447 CB LEU B 48 13.484 6.505 21.317 1.00 23.96 C -ATOM 1448 CG LEU B 48 13.754 5.148 21.718 1.00 24.35 C -ATOM 1449 CD1 LEU B 48 12.414 4.237 21.541 1.00 34.74 C -ATOM 1450 CD2 LEU B 48 14.775 4.377 21.408 1.00 34.58 C -ATOM 1451 N SER B 49 15.103 9.812 21.342 1.00 41.94 N -ATOM 1452 CA SER B 49 14.421 11.168 20.634 1.00 46.28 C -ATOM 1453 C SER B 49 15.582 11.613 20.219 1.00 38.86 C -ATOM 1454 O SER B 49 14.817 12.605 18.942 1.00 41.94 O -ATOM 1455 CB SER B 49 14.717 12.244 22.089 1.00 37.98 C -ATOM 1456 OG SER B 49 16.403 12.088 22.302 1.00 37.71 O -ATOM 1457 N THR B 50 16.507 11.264 19.343 1.00 28.29 N -ATOM 1458 CA THR B 50 17.236 11.360 18.289 1.00 30.77 C -ATOM 1459 C THR B 50 17.885 10.175 17.455 1.00 28.12 C -ATOM 1460 O THR B 50 17.899 9.107 18.221 1.00 25.38 O -ATOM 1461 CB THR B 50 18.076 12.160 18.824 1.00 33.39 C -ATOM 1462 OG1 THR B 50 19.415 11.795 19.160 1.00 37.96 O -ATOM 1463 CG2 THR B 50 18.083 13.812 19.397 1.00 29.64 C -ATOM 1464 N PRO B 51 18.477 10.443 16.283 1.00 28.96 N -ATOM 1465 CA PRO B 51 18.840 9.268 15.580 1.00 22.25 C -ATOM 1466 C PRO B 51 20.003 8.659 16.259 1.00 19.80 C -ATOM 1467 O PRO B 51 20.229 7.322 16.651 1.00 21.55 O -ATOM 1468 CB PRO B 51 19.279 9.752 14.257 1.00 27.29 C -ATOM 1469 CG PRO B 51 18.236 10.849 14.019 1.00 23.54 C -ATOM 1470 CD PRO B 51 18.120 11.592 15.204 1.00 26.04 C -ATOM 1471 N ASP B 52 20.955 9.490 16.887 1.00 21.99 N -ATOM 1472 CA ASP B 52 22.107 9.063 17.596 1.00 20.50 C -ATOM 1473 C ASP B 52 21.711 8.282 18.816 1.00 16.32 C -ATOM 1474 O ASP B 52 22.264 7.261 19.307 1.00 25.55 O -ATOM 1475 CB ASP B 52 22.971 10.246 17.966 1.00 32.17 C -ATOM 1476 CG ASP B 52 24.234 10.367 16.728 1.00 47.24 C -ATOM 1477 OD1 ASP B 52 24.140 9.731 15.886 1.00 41.78 O -ATOM 1478 OD2 ASP B 52 24.041 11.689 16.359 1.00 62.08 O -ATOM 1479 N ALA B 53 20.654 8.843 19.515 1.00 23.18 N -ATOM 1480 CA ALA B 53 20.143 8.181 20.776 1.00 24.60 C -ATOM 1481 C ALA B 53 19.728 6.737 20.669 1.00 20.91 C -ATOM 1482 O ALA B 53 19.736 5.693 21.187 1.00 20.19 O -ATOM 1483 CB ALA B 53 19.176 8.937 21.371 1.00 23.45 C -ATOM 1484 N VAL B 54 18.925 6.610 19.428 1.00 19.02 N -ATOM 1485 CA VAL B 54 18.396 5.367 18.970 1.00 17.30 C -ATOM 1486 C VAL B 54 19.363 4.542 18.660 1.00 15.03 C -ATOM 1487 O VAL B 54 19.429 3.266 19.120 1.00 19.06 O -ATOM 1488 CB VAL B 54 17.268 5.613 17.733 1.00 27.63 C -ATOM 1489 CG1 VAL B 54 17.019 4.214 17.213 1.00 22.46 C -ATOM 1490 CG2 VAL B 54 16.224 6.564 17.992 1.00 27.27 C -ATOM 1491 N MET B 55 20.370 4.888 17.834 1.00 21.73 N -ATOM 1492 CA MET B 55 21.262 3.920 17.351 1.00 17.86 C -ATOM 1493 C MET B 55 22.215 3.437 18.454 1.00 32.16 C -ATOM 1494 O MET B 55 22.701 2.355 18.174 1.00 26.15 O -ATOM 1495 CB MET B 55 22.167 4.509 16.152 1.00 19.12 C -ATOM 1496 CG MET B 55 21.367 4.924 14.914 1.00 18.10 C -ATOM 1497 SD MET B 55 20.328 3.573 14.221 1.00 21.28 S -ATOM 1498 CE MET B 55 21.373 2.471 13.659 1.00 20.66 C -ATOM 1499 N GLY B 56 22.406 4.339 19.361 1.00 24.42 N -ATOM 1500 CA GLY B 56 23.329 3.841 20.456 1.00 36.79 C -ATOM 1501 C GLY B 56 22.514 3.565 21.746 1.00 33.28 C -ATOM 1502 O GLY B 56 23.093 2.903 22.699 1.00 24.94 O -ATOM 1503 N ASN B 57 21.348 2.997 21.778 1.00 22.01 N -ATOM 1504 CA ASN B 57 20.559 2.685 22.827 1.00 15.71 C -ATOM 1505 C ASN B 57 20.755 1.267 22.976 1.00 17.88 C -ATOM 1506 O ASN B 57 20.502 0.300 22.098 1.00 18.04 O -ATOM 1507 CB ASN B 57 19.144 2.920 22.701 1.00 21.80 C -ATOM 1508 CG ASN B 57 18.247 2.358 23.776 1.00 18.78 C -ATOM 1509 OD1 ASN B 57 18.261 1.376 24.212 1.00 23.41 O -ATOM 1510 ND2 ASN B 57 17.583 3.338 24.270 1.00 26.53 N -ATOM 1511 N PRO B 58 21.174 0.662 24.086 1.00 24.81 N -ATOM 1512 CA PRO B 58 21.379 -0.699 24.384 1.00 24.38 C -ATOM 1513 C PRO B 58 20.320 -1.707 24.238 1.00 16.45 C -ATOM 1514 O PRO B 58 20.621 -2.865 23.942 1.00 22.03 O -ATOM 1515 CB PRO B 58 22.199 -0.585 25.810 1.00 41.00 C -ATOM 1516 CG PRO B 58 21.985 0.546 26.007 1.00 36.46 C -ATOM 1517 CD PRO B 58 21.572 1.751 25.438 1.00 41.75 C -ATOM 1518 N LYS B 59 19.129 -1.092 24.601 1.00 16.03 N -ATOM 1519 CA LYS B 59 17.877 -2.002 24.599 1.00 22.04 C -ATOM 1520 C LYS B 59 17.389 -2.185 23.113 1.00 13.98 C -ATOM 1521 O LYS B 59 17.132 -3.370 22.712 1.00 15.67 O -ATOM 1522 CB LYS B 59 16.893 -1.439 25.346 1.00 22.22 C -ATOM 1523 CG LYS B 59 17.003 -1.840 26.817 1.00 45.70 C -ATOM 1524 CD LYS B 59 17.133 -0.988 27.329 1.00 44.05 C -ATOM 1525 CE LYS B 59 17.311 -2.126 29.392 1.00 71.22 C -ATOM 1526 NZ LYS B 59 16.304 -0.516 29.672 1.00 61.54 N -ATOM 1527 N VAL B 60 17.762 -1.228 22.435 1.00 17.28 N -ATOM 1528 CA VAL B 60 17.489 -1.267 20.987 1.00 18.21 C -ATOM 1529 C VAL B 60 18.198 -2.383 20.467 1.00 17.60 C -ATOM 1530 O VAL B 60 18.065 -3.331 19.597 1.00 19.11 O -ATOM 1531 CB VAL B 60 17.415 0.000 20.196 1.00 19.15 C -ATOM 1532 CG1 VAL B 60 17.700 -0.242 18.743 1.00 20.44 C -ATOM 1533 CG2 VAL B 60 16.452 0.957 20.699 1.00 20.64 C -ATOM 1534 N LYS B 61 19.612 -2.162 20.575 1.00 16.19 N -ATOM 1535 CA LYS B 61 20.529 -3.146 20.062 1.00 15.00 C -ATOM 1536 C LYS B 61 20.399 -4.610 20.622 1.00 17.90 C -ATOM 1537 O LYS B 61 20.213 -5.649 19.890 1.00 20.52 O -ATOM 1538 CB LYS B 61 21.934 -2.794 20.686 1.00 23.50 C -ATOM 1539 CG LYS B 61 22.389 -1.790 20.123 1.00 34.21 C -ATOM 1540 CD LYS B 61 23.914 -1.121 21.095 1.00 48.05 C -ATOM 1541 CE LYS B 61 24.659 -0.514 19.697 1.00 65.12 C -ATOM 1542 NZ LYS B 61 25.928 0.153 20.694 1.00 66.26 N -ATOM 1543 N ALA B 62 19.935 -4.789 21.817 1.00 18.99 N -ATOM 1544 CA ALA B 62 19.613 -6.179 22.281 1.00 20.11 C -ATOM 1545 C ALA B 62 18.327 -6.740 21.532 1.00 23.44 C -ATOM 1546 O ALA B 62 18.260 -7.852 21.400 1.00 21.26 O -ATOM 1547 CB ALA B 62 19.287 -6.023 23.792 1.00 28.90 C -ATOM 1548 N HIS B 63 17.361 -5.800 21.608 1.00 20.40 N -ATOM 1549 CA HIS B 63 16.190 -6.291 20.805 1.00 18.39 C -ATOM 1550 C HIS B 63 16.516 -6.639 19.256 1.00 14.88 C -ATOM 1551 O HIS B 63 16.111 -7.828 18.863 1.00 18.29 O -ATOM 1552 CB HIS B 63 15.116 -5.410 20.859 1.00 22.46 C -ATOM 1553 CG HIS B 63 13.751 -5.776 20.554 1.00 25.19 C -ATOM 1554 ND1 HIS B 63 13.281 -7.248 21.117 1.00 24.68 N -ATOM 1555 CD2 HIS B 63 13.005 -5.716 19.310 1.00 20.46 C -ATOM 1556 CE1 HIS B 63 11.969 -7.447 20.274 1.00 21.48 C -ATOM 1557 NE2 HIS B 63 11.891 -6.627 19.400 1.00 20.00 N -ATOM 1558 N GLY B 64 17.369 -5.912 18.807 1.00 15.81 N -ATOM 1559 CA GLY B 64 17.753 -6.266 17.372 1.00 16.57 C -ATOM 1560 C GLY B 64 18.356 -7.523 17.041 1.00 14.05 C -ATOM 1561 O GLY B 64 18.321 -8.353 16.306 1.00 17.38 O -ATOM 1562 N LYS B 65 19.222 -7.845 18.080 1.00 15.77 N -ATOM 1563 CA LYS B 65 19.749 -9.096 18.187 1.00 17.79 C -ATOM 1564 C LYS B 65 18.945 -10.321 18.319 1.00 18.32 C -ATOM 1565 O LYS B 65 19.205 -11.332 17.796 1.00 19.33 O -ATOM 1566 CB LYS B 65 21.117 -9.195 19.352 1.00 34.65 C -ATOM 1567 CG LYS B 65 20.823 -9.337 19.828 1.00 64.04 C -ATOM 1568 CD LYS B 65 22.866 -9.404 21.254 1.00 58.77 C -ATOM 1569 CE LYS B 65 21.591 -11.376 21.213 1.00 64.47 C -ATOM 1570 NZ LYS B 65 22.762 -11.190 23.512 1.00 67.19 N -ATOM 1571 N LYS B 66 17.979 -10.126 19.094 1.00 17.45 N -ATOM 1572 CA LYS B 66 17.297 -11.071 19.293 1.00 20.10 C -ATOM 1573 C LYS B 66 16.171 -11.403 18.033 1.00 21.06 C -ATOM 1574 O LYS B 66 15.915 -12.596 17.725 1.00 17.84 O -ATOM 1575 CB LYS B 66 16.183 -10.827 20.504 1.00 22.19 C -ATOM 1576 CG LYS B 66 15.115 -11.668 20.860 1.00 40.97 C -ATOM 1577 CD LYS B 66 14.348 -11.289 22.165 1.00 49.22 C -ATOM 1578 CE LYS B 66 14.883 -13.426 23.031 1.00 72.58 C -ATOM 1579 NZ LYS B 66 13.505 -13.329 24.195 1.00 70.66 N -ATOM 1580 N VAL B 67 15.722 -10.213 17.591 1.00 16.93 N -ATOM 1581 CA VAL B 67 14.967 -10.430 16.204 1.00 19.22 C -ATOM 1582 C VAL B 67 15.793 -10.926 15.110 1.00 11.08 C -ATOM 1583 O VAL B 67 15.419 -12.032 14.481 1.00 14.57 O -ATOM 1584 CB VAL B 67 14.239 -9.056 15.913 1.00 21.56 C -ATOM 1585 CG1 VAL B 67 13.929 -8.835 14.427 1.00 18.58 C -ATOM 1586 CG2 VAL B 67 13.400 -8.550 17.010 1.00 21.34 C -ATOM 1587 N LEU B 68 16.954 -10.461 14.916 1.00 11.62 N -ATOM 1588 CA LEU B 68 17.765 -11.045 13.835 1.00 15.23 C -ATOM 1589 C LEU B 68 18.198 -12.546 14.030 1.00 13.22 C -ATOM 1590 O LEU B 68 18.576 -13.320 13.014 1.00 14.49 O -ATOM 1591 CB LEU B 68 18.788 -10.157 13.424 1.00 22.80 C -ATOM 1592 CG LEU B 68 18.947 -9.620 11.990 1.00 26.57 C -ATOM 1593 CD1 LEU B 68 20.192 -10.323 11.868 1.00 62.38 C -ATOM 1594 CD2 LEU B 68 17.922 -9.301 11.306 1.00 35.30 C -ATOM 1595 N GLY B 69 18.512 -12.954 15.230 1.00 14.77 N -ATOM 1596 CA GLY B 69 18.843 -14.169 15.499 1.00 20.29 C -ATOM 1597 C GLY B 69 17.847 -15.440 15.178 1.00 17.59 C -ATOM 1598 O GLY B 69 17.982 -16.324 14.534 1.00 19.02 O -ATOM 1599 N ALA B 70 16.471 -14.870 15.541 1.00 19.76 N -ATOM 1600 CA ALA B 70 15.432 -15.582 15.055 1.00 20.35 C -ATOM 1601 C ALA B 70 15.296 -15.691 13.506 1.00 16.36 C -ATOM 1602 O ALA B 70 14.996 -16.706 12.805 1.00 18.12 O -ATOM 1603 CB ALA B 70 14.137 -15.174 15.556 1.00 18.92 C -ATOM 1604 N PHE B 71 15.441 -14.520 12.868 1.00 14.47 N -ATOM 1605 CA PHE B 71 15.473 -14.523 11.393 1.00 18.37 C -ATOM 1606 C PHE B 71 16.681 -15.484 10.885 1.00 23.80 C -ATOM 1607 O PHE B 71 16.324 -16.238 10.064 1.00 20.23 O -ATOM 1608 CB PHE B 71 15.760 -13.050 11.104 1.00 13.73 C -ATOM 1609 CG PHE B 71 15.796 -12.885 9.606 1.00 18.08 C -ATOM 1610 CD1 PHE B 71 14.729 -12.558 8.930 1.00 25.10 C -ATOM 1611 CD2 PHE B 71 17.072 -12.967 8.830 1.00 17.17 C -ATOM 1612 CE1 PHE B 71 14.623 -12.282 7.460 1.00 19.10 C -ATOM 1613 CE2 PHE B 71 16.901 -12.741 7.550 1.00 22.20 C -ATOM 1614 CZ PHE B 71 15.701 -12.364 6.812 1.00 12.94 C -ATOM 1615 N SER B 72 17.595 -15.502 11.393 1.00 20.10 N -ATOM 1616 CA SER B 72 18.969 -16.288 11.125 1.00 20.52 C -ATOM 1617 C SER B 72 18.446 -17.702 11.027 1.00 24.58 C -ATOM 1618 O SER B 72 18.709 -18.593 10.064 1.00 22.06 O -ATOM 1619 CB SER B 72 20.232 -15.732 11.864 1.00 15.28 C -ATOM 1620 OG SER B 72 21.400 -16.267 11.544 1.00 25.10 O -ATOM 1621 N ASP B 73 17.933 -17.999 12.102 1.00 27.59 N -ATOM 1622 CA ASP B 73 17.456 -19.508 12.282 1.00 37.45 C -ATOM 1623 C ASP B 73 16.631 -19.746 11.447 1.00 25.08 C -ATOM 1624 O ASP B 73 16.306 -20.962 10.848 1.00 31.64 O -ATOM 1625 CB ASP B 73 17.022 -19.613 13.914 1.00 36.32 C -ATOM 1626 CG ASP B 73 18.407 -19.595 14.926 1.00 45.09 C -ATOM 1627 OD1 ASP B 73 19.800 -19.407 14.506 1.00 37.33 O -ATOM 1628 OD2 ASP B 73 18.096 -19.496 15.880 1.00 52.94 O -ATOM 1629 N GLY B 74 15.535 -19.019 10.954 1.00 21.04 N -ATOM 1630 CA GLY B 74 14.735 -19.149 9.973 1.00 15.14 C -ATOM 1631 C GLY B 74 14.988 -19.490 8.722 1.00 22.81 C -ATOM 1632 O GLY B 74 14.637 -20.071 7.621 1.00 25.94 O -ATOM 1633 N LEU B 75 16.509 -18.919 8.215 1.00 20.94 N -ATOM 1634 CA LEU B 75 17.037 -19.090 6.965 1.00 15.84 C -ATOM 1635 C LEU B 75 17.465 -20.570 6.842 1.00 26.11 C -ATOM 1636 O LEU B 75 17.646 -20.979 5.741 1.00 28.14 O -ATOM 1637 CB LEU B 75 18.377 -18.389 6.691 1.00 21.09 C -ATOM 1638 CG LEU B 75 18.160 -17.146 6.885 1.00 27.76 C -ATOM 1639 CD1 LEU B 75 19.415 -16.065 6.621 1.00 33.03 C -ATOM 1640 CD2 LEU B 75 17.192 -16.405 5.891 1.00 30.01 C -ATOM 1641 N ALA B 76 17.528 -21.312 7.923 1.00 21.21 N -ATOM 1642 CA ALA B 76 17.717 -22.609 7.710 1.00 22.79 C -ATOM 1643 C ALA B 76 16.647 -23.681 7.464 1.00 40.88 C -ATOM 1644 O ALA B 76 16.656 -24.527 7.123 1.00 38.44 O -ATOM 1645 CB ALA B 76 18.164 -23.328 9.061 1.00 29.05 C -ATOM 1646 N HIS B 77 15.219 -22.886 7.385 1.00 23.87 N -ATOM 1647 CA HIS B 77 13.929 -23.700 7.284 1.00 21.57 C -ATOM 1648 C HIS B 77 13.284 -22.870 6.150 1.00 18.37 C -ATOM 1649 O HIS B 77 12.059 -22.798 6.220 1.00 23.13 O -ATOM 1650 CB HIS B 77 13.250 -23.395 8.460 1.00 29.02 C -ATOM 1651 CG HIS B 77 14.079 -24.146 9.683 1.00 36.16 C -ATOM 1652 ND1 HIS B 77 14.936 -23.842 10.757 1.00 45.10 N -ATOM 1653 CD2 HIS B 77 14.095 -25.953 9.360 1.00 41.12 C -ATOM 1654 CE1 HIS B 77 15.178 -24.891 11.130 1.00 37.52 C -ATOM 1655 NE2 HIS B 77 14.852 -25.983 10.561 1.00 42.04 N -ATOM 1656 N LEU B 78 13.874 -22.553 5.099 1.00 22.31 N -ATOM 1657 CA LEU B 78 13.302 -21.614 4.148 1.00 20.28 C -ATOM 1658 C LEU B 78 12.283 -22.522 3.216 1.00 31.20 C -ATOM 1659 O LEU B 78 11.288 -21.899 3.087 1.00 34.80 O -ATOM 1660 CB LEU B 78 14.257 -21.383 2.881 1.00 19.92 C -ATOM 1661 CG LEU B 78 14.986 -19.978 3.420 1.00 39.49 C -ATOM 1662 CD1 LEU B 78 16.407 -19.926 2.680 1.00 34.16 C -ATOM 1663 CD2 LEU B 78 14.406 -18.731 3.892 1.00 31.09 C -ATOM 1664 N ASP B 79 12.097 -23.916 3.393 1.00 31.59 N -ATOM 1665 CA ASP B 79 11.104 -24.882 2.602 1.00 37.85 C -ATOM 1666 C ASP B 79 9.843 -24.653 3.569 1.00 38.72 C -ATOM 1667 O ASP B 79 9.096 -25.342 3.631 1.00 37.62 O -ATOM 1668 CB ASP B 79 11.737 -26.234 3.104 1.00 48.10 C -ATOM 1669 CG ASP B 79 12.662 -26.319 2.384 1.00 61.60 C -ATOM 1670 OD1 ASP B 79 13.286 -27.317 2.464 1.00 57.05 O -ATOM 1671 OD2 ASP B 79 12.655 -25.818 0.790 1.00 50.26 O -ATOM 1672 N ASN B 80 10.028 -24.212 4.945 1.00 35.73 N -ATOM 1673 CA ASN B 80 8.836 -24.555 6.146 1.00 42.30 C -ATOM 1674 C ASN B 80 9.062 -22.961 6.944 1.00 30.43 C -ATOM 1675 O ASN B 80 8.998 -23.185 7.997 1.00 27.17 O -ATOM 1676 CB ASN B 80 9.098 -25.723 6.800 1.00 45.64 C -ATOM 1677 CG ASN B 80 7.793 -26.259 7.837 1.00 49.79 C -ATOM 1678 OD1 ASN B 80 6.751 -25.228 7.493 1.00 49.18 O -ATOM 1679 ND2 ASN B 80 8.556 -26.466 8.946 1.00 48.18 N -ATOM 1680 N LEU B 81 8.851 -21.845 6.271 1.00 31.23 N -ATOM 1681 CA LEU B 81 8.683 -20.637 7.429 1.00 24.59 C -ATOM 1682 C LEU B 81 7.679 -20.724 8.281 1.00 25.32 C -ATOM 1683 O LEU B 81 7.523 -20.208 9.309 1.00 23.54 O -ATOM 1684 CB LEU B 81 8.987 -19.631 6.449 1.00 29.09 C -ATOM 1685 CG LEU B 81 10.160 -19.226 5.665 1.00 21.46 C -ATOM 1686 CD1 LEU B 81 10.084 -18.185 4.643 1.00 28.62 C -ATOM 1687 CD2 LEU B 81 11.341 -18.875 6.546 1.00 30.82 C -ATOM 1688 N LYS B 82 6.283 -21.136 7.490 1.00 26.15 N -ATOM 1689 CA LYS B 82 5.156 -20.862 8.452 1.00 24.25 C -ATOM 1690 C LYS B 82 5.202 -21.643 9.461 1.00 23.08 C -ATOM 1691 O LYS B 82 4.869 -21.389 10.597 1.00 24.88 O -ATOM 1692 CB LYS B 82 4.142 -21.433 7.392 1.00 40.41 C -ATOM 1693 CG LYS B 82 3.479 -20.229 6.738 1.00 39.73 C -ATOM 1694 CD LYS B 82 2.160 -20.747 5.755 1.00 66.91 C -ATOM 1695 CE LYS B 82 1.685 -20.767 6.266 1.00 59.33 C -ATOM 1696 NZ LYS B 82 -0.023 -22.087 5.346 1.00 80.12 N -ATOM 1697 N GLY B 83 5.725 -22.942 9.358 1.00 26.18 N -ATOM 1698 CA GLY B 83 5.798 -23.724 10.746 1.00 41.64 C -ATOM 1699 C GLY B 83 6.819 -23.249 11.591 1.00 31.59 C -ATOM 1700 O GLY B 83 6.621 -23.464 12.858 1.00 36.40 O -ATOM 1701 N THR B 84 7.985 -22.864 11.019 1.00 26.72 N -ATOM 1702 CA THR B 84 9.150 -22.242 11.744 1.00 25.47 C -ATOM 1703 C THR B 84 8.609 -21.278 12.796 1.00 33.72 C -ATOM 1704 O THR B 84 8.964 -20.907 13.790 1.00 27.43 O -ATOM 1705 CB THR B 84 10.394 -21.742 11.042 1.00 25.58 C -ATOM 1706 OG1 THR B 84 10.806 -23.108 10.337 1.00 39.04 O -ATOM 1707 CG2 THR B 84 11.362 -21.482 11.789 1.00 30.76 C -ATOM 1708 N PHE B 85 7.740 -20.301 12.125 1.00 23.61 N -ATOM 1709 CA PHE B 85 7.236 -18.963 12.749 1.00 21.59 C -ATOM 1710 C PHE B 85 5.980 -19.056 13.414 1.00 28.51 C -ATOM 1711 O PHE B 85 5.496 -18.006 13.809 1.00 18.85 O -ATOM 1712 CB PHE B 85 7.575 -17.733 11.855 1.00 18.34 C -ATOM 1713 CG PHE B 85 8.914 -17.486 11.587 1.00 13.87 C -ATOM 1714 CD1 PHE B 85 9.583 -17.701 10.358 1.00 16.61 C -ATOM 1715 CD2 PHE B 85 9.616 -17.039 12.693 1.00 18.32 C -ATOM 1716 CE1 PHE B 85 11.009 -17.444 10.305 1.00 27.99 C -ATOM 1717 CE2 PHE B 85 11.013 -16.752 12.253 1.00 21.68 C -ATOM 1718 CZ PHE B 85 11.837 -16.973 11.161 1.00 21.59 C -ATOM 1719 N ALA B 86 5.328 -20.141 13.373 1.00 22.16 N -ATOM 1720 CA ALA B 86 3.899 -20.242 13.948 1.00 23.14 C -ATOM 1721 C ALA B 86 3.715 -19.788 15.246 1.00 20.99 C -ATOM 1722 O ALA B 86 2.881 -18.975 15.595 1.00 20.07 O -ATOM 1723 CB ALA B 86 3.272 -21.660 13.783 1.00 23.69 C -ATOM 1724 N THR B 87 4.501 -20.280 16.157 1.00 14.82 N -ATOM 1725 CA THR B 87 4.271 -19.764 17.443 1.00 18.61 C -ATOM 1726 C THR B 87 4.737 -18.271 17.729 1.00 25.42 C -ATOM 1727 O THR B 87 4.013 -17.569 18.383 1.00 23.63 O -ATOM 1728 CB THR B 87 5.631 -20.439 18.664 1.00 36.27 C -ATOM 1729 OG1 THR B 87 5.010 -21.597 18.659 1.00 56.82 O -ATOM 1730 CG2 THR B 87 4.455 -20.311 20.305 1.00 60.80 C -ATOM 1731 N LEU B 88 5.836 -17.770 16.978 1.00 19.44 N -ATOM 1732 CA LEU B 88 5.984 -16.362 17.087 1.00 17.97 C -ATOM 1733 C LEU B 88 4.882 -15.510 16.526 1.00 11.34 C -ATOM 1734 O LEU B 88 4.682 -14.416 16.964 1.00 17.71 O -ATOM 1735 CB LEU B 88 7.361 -16.058 16.476 1.00 20.20 C -ATOM 1736 CG LEU B 88 8.654 -16.553 17.229 1.00 27.17 C -ATOM 1737 CD1 LEU B 88 9.614 -15.962 16.454 1.00 32.32 C -ATOM 1738 CD2 LEU B 88 8.631 -15.491 18.343 1.00 27.72 C -ATOM 1739 N SER B 89 4.254 -16.087 15.451 1.00 12.58 N -ATOM 1740 CA SER B 89 3.084 -15.313 14.877 1.00 15.21 C -ATOM 1741 C SER B 89 1.999 -14.995 15.898 1.00 14.13 C -ATOM 1742 O SER B 89 1.472 -13.894 16.189 1.00 14.29 O -ATOM 1743 CB SER B 89 2.771 -16.248 13.670 1.00 18.34 C -ATOM 1744 OG SER B 89 1.531 -15.441 13.107 1.00 17.85 O -ATOM 1745 N GLU B 90 1.628 -16.201 16.484 1.00 14.25 N -ATOM 1746 CA GLU B 90 0.931 -16.070 17.617 1.00 20.50 C -ATOM 1747 C GLU B 90 0.876 -15.142 18.820 1.00 13.47 C -ATOM 1748 O GLU B 90 0.179 -14.243 19.122 1.00 16.05 O -ATOM 1749 CB GLU B 90 0.387 -17.706 18.270 1.00 21.76 C -ATOM 1750 CG GLU B 90 0.049 -18.266 17.145 1.00 48.13 C -ATOM 1751 CD GLU B 90 -0.726 -20.095 17.710 1.00 78.64 C -ATOM 1752 OE1 GLU B 90 -1.132 -19.837 18.495 1.00 55.55 O -ATOM 1753 OE2 GLU B 90 0.235 -20.950 17.492 1.00 74.37 O -ATOM 1754 N LEU B 91 2.312 -15.215 19.185 1.00 13.36 N -ATOM 1755 CA LEU B 91 2.718 -14.253 20.128 1.00 14.20 C -ATOM 1756 C LEU B 91 2.527 -12.831 19.767 1.00 8.80 C -ATOM 1757 O LEU B 91 2.160 -11.906 20.481 1.00 10.74 O -ATOM 1758 CB LEU B 91 4.110 -14.807 20.432 1.00 12.00 C -ATOM 1759 CG LEU B 91 4.669 -13.801 21.348 1.00 18.50 C -ATOM 1760 CD1 LEU B 91 4.127 -14.212 22.834 1.00 20.79 C -ATOM 1761 CD2 LEU B 91 5.943 -13.652 21.455 1.00 37.40 C -ATOM 1762 N HIS B 92 3.059 -12.662 18.493 1.00 10.78 N -ATOM 1763 CA HIS B 92 3.032 -11.268 18.253 1.00 11.85 C -ATOM 1764 C HIS B 92 1.536 -10.600 17.895 1.00 11.06 C -ATOM 1765 O HIS B 92 1.291 -9.431 18.158 1.00 13.45 O -ATOM 1766 CB HIS B 92 3.754 -11.078 16.807 1.00 9.95 C -ATOM 1767 CG HIS B 92 5.289 -10.900 17.051 1.00 15.50 C -ATOM 1768 ND1 HIS B 92 6.099 -12.172 17.134 1.00 15.27 N -ATOM 1769 CD2 HIS B 92 6.215 -9.905 16.994 1.00 23.76 C -ATOM 1770 CE1 HIS B 92 7.432 -11.572 17.375 1.00 16.99 C -ATOM 1771 NE2 HIS B 92 7.367 -10.337 17.129 1.00 14.76 N -ATOM 1772 N CYS B 93 0.636 -11.512 17.534 1.00 14.83 N -ATOM 1773 CA CYS B 93 -0.706 -11.057 17.499 1.00 12.23 C -ATOM 1774 C CYS B 93 -1.360 -10.953 18.986 1.00 10.49 C -ATOM 1775 O CYS B 93 -1.843 -9.987 19.222 1.00 18.01 O -ATOM 1776 CB CYS B 93 -1.330 -12.054 16.605 1.00 15.43 C -ATOM 1777 SG CYS B 93 -3.259 -11.741 16.494 1.00 18.37 S -ATOM 1778 N ASP B 94 -1.338 -12.094 19.598 1.00 13.11 N -ATOM 1779 CA ASP B 94 -2.308 -12.076 20.721 1.00 15.32 C -ATOM 1780 C ASP B 94 -1.586 -11.449 21.803 1.00 25.71 C -ATOM 1781 O ASP B 94 -2.319 -10.827 22.800 1.00 21.65 O -ATOM 1782 CB ASP B 94 -2.522 -13.477 21.183 1.00 21.65 C -ATOM 1783 CG ASP B 94 -3.443 -14.553 20.246 1.00 42.42 C -ATOM 1784 OD1 ASP B 94 -3.967 -13.792 19.626 1.00 30.02 O -ATOM 1785 OD2 ASP B 94 -3.094 -15.441 20.443 1.00 43.30 O -ATOM 1786 N LYS B 95 -0.348 -11.361 22.144 1.00 18.55 N -ATOM 1787 CA LYS B 95 0.080 -10.591 23.184 1.00 19.10 C -ATOM 1788 C LYS B 95 0.803 -9.499 23.130 1.00 19.57 C -ATOM 1789 O LYS B 95 0.736 -8.565 23.699 1.00 21.87 O -ATOM 1790 CB LYS B 95 1.151 -11.737 23.890 1.00 25.95 C -ATOM 1791 CG LYS B 95 0.477 -13.054 24.377 1.00 24.86 C -ATOM 1792 CD LYS B 95 -0.659 -12.473 25.407 1.00 36.14 C -ATOM 1793 CE LYS B 95 -1.063 -13.745 26.122 1.00 47.76 C -ATOM 1794 NZ LYS B 95 -2.126 -13.501 26.952 1.00 55.91 N -ATOM 1795 N LEU B 96 1.669 -9.358 21.897 1.00 12.40 N -ATOM 1796 CA LEU B 96 2.264 -8.159 21.581 1.00 11.86 C -ATOM 1797 C LEU B 96 1.626 -7.005 20.824 1.00 15.10 C -ATOM 1798 O LEU B 96 2.002 -5.926 20.849 1.00 17.50 O -ATOM 1799 CB LEU B 96 3.645 -8.491 21.134 1.00 14.08 C -ATOM 1800 CG LEU B 96 4.528 -9.722 21.739 1.00 12.34 C -ATOM 1801 CD1 LEU B 96 5.778 -9.939 20.848 1.00 13.78 C -ATOM 1802 CD2 LEU B 96 4.863 -8.876 23.113 1.00 22.81 C -ATOM 1803 N HIS B 97 0.616 -7.508 20.069 1.00 15.44 N -ATOM 1804 CA HIS B 97 -0.223 -6.510 19.374 1.00 18.15 C -ATOM 1805 C HIS B 97 0.581 -5.736 18.319 1.00 12.24 C -ATOM 1806 O HIS B 97 0.337 -4.532 18.056 1.00 15.82 O -ATOM 1807 CB HIS B 97 -1.053 -5.508 20.203 1.00 17.74 C -ATOM 1808 CG HIS B 97 -1.716 -6.273 21.483 1.00 16.77 C -ATOM 1809 ND1 HIS B 97 -2.602 -7.310 21.250 1.00 19.56 N -ATOM 1810 CD2 HIS B 97 -1.189 -6.197 22.703 1.00 23.33 C -ATOM 1811 CE1 HIS B 97 -2.759 -7.812 22.476 1.00 19.82 C -ATOM 1812 NE2 HIS B 97 -2.056 -7.104 23.341 1.00 20.39 N -ATOM 1813 N VAL B 98 1.359 -6.524 17.506 1.00 13.81 N -ATOM 1814 CA VAL B 98 2.284 -5.763 16.567 1.00 9.22 C -ATOM 1815 C VAL B 98 1.443 -5.905 15.109 1.00 9.86 C -ATOM 1816 O VAL B 98 1.420 -7.012 14.615 1.00 12.90 O -ATOM 1817 CB VAL B 98 3.592 -6.460 16.393 1.00 9.87 C -ATOM 1818 CG1 VAL B 98 4.438 -5.824 15.405 1.00 14.91 C -ATOM 1819 CG2 VAL B 98 4.444 -6.258 17.798 1.00 11.36 C -ATOM 1820 N ASP B 99 1.147 -4.763 14.513 1.00 11.46 N -ATOM 1821 CA ASP B 99 0.360 -4.723 13.272 1.00 9.02 C -ATOM 1822 C ASP B 99 1.555 -5.328 12.375 1.00 15.41 C -ATOM 1823 O ASP B 99 2.744 -4.931 12.235 1.00 10.63 O -ATOM 1824 CB ASP B 99 0.336 -3.327 12.907 1.00 9.79 C -ATOM 1825 CG ASP B 99 -0.231 -3.002 11.431 1.00 10.69 C -ATOM 1826 OD1 ASP B 99 -0.535 -1.748 11.309 1.00 15.04 O -ATOM 1827 OD2 ASP B 99 -0.299 -4.052 10.734 1.00 11.07 O -ATOM 1828 N PRO B 100 1.274 -6.350 11.556 1.00 10.46 N -ATOM 1829 CA PRO B 100 2.264 -7.099 10.669 1.00 11.87 C -ATOM 1830 C PRO B 100 2.744 -6.170 9.522 1.00 13.04 C -ATOM 1831 O PRO B 100 3.883 -6.627 8.995 1.00 13.79 O -ATOM 1832 CB PRO B 100 1.545 -8.233 10.081 1.00 17.03 C -ATOM 1833 CG PRO B 100 0.234 -8.243 10.793 1.00 17.33 C -ATOM 1834 CD PRO B 100 -0.030 -7.028 11.592 1.00 9.97 C -ATOM 1835 N GLU B 101 2.300 -4.973 9.393 1.00 9.66 N -ATOM 1836 CA GLU B 101 2.927 -3.983 8.469 1.00 11.29 C -ATOM 1837 C GLU B 101 4.322 -3.633 8.825 1.00 17.59 C -ATOM 1838 O GLU B 101 5.293 -3.640 8.196 1.00 16.98 O -ATOM 1839 CB GLU B 101 2.178 -2.819 8.156 1.00 18.71 C -ATOM 1840 CG GLU B 101 2.755 -1.760 7.270 1.00 30.25 C -ATOM 1841 CD GLU B 101 2.569 -2.612 5.445 1.00 26.27 C -ATOM 1842 OE1 GLU B 101 1.725 -3.411 5.564 1.00 25.29 O -ATOM 1843 OE2 GLU B 101 3.441 -1.765 5.293 1.00 34.30 O -ATOM 1844 N ASN B 102 4.601 -3.752 10.314 1.00 12.60 N -ATOM 1845 CA ASN B 102 5.969 -3.548 10.721 1.00 9.48 C -ATOM 1846 C ASN B 102 6.861 -4.572 10.309 1.00 8.44 C -ATOM 1847 O ASN B 102 8.118 -4.224 10.106 1.00 13.92 O -ATOM 1848 CB ASN B 102 5.901 -3.665 12.265 1.00 18.27 C -ATOM 1849 CG ASN B 102 5.284 -2.285 12.825 1.00 26.18 C -ATOM 1850 OD1 ASN B 102 5.641 -1.422 12.815 1.00 20.87 O -ATOM 1851 ND2 ASN B 102 4.003 -2.618 13.502 1.00 25.76 N -ATOM 1852 N PHE B 103 6.584 -5.846 10.057 1.00 11.66 N -ATOM 1853 CA PHE B 103 7.332 -6.920 9.605 1.00 11.79 C -ATOM 1854 C PHE B 103 7.931 -6.435 8.177 1.00 19.35 C -ATOM 1855 O PHE B 103 8.997 -6.751 7.762 1.00 16.06 O -ATOM 1856 CB PHE B 103 6.816 -8.253 9.574 1.00 12.75 C -ATOM 1857 CG PHE B 103 6.173 -8.727 10.951 1.00 17.48 C -ATOM 1858 CD1 PHE B 103 6.884 -8.372 12.079 1.00 13.65 C -ATOM 1859 CD2 PHE B 103 5.035 -9.335 10.925 1.00 13.36 C -ATOM 1860 CE1 PHE B 103 6.240 -8.652 13.315 1.00 14.94 C -ATOM 1861 CE2 PHE B 103 4.498 -9.665 12.273 1.00 14.24 C -ATOM 1862 CZ PHE B 103 5.298 -9.364 13.368 1.00 19.61 C -ATOM 1863 N ARG B 104 6.970 -5.873 7.380 1.00 13.60 N -ATOM 1864 CA ARG B 104 7.430 -5.624 6.005 1.00 17.00 C -ATOM 1865 C ARG B 104 8.326 -4.499 5.935 1.00 13.66 C -ATOM 1866 O ARG B 104 9.337 -4.368 5.141 1.00 13.41 O -ATOM 1867 CB ARG B 104 6.018 -5.177 5.223 1.00 18.62 C -ATOM 1868 CG ARG B 104 5.137 -6.280 4.965 1.00 31.60 C -ATOM 1869 CD ARG B 104 3.494 -6.093 4.370 1.00 44.99 C -ATOM 1870 NE ARG B 104 2.810 -7.429 5.065 1.00 53.69 N -ATOM 1871 CZ ARG B 104 1.600 -6.829 3.420 1.00 80.12 C -ATOM 1872 NH1 ARG B 104 0.761 -5.157 3.344 1.00 72.76 N -ATOM 1873 NH2 ARG B 104 1.186 -8.540 2.528 1.00 80.07 N -ATOM 1874 N LEU B 105 8.064 -3.438 6.831 1.00 12.29 N -ATOM 1875 CA LEU B 105 8.899 -2.275 6.982 1.00 11.07 C -ATOM 1876 C LEU B 105 10.327 -2.808 7.482 1.00 13.91 C -ATOM 1877 O LEU B 105 11.317 -2.347 6.887 1.00 14.94 O -ATOM 1878 CB LEU B 105 8.443 -1.409 8.005 1.00 12.50 C -ATOM 1879 CG LEU B 105 7.121 -0.514 7.549 1.00 17.21 C -ATOM 1880 CD1 LEU B 105 6.747 0.236 8.813 1.00 19.52 C -ATOM 1881 CD2 LEU B 105 7.420 0.384 6.353 1.00 25.82 C -ATOM 1882 N LEU B 106 10.302 -3.738 8.415 1.00 16.16 N -ATOM 1883 CA LEU B 106 11.679 -4.227 8.855 1.00 11.19 C -ATOM 1884 C LEU B 106 12.325 -4.914 7.713 1.00 11.49 C -ATOM 1885 O LEU B 106 13.544 -4.734 7.492 1.00 14.59 O -ATOM 1886 CB LEU B 106 11.615 -5.043 10.074 1.00 9.57 C -ATOM 1887 CG LEU B 106 12.904 -5.567 10.740 1.00 14.52 C -ATOM 1888 CD1 LEU B 106 13.738 -4.483 11.015 1.00 20.21 C -ATOM 1889 CD2 LEU B 106 12.609 -6.504 11.567 1.00 25.23 C -ATOM 1890 N GLY B 107 11.728 -5.699 6.854 1.00 8.80 N -ATOM 1891 CA GLY B 107 12.297 -6.476 5.851 1.00 11.35 C -ATOM 1892 C GLY B 107 12.781 -5.426 4.844 1.00 11.83 C -ATOM 1893 O GLY B 107 13.958 -5.700 4.332 1.00 14.42 O -ATOM 1894 N ASN B 108 12.187 -4.243 4.553 1.00 11.55 N -ATOM 1895 CA ASN B 108 12.802 -3.506 3.538 1.00 9.47 C -ATOM 1896 C ASN B 108 14.026 -2.647 4.184 1.00 9.85 C -ATOM 1897 O ASN B 108 14.983 -2.466 3.460 1.00 13.16 O -ATOM 1898 CB ASN B 108 11.824 -2.458 3.182 1.00 16.47 C -ATOM 1899 CG ASN B 108 10.727 -3.234 1.924 1.00 25.36 C -ATOM 1900 OD1 ASN B 108 11.335 -4.320 1.398 1.00 28.00 O -ATOM 1901 ND2 ASN B 108 10.036 -2.270 2.100 1.00 42.45 N -ATOM 1902 N VAL B 109 14.008 -2.327 5.491 1.00 11.97 N -ATOM 1903 CA VAL B 109 15.193 -1.717 6.001 1.00 8.99 C -ATOM 1904 C VAL B 109 16.259 -2.676 6.124 1.00 12.55 C -ATOM 1905 O VAL B 109 17.518 -2.304 5.902 1.00 13.71 O -ATOM 1906 CB VAL B 109 14.853 -1.250 7.488 1.00 15.07 C -ATOM 1907 CG1 VAL B 109 16.100 -0.810 8.069 1.00 19.91 C -ATOM 1908 CG2 VAL B 109 13.852 0.066 7.393 1.00 15.78 C -ATOM 1909 N LEU B 110 16.030 -4.023 6.388 1.00 9.97 N -ATOM 1910 CA LEU B 110 17.059 -5.101 6.357 1.00 9.78 C -ATOM 1911 C LEU B 110 17.764 -5.056 5.040 1.00 13.14 C -ATOM 1912 O LEU B 110 18.980 -5.187 4.895 1.00 11.97 O -ATOM 1913 CB LEU B 110 16.410 -6.369 6.847 1.00 11.11 C -ATOM 1914 CG LEU B 110 17.490 -7.596 6.862 1.00 18.59 C -ATOM 1915 CD1 LEU B 110 18.696 -7.290 7.723 1.00 24.07 C -ATOM 1916 CD2 LEU B 110 17.031 -8.897 7.193 1.00 21.67 C -ATOM 1917 N VAL B 111 17.015 -5.083 3.938 1.00 10.25 N -ATOM 1918 CA VAL B 111 17.517 -5.121 2.535 1.00 8.08 C -ATOM 1919 C VAL B 111 18.459 -3.959 2.465 1.00 10.10 C -ATOM 1920 O VAL B 111 19.605 -3.960 1.822 1.00 14.18 O -ATOM 1921 CB VAL B 111 16.320 -5.216 1.576 1.00 11.95 C -ATOM 1922 CG1 VAL B 111 16.949 -4.942 0.196 1.00 16.64 C -ATOM 1923 CG2 VAL B 111 15.888 -6.643 1.659 1.00 12.92 C -ATOM 1924 N CYS B 112 18.155 -2.685 2.811 1.00 10.01 N -ATOM 1925 CA CYS B 112 18.863 -1.400 2.699 1.00 9.19 C -ATOM 1926 C CYS B 112 20.143 -1.657 3.581 1.00 14.92 C -ATOM 1927 O CYS B 112 21.199 -1.284 3.015 1.00 13.93 O -ATOM 1928 CB CYS B 112 18.369 -0.230 3.207 1.00 15.04 C -ATOM 1929 SG CYS B 112 16.911 0.308 2.042 1.00 18.10 S -ATOM 1930 N VAL B 113 19.969 -2.202 4.651 1.00 9.52 N -ATOM 1931 CA VAL B 113 21.202 -2.512 5.398 1.00 11.92 C -ATOM 1932 C VAL B 113 22.035 -3.532 4.865 1.00 15.57 C -ATOM 1933 O VAL B 113 23.397 -3.138 4.862 1.00 13.38 O -ATOM 1934 CB VAL B 113 20.888 -2.948 6.932 1.00 12.70 C -ATOM 1935 CG1 VAL B 113 22.031 -3.383 7.663 1.00 17.23 C -ATOM 1936 CG2 VAL B 113 20.282 -1.893 7.694 1.00 17.43 C -ATOM 1937 N LEU B 114 21.768 -4.615 4.224 1.00 10.74 N -ATOM 1938 CA LEU B 114 22.632 -5.454 3.485 1.00 10.20 C -ATOM 1939 C LEU B 114 23.346 -4.641 2.455 1.00 10.87 C -ATOM 1940 O LEU B 114 24.522 -5.071 2.156 1.00 12.76 O -ATOM 1941 CB LEU B 114 21.856 -6.600 3.242 1.00 6.84 C -ATOM 1942 CG LEU B 114 21.362 -7.530 4.328 1.00 10.74 C -ATOM 1943 CD1 LEU B 114 20.435 -8.554 3.798 1.00 15.38 C -ATOM 1944 CD2 LEU B 114 22.500 -8.141 5.077 1.00 21.35 C -ATOM 1945 N ALA B 115 22.472 -3.897 1.677 1.00 9.28 N -ATOM 1946 CA ALA B 115 23.134 -3.206 0.546 1.00 9.22 C -ATOM 1947 C ALA B 115 24.284 -2.278 1.091 1.00 9.44 C -ATOM 1948 O ALA B 115 25.320 -2.142 0.446 1.00 12.10 O -ATOM 1949 CB ALA B 115 21.930 -2.539 -0.036 1.00 12.15 C -ATOM 1950 N HIS B 116 23.975 -1.612 2.171 1.00 13.11 N -ATOM 1951 CA HIS B 116 25.023 -0.593 2.641 1.00 12.81 C -ATOM 1952 C HIS B 116 26.176 -1.395 3.061 1.00 18.85 C -ATOM 1953 O HIS B 116 27.357 -0.986 2.878 1.00 16.05 O -ATOM 1954 CB HIS B 116 24.442 0.070 3.767 1.00 17.43 C -ATOM 1955 CG HIS B 116 25.164 1.158 4.279 1.00 27.80 C -ATOM 1956 ND1 HIS B 116 25.567 1.157 5.736 1.00 27.30 N -ATOM 1957 CD2 HIS B 116 25.793 2.195 3.793 1.00 25.62 C -ATOM 1958 CE1 HIS B 116 26.226 2.480 5.818 1.00 29.22 C -ATOM 1959 NE2 HIS B 116 26.570 2.986 4.660 1.00 26.05 N -ATOM 1960 N HIS B 117 26.066 -2.490 3.850 1.00 11.35 N -ATOM 1961 CA HIS B 117 27.064 -3.366 4.194 1.00 18.75 C -ATOM 1962 C HIS B 117 27.881 -3.985 3.242 1.00 20.53 C -ATOM 1963 O HIS B 117 29.104 -4.114 3.403 1.00 17.07 O -ATOM 1964 CB HIS B 117 26.621 -4.637 5.175 1.00 19.57 C -ATOM 1965 CG HIS B 117 27.096 -4.621 6.444 1.00 39.90 C -ATOM 1966 ND1 HIS B 117 26.039 -3.036 6.824 1.00 47.73 N -ATOM 1967 CD2 HIS B 117 28.146 -5.329 7.512 1.00 38.82 C -ATOM 1968 CE1 HIS B 117 26.295 -2.928 8.550 1.00 27.38 C -ATOM 1969 NE2 HIS B 117 26.763 -4.335 8.924 1.00 51.83 N -ATOM 1970 N PHE B 118 27.367 -4.628 2.104 1.00 13.44 N -ATOM 1971 CA PHE B 118 27.888 -5.419 1.096 1.00 13.47 C -ATOM 1972 C PHE B 118 28.280 -4.574 -0.126 1.00 14.52 C -ATOM 1973 O PHE B 118 29.082 -5.219 -0.874 1.00 15.85 O -ATOM 1974 CB PHE B 118 27.174 -6.618 0.947 1.00 14.99 C -ATOM 1975 CG PHE B 118 27.310 -7.470 1.980 1.00 22.65 C -ATOM 1976 CD1 PHE B 118 26.224 -7.666 2.855 1.00 28.61 C -ATOM 1977 CD2 PHE B 118 28.549 -8.159 2.601 1.00 34.26 C -ATOM 1978 CE1 PHE B 118 26.242 -8.675 3.981 1.00 29.50 C -ATOM 1979 CE2 PHE B 118 28.351 -9.080 3.277 1.00 36.60 C -ATOM 1980 CZ PHE B 118 27.627 -9.130 4.417 1.00 30.15 C -ATOM 1981 N GLY B 119 27.701 -3.412 -0.335 1.00 13.81 N -ATOM 1982 CA GLY B 119 28.107 -2.567 -1.533 1.00 14.28 C -ATOM 1983 C GLY B 119 27.814 -3.353 -2.686 1.00 17.07 C -ATOM 1984 O GLY B 119 26.808 -4.212 -2.888 1.00 16.48 O -ATOM 1985 N LYS B 120 28.740 -3.472 -3.465 1.00 19.17 N -ATOM 1986 CA LYS B 120 28.535 -4.059 -4.848 1.00 27.00 C -ATOM 1987 C LYS B 120 28.486 -5.640 -4.886 1.00 25.94 C -ATOM 1988 O LYS B 120 27.868 -6.039 -5.935 1.00 20.66 O -ATOM 1989 CB LYS B 120 29.863 -3.838 -5.852 1.00 31.85 C -ATOM 1990 CG LYS B 120 30.960 -4.510 -5.562 1.00 36.58 C -ATOM 1991 CD LYS B 120 32.161 -4.170 -6.625 1.00 49.76 C -ATOM 1992 CE LYS B 120 33.201 -5.292 -5.966 1.00 55.47 C -ATOM 1993 NZ LYS B 120 34.292 -5.686 -6.589 1.00 71.03 N -ATOM 1994 N GLU B 121 28.720 -6.302 -3.902 1.00 20.26 N -ATOM 1995 CA GLU B 121 28.393 -7.556 -3.778 1.00 15.17 C -ATOM 1996 C GLU B 121 26.786 -7.871 -3.622 1.00 13.63 C -ATOM 1997 O GLU B 121 26.362 -9.055 -3.923 1.00 17.16 O -ATOM 1998 CB GLU B 121 29.233 -8.318 -2.533 1.00 29.40 C -ATOM 1999 CG GLU B 121 29.541 -9.342 -2.700 1.00 50.25 C -ATOM 2000 CD GLU B 121 30.241 -9.882 -0.830 1.00 42.74 C -ATOM 2001 OE1 GLU B 121 29.786 -11.667 -1.141 1.00 47.83 O -ATOM 2002 OE2 GLU B 121 31.217 -9.425 -1.168 1.00 34.52 O -ATOM 2003 N PHE B 122 26.054 -6.831 -3.241 1.00 14.63 N -ATOM 2004 CA PHE B 122 24.581 -7.077 -3.075 1.00 15.34 C -ATOM 2005 C PHE B 122 24.015 -6.737 -4.532 1.00 13.61 C -ATOM 2006 O PHE B 122 23.478 -5.701 -4.760 1.00 14.29 O -ATOM 2007 CB PHE B 122 24.133 -6.005 -1.987 1.00 12.07 C -ATOM 2008 CG PHE B 122 22.750 -6.466 -1.525 1.00 11.02 C -ATOM 2009 CD1 PHE B 122 22.540 -7.652 -0.894 1.00 16.65 C -ATOM 2010 CD2 PHE B 122 21.790 -5.593 -1.747 1.00 10.83 C -ATOM 2011 CE1 PHE B 122 21.288 -8.069 -0.329 1.00 13.73 C -ATOM 2012 CE2 PHE B 122 20.427 -5.937 -1.325 1.00 12.97 C -ATOM 2013 CZ PHE B 122 20.322 -7.247 -0.672 1.00 16.05 C -ATOM 2014 N THR B 123 24.216 -7.664 -5.332 1.00 18.07 N -ATOM 2015 CA THR B 123 23.866 -7.444 -6.796 1.00 21.03 C -ATOM 2016 C THR B 123 22.176 -7.347 -6.888 1.00 27.18 C -ATOM 2017 O THR B 123 21.678 -7.911 -6.078 1.00 14.31 O -ATOM 2018 CB THR B 123 24.352 -8.535 -7.622 1.00 19.82 C -ATOM 2019 OG1 THR B 123 24.030 -9.746 -7.305 1.00 17.47 O -ATOM 2020 CG2 THR B 123 25.945 -8.568 -7.681 1.00 22.67 C -ATOM 2021 N PRO B 124 21.821 -7.033 -7.981 1.00 19.47 N -ATOM 2022 CA PRO B 124 20.309 -7.060 -8.306 1.00 20.19 C -ATOM 2023 C PRO B 124 19.874 -8.457 -8.199 1.00 20.69 C -ATOM 2024 O PRO B 124 18.738 -8.543 -7.455 1.00 13.34 O -ATOM 2025 CB PRO B 124 20.074 -6.480 -9.678 1.00 17.09 C -ATOM 2026 CG PRO B 124 21.308 -5.510 -9.842 1.00 18.87 C -ATOM 2027 CD PRO B 124 22.649 -6.190 -9.202 1.00 24.42 C -ATOM 2028 N PRO B 125 20.354 -9.489 -8.576 1.00 16.20 N -ATOM 2029 CA PRO B 125 19.952 -10.892 -8.433 1.00 16.84 C -ATOM 2030 C PRO B 125 19.925 -11.341 -6.992 1.00 14.92 C -ATOM 2031 O PRO B 125 18.950 -11.983 -6.530 1.00 16.05 O -ATOM 2032 CB PRO B 125 20.675 -11.924 -9.198 1.00 19.48 C -ATOM 2033 CG PRO B 125 21.240 -11.056 -10.143 1.00 21.56 C -ATOM 2034 CD PRO B 125 21.611 -9.723 -9.654 1.00 25.73 C -ATOM 2035 N VAL B 126 20.904 -10.923 -6.329 1.00 13.83 N -ATOM 2036 CA VAL B 126 20.919 -11.183 -4.904 1.00 19.80 C -ATOM 2037 C VAL B 126 20.061 -10.295 -4.143 1.00 14.89 C -ATOM 2038 O VAL B 126 19.229 -10.946 -3.203 1.00 13.92 O -ATOM 2039 CB VAL B 126 22.424 -10.769 -4.382 1.00 19.55 C -ATOM 2040 CG1 VAL B 126 22.408 -11.156 -2.912 1.00 21.55 C -ATOM 2041 CG2 VAL B 126 23.366 -11.841 -4.809 1.00 27.82 C -ATOM 2042 N GLN B 127 19.711 -9.155 -4.321 1.00 13.64 N -ATOM 2043 CA GLN B 127 18.607 -8.382 -3.880 1.00 9.72 C -ATOM 2044 C GLN B 127 17.397 -9.130 -3.899 1.00 16.14 C -ATOM 2045 O GLN B 127 16.431 -9.272 -3.189 1.00 12.24 O -ATOM 2046 CB GLN B 127 18.574 -6.951 -4.292 1.00 13.15 C -ATOM 2047 CG GLN B 127 17.258 -6.340 -3.818 1.00 13.42 C -ATOM 2048 CD GLN B 127 17.180 -5.056 -4.465 1.00 16.28 C -ATOM 2049 OE1 GLN B 127 17.979 -4.488 -5.247 1.00 16.20 O -ATOM 2050 NE2 GLN B 127 16.107 -4.400 -4.118 1.00 19.47 N -ATOM 2051 N ALA B 128 17.014 -9.478 -5.230 1.00 15.15 N -ATOM 2052 CA ALA B 128 15.847 -10.225 -5.543 1.00 15.02 C -ATOM 2053 C ALA B 128 15.496 -11.450 -4.737 1.00 11.97 C -ATOM 2054 O ALA B 128 14.413 -11.642 -4.228 1.00 16.35 O -ATOM 2055 CB ALA B 128 15.759 -10.403 -7.092 1.00 17.08 C -ATOM 2056 N ALA B 129 16.462 -12.287 -4.461 1.00 13.66 N -ATOM 2057 CA ALA B 129 16.408 -13.427 -3.647 1.00 13.76 C -ATOM 2058 C ALA B 129 16.208 -12.966 -2.160 1.00 10.22 C -ATOM 2059 O ALA B 129 15.192 -13.627 -1.584 1.00 10.46 O -ATOM 2060 CB ALA B 129 17.632 -14.165 -3.702 1.00 13.23 C -ATOM 2061 N TYR B 130 16.867 -11.953 -1.693 1.00 10.66 N -ATOM 2062 CA TYR B 130 16.462 -11.629 -0.331 1.00 13.05 C -ATOM 2063 C TYR B 130 15.102 -10.929 -0.163 1.00 11.70 C -ATOM 2064 O TYR B 130 14.473 -11.012 0.813 1.00 11.83 O -ATOM 2065 CB TYR B 130 17.543 -10.575 0.161 1.00 11.97 C -ATOM 2066 CG TYR B 130 18.623 -11.287 0.924 1.00 13.90 C -ATOM 2067 CD1 TYR B 130 18.650 -11.526 2.272 1.00 15.61 C -ATOM 2068 CD2 TYR B 130 19.782 -11.574 0.237 1.00 14.18 C -ATOM 2069 CE1 TYR B 130 19.630 -12.272 2.811 1.00 19.97 C -ATOM 2070 CE2 TYR B 130 20.865 -12.543 0.889 1.00 19.65 C -ATOM 2071 CZ TYR B 130 20.770 -12.571 2.260 1.00 22.28 C -ATOM 2072 OH TYR B 130 21.731 -13.339 2.902 1.00 21.52 O -ATOM 2073 N GLN B 131 14.606 -10.236 -1.202 1.00 12.03 N -ATOM 2074 CA GLN B 131 13.282 -9.830 -1.214 1.00 12.03 C -ATOM 2075 C GLN B 131 12.216 -10.851 -1.125 1.00 12.76 C -ATOM 2076 O GLN B 131 11.369 -10.664 -0.189 1.00 15.09 O -ATOM 2077 CB GLN B 131 12.944 -9.078 -2.464 1.00 14.85 C -ATOM 2078 CG GLN B 131 13.735 -7.716 -2.449 1.00 19.57 C -ATOM 2079 CD GLN B 131 13.251 -6.548 -1.638 1.00 22.82 C -ATOM 2080 OE1 GLN B 131 13.981 -5.553 -1.833 1.00 18.44 O -ATOM 2081 NE2 GLN B 131 12.251 -6.415 -0.990 1.00 16.43 N -ATOM 2082 N LYS B 132 12.503 -11.991 -1.746 1.00 12.50 N -ATOM 2083 CA LYS B 132 11.644 -13.098 -1.708 1.00 14.23 C -ATOM 2084 C LYS B 132 11.592 -13.603 -0.224 1.00 17.46 C -ATOM 2085 O LYS B 132 10.599 -13.851 0.497 1.00 14.87 O -ATOM 2086 CB LYS B 132 11.937 -14.147 -2.452 1.00 19.74 C -ATOM 2087 CG LYS B 132 11.561 -13.879 -3.966 1.00 26.28 C -ATOM 2088 CD LYS B 132 11.989 -15.031 -4.739 1.00 31.58 C -ATOM 2089 CE LYS B 132 11.660 -14.274 -6.180 1.00 32.98 C -ATOM 2090 NZ LYS B 132 12.119 -15.998 -6.779 1.00 37.48 N -ATOM 2091 N VAL B 133 12.856 -13.702 0.483 1.00 17.22 N -ATOM 2092 CA VAL B 133 13.038 -14.205 1.805 1.00 11.45 C -ATOM 2093 C VAL B 133 12.401 -13.319 2.840 1.00 11.90 C -ATOM 2094 O VAL B 133 11.556 -13.799 3.731 1.00 13.71 O -ATOM 2095 CB VAL B 133 14.459 -14.401 2.160 1.00 16.41 C -ATOM 2096 CG1 VAL B 133 14.632 -14.683 3.511 1.00 36.18 C -ATOM 2097 CG2 VAL B 133 15.014 -15.541 1.250 1.00 15.51 C -ATOM 2098 N VAL B 134 12.512 -11.981 2.749 1.00 13.21 N -ATOM 2099 CA VAL B 134 12.091 -11.081 3.574 1.00 12.26 C -ATOM 2100 C VAL B 134 10.632 -11.128 3.483 1.00 16.19 C -ATOM 2101 O VAL B 134 9.763 -10.888 4.517 1.00 17.40 O -ATOM 2102 CB VAL B 134 12.356 -9.643 3.780 1.00 11.96 C -ATOM 2103 CG1 VAL B 134 13.841 -9.777 4.082 1.00 18.38 C -ATOM 2104 CG2 VAL B 134 12.314 -8.873 2.475 1.00 14.78 C -ATOM 2105 N ALA B 135 9.938 -11.113 2.262 1.00 13.32 N -ATOM 2106 CA ALA B 135 8.505 -11.237 2.119 1.00 21.37 C -ATOM 2107 C ALA B 135 7.942 -12.494 2.777 1.00 17.09 C -ATOM 2108 O ALA B 135 6.829 -12.512 3.348 1.00 17.43 O -ATOM 2109 CB ALA B 135 8.135 -10.953 0.769 1.00 28.77 C -ATOM 2110 N GLY B 136 8.572 -13.635 2.636 1.00 18.26 N -ATOM 2111 CA GLY B 136 8.219 -15.058 3.189 1.00 19.82 C -ATOM 2112 C GLY B 136 8.146 -14.912 4.633 1.00 16.67 C -ATOM 2113 O GLY B 136 7.260 -15.405 5.231 1.00 15.34 O -ATOM 2114 N VAL B 137 9.300 -14.354 5.275 1.00 19.06 N -ATOM 2115 CA VAL B 137 9.275 -14.229 6.676 1.00 13.40 C -ATOM 2116 C VAL B 137 8.222 -13.320 7.172 1.00 14.98 C -ATOM 2117 O VAL B 137 7.448 -13.726 8.127 1.00 15.32 O -ATOM 2118 CB VAL B 137 10.681 -13.683 7.141 1.00 12.05 C -ATOM 2119 CG1 VAL B 137 10.587 -13.517 8.589 1.00 24.37 C -ATOM 2120 CG2 VAL B 137 11.663 -14.723 6.701 1.00 11.44 C -ATOM 2121 N ALA B 138 7.830 -12.223 6.567 1.00 14.63 N -ATOM 2122 CA ALA B 138 6.739 -11.343 6.960 1.00 14.97 C -ATOM 2123 C ALA B 138 5.477 -12.035 7.025 1.00 14.00 C -ATOM 2124 O ALA B 138 4.520 -11.965 7.766 1.00 15.18 O -ATOM 2125 CB ALA B 138 6.733 -10.129 6.135 1.00 21.60 C -ATOM 2126 N ASN B 139 5.257 -12.632 5.801 1.00 14.76 N -ATOM 2127 CA ASN B 139 3.965 -13.443 5.693 1.00 19.56 C -ATOM 2128 C ASN B 139 3.788 -14.741 6.508 1.00 16.64 C -ATOM 2129 O ASN B 139 2.773 -14.813 7.122 1.00 15.66 O -ATOM 2130 CB ASN B 139 3.915 -14.281 4.273 1.00 32.30 C -ATOM 2131 CG ASN B 139 3.642 -13.817 3.893 1.00 58.46 C -ATOM 2132 OD1 ASN B 139 3.350 -12.337 3.410 1.00 49.38 O -ATOM 2133 ND2 ASN B 139 4.138 -13.358 1.997 1.00 59.02 N -ATOM 2134 N ALA B 140 4.975 -15.279 6.996 1.00 12.53 N -ATOM 2135 CA ALA B 140 4.880 -16.341 7.880 1.00 19.39 C -ATOM 2136 C ALA B 140 4.686 -15.725 9.225 1.00 15.37 C -ATOM 2137 O ALA B 140 3.890 -16.337 10.107 1.00 15.92 O -ATOM 2138 CB ALA B 140 6.298 -17.186 7.962 1.00 22.20 C -ATOM 2139 N LEU B 141 5.135 -14.663 9.697 1.00 12.47 N -ATOM 2140 CA LEU B 141 4.897 -13.957 10.913 1.00 15.63 C -ATOM 2141 C LEU B 141 3.480 -13.697 11.034 1.00 21.66 C -ATOM 2142 O LEU B 141 2.905 -13.294 12.092 1.00 17.40 O -ATOM 2143 CB LEU B 141 5.926 -12.962 11.275 1.00 15.12 C -ATOM 2144 CG LEU B 141 7.158 -13.407 11.868 1.00 17.02 C -ATOM 2145 CD1 LEU B 141 8.083 -12.226 12.076 1.00 19.94 C -ATOM 2146 CD2 LEU B 141 7.122 -13.935 13.238 1.00 21.74 C -ATOM 2147 N ALA B 142 2.836 -13.244 9.876 1.00 12.86 N -ATOM 2148 CA ALA B 142 1.608 -12.628 9.849 1.00 14.61 C -ATOM 2149 C ALA B 142 0.405 -13.995 9.823 1.00 20.31 C -ATOM 2150 O ALA B 142 -0.813 -13.424 10.022 1.00 18.06 O -ATOM 2151 CB ALA B 142 1.282 -11.676 8.702 1.00 21.40 C -ATOM 2152 N HIS B 143 0.842 -15.030 9.582 1.00 17.95 N -ATOM 2153 CA HIS B 143 0.024 -16.256 9.074 1.00 26.37 C -ATOM 2154 C HIS B 143 -1.200 -16.456 10.329 1.00 19.76 C -ATOM 2155 O HIS B 143 -2.306 -16.886 9.956 1.00 21.59 O -ATOM 2156 CB HIS B 143 0.773 -17.382 8.911 1.00 35.96 C -ATOM 2157 CG HIS B 143 -0.236 -18.629 8.237 1.00 57.59 C -ATOM 2158 ND1 HIS B 143 0.057 -19.594 9.608 1.00 48.44 N -ATOM 2159 CD2 HIS B 143 -0.841 -18.281 7.293 1.00 54.87 C -ATOM 2160 CE1 HIS B 143 -0.983 -20.316 8.077 1.00 74.03 C -ATOM 2161 NE2 HIS B 143 -1.640 -19.381 7.013 1.00 57.99 N -ATOM 2162 N LYS B 144 -0.804 -16.302 11.559 1.00 18.69 N -ATOM 2163 CA LYS B 144 -1.735 -16.737 12.588 1.00 14.86 C -ATOM 2164 C LYS B 144 -2.396 -15.617 12.962 1.00 16.55 C -ATOM 2165 O LYS B 144 -3.129 -15.705 14.113 1.00 18.03 O -ATOM 2166 CB LYS B 144 -0.819 -17.365 13.621 1.00 17.13 C -ATOM 2167 CG LYS B 144 -0.392 -18.897 13.123 1.00 20.99 C -ATOM 2168 CD LYS B 144 -1.238 -19.970 13.316 1.00 34.56 C -ATOM 2169 CE LYS B 144 -2.035 -21.775 13.683 1.00 62.41 C -ATOM 2170 NZ LYS B 144 -0.955 -22.424 15.226 1.00 62.40 N -ATOM 2171 N TYR B 145 -2.408 -14.424 12.668 1.00 19.33 N -ATOM 2172 CA TYR B 145 -3.111 -13.193 12.851 1.00 25.80 C -ATOM 2173 C TYR B 145 -4.833 -13.485 12.942 1.00 37.10 C -ATOM 2174 O TYR B 145 -4.989 -14.273 11.858 1.00 25.59 O -ATOM 2175 CB TYR B 145 -2.815 -11.990 12.502 1.00 20.19 C -ATOM 2176 CG TYR B 145 -1.513 -11.202 13.062 1.00 16.11 C -ATOM 2177 CD1 TYR B 145 -1.713 -10.043 13.732 1.00 13.84 C -ATOM 2178 CD2 TYR B 145 -0.444 -12.052 12.964 1.00 19.35 C -ATOM 2179 CE1 TYR B 145 -0.716 -9.470 14.306 1.00 14.00 C -ATOM 2180 CE2 TYR B 145 0.824 -11.431 13.760 1.00 16.15 C -ATOM 2181 CZ TYR B 145 0.705 -10.123 14.396 1.00 11.23 C -ATOM 2182 OH TYR B 145 1.824 -9.505 14.779 1.00 11.07 O -ATOM 2183 N HIS B 146 -5.455 -13.156 13.610 1.00 22.40 N -ATOM 2184 CA HIS B 146 -7.082 -13.260 13.817 1.00 24.36 C -ATOM 2185 C HIS B 146 -7.642 -12.243 14.547 1.00 19.29 C -ATOM 2186 O HIS B 146 -6.896 -11.423 15.229 1.00 20.20 O -ATOM 2187 CB HIS B 146 -7.319 -14.676 14.251 1.00 17.91 C -ATOM 2188 CG HIS B 146 -7.349 -14.408 16.278 1.00 30.29 C -ATOM 2189 ND1 HIS B 146 -7.504 -15.329 16.577 1.00 56.02 N -ATOM 2190 CD2 HIS B 146 -5.754 -14.700 16.400 1.00 32.02 C -ATOM 2191 CE1 HIS B 146 -6.763 -15.571 18.243 1.00 45.40 C -ATOM 2192 NE2 HIS B 146 -6.023 -14.569 17.782 1.00 35.25 N -ATOM 2193 OXT HIS B 146 -8.867 -12.118 14.478 1.00 28.98 O -TER 2194 HIS B 146 -ATOM 2195 N VAL C 1 -6.932 15.801 -4.736 1.00 53.78 N -ATOM 2196 CA VAL C 1 -6.986 18.132 -4.726 1.00 39.83 C -ATOM 2197 C VAL C 1 -8.725 18.013 -5.289 1.00 29.73 C -ATOM 2198 O VAL C 1 -9.322 17.317 -6.202 1.00 31.20 O -ATOM 2199 CB VAL C 1 -6.406 17.702 -5.747 1.00 52.94 C -ATOM 2200 CG1 VAL C 1 -7.045 19.788 -6.149 1.00 47.73 C -ATOM 2201 CG2 VAL C 1 -5.138 19.765 -5.197 1.00 67.01 C -ATOM 2202 N LEU C 2 -9.481 18.489 -4.357 1.00 33.50 N -ATOM 2203 CA LEU C 2 -10.829 18.318 -4.244 1.00 35.54 C -ATOM 2204 C LEU C 2 -11.593 19.461 -5.392 1.00 25.83 C -ATOM 2205 O LEU C 2 -11.224 20.587 -4.763 1.00 37.30 O -ATOM 2206 CB LEU C 2 -11.320 18.570 -2.993 1.00 38.49 C -ATOM 2207 CG LEU C 2 -11.368 17.191 -2.068 1.00 34.89 C -ATOM 2208 CD1 LEU C 2 -11.559 17.406 -0.855 1.00 40.00 C -ATOM 2209 CD2 LEU C 2 -11.556 16.072 -2.571 1.00 36.30 C -ATOM 2210 N SER C 3 -12.051 19.126 -6.445 1.00 20.82 N -ATOM 2211 CA SER C 3 -12.764 20.102 -7.265 1.00 16.99 C -ATOM 2212 C SER C 3 -13.851 20.641 -6.492 1.00 19.86 C -ATOM 2213 O SER C 3 -14.562 20.118 -5.605 1.00 23.30 O -ATOM 2214 CB SER C 3 -12.915 19.412 -8.479 1.00 21.69 C -ATOM 2215 OG SER C 3 -14.045 18.617 -8.438 1.00 24.96 O -ATOM 2216 N PRO C 4 -14.614 21.747 -7.040 1.00 27.73 N -ATOM 2217 CA PRO C 4 -15.686 22.248 -6.606 1.00 18.30 C -ATOM 2218 C PRO C 4 -16.940 21.185 -6.683 1.00 21.79 C -ATOM 2219 O PRO C 4 -17.669 21.118 -5.776 1.00 30.78 O -ATOM 2220 CB PRO C 4 -16.024 23.555 -7.534 1.00 35.17 C -ATOM 2221 CG PRO C 4 -14.548 23.940 -7.997 1.00 39.10 C -ATOM 2222 CD PRO C 4 -13.753 22.599 -7.931 1.00 33.69 C -ATOM 2223 N ALA C 5 -16.700 20.569 -7.707 1.00 20.53 N -ATOM 2224 CA ALA C 5 -17.694 19.448 -7.877 1.00 15.17 C -ATOM 2225 C ALA C 5 -17.668 18.427 -6.566 1.00 17.36 C -ATOM 2226 O ALA C 5 -18.567 17.818 -6.161 1.00 18.86 O -ATOM 2227 CB ALA C 5 -17.845 18.678 -9.144 1.00 14.70 C -ATOM 2228 N ASP C 6 -16.408 17.997 -6.530 1.00 17.28 N -ATOM 2229 CA ASP C 6 -16.090 17.056 -5.440 1.00 13.65 C -ATOM 2230 C ASP C 6 -16.737 17.558 -4.126 1.00 16.19 C -ATOM 2231 O ASP C 6 -17.234 16.746 -3.292 1.00 18.77 O -ATOM 2232 CB ASP C 6 -14.589 16.808 -5.234 1.00 14.90 C -ATOM 2233 CG ASP C 6 -14.039 15.955 -6.391 1.00 15.46 C -ATOM 2234 OD1 ASP C 6 -14.772 14.926 -6.958 1.00 20.59 O -ATOM 2235 OD2 ASP C 6 -12.866 16.168 -6.605 1.00 19.80 O -ATOM 2236 N LYS C 7 -16.400 18.816 -3.902 1.00 17.95 N -ATOM 2237 CA LYS C 7 -17.103 19.561 -2.483 1.00 25.53 C -ATOM 2238 C LYS C 7 -18.248 19.426 -2.208 1.00 19.12 C -ATOM 2239 O LYS C 7 -18.931 19.046 -1.371 1.00 19.71 O -ATOM 2240 CB LYS C 7 -16.318 20.793 -2.391 1.00 27.50 C -ATOM 2241 CG LYS C 7 -14.901 20.741 -2.614 1.00 53.71 C -ATOM 2242 CD LYS C 7 -13.993 22.186 -1.677 1.00 60.72 C -ATOM 2243 CE LYS C 7 -13.186 22.490 -2.528 1.00 63.74 C -ATOM 2244 NZ LYS C 7 -12.305 23.225 -2.858 1.00 80.12 N -ATOM 2245 N THR C 8 -18.940 19.776 -3.501 1.00 18.59 N -ATOM 2246 CA THR C 8 -20.439 19.567 -3.523 1.00 17.68 C -ATOM 2247 C THR C 8 -21.010 18.410 -3.219 1.00 15.92 C -ATOM 2248 O THR C 8 -21.956 18.189 -2.497 1.00 18.11 O -ATOM 2249 CB THR C 8 -21.005 20.281 -5.121 1.00 18.41 C -ATOM 2250 OG1 THR C 8 -20.596 21.570 -4.936 1.00 22.00 O -ATOM 2251 CG2 THR C 8 -22.332 20.382 -5.020 1.00 19.72 C -ATOM 2252 N ASN C 9 -20.389 17.337 -3.881 1.00 14.52 N -ATOM 2253 CA ASN C 9 -20.679 15.854 -3.720 1.00 11.76 C -ATOM 2254 C ASN C 9 -20.524 15.368 -2.372 1.00 13.43 C -ATOM 2255 O ASN C 9 -21.452 14.760 -1.788 1.00 14.77 O -ATOM 2256 CB ASN C 9 -19.952 14.978 -4.802 1.00 15.52 C -ATOM 2257 CG ASN C 9 -20.502 14.902 -6.224 1.00 21.23 C -ATOM 2258 OD1 ASN C 9 -21.551 15.460 -6.366 1.00 17.78 O -ATOM 2259 ND2 ASN C 9 -19.655 14.764 -7.036 1.00 16.93 N -ATOM 2260 N VAL C 10 -19.456 15.819 -1.845 1.00 15.37 N -ATOM 2261 CA VAL C 10 -19.214 15.430 -0.511 1.00 15.09 C -ATOM 2262 C VAL C 10 -20.248 16.151 0.791 1.00 19.82 C -ATOM 2263 O VAL C 10 -20.653 15.344 1.499 1.00 21.55 O -ATOM 2264 CB VAL C 10 -17.776 15.740 -0.056 1.00 23.83 C -ATOM 2265 CG1 VAL C 10 -17.369 15.319 1.491 1.00 26.38 C -ATOM 2266 CG2 VAL C 10 -16.835 14.843 -0.837 1.00 22.96 C -ATOM 2267 N LYS C 11 -20.423 17.395 0.515 1.00 19.06 N -ATOM 2268 CA LYS C 11 -21.545 18.040 1.267 1.00 21.27 C -ATOM 2269 C LYS C 11 -22.705 17.621 1.194 1.00 24.36 C -ATOM 2270 O LYS C 11 -23.497 17.219 2.050 1.00 26.88 O -ATOM 2271 CB LYS C 11 -21.200 19.455 1.180 1.00 24.11 C -ATOM 2272 CG LYS C 11 -19.982 20.187 1.471 1.00 39.96 C -ATOM 2273 CD LYS C 11 -20.184 21.708 1.326 1.00 36.60 C -ATOM 2274 CE LYS C 11 -19.119 22.424 1.599 1.00 40.99 C -ATOM 2275 NZ LYS C 11 -18.303 23.379 0.156 1.00 57.68 N -ATOM 2276 N ALA C 12 -23.071 17.255 -0.098 1.00 26.89 N -ATOM 2277 CA ALA C 12 -24.190 16.574 -0.166 1.00 22.80 C -ATOM 2278 C ALA C 12 -24.709 15.466 0.479 1.00 22.96 C -ATOM 2279 O ALA C 12 -25.641 14.894 1.303 1.00 25.17 O -ATOM 2280 CB ALA C 12 -24.758 16.354 -1.436 1.00 30.68 C -ATOM 2281 N ALA C 13 -23.698 14.326 0.213 1.00 19.81 N -ATOM 2282 CA ALA C 13 -23.581 12.980 0.775 1.00 20.52 C -ATOM 2283 C ALA C 13 -23.620 13.074 2.219 1.00 17.10 C -ATOM 2284 O ALA C 13 -24.459 12.346 2.958 1.00 22.70 O -ATOM 2285 CB ALA C 13 -22.559 12.176 0.137 1.00 20.00 C -ATOM 2286 N TRP C 14 -22.646 13.784 2.878 1.00 18.93 N -ATOM 2287 CA TRP C 14 -22.430 13.732 4.346 1.00 19.61 C -ATOM 2288 C TRP C 14 -23.567 14.473 4.894 1.00 29.50 C -ATOM 2289 O TRP C 14 -24.277 14.100 6.022 1.00 22.89 O -ATOM 2290 CB TRP C 14 -21.334 14.670 4.695 1.00 20.94 C -ATOM 2291 CG TRP C 14 -20.803 14.092 5.924 1.00 20.44 C -ATOM 2292 CD1 TRP C 14 -21.097 15.028 7.151 1.00 25.06 C -ATOM 2293 CD2 TRP C 14 -20.135 12.848 6.216 1.00 19.23 C -ATOM 2294 NE1 TRP C 14 -20.337 14.117 8.027 1.00 26.03 N -ATOM 2295 CE2 TRP C 14 -19.941 12.969 7.773 1.00 27.20 C -ATOM 2296 CE3 TRP C 14 -19.861 11.878 5.555 1.00 24.26 C -ATOM 2297 CZ2 TRP C 14 -19.510 11.822 8.284 1.00 29.42 C -ATOM 2298 CZ3 TRP C 14 -19.277 10.605 6.015 1.00 27.47 C -ATOM 2299 CH2 TRP C 14 -19.230 10.798 7.728 1.00 31.11 C -ATOM 2300 N GLY C 15 -24.359 15.298 4.516 1.00 39.26 N -ATOM 2301 CA GLY C 15 -25.631 16.086 4.525 1.00 27.60 C -ATOM 2302 C GLY C 15 -26.650 15.043 4.748 1.00 35.88 C -ATOM 2303 O GLY C 15 -27.292 14.929 6.180 1.00 44.35 O -ATOM 2304 N LYS C 16 -26.927 14.192 4.125 1.00 34.61 N -ATOM 2305 CA LYS C 16 -27.870 13.141 3.632 1.00 36.98 C -ATOM 2306 C LYS C 16 -27.538 12.020 5.023 1.00 26.09 C -ATOM 2307 O LYS C 16 -28.345 11.313 5.635 1.00 33.01 O -ATOM 2308 CB LYS C 16 -28.251 12.406 2.440 1.00 27.30 C -ATOM 2309 CG LYS C 16 -30.036 12.836 1.831 1.00 50.84 C -ATOM 2310 CD LYS C 16 -30.158 11.081 2.262 1.00 68.28 C -ATOM 2311 CE LYS C 16 -32.371 10.866 2.370 1.00 73.16 C -ATOM 2312 NZ LYS C 16 -32.038 9.453 3.272 1.00 69.52 N -ATOM 2313 N VAL C 17 -26.252 12.133 5.573 1.00 35.88 N -ATOM 2314 CA VAL C 17 -25.770 11.297 6.645 1.00 27.62 C -ATOM 2315 C VAL C 17 -26.612 11.695 7.685 1.00 30.67 C -ATOM 2316 O VAL C 17 -27.281 11.042 8.701 1.00 29.27 O -ATOM 2317 CB VAL C 17 -24.169 10.853 6.795 1.00 24.84 C -ATOM 2318 CG1 VAL C 17 -23.946 10.589 8.064 1.00 24.66 C -ATOM 2319 CG2 VAL C 17 -23.794 9.916 5.483 1.00 36.95 C -ATOM 2320 N GLY C 18 -26.104 13.085 7.958 1.00 37.42 N -ATOM 2321 CA GLY C 18 -26.962 13.614 9.161 1.00 36.79 C -ATOM 2322 C GLY C 18 -26.609 13.344 10.447 1.00 35.54 C -ATOM 2323 O GLY C 18 -25.379 12.833 10.941 1.00 34.05 O -ATOM 2324 N ALA C 19 -27.875 13.044 10.943 1.00 30.07 N -ATOM 2325 CA ALA C 19 -27.686 12.652 12.207 1.00 42.34 C -ATOM 2326 C ALA C 19 -27.441 11.246 12.497 1.00 38.75 C -ATOM 2327 O ALA C 19 -27.016 10.579 13.697 1.00 34.11 O -ATOM 2328 CB ALA C 19 -28.889 12.929 12.875 1.00 49.98 C -ATOM 2329 N HIS C 20 -27.337 10.243 11.555 1.00 27.23 N -ATOM 2330 CA HIS C 20 -26.912 8.767 11.705 1.00 31.96 C -ATOM 2331 C HIS C 20 -25.296 8.716 11.689 1.00 24.34 C -ATOM 2332 O HIS C 20 -24.833 7.499 11.716 1.00 23.07 O -ATOM 2333 CB HIS C 20 -27.281 8.149 10.528 1.00 47.99 C -ATOM 2334 CG HIS C 20 -28.926 8.104 10.076 1.00 49.70 C -ATOM 2335 ND1 HIS C 20 -29.432 7.280 11.405 1.00 46.00 N -ATOM 2336 CD2 HIS C 20 -29.730 9.020 9.630 1.00 46.72 C -ATOM 2337 CE1 HIS C 20 -31.098 7.852 11.111 1.00 49.28 C -ATOM 2338 NE2 HIS C 20 -30.830 8.671 9.800 1.00 51.94 N -ATOM 2339 N ALA C 21 -24.619 9.813 11.399 1.00 28.71 N -ATOM 2340 CA ALA C 21 -23.098 9.802 11.331 1.00 32.59 C -ATOM 2341 C ALA C 21 -22.391 9.015 12.473 1.00 33.22 C -ATOM 2342 O ALA C 21 -21.700 8.030 11.964 1.00 25.05 O -ATOM 2343 CB ALA C 21 -22.805 11.312 11.238 1.00 28.99 C -ATOM 2344 N GLY C 22 -22.670 8.973 13.605 1.00 30.50 N -ATOM 2345 CA GLY C 22 -22.269 8.117 14.625 1.00 25.20 C -ATOM 2346 C GLY C 22 -22.605 6.970 14.498 1.00 28.87 C -ATOM 2347 O GLY C 22 -21.738 5.901 14.583 1.00 21.09 O -ATOM 2348 N GLU C 23 -23.752 6.203 14.168 1.00 19.95 N -ATOM 2349 CA GLU C 23 -24.151 4.976 13.969 1.00 21.38 C -ATOM 2350 C GLU C 23 -23.181 4.329 12.723 1.00 15.02 C -ATOM 2351 O GLU C 23 -22.815 3.097 12.742 1.00 16.54 O -ATOM 2352 CB GLU C 23 -25.689 4.819 13.452 1.00 29.82 C -ATOM 2353 CG GLU C 23 -26.106 3.452 13.736 1.00 36.93 C -ATOM 2354 CD GLU C 23 -28.202 3.924 13.602 1.00 80.12 C -ATOM 2355 OE1 GLU C 23 -27.795 2.922 11.489 1.00 66.02 O -ATOM 2356 OE2 GLU C 23 -27.964 4.694 13.267 1.00 59.79 O -ATOM 2357 N TYR C 24 -23.207 5.173 11.697 1.00 21.28 N -ATOM 2358 CA TYR C 24 -22.418 4.812 10.585 1.00 19.46 C -ATOM 2359 C TYR C 24 -20.849 4.466 10.860 1.00 15.33 C -ATOM 2360 O TYR C 24 -20.148 3.754 10.360 1.00 13.77 O -ATOM 2361 CB TYR C 24 -22.651 5.606 9.406 1.00 16.14 C -ATOM 2362 CG TYR C 24 -24.080 5.727 8.793 1.00 13.71 C -ATOM 2363 CD1 TYR C 24 -24.170 6.732 7.640 1.00 24.76 C -ATOM 2364 CD2 TYR C 24 -25.002 4.824 9.337 1.00 21.84 C -ATOM 2365 CE1 TYR C 24 -25.645 6.832 7.377 1.00 25.66 C -ATOM 2366 CE2 TYR C 24 -26.453 4.934 8.784 1.00 17.49 C -ATOM 2367 CZ TYR C 24 -26.325 5.877 7.791 1.00 27.32 C -ATOM 2368 OH TYR C 24 -27.810 6.069 7.401 1.00 31.23 O -ATOM 2369 N GLY C 25 -20.290 5.421 11.638 1.00 18.29 N -ATOM 2370 CA GLY C 25 -19.027 5.388 12.069 1.00 15.33 C -ATOM 2371 C GLY C 25 -18.807 4.272 12.918 1.00 12.64 C -ATOM 2372 O GLY C 25 -17.733 3.304 12.661 1.00 15.23 O -ATOM 2373 N ALA C 26 -19.542 3.599 13.820 1.00 16.00 N -ATOM 2374 CA ALA C 26 -19.471 2.386 14.471 1.00 11.42 C -ATOM 2375 C ALA C 26 -19.307 1.193 13.564 1.00 10.94 C -ATOM 2376 O ALA C 26 -18.739 0.230 13.578 1.00 13.65 O -ATOM 2377 CB ALA C 26 -20.512 2.232 15.656 1.00 11.99 C -ATOM 2378 N GLU C 27 -20.425 1.260 12.521 1.00 12.87 N -ATOM 2379 CA GLU C 27 -20.638 0.028 11.636 1.00 15.51 C -ATOM 2380 C GLU C 27 -19.412 0.022 10.785 1.00 12.84 C -ATOM 2381 O GLU C 27 -18.849 -1.119 10.534 1.00 15.95 O -ATOM 2382 CB GLU C 27 -21.715 0.427 10.623 1.00 15.50 C -ATOM 2383 CG GLU C 27 -21.926 -0.710 9.772 1.00 17.08 C -ATOM 2384 CD GLU C 27 -23.164 -0.586 8.872 1.00 30.48 C -ATOM 2385 OE1 GLU C 27 -23.095 -0.770 7.588 1.00 18.71 O -ATOM 2386 OE2 GLU C 27 -24.194 0.119 9.312 1.00 24.16 O -ATOM 2387 N ALA C 28 -18.789 1.258 10.332 1.00 11.36 N -ATOM 2388 CA ALA C 28 -17.460 1.158 9.500 1.00 9.58 C -ATOM 2389 C ALA C 28 -16.340 0.418 10.332 1.00 9.29 C -ATOM 2390 O ALA C 28 -15.677 -0.370 9.760 1.00 12.64 O -ATOM 2391 CB ALA C 28 -17.171 2.523 9.159 1.00 13.35 C -ATOM 2392 N LEU C 29 -16.325 0.834 11.666 1.00 12.01 N -ATOM 2393 CA LEU C 29 -15.240 0.036 12.460 1.00 9.42 C -ATOM 2394 C LEU C 29 -15.351 -1.296 12.531 1.00 8.04 C -ATOM 2395 O LEU C 29 -14.557 -2.221 12.462 1.00 11.27 O -ATOM 2396 CB LEU C 29 -15.253 0.792 13.944 1.00 13.39 C -ATOM 2397 CG LEU C 29 -14.671 2.120 14.000 1.00 14.28 C -ATOM 2398 CD1 LEU C 29 -15.060 2.641 15.229 1.00 21.17 C -ATOM 2399 CD2 LEU C 29 -13.328 2.186 13.586 1.00 17.52 C -ATOM 2400 N GLU C 30 -16.582 -1.891 12.768 1.00 12.13 N -ATOM 2401 CA GLU C 30 -17.039 -3.158 12.830 1.00 15.15 C -ATOM 2402 C GLU C 30 -16.575 -3.834 11.597 1.00 15.74 C -ATOM 2403 O GLU C 30 -16.144 -4.973 11.643 1.00 15.15 O -ATOM 2404 CB GLU C 30 -18.512 -3.390 13.241 1.00 16.95 C -ATOM 2405 CG GLU C 30 -18.749 -4.796 13.397 1.00 22.01 C -ATOM 2406 CD GLU C 30 -20.492 -5.310 14.125 1.00 33.25 C -ATOM 2407 OE1 GLU C 30 -20.859 -4.170 14.215 1.00 33.78 O -ATOM 2408 OE2 GLU C 30 -20.298 -6.063 14.309 1.00 40.59 O -ATOM 2409 N ARG C 31 -17.016 -3.172 10.500 1.00 9.68 N -ATOM 2410 CA ARG C 31 -16.706 -3.791 9.173 1.00 8.70 C -ATOM 2411 C ARG C 31 -15.092 -4.029 9.070 1.00 13.62 C -ATOM 2412 O ARG C 31 -14.706 -5.080 8.618 1.00 13.67 O -ATOM 2413 CB ARG C 31 -17.211 -2.898 8.144 1.00 12.42 C -ATOM 2414 CG ARG C 31 -18.743 -3.121 7.942 1.00 11.84 C -ATOM 2415 CD ARG C 31 -19.136 -2.201 6.911 1.00 15.20 C -ATOM 2416 NE ARG C 31 -20.701 -2.256 6.631 1.00 14.19 N -ATOM 2417 CZ ARG C 31 -21.363 -3.224 5.977 1.00 11.42 C -ATOM 2418 NH1 ARG C 31 -20.645 -4.259 5.462 1.00 11.92 N -ATOM 2419 NH2 ARG C 31 -22.607 -3.167 6.110 1.00 15.15 N -ATOM 2420 N MET C 32 -14.391 -2.999 9.390 1.00 10.57 N -ATOM 2421 CA MET C 32 -12.880 -2.985 9.431 1.00 8.16 C -ATOM 2422 C MET C 32 -12.304 -4.106 10.303 1.00 7.80 C -ATOM 2423 O MET C 32 -11.482 -4.880 9.804 1.00 11.64 O -ATOM 2424 CB MET C 32 -12.387 -1.587 9.793 1.00 8.09 C -ATOM 2425 CG MET C 32 -10.949 -1.623 9.744 1.00 11.10 C -ATOM 2426 SD MET C 32 -10.226 -0.081 10.328 1.00 18.02 S -ATOM 2427 CE MET C 32 -10.638 -0.209 12.043 1.00 20.04 C -ATOM 2428 N PHE C 33 -12.802 -4.206 11.603 1.00 13.50 N -ATOM 2429 CA PHE C 33 -12.271 -5.320 12.432 1.00 12.85 C -ATOM 2430 C PHE C 33 -12.547 -6.578 11.951 1.00 15.05 C -ATOM 2431 O PHE C 33 -11.717 -7.551 12.143 1.00 13.38 O -ATOM 2432 CB PHE C 33 -12.756 -5.046 13.817 1.00 12.45 C -ATOM 2433 CG PHE C 33 -12.568 -3.710 14.467 1.00 10.81 C -ATOM 2434 CD1 PHE C 33 -11.266 -3.320 14.428 1.00 14.60 C -ATOM 2435 CD2 PHE C 33 -13.526 -3.151 15.305 1.00 15.15 C -ATOM 2436 CE1 PHE C 33 -10.894 -2.155 15.062 1.00 15.80 C -ATOM 2437 CE2 PHE C 33 -13.010 -1.947 15.768 1.00 13.43 C -ATOM 2438 CZ PHE C 33 -11.786 -1.494 15.661 1.00 22.23 C -ATOM 2439 N LEU C 34 -13.672 -6.909 11.292 1.00 11.85 N -ATOM 2440 CA LEU C 34 -14.025 -8.262 10.744 1.00 12.31 C -ATOM 2441 C LEU C 34 -13.308 -8.546 9.433 1.00 15.72 C -ATOM 2442 O LEU C 34 -12.814 -9.634 9.197 1.00 19.67 O -ATOM 2443 CB LEU C 34 -15.490 -8.519 10.506 1.00 16.89 C -ATOM 2444 CG LEU C 34 -16.308 -8.523 11.809 1.00 26.21 C -ATOM 2445 CD1 LEU C 34 -17.801 -8.703 11.585 1.00 26.59 C -ATOM 2446 CD2 LEU C 34 -15.886 -9.544 12.837 1.00 38.34 C -ATOM 2447 N SER C 35 -13.287 -7.520 8.527 1.00 12.82 N -ATOM 2448 CA SER C 35 -12.594 -7.794 7.329 1.00 10.93 C -ATOM 2449 C SER C 35 -11.162 -7.828 7.166 1.00 14.27 C -ATOM 2450 O SER C 35 -10.505 -8.327 6.376 1.00 16.71 O -ATOM 2451 CB SER C 35 -13.015 -6.732 6.237 1.00 13.98 C -ATOM 2452 OG SER C 35 -14.406 -6.851 5.967 1.00 18.75 O -ATOM 2453 N PHE C 36 -10.441 -6.974 8.104 1.00 11.09 N -ATOM 2454 CA PHE C 36 -9.024 -6.696 8.153 1.00 10.70 C -ATOM 2455 C PHE C 36 -8.606 -6.742 9.707 1.00 13.97 C -ATOM 2456 O PHE C 36 -8.344 -5.778 10.402 1.00 16.32 O -ATOM 2457 CB PHE C 36 -8.759 -5.327 7.682 1.00 12.71 C -ATOM 2458 CG PHE C 36 -9.244 -5.034 6.227 1.00 14.13 C -ATOM 2459 CD1 PHE C 36 -10.405 -4.227 6.071 1.00 14.98 C -ATOM 2460 CD2 PHE C 36 -8.716 -5.826 5.029 1.00 21.47 C -ATOM 2461 CE1 PHE C 36 -10.962 -3.950 4.805 1.00 23.41 C -ATOM 2462 CE2 PHE C 36 -9.304 -5.498 3.966 1.00 24.62 C -ATOM 2463 CZ PHE C 36 -10.428 -4.612 3.839 1.00 15.55 C -ATOM 2464 N PRO C 37 -8.487 -8.050 9.947 1.00 18.65 N -ATOM 2465 CA PRO C 37 -8.320 -8.334 11.359 1.00 17.35 C -ATOM 2466 C PRO C 37 -6.962 -7.708 12.012 1.00 18.35 C -ATOM 2467 O PRO C 37 -6.854 -7.465 13.248 1.00 14.04 O -ATOM 2468 CB PRO C 37 -8.349 -9.870 11.562 1.00 27.87 C -ATOM 2469 CG PRO C 37 -8.429 -10.372 10.373 1.00 37.42 C -ATOM 2470 CD PRO C 37 -8.767 -9.192 9.450 1.00 22.48 C -ATOM 2471 N THR C 38 -6.066 -7.410 11.173 1.00 12.63 N -ATOM 2472 CA THR C 38 -4.834 -6.636 11.753 1.00 17.25 C -ATOM 2473 C THR C 38 -5.049 -5.478 12.414 1.00 15.32 C -ATOM 2474 O THR C 38 -4.264 -5.001 13.219 1.00 11.09 O -ATOM 2475 CB THR C 38 -3.639 -7.011 10.452 1.00 12.40 C -ATOM 2476 OG1 THR C 38 -4.178 -5.757 9.596 1.00 15.33 O -ATOM 2477 CG2 THR C 38 -4.507 -7.126 9.385 1.00 80.12 C -ATOM 2478 N THR C 39 -6.072 -4.797 11.866 1.00 10.35 N -ATOM 2479 CA THR C 39 -6.458 -3.530 12.499 1.00 11.60 C -ATOM 2480 C THR C 39 -6.867 -3.675 13.987 1.00 11.25 C -ATOM 2481 O THR C 39 -6.719 -2.683 14.751 1.00 15.31 O -ATOM 2482 CB THR C 39 -7.618 -2.839 11.782 1.00 10.41 C -ATOM 2483 OG1 THR C 39 -8.902 -3.535 11.780 1.00 8.43 O -ATOM 2484 CG2 THR C 39 -7.110 -2.694 10.278 1.00 7.27 C -ATOM 2485 N LYS C 40 -7.142 -4.800 14.416 1.00 12.10 N -ATOM 2486 CA LYS C 40 -7.571 -4.948 15.946 1.00 12.37 C -ATOM 2487 C LYS C 40 -6.340 -4.815 16.822 1.00 12.69 C -ATOM 2488 O LYS C 40 -6.554 -4.646 17.995 1.00 13.50 O -ATOM 2489 CB LYS C 40 -8.135 -6.441 16.142 1.00 13.01 C -ATOM 2490 CG LYS C 40 -9.508 -6.644 15.446 1.00 16.35 C -ATOM 2491 CD LYS C 40 -9.585 -8.284 15.551 1.00 21.60 C -ATOM 2492 CE LYS C 40 -10.395 -8.518 15.432 1.00 41.58 C -ATOM 2493 NZ LYS C 40 -10.104 -10.161 15.709 1.00 24.62 N -ATOM 2494 N THR C 41 -5.213 -4.883 16.231 1.00 15.39 N -ATOM 2495 CA THR C 41 -3.858 -4.878 17.048 1.00 15.24 C -ATOM 2496 C THR C 41 -3.895 -3.538 17.513 1.00 24.53 C -ATOM 2497 O THR C 41 -3.052 -3.276 18.625 1.00 20.94 O -ATOM 2498 CB THR C 41 -2.611 -5.058 16.204 1.00 10.27 C -ATOM 2499 OG1 THR C 41 -2.473 -4.084 15.265 1.00 10.56 O -ATOM 2500 CG2 THR C 41 -2.649 -6.370 15.637 1.00 13.16 C -ATOM 2501 N TYR C 42 -4.559 -2.347 17.313 1.00 15.74 N -ATOM 2502 CA TYR C 42 -4.420 -1.045 17.757 1.00 10.60 C -ATOM 2503 C TYR C 42 -5.479 -0.829 18.921 1.00 12.75 C -ATOM 2504 O TYR C 42 -5.553 0.201 19.530 1.00 15.68 O -ATOM 2505 CB TYR C 42 -4.800 0.068 16.774 1.00 16.68 C -ATOM 2506 CG TYR C 42 -3.607 -0.087 15.746 1.00 10.99 C -ATOM 2507 CD1 TYR C 42 -2.328 0.661 16.011 1.00 17.16 C -ATOM 2508 CD2 TYR C 42 -3.699 -0.743 14.478 1.00 12.51 C -ATOM 2509 CE1 TYR C 42 -1.337 0.521 15.154 1.00 15.83 C -ATOM 2510 CE2 TYR C 42 -2.696 -0.758 13.617 1.00 12.91 C -ATOM 2511 CZ TYR C 42 -1.386 -0.114 13.943 1.00 12.97 C -ATOM 2512 OH TYR C 42 -0.401 -0.078 12.976 1.00 13.25 O -ATOM 2513 N PHE C 43 -6.271 -1.850 19.113 1.00 15.49 N -ATOM 2514 CA PHE C 43 -7.459 -1.760 20.167 1.00 17.75 C -ATOM 2515 C PHE C 43 -7.514 -3.016 21.053 1.00 20.04 C -ATOM 2516 O PHE C 43 -8.605 -3.535 21.334 1.00 17.05 O -ATOM 2517 CB PHE C 43 -8.817 -1.519 19.333 1.00 26.70 C -ATOM 2518 CG PHE C 43 -8.906 -0.392 18.437 1.00 14.42 C -ATOM 2519 CD1 PHE C 43 -8.473 -0.554 17.054 1.00 15.73 C -ATOM 2520 CD2 PHE C 43 -9.700 0.777 18.998 1.00 15.90 C -ATOM 2521 CE1 PHE C 43 -8.663 0.579 16.317 1.00 16.99 C -ATOM 2522 CE2 PHE C 43 -9.585 1.781 18.059 1.00 19.76 C -ATOM 2523 CZ PHE C 43 -9.193 1.883 16.726 1.00 10.96 C -ATOM 2524 N PRO C 44 -6.303 -3.266 21.758 1.00 17.51 N -ATOM 2525 CA PRO C 44 -6.430 -4.575 22.577 1.00 22.01 C -ATOM 2526 C PRO C 44 -7.021 -4.034 23.952 1.00 23.34 C -ATOM 2527 O PRO C 44 -7.479 -5.004 24.549 1.00 23.67 O -ATOM 2528 CB PRO C 44 -4.725 -4.600 22.823 1.00 28.76 C -ATOM 2529 CG PRO C 44 -4.302 -3.265 22.722 1.00 30.00 C -ATOM 2530 CD PRO C 44 -5.000 -2.496 21.564 1.00 18.17 C -ATOM 2531 N HIS C 45 -7.313 -2.986 24.170 1.00 23.82 N -ATOM 2532 CA HIS C 45 -8.129 -2.454 25.363 1.00 24.33 C -ATOM 2533 C HIS C 45 -9.774 -2.425 25.223 1.00 36.67 C -ATOM 2534 O HIS C 45 -10.201 -1.856 26.159 1.00 32.61 O -ATOM 2535 CB HIS C 45 -7.724 -1.122 25.714 1.00 29.73 C -ATOM 2536 CG HIS C 45 -7.512 0.207 24.830 1.00 29.43 C -ATOM 2537 ND1 HIS C 45 -6.904 -0.240 23.536 1.00 26.84 N -ATOM 2538 CD2 HIS C 45 -8.212 1.313 24.765 1.00 33.54 C -ATOM 2539 CE1 HIS C 45 -7.241 0.770 23.119 1.00 37.75 C -ATOM 2540 NE2 HIS C 45 -7.901 1.880 23.651 1.00 39.11 N -ATOM 2541 N PHE C 46 -10.097 -2.588 23.981 1.00 19.71 N -ATOM 2542 CA PHE C 46 -11.427 -2.447 23.784 1.00 16.71 C -ATOM 2543 C PHE C 46 -11.984 -3.704 23.878 1.00 21.27 C -ATOM 2544 O PHE C 46 -11.601 -4.890 23.408 1.00 23.84 O -ATOM 2545 CB PHE C 46 -11.721 -1.909 22.223 1.00 21.57 C -ATOM 2546 CG PHE C 46 -11.812 -0.571 22.355 1.00 17.89 C -ATOM 2547 CD1 PHE C 46 -12.584 0.134 21.407 1.00 29.22 C -ATOM 2548 CD2 PHE C 46 -11.092 0.466 22.932 1.00 29.35 C -ATOM 2549 CE1 PHE C 46 -12.539 1.579 21.231 1.00 23.51 C -ATOM 2550 CE2 PHE C 46 -11.283 1.342 22.737 1.00 34.19 C -ATOM 2551 CZ PHE C 46 -11.794 2.381 21.680 1.00 30.38 C -ATOM 2552 N ASP C 47 -13.484 -3.924 24.123 1.00 21.22 N -ATOM 2553 CA ASP C 47 -14.200 -5.093 23.710 1.00 21.17 C -ATOM 2554 C ASP C 47 -14.972 -4.945 22.231 1.00 15.44 C -ATOM 2555 O ASP C 47 -15.394 -3.747 22.085 1.00 19.22 O -ATOM 2556 CB ASP C 47 -15.564 -4.912 24.743 1.00 26.87 C -ATOM 2557 CG ASP C 47 -16.291 -6.456 24.524 1.00 44.60 C -ATOM 2558 OD1 ASP C 47 -16.314 -6.539 23.491 1.00 38.14 O -ATOM 2559 OD2 ASP C 47 -17.247 -6.397 25.386 1.00 35.16 O -ATOM 2560 N LEU C 48 -14.283 -5.744 21.445 1.00 20.23 N -ATOM 2561 CA LEU C 48 -14.738 -5.455 19.945 1.00 22.13 C -ATOM 2562 C LEU C 48 -15.716 -6.250 19.550 1.00 26.79 C -ATOM 2563 O LEU C 48 -16.269 -6.380 18.272 1.00 28.79 O -ATOM 2564 CB LEU C 48 -13.468 -5.863 19.207 1.00 20.10 C -ATOM 2565 CG LEU C 48 -12.283 -5.143 19.138 1.00 22.13 C -ATOM 2566 CD1 LEU C 48 -10.976 -5.443 18.455 1.00 30.66 C -ATOM 2567 CD2 LEU C 48 -12.440 -3.412 19.024 1.00 21.27 C -ATOM 2568 N SER C 49 -16.750 -6.795 20.348 1.00 29.67 N -ATOM 2569 CA SER C 49 -17.996 -7.682 20.348 1.00 26.45 C -ATOM 2570 C SER C 49 -18.688 -6.784 19.661 1.00 19.97 C -ATOM 2571 O SER C 49 -18.950 -5.536 19.662 1.00 20.96 O -ATOM 2572 CB SER C 49 -18.391 -8.577 21.574 1.00 26.72 C -ATOM 2573 OG SER C 49 -18.238 -7.994 22.499 1.00 34.29 O -ATOM 2574 N HIS C 50 -19.776 -7.581 18.833 1.00 28.23 N -ATOM 2575 CA HIS C 50 -20.784 -6.859 18.155 1.00 26.06 C -ATOM 2576 C HIS C 50 -21.742 -6.003 19.283 1.00 24.81 C -ATOM 2577 O HIS C 50 -21.976 -6.730 20.143 1.00 27.33 O -ATOM 2578 CB HIS C 50 -21.772 -7.860 17.171 1.00 33.58 C -ATOM 2579 CG HIS C 50 -22.495 -6.997 16.501 1.00 21.75 C -ATOM 2580 ND1 HIS C 50 -24.098 -7.224 16.903 1.00 37.61 N -ATOM 2581 CD2 HIS C 50 -22.721 -6.030 15.749 1.00 24.11 C -ATOM 2582 CE1 HIS C 50 -24.713 -6.289 16.301 1.00 35.12 C -ATOM 2583 NE2 HIS C 50 -23.972 -5.305 15.362 1.00 42.35 N -ATOM 2584 N GLY C 51 -21.911 -4.827 19.019 1.00 24.42 N -ATOM 2585 CA GLY C 51 -22.633 -4.098 19.831 1.00 26.56 C -ATOM 2586 C GLY C 51 -22.082 -3.387 20.930 1.00 23.39 C -ATOM 2587 O GLY C 51 -22.536 -2.501 21.731 1.00 25.53 O -ATOM 2588 N SER C 52 -20.724 -3.498 20.885 1.00 22.06 N -ATOM 2589 CA SER C 52 -19.739 -2.846 21.982 1.00 25.03 C -ATOM 2590 C SER C 52 -19.903 -1.593 22.193 1.00 31.37 C -ATOM 2591 O SER C 52 -19.945 -0.663 21.200 1.00 22.94 O -ATOM 2592 CB SER C 52 -18.376 -3.162 21.704 1.00 30.26 C -ATOM 2593 OG SER C 52 -17.567 -2.497 22.631 1.00 21.66 O -ATOM 2594 N ALA C 53 -20.311 -0.885 23.302 1.00 22.15 N -ATOM 2595 CA ALA C 53 -20.223 0.561 23.639 1.00 29.32 C -ATOM 2596 C ALA C 53 -19.008 1.341 23.195 1.00 23.50 C -ATOM 2597 O ALA C 53 -19.144 2.489 22.964 1.00 19.56 O -ATOM 2598 CB ALA C 53 -21.016 0.770 24.778 1.00 46.37 C -ATOM 2599 N GLN C 54 -18.075 0.456 23.565 1.00 20.69 N -ATOM 2600 CA GLN C 54 -16.671 1.124 23.388 1.00 22.13 C -ATOM 2601 C GLN C 54 -16.498 1.625 21.724 1.00 21.00 C -ATOM 2602 O GLN C 54 -15.986 2.677 21.452 1.00 19.66 O -ATOM 2603 CB GLN C 54 -15.533 0.388 23.780 1.00 23.01 C -ATOM 2604 CG GLN C 54 -15.387 0.264 25.146 1.00 26.98 C -ATOM 2605 CD GLN C 54 -14.244 -0.704 25.751 1.00 17.64 C -ATOM 2606 OE1 GLN C 54 -14.213 -1.867 25.317 1.00 23.97 O -ATOM 2607 NE2 GLN C 54 -13.269 -0.029 26.343 1.00 35.16 N -ATOM 2608 N VAL C 55 -16.998 0.495 20.976 1.00 18.58 N -ATOM 2609 CA VAL C 55 -16.782 0.728 19.397 1.00 18.23 C -ATOM 2610 C VAL C 55 -17.788 1.835 19.121 1.00 15.73 C -ATOM 2611 O VAL C 55 -17.557 2.638 18.250 1.00 16.15 O -ATOM 2612 CB VAL C 55 -17.023 -0.655 18.769 1.00 16.13 C -ATOM 2613 CG1 VAL C 55 -17.141 -0.282 17.289 1.00 22.56 C -ATOM 2614 CG2 VAL C 55 -15.953 -1.526 19.088 1.00 16.34 C -ATOM 2615 N LYS C 56 -19.064 1.844 19.638 1.00 17.00 N -ATOM 2616 CA LYS C 56 -20.011 2.798 19.335 1.00 18.57 C -ATOM 2617 C LYS C 56 -19.657 4.015 19.595 1.00 20.36 C -ATOM 2618 O LYS C 56 -19.638 5.117 18.950 1.00 20.10 O -ATOM 2619 CB LYS C 56 -21.306 2.565 20.099 1.00 27.04 C -ATOM 2620 CG LYS C 56 -22.017 1.239 19.517 1.00 42.35 C -ATOM 2621 CD LYS C 56 -23.983 2.334 19.796 1.00 43.36 C -ATOM 2622 CE LYS C 56 -24.238 -0.016 19.420 1.00 48.38 C -ATOM 2623 NZ LYS C 56 -25.547 0.420 20.454 1.00 67.70 N -ATOM 2624 N GLY C 57 -18.873 4.239 20.758 1.00 16.00 N -ATOM 2625 CA GLY C 57 -18.397 5.432 21.231 1.00 21.54 C -ATOM 2626 C GLY C 57 -17.299 6.086 20.387 1.00 18.61 C -ATOM 2627 O GLY C 57 -17.174 7.416 20.069 1.00 24.59 O -ATOM 2628 N HIS C 58 -16.421 5.133 20.063 1.00 15.81 N -ATOM 2629 CA HIS C 58 -15.259 5.492 19.163 1.00 16.10 C -ATOM 2630 C HIS C 58 -15.968 5.977 17.705 1.00 21.16 C -ATOM 2631 O HIS C 58 -15.334 6.873 17.165 1.00 17.74 O -ATOM 2632 CB HIS C 58 -14.298 4.450 19.037 1.00 15.43 C -ATOM 2633 CG HIS C 58 -13.084 4.816 18.336 1.00 18.98 C -ATOM 2634 ND1 HIS C 58 -12.377 5.886 18.887 1.00 21.14 N -ATOM 2635 CD2 HIS C 58 -12.537 4.339 17.359 1.00 16.95 C -ATOM 2636 CE1 HIS C 58 -11.397 5.896 17.811 1.00 21.77 C -ATOM 2637 NE2 HIS C 58 -11.418 4.951 16.789 1.00 17.45 N -ATOM 2638 N GLY C 59 -16.820 5.155 17.321 1.00 20.04 N -ATOM 2639 CA GLY C 59 -17.341 5.505 16.148 1.00 24.32 C -ATOM 2640 C GLY C 59 -18.005 6.810 15.949 1.00 16.44 C -ATOM 2641 O GLY C 59 -17.768 7.655 14.926 1.00 16.63 O -ATOM 2642 N LYS C 60 -18.641 7.304 17.045 1.00 14.40 N -ATOM 2643 CA LYS C 60 -19.047 8.674 17.195 1.00 14.87 C -ATOM 2644 C LYS C 60 -18.066 9.704 17.103 1.00 17.20 C -ATOM 2645 O LYS C 60 -18.083 10.725 16.452 1.00 19.10 O -ATOM 2646 CB LYS C 60 -20.090 8.722 18.417 1.00 20.14 C -ATOM 2647 CG LYS C 60 -20.474 10.102 18.286 1.00 36.22 C -ATOM 2648 CD LYS C 60 -21.736 10.498 19.120 1.00 67.45 C -ATOM 2649 CE LYS C 60 -22.281 11.583 18.549 1.00 61.41 C -ATOM 2650 NZ LYS C 60 -21.104 12.754 19.691 1.00 67.02 N -ATOM 2651 N LYS C 61 -16.927 9.423 17.774 1.00 17.79 N -ATOM 2652 CA LYS C 61 -15.858 10.357 17.767 1.00 21.13 C -ATOM 2653 C LYS C 61 -15.164 10.595 16.162 1.00 16.24 C -ATOM 2654 O LYS C 61 -14.881 11.695 15.808 1.00 15.80 O -ATOM 2655 CB LYS C 61 -14.696 9.830 18.603 1.00 23.05 C -ATOM 2656 CG LYS C 61 -15.062 10.074 19.860 1.00 29.48 C -ATOM 2657 CD LYS C 61 -14.168 9.693 20.841 1.00 35.76 C -ATOM 2658 CE LYS C 61 -14.859 10.184 22.437 1.00 58.26 C -ATOM 2659 NZ LYS C 61 -13.290 9.055 22.853 1.00 59.87 N -ATOM 2660 N VAL C 62 -15.053 9.278 15.522 1.00 15.31 N -ATOM 2661 CA VAL C 62 -14.623 9.355 14.153 1.00 17.56 C -ATOM 2662 C VAL C 62 -15.371 10.194 13.113 1.00 16.25 C -ATOM 2663 O VAL C 62 -15.014 11.087 12.455 1.00 13.61 O -ATOM 2664 CB VAL C 62 -14.380 7.809 13.720 1.00 18.84 C -ATOM 2665 CG1 VAL C 62 -14.183 7.763 12.290 1.00 17.19 C -ATOM 2666 CG2 VAL C 62 -13.252 7.305 14.521 1.00 18.33 C -ATOM 2667 N ALA C 63 -16.701 9.866 13.495 1.00 13.67 N -ATOM 2668 CA ALA C 63 -17.818 10.501 12.645 1.00 21.56 C -ATOM 2669 C ALA C 63 -17.715 11.855 12.728 1.00 19.04 C -ATOM 2670 O ALA C 63 -17.832 12.775 11.974 1.00 17.01 O -ATOM 2671 CB ALA C 63 -19.206 9.890 12.827 1.00 17.02 C -ATOM 2672 N ASP C 64 -17.653 12.417 13.991 1.00 16.51 N -ATOM 2673 CA ASP C 64 -17.709 13.830 14.243 1.00 19.49 C -ATOM 2674 C ASP C 64 -16.540 14.535 13.748 1.00 14.91 C -ATOM 2675 O ASP C 64 -16.584 15.604 13.224 1.00 19.95 O -ATOM 2676 CB ASP C 64 -17.991 14.096 15.799 1.00 24.76 C -ATOM 2677 CG ASP C 64 -19.393 13.818 16.643 1.00 34.25 C -ATOM 2678 OD1 ASP C 64 -20.152 13.414 15.899 1.00 28.85 O -ATOM 2679 OD2 ASP C 64 -19.056 13.688 17.650 1.00 27.13 O -ATOM 2680 N ALA C 65 -15.369 13.857 13.860 1.00 16.65 N -ATOM 2681 CA ALA C 65 -14.163 14.481 13.291 1.00 16.32 C -ATOM 2682 C ALA C 65 -14.252 14.735 11.694 1.00 13.95 C -ATOM 2683 O ALA C 65 -13.994 15.689 11.048 1.00 16.33 O -ATOM 2684 CB ALA C 65 -13.017 13.593 13.359 1.00 16.15 C -ATOM 2685 N LEU C 66 -15.064 13.712 10.969 1.00 17.13 N -ATOM 2686 CA LEU C 66 -15.337 13.726 9.525 1.00 13.55 C -ATOM 2687 C LEU C 66 -16.272 14.810 9.233 1.00 14.32 C -ATOM 2688 O LEU C 66 -16.159 15.647 8.296 1.00 15.99 O -ATOM 2689 CB LEU C 66 -15.780 12.400 8.970 1.00 12.37 C -ATOM 2690 CG LEU C 66 -14.557 11.353 8.900 1.00 14.22 C -ATOM 2691 CD1 LEU C 66 -15.162 10.177 8.798 1.00 25.53 C -ATOM 2692 CD2 LEU C 66 -13.636 11.641 7.894 1.00 14.43 C -ATOM 2693 N THR C 67 -17.292 14.977 10.145 1.00 14.80 N -ATOM 2694 CA THR C 67 -18.300 16.119 9.983 1.00 15.27 C -ATOM 2695 C THR C 67 -17.479 17.374 10.100 1.00 19.15 C -ATOM 2696 O THR C 67 -17.741 18.262 9.274 1.00 21.53 O -ATOM 2697 CB THR C 67 -19.282 15.886 11.189 1.00 13.22 C -ATOM 2698 OG1 THR C 67 -20.066 14.785 10.961 1.00 17.30 O -ATOM 2699 CG2 THR C 67 -20.207 17.226 11.132 1.00 30.44 C -ATOM 2700 N ASN C 68 -16.541 17.536 11.125 1.00 19.52 N -ATOM 2701 CA ASN C 68 -15.765 18.613 11.088 1.00 21.49 C -ATOM 2702 C ASN C 68 -14.901 18.833 9.858 1.00 19.25 C -ATOM 2703 O ASN C 68 -14.653 20.197 9.353 1.00 22.73 O -ATOM 2704 CB ASN C 68 -14.964 18.621 12.362 1.00 16.47 C -ATOM 2705 CG ASN C 68 -13.974 19.880 12.584 1.00 43.34 C -ATOM 2706 OD1 ASN C 68 -14.128 20.746 12.326 1.00 49.22 O -ATOM 2707 ND2 ASN C 68 -12.524 19.654 13.058 1.00 50.67 N -ATOM 2708 N ALA C 69 -14.378 17.793 9.402 1.00 16.22 N -ATOM 2709 CA ALA C 69 -13.526 17.929 8.006 1.00 15.27 C -ATOM 2710 C ALA C 69 -14.531 18.551 6.897 1.00 20.32 C -ATOM 2711 O ALA C 69 -13.858 19.250 6.103 1.00 22.38 O -ATOM 2712 CB ALA C 69 -12.891 16.615 7.759 1.00 15.52 C -ATOM 2713 N VAL C 70 -15.649 17.853 6.837 1.00 18.62 N -ATOM 2714 CA VAL C 70 -16.708 18.432 5.673 1.00 21.72 C -ATOM 2715 C VAL C 70 -16.947 20.121 6.025 1.00 33.94 C -ATOM 2716 O VAL C 70 -16.795 20.608 4.872 1.00 26.93 O -ATOM 2717 CB VAL C 70 -17.884 17.598 5.765 1.00 16.50 C -ATOM 2718 CG1 VAL C 70 -18.759 18.120 4.709 1.00 19.06 C -ATOM 2719 CG2 VAL C 70 -17.623 16.139 5.358 1.00 16.14 C -ATOM 2720 N ALA C 71 -17.135 20.362 6.965 1.00 27.30 N -ATOM 2721 CA ALA C 71 -17.392 21.922 7.494 1.00 22.92 C -ATOM 2722 C ALA C 71 -16.435 22.534 6.896 1.00 25.79 C -ATOM 2723 O ALA C 71 -16.374 23.836 6.718 1.00 24.88 O -ATOM 2724 CB ALA C 71 -17.865 21.980 8.684 1.00 26.73 C -ATOM 2725 N HIS C 72 -15.134 22.254 6.980 1.00 25.11 N -ATOM 2726 CA HIS C 72 -13.948 22.613 6.662 1.00 31.54 C -ATOM 2727 C HIS C 72 -13.174 22.493 5.762 1.00 23.73 C -ATOM 2728 O HIS C 72 -11.739 22.306 5.638 1.00 26.60 O -ATOM 2729 CB HIS C 72 -12.834 22.798 8.133 1.00 34.18 C -ATOM 2730 CG HIS C 72 -13.458 23.235 9.080 1.00 46.84 C -ATOM 2731 ND1 HIS C 72 -13.546 24.937 9.646 1.00 41.84 N -ATOM 2732 CD2 HIS C 72 -14.636 22.949 10.155 1.00 36.64 C -ATOM 2733 CE1 HIS C 72 -14.088 24.896 10.559 1.00 46.81 C -ATOM 2734 NE2 HIS C 72 -14.920 23.926 11.193 1.00 49.65 N -ATOM 2735 N VAL C 73 -13.783 21.917 4.647 1.00 19.28 N -ATOM 2736 CA VAL C 73 -13.123 21.287 3.673 1.00 19.45 C -ATOM 2737 C VAL C 73 -11.827 22.122 2.987 1.00 29.84 C -ATOM 2738 O VAL C 73 -10.987 21.361 2.509 1.00 35.51 O -ATOM 2739 CB VAL C 73 -14.122 20.427 2.448 1.00 30.11 C -ATOM 2740 CG1 VAL C 73 -14.780 21.629 2.180 1.00 33.72 C -ATOM 2741 CG2 VAL C 73 -13.307 19.397 1.916 1.00 28.74 C -ATOM 2742 N ASP C 74 -12.046 23.454 3.145 1.00 28.51 N -ATOM 2743 CA ASP C 74 -10.850 24.295 2.500 1.00 28.33 C -ATOM 2744 C ASP C 74 -9.537 24.483 3.294 1.00 41.00 C -ATOM 2745 O ASP C 74 -8.999 25.130 2.953 1.00 39.68 O -ATOM 2746 CB ASP C 74 -11.641 25.551 2.038 1.00 34.16 C -ATOM 2747 CG ASP C 74 -12.636 25.691 1.138 1.00 52.11 C -ATOM 2748 OD1 ASP C 74 -12.809 24.845 -0.109 1.00 41.95 O -ATOM 2749 OD2 ASP C 74 -13.725 26.027 1.050 1.00 57.27 O -ATOM 2750 N ASP C 75 -9.900 24.071 4.497 1.00 29.36 N -ATOM 2751 CA ASP C 75 -8.638 24.283 5.628 1.00 35.73 C -ATOM 2752 C ASP C 75 -9.022 23.128 6.558 1.00 33.10 C -ATOM 2753 O ASP C 75 -8.649 23.257 7.697 1.00 33.04 O -ATOM 2754 CB ASP C 75 -9.160 25.604 6.376 1.00 60.97 C -ATOM 2755 CG ASP C 75 -8.310 26.492 7.214 1.00 66.84 C -ATOM 2756 OD1 ASP C 75 -7.090 26.471 6.833 1.00 48.92 O -ATOM 2757 OD2 ASP C 75 -9.269 26.482 8.164 1.00 62.98 O -ATOM 2758 N MET C 76 -8.644 21.799 5.775 1.00 27.58 N -ATOM 2759 CA MET C 76 -8.452 20.656 6.738 1.00 27.89 C -ATOM 2760 C MET C 76 -7.374 20.534 7.506 1.00 27.58 C -ATOM 2761 O MET C 76 -7.529 20.166 8.646 1.00 20.50 O -ATOM 2762 CB MET C 76 -8.792 19.438 5.724 1.00 26.12 C -ATOM 2763 CG MET C 76 -10.257 19.383 5.400 1.00 43.36 C -ATOM 2764 SD MET C 76 -10.271 17.473 4.652 1.00 37.03 S -ATOM 2765 CE MET C 76 -9.415 17.721 3.291 1.00 44.39 C -ATOM 2766 N PRO C 77 -6.212 20.856 6.950 1.00 20.45 N -ATOM 2767 CA PRO C 77 -5.120 20.876 8.013 1.00 25.45 C -ATOM 2768 C PRO C 77 -5.008 21.386 9.255 1.00 36.43 C -ATOM 2769 O PRO C 77 -4.686 20.931 10.357 1.00 30.57 O -ATOM 2770 CB PRO C 77 -3.910 21.274 7.011 1.00 26.13 C -ATOM 2771 CG PRO C 77 -4.232 21.298 5.608 1.00 24.41 C -ATOM 2772 CD PRO C 77 -5.794 21.507 5.765 1.00 18.39 C -ATOM 2773 N ASN C 78 -5.556 22.597 9.438 1.00 27.78 N -ATOM 2774 CA ASN C 78 -6.067 23.245 10.604 1.00 53.47 C -ATOM 2775 C ASN C 78 -6.714 22.831 11.450 1.00 25.06 C -ATOM 2776 O ASN C 78 -6.836 22.551 12.629 1.00 27.11 O -ATOM 2777 CB ASN C 78 -5.848 24.913 10.378 1.00 49.62 C -ATOM 2778 CG ASN C 78 -5.937 25.817 11.891 1.00 27.09 C -ATOM 2779 OD1 ASN C 78 -5.094 25.489 12.673 1.00 25.78 O -ATOM 2780 ND2 ASN C 78 -7.164 26.163 12.327 1.00 30.98 N -ATOM 2781 N ALA C 79 -8.038 22.510 10.822 1.00 21.32 N -ATOM 2782 CA ALA C 79 -9.063 21.943 11.591 1.00 21.47 C -ATOM 2783 C ALA C 79 -8.803 20.510 12.317 1.00 24.81 C -ATOM 2784 O ALA C 79 -9.440 20.242 13.323 1.00 25.13 O -ATOM 2785 CB ALA C 79 -10.333 21.459 10.764 1.00 25.42 C -ATOM 2786 N LEU C 80 -8.034 19.757 11.542 1.00 14.71 N -ATOM 2787 CA LEU C 80 -7.693 18.364 12.080 1.00 14.80 C -ATOM 2788 C LEU C 80 -6.147 18.320 12.632 1.00 13.69 C -ATOM 2789 O LEU C 80 -5.765 17.251 13.012 1.00 17.02 O -ATOM 2790 CB LEU C 80 -7.618 17.425 10.975 1.00 23.31 C -ATOM 2791 CG LEU C 80 -9.017 17.241 10.096 1.00 28.90 C -ATOM 2792 CD1 LEU C 80 -8.888 16.179 9.066 1.00 22.59 C -ATOM 2793 CD2 LEU C 80 -9.912 16.862 11.126 1.00 28.24 C -ATOM 2794 N SER C 81 -5.642 19.595 13.022 1.00 15.20 N -ATOM 2795 CA SER C 81 -4.176 19.598 13.532 1.00 16.69 C -ATOM 2796 C SER C 81 -4.082 18.751 14.821 1.00 15.66 C -ATOM 2797 O SER C 81 -3.121 18.036 14.913 1.00 18.30 O -ATOM 2798 CB SER C 81 -4.200 21.212 13.927 1.00 20.04 C -ATOM 2799 OG SER C 81 -2.662 21.194 13.956 1.00 27.86 O -ATOM 2800 N ALA C 82 -4.975 18.951 15.740 1.00 16.14 N -ATOM 2801 CA ALA C 82 -4.666 18.152 16.940 1.00 27.63 C -ATOM 2802 C ALA C 82 -4.666 16.766 16.844 1.00 26.48 C -ATOM 2803 O ALA C 82 -4.201 15.804 17.443 1.00 22.53 O -ATOM 2804 CB ALA C 82 -5.631 18.625 18.033 1.00 26.01 C -ATOM 2805 N LEU C 83 -5.794 16.171 15.738 1.00 16.69 N -ATOM 2806 CA LEU C 83 -5.833 14.767 15.713 1.00 11.24 C -ATOM 2807 C LEU C 83 -4.721 14.342 14.699 1.00 14.18 C -ATOM 2808 O LEU C 83 -4.218 13.107 15.018 1.00 18.82 O -ATOM 2809 CB LEU C 83 -7.049 14.621 14.641 1.00 19.57 C -ATOM 2810 CG LEU C 83 -8.323 14.343 15.598 1.00 31.08 C -ATOM 2811 CD1 LEU C 83 -9.453 13.945 14.510 1.00 37.56 C -ATOM 2812 CD2 LEU C 83 -8.174 13.408 16.783 1.00 31.25 C -ATOM 2813 N SER C 84 -4.154 15.133 13.918 1.00 17.80 N -ATOM 2814 CA SER C 84 -2.888 14.776 13.267 1.00 16.31 C -ATOM 2815 C SER C 84 -1.740 14.590 14.181 1.00 16.72 C -ATOM 2816 O SER C 84 -0.882 13.728 14.196 1.00 20.08 O -ATOM 2817 CB SER C 84 -1.928 15.701 12.069 1.00 25.74 C -ATOM 2818 OG SER C 84 -2.988 16.059 11.690 1.00 36.74 O -ATOM 2819 N ASP C 85 -1.671 15.596 15.245 1.00 14.56 N -ATOM 2820 CA ASP C 85 -0.682 15.299 16.354 1.00 16.51 C -ATOM 2821 C ASP C 85 -0.794 14.103 17.109 1.00 12.46 C -ATOM 2822 O ASP C 85 0.064 13.405 17.411 1.00 15.88 O -ATOM 2823 CB ASP C 85 -0.758 16.459 17.195 1.00 24.70 C -ATOM 2824 CG ASP C 85 -0.167 17.721 16.629 1.00 34.11 C -ATOM 2825 OD1 ASP C 85 0.446 17.900 15.796 1.00 25.15 O -ATOM 2826 OD2 ASP C 85 -0.625 18.754 17.406 1.00 33.76 O -ATOM 2827 N LEU C 86 -2.190 13.771 17.337 1.00 12.70 N -ATOM 2828 CA LEU C 86 -2.467 12.693 18.111 1.00 16.53 C -ATOM 2829 C LEU C 86 -2.015 11.303 17.695 1.00 14.13 C -ATOM 2830 O LEU C 86 -1.425 10.432 18.116 1.00 17.79 O -ATOM 2831 CB LEU C 86 -3.980 12.638 18.447 1.00 18.93 C -ATOM 2832 CG LEU C 86 -4.506 11.657 19.521 1.00 29.36 C -ATOM 2833 CD1 LEU C 86 -3.802 11.791 20.879 1.00 25.18 C -ATOM 2834 CD2 LEU C 86 -5.938 11.585 19.602 1.00 37.62 C -ATOM 2835 N HIS C 87 -2.350 11.290 16.308 1.00 15.64 N -ATOM 2836 CA HIS C 87 -2.196 9.988 15.684 1.00 15.27 C -ATOM 2837 C HIS C 87 -0.432 9.776 15.294 1.00 11.96 C -ATOM 2838 O HIS C 87 -0.010 8.655 15.509 1.00 15.54 O -ATOM 2839 CB HIS C 87 -2.877 9.761 14.248 1.00 15.31 C -ATOM 2840 CG HIS C 87 -4.370 9.569 14.496 1.00 12.16 C -ATOM 2841 ND1 HIS C 87 -5.204 10.514 14.931 1.00 15.96 N -ATOM 2842 CD2 HIS C 87 -5.162 8.339 14.571 1.00 14.58 C -ATOM 2843 CE1 HIS C 87 -6.508 9.921 15.132 1.00 13.46 C -ATOM 2844 NE2 HIS C 87 -6.403 8.796 14.850 1.00 17.27 N -ATOM 2845 N ALA C 88 0.106 11.030 15.024 1.00 14.25 N -ATOM 2846 CA ALA C 88 1.440 11.027 14.747 1.00 15.37 C -ATOM 2847 C ALA C 88 2.402 10.439 15.994 1.00 19.72 C -ATOM 2848 O ALA C 88 3.419 9.888 15.742 1.00 18.60 O -ATOM 2849 CB ALA C 88 2.009 12.263 14.095 1.00 17.41 C -ATOM 2850 N HIS C 89 2.139 11.270 17.065 1.00 17.52 N -ATOM 2851 CA HIS C 89 2.856 11.246 18.393 1.00 20.01 C -ATOM 2852 C HIS C 89 2.445 10.295 19.376 1.00 19.52 C -ATOM 2853 O HIS C 89 3.400 9.856 20.127 1.00 22.69 O -ATOM 2854 CB HIS C 89 3.204 12.750 18.766 1.00 26.82 C -ATOM 2855 CG HIS C 89 3.898 13.462 17.550 1.00 23.76 C -ATOM 2856 ND1 HIS C 89 5.028 13.110 16.879 1.00 28.14 N -ATOM 2857 CD2 HIS C 89 3.344 14.574 17.213 1.00 25.55 C -ATOM 2858 CE1 HIS C 89 4.845 14.030 16.064 1.00 32.36 C -ATOM 2859 NE2 HIS C 89 4.173 15.010 16.064 1.00 29.26 N -ATOM 2860 N LYS C 90 1.340 9.800 19.443 1.00 16.72 N -ATOM 2861 CA LYS C 90 0.718 9.223 20.440 1.00 20.32 C -ATOM 2862 C LYS C 90 0.299 7.707 20.002 1.00 20.91 C -ATOM 2863 O LYS C 90 0.862 6.631 20.320 1.00 23.22 O -ATOM 2864 CB LYS C 90 -0.138 9.844 21.447 1.00 20.81 C -ATOM 2865 CG LYS C 90 -0.560 8.580 22.285 1.00 29.14 C -ATOM 2866 CD LYS C 90 -1.751 9.734 23.205 1.00 67.74 C -ATOM 2867 CE LYS C 90 -1.793 8.441 24.607 1.00 66.29 C -ATOM 2868 NZ LYS C 90 -1.676 10.047 25.898 1.00 56.99 N -ATOM 2869 N LEU C 91 -0.852 7.689 19.140 1.00 13.37 N -ATOM 2870 CA LEU C 91 -1.388 6.384 18.683 1.00 10.47 C -ATOM 2871 C LEU C 91 -0.395 5.670 17.757 1.00 15.87 C -ATOM 2872 O LEU C 91 -0.337 4.504 17.810 1.00 17.45 O -ATOM 2873 CB LEU C 91 -2.734 6.916 18.060 1.00 11.80 C -ATOM 2874 CG LEU C 91 -3.503 7.677 18.936 1.00 14.59 C -ATOM 2875 CD1 LEU C 91 -4.817 8.063 18.135 1.00 18.31 C -ATOM 2876 CD2 LEU C 91 -3.927 6.656 20.006 1.00 19.42 C -ATOM 2877 N ARG C 92 0.163 6.386 16.757 1.00 17.30 N -ATOM 2878 CA ARG C 92 1.225 5.888 15.973 1.00 16.69 C -ATOM 2879 C ARG C 92 0.801 4.590 15.144 1.00 18.80 C -ATOM 2880 O ARG C 92 1.289 3.690 14.985 1.00 19.26 O -ATOM 2881 CB ARG C 92 2.462 5.556 16.835 1.00 13.64 C -ATOM 2882 CG ARG C 92 3.207 6.871 17.042 1.00 14.42 C -ATOM 2883 CD ARG C 92 4.320 6.680 18.089 1.00 27.16 C -ATOM 2884 NE ARG C 92 4.955 7.507 17.826 1.00 44.94 N -ATOM 2885 CZ ARG C 92 5.808 6.749 20.563 1.00 38.22 C -ATOM 2886 NH1 ARG C 92 4.053 6.376 21.084 1.00 33.94 N -ATOM 2887 NH2 ARG C 92 6.026 7.349 19.817 1.00 48.21 N -ATOM 2888 N VAL C 93 -0.511 4.844 14.546 1.00 13.36 N -ATOM 2889 CA VAL C 93 -1.122 3.790 13.672 1.00 14.31 C -ATOM 2890 C VAL C 93 -0.425 3.861 12.310 1.00 12.63 C -ATOM 2891 O VAL C 93 -0.266 4.875 11.618 1.00 14.78 O -ATOM 2892 CB VAL C 93 -2.622 4.322 13.422 1.00 8.72 C -ATOM 2893 CG1 VAL C 93 -3.298 3.413 12.409 1.00 14.83 C -ATOM 2894 CG2 VAL C 93 -3.256 4.402 14.761 1.00 15.34 C -ATOM 2895 N ASP C 94 -0.069 2.672 11.865 1.00 14.84 N -ATOM 2896 CA ASP C 94 0.516 2.634 10.645 1.00 17.19 C -ATOM 2897 C ASP C 94 -0.337 3.187 9.492 1.00 13.94 C -ATOM 2898 O ASP C 94 -1.496 2.844 9.436 1.00 13.55 O -ATOM 2899 CB ASP C 94 1.001 1.175 10.166 1.00 19.19 C -ATOM 2900 CG ASP C 94 2.066 1.114 9.015 1.00 25.98 C -ATOM 2901 OD1 ASP C 94 3.132 1.101 9.167 1.00 23.44 O -ATOM 2902 OD2 ASP C 94 1.457 1.246 7.818 1.00 20.10 O -ATOM 2903 N PRO C 95 0.336 3.997 8.656 1.00 13.43 N -ATOM 2904 CA PRO C 95 -0.533 4.680 7.482 1.00 16.10 C -ATOM 2905 C PRO C 95 -1.120 3.788 6.667 1.00 11.12 C -ATOM 2906 O PRO C 95 -2.331 4.229 6.243 1.00 14.55 O -ATOM 2907 CB PRO C 95 0.512 5.399 6.750 1.00 19.09 C -ATOM 2908 CG PRO C 95 1.437 5.610 7.677 1.00 18.28 C -ATOM 2909 CD PRO C 95 1.704 4.489 8.616 1.00 15.64 C -ATOM 2910 N VAL C 96 -0.975 2.426 6.418 1.00 15.60 N -ATOM 2911 CA VAL C 96 -1.688 1.553 5.597 1.00 13.24 C -ATOM 2912 C VAL C 96 -3.093 1.373 6.108 1.00 11.50 C -ATOM 2913 O VAL C 96 -4.125 1.168 5.337 1.00 13.19 O -ATOM 2914 CB VAL C 96 -0.963 0.166 5.595 1.00 20.64 C -ATOM 2915 CG1 VAL C 96 0.380 0.545 5.130 1.00 37.75 C -ATOM 2916 CG2 VAL C 96 -0.986 -0.723 6.614 1.00 28.85 C -ATOM 2917 N ASN C 97 -3.362 1.525 7.446 1.00 9.54 N -ATOM 2918 CA ASN C 97 -4.626 1.297 7.971 1.00 11.68 C -ATOM 2919 C ASN C 97 -5.641 2.261 7.562 1.00 9.63 C -ATOM 2920 O ASN C 97 -6.898 1.950 7.745 1.00 9.95 O -ATOM 2921 CB ASN C 97 -4.431 1.174 9.336 1.00 13.42 C -ATOM 2922 CG ASN C 97 -3.599 -0.084 9.836 1.00 14.06 C -ATOM 2923 OD1 ASN C 97 -3.997 -1.327 9.652 1.00 8.45 O -ATOM 2924 ND2 ASN C 97 -2.374 0.157 10.197 1.00 18.92 N -ATOM 2925 N PHE C 98 -5.236 3.438 7.306 1.00 11.20 N -ATOM 2926 CA PHE C 98 -6.082 4.528 6.931 1.00 10.00 C -ATOM 2927 C PHE C 98 -6.998 4.116 5.628 1.00 12.29 C -ATOM 2928 O PHE C 98 -8.203 4.405 5.580 1.00 11.85 O -ATOM 2929 CB PHE C 98 -5.520 5.917 6.784 1.00 11.84 C -ATOM 2930 CG PHE C 98 -4.966 6.392 8.161 1.00 10.85 C -ATOM 2931 CD1 PHE C 98 -5.796 7.234 8.908 1.00 20.50 C -ATOM 2932 CD2 PHE C 98 -3.900 5.913 8.688 1.00 15.66 C -ATOM 2933 CE1 PHE C 98 -5.555 7.714 10.141 1.00 25.62 C -ATOM 2934 CE2 PHE C 98 -3.735 6.528 10.021 1.00 23.17 C -ATOM 2935 CZ PHE C 98 -4.378 7.442 10.790 1.00 16.17 C -ATOM 2936 N LYS C 99 -6.268 3.417 4.783 1.00 12.40 N -ATOM 2937 CA LYS C 99 -6.999 2.958 3.593 1.00 16.89 C -ATOM 2938 C LYS C 99 -8.208 2.150 3.790 1.00 16.36 C -ATOM 2939 O LYS C 99 -9.081 1.954 3.131 1.00 12.00 O -ATOM 2940 CB LYS C 99 -5.965 2.519 2.404 1.00 37.75 C -ATOM 2941 CG LYS C 99 -5.634 1.867 2.299 1.00 60.42 C -ATOM 2942 CD LYS C 99 -4.523 1.328 0.960 1.00 80.12 C -ATOM 2943 CE LYS C 99 -5.145 -0.811 1.345 1.00 54.41 C -ATOM 2944 NZ LYS C 99 -4.072 -1.896 0.975 1.00 73.17 N -ATOM 2945 N LEU C 100 -7.771 1.248 4.812 1.00 11.58 N -ATOM 2946 CA LEU C 100 -8.668 0.083 5.298 1.00 10.08 C -ATOM 2947 C LEU C 100 -9.923 0.739 5.824 1.00 15.81 C -ATOM 2948 O LEU C 100 -11.033 0.328 5.495 1.00 12.64 O -ATOM 2949 CB LEU C 100 -7.919 -0.962 6.095 1.00 11.52 C -ATOM 2950 CG LEU C 100 -6.700 -1.456 5.659 1.00 12.29 C -ATOM 2951 CD1 LEU C 100 -6.140 -2.487 6.602 1.00 13.43 C -ATOM 2952 CD2 LEU C 100 -6.937 -2.037 4.366 1.00 20.82 C -ATOM 2953 N LEU C 101 -9.764 1.698 6.763 1.00 9.97 N -ATOM 2954 CA LEU C 101 -10.983 2.177 7.355 1.00 11.48 C -ATOM 2955 C LEU C 101 -11.756 3.062 6.216 1.00 15.63 C -ATOM 2956 O LEU C 101 -12.976 2.978 6.299 1.00 14.14 O -ATOM 2957 CB LEU C 101 -10.599 3.208 8.498 1.00 14.89 C -ATOM 2958 CG LEU C 101 -11.670 3.902 9.072 1.00 22.22 C -ATOM 2959 CD1 LEU C 101 -12.818 2.883 9.487 1.00 22.49 C -ATOM 2960 CD2 LEU C 101 -11.241 4.642 10.285 1.00 23.89 C -ATOM 2961 N SER C 102 -11.033 3.737 5.313 1.00 13.80 N -ATOM 2962 CA SER C 102 -11.714 4.605 4.376 1.00 7.27 C -ATOM 2963 C SER C 102 -12.532 3.565 3.508 1.00 8.13 C -ATOM 2964 O SER C 102 -13.716 4.048 3.196 1.00 14.48 O -ATOM 2965 CB SER C 102 -10.627 5.223 3.513 1.00 12.53 C -ATOM 2966 OG SER C 102 -9.908 6.246 4.205 1.00 16.99 O -ATOM 2967 N HIS C 103 -12.013 2.448 3.076 1.00 9.47 N -ATOM 2968 CA HIS C 103 -12.856 1.553 2.231 1.00 7.87 C -ATOM 2969 C HIS C 103 -13.969 1.179 3.005 1.00 9.96 C -ATOM 2970 O HIS C 103 -15.145 1.064 2.463 1.00 11.06 O -ATOM 2971 CB HIS C 103 -12.045 0.334 2.007 1.00 13.28 C -ATOM 2972 CG HIS C 103 -12.687 -0.723 1.251 1.00 12.69 C -ATOM 2973 ND1 HIS C 103 -12.940 -2.084 2.021 1.00 13.59 N -ATOM 2974 CD2 HIS C 103 -13.286 -0.768 0.111 1.00 11.80 C -ATOM 2975 CE1 HIS C 103 -13.607 -2.702 0.895 1.00 18.03 C -ATOM 2976 NE2 HIS C 103 -13.846 -2.052 -0.281 1.00 12.75 N -ATOM 2977 N CYS C 104 -13.956 0.809 4.281 1.00 11.32 N -ATOM 2978 CA CYS C 104 -15.102 0.402 5.220 1.00 10.36 C -ATOM 2979 C CYS C 104 -16.128 1.576 5.312 1.00 10.40 C -ATOM 2980 O CYS C 104 -17.326 1.230 5.408 1.00 13.45 O -ATOM 2981 CB CYS C 104 -14.679 -0.210 6.511 1.00 10.60 C -ATOM 2982 SG CYS C 104 -13.758 -1.766 6.256 1.00 14.84 S -ATOM 2983 N LEU C 105 -15.610 2.759 5.400 1.00 7.19 N -ATOM 2984 CA LEU C 105 -16.550 3.718 5.401 1.00 7.94 C -ATOM 2985 C LEU C 105 -17.308 3.811 4.064 1.00 12.20 C -ATOM 2986 O LEU C 105 -18.557 4.127 4.121 1.00 10.34 O -ATOM 2987 CB LEU C 105 -15.878 5.040 5.656 1.00 21.49 C -ATOM 2988 CG LEU C 105 -16.527 6.202 6.207 1.00 44.61 C -ATOM 2989 CD1 LEU C 105 -16.548 5.934 7.976 1.00 29.90 C -ATOM 2990 CD2 LEU C 105 -14.638 7.055 6.645 1.00 67.41 C -ATOM 2991 N LEU C 106 -16.563 3.801 3.055 1.00 12.01 N -ATOM 2992 CA LEU C 106 -17.399 3.653 1.720 1.00 11.59 C -ATOM 2993 C LEU C 106 -18.331 2.701 1.716 1.00 13.18 C -ATOM 2994 O LEU C 106 -19.445 3.007 1.174 1.00 13.67 O -ATOM 2995 CB LEU C 106 -16.393 3.784 0.463 1.00 15.01 C -ATOM 2996 CG LEU C 106 -15.665 4.920 0.043 1.00 26.98 C -ATOM 2997 CD1 LEU C 106 -14.786 4.477 -0.938 1.00 27.15 C -ATOM 2998 CD2 LEU C 106 -16.427 6.222 -0.197 1.00 28.82 C -ATOM 2999 N VAL C 107 -18.135 1.497 2.015 1.00 9.69 N -ATOM 3000 CA VAL C 107 -18.836 0.268 2.127 1.00 13.59 C -ATOM 3001 C VAL C 107 -20.197 0.605 2.883 1.00 17.84 C -ATOM 3002 O VAL C 107 -21.451 0.519 2.577 1.00 16.17 O -ATOM 3003 CB VAL C 107 -18.247 -1.024 2.534 1.00 6.66 C -ATOM 3004 CG1 VAL C 107 -19.313 -1.975 2.757 1.00 10.41 C -ATOM 3005 CG2 VAL C 107 -17.243 -1.377 1.493 1.00 9.95 C -ATOM 3006 N THR C 108 -20.022 1.317 4.069 1.00 12.50 N -ATOM 3007 CA THR C 108 -21.156 1.586 4.961 1.00 12.00 C -ATOM 3008 C THR C 108 -22.004 2.672 4.235 1.00 8.53 C -ATOM 3009 O THR C 108 -23.266 2.600 4.430 1.00 13.95 O -ATOM 3010 CB THR C 108 -20.489 2.175 6.313 1.00 10.15 C -ATOM 3011 OG1 THR C 108 -19.618 1.211 6.782 1.00 10.65 O -ATOM 3012 CG2 THR C 108 -21.574 2.581 7.303 1.00 9.30 C -ATOM 3013 N LEU C 109 -21.432 3.696 3.675 1.00 9.01 N -ATOM 3014 CA LEU C 109 -22.256 4.765 2.941 1.00 9.31 C -ATOM 3015 C LEU C 109 -23.120 4.001 2.078 1.00 15.85 C -ATOM 3016 O LEU C 109 -24.157 4.405 1.752 1.00 14.26 O -ATOM 3017 CB LEU C 109 -21.296 5.848 2.566 1.00 11.02 C -ATOM 3018 CG LEU C 109 -20.716 6.843 3.619 1.00 19.91 C -ATOM 3019 CD1 LEU C 109 -19.558 7.677 2.954 1.00 29.96 C -ATOM 3020 CD2 LEU C 109 -21.630 7.225 4.484 1.00 27.29 C -ATOM 3021 N ALA C 110 -22.355 3.185 1.097 1.00 14.51 N -ATOM 3022 CA ALA C 110 -22.975 2.438 -0.100 1.00 13.69 C -ATOM 3023 C ALA C 110 -24.179 1.916 0.467 1.00 24.66 C -ATOM 3024 O ALA C 110 -25.339 1.691 -0.205 1.00 18.31 O -ATOM 3025 CB ALA C 110 -21.958 1.541 -0.721 1.00 13.14 C -ATOM 3026 N ALA C 111 -24.108 1.069 1.636 1.00 17.30 N -ATOM 3027 CA ALA C 111 -25.131 0.205 2.227 1.00 14.98 C -ATOM 3028 C ALA C 111 -26.406 1.141 2.649 1.00 17.59 C -ATOM 3029 O ALA C 111 -27.374 0.392 2.964 1.00 18.70 O -ATOM 3030 CB ALA C 111 -24.528 -0.603 3.334 1.00 14.01 C -ATOM 3031 N HIS C 112 -26.145 2.311 3.092 1.00 17.57 N -ATOM 3032 CA HIS C 112 -27.157 3.218 3.684 1.00 17.81 C -ATOM 3033 C HIS C 112 -27.592 4.143 2.662 1.00 23.35 C -ATOM 3034 O HIS C 112 -28.643 4.846 3.027 1.00 25.70 O -ATOM 3035 CB HIS C 112 -26.632 3.907 4.985 1.00 19.09 C -ATOM 3036 CG HIS C 112 -26.731 2.953 5.878 1.00 25.33 C -ATOM 3037 ND1 HIS C 112 -25.315 2.095 6.535 1.00 35.05 N -ATOM 3038 CD2 HIS C 112 -27.507 2.446 6.914 1.00 26.57 C -ATOM 3039 CE1 HIS C 112 -25.696 1.397 7.484 1.00 18.65 C -ATOM 3040 NE2 HIS C 112 -27.041 1.550 7.786 1.00 32.92 N -ATOM 3041 N LEU C 113 -27.112 4.669 1.736 1.00 23.20 N -ATOM 3042 CA LEU C 113 -27.336 5.646 0.694 1.00 19.73 C -ATOM 3043 C LEU C 113 -27.527 4.917 -0.780 1.00 24.44 C -ATOM 3044 O LEU C 113 -26.931 5.709 -1.436 1.00 27.49 O -ATOM 3045 CB LEU C 113 -26.346 6.534 0.722 1.00 30.36 C -ATOM 3046 CG LEU C 113 -26.291 7.305 1.871 1.00 29.78 C -ATOM 3047 CD1 LEU C 113 -24.949 8.197 1.187 1.00 35.69 C -ATOM 3048 CD2 LEU C 113 -27.165 7.743 2.593 1.00 47.79 C -ATOM 3049 N PRO C 114 -28.533 4.269 -1.071 1.00 23.63 N -ATOM 3050 CA PRO C 114 -28.972 3.222 -2.364 1.00 26.62 C -ATOM 3051 C PRO C 114 -29.185 4.694 -3.555 1.00 35.32 C -ATOM 3052 O PRO C 114 -28.033 5.030 -4.238 1.00 38.93 O -ATOM 3053 CB PRO C 114 -29.692 2.344 -1.692 1.00 32.82 C -ATOM 3054 CG PRO C 114 -30.705 3.466 -1.031 1.00 48.45 C -ATOM 3055 CD PRO C 114 -29.572 3.964 0.093 1.00 44.41 C -ATOM 3056 N ALA C 115 -29.614 5.816 -3.110 1.00 34.13 N -ATOM 3057 CA ALA C 115 -29.733 6.788 -3.943 1.00 25.13 C -ATOM 3058 C ALA C 115 -28.814 7.547 -4.176 1.00 23.70 C -ATOM 3059 O ALA C 115 -28.484 8.189 -5.293 1.00 28.59 O -ATOM 3060 CB ALA C 115 -31.178 7.688 -4.040 1.00 49.66 C -ATOM 3061 N GLU C 116 -27.955 7.979 -3.256 1.00 19.87 N -ATOM 3062 CA GLU C 116 -26.996 9.192 -3.337 1.00 15.46 C -ATOM 3063 C GLU C 116 -25.546 8.615 -3.591 1.00 17.63 C -ATOM 3064 O GLU C 116 -24.903 9.456 -4.305 1.00 21.65 O -ATOM 3065 CB GLU C 116 -26.603 9.453 -1.769 1.00 24.21 C -ATOM 3066 CG GLU C 116 -28.465 8.862 -0.493 1.00 64.07 C -ATOM 3067 CD GLU C 116 -28.940 10.160 -0.964 1.00 64.09 C -ATOM 3068 OE1 GLU C 116 -28.783 10.922 -1.780 1.00 59.54 O -ATOM 3069 OE2 GLU C 116 -30.228 9.634 -0.550 1.00 58.51 O -ATOM 3070 N PHE C 117 -25.343 7.424 -3.452 1.00 18.06 N -ATOM 3071 CA PHE C 117 -24.055 6.750 -3.919 1.00 15.96 C -ATOM 3072 C PHE C 117 -23.837 6.451 -5.366 1.00 17.62 C -ATOM 3073 O PHE C 117 -23.697 5.333 -5.682 1.00 20.40 O -ATOM 3074 CB PHE C 117 -23.795 5.597 -3.019 1.00 11.69 C -ATOM 3075 CG PHE C 117 -22.482 5.073 -2.755 1.00 15.94 C -ATOM 3076 CD1 PHE C 117 -21.516 5.939 -2.024 1.00 20.23 C -ATOM 3077 CD2 PHE C 117 -21.879 3.939 -3.352 1.00 18.29 C -ATOM 3078 CE1 PHE C 117 -20.010 5.429 -1.856 1.00 21.74 C -ATOM 3079 CE2 PHE C 117 -20.499 3.543 -3.388 1.00 15.69 C -ATOM 3080 CZ PHE C 117 -19.734 4.357 -2.542 1.00 19.08 C -ATOM 3081 N THR C 118 -23.888 7.554 -6.187 1.00 16.36 N -ATOM 3082 CA THR C 118 -23.750 7.200 -7.579 1.00 24.73 C -ATOM 3083 C THR C 118 -22.162 7.085 -7.979 1.00 20.24 C -ATOM 3084 O THR C 118 -21.404 7.258 -6.938 1.00 17.57 O -ATOM 3085 CB THR C 118 -23.989 8.809 -8.229 1.00 24.50 C -ATOM 3086 OG1 THR C 118 -25.423 9.053 -8.024 1.00 43.24 O -ATOM 3087 CG2 THR C 118 -23.399 9.727 -8.021 1.00 20.86 C -ATOM 3088 N PRO C 119 -21.965 6.771 -8.980 1.00 16.01 N -ATOM 3089 CA PRO C 119 -20.523 6.700 -9.434 1.00 19.05 C -ATOM 3090 C PRO C 119 -19.780 7.932 -9.012 1.00 19.72 C -ATOM 3091 O PRO C 119 -18.600 7.893 -8.606 1.00 14.74 O -ATOM 3092 CB PRO C 119 -20.464 6.235 -10.815 1.00 21.12 C -ATOM 3093 CG PRO C 119 -21.872 5.425 -11.078 1.00 19.58 C -ATOM 3094 CD PRO C 119 -22.940 6.131 -10.122 1.00 19.86 C -ATOM 3095 N ALA C 120 -20.252 9.094 -9.502 1.00 19.86 N -ATOM 3096 CA ALA C 120 -19.548 10.276 -9.334 1.00 18.74 C -ATOM 3097 C ALA C 120 -19.388 10.637 -7.832 1.00 10.87 C -ATOM 3098 O ALA C 120 -18.248 11.251 -7.450 1.00 14.38 O -ATOM 3099 CB ALA C 120 -20.260 11.491 -9.979 1.00 23.51 C -ATOM 3100 N VAL C 121 -20.385 10.350 -7.040 1.00 15.38 N -ATOM 3101 CA VAL C 121 -20.425 10.526 -5.562 1.00 17.86 C -ATOM 3102 C VAL C 121 -19.282 9.640 -4.960 1.00 13.56 C -ATOM 3103 O VAL C 121 -18.551 10.181 -4.182 1.00 14.98 O -ATOM 3104 CB VAL C 121 -21.712 10.598 -4.961 1.00 16.82 C -ATOM 3105 CG1 VAL C 121 -21.586 10.574 -3.474 1.00 15.23 C -ATOM 3106 CG2 VAL C 121 -22.399 11.837 -5.508 1.00 18.21 C -ATOM 3107 N HIS C 122 -19.274 8.429 -5.423 1.00 13.62 N -ATOM 3108 CA HIS C 122 -18.258 7.352 -4.974 1.00 13.41 C -ATOM 3109 C HIS C 122 -16.927 7.953 -5.183 1.00 19.70 C -ATOM 3110 O HIS C 122 -16.069 7.929 -4.270 1.00 15.94 O -ATOM 3111 CB HIS C 122 -18.661 6.175 -5.608 1.00 13.44 C -ATOM 3112 CG HIS C 122 -17.896 4.996 -5.506 1.00 11.42 C -ATOM 3113 ND1 HIS C 122 -18.152 3.694 -5.975 1.00 16.43 N -ATOM 3114 CD2 HIS C 122 -16.677 4.952 -4.678 1.00 17.04 C -ATOM 3115 CE1 HIS C 122 -17.175 2.906 -5.621 1.00 20.17 C -ATOM 3116 NE2 HIS C 122 -16.333 3.490 -4.734 1.00 16.87 N -ATOM 3117 N ALA C 123 -16.663 8.527 -6.359 1.00 13.94 N -ATOM 3118 CA ALA C 123 -15.263 8.979 -6.644 1.00 17.63 C -ATOM 3119 C ALA C 123 -14.878 10.124 -5.801 1.00 15.63 C -ATOM 3120 O ALA C 123 -13.855 10.169 -5.195 1.00 16.32 O -ATOM 3121 CB ALA C 123 -15.304 9.355 -8.200 1.00 21.15 C -ATOM 3122 N SER C 124 -15.845 11.044 -5.588 1.00 11.75 N -ATOM 3123 CA SER C 124 -15.443 12.245 -4.719 1.00 15.01 C -ATOM 3124 C SER C 124 -15.332 11.744 -3.177 1.00 15.67 C -ATOM 3125 O SER C 124 -14.471 12.374 -2.655 1.00 13.45 O -ATOM 3126 CB SER C 124 -16.754 13.206 -4.754 1.00 14.78 C -ATOM 3127 OG SER C 124 -17.033 13.770 -6.107 1.00 17.64 O -ATOM 3128 N LEU C 125 -16.158 10.923 -2.823 1.00 10.43 N -ATOM 3129 CA LEU C 125 -15.983 10.431 -1.427 1.00 12.66 C -ATOM 3130 C LEU C 125 -14.705 9.708 -1.135 1.00 12.01 C -ATOM 3131 O LEU C 125 -13.873 9.973 -0.196 1.00 10.58 O -ATOM 3132 CB LEU C 125 -17.093 9.515 -1.060 1.00 10.32 C -ATOM 3133 CG LEU C 125 -18.393 10.264 -0.600 1.00 16.01 C -ATOM 3134 CD1 LEU C 125 -19.493 9.231 -0.642 1.00 21.31 C -ATOM 3135 CD2 LEU C 125 -18.244 11.194 0.645 1.00 19.17 C -ATOM 3136 N ASP C 126 -14.179 8.973 -2.132 1.00 15.23 N -ATOM 3137 CA ASP C 126 -12.896 8.220 -2.060 1.00 15.01 C -ATOM 3138 C ASP C 126 -11.877 9.262 -2.029 1.00 17.34 C -ATOM 3139 O ASP C 126 -10.873 9.161 -1.311 1.00 17.16 O -ATOM 3140 CB ASP C 126 -12.829 7.258 -3.164 1.00 14.23 C -ATOM 3141 CG ASP C 126 -11.630 6.072 -2.962 1.00 15.33 C -ATOM 3142 OD1 ASP C 126 -11.594 5.816 -1.849 1.00 21.18 O -ATOM 3143 OD2 ASP C 126 -10.723 6.195 -3.670 1.00 18.49 O -ATOM 3144 N LYS C 127 -11.889 10.369 -2.865 1.00 10.51 N -ATOM 3145 CA LYS C 127 -10.843 11.346 -2.937 1.00 9.26 C -ATOM 3146 C LYS C 127 -10.985 12.090 -1.550 1.00 10.60 C -ATOM 3147 O LYS C 127 -9.736 12.501 -1.011 1.00 13.38 O -ATOM 3148 CB LYS C 127 -11.128 12.473 -4.012 1.00 12.57 C -ATOM 3149 CG LYS C 127 -10.837 11.844 -5.259 1.00 21.03 C -ATOM 3150 CD LYS C 127 -11.084 12.905 -6.433 1.00 27.03 C -ATOM 3151 CE LYS C 127 -10.200 14.180 -6.287 1.00 36.89 C -ATOM 3152 NZ LYS C 127 -10.401 15.128 -7.495 1.00 25.75 N -ATOM 3153 N PHE C 128 -12.089 12.351 -1.096 1.00 12.44 N -ATOM 3154 CA PHE C 128 -12.150 13.112 0.060 1.00 14.73 C -ATOM 3155 C PHE C 128 -11.573 12.159 1.379 1.00 19.70 C -ATOM 3156 O PHE C 128 -10.742 12.890 2.141 1.00 15.58 O -ATOM 3157 CB PHE C 128 -13.559 13.504 0.502 1.00 11.17 C -ATOM 3158 CG PHE C 128 -13.873 13.981 2.080 1.00 11.86 C -ATOM 3159 CD1 PHE C 128 -13.416 15.303 2.300 1.00 15.77 C -ATOM 3160 CD2 PHE C 128 -14.468 13.060 2.611 1.00 23.89 C -ATOM 3161 CE1 PHE C 128 -13.803 15.496 3.630 1.00 14.00 C -ATOM 3162 CE2 PHE C 128 -14.618 13.544 4.103 1.00 26.48 C -ATOM 3163 CZ PHE C 128 -14.347 14.715 4.443 1.00 15.47 C -ATOM 3164 N LEU C 129 -11.958 10.929 1.410 1.00 14.00 N -ATOM 3165 CA LEU C 129 -11.373 10.116 2.580 1.00 13.04 C -ATOM 3166 C LEU C 129 -9.834 9.957 2.377 1.00 17.30 C -ATOM 3167 O LEU C 129 -8.955 10.001 3.360 1.00 14.75 O -ATOM 3168 CB LEU C 129 -11.850 8.796 2.608 1.00 12.12 C -ATOM 3169 CG LEU C 129 -13.240 8.898 3.000 1.00 20.92 C -ATOM 3170 CD1 LEU C 129 -14.044 7.674 2.880 1.00 26.64 C -ATOM 3171 CD2 LEU C 129 -13.522 9.300 4.355 1.00 35.02 C -ATOM 3172 N ALA C 130 -9.238 9.941 1.192 1.00 16.20 N -ATOM 3173 CA ALA C 130 -7.860 10.006 0.893 1.00 14.56 C -ATOM 3174 C ALA C 130 -7.216 11.214 1.438 1.00 19.27 C -ATOM 3175 O ALA C 130 -5.982 11.322 1.999 1.00 14.14 O -ATOM 3176 CB ALA C 130 -7.442 9.870 -0.423 1.00 17.10 C -ATOM 3177 N SER C 131 -7.839 12.284 1.109 1.00 18.74 N -ATOM 3178 CA SER C 131 -7.158 13.685 1.577 1.00 19.45 C -ATOM 3179 C SER C 131 -7.424 13.831 3.307 1.00 14.53 C -ATOM 3180 O SER C 131 -6.317 14.261 3.681 1.00 12.58 O -ATOM 3181 CB SER C 131 -8.220 14.954 1.086 1.00 22.90 C -ATOM 3182 OG SER C 131 -8.002 14.782 -0.395 1.00 37.64 O -ATOM 3183 N VAL C 132 -8.436 13.257 3.800 1.00 12.03 N -ATOM 3184 CA VAL C 132 -8.508 13.199 5.238 1.00 13.41 C -ATOM 3185 C VAL C 132 -7.272 12.425 5.809 1.00 19.42 C -ATOM 3186 O VAL C 132 -6.491 12.809 6.794 1.00 14.00 O -ATOM 3187 CB VAL C 132 -9.726 12.697 5.713 1.00 15.91 C -ATOM 3188 CG1 VAL C 132 -9.619 12.379 7.255 1.00 17.14 C -ATOM 3189 CG2 VAL C 132 -11.022 13.817 5.553 1.00 19.41 C -ATOM 3190 N SER C 133 -7.133 11.157 5.180 1.00 14.01 N -ATOM 3191 CA SER C 133 -6.066 10.266 5.421 1.00 13.12 C -ATOM 3192 C SER C 133 -4.733 10.965 5.281 1.00 21.83 C -ATOM 3193 O SER C 133 -3.772 10.686 6.325 1.00 18.12 O -ATOM 3194 CB SER C 133 -5.938 8.996 4.603 1.00 13.61 C -ATOM 3195 OG SER C 133 -7.161 8.346 5.111 1.00 18.98 O -ATOM 3196 N THR C 134 -4.427 11.617 4.350 1.00 17.53 N -ATOM 3197 CA THR C 134 -3.144 12.409 4.136 1.00 15.95 C -ATOM 3198 C THR C 134 -2.914 13.473 5.177 1.00 16.97 C -ATOM 3199 O THR C 134 -1.750 13.477 5.831 1.00 20.39 O -ATOM 3200 CB THR C 134 -3.269 13.086 2.683 1.00 18.28 C -ATOM 3201 OG1 THR C 134 -3.148 12.134 1.784 1.00 22.72 O -ATOM 3202 CG2 THR C 134 -2.059 13.978 2.401 1.00 22.70 C -ATOM 3203 N VAL C 135 -3.965 14.094 5.504 1.00 15.13 N -ATOM 3204 CA VAL C 135 -3.754 15.191 6.579 1.00 16.51 C -ATOM 3205 C VAL C 135 -3.260 14.323 7.873 1.00 16.40 C -ATOM 3206 O VAL C 135 -2.487 14.902 8.617 1.00 15.94 O -ATOM 3207 CB VAL C 135 -5.059 16.100 6.780 1.00 18.21 C -ATOM 3208 CG1 VAL C 135 -5.021 16.981 8.022 1.00 17.40 C -ATOM 3209 CG2 VAL C 135 -5.230 16.888 5.569 1.00 19.71 C -ATOM 3210 N LEU C 136 -4.222 13.312 8.307 1.00 12.10 N -ATOM 3211 CA LEU C 136 -4.023 12.675 9.630 1.00 15.98 C -ATOM 3212 C LEU C 136 -2.564 12.099 9.666 1.00 16.04 C -ATOM 3213 O LEU C 136 -2.112 11.725 10.867 1.00 16.42 O -ATOM 3214 CB LEU C 136 -5.060 11.690 9.725 1.00 16.86 C -ATOM 3215 CG LEU C 136 -6.464 12.340 9.949 1.00 24.99 C -ATOM 3216 CD1 LEU C 136 -7.273 11.133 10.442 1.00 18.69 C -ATOM 3217 CD2 LEU C 136 -6.479 13.221 11.104 1.00 43.05 C -ATOM 3218 N THR C 137 -1.948 11.875 8.493 1.00 14.30 N -ATOM 3219 CA THR C 137 -0.644 11.078 8.570 1.00 16.72 C -ATOM 3220 C THR C 137 0.600 12.250 8.229 1.00 20.27 C -ATOM 3221 O THR C 137 1.641 11.779 8.219 1.00 19.99 O -ATOM 3222 CB THR C 137 -0.616 9.898 7.452 1.00 21.82 C -ATOM 3223 OG1 THR C 137 -0.747 10.397 6.348 1.00 20.00 O -ATOM 3224 CG2 THR C 137 -1.429 8.802 8.131 1.00 20.00 C -ATOM 3225 N SER C 138 0.217 13.432 7.965 1.00 21.45 N -ATOM 3226 CA SER C 138 1.195 14.450 7.576 1.00 24.00 C -ATOM 3227 C SER C 138 2.427 14.664 8.641 1.00 26.98 C -ATOM 3228 O SER C 138 3.195 15.345 8.032 1.00 21.99 O -ATOM 3229 CB SER C 138 0.001 16.139 8.122 1.00 21.69 C -ATOM 3230 OG SER C 138 0.377 15.823 6.927 1.00 42.20 O -ATOM 3231 N LYS C 139 2.133 14.403 9.912 1.00 22.73 N -ATOM 3232 CA LYS C 139 3.191 14.934 10.883 1.00 27.59 C -ATOM 3233 C LYS C 139 3.975 13.581 11.372 1.00 19.22 C -ATOM 3234 O LYS C 139 4.646 13.643 12.389 1.00 14.35 O -ATOM 3235 CB LYS C 139 2.358 15.487 11.974 1.00 19.55 C -ATOM 3236 CG LYS C 139 2.071 17.001 11.340 1.00 22.79 C -ATOM 3237 CD LYS C 139 1.307 17.445 12.283 1.00 42.21 C -ATOM 3238 CE LYS C 139 1.086 19.324 11.798 1.00 36.26 C -ATOM 3239 NZ LYS C 139 -0.244 18.940 13.010 1.00 30.87 N -ATOM 3240 N TYR C 140 3.750 12.465 10.738 1.00 18.17 N -ATOM 3241 CA TYR C 140 4.409 11.291 11.242 1.00 17.49 C -ATOM 3242 C TYR C 140 5.879 11.300 11.241 1.00 19.10 C -ATOM 3243 O TYR C 140 6.366 10.507 12.197 1.00 22.35 O -ATOM 3244 CB TYR C 140 3.865 10.055 10.357 1.00 16.87 C -ATOM 3245 CG TYR C 140 2.674 9.300 10.891 1.00 12.61 C -ATOM 3246 CD1 TYR C 140 2.521 8.093 11.003 1.00 19.13 C -ATOM 3247 CD2 TYR C 140 1.410 10.025 11.225 1.00 16.63 C -ATOM 3248 CE1 TYR C 140 1.365 7.496 11.459 1.00 21.26 C -ATOM 3249 CE2 TYR C 140 0.269 9.420 11.748 1.00 17.45 C -ATOM 3250 CZ TYR C 140 0.153 8.203 11.775 1.00 14.84 C -ATOM 3251 OH TYR C 140 -0.838 7.429 12.277 1.00 15.53 O -ATOM 3252 N ARG C 141 6.450 11.994 10.246 1.00 20.34 N -ATOM 3253 CA ARG C 141 7.886 11.986 10.168 1.00 25.59 C -ATOM 3254 C ARG C 141 8.484 13.451 9.626 1.00 21.46 C -ATOM 3255 O ARG C 141 7.587 13.891 9.012 1.00 24.60 O -ATOM 3256 CB ARG C 141 8.511 10.698 9.627 1.00 27.67 C -ATOM 3257 CG ARG C 141 8.124 10.586 8.132 1.00 20.44 C -ATOM 3258 CD ARG C 141 8.972 9.192 7.851 1.00 27.35 C -ATOM 3259 NE ARG C 141 8.521 8.970 6.409 1.00 21.57 N -ATOM 3260 CZ ARG C 141 9.349 8.234 5.557 1.00 17.72 C -ATOM 3261 NH1 ARG C 141 10.182 7.400 5.980 1.00 16.11 N -ATOM 3262 NH2 ARG C 141 8.583 8.168 4.338 1.00 19.55 N -ATOM 3263 OXT ARG C 141 9.695 13.488 9.645 1.00 22.97 O -TER 3264 ARG C 141 -ATOM 3265 N VAL D 1 -8.916 -20.986 -1.208 1.00 44.53 N -ATOM 3266 CA VAL D 1 -8.728 -19.973 0.230 1.00 40.54 C -ATOM 3267 C VAL D 1 -9.597 -21.119 1.649 1.00 54.57 C -ATOM 3268 O VAL D 1 -10.511 -21.747 0.927 1.00 46.03 O -ATOM 3269 CB VAL D 1 -9.741 -18.620 0.365 1.00 59.62 C -ATOM 3270 CG1 VAL D 1 -8.976 -17.356 -0.533 1.00 56.25 C -ATOM 3271 CG2 VAL D 1 -10.766 -18.689 -0.199 1.00 44.49 C -ATOM 3272 N HIS D 2 -9.359 -20.204 2.359 1.00 54.55 N -ATOM 3273 CA HIS D 2 -10.028 -20.478 3.617 1.00 76.16 C -ATOM 3274 C HIS D 2 -11.503 -19.997 4.189 1.00 40.79 C -ATOM 3275 O HIS D 2 -10.949 -18.900 5.117 1.00 42.23 O -ATOM 3276 CB HIS D 2 -8.550 -21.746 4.671 1.00 61.25 C -ATOM 3277 CG HIS D 2 -9.111 -22.384 5.289 1.00 73.35 C -ATOM 3278 ND1 HIS D 2 -9.292 -20.744 7.139 1.00 63.32 N -ATOM 3279 CD2 HIS D 2 -10.298 -23.586 6.052 1.00 68.03 C -ATOM 3280 CE1 HIS D 2 -10.663 -21.227 8.362 1.00 55.48 C -ATOM 3281 NE2 HIS D 2 -10.906 -22.743 7.235 1.00 54.14 N -ATOM 3282 N LEU D 3 -12.538 -20.903 4.013 1.00 31.51 N -ATOM 3283 CA LEU D 3 -13.638 -20.047 4.223 1.00 32.74 C -ATOM 3284 C LEU D 3 -13.624 -20.741 5.723 1.00 43.55 C -ATOM 3285 O LEU D 3 -14.592 -22.168 5.344 1.00 38.09 O -ATOM 3286 CB LEU D 3 -14.958 -19.886 3.451 1.00 39.97 C -ATOM 3287 CG LEU D 3 -14.306 -18.748 2.457 1.00 33.25 C -ATOM 3288 CD1 LEU D 3 -15.545 -18.399 1.653 1.00 35.36 C -ATOM 3289 CD2 LEU D 3 -14.311 -17.477 2.906 1.00 43.98 C -ATOM 3290 N THR D 4 -14.873 -20.575 6.573 1.00 40.52 N -ATOM 3291 CA THR D 4 -15.571 -21.118 7.446 1.00 35.01 C -ATOM 3292 C THR D 4 -16.965 -21.835 7.057 1.00 36.50 C -ATOM 3293 O THR D 4 -17.217 -21.032 5.924 1.00 26.93 O -ATOM 3294 CB THR D 4 -15.866 -20.187 8.979 1.00 42.32 C -ATOM 3295 OG1 THR D 4 -16.874 -19.360 8.569 1.00 35.61 O -ATOM 3296 CG2 THR D 4 -14.805 -19.826 9.491 1.00 41.74 C -ATOM 3297 N PRO D 5 -17.421 -22.638 7.348 1.00 38.01 N -ATOM 3298 CA PRO D 5 -18.819 -22.801 6.165 1.00 45.26 C -ATOM 3299 C PRO D 5 -19.967 -21.905 6.477 1.00 40.88 C -ATOM 3300 O PRO D 5 -20.833 -21.591 5.783 1.00 35.71 O -ATOM 3301 CB PRO D 5 -19.489 -24.074 7.971 1.00 80.12 C -ATOM 3302 CG PRO D 5 -18.622 -24.429 8.450 1.00 36.53 C -ATOM 3303 CD PRO D 5 -17.099 -23.867 8.283 1.00 38.83 C -ATOM 3304 N GLU D 6 -19.807 -20.993 7.524 1.00 38.95 N -ATOM 3305 CA GLU D 6 -20.826 -20.251 7.892 1.00 54.36 C -ATOM 3306 C GLU D 6 -20.257 -18.491 6.516 1.00 29.53 C -ATOM 3307 O GLU D 6 -21.186 -18.231 6.189 1.00 34.33 O -ATOM 3308 CB GLU D 6 -20.808 -19.128 9.200 1.00 67.37 C -ATOM 3309 CG GLU D 6 -20.143 -19.295 9.841 1.00 68.32 C -ATOM 3310 CD GLU D 6 -19.833 -20.908 10.929 1.00 80.07 C -ATOM 3311 OE1 GLU D 6 -19.263 -21.552 10.554 1.00 62.33 O -ATOM 3312 OE2 GLU D 6 -17.422 -20.947 9.979 1.00 75.27 O -ATOM 3313 N GLU D 7 -19.046 -18.647 6.494 1.00 32.30 N -ATOM 3314 CA GLU D 7 -18.571 -17.615 5.450 1.00 26.92 C -ATOM 3315 C GLU D 7 -19.016 -18.399 3.955 1.00 36.61 C -ATOM 3316 O GLU D 7 -19.572 -17.530 3.297 1.00 31.61 O -ATOM 3317 CB GLU D 7 -17.035 -17.606 5.380 1.00 22.74 C -ATOM 3318 CG GLU D 7 -16.644 -16.558 6.886 1.00 25.68 C -ATOM 3319 CD GLU D 7 -15.325 -16.832 6.956 1.00 21.07 C -ATOM 3320 OE1 GLU D 7 -14.977 -15.445 7.269 1.00 41.17 O -ATOM 3321 OE2 GLU D 7 -14.302 -17.526 6.337 1.00 26.19 O -ATOM 3322 N LYS D 8 -18.754 -19.547 3.890 1.00 24.35 N -ATOM 3323 CA LYS D 8 -19.098 -20.158 2.364 1.00 27.18 C -ATOM 3324 C LYS D 8 -20.384 -20.203 2.052 1.00 23.43 C -ATOM 3325 O LYS D 8 -21.074 -19.662 1.178 1.00 23.08 O -ATOM 3326 CB LYS D 8 -18.527 -21.857 2.829 1.00 28.41 C -ATOM 3327 CG LYS D 8 -18.698 -21.991 1.053 1.00 48.31 C -ATOM 3328 CD LYS D 8 -18.147 -23.072 0.880 1.00 69.34 C -ATOM 3329 CE LYS D 8 -18.957 -23.705 -0.872 1.00 38.29 C -ATOM 3330 NZ LYS D 8 -17.931 -25.269 -1.374 1.00 72.55 N -ATOM 3331 N SER D 9 -21.307 -20.301 3.110 1.00 21.45 N -ATOM 3332 CA SER D 9 -22.632 -20.010 2.800 1.00 23.49 C -ATOM 3333 C SER D 9 -23.050 -18.608 2.651 1.00 32.73 C -ATOM 3334 O SER D 9 -24.111 -18.558 1.973 1.00 27.24 O -ATOM 3335 CB SER D 9 -23.425 -20.879 3.815 1.00 48.80 C -ATOM 3336 OG SER D 9 -24.248 -20.636 4.597 1.00 54.12 O -ATOM 3337 N ALA D 10 -22.340 -17.847 3.521 1.00 26.97 N -ATOM 3338 CA ALA D 10 -23.067 -16.421 3.397 1.00 27.01 C -ATOM 3339 C ALA D 10 -22.551 -15.974 1.781 1.00 23.29 C -ATOM 3340 O ALA D 10 -23.475 -15.280 1.185 1.00 20.87 O -ATOM 3341 CB ALA D 10 -22.056 -15.660 3.934 1.00 28.42 C -ATOM 3342 N VAL D 11 -21.472 -16.449 1.276 1.00 31.33 N -ATOM 3343 CA VAL D 11 -21.016 -15.993 -0.163 1.00 25.10 C -ATOM 3344 C VAL D 11 -21.923 -16.557 -1.184 1.00 18.64 C -ATOM 3345 O VAL D 11 -22.347 -15.774 -1.949 1.00 19.73 O -ATOM 3346 CB VAL D 11 -19.580 -16.599 -0.312 1.00 18.52 C -ATOM 3347 CG1 VAL D 11 -19.332 -16.430 -1.555 1.00 28.45 C -ATOM 3348 CG2 VAL D 11 -18.563 -15.544 0.540 1.00 21.05 C -ATOM 3349 N THR D 12 -22.095 -17.881 -0.865 1.00 19.99 N -ATOM 3350 CA THR D 12 -23.012 -18.659 -2.043 1.00 26.25 C -ATOM 3351 C THR D 12 -24.298 -18.196 -1.973 1.00 24.29 C -ATOM 3352 O THR D 12 -25.087 -17.804 -3.054 1.00 26.52 O -ATOM 3353 CB THR D 12 -23.024 -20.432 -1.285 1.00 24.72 C -ATOM 3354 OG1 THR D 12 -21.642 -20.629 -1.920 1.00 32.38 O -ATOM 3355 CG2 THR D 12 -24.127 -20.769 -2.067 1.00 56.05 C -ATOM 3356 N ALA D 13 -24.939 -17.863 -0.966 1.00 25.46 N -ATOM 3357 CA ALA D 13 -26.249 -17.368 -0.697 1.00 25.21 C -ATOM 3358 C ALA D 13 -26.716 -16.016 -1.505 1.00 24.39 C -ATOM 3359 O ALA D 13 -27.502 -15.783 -2.239 1.00 27.12 O -ATOM 3360 CB ALA D 13 -26.840 -17.284 0.237 1.00 40.91 C -ATOM 3361 N LEU D 14 -25.588 -15.038 -1.202 1.00 21.51 N -ATOM 3362 CA LEU D 14 -25.805 -13.895 -1.844 1.00 19.28 C -ATOM 3363 C LEU D 14 -25.557 -13.900 -3.355 1.00 20.58 C -ATOM 3364 O LEU D 14 -26.325 -13.141 -4.012 1.00 19.87 O -ATOM 3365 CB LEU D 14 -24.748 -12.802 -1.037 1.00 18.39 C -ATOM 3366 CG LEU D 14 -24.944 -11.344 -1.539 1.00 32.12 C -ATOM 3367 CD1 LEU D 14 -25.966 -10.962 -0.374 1.00 41.26 C -ATOM 3368 CD2 LEU D 14 -23.927 -10.587 -1.223 1.00 34.27 C -ATOM 3369 N TRP D 15 -24.663 -14.787 -3.692 1.00 16.79 N -ATOM 3370 CA TRP D 15 -24.253 -14.609 -5.178 1.00 13.47 C -ATOM 3371 C TRP D 15 -25.414 -15.354 -5.958 1.00 22.23 C -ATOM 3372 O TRP D 15 -25.691 -14.922 -7.051 1.00 22.75 O -ATOM 3373 CB TRP D 15 -23.003 -15.504 -5.278 1.00 17.27 C -ATOM 3374 CG TRP D 15 -22.390 -15.264 -6.607 1.00 18.39 C -ATOM 3375 CD1 TRP D 15 -22.417 -16.024 -7.714 1.00 29.85 C -ATOM 3376 CD2 TRP D 15 -21.683 -13.937 -6.966 1.00 19.14 C -ATOM 3377 NE1 TRP D 15 -21.775 -15.472 -8.770 1.00 25.67 N -ATOM 3378 CE2 TRP D 15 -21.205 -14.132 -8.458 1.00 18.90 C -ATOM 3379 CE3 TRP D 15 -21.251 -12.883 -6.227 1.00 24.35 C -ATOM 3380 CZ2 TRP D 15 -20.568 -13.098 -9.104 1.00 22.83 C -ATOM 3381 CZ3 TRP D 15 -20.364 -11.928 -6.894 1.00 24.62 C -ATOM 3382 CH2 TRP D 15 -20.127 -12.198 -8.397 1.00 30.44 C -ATOM 3383 N GLY D 16 -26.279 -16.244 -5.358 1.00 23.06 N -ATOM 3384 CA GLY D 16 -27.474 -16.657 -6.225 1.00 23.16 C -ATOM 3385 C GLY D 16 -28.300 -15.570 -6.485 1.00 26.54 C -ATOM 3386 O GLY D 16 -29.203 -15.791 -7.472 1.00 26.11 O -ATOM 3387 N LYS D 17 -28.475 -14.360 -5.980 1.00 18.84 N -ATOM 3388 CA LYS D 17 -29.272 -13.270 -5.974 1.00 24.96 C -ATOM 3389 C LYS D 17 -29.000 -12.271 -6.961 1.00 22.00 C -ATOM 3390 O LYS D 17 -29.037 -11.079 -7.508 1.00 24.63 O -ATOM 3391 CB LYS D 17 -29.587 -12.449 -4.588 1.00 28.33 C -ATOM 3392 CG LYS D 17 -30.108 -13.362 -3.795 1.00 27.71 C -ATOM 3393 CD LYS D 17 -30.415 -12.422 -2.822 1.00 33.37 C -ATOM 3394 CE LYS D 17 -30.390 -12.386 -1.399 1.00 43.68 C -ATOM 3395 NZ LYS D 17 -31.873 -11.072 -1.369 1.00 36.22 N -ATOM 3396 N VAL D 18 -27.474 -12.385 -7.448 1.00 33.39 N -ATOM 3397 CA VAL D 18 -26.489 -11.309 -8.320 1.00 24.51 C -ATOM 3398 C VAL D 18 -27.096 -11.570 -9.917 1.00 27.24 C -ATOM 3399 O VAL D 18 -26.940 -12.785 -10.011 1.00 26.54 O -ATOM 3400 CB VAL D 18 -25.245 -11.428 -8.185 1.00 31.98 C -ATOM 3401 CG1 VAL D 18 -24.320 -10.896 -8.917 1.00 31.25 C -ATOM 3402 CG2 VAL D 18 -24.647 -11.020 -6.542 1.00 22.12 C -ATOM 3403 N ASN D 19 -27.428 -10.545 -10.401 1.00 25.81 N -ATOM 3404 CA ASN D 19 -27.299 -10.403 -11.802 1.00 27.55 C -ATOM 3405 C ASN D 19 -26.159 -10.452 -12.333 1.00 24.31 C -ATOM 3406 O ASN D 19 -25.632 -9.111 -12.336 1.00 20.67 O -ATOM 3407 CB ASN D 19 -28.399 -9.524 -12.285 1.00 40.49 C -ATOM 3408 CG ASN D 19 -28.856 -10.175 -13.808 1.00 44.62 C -ATOM 3409 OD1 ASN D 19 -27.731 -9.601 -14.786 1.00 45.68 O -ATOM 3410 ND2 ASN D 19 -29.658 -8.823 -14.484 1.00 50.78 N -ATOM 3411 N VAL D 20 -25.460 -11.215 -12.835 1.00 22.82 N -ATOM 3412 CA VAL D 20 -23.926 -10.940 -13.321 1.00 40.38 C -ATOM 3413 C VAL D 20 -23.628 -9.968 -13.933 1.00 37.93 C -ATOM 3414 O VAL D 20 -22.741 -9.105 -14.256 1.00 32.18 O -ATOM 3415 CB VAL D 20 -22.926 -12.781 -13.318 1.00 54.80 C -ATOM 3416 CG1 VAL D 20 -22.524 -12.140 -14.217 1.00 63.33 C -ATOM 3417 CG2 VAL D 20 -23.373 -13.095 -12.306 1.00 34.72 C -ATOM 3418 N ASP D 21 -24.469 -9.996 -15.091 1.00 36.66 N -ATOM 3419 CA ASP D 21 -24.588 -8.635 -15.872 1.00 54.12 C -ATOM 3420 C ASP D 21 -24.717 -7.685 -15.749 1.00 46.84 C -ATOM 3421 O ASP D 21 -23.610 -6.686 -15.937 1.00 32.53 O -ATOM 3422 CB ASP D 21 -25.603 -8.934 -17.011 1.00 60.03 C -ATOM 3423 CG ASP D 21 -25.523 -10.565 -17.717 1.00 75.30 C -ATOM 3424 OD1 ASP D 21 -24.242 -11.481 -17.893 1.00 51.52 O -ATOM 3425 OD2 ASP D 21 -25.948 -10.502 -18.826 1.00 64.70 O -ATOM 3426 N GLU D 22 -25.623 -7.162 -14.906 1.00 27.09 N -ATOM 3427 CA GLU D 22 -25.919 -5.886 -14.386 1.00 23.15 C -ATOM 3428 C GLU D 22 -24.427 -5.530 -13.395 1.00 19.08 C -ATOM 3429 O GLU D 22 -24.197 -4.407 -13.172 1.00 21.80 O -ATOM 3430 CB GLU D 22 -27.280 -5.934 -13.774 1.00 35.52 C -ATOM 3431 CG GLU D 22 -27.211 -5.635 -13.083 1.00 68.74 C -ATOM 3432 CD GLU D 22 -28.960 -4.398 -12.033 1.00 80.12 C -ATOM 3433 OE1 GLU D 22 -29.624 -5.184 -11.024 1.00 61.13 O -ATOM 3434 OE2 GLU D 22 -29.463 -4.100 -13.136 1.00 73.88 O -ATOM 3435 N VAL D 23 -24.426 -6.315 -12.392 1.00 20.94 N -ATOM 3436 CA VAL D 23 -23.348 -6.099 -11.326 1.00 17.82 C -ATOM 3437 C VAL D 23 -21.966 -6.004 -12.061 1.00 15.07 C -ATOM 3438 O VAL D 23 -21.155 -5.154 -11.664 1.00 21.11 O -ATOM 3439 CB VAL D 23 -23.341 -7.268 -10.216 1.00 18.64 C -ATOM 3440 CG1 VAL D 23 -22.169 -7.160 -9.566 1.00 21.45 C -ATOM 3441 CG2 VAL D 23 -24.676 -6.892 -9.537 1.00 21.02 C -ATOM 3442 N GLY D 24 -21.629 -6.780 -12.936 1.00 12.96 N -ATOM 3443 CA GLY D 24 -20.442 -6.846 -13.669 1.00 18.39 C -ATOM 3444 C GLY D 24 -20.261 -5.559 -14.312 1.00 16.60 C -ATOM 3445 O GLY D 24 -19.233 -4.768 -14.272 1.00 15.31 O -ATOM 3446 N GLY D 25 -21.132 -4.866 -15.117 1.00 17.32 N -ATOM 3447 CA GLY D 25 -21.127 -3.499 -15.792 1.00 16.45 C -ATOM 3448 C GLY D 25 -21.008 -2.525 -14.804 1.00 12.17 C -ATOM 3449 O GLY D 25 -20.114 -1.633 -15.055 1.00 21.20 O -ATOM 3450 N GLU D 26 -21.690 -2.622 -13.683 1.00 15.97 N -ATOM 3451 CA GLU D 26 -21.600 -1.628 -12.730 1.00 13.66 C -ATOM 3452 C GLU D 26 -20.044 -1.546 -12.031 1.00 11.75 C -ATOM 3453 O GLU D 26 -19.572 -0.450 -11.864 1.00 13.88 O -ATOM 3454 CB GLU D 26 -22.662 -1.686 -11.514 1.00 18.62 C -ATOM 3455 CG GLU D 26 -23.979 0.008 -11.890 1.00 39.81 C -ATOM 3456 CD GLU D 26 -22.700 -0.395 -10.542 1.00 31.77 C -ATOM 3457 OE1 GLU D 26 -23.368 1.259 -10.392 1.00 34.99 O -ATOM 3458 OE2 GLU D 26 -24.210 -0.810 -9.865 1.00 54.79 O -ATOM 3459 N ALA D 27 -19.673 -2.710 -11.707 1.00 12.60 N -ATOM 3460 CA ALA D 27 -18.269 -2.901 -11.078 1.00 17.85 C -ATOM 3461 C ALA D 27 -17.180 -2.341 -11.937 1.00 15.51 C -ATOM 3462 O ALA D 27 -16.331 -1.489 -11.550 1.00 14.90 O -ATOM 3463 CB ALA D 27 -18.048 -4.225 -10.534 1.00 15.58 C -ATOM 3464 N LEU D 28 -17.183 -2.729 -13.203 1.00 16.04 N -ATOM 3465 CA LEU D 28 -16.186 -2.309 -14.163 1.00 11.08 C -ATOM 3466 C LEU D 28 -16.248 -0.897 -14.292 1.00 13.51 C -ATOM 3467 O LEU D 28 -15.238 -0.124 -14.487 1.00 14.05 O -ATOM 3468 CB LEU D 28 -16.275 -3.066 -15.497 1.00 12.20 C -ATOM 3469 CG LEU D 28 -14.973 -2.764 -16.433 1.00 28.52 C -ATOM 3470 CD1 LEU D 28 -13.779 -3.087 -15.679 1.00 36.95 C -ATOM 3471 CD2 LEU D 28 -15.242 -3.401 -17.606 1.00 34.25 C -ATOM 3472 N GLY D 29 -17.518 -0.283 -14.622 1.00 12.33 N -ATOM 3473 CA GLY D 29 -17.751 1.088 -14.735 1.00 13.25 C -ATOM 3474 C GLY D 29 -17.136 1.954 -13.603 1.00 12.50 C -ATOM 3475 O GLY D 29 -16.531 3.012 -13.890 1.00 16.69 O -ATOM 3476 N ARG D 30 -17.539 1.491 -12.441 1.00 15.15 N -ATOM 3477 CA ARG D 30 -17.026 2.243 -11.337 1.00 17.77 C -ATOM 3478 C ARG D 30 -15.527 2.171 -11.160 1.00 14.35 C -ATOM 3479 O ARG D 30 -14.968 3.218 -10.798 1.00 14.59 O -ATOM 3480 CB ARG D 30 -17.892 1.792 -10.040 1.00 15.53 C -ATOM 3481 CG ARG D 30 -19.275 2.313 -9.820 1.00 16.65 C -ATOM 3482 CD ARG D 30 -19.931 1.839 -8.709 1.00 28.01 C -ATOM 3483 NE ARG D 30 -21.099 2.164 -8.522 1.00 23.10 N -ATOM 3484 CZ ARG D 30 -21.731 3.109 -7.922 1.00 16.06 C -ATOM 3485 NH1 ARG D 30 -22.965 3.397 -7.723 1.00 17.46 N -ATOM 3486 NH2 ARG D 30 -21.050 3.807 -6.871 1.00 10.32 N -ATOM 3487 N LEU D 31 -14.961 1.160 -11.442 1.00 15.53 N -ATOM 3488 CA LEU D 31 -13.554 1.103 -11.546 1.00 14.63 C -ATOM 3489 C LEU D 31 -12.894 2.305 -12.254 1.00 16.67 C -ATOM 3490 O LEU D 31 -11.964 2.890 -11.986 1.00 15.33 O -ATOM 3491 CB LEU D 31 -12.961 -0.342 -11.951 1.00 12.02 C -ATOM 3492 CG LEU D 31 -11.524 -0.502 -11.963 1.00 17.81 C -ATOM 3493 CD1 LEU D 31 -10.867 -0.718 -10.607 1.00 18.94 C -ATOM 3494 CD2 LEU D 31 -11.112 -1.549 -12.889 1.00 18.38 C -ATOM 3495 N LEU D 32 -13.461 2.265 -13.601 1.00 8.95 N -ATOM 3496 CA LEU D 32 -13.016 3.232 -14.475 1.00 13.61 C -ATOM 3497 C LEU D 32 -13.249 4.589 -14.109 1.00 13.07 C -ATOM 3498 O LEU D 32 -12.457 5.593 -14.562 1.00 15.98 O -ATOM 3499 CB LEU D 32 -13.512 2.944 -15.805 1.00 14.00 C -ATOM 3500 CG LEU D 32 -12.943 1.707 -16.403 1.00 23.55 C -ATOM 3501 CD1 LEU D 32 -13.857 1.407 -17.761 1.00 25.80 C -ATOM 3502 CD2 LEU D 32 -11.759 1.263 -16.551 1.00 26.67 C -ATOM 3503 N VAL D 33 -14.340 4.892 -13.280 1.00 13.83 N -ATOM 3504 CA VAL D 33 -14.717 6.296 -12.776 1.00 13.13 C -ATOM 3505 C VAL D 33 -13.702 6.655 -11.697 1.00 16.82 C -ATOM 3506 O VAL D 33 -13.288 7.735 -11.589 1.00 15.10 O -ATOM 3507 CB VAL D 33 -16.181 6.271 -12.468 1.00 11.59 C -ATOM 3508 CG1 VAL D 33 -16.396 7.592 -11.833 1.00 21.42 C -ATOM 3509 CG2 VAL D 33 -16.955 6.215 -13.830 1.00 18.60 C -ATOM 3510 N VAL D 34 -13.788 5.741 -10.696 1.00 12.61 N -ATOM 3511 CA VAL D 34 -13.205 6.102 -9.422 1.00 13.03 C -ATOM 3512 C VAL D 34 -11.709 6.268 -9.501 1.00 15.88 C -ATOM 3513 O VAL D 34 -11.074 6.862 -8.702 1.00 16.40 O -ATOM 3514 CB VAL D 34 -13.754 5.224 -8.226 1.00 15.07 C -ATOM 3515 CG1 VAL D 34 -13.038 5.375 -6.973 1.00 13.90 C -ATOM 3516 CG2 VAL D 34 -15.220 5.422 -8.063 1.00 18.23 C -ATOM 3517 N TYR D 35 -11.136 5.248 -10.266 1.00 11.62 N -ATOM 3518 CA TYR D 35 -9.629 5.095 -10.409 1.00 14.47 C -ATOM 3519 C TYR D 35 -9.420 5.204 -11.973 1.00 16.31 C -ATOM 3520 O TYR D 35 -9.060 4.177 -12.606 1.00 17.14 O -ATOM 3521 CB TYR D 35 -9.241 3.705 -9.961 1.00 14.04 C -ATOM 3522 CG TYR D 35 -9.664 3.371 -8.620 1.00 16.50 C -ATOM 3523 CD1 TYR D 35 -9.076 4.102 -7.605 1.00 16.28 C -ATOM 3524 CD2 TYR D 35 -10.520 2.540 -8.304 1.00 21.92 C -ATOM 3525 CE1 TYR D 35 -9.315 3.966 -6.162 1.00 18.51 C -ATOM 3526 CE2 TYR D 35 -10.873 2.362 -6.966 1.00 25.13 C -ATOM 3527 CZ TYR D 35 -10.254 3.015 -5.920 1.00 19.91 C -ATOM 3528 OH TYR D 35 -10.861 2.820 -4.629 1.00 21.91 O -ATOM 3529 N PRO D 36 -9.392 6.463 -12.417 1.00 14.59 N -ATOM 3530 CA PRO D 36 -9.346 6.600 -14.037 1.00 16.73 C -ATOM 3531 C PRO D 36 -8.099 6.185 -14.723 1.00 13.23 C -ATOM 3532 O PRO D 36 -8.183 5.907 -15.944 1.00 15.17 O -ATOM 3533 CB PRO D 36 -9.750 8.096 -14.119 1.00 24.30 C -ATOM 3534 CG PRO D 36 -9.458 8.680 -12.746 1.00 25.67 C -ATOM 3535 CD PRO D 36 -9.575 7.632 -11.872 1.00 17.58 C -ATOM 3536 N TRP D 37 -6.974 5.929 -13.940 1.00 13.75 N -ATOM 3537 CA TRP D 37 -5.897 5.496 -14.615 1.00 15.13 C -ATOM 3538 C TRP D 37 -5.961 4.094 -15.089 1.00 14.32 C -ATOM 3539 O TRP D 37 -5.292 3.617 -16.098 1.00 19.70 O -ATOM 3540 CB TRP D 37 -4.642 5.522 -13.687 1.00 13.13 C -ATOM 3541 CG TRP D 37 -4.793 4.873 -12.298 1.00 8.65 C -ATOM 3542 CD1 TRP D 37 -4.494 3.633 -11.929 1.00 13.10 C -ATOM 3543 CD2 TRP D 37 -5.201 5.532 -10.999 1.00 14.59 C -ATOM 3544 NE1 TRP D 37 -4.604 3.407 -10.644 1.00 17.65 N -ATOM 3545 CE2 TRP D 37 -5.232 4.530 -10.117 1.00 16.05 C -ATOM 3546 CE3 TRP D 37 -5.786 6.762 -10.728 1.00 11.20 C -ATOM 3547 CZ2 TRP D 37 -5.541 4.775 -8.606 1.00 26.88 C -ATOM 3548 CZ3 TRP D 37 -6.287 7.021 -9.443 1.00 11.28 C -ATOM 3549 CH2 TRP D 37 -5.996 6.001 -8.551 1.00 16.90 C -ATOM 3550 N THR D 38 -6.984 3.333 -14.581 1.00 16.64 N -ATOM 3551 CA THR D 38 -7.362 1.995 -14.995 1.00 14.14 C -ATOM 3552 C THR D 38 -7.792 2.033 -16.539 1.00 18.16 C -ATOM 3553 O THR D 38 -7.920 0.930 -17.161 1.00 16.15 O -ATOM 3554 CB THR D 38 -8.440 1.318 -14.155 1.00 11.09 C -ATOM 3555 OG1 THR D 38 -9.618 2.008 -14.130 1.00 14.48 O -ATOM 3556 CG2 THR D 38 -7.730 1.043 -12.892 1.00 16.14 C -ATOM 3557 N GLN D 39 -8.345 3.275 -16.962 1.00 12.07 N -ATOM 3558 CA GLN D 39 -8.833 3.256 -18.352 1.00 10.72 C -ATOM 3559 C GLN D 39 -7.732 3.116 -19.349 1.00 16.84 C -ATOM 3560 O GLN D 39 -7.933 2.801 -20.471 1.00 21.52 O -ATOM 3561 CB GLN D 39 -9.205 4.786 -18.517 1.00 13.63 C -ATOM 3562 CG GLN D 39 -10.419 4.929 -17.639 1.00 17.04 C -ATOM 3563 CD GLN D 39 -10.861 6.282 -17.855 1.00 23.47 C -ATOM 3564 OE1 GLN D 39 -10.432 7.200 -18.833 1.00 25.04 O -ATOM 3565 NE2 GLN D 39 -11.740 6.840 -16.888 1.00 28.38 N -ATOM 3566 N ARG D 40 -6.331 2.999 -19.002 1.00 12.32 N -ATOM 3567 CA ARG D 40 -5.095 2.844 -19.730 1.00 16.79 C -ATOM 3568 C ARG D 40 -5.433 1.605 -20.411 1.00 17.58 C -ATOM 3569 O ARG D 40 -4.682 1.315 -21.633 1.00 20.86 O -ATOM 3570 CB ARG D 40 -3.966 2.461 -18.813 1.00 22.83 C -ATOM 3571 CG ARG D 40 -3.694 1.460 -18.189 1.00 37.26 C -ATOM 3572 CD ARG D 40 -2.418 1.834 -17.304 1.00 23.75 C -ATOM 3573 NE ARG D 40 -1.279 2.091 -17.831 1.00 28.71 N -ATOM 3574 CZ ARG D 40 -0.609 1.176 -18.760 1.00 41.77 C -ATOM 3575 NH1 ARG D 40 -0.700 0.067 -18.486 1.00 31.05 N -ATOM 3576 NH2 ARG D 40 0.625 1.911 -19.038 1.00 37.79 N -ATOM 3577 N PHE D 41 -6.207 0.540 -20.107 1.00 15.17 N -ATOM 3578 CA PHE D 41 -6.336 -0.770 -20.711 1.00 16.55 C -ATOM 3579 C PHE D 41 -7.612 -0.691 -21.880 1.00 20.00 C -ATOM 3580 O PHE D 41 -7.651 -1.868 -22.265 1.00 23.52 O -ATOM 3581 CB PHE D 41 -6.568 -1.995 -19.811 1.00 13.75 C -ATOM 3582 CG PHE D 41 -5.344 -2.033 -18.714 1.00 12.41 C -ATOM 3583 CD1 PHE D 41 -5.592 -1.379 -17.449 1.00 16.97 C -ATOM 3584 CD2 PHE D 41 -4.233 -2.496 -19.084 1.00 18.05 C -ATOM 3585 CE1 PHE D 41 -4.371 -1.693 -16.818 1.00 23.07 C -ATOM 3586 CE2 PHE D 41 -3.008 -2.505 -18.298 1.00 24.82 C -ATOM 3587 CZ PHE D 41 -3.359 -2.006 -17.025 1.00 25.09 C -ATOM 3588 N PHE D 42 -8.192 0.386 -21.832 1.00 15.21 N -ATOM 3589 CA PHE D 42 -9.461 0.148 -22.436 1.00 14.18 C -ATOM 3590 C PHE D 42 -9.645 1.104 -23.586 1.00 19.41 C -ATOM 3591 O PHE D 42 -10.690 1.871 -23.828 1.00 18.71 O -ATOM 3592 CB PHE D 42 -10.613 0.298 -21.592 1.00 21.58 C -ATOM 3593 CG PHE D 42 -10.602 -1.034 -20.710 1.00 17.63 C -ATOM 3594 CD1 PHE D 42 -10.145 -0.545 -19.164 1.00 20.37 C -ATOM 3595 CD2 PHE D 42 -11.012 -2.318 -21.048 1.00 20.14 C -ATOM 3596 CE1 PHE D 42 -10.225 -1.848 -18.434 1.00 27.02 C -ATOM 3597 CE2 PHE D 42 -10.887 -3.301 -20.223 1.00 27.08 C -ATOM 3598 CZ PHE D 42 -10.474 -2.972 -18.757 1.00 18.28 C -ATOM 3599 N GLU D 43 -8.375 1.400 -24.058 1.00 32.32 N -ATOM 3600 CA GLU D 43 -8.561 2.747 -24.914 1.00 33.61 C -ATOM 3601 C GLU D 43 -9.574 2.656 -26.563 1.00 12.75 C -ATOM 3602 O GLU D 43 -9.904 3.604 -26.926 1.00 26.94 O -ATOM 3603 CB GLU D 43 -7.590 2.897 -25.572 1.00 65.31 C -ATOM 3604 CG GLU D 43 -6.882 2.859 -25.890 1.00 43.00 C -ATOM 3605 CD GLU D 43 -6.060 4.011 -24.596 1.00 32.00 C -ATOM 3606 OE1 GLU D 43 -6.764 5.450 -24.611 1.00 29.89 O -ATOM 3607 OE2 GLU D 43 -4.721 4.728 -24.142 1.00 58.55 O -ATOM 3608 N SER D 44 -9.605 1.289 -26.702 1.00 19.02 N -ATOM 3609 CA SER D 44 -10.333 0.707 -27.924 1.00 25.67 C -ATOM 3610 C SER D 44 -11.604 0.898 -27.554 1.00 26.66 C -ATOM 3611 O SER D 44 -12.646 0.619 -28.203 1.00 32.13 O -ATOM 3612 CB SER D 44 -10.139 -0.585 -28.237 1.00 42.87 C -ATOM 3613 OG SER D 44 -10.504 -1.572 -27.556 1.00 44.29 O -ATOM 3614 N PHE D 45 -12.328 1.230 -26.297 1.00 27.34 N -ATOM 3615 CA PHE D 45 -13.753 1.140 -25.852 1.00 24.93 C -ATOM 3616 C PHE D 45 -14.575 2.593 -26.282 1.00 23.30 C -ATOM 3617 O PHE D 45 -15.815 2.187 -25.861 1.00 31.71 O -ATOM 3618 CB PHE D 45 -13.703 0.919 -24.328 1.00 26.07 C -ATOM 3619 CG PHE D 45 -13.645 -0.527 -24.075 1.00 19.10 C -ATOM 3620 CD1 PHE D 45 -14.209 -0.901 -22.815 1.00 43.96 C -ATOM 3621 CD2 PHE D 45 -13.155 -1.495 -24.645 1.00 26.17 C -ATOM 3622 CE1 PHE D 45 -14.066 -2.469 -22.506 1.00 29.49 C -ATOM 3623 CE2 PHE D 45 -12.912 -2.782 -24.307 1.00 32.75 C -ATOM 3624 CZ PHE D 45 -13.459 -3.397 -23.316 1.00 28.04 C -ATOM 3625 N GLY D 46 -14.104 3.279 -26.525 1.00 35.08 N -ATOM 3626 CA GLY D 46 -14.935 4.262 -26.788 1.00 34.51 C -ATOM 3627 C GLY D 46 -15.024 5.841 -25.884 1.00 32.00 C -ATOM 3628 O GLY D 46 -13.703 5.710 -25.436 1.00 42.65 O -ATOM 3629 N ASP D 47 -16.270 6.088 -25.501 1.00 33.75 N -ATOM 3630 CA ASP D 47 -15.315 7.928 -25.257 1.00 43.29 C -ATOM 3631 C ASP D 47 -15.918 7.002 -23.097 1.00 24.69 C -ATOM 3632 O ASP D 47 -17.090 6.340 -23.091 1.00 33.08 O -ATOM 3633 CB ASP D 47 -17.246 8.111 -25.348 1.00 48.49 C -ATOM 3634 CG ASP D 47 -17.316 9.636 -24.481 1.00 50.77 C -ATOM 3635 OD1 ASP D 47 -18.624 9.821 -24.553 1.00 57.75 O -ATOM 3636 OD2 ASP D 47 -16.233 10.163 -24.247 1.00 45.03 O -ATOM 3637 N LEU D 48 -14.887 7.498 -22.782 1.00 25.73 N -ATOM 3638 CA LEU D 48 -14.700 7.013 -21.145 1.00 29.97 C -ATOM 3639 C LEU D 48 -14.723 8.417 -20.213 1.00 32.06 C -ATOM 3640 O LEU D 48 -13.912 8.444 -19.219 1.00 36.43 O -ATOM 3641 CB LEU D 48 -13.472 6.468 -21.109 1.00 41.80 C -ATOM 3642 CG LEU D 48 -13.862 5.004 -21.634 1.00 22.03 C -ATOM 3643 CD1 LEU D 48 -12.363 4.146 -21.342 1.00 37.56 C -ATOM 3644 CD2 LEU D 48 -15.085 4.189 -21.243 1.00 29.67 C -ATOM 3645 N SER D 49 -15.191 9.523 -21.130 1.00 38.40 N -ATOM 3646 CA SER D 49 -14.387 10.788 -20.677 1.00 43.30 C -ATOM 3647 C SER D 49 -15.473 11.721 -19.486 1.00 46.97 C -ATOM 3648 O SER D 49 -14.763 12.145 -18.356 1.00 46.32 O -ATOM 3649 CB SER D 49 -14.644 11.939 -21.771 1.00 47.25 C -ATOM 3650 OG SER D 49 -16.017 12.123 -22.081 1.00 49.74 O -ATOM 3651 N THR D 50 -16.621 11.041 -19.530 1.00 43.91 N -ATOM 3652 CA THR D 50 -16.855 11.313 -17.860 1.00 36.95 C -ATOM 3653 C THR D 50 -18.023 10.172 -17.341 1.00 36.10 C -ATOM 3654 O THR D 50 -18.171 9.157 -18.076 1.00 28.99 O -ATOM 3655 CB THR D 50 -18.590 12.293 -18.547 1.00 37.26 C -ATOM 3656 OG1 THR D 50 -19.750 11.618 -19.297 1.00 36.38 O -ATOM 3657 CG2 THR D 50 -18.025 13.508 -19.178 1.00 56.40 C -ATOM 3658 N PRO D 51 -18.501 10.284 -16.193 1.00 37.42 N -ATOM 3659 CA PRO D 51 -19.225 9.303 -15.560 1.00 32.59 C -ATOM 3660 C PRO D 51 -20.269 8.625 -16.174 1.00 29.25 C -ATOM 3661 O PRO D 51 -20.632 7.313 -16.333 1.00 26.15 O -ATOM 3662 CB PRO D 51 -19.687 9.933 -14.153 1.00 37.41 C -ATOM 3663 CG PRO D 51 -18.587 10.776 -13.939 1.00 36.57 C -ATOM 3664 CD PRO D 51 -18.147 11.586 -15.357 1.00 42.54 C -ATOM 3665 N ASP D 52 -21.166 9.545 -16.896 1.00 30.65 N -ATOM 3666 CA ASP D 52 -22.575 8.738 -17.587 1.00 39.40 C -ATOM 3667 C ASP D 52 -21.861 8.056 -18.864 1.00 56.69 C -ATOM 3668 O ASP D 52 -22.611 7.193 -19.113 1.00 40.69 O -ATOM 3669 CB ASP D 52 -23.192 10.048 -17.807 1.00 43.19 C -ATOM 3670 CG ASP D 52 -24.003 11.080 -16.646 1.00 63.04 C -ATOM 3671 OD1 ASP D 52 -23.975 10.324 -15.803 1.00 49.71 O -ATOM 3672 OD2 ASP D 52 -21.902 12.263 -16.248 1.00 60.40 O -ATOM 3673 N ALA D 53 -21.035 8.713 -19.489 1.00 26.05 N -ATOM 3674 CA ALA D 53 -20.460 8.256 -20.648 1.00 33.75 C -ATOM 3675 C ALA D 53 -19.850 6.612 -20.478 1.00 42.76 C -ATOM 3676 O ALA D 53 -20.052 5.785 -20.744 1.00 38.58 O -ATOM 3677 CB ALA D 53 -19.424 8.739 -21.252 1.00 40.18 C -ATOM 3678 N VAL D 54 -18.829 6.696 -19.306 1.00 27.10 N -ATOM 3679 CA VAL D 54 -18.358 5.224 -18.836 1.00 25.12 C -ATOM 3680 C VAL D 54 -19.446 4.410 -18.467 1.00 26.50 C -ATOM 3681 O VAL D 54 -19.614 3.128 -18.953 1.00 24.76 O -ATOM 3682 CB VAL D 54 -17.388 5.607 -17.705 1.00 26.67 C -ATOM 3683 CG1 VAL D 54 -17.066 4.042 -17.246 1.00 25.19 C -ATOM 3684 CG2 VAL D 54 -16.359 6.289 -17.975 1.00 31.48 C -ATOM 3685 N MET D 55 -20.628 4.739 -17.700 1.00 25.87 N -ATOM 3686 CA MET D 55 -21.589 3.767 -17.229 1.00 29.84 C -ATOM 3687 C MET D 55 -22.865 3.307 -18.556 1.00 35.52 C -ATOM 3688 O MET D 55 -23.112 2.208 -18.285 1.00 32.07 O -ATOM 3689 CB MET D 55 -22.456 4.472 -15.982 1.00 26.28 C -ATOM 3690 CG MET D 55 -21.631 4.626 -15.056 1.00 36.16 C -ATOM 3691 SD MET D 55 -20.389 3.558 -14.111 1.00 25.36 S -ATOM 3692 CE MET D 55 -21.479 2.431 -13.702 1.00 19.21 C -ATOM 3693 N GLY D 56 -22.639 4.442 -19.311 1.00 30.97 N -ATOM 3694 CA GLY D 56 -23.658 3.737 -20.126 1.00 35.09 C -ATOM 3695 C GLY D 56 -22.967 3.067 -21.283 1.00 44.75 C -ATOM 3696 O GLY D 56 -23.331 2.815 -22.514 1.00 34.49 O -ATOM 3697 N ASN D 57 -21.558 3.094 -21.617 1.00 25.90 N -ATOM 3698 CA ASN D 57 -20.747 2.578 -22.658 1.00 29.86 C -ATOM 3699 C ASN D 57 -21.034 1.130 -22.652 1.00 26.15 C -ATOM 3700 O ASN D 57 -20.989 0.128 -21.968 1.00 26.55 O -ATOM 3701 CB ASN D 57 -19.324 2.902 -22.444 1.00 30.42 C -ATOM 3702 CG ASN D 57 -18.502 2.332 -23.503 1.00 23.49 C -ATOM 3703 OD1 ASN D 57 -18.423 1.194 -24.009 1.00 31.02 O -ATOM 3704 ND2 ASN D 57 -17.712 3.179 -23.808 1.00 27.30 N -ATOM 3705 N PRO D 58 -21.467 0.671 -23.926 1.00 29.25 N -ATOM 3706 CA PRO D 58 -21.926 -0.726 -24.096 1.00 25.97 C -ATOM 3707 C PRO D 58 -20.503 -1.629 -24.124 1.00 16.05 C -ATOM 3708 O PRO D 58 -20.837 -2.940 -23.655 1.00 24.61 O -ATOM 3709 CB PRO D 58 -22.522 -0.927 -25.620 1.00 33.18 C -ATOM 3710 CG PRO D 58 -21.947 0.977 -25.418 1.00 59.49 C -ATOM 3711 CD PRO D 58 -21.892 1.180 -25.502 1.00 43.36 C -ATOM 3712 N LYS D 59 -19.460 -1.283 -24.501 1.00 21.03 N -ATOM 3713 CA LYS D 59 -18.361 -2.042 -24.450 1.00 25.38 C -ATOM 3714 C LYS D 59 -17.715 -2.407 -22.856 1.00 17.84 C -ATOM 3715 O LYS D 59 -17.308 -3.569 -22.731 1.00 21.39 O -ATOM 3716 CB LYS D 59 -17.227 -1.661 -25.270 1.00 32.15 C -ATOM 3717 CG LYS D 59 -17.383 -1.768 -26.732 1.00 48.59 C -ATOM 3718 CD LYS D 59 -16.823 -1.145 -27.228 1.00 53.12 C -ATOM 3719 CE LYS D 59 -15.877 -1.703 -28.754 1.00 53.54 C -ATOM 3720 NZ LYS D 59 -16.728 -0.847 -29.838 1.00 62.98 N -ATOM 3721 N VAL D 60 -18.099 -1.250 -22.201 1.00 18.98 N -ATOM 3722 CA VAL D 60 -17.893 -1.490 -20.566 1.00 19.06 C -ATOM 3723 C VAL D 60 -18.582 -2.535 -20.118 1.00 17.34 C -ATOM 3724 O VAL D 60 -18.311 -3.436 -19.262 1.00 23.46 O -ATOM 3725 CB VAL D 60 -17.740 -0.068 -19.973 1.00 21.26 C -ATOM 3726 CG1 VAL D 60 -17.894 -0.452 -18.381 1.00 33.14 C -ATOM 3727 CG2 VAL D 60 -16.838 0.852 -20.547 1.00 22.06 C -ATOM 3728 N LYS D 61 -20.037 -2.374 -20.306 1.00 22.59 N -ATOM 3729 CA LYS D 61 -21.055 -3.383 -19.935 1.00 26.15 C -ATOM 3730 C LYS D 61 -20.810 -4.741 -20.319 1.00 17.30 C -ATOM 3731 O LYS D 61 -20.683 -5.728 -19.595 1.00 21.45 O -ATOM 3732 CB LYS D 61 -22.507 -2.996 -20.257 1.00 26.85 C -ATOM 3733 CG LYS D 61 -22.914 -1.601 -19.668 1.00 38.21 C -ATOM 3734 CD LYS D 61 -23.980 -1.298 -20.293 1.00 63.66 C -ATOM 3735 CE LYS D 61 -25.073 -0.202 -19.530 1.00 68.06 C -ATOM 3736 NZ LYS D 61 -26.116 0.022 -20.150 1.00 60.84 N -ATOM 3737 N ALA D 62 -20.349 -4.906 -21.599 1.00 19.16 N -ATOM 3738 CA ALA D 62 -20.005 -6.284 -22.177 1.00 20.58 C -ATOM 3739 C ALA D 62 -18.862 -7.045 -21.486 1.00 20.27 C -ATOM 3740 O ALA D 62 -18.872 -8.142 -21.107 1.00 20.37 O -ATOM 3741 CB ALA D 62 -19.803 -6.090 -23.619 1.00 22.88 C -ATOM 3742 N HIS D 63 -17.847 -6.087 -21.291 1.00 19.01 N -ATOM 3743 CA HIS D 63 -16.655 -6.703 -20.657 1.00 22.19 C -ATOM 3744 C HIS D 63 -16.866 -6.900 -19.133 1.00 18.77 C -ATOM 3745 O HIS D 63 -16.263 -7.930 -18.702 1.00 19.91 O -ATOM 3746 CB HIS D 63 -15.613 -5.996 -20.822 1.00 33.38 C -ATOM 3747 CG HIS D 63 -13.969 -6.285 -20.598 1.00 22.34 C -ATOM 3748 ND1 HIS D 63 -13.645 -7.369 -21.205 1.00 25.81 N -ATOM 3749 CD2 HIS D 63 -13.423 -5.898 -19.324 1.00 33.81 C -ATOM 3750 CE1 HIS D 63 -12.413 -7.623 -20.166 1.00 24.99 C -ATOM 3751 NE2 HIS D 63 -12.303 -6.521 -19.735 1.00 32.42 N -ATOM 3752 N GLY D 64 -17.554 -5.957 -18.637 1.00 15.38 N -ATOM 3753 CA GLY D 64 -17.922 -6.237 -17.300 1.00 18.66 C -ATOM 3754 C GLY D 64 -18.656 -7.558 -16.822 1.00 23.30 C -ATOM 3755 O GLY D 64 -18.361 -8.374 -16.052 1.00 21.27 O -ATOM 3756 N LYS D 65 -19.546 -7.946 -17.963 1.00 22.12 N -ATOM 3757 CA LYS D 65 -20.149 -9.350 -17.810 1.00 26.40 C -ATOM 3758 C LYS D 65 -19.206 -10.475 -18.054 1.00 25.29 C -ATOM 3759 O LYS D 65 -19.376 -11.449 -17.320 1.00 24.58 O -ATOM 3760 CB LYS D 65 -21.237 -9.249 -19.016 1.00 42.10 C -ATOM 3761 CG LYS D 65 -21.741 -10.662 -18.763 1.00 41.04 C -ATOM 3762 CD LYS D 65 -22.779 -10.191 -20.722 1.00 41.66 C -ATOM 3763 CE LYS D 65 -22.954 -12.381 -20.558 1.00 58.61 C -ATOM 3764 NZ LYS D 65 -24.294 -12.168 -21.421 1.00 49.59 N -ATOM 3765 N LYS D 66 -18.192 -10.318 -18.949 1.00 22.59 N -ATOM 3766 CA LYS D 66 -17.187 -11.342 -19.305 1.00 23.91 C -ATOM 3767 C LYS D 66 -16.648 -11.569 -17.853 1.00 25.32 C -ATOM 3768 O LYS D 66 -16.190 -12.713 -17.500 1.00 23.23 O -ATOM 3769 CB LYS D 66 -16.360 -10.927 -20.397 1.00 18.18 C -ATOM 3770 CG LYS D 66 -15.506 -11.226 -21.025 1.00 49.93 C -ATOM 3771 CD LYS D 66 -15.452 -11.136 -23.086 1.00 31.44 C -ATOM 3772 CE LYS D 66 -14.594 -13.236 -23.101 1.00 50.83 C -ATOM 3773 NZ LYS D 66 -13.105 -13.073 -24.350 1.00 53.30 N -ATOM 3774 N VAL D 67 -16.012 -10.379 -17.238 1.00 17.89 N -ATOM 3775 CA VAL D 67 -15.129 -10.761 -16.039 1.00 17.07 C -ATOM 3776 C VAL D 67 -15.858 -11.174 -14.995 1.00 11.37 C -ATOM 3777 O VAL D 67 -15.392 -12.090 -14.267 1.00 18.26 O -ATOM 3778 CB VAL D 67 -14.485 -9.126 -15.950 1.00 18.16 C -ATOM 3779 CG1 VAL D 67 -14.204 -9.183 -14.372 1.00 22.61 C -ATOM 3780 CG2 VAL D 67 -13.683 -8.637 -17.078 1.00 19.30 C -ATOM 3781 N LEU D 68 -17.081 -10.772 -14.714 1.00 12.24 N -ATOM 3782 CA LEU D 68 -17.709 -11.246 -13.544 1.00 14.83 C -ATOM 3783 C LEU D 68 -18.294 -12.710 -13.662 1.00 13.25 C -ATOM 3784 O LEU D 68 -18.430 -13.575 -12.845 1.00 18.25 O -ATOM 3785 CB LEU D 68 -18.960 -10.522 -12.977 1.00 23.35 C -ATOM 3786 CG LEU D 68 -19.065 -9.950 -11.782 1.00 32.52 C -ATOM 3787 CD1 LEU D 68 -18.211 -10.021 -10.888 1.00 40.78 C -ATOM 3788 CD2 LEU D 68 -20.119 -9.201 -11.516 1.00 39.22 C -ATOM 3789 N GLY D 69 -18.532 -13.001 -15.044 1.00 22.38 N -ATOM 3790 CA GLY D 69 -18.677 -14.387 -15.364 1.00 27.48 C -ATOM 3791 C GLY D 69 -17.639 -15.482 -15.016 1.00 17.57 C -ATOM 3792 O GLY D 69 -17.849 -16.416 -14.366 1.00 21.01 O -ATOM 3793 N ALA D 70 -16.381 -14.966 -15.333 1.00 17.61 N -ATOM 3794 CA ALA D 70 -15.237 -15.816 -14.969 1.00 17.42 C -ATOM 3795 C ALA D 70 -15.098 -15.818 -13.537 1.00 19.59 C -ATOM 3796 O ALA D 70 -14.642 -16.873 -12.761 1.00 18.72 O -ATOM 3797 CB ALA D 70 -14.109 -15.221 -15.702 1.00 18.83 C -ATOM 3798 N PHE D 71 -15.369 -14.689 -12.922 1.00 18.97 N -ATOM 3799 CA PHE D 71 -15.352 -14.546 -11.295 1.00 24.55 C -ATOM 3800 C PHE D 71 -16.405 -15.564 -10.716 1.00 22.73 C -ATOM 3801 O PHE D 71 -15.988 -16.296 -9.916 1.00 26.00 O -ATOM 3802 CB PHE D 71 -15.526 -13.076 -10.943 1.00 18.78 C -ATOM 3803 CG PHE D 71 -15.587 -12.889 -9.418 1.00 15.63 C -ATOM 3804 CD1 PHE D 71 -14.330 -12.356 -8.913 1.00 23.81 C -ATOM 3805 CD2 PHE D 71 -16.955 -13.108 -8.941 1.00 34.86 C -ATOM 3806 CE1 PHE D 71 -14.431 -12.324 -7.507 1.00 19.91 C -ATOM 3807 CE2 PHE D 71 -16.645 -13.000 -7.472 1.00 36.36 C -ATOM 3808 CZ PHE D 71 -15.423 -12.584 -6.796 1.00 26.08 C -ATOM 3809 N SER D 72 -17.526 -15.632 -11.448 1.00 19.94 N -ATOM 3810 CA SER D 72 -18.560 -16.484 -11.205 1.00 23.38 C -ATOM 3811 C SER D 72 -18.098 -17.836 -10.814 1.00 24.72 C -ATOM 3812 O SER D 72 -18.305 -18.802 -9.908 1.00 26.53 O -ATOM 3813 CB SER D 72 -20.212 -16.588 -11.400 1.00 29.23 C -ATOM 3814 OG SER D 72 -20.268 -15.282 -11.624 1.00 41.11 O -ATOM 3815 N ASP D 73 -17.601 -18.307 -12.047 1.00 28.33 N -ATOM 3816 CA ASP D 73 -16.810 -19.464 -12.087 1.00 41.54 C -ATOM 3817 C ASP D 73 -16.106 -20.105 -11.342 1.00 28.94 C -ATOM 3818 O ASP D 73 -15.997 -21.061 -10.645 1.00 34.21 O -ATOM 3819 CB ASP D 73 -16.190 -20.100 -13.720 1.00 46.96 C -ATOM 3820 CG ASP D 73 -17.426 -20.027 -14.053 1.00 54.92 C -ATOM 3821 OD1 ASP D 73 -18.701 -19.481 -14.810 1.00 44.49 O -ATOM 3822 OD2 ASP D 73 -16.811 -19.333 -16.112 1.00 50.27 O -ATOM 3823 N GLY D 74 -15.211 -19.059 -10.501 1.00 26.75 N -ATOM 3824 CA GLY D 74 -14.376 -19.390 -9.473 1.00 22.69 C -ATOM 3825 C GLY D 74 -14.851 -19.537 -8.039 1.00 23.14 C -ATOM 3826 O GLY D 74 -14.419 -20.191 -7.094 1.00 29.20 O -ATOM 3827 N LEU D 75 -16.177 -18.924 -8.005 1.00 21.18 N -ATOM 3828 CA LEU D 75 -16.870 -19.385 -6.815 1.00 34.17 C -ATOM 3829 C LEU D 75 -17.117 -20.780 -6.565 1.00 37.46 C -ATOM 3830 O LEU D 75 -17.563 -21.063 -5.534 1.00 40.90 O -ATOM 3831 CB LEU D 75 -18.078 -18.207 -6.714 1.00 36.63 C -ATOM 3832 CG LEU D 75 -17.957 -16.908 -6.209 1.00 28.96 C -ATOM 3833 CD1 LEU D 75 -16.674 -16.783 -5.652 1.00 54.84 C -ATOM 3834 CD2 LEU D 75 -18.450 -15.831 -6.570 1.00 41.72 C -ATOM 3835 N ALA D 76 -17.372 -21.329 -7.689 1.00 36.74 N -ATOM 3836 CA ALA D 76 -17.490 -23.239 -8.009 1.00 46.27 C -ATOM 3837 C ALA D 76 -16.460 -23.394 -7.753 1.00 39.68 C -ATOM 3838 O ALA D 76 -16.371 -24.793 -7.251 1.00 39.55 O -ATOM 3839 CB ALA D 76 -18.034 -22.779 -9.158 1.00 52.59 C -ATOM 3840 N HIS D 77 -15.221 -22.931 -7.252 1.00 34.88 N -ATOM 3841 CA HIS D 77 -14.175 -23.705 -7.014 1.00 37.75 C -ATOM 3842 C HIS D 77 -12.911 -22.947 -6.253 1.00 36.30 C -ATOM 3843 O HIS D 77 -11.715 -22.807 -6.207 1.00 30.91 O -ATOM 3844 CB HIS D 77 -13.016 -23.968 -8.303 1.00 35.95 C -ATOM 3845 CG HIS D 77 -13.662 -24.672 -9.381 1.00 39.15 C -ATOM 3846 ND1 HIS D 77 -14.327 -23.756 -10.232 1.00 58.22 N -ATOM 3847 CD2 HIS D 77 -13.455 -26.062 -9.566 1.00 48.66 C -ATOM 3848 CE1 HIS D 77 -15.214 -25.034 -11.337 1.00 49.77 C -ATOM 3849 NE2 HIS D 77 -14.945 -25.798 -10.683 1.00 36.55 N -ATOM 3850 N LEU D 78 -13.652 -22.590 -4.941 1.00 30.38 N -ATOM 3851 CA LEU D 78 -13.049 -22.225 -3.904 1.00 35.53 C -ATOM 3852 C LEU D 78 -11.853 -22.307 -3.241 1.00 31.52 C -ATOM 3853 O LEU D 78 -11.095 -21.930 -2.681 1.00 30.87 O -ATOM 3854 CB LEU D 78 -14.166 -21.218 -2.929 1.00 35.71 C -ATOM 3855 CG LEU D 78 -14.517 -19.696 -3.089 1.00 42.09 C -ATOM 3856 CD1 LEU D 78 -16.000 -19.812 -2.269 1.00 40.33 C -ATOM 3857 CD2 LEU D 78 -14.206 -18.936 -3.409 1.00 43.79 C -ATOM 3858 N ASP D 79 -11.841 -23.798 -3.366 1.00 27.09 N -ATOM 3859 CA ASP D 79 -10.671 -24.163 -2.603 1.00 39.93 C -ATOM 3860 C ASP D 79 -9.351 -24.818 -3.691 1.00 38.31 C -ATOM 3861 O ASP D 79 -8.220 -24.950 -3.380 1.00 37.24 O -ATOM 3862 CB ASP D 79 -11.204 -25.807 -2.720 1.00 49.19 C -ATOM 3863 CG ASP D 79 -12.348 -25.806 -2.280 1.00 60.14 C -ATOM 3864 OD1 ASP D 79 -12.747 -27.563 -1.436 1.00 58.54 O -ATOM 3865 OD2 ASP D 79 -11.720 -25.378 -0.450 1.00 49.76 O -ATOM 3866 N ASN D 80 -9.928 -24.165 -4.813 1.00 33.30 N -ATOM 3867 CA ASN D 80 -8.432 -24.074 -5.725 1.00 41.52 C -ATOM 3868 C ASN D 80 -8.757 -22.972 -7.024 1.00 29.72 C -ATOM 3869 O ASN D 80 -8.410 -23.186 -8.009 1.00 26.63 O -ATOM 3870 CB ASN D 80 -8.335 -25.027 -6.387 1.00 65.88 C -ATOM 3871 CG ASN D 80 -8.226 -26.006 -7.178 1.00 79.70 C -ATOM 3872 OD1 ASN D 80 -6.646 -26.141 -7.665 1.00 64.12 O -ATOM 3873 ND2 ASN D 80 -9.445 -26.052 -7.340 1.00 80.04 N -ATOM 3874 N LEU D 81 -8.454 -21.884 -6.206 1.00 24.36 N -ATOM 3875 CA LEU D 81 -8.539 -20.715 -7.081 1.00 25.83 C -ATOM 3876 C LEU D 81 -7.273 -20.637 -8.041 1.00 31.94 C -ATOM 3877 O LEU D 81 -7.415 -20.270 -9.214 1.00 25.17 O -ATOM 3878 CB LEU D 81 -8.579 -19.629 -6.126 1.00 20.37 C -ATOM 3879 CG LEU D 81 -9.997 -19.259 -5.589 1.00 25.65 C -ATOM 3880 CD1 LEU D 81 -9.956 -18.414 -4.674 1.00 40.59 C -ATOM 3881 CD2 LEU D 81 -11.103 -19.225 -6.396 1.00 23.30 C -ATOM 3882 N LYS D 82 -6.051 -20.893 -7.415 1.00 30.20 N -ATOM 3883 CA LYS D 82 -4.933 -20.852 -8.394 1.00 28.24 C -ATOM 3884 C LYS D 82 -5.124 -21.707 -9.528 1.00 33.91 C -ATOM 3885 O LYS D 82 -4.821 -21.459 -10.648 1.00 25.48 O -ATOM 3886 CB LYS D 82 -3.611 -21.239 -7.521 1.00 33.73 C -ATOM 3887 CG LYS D 82 -3.123 -20.210 -6.921 1.00 40.61 C -ATOM 3888 CD LYS D 82 -1.453 -20.533 -6.100 1.00 64.29 C -ATOM 3889 CE LYS D 82 -2.245 -18.592 -4.901 1.00 50.61 C -ATOM 3890 NZ LYS D 82 -1.640 -20.210 -4.012 1.00 57.77 N -ATOM 3891 N GLY D 83 -5.684 -23.133 -9.543 1.00 30.21 N -ATOM 3892 CA GLY D 83 -5.556 -24.039 -10.631 1.00 23.41 C -ATOM 3893 C GLY D 83 -6.710 -23.708 -11.373 1.00 31.79 C -ATOM 3894 O GLY D 83 -6.545 -23.384 -12.827 1.00 27.38 O -ATOM 3895 N THR D 84 -7.929 -22.850 -10.943 1.00 27.06 N -ATOM 3896 CA THR D 84 -8.896 -22.475 -11.769 1.00 31.17 C -ATOM 3897 C THR D 84 -8.254 -21.368 -12.862 1.00 35.08 C -ATOM 3898 O THR D 84 -9.023 -21.163 -13.732 1.00 26.93 O -ATOM 3899 CB THR D 84 -10.186 -21.934 -10.990 1.00 26.68 C -ATOM 3900 OG1 THR D 84 -10.450 -22.939 -10.341 1.00 41.82 O -ATOM 3901 CG2 THR D 84 -11.436 -21.350 -11.615 1.00 32.36 C -ATOM 3902 N PHE D 85 -7.713 -20.405 -12.026 1.00 23.78 N -ATOM 3903 CA PHE D 85 -7.538 -18.984 -12.806 1.00 17.94 C -ATOM 3904 C PHE D 85 -6.138 -19.115 -13.564 1.00 20.32 C -ATOM 3905 O PHE D 85 -5.528 -18.116 -14.137 1.00 18.46 O -ATOM 3906 CB PHE D 85 -7.425 -17.913 -11.819 1.00 16.82 C -ATOM 3907 CG PHE D 85 -8.885 -17.567 -11.680 1.00 15.41 C -ATOM 3908 CD1 PHE D 85 -9.422 -17.861 -10.346 1.00 21.43 C -ATOM 3909 CD2 PHE D 85 -9.605 -16.833 -12.552 1.00 29.52 C -ATOM 3910 CE1 PHE D 85 -10.820 -17.512 -9.993 1.00 27.35 C -ATOM 3911 CE2 PHE D 85 -11.060 -16.678 -12.198 1.00 23.38 C -ATOM 3912 CZ PHE D 85 -11.788 -16.979 -10.988 1.00 20.96 C -ATOM 3913 N ALA D 86 -5.306 -20.190 -13.510 1.00 16.78 N -ATOM 3914 CA ALA D 86 -3.786 -20.129 -13.990 1.00 21.66 C -ATOM 3915 C ALA D 86 -3.859 -19.751 -15.592 1.00 13.70 C -ATOM 3916 O ALA D 86 -2.977 -18.900 -15.942 1.00 16.83 O -ATOM 3917 CB ALA D 86 -3.276 -21.717 -14.150 1.00 23.60 C -ATOM 3918 N THR D 87 -4.799 -20.235 -16.291 1.00 17.09 N -ATOM 3919 CA THR D 87 -4.700 -19.770 -17.696 1.00 15.85 C -ATOM 3920 C THR D 87 -4.913 -18.223 -17.934 1.00 17.61 C -ATOM 3921 O THR D 87 -4.226 -17.589 -18.665 1.00 21.97 O -ATOM 3922 CB THR D 87 -5.803 -20.551 -18.552 1.00 23.34 C -ATOM 3923 OG1 THR D 87 -5.495 -21.943 -18.388 1.00 26.37 O -ATOM 3924 CG2 THR D 87 -5.595 -20.344 -19.930 1.00 26.08 C -ATOM 3925 N LEU D 88 -5.980 -17.807 -17.359 1.00 19.60 N -ATOM 3926 CA LEU D 88 -6.271 -16.457 -17.415 1.00 18.18 C -ATOM 3927 C LEU D 88 -5.187 -15.518 -16.684 1.00 15.66 C -ATOM 3928 O LEU D 88 -4.841 -14.368 -17.168 1.00 16.54 O -ATOM 3929 CB LEU D 88 -7.631 -16.058 -16.725 1.00 24.93 C -ATOM 3930 CG LEU D 88 -8.806 -16.413 -17.604 1.00 29.68 C -ATOM 3931 CD1 LEU D 88 -9.913 -16.362 -16.626 1.00 33.11 C -ATOM 3932 CD2 LEU D 88 -8.780 -15.785 -18.779 1.00 21.96 C -ATOM 3933 N SER D 89 -4.550 -16.190 -15.577 1.00 21.20 N -ATOM 3934 CA SER D 89 -3.384 -15.545 -14.950 1.00 17.78 C -ATOM 3935 C SER D 89 -2.295 -15.067 -15.986 1.00 16.70 C -ATOM 3936 O SER D 89 -1.619 -14.055 -16.257 1.00 15.86 O -ATOM 3937 CB SER D 89 -2.725 -16.272 -13.880 1.00 19.29 C -ATOM 3938 OG SER D 89 -1.733 -15.529 -13.240 1.00 14.95 O -ATOM 3939 N GLU D 90 -1.806 -16.218 -16.719 1.00 15.58 N -ATOM 3940 CA GLU D 90 -0.961 -16.101 -17.900 1.00 21.65 C -ATOM 3941 C GLU D 90 -1.319 -15.129 -19.030 1.00 13.57 C -ATOM 3942 O GLU D 90 -0.576 -14.403 -19.451 1.00 18.38 O -ATOM 3943 CB GLU D 90 -0.700 -17.640 -18.253 1.00 19.08 C -ATOM 3944 CG GLU D 90 0.585 -17.390 -19.009 1.00 38.09 C -ATOM 3945 CD GLU D 90 0.916 -19.788 -19.196 1.00 62.85 C -ATOM 3946 OE1 GLU D 90 0.495 -19.279 -20.696 1.00 54.38 O -ATOM 3947 OE2 GLU D 90 -0.172 -20.134 -18.632 1.00 49.69 O -ATOM 3948 N LEU D 91 -2.614 -15.260 -19.279 1.00 12.64 N -ATOM 3949 CA LEU D 91 -2.918 -14.282 -20.199 1.00 11.29 C -ATOM 3950 C LEU D 91 -2.769 -12.767 -19.975 1.00 14.82 C -ATOM 3951 O LEU D 91 -2.486 -11.814 -20.708 1.00 14.36 O -ATOM 3952 CB LEU D 91 -4.443 -14.616 -20.526 1.00 13.30 C -ATOM 3953 CG LEU D 91 -5.325 -13.643 -21.412 1.00 17.13 C -ATOM 3954 CD1 LEU D 91 -4.702 -13.618 -23.000 1.00 25.95 C -ATOM 3955 CD2 LEU D 91 -6.752 -13.787 -21.472 1.00 20.87 C -ATOM 3956 N HIS D 92 -3.278 -12.509 -18.598 1.00 14.55 N -ATOM 3957 CA HIS D 92 -3.429 -10.968 -18.356 1.00 18.41 C -ATOM 3958 C HIS D 92 -1.750 -10.659 -17.942 1.00 25.22 C -ATOM 3959 O HIS D 92 -1.542 -9.487 -18.276 1.00 15.09 O -ATOM 3960 CB HIS D 92 -3.870 -11.061 -16.956 1.00 16.94 C -ATOM 3961 CG HIS D 92 -5.443 -10.779 -17.044 1.00 14.87 C -ATOM 3962 ND1 HIS D 92 -6.226 -12.088 -17.324 1.00 14.65 N -ATOM 3963 CD2 HIS D 92 -6.494 -9.930 -17.027 1.00 12.93 C -ATOM 3964 CE1 HIS D 92 -7.513 -11.488 -17.344 1.00 12.97 C -ATOM 3965 NE2 HIS D 92 -7.794 -10.264 -17.456 1.00 18.10 N -ATOM 3966 N CYS D 93 -0.853 -11.610 -17.750 1.00 16.12 N -ATOM 3967 CA CYS D 93 0.671 -11.156 -17.799 1.00 16.35 C -ATOM 3968 C CYS D 93 1.184 -10.895 -19.303 1.00 18.55 C -ATOM 3969 O CYS D 93 1.616 -9.948 -19.471 1.00 17.22 O -ATOM 3970 CB CYS D 93 1.177 -12.201 -16.844 1.00 20.93 C -ATOM 3971 SG CYS D 93 3.106 -11.680 -16.838 1.00 18.90 S -ATOM 3972 N ASP D 94 1.071 -12.148 -19.853 1.00 14.32 N -ATOM 3973 CA ASP D 94 2.076 -12.170 -21.195 1.00 16.01 C -ATOM 3974 C ASP D 94 1.351 -11.461 -22.242 1.00 19.68 C -ATOM 3975 O ASP D 94 1.981 -11.016 -23.089 1.00 27.14 O -ATOM 3976 CB ASP D 94 2.163 -13.661 -21.334 1.00 20.44 C -ATOM 3977 CG ASP D 94 3.220 -14.533 -20.409 1.00 36.43 C -ATOM 3978 OD1 ASP D 94 3.523 -13.728 -19.788 1.00 32.86 O -ATOM 3979 OD2 ASP D 94 2.735 -15.960 -20.657 1.00 40.09 O -ATOM 3980 N LYS D 95 0.079 -11.509 -22.378 1.00 14.90 N -ATOM 3981 CA LYS D 95 -0.657 -10.830 -23.618 1.00 16.76 C -ATOM 3982 C LYS D 95 -1.037 -9.542 -23.369 1.00 18.82 C -ATOM 3983 O LYS D 95 -1.025 -8.517 -23.887 1.00 19.72 O -ATOM 3984 CB LYS D 95 -1.739 -11.719 -24.171 1.00 24.57 C -ATOM 3985 CG LYS D 95 -1.405 -13.254 -24.270 1.00 49.61 C -ATOM 3986 CD LYS D 95 0.033 -12.822 -25.830 1.00 60.17 C -ATOM 3987 CE LYS D 95 0.875 -13.698 -26.541 1.00 57.82 C -ATOM 3988 NZ LYS D 95 1.951 -12.652 -27.842 1.00 59.53 N -ATOM 3989 N LEU D 96 -1.816 -9.347 -21.943 1.00 16.80 N -ATOM 3990 CA LEU D 96 -2.489 -8.095 -21.711 1.00 16.58 C -ATOM 3991 C LEU D 96 -1.557 -6.998 -20.981 1.00 16.01 C -ATOM 3992 O LEU D 96 -2.025 -5.870 -20.986 1.00 15.73 O -ATOM 3993 CB LEU D 96 -3.813 -8.447 -21.040 1.00 21.01 C -ATOM 3994 CG LEU D 96 -4.799 -9.421 -21.657 1.00 22.06 C -ATOM 3995 CD1 LEU D 96 -6.039 -9.748 -20.763 1.00 15.50 C -ATOM 3996 CD2 LEU D 96 -5.152 -8.823 -22.921 1.00 34.04 C -ATOM 3997 N HIS D 97 -0.781 -7.579 -20.217 1.00 18.03 N -ATOM 3998 CA HIS D 97 0.244 -6.637 -19.580 1.00 18.48 C -ATOM 3999 C HIS D 97 -0.432 -5.796 -18.443 1.00 13.60 C -ATOM 4000 O HIS D 97 -0.253 -4.620 -18.215 1.00 15.07 O -ATOM 4001 CB HIS D 97 0.990 -5.653 -20.400 1.00 24.24 C -ATOM 4002 CG HIS D 97 1.776 -6.391 -21.656 1.00 28.24 C -ATOM 4003 ND1 HIS D 97 2.554 -7.432 -21.385 1.00 26.25 N -ATOM 4004 CD2 HIS D 97 1.271 -6.244 -22.910 1.00 35.10 C -ATOM 4005 CE1 HIS D 97 3.136 -7.961 -22.703 1.00 25.85 C -ATOM 4006 NE2 HIS D 97 2.325 -7.208 -23.322 1.00 28.28 N -ATOM 4007 N VAL D 98 -1.455 -6.545 -17.703 1.00 15.21 N -ATOM 4008 CA VAL D 98 -2.210 -5.794 -16.736 1.00 14.55 C -ATOM 4009 C VAL D 98 -1.489 -5.841 -15.285 1.00 10.52 C -ATOM 4010 O VAL D 98 -1.368 -7.002 -14.827 1.00 11.77 O -ATOM 4011 CB VAL D 98 -3.549 -6.468 -16.502 1.00 15.30 C -ATOM 4012 CG1 VAL D 98 -4.339 -5.933 -15.325 1.00 15.30 C -ATOM 4013 CG2 VAL D 98 -4.285 -6.152 -17.968 1.00 17.14 C -ATOM 4014 N ASP D 99 -1.167 -4.730 -14.701 1.00 9.86 N -ATOM 4015 CA ASP D 99 -0.610 -4.765 -13.282 1.00 10.99 C -ATOM 4016 C ASP D 99 -1.652 -5.465 -12.445 1.00 12.34 C -ATOM 4017 O ASP D 99 -2.837 -4.921 -12.433 1.00 15.90 O -ATOM 4018 CB ASP D 99 -0.421 -3.334 -12.976 1.00 12.59 C -ATOM 4019 CG ASP D 99 0.231 -3.018 -11.481 1.00 12.64 C -ATOM 4020 OD1 ASP D 99 0.529 -1.770 -11.464 1.00 11.35 O -ATOM 4021 OD2 ASP D 99 0.421 -4.097 -10.818 1.00 14.04 O -ATOM 4022 N PRO D 100 -1.293 -6.422 -11.755 1.00 16.57 N -ATOM 4023 CA PRO D 100 -2.075 -7.130 -10.712 1.00 11.14 C -ATOM 4024 C PRO D 100 -2.767 -6.164 -9.672 1.00 11.03 C -ATOM 4025 O PRO D 100 -3.730 -6.728 -9.131 1.00 12.40 O -ATOM 4026 CB PRO D 100 -1.455 -8.509 -10.454 1.00 18.57 C -ATOM 4027 CG PRO D 100 -0.120 -8.351 -10.644 1.00 16.52 C -ATOM 4028 CD PRO D 100 0.008 -7.085 -11.678 1.00 15.61 C -ATOM 4029 N GLU D 101 -2.120 -5.022 -9.432 1.00 9.29 N -ATOM 4030 CA GLU D 101 -2.721 -4.184 -8.535 1.00 12.45 C -ATOM 4031 C GLU D 101 -4.150 -3.766 -8.894 1.00 20.07 C -ATOM 4032 O GLU D 101 -5.139 -3.640 -8.044 1.00 15.47 O -ATOM 4033 CB GLU D 101 -1.898 -2.971 -8.352 1.00 18.48 C -ATOM 4034 CG GLU D 101 -2.751 -1.912 -7.301 1.00 30.49 C -ATOM 4035 CD GLU D 101 -2.928 -2.595 -5.361 1.00 32.99 C -ATOM 4036 OE1 GLU D 101 -1.814 -3.251 -5.501 1.00 22.72 O -ATOM 4037 OE2 GLU D 101 -3.790 -1.433 -5.275 1.00 37.16 O -ATOM 4038 N ASN D 102 -4.416 -3.866 -10.222 1.00 14.86 N -ATOM 4039 CA ASN D 102 -5.827 -3.553 -10.820 1.00 14.38 C -ATOM 4040 C ASN D 102 -6.730 -4.706 -10.375 1.00 12.83 C -ATOM 4041 O ASN D 102 -8.073 -4.305 -10.051 1.00 15.98 O -ATOM 4042 CB ASN D 102 -5.825 -3.726 -12.202 1.00 15.85 C -ATOM 4043 CG ASN D 102 -5.178 -2.418 -12.728 1.00 20.86 C -ATOM 4044 OD1 ASN D 102 -5.594 -1.386 -12.707 1.00 17.49 O -ATOM 4045 ND2 ASN D 102 -3.900 -2.610 -13.401 1.00 22.52 N -ATOM 4046 N PHE D 103 -6.450 -5.902 -10.088 1.00 11.06 N -ATOM 4047 CA PHE D 103 -7.223 -7.062 -9.594 1.00 11.10 C -ATOM 4048 C PHE D 103 -7.838 -6.627 -8.138 1.00 14.83 C -ATOM 4049 O PHE D 103 -9.038 -6.926 -7.755 1.00 12.07 O -ATOM 4050 CB PHE D 103 -6.641 -8.378 -9.453 1.00 14.26 C -ATOM 4051 CG PHE D 103 -5.978 -8.685 -10.884 1.00 14.43 C -ATOM 4052 CD1 PHE D 103 -6.722 -8.442 -12.150 1.00 22.91 C -ATOM 4053 CD2 PHE D 103 -4.777 -9.418 -10.920 1.00 19.84 C -ATOM 4054 CE1 PHE D 103 -6.285 -8.812 -13.376 1.00 22.48 C -ATOM 4055 CE2 PHE D 103 -4.350 -9.752 -12.200 1.00 13.44 C -ATOM 4056 CZ PHE D 103 -4.988 -9.426 -13.435 1.00 16.91 C -ATOM 4057 N ARG D 104 -6.979 -6.041 -7.313 1.00 14.96 N -ATOM 4058 CA ARG D 104 -7.236 -5.640 -5.946 1.00 18.64 C -ATOM 4059 C ARG D 104 -8.352 -4.439 -5.984 1.00 17.76 C -ATOM 4060 O ARG D 104 -9.251 -4.482 -5.206 1.00 14.29 O -ATOM 4061 CB ARG D 104 -5.925 -5.205 -5.097 1.00 19.67 C -ATOM 4062 CG ARG D 104 -5.188 -6.366 -5.055 1.00 39.66 C -ATOM 4063 CD ARG D 104 -3.686 -6.042 -4.324 1.00 67.99 C -ATOM 4064 NE ARG D 104 -3.285 -7.833 -4.405 1.00 67.11 N -ATOM 4065 CZ ARG D 104 -0.829 -7.130 -4.074 1.00 80.12 C -ATOM 4066 NH1 ARG D 104 -1.228 -5.714 -3.904 1.00 77.56 N -ATOM 4067 NH2 ARG D 104 -1.024 -7.904 -3.149 1.00 80.12 N -ATOM 4068 N LEU D 105 -8.019 -3.490 -6.857 1.00 14.78 N -ATOM 4069 CA LEU D 105 -8.933 -2.377 -6.997 1.00 11.66 C -ATOM 4070 C LEU D 105 -10.366 -2.815 -7.384 1.00 13.52 C -ATOM 4071 O LEU D 105 -11.325 -2.484 -6.781 1.00 12.56 O -ATOM 4072 CB LEU D 105 -8.385 -1.463 -7.865 1.00 16.32 C -ATOM 4073 CG LEU D 105 -7.155 -0.533 -7.691 1.00 23.61 C -ATOM 4074 CD1 LEU D 105 -6.564 0.347 -8.601 1.00 25.65 C -ATOM 4075 CD2 LEU D 105 -7.175 -0.008 -6.272 1.00 30.28 C -ATOM 4076 N LEU D 106 -10.388 -3.731 -8.359 1.00 11.11 N -ATOM 4077 CA LEU D 106 -11.776 -4.169 -8.774 1.00 10.81 C -ATOM 4078 C LEU D 106 -12.425 -4.909 -7.735 1.00 7.04 C -ATOM 4079 O LEU D 106 -13.596 -4.860 -7.508 1.00 8.65 O -ATOM 4080 CB LEU D 106 -11.565 -5.136 -9.996 1.00 12.84 C -ATOM 4081 CG LEU D 106 -12.908 -5.591 -10.559 1.00 16.25 C -ATOM 4082 CD1 LEU D 106 -13.855 -4.506 -11.046 1.00 16.77 C -ATOM 4083 CD2 LEU D 106 -12.516 -6.548 -11.540 1.00 20.04 C -ATOM 4084 N GLY D 107 -11.735 -5.688 -6.939 1.00 12.52 N -ATOM 4085 CA GLY D 107 -12.179 -6.516 -5.777 1.00 16.15 C -ATOM 4086 C GLY D 107 -12.899 -5.574 -4.792 1.00 14.99 C -ATOM 4087 O GLY D 107 -14.015 -5.773 -4.332 1.00 12.81 O -ATOM 4088 N ASN D 108 -12.285 -4.436 -4.514 1.00 12.36 N -ATOM 4089 CA ASN D 108 -12.802 -3.491 -3.621 1.00 14.00 C -ATOM 4090 C ASN D 108 -13.963 -2.724 -4.098 1.00 11.43 C -ATOM 4091 O ASN D 108 -15.056 -2.507 -3.385 1.00 12.39 O -ATOM 4092 CB ASN D 108 -11.844 -2.454 -3.053 1.00 18.57 C -ATOM 4093 CG ASN D 108 -10.617 -3.293 -1.988 1.00 22.26 C -ATOM 4094 OD1 ASN D 108 -11.199 -4.293 -1.311 1.00 22.78 O -ATOM 4095 ND2 ASN D 108 -9.853 -2.344 -1.843 1.00 30.03 N -ATOM 4096 N VAL D 109 -13.924 -2.387 -5.385 1.00 10.09 N -ATOM 4097 CA VAL D 109 -15.064 -1.848 -6.032 1.00 8.21 C -ATOM 4098 C VAL D 109 -16.234 -2.783 -6.101 1.00 9.89 C -ATOM 4099 O VAL D 109 -17.335 -2.321 -5.728 1.00 11.76 O -ATOM 4100 CB VAL D 109 -14.656 -1.351 -7.492 1.00 11.59 C -ATOM 4101 CG1 VAL D 109 -15.861 -0.846 -8.320 1.00 17.96 C -ATOM 4102 CG2 VAL D 109 -13.771 -0.178 -7.377 1.00 17.98 C -ATOM 4103 N LEU D 110 -15.952 -4.083 -6.403 1.00 9.62 N -ATOM 4104 CA LEU D 110 -17.024 -5.059 -6.369 1.00 14.08 C -ATOM 4105 C LEU D 110 -17.831 -5.035 -5.141 1.00 11.97 C -ATOM 4106 O LEU D 110 -19.008 -5.257 -4.826 1.00 10.97 O -ATOM 4107 CB LEU D 110 -16.600 -6.309 -6.770 1.00 15.34 C -ATOM 4108 CG LEU D 110 -17.478 -7.458 -6.761 1.00 14.97 C -ATOM 4109 CD1 LEU D 110 -18.670 -7.282 -7.592 1.00 23.21 C -ATOM 4110 CD2 LEU D 110 -16.862 -8.829 -7.132 1.00 26.92 C -ATOM 4111 N VAL D 111 -16.932 -5.013 -3.909 1.00 14.50 N -ATOM 4112 CA VAL D 111 -17.557 -5.003 -2.482 1.00 11.82 C -ATOM 4113 C VAL D 111 -18.496 -3.835 -2.339 1.00 14.01 C -ATOM 4114 O VAL D 111 -19.560 -3.938 -1.746 1.00 12.03 O -ATOM 4115 CB VAL D 111 -16.468 -5.174 -1.423 1.00 12.62 C -ATOM 4116 CG1 VAL D 111 -17.105 -4.887 -0.077 1.00 15.85 C -ATOM 4117 CG2 VAL D 111 -15.845 -6.615 -1.505 1.00 10.77 C -ATOM 4118 N CYS D 112 -17.954 -2.598 -2.876 1.00 13.62 N -ATOM 4119 CA CYS D 112 -18.674 -1.428 -2.875 1.00 13.72 C -ATOM 4120 C CYS D 112 -20.245 -1.545 -3.397 1.00 20.10 C -ATOM 4121 O CYS D 112 -21.199 -1.153 -2.984 1.00 16.56 O -ATOM 4122 CB CYS D 112 -18.077 -0.213 -3.441 1.00 12.95 C -ATOM 4123 SG CYS D 112 -16.890 0.371 -2.238 1.00 15.21 S -ATOM 4124 N VAL D 113 -20.090 -2.259 -4.565 1.00 17.02 N -ATOM 4125 CA VAL D 113 -21.229 -2.476 -5.537 1.00 12.28 C -ATOM 4126 C VAL D 113 -22.216 -3.415 -4.943 1.00 12.56 C -ATOM 4127 O VAL D 113 -23.393 -3.166 -4.833 1.00 15.84 O -ATOM 4128 CB VAL D 113 -20.819 -3.012 -6.914 1.00 17.85 C -ATOM 4129 CG1 VAL D 113 -22.007 -3.440 -7.657 1.00 18.74 C -ATOM 4130 CG2 VAL D 113 -20.123 -1.688 -7.807 1.00 21.41 C -ATOM 4131 N LEU D 114 -21.799 -4.480 -4.273 1.00 10.75 N -ATOM 4132 CA LEU D 114 -22.611 -5.453 -3.526 1.00 10.78 C -ATOM 4133 C LEU D 114 -23.336 -4.689 -2.455 1.00 19.00 C -ATOM 4134 O LEU D 114 -24.454 -4.811 -2.196 1.00 11.46 O -ATOM 4135 CB LEU D 114 -21.815 -6.582 -3.114 1.00 14.56 C -ATOM 4136 CG LEU D 114 -21.183 -7.401 -4.241 1.00 17.11 C -ATOM 4137 CD1 LEU D 114 -20.368 -8.591 -3.652 1.00 17.06 C -ATOM 4138 CD2 LEU D 114 -22.473 -8.135 -5.021 1.00 20.86 C -ATOM 4139 N ALA D 115 -22.573 -3.965 -1.677 1.00 11.71 N -ATOM 4140 CA ALA D 115 -23.177 -3.124 -0.512 1.00 11.69 C -ATOM 4141 C ALA D 115 -24.286 -2.193 -1.056 1.00 15.12 C -ATOM 4142 O ALA D 115 -25.190 -2.078 -0.405 1.00 15.47 O -ATOM 4143 CB ALA D 115 -22.014 -2.336 0.283 1.00 12.28 C -ATOM 4144 N HIS D 116 -23.996 -1.420 -2.116 1.00 15.03 N -ATOM 4145 CA HIS D 116 -24.955 -0.497 -2.730 1.00 12.09 C -ATOM 4146 C HIS D 116 -26.163 -1.244 -3.183 1.00 12.50 C -ATOM 4147 O HIS D 116 -27.367 -0.733 -2.977 1.00 15.93 O -ATOM 4148 CB HIS D 116 -24.260 0.137 -3.930 1.00 20.66 C -ATOM 4149 CG HIS D 116 -25.177 1.236 -4.511 1.00 27.72 C -ATOM 4150 ND1 HIS D 116 -25.302 1.194 -5.752 1.00 29.99 N -ATOM 4151 CD2 HIS D 116 -25.633 2.207 -3.823 1.00 30.96 C -ATOM 4152 CE1 HIS D 116 -26.002 2.415 -6.103 1.00 27.26 C -ATOM 4153 NE2 HIS D 116 -26.344 3.000 -4.762 1.00 28.89 N -ATOM 4154 N HIS D 117 -26.018 -2.363 -3.828 1.00 13.33 N -ATOM 4155 CA HIS D 117 -27.076 -3.136 -4.425 1.00 15.24 C -ATOM 4156 C HIS D 117 -27.870 -3.712 -3.255 1.00 17.50 C -ATOM 4157 O HIS D 117 -29.133 -3.855 -3.315 1.00 16.06 O -ATOM 4158 CB HIS D 117 -26.496 -4.135 -5.434 1.00 17.22 C -ATOM 4159 CG HIS D 117 -27.385 -4.774 -6.024 1.00 54.91 C -ATOM 4160 ND1 HIS D 117 -28.250 -3.991 -7.312 1.00 47.40 N -ATOM 4161 CD2 HIS D 117 -28.517 -5.901 -5.930 1.00 49.34 C -ATOM 4162 CE1 HIS D 117 -29.253 -5.278 -7.522 1.00 48.36 C -ATOM 4163 NE2 HIS D 117 -29.230 -6.041 -6.924 1.00 37.10 N -ATOM 4164 N PHE D 118 -27.360 -4.464 -2.297 1.00 14.50 N -ATOM 4165 CA PHE D 118 -28.031 -5.299 -1.218 1.00 19.30 C -ATOM 4166 C PHE D 118 -28.313 -4.501 -0.028 1.00 20.52 C -ATOM 4167 O PHE D 118 -29.066 -5.081 0.915 1.00 18.09 O -ATOM 4168 CB PHE D 118 -27.213 -6.481 -0.908 1.00 18.97 C -ATOM 4169 CG PHE D 118 -27.223 -7.413 -2.204 1.00 18.93 C -ATOM 4170 CD1 PHE D 118 -26.304 -7.801 -3.109 1.00 24.34 C -ATOM 4171 CD2 PHE D 118 -28.509 -8.118 -2.367 1.00 26.48 C -ATOM 4172 CE1 PHE D 118 -26.170 -8.548 -4.227 1.00 20.81 C -ATOM 4173 CE2 PHE D 118 -28.524 -8.992 -3.636 1.00 22.90 C -ATOM 4174 CZ PHE D 118 -27.563 -8.928 -4.575 1.00 38.52 C -ATOM 4175 N GLY D 119 -27.754 -3.376 0.316 1.00 12.95 N -ATOM 4176 CA GLY D 119 -28.196 -2.563 1.458 1.00 17.60 C -ATOM 4177 C GLY D 119 -27.642 -3.404 2.740 1.00 22.58 C -ATOM 4178 O GLY D 119 -26.745 -4.123 2.946 1.00 17.60 O -ATOM 4179 N LYS D 120 -28.738 -3.418 3.697 1.00 21.46 N -ATOM 4180 CA LYS D 120 -28.403 -3.844 5.025 1.00 20.05 C -ATOM 4181 C LYS D 120 -28.472 -5.257 5.045 1.00 21.98 C -ATOM 4182 O LYS D 120 -27.730 -5.889 5.925 1.00 18.57 O -ATOM 4183 CB LYS D 120 -29.674 -3.273 5.899 1.00 27.28 C -ATOM 4184 CG LYS D 120 -30.525 -4.321 5.995 1.00 44.07 C -ATOM 4185 CD LYS D 120 -31.907 -4.631 6.867 1.00 48.21 C -ATOM 4186 CE LYS D 120 -33.041 -5.118 5.873 1.00 53.23 C -ATOM 4187 NZ LYS D 120 -34.578 -6.152 7.224 1.00 62.54 N -ATOM 4188 N GLU D 121 -28.504 -6.080 4.008 1.00 25.88 N -ATOM 4189 CA GLU D 121 -28.273 -7.343 3.934 1.00 20.02 C -ATOM 4190 C GLU D 121 -26.675 -7.822 3.749 1.00 18.96 C -ATOM 4191 O GLU D 121 -26.335 -8.975 4.074 1.00 16.05 O -ATOM 4192 CB GLU D 121 -29.032 -8.153 2.527 1.00 28.13 C -ATOM 4193 CG GLU D 121 -28.995 -9.238 2.561 1.00 40.20 C -ATOM 4194 CD GLU D 121 -30.346 -10.237 1.461 1.00 49.97 C -ATOM 4195 OE1 GLU D 121 -29.357 -11.293 1.004 1.00 36.73 O -ATOM 4196 OE2 GLU D 121 -30.336 -9.346 0.552 1.00 38.86 O -ATOM 4197 N PHE D 122 -26.073 -6.783 3.271 1.00 14.83 N -ATOM 4198 CA PHE D 122 -24.573 -7.060 3.133 1.00 20.37 C -ATOM 4199 C PHE D 122 -23.961 -6.641 4.530 1.00 15.94 C -ATOM 4200 O PHE D 122 -23.307 -5.592 4.698 1.00 17.73 O -ATOM 4201 CB PHE D 122 -24.256 -6.093 2.128 1.00 14.63 C -ATOM 4202 CG PHE D 122 -22.862 -6.484 1.494 1.00 12.39 C -ATOM 4203 CD1 PHE D 122 -22.569 -7.575 0.927 1.00 14.73 C -ATOM 4204 CD2 PHE D 122 -21.593 -5.712 1.717 1.00 15.96 C -ATOM 4205 CE1 PHE D 122 -21.227 -8.021 0.354 1.00 19.03 C -ATOM 4206 CE2 PHE D 122 -20.268 -6.011 1.383 1.00 16.31 C -ATOM 4207 CZ PHE D 122 -20.290 -7.145 0.714 1.00 19.86 C -ATOM 4208 N THR D 123 -24.154 -7.525 5.413 1.00 12.54 N -ATOM 4209 CA THR D 123 -23.654 -7.132 6.808 1.00 13.34 C -ATOM 4210 C THR D 123 -22.221 -7.283 6.854 1.00 15.73 C -ATOM 4211 O THR D 123 -21.546 -7.802 6.060 1.00 13.84 O -ATOM 4212 CB THR D 123 -24.160 -8.212 7.778 1.00 17.72 C -ATOM 4213 OG1 THR D 123 -23.892 -9.520 7.414 1.00 19.04 O -ATOM 4214 CG2 THR D 123 -25.951 -8.264 7.657 1.00 20.06 C -ATOM 4215 N PRO D 124 -21.722 -6.789 8.010 1.00 17.46 N -ATOM 4216 CA PRO D 124 -20.251 -6.940 8.311 1.00 14.41 C -ATOM 4217 C PRO D 124 -19.706 -8.259 8.132 1.00 12.05 C -ATOM 4218 O PRO D 124 -18.668 -8.405 7.486 1.00 13.28 O -ATOM 4219 CB PRO D 124 -20.088 -6.243 9.615 1.00 14.54 C -ATOM 4220 CG PRO D 124 -21.223 -5.227 9.715 1.00 15.93 C -ATOM 4221 CD PRO D 124 -22.358 -6.045 9.113 1.00 14.57 C -ATOM 4222 N PRO D 125 -20.257 -9.372 8.599 1.00 11.40 N -ATOM 4223 CA PRO D 125 -19.807 -10.596 8.366 1.00 17.87 C -ATOM 4224 C PRO D 125 -19.690 -11.236 6.993 1.00 15.21 C -ATOM 4225 O PRO D 125 -18.781 -11.857 6.488 1.00 14.41 O -ATOM 4226 CB PRO D 125 -20.651 -11.465 9.240 1.00 23.30 C -ATOM 4227 CG PRO D 125 -21.148 -10.683 10.183 1.00 26.37 C -ATOM 4228 CD PRO D 125 -21.413 -9.462 9.802 1.00 17.49 C -ATOM 4229 N VAL D 126 -20.833 -10.714 6.263 1.00 17.66 N -ATOM 4230 CA VAL D 126 -20.828 -11.114 4.812 1.00 21.55 C -ATOM 4231 C VAL D 126 -19.574 -10.424 3.938 1.00 16.49 C -ATOM 4232 O VAL D 126 -19.053 -10.988 3.156 1.00 13.46 O -ATOM 4233 CB VAL D 126 -22.452 -10.640 4.161 1.00 13.98 C -ATOM 4234 CG1 VAL D 126 -22.335 -11.055 2.842 1.00 20.70 C -ATOM 4235 CG2 VAL D 126 -23.218 -11.661 4.994 1.00 18.54 C -ATOM 4236 N GLN D 127 -19.567 -8.990 4.377 1.00 10.60 N -ATOM 4237 CA GLN D 127 -18.404 -8.336 3.872 1.00 12.83 C -ATOM 4238 C GLN D 127 -17.168 -9.034 3.964 1.00 13.74 C -ATOM 4239 O GLN D 127 -16.333 -9.154 3.044 1.00 12.71 O -ATOM 4240 CB GLN D 127 -18.494 -6.875 4.230 1.00 11.73 C -ATOM 4241 CG GLN D 127 -17.167 -6.142 3.667 1.00 13.68 C -ATOM 4242 CD GLN D 127 -16.957 -4.845 4.400 1.00 11.81 C -ATOM 4243 OE1 GLN D 127 -17.847 -4.243 5.015 1.00 13.99 O -ATOM 4244 NE2 GLN D 127 -15.920 -4.250 3.871 1.00 15.96 N -ATOM 4245 N ALA D 128 -16.860 -9.470 5.254 1.00 12.61 N -ATOM 4246 CA ALA D 128 -15.629 -10.118 5.636 1.00 9.64 C -ATOM 4247 C ALA D 128 -15.294 -11.332 4.779 1.00 7.66 C -ATOM 4248 O ALA D 128 -14.216 -11.498 4.302 1.00 11.68 O -ATOM 4249 CB ALA D 128 -15.618 -10.468 7.105 1.00 13.80 C -ATOM 4250 N ALA D 129 -16.442 -11.965 4.516 1.00 13.18 N -ATOM 4251 CA ALA D 129 -16.351 -13.231 3.750 1.00 11.17 C -ATOM 4252 C ALA D 129 -15.929 -12.840 2.277 1.00 11.52 C -ATOM 4253 O ALA D 129 -15.098 -13.537 1.657 1.00 13.56 O -ATOM 4254 CB ALA D 129 -17.591 -14.039 3.811 1.00 14.35 C -ATOM 4255 N TYR D 130 -16.661 -11.959 1.697 1.00 13.36 N -ATOM 4256 CA TYR D 130 -16.475 -11.445 0.343 1.00 13.72 C -ATOM 4257 C TYR D 130 -15.053 -10.791 0.256 1.00 15.10 C -ATOM 4258 O TYR D 130 -14.355 -11.020 -0.750 1.00 13.21 O -ATOM 4259 CB TYR D 130 -17.422 -10.440 -0.057 1.00 13.30 C -ATOM 4260 CG TYR D 130 -18.539 -11.158 -0.682 1.00 15.19 C -ATOM 4261 CD1 TYR D 130 -18.456 -11.539 -1.989 1.00 16.58 C -ATOM 4262 CD2 TYR D 130 -19.661 -11.646 -0.093 1.00 11.73 C -ATOM 4263 CE1 TYR D 130 -19.348 -12.381 -2.950 1.00 20.28 C -ATOM 4264 CE2 TYR D 130 -20.692 -12.412 -0.867 1.00 14.90 C -ATOM 4265 CZ TYR D 130 -20.584 -12.824 -2.071 1.00 22.05 C -ATOM 4266 OH TYR D 130 -21.522 -13.470 -2.725 1.00 20.92 O -ATOM 4267 N GLN D 131 -14.583 -10.235 1.300 1.00 12.24 N -ATOM 4268 CA GLN D 131 -13.174 -9.715 1.275 1.00 13.72 C -ATOM 4269 C GLN D 131 -12.128 -10.656 1.064 1.00 20.69 C -ATOM 4270 O GLN D 131 -11.251 -10.668 0.401 1.00 17.83 O -ATOM 4271 CB GLN D 131 -12.830 -8.708 2.421 1.00 13.45 C -ATOM 4272 CG GLN D 131 -13.616 -7.579 2.534 1.00 20.19 C -ATOM 4273 CD GLN D 131 -13.161 -6.166 1.573 1.00 18.43 C -ATOM 4274 OE1 GLN D 131 -14.035 -5.385 1.692 1.00 14.48 O -ATOM 4275 NE2 GLN D 131 -12.233 -6.377 0.841 1.00 16.06 N -ATOM 4276 N LYS D 132 -12.389 -11.876 1.744 1.00 12.67 N -ATOM 4277 CA LYS D 132 -11.377 -12.991 1.725 1.00 15.63 C -ATOM 4278 C LYS D 132 -11.407 -13.587 0.293 1.00 18.80 C -ATOM 4279 O LYS D 132 -10.481 -13.843 -0.328 1.00 14.05 O -ATOM 4280 CB LYS D 132 -11.780 -14.083 2.621 1.00 24.81 C -ATOM 4281 CG LYS D 132 -11.356 -13.759 4.081 1.00 25.97 C -ATOM 4282 CD LYS D 132 -11.952 -14.985 5.007 1.00 26.81 C -ATOM 4283 CE LYS D 132 -12.396 -14.023 6.345 1.00 50.23 C -ATOM 4284 NZ LYS D 132 -12.099 -16.364 7.125 1.00 63.38 N -ATOM 4285 N VAL D 133 -12.646 -13.574 -0.320 1.00 13.42 N -ATOM 4286 CA VAL D 133 -12.819 -14.186 -1.656 1.00 18.27 C -ATOM 4287 C VAL D 133 -12.113 -13.235 -2.641 1.00 19.39 C -ATOM 4288 O VAL D 133 -11.376 -13.757 -3.529 1.00 15.06 O -ATOM 4289 CB VAL D 133 -14.347 -14.459 -2.009 1.00 17.40 C -ATOM 4290 CG1 VAL D 133 -14.482 -14.527 -3.527 1.00 22.79 C -ATOM 4291 CG2 VAL D 133 -14.897 -15.429 -1.020 1.00 19.90 C -ATOM 4292 N VAL D 134 -12.419 -12.044 -2.631 1.00 14.66 N -ATOM 4293 CA VAL D 134 -11.817 -11.184 -3.697 1.00 17.41 C -ATOM 4294 C VAL D 134 -10.205 -10.998 -3.622 1.00 17.93 C -ATOM 4295 O VAL D 134 -9.555 -11.088 -4.632 1.00 17.13 O -ATOM 4296 CB VAL D 134 -12.523 -9.795 -3.826 1.00 16.69 C -ATOM 4297 CG1 VAL D 134 -13.942 -9.809 -3.996 1.00 22.42 C -ATOM 4298 CG2 VAL D 134 -12.135 -9.012 -2.596 1.00 16.30 C -ATOM 4299 N ALA D 135 -9.754 -11.116 -2.425 1.00 16.25 N -ATOM 4300 CA ALA D 135 -8.338 -11.031 -2.088 1.00 14.79 C -ATOM 4301 C ALA D 135 -7.743 -12.494 -2.790 1.00 21.70 C -ATOM 4302 O ALA D 135 -6.667 -12.571 -3.342 1.00 16.89 O -ATOM 4303 CB ALA D 135 -7.946 -11.087 -0.719 1.00 18.34 C -ATOM 4304 N GLY D 136 -8.430 -13.631 -2.593 1.00 17.40 N -ATOM 4305 CA GLY D 136 -8.238 -14.854 -2.994 1.00 16.77 C -ATOM 4306 C GLY D 136 -8.046 -14.863 -4.547 1.00 21.35 C -ATOM 4307 O GLY D 136 -7.103 -15.386 -5.248 1.00 16.80 O -ATOM 4308 N VAL D 137 -9.061 -14.287 -5.106 1.00 23.70 N -ATOM 4309 CA VAL D 137 -9.117 -14.207 -6.516 1.00 26.49 C -ATOM 4310 C VAL D 137 -8.271 -13.386 -7.311 1.00 33.07 C -ATOM 4311 O VAL D 137 -7.434 -13.729 -8.023 1.00 30.90 O -ATOM 4312 CB VAL D 137 -10.635 -13.731 -7.203 1.00 15.94 C -ATOM 4313 CG1 VAL D 137 -10.606 -13.355 -8.722 1.00 21.57 C -ATOM 4314 CG2 VAL D 137 -11.540 -14.757 -6.690 1.00 21.46 C -ATOM 4315 N ALA D 138 -7.804 -12.254 -6.635 1.00 14.66 N -ATOM 4316 CA ALA D 138 -6.688 -11.339 -7.074 1.00 18.95 C -ATOM 4317 C ALA D 138 -5.417 -12.079 -7.070 1.00 18.17 C -ATOM 4318 O ALA D 138 -4.593 -11.997 -7.851 1.00 14.81 O -ATOM 4319 CB ALA D 138 -6.540 -10.040 -6.183 1.00 19.78 C -ATOM 4320 N ASN D 139 -5.187 -12.811 -5.928 1.00 15.30 N -ATOM 4321 CA ASN D 139 -3.937 -13.374 -5.586 1.00 18.41 C -ATOM 4322 C ASN D 139 -3.703 -14.483 -6.697 1.00 25.63 C -ATOM 4323 O ASN D 139 -2.635 -14.913 -7.329 1.00 23.38 O -ATOM 4324 CB ASN D 139 -3.989 -14.050 -4.592 1.00 50.89 C -ATOM 4325 CG ASN D 139 -3.194 -13.790 -3.503 1.00 63.06 C -ATOM 4326 OD1 ASN D 139 -2.135 -15.017 -3.938 1.00 52.41 O -ATOM 4327 ND2 ASN D 139 -3.072 -12.228 -3.482 1.00 29.84 N -ATOM 4328 N ALA D 140 -4.873 -15.260 -6.949 1.00 19.40 N -ATOM 4329 CA ALA D 140 -5.005 -16.402 -7.986 1.00 23.09 C -ATOM 4330 C ALA D 140 -4.740 -15.710 -9.403 1.00 18.16 C -ATOM 4331 O ALA D 140 -3.930 -16.420 -10.089 1.00 16.51 O -ATOM 4332 CB ALA D 140 -6.303 -16.997 -8.071 1.00 18.14 C -ATOM 4333 N LEU D 141 -5.172 -14.659 -9.775 1.00 14.97 N -ATOM 4334 CA LEU D 141 -4.899 -14.068 -11.011 1.00 14.94 C -ATOM 4335 C LEU D 141 -3.434 -13.602 -11.198 1.00 11.73 C -ATOM 4336 O LEU D 141 -2.840 -13.285 -12.242 1.00 15.21 O -ATOM 4337 CB LEU D 141 -6.006 -12.939 -11.311 1.00 15.16 C -ATOM 4338 CG LEU D 141 -7.325 -13.394 -11.757 1.00 17.87 C -ATOM 4339 CD1 LEU D 141 -7.836 -12.121 -12.278 1.00 24.86 C -ATOM 4340 CD2 LEU D 141 -6.860 -13.940 -13.382 1.00 16.07 C -ATOM 4341 N ALA D 142 -2.826 -13.097 -10.036 1.00 14.26 N -ATOM 4342 CA ALA D 142 -1.439 -12.718 -10.054 1.00 17.21 C -ATOM 4343 C ALA D 142 -0.379 -13.783 -9.991 1.00 18.46 C -ATOM 4344 O ALA D 142 0.751 -13.412 -10.228 1.00 18.92 O -ATOM 4345 CB ALA D 142 -1.279 -11.774 -8.892 1.00 19.11 C -ATOM 4346 N HIS D 143 -0.748 -15.020 -9.767 1.00 19.75 N -ATOM 4347 CA HIS D 143 0.079 -16.200 -9.518 1.00 26.63 C -ATOM 4348 C HIS D 143 1.176 -16.436 -10.670 1.00 23.72 C -ATOM 4349 O HIS D 143 2.224 -16.803 -10.136 1.00 24.41 O -ATOM 4350 CB HIS D 143 -0.669 -17.339 -8.942 1.00 25.89 C -ATOM 4351 CG HIS D 143 0.097 -18.406 -8.683 1.00 56.45 C -ATOM 4352 ND1 HIS D 143 0.122 -19.475 -9.292 1.00 44.25 N -ATOM 4353 CD2 HIS D 143 1.035 -18.261 -7.098 1.00 48.81 C -ATOM 4354 CE1 HIS D 143 1.293 -20.089 -8.356 1.00 56.93 C -ATOM 4355 NE2 HIS D 143 1.407 -19.517 -7.123 1.00 49.27 N -ATOM 4356 N LYS D 144 0.773 -16.313 -11.824 1.00 19.26 N -ATOM 4357 CA LYS D 144 1.442 -16.574 -13.172 1.00 33.94 C -ATOM 4358 C LYS D 144 2.421 -15.633 -13.479 1.00 32.28 C -ATOM 4359 O LYS D 144 2.996 -15.637 -14.654 1.00 23.60 O -ATOM 4360 CB LYS D 144 1.055 -17.526 -13.968 1.00 31.20 C -ATOM 4361 CG LYS D 144 0.220 -18.870 -13.388 1.00 40.85 C -ATOM 4362 CD LYS D 144 1.002 -19.972 -13.512 1.00 59.03 C -ATOM 4363 CE LYS D 144 0.888 -21.048 -13.306 1.00 56.19 C -ATOM 4364 NZ LYS D 144 1.510 -22.846 -14.338 1.00 70.96 N -ATOM 4365 N TYR D 145 2.435 -14.424 -12.946 1.00 24.92 N -ATOM 4366 CA TYR D 145 3.207 -13.372 -13.244 1.00 29.13 C -ATOM 4367 C TYR D 145 4.717 -13.524 -13.102 1.00 38.17 C -ATOM 4368 O TYR D 145 5.061 -14.114 -12.139 1.00 27.99 O -ATOM 4369 CB TYR D 145 2.744 -12.016 -12.590 1.00 17.99 C -ATOM 4370 CG TYR D 145 1.621 -11.268 -13.262 1.00 17.42 C -ATOM 4371 CD1 TYR D 145 1.523 -10.110 -13.925 1.00 16.93 C -ATOM 4372 CD2 TYR D 145 0.375 -12.020 -13.134 1.00 18.60 C -ATOM 4373 CE1 TYR D 145 0.498 -9.521 -14.492 1.00 17.99 C -ATOM 4374 CE2 TYR D 145 -0.813 -11.356 -13.802 1.00 14.96 C -ATOM 4375 CZ TYR D 145 -0.763 -10.275 -14.381 1.00 12.85 C -ATOM 4376 OH TYR D 145 -1.813 -9.580 -14.987 1.00 13.31 O -ATOM 4377 N HIS D 146 5.428 -13.165 -14.072 1.00 26.11 N -ATOM 4378 CA HIS D 146 7.054 -13.167 -14.050 1.00 31.89 C -ATOM 4379 C HIS D 146 7.429 -12.153 -15.048 1.00 21.33 C -ATOM 4380 O HIS D 146 6.931 -11.249 -15.530 1.00 27.92 O -ATOM 4381 CB HIS D 146 7.223 -14.769 -14.665 1.00 30.13 C -ATOM 4382 CG HIS D 146 6.497 -14.789 -15.882 1.00 40.51 C -ATOM 4383 ND1 HIS D 146 7.552 -14.702 -17.398 1.00 47.51 N -ATOM 4384 CD2 HIS D 146 5.784 -14.325 -16.776 1.00 45.49 C -ATOM 4385 CE1 HIS D 146 7.188 -14.800 -17.949 1.00 56.67 C -ATOM 4386 NE2 HIS D 146 5.714 -14.339 -18.353 1.00 37.33 N -ATOM 4387 OXT HIS D 146 8.812 -12.134 -14.847 1.00 21.61 O -TER 4388 HIS D 146 -HETATM 4389 FE HEM A 142 8.116 7.403 -15.045 1.00 18.07 FE -HETATM 4390 CHA HEM A 142 8.585 7.902 -18.282 1.00 16.31 C -HETATM 4391 CHB HEM A 142 10.355 9.805 -14.208 1.00 26.27 C -HETATM 4392 CHC HEM A 142 8.341 6.363 -11.589 1.00 13.23 C -HETATM 4393 CHD HEM A 142 6.988 4.088 -15.744 1.00 14.77 C -HETATM 4394 NA HEM A 142 9.397 8.686 -16.211 1.00 16.46 N -HETATM 4395 C1A HEM A 142 9.141 8.725 -17.504 1.00 17.40 C -HETATM 4396 C2A HEM A 142 10.098 9.952 -17.887 1.00 18.53 C -HETATM 4397 C3A HEM A 142 10.636 10.499 -16.796 1.00 18.36 C -HETATM 4398 C4A HEM A 142 10.137 9.679 -15.611 1.00 16.88 C -HETATM 4399 CMA HEM A 142 11.613 11.590 -16.732 1.00 21.20 C -HETATM 4400 CAA HEM A 142 10.403 10.367 -19.312 1.00 25.54 C -HETATM 4401 CBA HEM A 142 9.552 11.270 -19.659 1.00 31.38 C -HETATM 4402 CGA HEM A 142 10.793 12.286 -21.342 1.00 44.82 C -HETATM 4403 O1A HEM A 142 9.887 11.345 -21.943 1.00 39.10 O -HETATM 4404 O2A HEM A 142 9.308 12.698 -21.487 1.00 54.71 O -HETATM 4405 NB HEM A 142 9.343 8.012 -13.298 1.00 12.29 N -HETATM 4406 C1B HEM A 142 9.938 9.271 -13.145 1.00 23.63 C -HETATM 4407 C2B HEM A 142 10.318 9.380 -11.838 1.00 11.67 C -HETATM 4408 C3B HEM A 142 9.660 8.341 -11.052 1.00 17.41 C -HETATM 4409 C4B HEM A 142 9.028 7.467 -11.975 1.00 14.84 C -HETATM 4410 CMB HEM A 142 11.048 10.634 -11.389 1.00 12.32 C -HETATM 4411 CAB HEM A 142 9.567 8.336 -9.634 1.00 24.30 C -HETATM 4412 CBB HEM A 142 10.576 8.441 -8.785 1.00 28.40 C -HETATM 4413 NC HEM A 142 7.604 5.533 -13.949 1.00 15.07 N -HETATM 4414 C1C HEM A 142 7.680 5.498 -12.499 1.00 13.39 C -HETATM 4415 C2C HEM A 142 7.270 4.198 -12.170 1.00 11.20 C -HETATM 4416 C3C HEM A 142 6.975 3.441 -13.304 1.00 8.94 C -HETATM 4417 C4C HEM A 142 7.207 4.445 -14.517 1.00 10.29 C -HETATM 4418 CMC HEM A 142 7.098 3.618 -10.845 1.00 13.77 C -HETATM 4419 CAC HEM A 142 6.342 2.184 -13.525 1.00 13.45 C -HETATM 4420 CBC HEM A 142 6.722 1.153 -12.766 1.00 11.27 C -HETATM 4421 ND HEM A 142 7.715 6.202 -16.788 1.00 13.07 N -HETATM 4422 C1D HEM A 142 7.302 4.989 -16.733 1.00 11.32 C -HETATM 4423 C2D HEM A 142 7.141 4.644 -18.240 1.00 16.69 C -HETATM 4424 C3D HEM A 142 7.540 5.718 -18.887 1.00 20.49 C -HETATM 4425 C4D HEM A 142 8.172 6.582 -18.158 1.00 16.46 C -HETATM 4426 CMD HEM A 142 6.354 3.385 -18.817 1.00 19.45 C -HETATM 4427 CAD HEM A 142 7.621 5.740 -20.408 1.00 21.31 C -HETATM 4428 CBD HEM A 142 8.764 5.354 -20.767 1.00 38.22 C -HETATM 4429 CGD HEM A 142 9.138 5.049 -22.798 1.00 41.21 C -HETATM 4430 O1D HEM A 142 9.998 5.836 -22.703 1.00 42.81 O -HETATM 4431 O2D HEM A 142 8.349 4.920 -23.144 1.00 40.12 O -HETATM 4432 P PO4 B 147 5.931 -21.573 3.319 1.00 32.97 P -HETATM 4433 FE HEM B 148 9.333 -9.335 17.389 1.00 15.00 FE -HETATM 4434 CHA HEM B 148 9.659 -10.155 20.773 1.00 21.59 C -HETATM 4435 CHB HEM B 148 11.121 -12.190 16.575 1.00 16.50 C -HETATM 4436 CHC HEM B 148 9.762 -8.175 14.122 1.00 16.82 C -HETATM 4437 CHD HEM B 148 8.223 -6.187 18.294 1.00 16.19 C -HETATM 4438 NA HEM B 148 10.260 -10.823 18.453 1.00 15.64 N -HETATM 4439 C1A HEM B 148 10.199 -10.977 19.856 1.00 24.57 C -HETATM 4440 C2A HEM B 148 10.940 -12.186 20.114 1.00 17.10 C -HETATM 4441 C3A HEM B 148 11.529 -12.852 19.028 1.00 13.46 C -HETATM 4442 C4A HEM B 148 10.911 -11.942 17.916 1.00 18.78 C -HETATM 4443 CMA HEM B 148 12.211 -14.084 18.855 1.00 20.21 C -HETATM 4444 CAA HEM B 148 11.171 -12.750 21.554 1.00 21.16 C -HETATM 4445 CBA HEM B 148 10.089 -13.674 21.941 1.00 27.78 C -HETATM 4446 CGA HEM B 148 9.936 -14.643 23.585 1.00 59.12 C -HETATM 4447 O1A HEM B 148 10.040 -13.299 24.151 1.00 44.32 O -HETATM 4448 O2A HEM B 148 9.582 -15.171 23.405 1.00 46.16 O -HETATM 4449 NB HEM B 148 10.199 -10.051 15.722 1.00 12.71 N -HETATM 4450 C1B HEM B 148 10.820 -11.284 15.524 1.00 10.36 C -HETATM 4451 C2B HEM B 148 11.247 -11.528 14.048 1.00 7.33 C -HETATM 4452 C3B HEM B 148 10.827 -10.448 13.495 1.00 15.63 C -HETATM 4453 C4B HEM B 148 10.176 -9.458 14.534 1.00 15.33 C -HETATM 4454 CMB HEM B 148 11.793 -12.748 13.802 1.00 14.96 C -HETATM 4455 CAB HEM B 148 10.965 -10.083 11.934 1.00 19.63 C -HETATM 4456 CBB HEM B 148 12.063 -10.466 11.288 1.00 39.39 C -HETATM 4457 NC HEM B 148 9.104 -7.643 16.544 1.00 11.22 N -HETATM 4458 C1C HEM B 148 9.223 -7.280 15.193 1.00 14.39 C -HETATM 4459 C2C HEM B 148 8.943 -5.947 14.698 1.00 10.78 C -HETATM 4460 C3C HEM B 148 8.461 -5.188 15.934 1.00 10.68 C -HETATM 4461 C4C HEM B 148 8.575 -6.422 16.809 1.00 8.70 C -HETATM 4462 CMC HEM B 148 9.067 -5.306 13.381 1.00 13.95 C -HETATM 4463 CAC HEM B 148 7.915 -3.899 16.132 1.00 11.87 C -HETATM 4464 CBC HEM B 148 8.359 -2.863 15.599 1.00 12.63 C -HETATM 4465 ND HEM B 148 9.090 -8.239 19.067 1.00 16.72 N -HETATM 4466 C1D HEM B 148 8.576 -7.046 19.346 1.00 18.32 C -HETATM 4467 C2D HEM B 148 8.195 -6.791 20.753 1.00 15.48 C -HETATM 4468 C3D HEM B 148 8.512 -8.051 21.256 1.00 14.57 C -HETATM 4469 C4D HEM B 148 9.290 -8.905 20.340 1.00 20.76 C -HETATM 4470 CMD HEM B 148 7.722 -5.449 21.269 1.00 27.50 C -HETATM 4471 CAD HEM B 148 8.696 -7.989 22.865 1.00 13.85 C -HETATM 4472 CBD HEM B 148 10.051 -7.739 23.453 1.00 17.11 C -HETATM 4473 CGD HEM B 148 10.333 -8.222 25.219 1.00 27.09 C -HETATM 4474 O1D HEM B 148 11.372 -7.572 25.386 1.00 27.49 O -HETATM 4475 O2D HEM B 148 9.169 -8.132 25.625 1.00 23.65 O -HETATM 4476 FE HEM C 142 -8.129 7.348 15.002 1.00 16.89 FE -HETATM 4477 CHA HEM C 142 -8.630 7.776 18.352 1.00 18.96 C -HETATM 4478 CHB HEM C 142 -10.320 10.048 14.384 1.00 20.49 C -HETATM 4479 CHC HEM C 142 -8.304 6.446 11.794 1.00 15.25 C -HETATM 4480 CHD HEM C 142 -6.900 4.052 15.698 1.00 14.70 C -HETATM 4481 NA HEM C 142 -9.276 8.702 16.089 1.00 16.55 N -HETATM 4482 C1A HEM C 142 -9.195 8.664 17.417 1.00 16.72 C -HETATM 4483 C2A HEM C 142 -10.045 9.791 17.916 1.00 15.73 C -HETATM 4484 C3A HEM C 142 -10.613 10.462 16.942 1.00 17.27 C -HETATM 4485 C4A HEM C 142 -10.077 9.749 15.710 1.00 12.07 C -HETATM 4486 CMA HEM C 142 -11.422 11.658 16.756 1.00 31.88 C -HETATM 4487 CAA HEM C 142 -10.321 10.351 19.308 1.00 24.60 C -HETATM 4488 CBA HEM C 142 -9.201 11.341 19.696 1.00 36.28 C -HETATM 4489 CGA HEM C 142 -10.014 12.024 21.724 1.00 43.70 C -HETATM 4490 O1A HEM C 142 -9.511 10.786 22.089 1.00 38.93 O -HETATM 4491 O2A HEM C 142 -9.503 12.583 21.415 1.00 46.28 O -HETATM 4492 NB HEM C 142 -9.138 8.185 13.333 1.00 12.79 N -HETATM 4493 C1B HEM C 142 -9.882 9.419 13.260 1.00 18.45 C -HETATM 4494 C2B HEM C 142 -10.342 9.474 11.782 1.00 12.95 C -HETATM 4495 C3B HEM C 142 -9.631 8.558 11.160 1.00 12.49 C -HETATM 4496 C4B HEM C 142 -8.945 7.665 12.157 1.00 8.33 C -HETATM 4497 CMB HEM C 142 -11.015 10.631 11.441 1.00 15.16 C -HETATM 4498 CAB HEM C 142 -9.701 8.335 9.552 1.00 21.83 C -HETATM 4499 CBB HEM C 142 -10.742 8.875 9.052 1.00 33.11 C -HETATM 4500 NC HEM C 142 -7.518 5.627 13.990 1.00 12.28 N -HETATM 4501 C1C HEM C 142 -7.751 5.629 12.596 1.00 15.97 C -HETATM 4502 C2C HEM C 142 -7.320 4.232 12.130 1.00 9.41 C -HETATM 4503 C3C HEM C 142 -6.879 3.543 13.304 1.00 11.73 C -HETATM 4504 C4C HEM C 142 -7.009 4.441 14.484 1.00 15.36 C -HETATM 4505 CMC HEM C 142 -7.210 3.774 10.722 1.00 13.23 C -HETATM 4506 CAC HEM C 142 -6.459 2.233 13.437 1.00 19.55 C -HETATM 4507 CBC HEM C 142 -6.761 1.082 12.572 1.00 14.52 C -HETATM 4508 ND HEM C 142 -7.740 6.303 16.793 1.00 12.30 N -HETATM 4509 C1D HEM C 142 -7.305 4.996 16.751 1.00 11.54 C -HETATM 4510 C2D HEM C 142 -6.959 4.620 18.250 1.00 12.94 C -HETATM 4511 C3D HEM C 142 -7.527 5.654 18.907 1.00 11.38 C -HETATM 4512 C4D HEM C 142 -7.947 6.663 18.081 1.00 11.29 C -HETATM 4513 CMD HEM C 142 -6.299 3.375 18.648 1.00 13.29 C -HETATM 4514 CAD HEM C 142 -7.594 5.618 20.504 1.00 15.84 C -HETATM 4515 CBD HEM C 142 -8.833 5.076 20.877 1.00 21.27 C -HETATM 4516 CGD HEM C 142 -9.085 5.314 22.774 1.00 26.94 C -HETATM 4517 O1D HEM C 142 -10.036 5.486 22.824 1.00 30.21 O -HETATM 4518 O2D HEM C 142 -8.326 4.541 23.113 1.00 25.95 O -HETATM 4519 P PO4 D 147 -6.147 -21.111 -3.332 1.00 31.17 P -HETATM 4520 FE HEM D 148 -9.504 -9.265 -17.387 1.00 15.46 FE -HETATM 4521 CHA HEM D 148 -9.813 -9.884 -20.599 1.00 19.84 C -HETATM 4522 CHB HEM D 148 -11.252 -11.989 -16.610 1.00 16.61 C -HETATM 4523 CHC HEM D 148 -9.951 -8.302 -14.119 1.00 13.93 C -HETATM 4524 CHD HEM D 148 -8.200 -5.985 -18.127 1.00 15.88 C -HETATM 4525 NA HEM D 148 -10.454 -10.804 -18.459 1.00 15.98 N -HETATM 4526 C1A HEM D 148 -10.428 -10.865 -19.783 1.00 28.09 C -HETATM 4527 C2A HEM D 148 -11.318 -12.071 -20.258 1.00 22.30 C -HETATM 4528 C3A HEM D 148 -11.693 -12.664 -19.188 1.00 22.59 C -HETATM 4529 C4A HEM D 148 -11.051 -11.756 -18.004 1.00 25.38 C -HETATM 4530 CMA HEM D 148 -12.566 -13.772 -18.973 1.00 20.23 C -HETATM 4531 CAA HEM D 148 -11.486 -12.464 -21.884 1.00 19.24 C -HETATM 4532 CBA HEM D 148 -10.405 -12.971 -22.194 1.00 50.08 C -HETATM 4533 CGA HEM D 148 -9.805 -13.296 -24.484 1.00 47.00 C -HETATM 4534 O1A HEM D 148 -11.117 -13.581 -24.158 1.00 49.99 O -HETATM 4535 O2A HEM D 148 -9.172 -14.946 -24.346 1.00 55.24 O -HETATM 4536 NB HEM D 148 -10.364 -9.999 -15.688 1.00 14.27 N -HETATM 4537 C1B HEM D 148 -10.937 -11.332 -15.462 1.00 14.32 C -HETATM 4538 C2B HEM D 148 -11.232 -11.509 -14.176 1.00 15.75 C -HETATM 4539 C3B HEM D 148 -10.801 -10.525 -13.479 1.00 14.95 C -HETATM 4540 C4B HEM D 148 -10.217 -9.585 -14.421 1.00 12.78 C -HETATM 4541 CMB HEM D 148 -11.799 -12.726 -13.757 1.00 18.74 C -HETATM 4542 CAB HEM D 148 -10.869 -10.291 -11.895 1.00 16.19 C -HETATM 4543 CBB HEM D 148 -11.756 -10.396 -11.494 1.00 34.22 C -HETATM 4544 NC HEM D 148 -9.228 -7.489 -16.235 1.00 12.21 N -HETATM 4545 C1C HEM D 148 -9.469 -7.417 -14.891 1.00 14.15 C -HETATM 4546 C2C HEM D 148 -8.915 -5.898 -14.609 1.00 16.84 C -HETATM 4547 C3C HEM D 148 -8.353 -5.322 -15.741 1.00 13.21 C -HETATM 4548 C4C HEM D 148 -8.605 -6.360 -16.751 1.00 15.07 C -HETATM 4549 CMC HEM D 148 -9.128 -5.229 -13.166 1.00 18.77 C -HETATM 4550 CAC HEM D 148 -7.843 -4.077 -15.916 1.00 13.84 C -HETATM 4551 CBC HEM D 148 -8.331 -3.032 -15.408 1.00 20.77 C -HETATM 4552 ND HEM D 148 -9.282 -8.209 -19.162 1.00 12.94 N -HETATM 4553 C1D HEM D 148 -8.465 -7.065 -19.281 1.00 18.28 C -HETATM 4554 C2D HEM D 148 -8.394 -6.595 -20.574 1.00 20.40 C -HETATM 4555 C3D HEM D 148 -8.861 -7.841 -21.341 1.00 19.16 C -HETATM 4556 C4D HEM D 148 -9.573 -8.702 -20.531 1.00 19.80 C -HETATM 4557 CMD HEM D 148 -7.686 -5.397 -21.106 1.00 25.65 C -HETATM 4558 CAD HEM D 148 -8.956 -7.733 -22.890 1.00 23.94 C -HETATM 4559 CBD HEM D 148 -10.040 -6.949 -23.304 1.00 45.78 C -HETATM 4560 CGD HEM D 148 -10.579 -7.365 -25.200 1.00 48.49 C -HETATM 4561 O1D HEM D 148 -9.907 -5.916 -25.395 1.00 40.71 O -HETATM 4562 O2D HEM D 148 -9.982 -7.978 -25.490 1.00 45.79 O -HETATM 4563 O HOH A 143 27.864 0.667 0.584 1.00 21.15 O -HETATM 4564 O HOH A 144 10.459 5.072 -14.201 1.00 29.96 O -HETATM 4565 O HOH A 145 17.782 -1.325 -26.109 1.00 23.65 O -HETATM 4566 O HOH A 146 13.825 2.114 3.861 1.00 23.17 O -HETATM 4567 O HOH A 147 16.741 12.813 9.083 1.00 26.86 O -HETATM 4568 O HOH A 148 22.374 9.235 11.515 1.00 30.53 O -HETATM 4569 O HOH A 149 25.903 -1.921 -7.245 1.00 27.68 O -HETATM 4570 O HOH A 150 11.472 3.167 0.508 1.00 27.27 O -HETATM 4571 O HOH A 151 30.661 6.822 -0.101 1.00 29.31 O -HETATM 4572 O HOH A 152 -3.585 1.717 -5.969 1.00 29.54 O -HETATM 4573 O HOH A 153 32.341 10.298 6.014 1.00 35.74 O -HETATM 4574 O HOH A 154 34.406 10.442 4.080 1.00 31.58 O -HETATM 4575 O HOH A 155 30.017 0.297 -1.177 1.00 37.73 O -HETATM 4576 O HOH A 156 21.428 14.396 -13.024 1.00 37.58 O -HETATM 4577 O HOH A 157 10.103 6.463 -0.224 1.00 29.83 O -HETATM 4578 O HOH A 158 28.011 -0.672 -5.493 1.00 34.75 O -HETATM 4579 O HOH A 159 12.221 6.676 -21.742 1.00 35.95 O -HETATM 4580 O HOH A 160 0.070 13.369 -11.506 1.00 27.36 O -HETATM 4581 O HOH A 161 6.073 -7.542 -8.224 1.00 27.80 O -HETATM 4582 O HOH A 162 0.959 -1.910 -19.919 1.00 29.65 O -HETATM 4583 O HOH A 163 -5.435 9.067 -14.288 1.00 30.27 O -HETATM 4584 O HOH A 164 3.108 18.897 -10.351 1.00 37.13 O -HETATM 4585 O HOH A 165 9.253 2.690 -0.595 1.00 31.92 O -HETATM 4586 O HOH A 166 3.509 1.516 -20.390 1.00 30.86 O -HETATM 4587 O HOH A 167 7.323 6.472 -2.528 1.00 34.91 O -HETATM 4588 O HOH A 168 8.069 21.100 -2.836 1.00 34.13 O -HETATM 4589 O HOH A 169 22.069 5.076 -17.599 1.00 36.10 O -HETATM 4590 O HOH A 170 12.511 23.031 -13.238 1.00 37.77 O -HETATM 4591 O HOH A 171 27.846 5.439 7.283 1.00 39.01 O -HETATM 4592 O HOH A 172 16.593 -6.697 -7.432 1.00 35.74 O -HETATM 4593 O HOH A 173 19.969 -3.554 -17.319 1.00 36.03 O -HETATM 4594 O HOH A 174 14.440 13.918 -17.292 1.00 34.06 O -HETATM 4595 O HOH A 175 30.151 3.417 -5.741 1.00 35.04 O -HETATM 4596 O HOH A 176 8.360 5.321 2.557 1.00 38.02 O -HETATM 4597 O HOH A 177 -6.479 11.748 -17.967 1.00 39.72 O -HETATM 4598 O HOH A 178 8.608 18.432 -15.341 1.00 36.40 O -HETATM 4599 O HOH A 179 13.827 13.620 8.994 1.00 37.52 O -HETATM 4600 O HOH A 180 16.070 12.039 11.262 1.00 38.53 O -HETATM 4601 O HOH A 181 2.747 5.937 -4.128 1.00 42.85 O -HETATM 4602 O HOH A 182 7.523 20.881 -15.648 1.00 39.27 O -HETATM 4603 O HOH A 183 11.712 -10.960 -5.769 1.00 38.61 O -HETATM 4604 O HOH A 184 30.119 4.139 -8.587 1.00 34.80 O -HETATM 4605 O HOH A 185 25.533 1.205 -11.184 1.00 42.30 O -HETATM 4606 O HOH A 186 -4.812 12.384 -7.265 1.00 38.29 O -HETATM 4607 O HOH A 187 23.809 19.925 1.758 1.00 39.37 O -HETATM 4608 O HOH A 188 26.015 11.766 5.159 1.00 40.95 O -HETATM 4609 O HOH A 189 14.639 24.823 -4.300 1.00 41.35 O -HETATM 4610 O HOH A 190 14.903 5.393 -23.047 1.00 37.45 O -HETATM 4611 O HOH A 191 16.650 -5.137 -16.717 1.00 39.12 O -HETATM 4612 O HOH A 192 7.424 -6.700 -20.085 1.00 38.62 O -HETATM 4613 O HOH A 193 23.120 -3.118 -12.992 1.00 37.05 O -HETATM 4614 O HOH A 194 23.664 0.968 -14.389 1.00 36.25 O -HETATM 4615 O HOH A 195 25.698 7.981 -15.362 1.00 35.85 O -HETATM 4616 O HOH A 196 30.009 16.347 -6.794 1.00 37.62 O -HETATM 4617 O HOH A 197 27.728 16.677 -1.376 1.00 42.54 O -HETATM 4618 O HOH A 198 8.142 18.836 1.041 1.00 39.90 O -HETATM 4619 O HOH B 149 0.093 -2.470 16.222 1.00 21.64 O -HETATM 4620 O HOH B 150 -5.404 -9.289 14.863 1.00 29.94 O -HETATM 4621 O HOH B 151 17.543 -13.863 -8.044 1.00 26.33 O -HETATM 4622 O HOH B 152 10.126 -8.396 -0.639 1.00 27.87 O -HETATM 4623 O HOH B 153 25.765 -4.888 -7.482 1.00 33.60 O -HETATM 4624 O HOH B 154 31.028 -6.924 -0.005 1.00 27.86 O -HETATM 4625 O HOH B 155 10.572 -9.505 7.329 1.00 34.89 O -HETATM 4626 O HOH B 156 2.908 -19.221 10.523 1.00 29.82 O -HETATM 4627 O HOH B 157 27.245 -11.383 -5.263 1.00 34.30 O -HETATM 4628 O HOH B 158 5.726 -17.664 4.076 1.00 29.36 O -HETATM 4629 O HOH B 159 30.677 -1.382 -3.264 1.00 34.23 O -HETATM 4630 O HOH B 160 21.396 -19.202 9.299 1.00 34.06 O -HETATM 4631 O HOH B 161 3.400 -4.625 22.878 1.00 34.98 O -HETATM 4632 O HOH B 162 23.029 7.858 13.868 1.00 34.02 O -HETATM 4633 O HOH B 163 10.054 0.537 2.970 1.00 33.29 O -HETATM 4634 O HOH B 164 16.523 -14.815 19.144 1.00 32.12 O -HETATM 4635 O HOH B 165 -3.521 -7.996 18.788 1.00 35.56 O -HETATM 4636 O HOH B 166 9.429 -6.067 3.140 1.00 34.98 O -HETATM 4637 O HOH B 167 25.800 -14.208 -2.740 1.00 37.65 O -HETATM 4638 O HOH B 168 0.313 -14.430 5.859 1.00 34.45 O -HETATM 4639 O HOH B 169 25.879 -15.224 10.033 1.00 33.37 O -HETATM 4640 O HOH B 170 35.602 -4.153 -9.289 1.00 35.71 O -HETATM 4641 O HOH B 171 20.781 6.254 23.632 1.00 38.68 O -HETATM 4642 O HOH B 172 21.800 -18.543 12.994 1.00 40.56 O -HETATM 4643 O HOH B 173 7.807 -19.735 16.230 1.00 34.56 O -HETATM 4644 O HOH B 174 -2.047 -12.487 30.048 1.00 36.28 O -HETATM 4645 O HOH B 175 13.681 -7.349 23.790 1.00 31.60 O -HETATM 4646 O HOH B 176 24.831 -18.968 5.896 1.00 34.00 O -HETATM 4647 O HOH B 177 5.475 -5.297 23.977 1.00 36.71 O -HETATM 4648 O HOH B 178 15.904 -5.466 24.689 1.00 34.84 O -HETATM 4649 O HOH B 179 22.123 0.182 16.584 1.00 33.20 O -HETATM 4650 O HOH B 180 19.207 -15.705 -9.408 1.00 37.19 O -HETATM 4651 O HOH B 181 25.174 -12.029 -8.381 1.00 35.87 O -HETATM 4652 O HOH B 182 -10.362 -13.333 12.465 1.00 36.08 O -HETATM 4653 O HOH B 183 12.092 8.997 23.297 1.00 38.22 O -HETATM 4654 O HOH B 184 7.727 5.204 22.116 1.00 43.17 O -HETATM 4655 O HOH B 185 30.137 -14.006 10.129 1.00 36.03 O -HETATM 4656 O HOH B 186 13.730 -18.833 14.202 1.00 39.57 O -HETATM 4657 O HOH B 187 22.379 8.870 23.585 1.00 37.45 O -HETATM 4658 O HOH B 188 -4.205 -14.646 8.671 1.00 38.65 O -HETATM 4659 O HOH B 189 12.589 14.261 19.653 1.00 36.93 O -HETATM 4660 O HOH B 190 24.652 6.230 17.996 1.00 42.01 O -HETATM 4661 O HOH B 191 8.775 -23.438 16.055 1.00 42.33 O -HETATM 4662 O HOH B 192 -7.480 -10.898 17.998 1.00 38.06 O -HETATM 4663 O HOH B 193 11.388 -11.044 24.763 1.00 39.34 O -HETATM 4664 O HOH B 194 3.735 -3.643 2.734 1.00 42.17 O -HETATM 4665 O HOH B 195 3.149 -0.692 2.083 1.00 41.40 O -HETATM 4666 O HOH B 196 4.511 -25.886 13.006 1.00 39.83 O -HETATM 4667 O HOH B 197 8.712 -21.655 3.577 1.00 43.08 O -HETATM 4668 O HOH B 198 22.926 -4.304 24.079 1.00 38.10 O -HETATM 4669 O HOH B 199 11.435 9.654 20.618 1.00 40.23 O -HETATM 4670 O HOH B 200 18.099 5.542 27.744 1.00 39.03 O -HETATM 4671 O HOH B 201 12.174 9.951 9.804 1.00 44.34 O -HETATM 4672 O HOH B 202 24.745 -2.501 15.270 1.00 39.78 O -HETATM 4673 O HOH B 203 24.231 0.100 14.764 1.00 42.94 O -HETATM 4674 O HOH B 204 23.324 -18.136 10.981 1.00 53.60 O -HETATM 4675 O HOH B 205 25.576 -22.211 6.309 1.00 45.18 O -HETATM 4676 O HOH C 143 -2.661 -3.608 9.261 1.00 21.26 O -HETATM 4677 O HOH C 144 0.111 13.200 11.373 1.00 21.54 O -HETATM 4678 O HOH C 145 -16.704 12.691 -9.201 1.00 23.30 O -HETATM 4679 O HOH C 146 -13.774 2.466 -4.032 1.00 22.15 O -HETATM 4680 O HOH C 147 5.273 9.077 14.193 1.00 28.02 O -HETATM 4681 O HOH C 148 -11.466 3.494 -0.405 1.00 32.97 O -HETATM 4682 O HOH C 149 -10.454 4.898 14.327 1.00 33.04 O -HETATM 4683 O HOH C 150 -7.824 6.701 2.273 1.00 27.40 O -HETATM 4684 O HOH C 151 -1.248 -1.596 20.098 1.00 29.84 O -HETATM 4685 O HOH C 152 2.150 -0.244 14.446 1.00 30.74 O -HETATM 4686 O HOH C 153 -2.060 18.771 19.773 1.00 29.22 O -HETATM 4687 O HOH C 154 -21.154 14.002 13.362 1.00 32.40 O -HETATM 4688 O HOH C 155 -9.105 3.030 0.663 1.00 28.46 O -HETATM 4689 O HOH C 156 0.739 12.802 4.676 1.00 38.51 O -HETATM 4690 O HOH C 157 -8.549 18.107 15.436 1.00 35.20 O -HETATM 4691 O HOH C 158 -3.358 1.489 20.400 1.00 39.88 O -HETATM 4692 O HOH C 159 -2.351 -4.643 6.766 1.00 36.39 O -HETATM 4693 O HOH C 160 -9.995 6.820 0.255 1.00 29.81 O -HETATM 4694 O HOH C 161 -1.621 21.259 16.530 1.00 33.74 O -HETATM 4695 O HOH C 162 -5.469 23.850 15.062 1.00 31.03 O -HETATM 4696 O HOH C 163 3.572 1.751 6.044 1.00 29.72 O -HETATM 4697 O HOH C 164 -12.295 6.520 21.611 1.00 31.11 O -HETATM 4698 O HOH C 165 -14.251 13.845 17.234 1.00 30.77 O -HETATM 4699 O HOH C 166 -17.414 -5.952 27.962 1.00 34.94 O -HETATM 4700 O HOH C 167 -3.547 16.435 20.027 1.00 34.58 O -HETATM 4701 O HOH C 168 -16.355 -6.652 7.174 1.00 37.69 O -HETATM 4702 O HOH C 169 -7.541 12.855 -2.773 1.00 34.39 O -HETATM 4703 O HOH C 170 -4.225 9.070 1.455 1.00 35.72 O -HETATM 4704 O HOH C 171 -25.974 -1.828 7.173 1.00 32.50 O -HETATM 4705 O HOH C 172 -9.581 -6.364 21.942 1.00 37.91 O -HETATM 4706 O HOH C 173 -14.874 4.521 23.126 1.00 36.81 O -HETATM 4707 O HOH C 174 -15.534 20.875 -10.339 1.00 37.83 O -HETATM 4708 O HOH C 175 -8.242 21.385 2.969 1.00 35.70 O -HETATM 4709 O HOH C 176 -5.634 24.523 6.954 1.00 37.22 O -HETATM 4710 O HOH C 177 -22.981 14.501 -8.660 1.00 34.30 O -HETATM 4711 O HOH C 178 -13.871 16.688 -10.143 1.00 36.92 O -HETATM 4712 O HOH C 179 -20.275 19.235 8.097 1.00 34.30 O -HETATM 4713 O HOH C 180 1.720 15.273 3.670 1.00 39.46 O -HETATM 4714 O HOH C 181 -2.824 18.993 10.315 1.00 37.49 O -HETATM 4715 O HOH C 182 -2.160 0.091 22.111 1.00 39.39 O -HETATM 4716 O HOH C 183 7.922 12.037 14.216 1.00 34.40 O -HETATM 4717 O HOH C 184 -2.698 5.986 4.174 1.00 37.01 O -HETATM 4718 O HOH C 185 6.321 10.115 3.931 1.00 35.17 O -HETATM 4719 O HOH C 186 -7.096 21.140 15.539 1.00 35.39 O -HETATM 4720 O HOH C 187 -10.581 17.364 16.459 1.00 39.95 O -HETATM 4721 O HOH C 188 -4.668 13.050 -0.747 1.00 39.36 O -HETATM 4722 O HOH C 189 -4.764 -6.228 5.515 1.00 40.89 O -HETATM 4723 O HOH C 190 4.693 12.083 7.558 1.00 40.24 O -HETATM 4724 O HOH C 191 -4.731 16.453 2.295 1.00 36.37 O -HETATM 4725 O HOH C 192 -1.055 11.866 -0.448 1.00 43.19 O -HETATM 4726 O HOH C 193 -18.517 -8.355 15.267 1.00 35.55 O -HETATM 4727 O HOH C 194 6.547 9.706 16.296 1.00 41.86 O -HETATM 4728 O HOH C 195 0.029 22.606 14.164 1.00 43.02 O -HETATM 4729 O HOH C 196 -11.367 0.306 28.463 1.00 44.30 O -HETATM 4730 O HOH C 197 -19.950 -10.635 14.301 1.00 40.17 O -HETATM 4731 O HOH C 198 -7.047 -6.324 20.098 1.00 36.98 O -HETATM 4732 O HOH C 199 -23.876 1.108 14.102 1.00 33.31 O -HETATM 4733 O HOH C 200 -34.199 8.033 11.037 1.00 40.72 O -HETATM 4734 O HOH C 201 -14.173 13.393 -8.778 1.00 43.21 O -HETATM 4735 O HOH D 149 0.061 -2.494 -16.397 1.00 18.64 O -HETATM 4736 O HOH D 150 -8.041 -19.581 -16.153 1.00 26.28 O -HETATM 4737 O HOH D 151 2.825 -3.769 -9.602 1.00 23.08 O -HETATM 4738 O HOH D 152 -2.494 -0.118 -14.151 1.00 25.33 O -HETATM 4739 O HOH D 153 -9.792 -8.060 0.750 1.00 30.48 O -HETATM 4740 O HOH D 154 -6.518 -22.534 -15.665 1.00 34.60 O -HETATM 4741 O HOH D 155 -17.398 -13.549 8.357 1.00 35.82 O -HETATM 4742 O HOH D 156 5.350 -9.378 -15.018 1.00 27.68 O -HETATM 4743 O HOH D 157 -6.300 -24.347 -19.100 1.00 35.93 O -HETATM 4744 O HOH D 158 -9.520 7.447 -21.130 1.00 40.04 O -HETATM 4745 O HOH D 159 -16.425 -5.250 -24.764 1.00 32.57 O -HETATM 4746 O HOH D 160 -7.987 -14.493 1.146 1.00 34.30 O -HETATM 4747 O HOH D 161 -3.890 0.572 -11.856 1.00 34.78 O -HETATM 4748 O HOH D 162 -29.504 -0.198 -4.474 1.00 38.63 O -HETATM 4749 O HOH D 163 -25.631 -15.732 -9.906 1.00 33.22 O -HETATM 4750 O HOH D 164 -2.623 -18.453 -21.128 1.00 35.47 O -HETATM 4751 O HOH D 165 -2.780 -19.130 -10.800 1.00 30.23 O -HETATM 4752 O HOH D 166 -25.734 -4.456 7.605 1.00 34.33 O -HETATM 4753 O HOH D 167 -11.771 -10.816 5.496 1.00 38.68 O -HETATM 4754 O HOH D 168 -9.924 0.291 -2.970 1.00 38.71 O -HETATM 4755 O HOH D 169 -25.514 -14.066 2.449 1.00 36.60 O -HETATM 4756 O HOH D 170 -5.455 -17.392 -4.316 1.00 34.43 O -HETATM 4757 O HOH D 171 2.688 -11.418 -8.564 1.00 35.73 O -HETATM 4758 O HOH D 172 7.091 -10.993 -18.224 1.00 32.39 O -HETATM 4759 O HOH D 173 -9.377 -6.399 -3.029 1.00 35.44 O -HETATM 4760 O HOH D 174 -16.565 -17.782 -17.506 1.00 41.02 O -HETATM 4761 O HOH D 175 -8.141 -3.463 -24.390 1.00 37.14 O -HETATM 4762 O HOH D 176 -16.560 -15.177 -19.016 1.00 34.89 O -HETATM 4763 O HOH D 177 3.477 -8.048 -19.033 1.00 35.94 O -HETATM 4764 O HOH D 178 -24.698 -11.573 8.724 1.00 38.01 O -HETATM 4765 O HOH D 179 2.193 -4.435 -6.557 1.00 38.51 O -HETATM 4766 O HOH D 180 -29.898 -16.926 -2.135 1.00 36.37 O -HETATM 4767 O HOH D 181 -7.374 8.034 -17.831 1.00 34.05 O -HETATM 4768 O HOH D 182 -24.015 0.401 -15.301 1.00 39.14 O -HETATM 4769 O HOH D 183 -12.141 9.790 -10.238 1.00 38.30 O -HETATM 4770 O HOH D 184 -5.765 -3.569 -23.682 1.00 36.68 O -HETATM 4771 O HOH D 185 -4.860 -9.811 -2.967 1.00 37.10 O -HETATM 4772 O HOH D 186 -23.107 -4.490 -24.359 1.00 37.97 O -HETATM 4773 O HOH D 187 -10.377 -9.632 -7.043 1.00 38.85 O -HETATM 4774 O HOH D 188 -7.871 -9.078 2.406 1.00 43.37 O -HETATM 4775 O HOH D 189 -27.610 -10.991 5.353 1.00 43.46 O -HETATM 4776 O HOH D 190 -14.034 2.806 -30.367 1.00 41.77 O -HETATM 4777 O HOH D 191 -32.905 -9.033 0.480 1.00 43.68 O -HETATM 4778 O HOH D 192 -28.749 -13.315 1.938 1.00 45.36 O -HETATM 4779 O HOH D 193 0.516 -8.074 -26.354 1.00 41.53 O -HETATM 4780 O HOH D 194 -20.080 -9.873 -22.862 1.00 36.25 O -HETATM 4781 O HOH D 195 -13.442 9.778 -13.572 1.00 39.70 O -HETATM 4782 O HOH D 196 -24.804 -2.608 -15.488 1.00 37.79 O -HETATM 4783 O HOH D 197 -1.263 -2.837 -21.251 1.00 45.10 O -CONECT 650 4389 -CONECT 1771 4433 -CONECT 2844 4476 -CONECT 3965 4520 -CONECT 4389 650 4394 4405 4413 -CONECT 4389 4421 -CONECT 4390 4395 4425 -CONECT 4391 4398 4406 -CONECT 4392 4409 4414 -CONECT 4393 4417 4422 -CONECT 4394 4389 4395 4398 -CONECT 4395 4390 4394 4396 -CONECT 4396 4395 4397 4400 -CONECT 4397 4396 4398 4399 -CONECT 4398 4391 4394 4397 -CONECT 4399 4397 -CONECT 4400 4396 4401 -CONECT 4401 4400 4402 -CONECT 4402 4401 4403 4404 -CONECT 4403 4402 -CONECT 4404 4402 -CONECT 4405 4389 4406 4409 -CONECT 4406 4391 4405 4407 -CONECT 4407 4406 4408 4410 -CONECT 4408 4407 4409 4411 -CONECT 4409 4392 4405 4408 -CONECT 4410 4407 -CONECT 4411 4408 4412 -CONECT 4412 4411 -CONECT 4413 4389 4414 4417 -CONECT 4414 4392 4413 4415 -CONECT 4415 4414 4416 4418 -CONECT 4416 4415 4417 4419 -CONECT 4417 4393 4413 4416 -CONECT 4418 4415 -CONECT 4419 4416 4420 -CONECT 4420 4419 -CONECT 4421 4389 4422 4425 -CONECT 4422 4393 4421 4423 -CONECT 4423 4422 4424 4426 -CONECT 4424 4423 4425 4427 -CONECT 4425 4390 4421 4424 -CONECT 4426 4423 -CONECT 4427 4424 4428 -CONECT 4428 4427 4429 -CONECT 4429 4428 4430 4431 -CONECT 4430 4429 -CONECT 4431 4429 -CONECT 4433 1771 4438 4449 4457 -CONECT 4433 4465 -CONECT 4434 4439 4469 -CONECT 4435 4442 4450 -CONECT 4436 4453 4458 -CONECT 4437 4461 4466 -CONECT 4438 4433 4439 4442 -CONECT 4439 4434 4438 4440 -CONECT 4440 4439 4441 4444 -CONECT 4441 4440 4442 4443 -CONECT 4442 4435 4438 4441 -CONECT 4443 4441 -CONECT 4444 4440 4445 -CONECT 4445 4444 4446 -CONECT 4446 4445 4447 4448 -CONECT 4447 4446 -CONECT 4448 4446 -CONECT 4449 4433 4450 4453 -CONECT 4450 4435 4449 4451 -CONECT 4451 4450 4452 4454 -CONECT 4452 4451 4453 4455 -CONECT 4453 4436 4449 4452 -CONECT 4454 4451 -CONECT 4455 4452 4456 -CONECT 4456 4455 -CONECT 4457 4433 4458 4461 -CONECT 4458 4436 4457 4459 -CONECT 4459 4458 4460 4462 -CONECT 4460 4459 4461 4463 -CONECT 4461 4437 4457 4460 -CONECT 4462 4459 -CONECT 4463 4460 4464 -CONECT 4464 4463 -CONECT 4465 4433 4466 4469 -CONECT 4466 4437 4465 4467 -CONECT 4467 4466 4468 4470 -CONECT 4468 4467 4469 4471 -CONECT 4469 4434 4465 4468 -CONECT 4470 4467 -CONECT 4471 4468 4472 -CONECT 4472 4471 4473 -CONECT 4473 4472 4474 4475 -CONECT 4474 4473 -CONECT 4475 4473 -CONECT 4476 2844 4481 4492 4500 -CONECT 4476 4508 -CONECT 4477 4482 4512 -CONECT 4478 4485 4493 -CONECT 4479 4496 4501 -CONECT 4480 4504 4509 -CONECT 4481 4476 4482 4485 -CONECT 4482 4477 4481 4483 -CONECT 4483 4482 4484 4487 -CONECT 4484 4483 4485 4486 -CONECT 4485 4478 4481 4484 -CONECT 4486 4484 -CONECT 4487 4483 4488 -CONECT 4488 4487 4489 -CONECT 4489 4488 4490 4491 -CONECT 4490 4489 -CONECT 4491 4489 -CONECT 4492 4476 4493 4496 -CONECT 4493 4478 4492 4494 -CONECT 4494 4493 4495 4497 -CONECT 4495 4494 4496 4498 -CONECT 4496 4479 4492 4495 -CONECT 4497 4494 -CONECT 4498 4495 4499 -CONECT 4499 4498 -CONECT 4500 4476 4501 4504 -CONECT 4501 4479 4500 4502 -CONECT 4502 4501 4503 4505 -CONECT 4503 4502 4504 4506 -CONECT 4504 4480 4500 4503 -CONECT 4505 4502 -CONECT 4506 4503 4507 -CONECT 4507 4506 -CONECT 4508 4476 4509 4512 -CONECT 4509 4480 4508 4510 -CONECT 4510 4509 4511 4513 -CONECT 4511 4510 4512 4514 -CONECT 4512 4477 4508 4511 -CONECT 4513 4510 -CONECT 4514 4511 4515 -CONECT 4515 4514 4516 -CONECT 4516 4515 4517 4518 -CONECT 4517 4516 -CONECT 4518 4516 -CONECT 4520 3965 4525 4536 4544 -CONECT 4520 4552 -CONECT 4521 4526 4556 -CONECT 4522 4529 4537 -CONECT 4523 4540 4545 -CONECT 4524 4548 4553 -CONECT 4525 4520 4526 4529 -CONECT 4526 4521 4525 4527 -CONECT 4527 4526 4528 4531 -CONECT 4528 4527 4529 4530 -CONECT 4529 4522 4525 4528 -CONECT 4530 4528 -CONECT 4531 4527 4532 -CONECT 4532 4531 4533 -CONECT 4533 4532 4534 4535 -CONECT 4534 4533 -CONECT 4535 4533 -CONECT 4536 4520 4537 4540 -CONECT 4537 4522 4536 4538 -CONECT 4538 4537 4539 4541 -CONECT 4539 4538 4540 4542 -CONECT 4540 4523 4536 4539 -CONECT 4541 4538 -CONECT 4542 4539 4543 -CONECT 4543 4542 -CONECT 4544 4520 4545 4548 -CONECT 4545 4523 4544 4546 -CONECT 4546 4545 4547 4549 -CONECT 4547 4546 4548 4550 -CONECT 4548 4524 4544 4547 -CONECT 4549 4546 -CONECT 4550 4547 4551 -CONECT 4551 4550 -CONECT 4552 4520 4553 4556 -CONECT 4553 4524 4552 4554 -CONECT 4554 4553 4555 4557 -CONECT 4555 4554 4556 4558 -CONECT 4556 4521 4552 4555 -CONECT 4557 4554 -CONECT 4558 4555 4559 -CONECT 4559 4558 4560 -CONECT 4560 4559 4561 4562 -CONECT 4561 4560 -CONECT 4562 4560 -MASTER 868 1 6 32 0 0 16 9 4779 4 180 46 -END diff --git a/mode/examples/Demos/Graphics/RotatingArcs/RotatingArcs.pde b/mode/examples/Demos/Graphics/RotatingArcs/RotatingArcs.pde deleted file mode 100644 index b51b74f38..000000000 --- a/mode/examples/Demos/Graphics/RotatingArcs/RotatingArcs.pde +++ /dev/null @@ -1,162 +0,0 @@ -/** - * Geometry - * by Marius Watz. - * - * Using sin/cos lookup tables, blends colors, and draws a series of - * rotating arcs on the screen. -*/ - -// Trig lookup tables borrowed from Toxi; cryptic but effective. -float sinLUT[]; -float cosLUT[]; -float SINCOS_PRECISION=1.0; -int SINCOS_LENGTH= int((360.0/SINCOS_PRECISION)); - -// System data -boolean dosave=false; -int num; -float pt[]; -int style[]; - - -void setup() { - size(displayWidth, displayHeight, P3D); - background(255); - - // Fill the tables - sinLUT=new float[SINCOS_LENGTH]; - cosLUT=new float[SINCOS_LENGTH]; - for (int i = 0; i < SINCOS_LENGTH; i++) { - sinLUT[i]= (float)Math.sin(i*DEG_TO_RAD*SINCOS_PRECISION); - cosLUT[i]= (float)Math.cos(i*DEG_TO_RAD*SINCOS_PRECISION); - } - - num = 50; - pt = new float[6*num]; // rotx, roty, deg, rad, w, speed - style = new int[2*num]; // color, render style - - // Set up arc shapes - int index=0; - float prob; - for (int i=0; i90) pt[index]=(int)random(8,27)*10; - - pt[index++] = int(random(2,50)*5); // Radius. Space them out nicely - - pt[index++] = random(4,32); // Width of band - if(random(100)>90) pt[index]=random(40,60); // Width of band - - pt[index++] = radians(random(5,30))/5; // Speed of rotation - - // get colors - prob = random(100); - if(prob<30) style[i*2]=colorBlended(random(1), 255,0,100, 255,0,0, 210); - else if(prob<70) style[i*2]=colorBlended(random(1), 0,153,255, 170,225,255, 210); - else if(prob<90) style[i*2]=colorBlended(random(1), 200,255,0, 150,255,0, 210); - else style[i*2]=color(255,255,255, 220); - - if(prob<50) style[i*2]=colorBlended(random(1), 200,255,0, 50,120,0, 210); - else if(prob<90) style[i*2]=colorBlended(random(1), 255,100,0, 255,255,0, 210); - else style[i*2]=color(255,255,255, 220); - - style[i*2+1]=(int)(random(100))%3; - } -} - -void draw() { - - background(0); - - int index=0; - translate(width/2, height/2, 0); - rotateX(PI/6); - rotateY(PI/6); - - for (int i = 0; i < num; i++) { - pushMatrix(); - - rotateX(pt[index++]); - rotateY(pt[index++]); - - if(style[i*2+1]==0) { - stroke(style[i*2]); - noFill(); - strokeWeight(1); - arcLine(0,0, pt[index++],pt[index++],pt[index++]); - } - else if(style[i*2+1]==1) { - fill(style[i*2]); - noStroke(); - arcLineBars(0,0, pt[index++],pt[index++],pt[index++]); - } - else { - fill(style[i*2]); - noStroke(); - arc(0,0, pt[index++],pt[index++],pt[index++]); - } - - // increase rotation - pt[index-5]+=pt[index]/10; - pt[index-4]+=pt[index++]/20; - - popMatrix(); - } -} - - -// Get blend of two colors -int colorBlended(float fract, -float r, float g, float b, -float r2, float g2, float b2, float a) { - - r2 = (r2 - r); - g2 = (g2 - g); - b2 = (b2 - b); - return color(r + r2 * fract, g + g2 * fract, b + b2 * fract, a); -} - - -// Draw arc line -void arcLine(float x,float y,float deg,float rad,float w) { - int a=(int)(min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1)); - int numlines=(int)(w/2); - - for (int j=0; j= capacity) { - // there are all sorts of possible solutions here, - // but for abject simplicity, I don't do anything. - } - else { - float v = distToLast(x, y); - float p = getPressureFromVelocity(v); - path[nPoints++].set(x,y,p); - - if (nPoints > 1) { - exists = true; - jumpDx = path[nPoints-1].x - path[0].x; - jumpDy = path[nPoints-1].y - path[0].y; - } - } - - } - - float getPressureFromVelocity(float v) { - final float scale = 18; - final float minP = 0.02; - final float oldP = (nPoints > 0) ? path[nPoints-1].p : 0; - return ((minP + max(0, 1.0 - v/scale)) + (damp1*oldP))*dampInv; - } - - void setPressures() { - // pressures vary from 0...1 - float pressure; - Vec3f tmp; - float t = 0; - float u = 1.0 / (nPoints - 1)*TWO_PI; - for (int i = 0; i < nPoints; i++) { - pressure = sqrt((1.0 - cos(t))*0.5); - path[i].p = pressure; - t += u; - } - } - - float distToLast(float ix, float iy) { - if (nPoints > 0) { - Vec3f v = path[nPoints-1]; - float dx = v.x - ix; - float dy = v.y - iy; - return mag(dx, dy); - } - else { - return 30; - } - } - - void compile() { - // compute the polygons from the path of Vec3f's - if (exists) { - clearPolys(); - - Vec3f p0, p1, p2; - float radius0, radius1; - float ax, bx, cx, dx; - float ay, by, cy, dy; - int axi, bxi, cxi, dxi, axip, axid; - int ayi, byi, cyi, dyi, ayip, ayid; - float p1x, p1y; - float dx01, dy01, hp01, si01, co01; - float dx02, dy02, hp02, si02, co02; - float dx13, dy13, hp13, si13, co13; - float taper = 1.0; - - int nPathPoints = nPoints - 1; - int lastPolyIndex = nPathPoints - 1; - float npm1finv = 1.0 / max(1, nPathPoints - 1); - - // handle the first point - p0 = path[0]; - p1 = path[1]; - radius0 = p0.p * thickness; - dx01 = p1.x - p0.x; - dy01 = p1.y - p0.y; - hp01 = sqrt(dx01*dx01 + dy01*dy01); - if (hp01 == 0) { - hp02 = 0.0001; - } - co01 = radius0 * dx01 / hp01; - si01 = radius0 * dy01 / hp01; - ax = p0.x - si01; - ay = p0.y + co01; - bx = p0.x + si01; - by = p0.y - co01; - - int xpts[]; - int ypts[]; - - int LC = 20; - int RC = w-LC; - int TC = 20; - int BC = h-TC; - float mint = 0.618; - float tapow = 0.4; - - // handle the middle points - int i = 1; - Polygon apoly; - for (i = 1; i < nPathPoints; i++) { - taper = pow((lastPolyIndex-i)*npm1finv,tapow); - - p0 = path[i-1]; - p1 = path[i ]; - p2 = path[i+1]; - p1x = p1.x; - p1y = p1.y; - radius1 = Math.max(mint,taper*p1.p*thickness); - - // assumes all segments are roughly the same length... - dx02 = p2.x - p0.x; - dy02 = p2.y - p0.y; - hp02 = (float) Math.sqrt(dx02*dx02 + dy02*dy02); - if (hp02 != 0) { - hp02 = radius1/hp02; - } - co02 = dx02 * hp02; - si02 = dy02 * hp02; - - // translate the integer coordinates to the viewing rectangle - axi = axip = (int)ax; - ayi = ayip = (int)ay; - axi=(axi<0)?(w-((-axi)%w)):axi%w; - axid = axi-axip; - ayi=(ayi<0)?(h-((-ayi)%h)):ayi%h; - ayid = ayi-ayip; - - // set the vertices of the polygon - apoly = polygons[nPolys++]; - xpts = apoly.xpoints; - ypts = apoly.ypoints; - xpts[0] = axi = axid + axip; - xpts[1] = bxi = axid + (int) bx; - xpts[2] = cxi = axid + (int)(cx = p1x + si02); - xpts[3] = dxi = axid + (int)(dx = p1x - si02); - ypts[0] = ayi = ayid + ayip; - ypts[1] = byi = ayid + (int) by; - ypts[2] = cyi = ayid + (int)(cy = p1y - co02); - ypts[3] = dyi = ayid + (int)(dy = p1y + co02); - - // keep a record of where we cross the edge of the screen - crosses[i] = 0; - if ((axi<=LC)||(bxi<=LC)||(cxi<=LC)||(dxi<=LC)) { - crosses[i]|=1; - } - if ((axi>=RC)||(bxi>=RC)||(cxi>=RC)||(dxi>=RC)) { - crosses[i]|=2; - } - if ((ayi<=TC)||(byi<=TC)||(cyi<=TC)||(dyi<=TC)) { - crosses[i]|=4; - } - if ((ayi>=BC)||(byi>=BC)||(cyi>=BC)||(dyi>=BC)) { - crosses[i]|=8; - } - - //swap data for next time - ax = dx; - ay = dy; - bx = cx; - by = cy; - } - - // handle the last point - p2 = path[nPathPoints]; - apoly = polygons[nPolys++]; - xpts = apoly.xpoints; - ypts = apoly.ypoints; - - xpts[0] = (int)ax; - xpts[1] = (int)bx; - xpts[2] = (int)(p2.x); - xpts[3] = (int)(p2.x); - - ypts[0] = (int)ay; - ypts[1] = (int)by; - ypts[2] = (int)(p2.y); - ypts[3] = (int)(p2.y); - - } - } - - void smooth() { - // average neighboring points - - final float weight = 18; - final float scale = 1.0 / (weight + 2); - int nPointsMinusTwo = nPoints - 2; - Vec3f lower, upper, center; - - for (int i = 1; i < nPointsMinusTwo; i++) { - lower = path[i-1]; - center = path[i]; - upper = path[i+1]; - - center.x = (lower.x + weight*center.x + upper.x)*scale; - center.y = (lower.y + weight*center.y + upper.y)*scale; - } - } -} - diff --git a/mode/examples/Demos/Graphics/Yellowtail/Polygon.pde b/mode/examples/Demos/Graphics/Yellowtail/Polygon.pde deleted file mode 100644 index f00d53875..000000000 --- a/mode/examples/Demos/Graphics/Yellowtail/Polygon.pde +++ /dev/null @@ -1,12 +0,0 @@ -public class Polygon { - int npoints; - int[] xpoints; - int[] ypoints; - - public Polygon(int n) { - npoints = n; - xpoints = new int[n]; - ypoints = new int[n]; - } -} - diff --git a/mode/examples/Demos/Graphics/Yellowtail/Vec3f.pde b/mode/examples/Demos/Graphics/Yellowtail/Vec3f.pde deleted file mode 100644 index 865d3c32f..000000000 --- a/mode/examples/Demos/Graphics/Yellowtail/Vec3f.pde +++ /dev/null @@ -1,19 +0,0 @@ -class Vec3f { - float x; - float y; - float p; // Pressure - - Vec3f() { - set(0, 0, 0); - } - - Vec3f(float ix, float iy, float ip) { - set(ix, iy, ip); - } - - void set(float ix, float iy, float ip) { - x = ix; - y = iy; - p = ip; - } -} diff --git a/mode/examples/Demos/Graphics/Yellowtail/Yellowtail.pde b/mode/examples/Demos/Graphics/Yellowtail/Yellowtail.pde deleted file mode 100644 index a26cba3fc..000000000 --- a/mode/examples/Demos/Graphics/Yellowtail/Yellowtail.pde +++ /dev/null @@ -1,186 +0,0 @@ -/** - * Yellowtail - * by Golan Levin (www.flong.com). - * - * Click, drag, and release to create a kinetic gesture. - * - * Yellowtail (1998-2000) is an interactive software system for the gestural - * creation and performance of real-time abstract animation. Yellowtail repeats - * a user's strokes end-over-end, enabling simultaneous specification of a - * line's shape and quality of movement. Each line repeats according to its - * own period, producing an ever-changing and responsive display of lively, - * worm-like textures. - */ - -Gesture gestureArray[]; -final int nGestures = 36; // Number of gestures -final int minMove = 3; // Minimum travel for a new point -int currentGestureID; - -Polygon tempP; -int tmpXp[]; -int tmpYp[]; - - -void setup() { - size(displayWidth, displayHeight, P2D); - background(0, 0, 0); - noStroke(); - - currentGestureID = -1; - gestureArray = new Gesture[nGestures]; - for (int i = 0; i < nGestures; i++) { - gestureArray[i] = new Gesture(width, height); - } - clearGestures(); -} - - -void draw() { - background(0); - - updateGeometry(); - fill(255, 255, 245); - for (int i = 0; i < nGestures; i++) { - renderGesture(gestureArray[i], width, height); - } -} - -void mousePressed() { - currentGestureID = (currentGestureID+1) % nGestures; - Gesture G = gestureArray[currentGestureID]; - G.clear(); - G.clearPolys(); - G.addPoint(mouseX, mouseY); -} - - -void mouseDragged() { - if (currentGestureID >= 0) { - Gesture G = gestureArray[currentGestureID]; - if (G.distToLast(mouseX, mouseY) > minMove) { - G.addPoint(mouseX, mouseY); - G.smooth(); - G.compile(); - } - } -} - - -void keyPressed() { - if (key == '+' || key == '=') { - if (currentGestureID >= 0) { - float th = gestureArray[currentGestureID].thickness; - gestureArray[currentGestureID].thickness = min(96, th+1); - gestureArray[currentGestureID].compile(); - } - } else if (key == '-') { - if (currentGestureID >= 0) { - float th = gestureArray[currentGestureID].thickness; - gestureArray[currentGestureID].thickness = max(2, th-1); - gestureArray[currentGestureID].compile(); - } - } else if (key == ' ') { - clearGestures(); - } -} - - -void renderGesture(Gesture gesture, int w, int h) { - if (gesture.exists) { - if (gesture.nPolys > 0) { - Polygon polygons[] = gesture.polygons; - int crosses[] = gesture.crosses; - - int xpts[]; - int ypts[]; - Polygon p; - int cr; - - beginShape(QUADS); - int gnp = gesture.nPolys; - for (int i=0; i 0) { - if ((cr & 3)>0) { - vertex(xpts[0]+w, ypts[0]); - vertex(xpts[1]+w, ypts[1]); - vertex(xpts[2]+w, ypts[2]); - vertex(xpts[3]+w, ypts[3]); - - vertex(xpts[0]-w, ypts[0]); - vertex(xpts[1]-w, ypts[1]); - vertex(xpts[2]-w, ypts[2]); - vertex(xpts[3]-w, ypts[3]); - } - if ((cr & 12)>0) { - vertex(xpts[0], ypts[0]+h); - vertex(xpts[1], ypts[1]+h); - vertex(xpts[2], ypts[2]+h); - vertex(xpts[3], ypts[3]+h); - - vertex(xpts[0], ypts[0]-h); - vertex(xpts[1], ypts[1]-h); - vertex(xpts[2], ypts[2]-h); - vertex(xpts[3], ypts[3]-h); - } - - // I have knowingly retained the small flaw of not - // completely dealing with the corner conditions - // (the case in which both of the above are true). - } - } - endShape(); - } - } -} - -void updateGeometry() { - Gesture J; - for (int g=0; g 0) { - path = gesture.path; - for (int i = nPts1; i > 0; i--) { - path[i].x = path[i-1].x; - path[i].y = path[i-1].y; - } - path[0].x = path[nPts1].x - jx; - path[0].y = path[nPts1].y - jy; - gesture.compile(); - } - } -} - -void clearGestures() { - for (int i = 0; i < nGestures; i++) { - gestureArray[i].clear(); - } -} diff --git a/mode/examples/Demos/Performance/CubicGridImmediate/CubicGridImmediate.pde b/mode/examples/Demos/Performance/CubicGridImmediate/CubicGridImmediate.pde deleted file mode 100644 index 1faa0bcb4..000000000 --- a/mode/examples/Demos/Performance/CubicGridImmediate/CubicGridImmediate.pde +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Cubic Grid - * by Ira Greenberg. - * - * 3D translucent colored grid uses nested pushMatrix() - * and popMatrix() functions. - */ - -float boxSize = 50; -float margin = boxSize*2; -float depth = 400; -color boxFill; - -int fcount, lastm; -float frate; -int fint = 3; - -void setup() { - size(640, 360, P3D); - orientation(LANDSCAPE); - frameRate(60); - noSmooth(); - noStroke(); -} - -void draw() { - background(255); - - hint(DISABLE_DEPTH_TEST); - - // Center and spin grid - pushMatrix(); - translate(width/2, height/2, -depth); - rotateY(frameCount * 0.01); - rotateX(frameCount * 0.01); - - // Build grid using multiple translations - for (float i =- depth/2+margin; i <= depth/2-margin; i += boxSize){ - for (float j =- height+margin; j <= height-margin; j += boxSize){ - for (float k =- width+margin; k <= width-margin; k += boxSize){ - // Base fill color on counter values, abs function - // ensures values stay within legal range - boxFill = color(abs(i), abs(j), abs(k), 50); - pushMatrix(); - translate(k, j, i); - fill(boxFill); - box(boxSize, boxSize, boxSize); - popMatrix(); - } - } - } - popMatrix(); - - hint(ENABLE_DEPTH_TEST); - - fcount += 1; - int m = millis(); - if (m - lastm > 1000 * fint) { - frate = float(fcount) / fint; - fcount = 0; - lastm = m; - println("fps: " + frate); - } - fill(0); - text("fps: " + frate, 10, 20); -} diff --git a/mode/examples/Demos/Performance/CubicGridRetained/CubicGridRetained.pde b/mode/examples/Demos/Performance/CubicGridRetained/CubicGridRetained.pde deleted file mode 100644 index 86ce45720..000000000 --- a/mode/examples/Demos/Performance/CubicGridRetained/CubicGridRetained.pde +++ /dev/null @@ -1,63 +0,0 @@ -float boxSize = 50; -float margin = boxSize*2; -float depth = 400; -color boxFill; - -PShape grid; - -int fcount, lastm; -float frate; -int fint = 3; - -void setup() { - size(640, 360, P3D); - orientation(LANDSCAPE); - frameRate(60); - noSmooth(); - noStroke(); - - grid = createShape(GROUP); - - // Build grid using multiple translations - for (float i =- depth/2+margin; i <= depth/2-margin; i += boxSize){ - for (float j =- height+margin; j <= height-margin; j += boxSize){ - for (float k =- width+margin; k <= width-margin; k += boxSize){ - // Base fill color on counter values, abs function - // ensures values stay within legal range - boxFill = color(abs(i), abs(j), abs(k), 50); - PShape cube = createShape(BOX, boxSize, boxSize, boxSize); - cube.setFill(boxFill); - cube.translate(k, j, i); - grid.addChild(cube); - } - } - } -} - -void draw() { - background(255); - - hint(DISABLE_DEPTH_TEST); - - // Center and spin grid - pushMatrix(); - translate(width/2, height/2, -depth); - rotateY(frameCount * 0.01); - rotateX(frameCount * 0.01); - - shape(grid); - popMatrix(); - - hint(ENABLE_DEPTH_TEST); - - fcount += 1; - int m = millis(); - if (m - lastm > 1000 * fint) { - frate = float(fcount) / fint; - fcount = 0; - lastm = m; - println("fps: " + frate); - } - fill(0); - text("fps: " + frate, 10, 20); -} diff --git a/mode/examples/Demos/Performance/DynamicParticlesImmediate/DynamicParticlesImmediate.pde b/mode/examples/Demos/Performance/DynamicParticlesImmediate/DynamicParticlesImmediate.pde deleted file mode 100644 index f7e9c9cac..000000000 --- a/mode/examples/Demos/Performance/DynamicParticlesImmediate/DynamicParticlesImmediate.pde +++ /dev/null @@ -1,119 +0,0 @@ -PImage sprite; - -int npartTotal = 1000; -int npartPerFrame = 10; -float speed = 1.0; -float gravity = 0.05; -float partSize = 20; - -int partLifetime; -PVector positions[]; -PVector velocities[]; -int lifetimes[]; - -int fcount, lastm; -float frate; -int fint = 3; - -void setup() { - size(640, 480, P3D); - orientation(LANDSCAPE); - frameRate(60); - - sprite = loadImage("sprite.png"); - - partLifetime = npartTotal / npartPerFrame; - initPositions(); - initVelocities(); - initLifetimes(); - - // Writing to the depth buffer is disabled to avoid rendering - // artifacts due to the fact that the particles are semi-transparent - // but not z-sorted. - hint(DISABLE_DEPTH_MASK); - - // Testing some hints - //hint(DISABLE_TRANSFORM_CACHE); - //hint(ENABLE_ACCURATE_2D); -} - -void draw () { - background(0); - - for (int n = 0; n < npartTotal; n++) { - lifetimes[n]++; - if (lifetimes[n] == partLifetime) { - lifetimes[n] = 0; - } - - if (0 <= lifetimes[n]) { - float opacity = 1.0 - float(lifetimes[n]) / partLifetime; - - if (lifetimes[n] == 0) { - // Re-spawn dead particle - positions[n].x = mouseX; - positions[n].y = mouseY; - - float angle = random(0, TWO_PI); - float s = random(0.5 * speed, 0.5 * speed); - velocities[n].x = s * cos(angle); - velocities[n].y = s * sin(angle); - } else { - positions[n].x += velocities[n].x; - positions[n].y += velocities[n].y; - - velocities[n].y += gravity; - } - drawParticle(positions[n], opacity); - } - } - - fcount += 1; - int m = millis(); - if (m - lastm > 1000 * fint) { - frate = float(fcount) / fint; - fcount = 0; - lastm = m; - println("fps: " + frate); - } -} - -void drawParticle(PVector center, float opacity) { - beginShape(QUAD); - noStroke(); - tint(255, opacity * 255); - texture(sprite); - normal(0, 0, 1); - vertex(center.x - partSize/2, center.y - partSize/2, 0, 0); - vertex(center.x + partSize/2, center.y - partSize/2, sprite.width, 0); - vertex(center.x + partSize/2, center.y + partSize/2, sprite.width, sprite.height); - vertex(center.x - partSize/2, center.y + partSize/2, 0, sprite.height); - endShape(); -} - -void initPositions() { - positions = new PVector[npartTotal]; - for (int n = 0; n < positions.length; n++) { - positions[n] = new PVector(); - } -} - -void initVelocities() { - velocities = new PVector[npartTotal]; - for (int n = 0; n < velocities.length; n++) { - velocities[n] = new PVector(); - } -} - -void initLifetimes() { - // Initializing particles with negative lifetimes so they are added - // progressively into the screen during the first frames of the sketch - lifetimes = new int[npartTotal]; - int t = -1; - for (int n = 0; n < lifetimes.length; n++) { - if (n % npartPerFrame == 0) { - t++; - } - lifetimes[n] = -t; - } -} diff --git a/mode/examples/Demos/Performance/DynamicParticlesImmediate/data/sprite.png b/mode/examples/Demos/Performance/DynamicParticlesImmediate/data/sprite.png deleted file mode 100644 index cc0f45cba..000000000 Binary files a/mode/examples/Demos/Performance/DynamicParticlesImmediate/data/sprite.png and /dev/null differ diff --git a/mode/examples/Demos/Performance/DynamicParticlesRetained/DynamicParticlesRetained.pde b/mode/examples/Demos/Performance/DynamicParticlesRetained/DynamicParticlesRetained.pde deleted file mode 100644 index 10f312e97..000000000 --- a/mode/examples/Demos/Performance/DynamicParticlesRetained/DynamicParticlesRetained.pde +++ /dev/null @@ -1,112 +0,0 @@ -PShape particles; -PImage sprite; - -int npartTotal = 1000; -int npartPerFrame = 10; -float speed = 1.0; -float gravity = 0.05; -float partSize = 20; - -int partLifetime; -PVector velocities[]; -int lifetimes[]; - -int fcount, lastm; -float frate; -int fint = 3; - -void setup() { - size(640, 480, P3D); - orientation(LANDSCAPE); - frameRate(60); - - particles = createShape(PShape.GROUP); - sprite = loadImage("sprite.png"); - - for (int n = 0; n < npartTotal; n++) { - PShape part = createShape(); - part.beginShape(QUAD); - part.noStroke(); - part.texture(sprite); - part.normal(0, 0, 1); - part.vertex(-partSize/2, -partSize/2, 0, 0); - part.vertex(+partSize/2, -partSize/2, sprite.width, 0); - part.vertex(+partSize/2, +partSize/2, sprite.width, sprite.height); - part.vertex(-partSize/2, +partSize/2, 0, sprite.height); - part.endShape(); - particles.addChild(part); - } - - partLifetime = npartTotal / npartPerFrame; - initVelocities(); - initLifetimes(); - - // Writing to the depth buffer is disabled to avoid rendering - // artifacts due to the fact that the particles are semi-transparent - // but not z-sorted. - hint(DISABLE_DEPTH_MASK); -} - -void draw () { - background(0); - - for (int n = 0; n < particles.getChildCount(); n++) { - PShape part = particles.getChild(n); - - lifetimes[n]++; - if (lifetimes[n] == partLifetime) { - lifetimes[n] = 0; - } - - if (0 <= lifetimes[n]) { - float opacity = 1.0 - float(lifetimes[n]) / partLifetime; - part.setTint(color(255, opacity * 255)); - - if (lifetimes[n] == 0) { - // Re-spawn dead particle - part.resetMatrix(); - part.translate(mouseX, mouseY); - float angle = random(0, TWO_PI); - float s = random(0.5 * speed, 0.5 * speed); - velocities[n].x = s * cos(angle); - velocities[n].y = s * sin(angle); - } else { - part.translate(velocities[n].x, velocities[n].y); - velocities[n].y += gravity; - } - } else { - part.setTint(color(0)); - } - } - - shape(particles); - - fcount += 1; - int m = millis(); - if (m - lastm > 1000 * fint) { - frate = float(fcount) / fint; - fcount = 0; - lastm = m; - println("fps: " + frate); - } -} - -void initVelocities() { - velocities = new PVector[npartTotal]; - for (int n = 0; n < velocities.length; n++) { - velocities[n] = new PVector(); - } -} - -void initLifetimes() { - // Initializing particles with negative lifetimes so they are added - // progressively into the screen during the first frames of the sketch - lifetimes = new int[npartTotal]; - int t = -1; - for (int n = 0; n < lifetimes.length; n++) { - if (n % npartPerFrame == 0) { - t++; - } - lifetimes[n] = -t; - } -} diff --git a/mode/examples/Demos/Performance/DynamicParticlesRetained/data/sprite.png b/mode/examples/Demos/Performance/DynamicParticlesRetained/data/sprite.png deleted file mode 100644 index cc0f45cba..000000000 Binary files a/mode/examples/Demos/Performance/DynamicParticlesRetained/data/sprite.png and /dev/null differ diff --git a/mode/examples/Demos/Performance/Esfera/Esfera.pde b/mode/examples/Demos/Performance/Esfera/Esfera.pde deleted file mode 100644 index b28463573..000000000 --- a/mode/examples/Demos/Performance/Esfera/Esfera.pde +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Esfera - * by David Pena. - * - * Distribucion aleatoria uniforme sobre la superficie de una esfera. - */ - -int cuantos = 1600; -pelo[] lista ; -float[] z = new float[cuantos]; -float[] phi = new float[cuantos]; -float[] largos = new float[cuantos]; -float radio = 200; -float rx = 0; -float ry =0; - -void setup() { - size(displayWidth, displayHeight, P3D); - noSmooth(); - frameRate(120); - radio = height/3.5; - - lista = new pelo[cuantos]; - for (int i=0; i 1000 * fint) { - frate = float(fcount) / fint; - fcount = 0; - lastm = m; - println("fps: " + frate); - } -} - -void drawParticle(PVector center) { - beginShape(QUAD); - noStroke(); - tint(255); - texture(sprite); - normal(0, 0, 1); - vertex(center.x - partSize/2, center.y - partSize/2, center.z, 0, 0); - vertex(center.x + partSize/2, center.y - partSize/2, center.z, sprite.width, 0); - vertex(center.x + partSize/2, center.y + partSize/2, center.z, sprite.width, sprite.height); - vertex(center.x - partSize/2, center.y + partSize/2, center.z, 0, sprite.height); - endShape(); -} - -void initPositions() { - positions = new PVector[npartTotal]; - for (int n = 0; n < positions.length; n++) { - positions[n] = new PVector(random(-500, +500), random(-500, +500), random(-500, +500)); - } -} - diff --git a/mode/examples/Demos/Performance/StaticParticlesImmediate/data/sprite.png b/mode/examples/Demos/Performance/StaticParticlesImmediate/data/sprite.png deleted file mode 100644 index cc0f45cba..000000000 Binary files a/mode/examples/Demos/Performance/StaticParticlesImmediate/data/sprite.png and /dev/null differ diff --git a/mode/examples/Demos/Performance/StaticParticlesRetained/StaticParticlesRetained.pde b/mode/examples/Demos/Performance/StaticParticlesRetained/StaticParticlesRetained.pde deleted file mode 100644 index dbc29a082..000000000 --- a/mode/examples/Demos/Performance/StaticParticlesRetained/StaticParticlesRetained.pde +++ /dev/null @@ -1,61 +0,0 @@ -PShape particles; -PImage sprite; - -int npartTotal = 5000; -float partSize = 20; - -int fcount, lastm; -float frate; -int fint = 3; - -void setup() { - size(displayWidth, displayHeight, P3D); - orientation(LANDSCAPE); - frameRate(60); - - particles = createShape(PShape.GROUP); - sprite = loadImage("sprite.png"); - - for (int n = 0; n < npartTotal; n++) { - float cx = random(-500, +500); - float cy = random(-500, +500); - float cz = random(-500, +500); - - PShape part = createShape(); - part.beginShape(QUAD); - part.noStroke(); - part.tint(255); - part.texture(sprite); - part.normal(0, 0, 1); - part.vertex(cx - partSize/2, cy - partSize/2, cz, 0, 0); - part.vertex(cx + partSize/2, cy - partSize/2, cz, sprite.width, 0); - part.vertex(cx + partSize/2, cy + partSize/2, cz, sprite.width, sprite.height); - part.vertex(cx - partSize/2, cy + partSize/2, cz, 0, sprite.height); - part.endShape(); - particles.addChild(part); - } - - // Writing to the depth buffer is disabled to avoid rendering - // artifacts due to the fact that the particles are semi-transparent - // but not z-sorted. - hint(DISABLE_DEPTH_MASK); -} - -void draw () { - background(0); - - translate(width/2, height/2); - rotateY(frameCount * 0.01); - - shape(particles); - - fcount += 1; - int m = millis(); - if (m - lastm > 1000 * fint) { - frate = float(fcount) / fint; - fcount = 0; - lastm = m; - println("fps: " + frate); - } -} - diff --git a/mode/examples/Demos/Performance/StaticParticlesRetained/data/sprite.png b/mode/examples/Demos/Performance/StaticParticlesRetained/data/sprite.png deleted file mode 100644 index cc0f45cba..000000000 Binary files a/mode/examples/Demos/Performance/StaticParticlesRetained/data/sprite.png and /dev/null differ diff --git a/mode/examples/Demos/Performance/TextRendering/TextRendering.pde b/mode/examples/Demos/Performance/TextRendering/TextRendering.pde deleted file mode 100644 index 36ae280a6..000000000 --- a/mode/examples/Demos/Performance/TextRendering/TextRendering.pde +++ /dev/null @@ -1,17 +0,0 @@ -import processing.opengl.*; - -public void setup() { - size(800, 600, OPENGL); - orientation(LANDSCAPE); - fill(0); -} - -public void draw() { - background(255); - for (int i = 0; i < 1000; i++) { - float x = random(width); - float y = random(height); - text("HELLO", x, y); - } - if (frameCount % 10 == 0) println(frameRate); -} diff --git a/mode/examples/Demos/Tests/NoBackgroundTest/NoBackgroundTest.pde b/mode/examples/Demos/Tests/NoBackgroundTest/NoBackgroundTest.pde deleted file mode 100644 index a5a1d5aa0..000000000 --- a/mode/examples/Demos/Tests/NoBackgroundTest/NoBackgroundTest.pde +++ /dev/null @@ -1,10 +0,0 @@ -void setup() { - size(400, 400, P2D); - background(255, 0, 0); - fill(255, 150); -} - -void draw() { - ellipse(mouseX, mouseY, 100, 100); -} - diff --git a/mode/examples/Demos/Tests/OffscreenTest/OffscreenTest.pde b/mode/examples/Demos/Tests/OffscreenTest/OffscreenTest.pde deleted file mode 100644 index 0244b3521..000000000 --- a/mode/examples/Demos/Tests/OffscreenTest/OffscreenTest.pde +++ /dev/null @@ -1,19 +0,0 @@ -PGraphics pg; - -void setup() { - size(400, 400, P3D); - - pg = createGraphics(400, 400, P3D); -} - -void draw() { - background(0); - - pg.beginDraw(); - pg.background(255, 0, 0); - pg.ellipse(mouseX, mouseY, 100, 100); - pg.endDraw(); - - image(pg, 0, 0, 400, 400); -} - diff --git a/mode/examples/Demos/Tests/RedrawTest/RedrawTest.pde b/mode/examples/Demos/Tests/RedrawTest/RedrawTest.pde deleted file mode 100644 index e88a3af5f..000000000 --- a/mode/examples/Demos/Tests/RedrawTest/RedrawTest.pde +++ /dev/null @@ -1,15 +0,0 @@ -void setup() { - size(400, 400, P2D); - noLoop(); -} - -void draw() { - background(255, 0, 0); - ellipse(mouseX, mouseY, 100, 50); - println("draw"); -} - -void mousePressed() { - redraw(); -} - diff --git a/mode/examples/Sensors/Accelerometer/Accelerometer.pde b/mode/examples/Sensors/Accelerometer/Accelerometer.pde deleted file mode 100644 index 56e346d4a..000000000 --- a/mode/examples/Sensors/Accelerometer/Accelerometer.pde +++ /dev/null @@ -1,49 +0,0 @@ -AccelerometerManager accel; -float ax, ay, az; - - -void setup() { - accel = new AccelerometerManager(this); - orientation(PORTRAIT); - noLoop(); -} - - -void draw() { - background(0); - fill(255); - textSize(70); - textAlign(CENTER, CENTER); - text("x: " + nf(ax, 1, 2) + "\n" + - "y: " + nf(ay, 1, 2) + "\n" + - "z: " + nf(az, 1, 2), - 0, 0, width, height); -} - - -public void resume() { - if (accel != null) { - accel.resume(); - } -} - - -public void pause() { - if (accel != null) { - accel.pause(); - } -} - - -public void shakeEvent(float force) { - println("shake : " + force); -} - - -public void accelerationEvent(float x, float y, float z) { -// println("acceleration: " + x + ", " + y + ", " + z); - ax = x; - ay = y; - az = z; - redraw(); -} \ No newline at end of file diff --git a/mode/examples/Sensors/Accelerometer/AccelerometerManager.java b/mode/examples/Sensors/Accelerometer/AccelerometerManager.java deleted file mode 100644 index 1952ea8c5..000000000 --- a/mode/examples/Sensors/Accelerometer/AccelerometerManager.java +++ /dev/null @@ -1,244 +0,0 @@ -import processing.core.PApplet; - -import java.lang.reflect.*; -import java.util.List; - -import android.content.Context; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; - - -/** - * Android Accelerometer Sensor Manager Archetype - * @author antoine vianey - * under GPL v3 : http://www.gnu.org/licenses/gpl-3.0.html - */ -public class AccelerometerManager { - /** Accuracy configuration */ - private float threshold = 0.2f; - private int interval = 1000; - - private Sensor sensor; - private SensorManager sensorManager; - // you could use an OrientationListener array instead - // if you plans to use more than one listener -// private AccelerometerListener listener; - - Method shakeEventMethod; - Method accelerationEventMethod; - - /** indicates whether or not Accelerometer Sensor is supported */ - private Boolean supported; - /** indicates whether or not Accelerometer Sensor is running */ - private boolean running = false; - - PApplet parent; - Context context; - - public AccelerometerManager(PApplet parent) { - this.parent = parent; - this.context = parent.getActivity(); - - try { - shakeEventMethod = - parent.getClass().getMethod("shakeEvent", new Class[] { Float.TYPE }); - } catch (Exception e) { - // no such method, or an error.. which is fine, just ignore - } - - try { - accelerationEventMethod = - parent.getClass().getMethod("accelerationEvent", new Class[] { Float.TYPE, Float.TYPE, Float.TYPE }); - } catch (Exception e) { - // no such method, or an error.. which is fine, just ignore - } -// System.out.println("shakeEventMethod is " + shakeEventMethod); -// System.out.println("accelerationEventMethod is " + accelerationEventMethod); - resume(); - } - - - public AccelerometerManager(PApplet parent, int threshold, int interval) { - this(parent); - this.threshold = threshold; - this.interval = interval; - } - - - public void resume() { - if (isSupported()) { - startListening(); - } - } - - - public void pause() { - if (isListening()) { - stopListening(); - } - } - - - /** - * Returns true if the manager is listening to orientation changes - */ - public boolean isListening() { - return running; - } - - - /** - * Unregisters listeners - */ - public void stopListening() { - running = false; - try { - if (sensorManager != null && sensorEventListener != null) { - sensorManager.unregisterListener(sensorEventListener); - } - } - catch (Exception e) { - } - } - - - /** - * Returns true if at least one Accelerometer sensor is available - */ - public boolean isSupported() { - if (supported == null) { - sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - List sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER); - supported = new Boolean(sensors.size() > 0); - } - return supported; - } - - -// /** -// * Configure the listener for shaking -// * @param threshold -// * minimum acceleration variation for considering shaking -// * @param interval -// * minimum interval between to shake events -// */ -// public static void configure(int threshold, int interval) { -// AccelerometerManager.threshold = threshold; -// AccelerometerManager.interval = interval; -// } - - - /** - * Registers a listener and start listening - * @param accelerometerListener callback for accelerometer events - */ - public void startListening() { -// AccelerometerListener accelerometerListener = (AccelerometerListener) context; - sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - List sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER); - if (sensors.size() > 0) { - sensor = sensors.get(0); - running = sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_GAME); -// listener = accelerometerListener; - } - } - - -// /** -// * Configures threshold and interval -// * And registers a listener and start listening -// * @param accelerometerListener -// * callback for accelerometer events -// * @param threshold -// * minimum acceleration variation for considering shaking -// * @param interval -// * minimum interval between to shake events -// */ -// public void startListening(int threshold, int interval) { -// configure(threshold, interval); -// startListening(); -// } - - - /** - * The listener that listen to events from the accelerometer listener - */ - //private static SensorEventListener sensorEventListener = new SensorEventListener() { - private SensorEventListener sensorEventListener = new SensorEventListener() { - private long now = 0; - private long timeDiff = 0; - private long lastUpdate = 0; - private long lastShake = 0; - - private float x = 0; - private float y = 0; - private float z = 0; - private float lastX = 0; - private float lastY = 0; - private float lastZ = 0; - private float force = 0; - - public void onAccuracyChanged(Sensor sensor, int accuracy) { - } - - public void onSensorChanged(SensorEvent event) { - // use the event timestamp as reference - // so the manager precision won't depends - // on the AccelerometerListener implementation - // processing time - now = event.timestamp; - - x = event.values[0]; - y = event.values[1]; - z = event.values[2]; - - // if not interesting in shake events - // just remove the whole if then else bloc - if (lastUpdate == 0) { - lastUpdate = now; - lastShake = now; - lastX = x; - lastY = y; - lastZ = z; - - } else { - timeDiff = now - lastUpdate; - if (timeDiff > 0) { - force = Math.abs(x + y + z - lastX - lastY - lastZ) - / timeDiff; - if (force > threshold) { - if (now - lastShake >= interval) { - // trigger shake event -// listener.onShake(force); - if (shakeEventMethod != null) { - try { - shakeEventMethod.invoke(parent, new Object[] { new Float(force) }); - } catch (Exception e) { - e.printStackTrace(); - shakeEventMethod = null; - } - } - } - lastShake = now; - } - lastX = x; - lastY = y; - lastZ = z; - lastUpdate = now; - } - } - // trigger change event -// listener.onAccelerationChanged(x, y, z); - if (accelerationEventMethod != null) { - try { - accelerationEventMethod.invoke(parent, new Object[] { x, y, z }); - } catch (Exception e) { - e.printStackTrace(); - accelerationEventMethod = null; - } - } - } - }; -} \ No newline at end of file diff --git a/mode/examples/Sensors/Compass/Compass.pde b/mode/examples/Sensors/Compass/Compass.pde deleted file mode 100644 index d227f8ef5..000000000 --- a/mode/examples/Sensors/Compass/Compass.pde +++ /dev/null @@ -1,39 +0,0 @@ -CompassManager compass; -float direction; - - -void setup() { - compass = new CompassManager(this); -} - - -void pause() { - if (compass != null) compass.pause(); -} - - -void resume() { - if (compass != null) compass.resume(); -} - - -void draw() { - background(255); - fill(192, 0, 0); - noStroke(); - - translate(width/2, height/2); - scale(2); - rotate(direction); - beginShape(); - vertex(0, -50); - vertex(-20, 60); - vertex(0, 50); - vertex(20, 60); - endShape(CLOSE); -} - - -void directionEvent(float newDirection) { - direction = newDirection; -} diff --git a/mode/examples/Sensors/Compass/CompassManager.java b/mode/examples/Sensors/Compass/CompassManager.java deleted file mode 100644 index f3cd99d71..000000000 --- a/mode/examples/Sensors/Compass/CompassManager.java +++ /dev/null @@ -1,141 +0,0 @@ -import processing.core.PApplet; - -import java.lang.reflect.*; -import java.util.List; - -import android.content.Context; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; - - -public class CompassManager { - private Sensor sensor; - private SensorManager sensorManager; - - Method compassEventMethod; - Method directionEventMethod; - - private Boolean supported; - private boolean running = false; - - PApplet parent; - Context context; - - public CompassManager(PApplet parent) { - this.parent = parent; - this.context = parent.getActivity(); - - try { - compassEventMethod = - parent.getClass().getMethod("compassEvent", new Class[] { Float.TYPE, Float.TYPE, Float.TYPE }); - } catch (Exception e) { - // no such method, or an error.. which is fine, just ignore - } - try { - directionEventMethod = - parent.getClass().getMethod("directionEvent", new Class[] { Float.TYPE }); - } catch (Exception e) { - // no such method, or an error.. which is fine, just ignore - } -// System.out.println("directionEventMethod is " + directionEventMethod); - - resume(); - } - - - public void resume() { - if (isSupported()) { - startListening(); - } - } - - - public void pause() { - if (isListening()) { - stopListening(); - } - } - - - /** - * Returns true if the manager is listening to orientation changes - */ - public boolean isListening() { - return running; - } - - - /** - * Unregisters listeners - */ - public void stopListening() { - running = false; - try { - if (sensorManager != null && sensorEventListener != null) { - sensorManager.unregisterListener(sensorEventListener); - } - } - catch (Exception e) { - } - } - - - /** - * Returns true if at least one Accelerometer sensor is available - */ - public boolean isSupported() { - if (supported == null) { - sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - List sensors = sensorManager.getSensorList(Sensor.TYPE_ORIENTATION); - supported = new Boolean(sensors.size() > 0); - } - return supported; - } - - - public void startListening() { - sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - List sensors = sensorManager.getSensorList(Sensor.TYPE_ORIENTATION); - if (sensors.size() > 0) { - sensor = sensors.get(0); - running = sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_GAME); - } - } - - - /** - * The listener that listen to events from the accelerometer listener - */ - private SensorEventListener sensorEventListener = new SensorEventListener() { - - public void onAccuracyChanged(Sensor sensor, int accuracy) { - // ignored for now - } - - public void onSensorChanged(SensorEvent event) { - float x = event.values[0]; - float y = event.values[1]; - float z = event.values[2]; - - if (compassEventMethod != null) { - try { - compassEventMethod.invoke(parent, new Object[] { x, y, z }); - } catch (Exception e) { - e.printStackTrace(); - compassEventMethod = null; - } - } - - if (directionEventMethod != null) { - try { - directionEventMethod.invoke(parent, new Object[] { (float) (-x * Math.PI / 180) }); - } catch (Exception e) { - e.printStackTrace(); - directionEventMethod = null; - } - } - } - }; -} \ No newline at end of file diff --git a/mode/examples/Topics/Advanced Data/ArrayListClass/ArrayListClass.pde b/mode/examples/Topics/Advanced Data/ArrayListClass/ArrayListClass.pde deleted file mode 100644 index 09521cb17..000000000 --- a/mode/examples/Topics/Advanced Data/ArrayListClass/ArrayListClass.pde +++ /dev/null @@ -1,52 +0,0 @@ -/** - * ArrayList of objects - * by Daniel Shiffman. - * - * This example demonstrates how to use a Java ArrayList to store - * a variable number of objects. Items can be added and removed - * from the ArrayList. - * - * Click the mouse to add bouncing balls. - */ - -ArrayList balls; -int ballWidth = 48; - -void setup() { - size(200, 200); - smooth(); - noStroke(); - - // Create an empty ArrayList - balls = new ArrayList(); - - // Start by adding one element - balls.add(new Ball(width/2, 0, ballWidth)); -} - -void draw() { - background(255); - - // With an array, we say balls.length, with an ArrayList, we say balls.size() - // The length of an ArrayList is dynamic - // Notice how we are looping through the ArrayList backwards - // This is because we are deleting elements from the list - for (int i = balls.size()-1; i >= 0; i--) { - // An ArrayList doesn't know what it is storing so we have to cast the object coming out - Ball ball = (Ball) balls.get(i); - ball.move(); - ball.display(); - if (ball.finished()) { - // Items can be deleted with remove() - balls.remove(i); - } - - } - -} - -void mousePressed() { - // A new ball object is added to the ArrayList (by default to the end) - balls.add(new Ball(mouseX, mouseY, ballWidth)); -} - diff --git a/mode/examples/Topics/Advanced Data/ArrayListClass/Ball.pde b/mode/examples/Topics/Advanced Data/ArrayListClass/Ball.pde deleted file mode 100644 index 3f613b787..000000000 --- a/mode/examples/Topics/Advanced Data/ArrayListClass/Ball.pde +++ /dev/null @@ -1,50 +0,0 @@ -// Simple bouncing ball class - -class Ball { - - float x; - float y; - float speed; - float gravity; - float w; - float life = 255; - - Ball(float tempX, float tempY, float tempW) { - x = tempX; - y = tempY; - w = tempW; - speed = 0; - gravity = 0.1; - } - - void move() { - // Add gravity to speed - speed = speed + gravity; - // Add speed to y location - y = y + speed; - // If square reaches the bottom - // Reverse speed - if (y > height) { - // Dampening - speed = speed * -0.8; - y = height; - } - } - - boolean finished() { - // Balls fade out - life--; - if (life < 0) { - return true; - } else { - return false; - } - } - - void display() { - // Display the circle - fill(0,life); - //stroke(0,life); - ellipse(x,y,w,w); - } -} diff --git a/mode/examples/Topics/Advanced Data/DirectoryList/DirectoryList.pde b/mode/examples/Topics/Advanced Data/DirectoryList/DirectoryList.pde deleted file mode 100644 index bb8c364d2..000000000 --- a/mode/examples/Topics/Advanced Data/DirectoryList/DirectoryList.pde +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Listing files in directories and subdirectories - * by Daniel Shiffman. - * - * This example has three functions:
    - * 1) List the names of files in a directory
    - * 2) List the names along with metadata (size, lastModified)
    - * of files in a directory
    - * 3) List the names along with metadata (size, lastModified)
    - * of files in a directory and all subdirectories (using recursion) - */ - - -void setup() { - - // Path - String path = sketchPath; - - println("Listing all filenames in a directory: "); - String[] filenames = listFileNames(path); - println(filenames); - - println("\nListing info about all files in a directory: "); - File[] files = listFiles(path); - for (int i = 0; i < files.length; i++) { - File f = files[i]; - println("Name: " + f.getName()); - println("Is directory: " + f.isDirectory()); - println("Size: " + f.length()); - String lastModified = new Date(f.lastModified()).toString(); - println("Last Modified: " + lastModified); - println("-----------------------"); - } - - println("\nListing info about all files in a directory and all subdirectories: "); - ArrayList allFiles = listFilesRecursive(path); - - for (int i = 0; i < allFiles.size(); i++) { - File f = (File) allFiles.get(i); - println("Name: " + f.getName()); - println("Full path: " + f.getAbsolutePath()); - println("Is directory: " + f.isDirectory()); - println("Size: " + f.length()); - String lastModified = new Date(f.lastModified()).toString(); - println("Last Modified: " + lastModified); - println("-----------------------"); - } - - noLoop(); -} - -// Nothing is drawn in this program and the draw() doesn't loop because -// of the noLoop() in setup() -void draw() { - -} - - -// This function returns all the files in a directory as an array of Strings -String[] listFileNames(String dir) { - File file = new File(dir); - if (file.isDirectory()) { - String names[] = file.list(); - return names; - } else { - // If it's not a directory - return null; - } -} - -// This function returns all the files in a directory as an array of File objects -// This is useful if you want more info about the file -File[] listFiles(String dir) { - File file = new File(dir); - if (file.isDirectory()) { - File[] files = file.listFiles(); - return files; - } else { - // If it's not a directory - return null; - } -} - -// Function to get a list ofall files in a directory and all subdirectories -ArrayList listFilesRecursive(String dir) { - ArrayList fileList = new ArrayList(); - recurseDir(fileList,dir); - return fileList; -} - -// Recursive function to traverse subdirectories -void recurseDir(ArrayList a, String dir) { - File file = new File(dir); - if (file.isDirectory()) { - // If you want to include directories in the list - a.add(file); - File[] subfiles = file.listFiles(); - for (int i = 0; i < subfiles.length; i++) { - // Call this function on all files in this directory - recurseDir(a,subfiles[i].getAbsolutePath()); - } - } else { - a.add(file); - } -} diff --git a/mode/examples/Topics/Advanced Data/HashMapClass/HashMapClass.pde b/mode/examples/Topics/Advanced Data/HashMapClass/HashMapClass.pde deleted file mode 100644 index b19c30c60..000000000 --- a/mode/examples/Topics/Advanced Data/HashMapClass/HashMapClass.pde +++ /dev/null @@ -1,89 +0,0 @@ -/** - * HashMap example - * by Daniel Shiffman. - * - * This example demonstrates how to use a HashMap to store - * a collection of objects referenced by a key. - * This is much like an array, only instead of accessing elements - * with a numeric index, we use a String. - * If you are familiar with associative arrays from other languages, - * this is the same idea. - * - * This example uses the HashMap to perform a simple concordance - * http://en.wikipedia.org/wiki/Concordance_(publishing) - */ - - -HashMap words; // HashMap object - -String[] tokens; // Array of all words from input file -int counter; - -PFont f; - -void setup() { - size(640, 360); - words = new HashMap(); - - // Load file and chop it up - String[] lines = loadStrings("dracula.txt"); - String allText = join(lines, " "); - tokens = splitTokens(allText, " ,.?!:;[]-"); - f = createFont("Georgia", 36, true); -} - -void draw() { - background(255); - fill(0); - - // Look at words one at a time - String s = tokens[counter]; - counter = (counter + 1) % tokens.length; - - // Is the word in the HashMap - if (words.containsKey(s)) { - // Get the word object and increase the count - // We access objects from a HashMap via its key, the String - Word w = (Word) words.get(s); - w.count(); - } else { - // Otherwise make a new word - Word w = new Word(s); - // And add to the HashMap - // put() takes two arguments, "key" and "value" - // The key for us is the String and the value is the Word object - words.put(s, w); - } - - // Make an iterator to look at all the things in the HashMap - Iterator i = words.values().iterator(); - - // x and y will be used to locate each word - float x = 0; - float y = height-10; - - while (i.hasNext()) { - // Look at each word - Word w = (Word) i.next(); - - // Only display words that appear 3 times - if (w.count > 3) { - // The size is the count - int fsize = constrain(w.count, 0, 100); - textFont(f, fsize); - text(w.word, x, y); - // Move along the x-axis - x += textWidth(w.word + " "); - } - - // If x gets to the end, move Y - if (x > width) { - x = 0; - y -= 100; - // If y gets to the end, we're done - if (y < 0) { - break; - } - } - } -} diff --git a/mode/examples/Topics/Advanced Data/HashMapClass/Word.pde b/mode/examples/Topics/Advanced Data/HashMapClass/Word.pde deleted file mode 100644 index cc8568491..000000000 --- a/mode/examples/Topics/Advanced Data/HashMapClass/Word.pde +++ /dev/null @@ -1,15 +0,0 @@ -class Word { - - int count; - String word; - - Word(String s) { - word = s; - count = 1; - } - - void count() { - count++; - } - -} diff --git a/mode/examples/Topics/Advanced Data/HashMapClass/data/dracula.txt b/mode/examples/Topics/Advanced Data/HashMapClass/data/dracula.txt deleted file mode 100644 index 7fb73f568..000000000 --- a/mode/examples/Topics/Advanced Data/HashMapClass/data/dracula.txt +++ /dev/null @@ -1,16624 +0,0 @@ -The Project Gutenberg EBook of Dracula, by Bram Stoker - -This eBook is for the use of anyone anywhere at no cost and with -almost no restrictions whatsoever. You may copy it, give it away or -re-use it under the terms of the Project Gutenberg License included -with this eBook or online at www.gutenberg.net - - -Title: Dracula - -Author: Bram Stoker - -Release Date: May 9, 2008 [EBook #345] - -Language: English - -Character set encoding: ASCII - -*** START OF THIS PROJECT GUTENBERG EBOOK DRACULA *** - - - - - - - - - - - - - - -DRACULA - -by - -Bram Stoker - - -1897 edition - - - - -TABLE OF CONTENTS - - -CHAPTER - - 1 Jonathan Harker's Journal - 2 Jonathan Harker's Journal - 3 Jonathan Harker's Journal - 4 Jonathan Harker's Journal - 5 Letter From Miss Mina Murray To Miss Lucy Westenra - 6 Mina Murray's Journal - 7 Cutting From "The Dailygraph", 8 August - 8 Mina Murray's Journal - 9 Letter, Mina Harker To Lucy Westenra - 10 Letter, Dr. Seward To Hon. Arthur Holmwood - 11 Lucy Westenra's Diary - 12 Dr. Seward's Diary - 13 Dr. Seward's Diary - 14 Mina Harker's Journal - 15 Dr. Seward's Diary - 16 Dr. Seward's Diary - 17 Dr. Seward's Diary - 18 Dr. Seward's Diary - 19 Jonathan Harker's Journal - 20 Jonathan Harker's Journal - 21 Dr. Seward's Diary - 22 Jonathan Harker's Journal - 23 Dr. Seward's Diary - 24 Dr. Seward's Phonograph Diary - 25 Dr. Seward's Diary - 26 Dr. Seward's Diary - 27 Mina Harker's Journal - - - - -CHAPTER 1 - - -Jonathan Harker's Journal - -3 May. Bistritz.--Left Munich at 8:35 P.M., on 1st May, arriving at -Vienna early next morning; should have arrived at 6:46, but train was -an hour late. Buda-Pesth seems a wonderful place, from the glimpse -which I got of it from the train and the little I could walk through -the streets. I feared to go very far from the station, as we had -arrived late and would start as near the correct time as possible. - -The impression I had was that we were leaving the West and entering the -East; the most western of splendid bridges over the Danube, which is -here of noble width and depth, took us among the traditions of Turkish -rule. - -We left in pretty good time, and came after nightfall to Klausenburgh. -Here I stopped for the night at the Hotel Royale. I had for dinner, -or rather supper, a chicken done up some way with red pepper, which -was very good but thirsty. (Mem. get recipe for Mina.) I asked the -waiter, and he said it was called "paprika hendl," and that, as it was -a national dish, I should be able to get it anywhere along the -Carpathians. - -I found my smattering of German very useful here, indeed, I don't know -how I should be able to get on without it. - -Having had some time at my disposal when in London, I had visited the -British Museum, and made search among the books and maps in the -library regarding Transylvania; it had struck me that some -foreknowledge of the country could hardly fail to have some importance -in dealing with a nobleman of that country. - - -I find that the district he named is in the extreme east of the -country, just on the borders of three states, Transylvania, Moldavia, -and Bukovina, in the midst of the Carpathian mountains; one of the -wildest and least known portions of Europe. - -I was not able to light on any map or work giving the exact locality -of the Castle Dracula, as there are no maps of this country as yet to -compare with our own Ordance Survey Maps; but I found that Bistritz, -the post town named by Count Dracula, is a fairly well-known place. I -shall enter here some of my notes, as they may refresh my memory when -I talk over my travels with Mina. - -In the population of Transylvania there are four distinct -nationalities: Saxons in the South, and mixed with them the Wallachs, -who are the descendants of the Dacians; Magyars in the West, and -Szekelys in the East and North. I am going among the latter, who -claim to be descended from Attila and the Huns. This may be so, for -when the Magyars conquered the country in the eleventh century they -found the Huns settled in it. - -I read that every known superstition in the world is gathered into the -horseshoe of the Carpathians, as if it were the centre of some sort of -imaginative whirlpool; if so my stay may be very interesting. (Mem., -I must ask the Count all about them.) - -I did not sleep well, though my bed was comfortable enough, for I had -all sorts of queer dreams. There was a dog howling all night under my -window, which may have had something to do with it; or it may have -been the paprika, for I had to drink up all the water in my carafe, -and was still thirsty. Towards morning I slept and was wakened by the -continuous knocking at my door, so I guess I must have been sleeping -soundly then. - -I had for breakfast more paprika, and a sort of porridge of maize -flour which they said was "mamaliga", and egg-plant stuffed with -forcemeat, a very excellent dish, which they call "impletata". (Mem., -get recipe for this also.) - -I had to hurry breakfast, for the train started a little before eight, -or rather it ought to have done so, for after rushing to the station -at 7:30 I had to sit in the carriage for more than an hour before we -began to move. - -It seems to me that the further east you go the more unpunctual are -the trains. What ought they to be in China? - -All day long we seemed to dawdle through a country which was full of -beauty of every kind. Sometimes we saw little towns or castles on the -top of steep hills such as we see in old missals; sometimes we ran by -rivers and streams which seemed from the wide stony margin on each -side of them to be subject to great floods. It takes a lot of water, -and running strong, to sweep the outside edge of a river clear. - -At every station there were groups of people, sometimes crowds, and in -all sorts of attire. Some of them were just like the peasants at home -or those I saw coming through France and Germany, with short jackets, -and round hats, and home-made trousers; but others were very -picturesque. - -The women looked pretty, except when you got near them, but they were -very clumsy about the waist. They had all full white sleeves of some -kind or other, and most of them had big belts with a lot of strips of -something fluttering from them like the dresses in a ballet, but of -course there were petticoats under them. - -The strangest figures we saw were the Slovaks, who were more barbarian -than the rest, with their big cow-boy hats, great baggy dirty-white -trousers, white linen shirts, and enormous heavy leather belts, nearly -a foot wide, all studded over with brass nails. They wore high boots, -with their trousers tucked into them, and had long black hair and -heavy black moustaches. They are very picturesque, but do not look -prepossessing. On the stage they would be set down at once as some -old Oriental band of brigands. They are, however, I am told, very -harmless and rather wanting in natural self-assertion. - -It was on the dark side of twilight when we got to Bistritz, which is -a very interesting old place. Being practically on the frontier--for -the Borgo Pass leads from it into Bukovina--it has had a very stormy -existence, and it certainly shows marks of it. Fifty years ago a -series of great fires took place, which made terrible havoc on five -separate occasions. At the very beginning of the seventeenth century -it underwent a siege of three weeks and lost 13,000 people, the -casualties of war proper being assisted by famine and disease. - -Count Dracula had directed me to go to the Golden Krone Hotel, which I -found, to my great delight, to be thoroughly old-fashioned, for of -course I wanted to see all I could of the ways of the country. - -I was evidently expected, for when I got near the door I faced a -cheery-looking elderly woman in the usual peasant dress--white -undergarment with a long double apron, front, and back, of coloured -stuff fitting almost too tight for modesty. When I came close she -bowed and said, "The Herr Englishman?" - -"Yes," I said, "Jonathan Harker." - -She smiled, and gave some message to an elderly man in white -shirtsleeves, who had followed her to the door. - -He went, but immediately returned with a letter: - -"My friend.--Welcome to the Carpathians. I am anxiously expecting -you. Sleep well tonight. At three tomorrow the diligence will -start for Bukovina; a place on it is kept for you. At the Borgo -Pass my carriage will await you and will bring you to me. I trust -that your journey from London has been a happy one, and that you -will enjoy your stay in my beautiful land.--Your friend, Dracula." - - -4 May--I found that my landlord had got a letter from the Count, -directing him to secure the best place on the coach for me; but on -making inquiries as to details he seemed somewhat reticent, and -pretended that he could not understand my German. - -This could not be true, because up to then he had understood it -perfectly; at least, he answered my questions exactly as if he did. - -He and his wife, the old lady who had received me, looked at each -other in a frightened sort of way. He mumbled out that the money had -been sent in a letter, and that was all he knew. When I asked him if -he knew Count Dracula, and could tell me anything of his castle, both -he and his wife crossed themselves, and, saying that they knew nothing -at all, simply refused to speak further. It was so near the time of -starting that I had no time to ask anyone else, for it was all very -mysterious and not by any means comforting. - -Just before I was leaving, the old lady came up to my room and said in -a hysterical way: "Must you go? Oh! Young Herr, must you go?" She -was in such an excited state that she seemed to have lost her grip of -what German she knew, and mixed it all up with some other language -which I did not know at all. I was just able to follow her by asking -many questions. When I told her that I must go at once, and that I -was engaged on important business, she asked again: - -"Do you know what day it is?" I answered that it was the fourth of -May. She shook her head as she said again: - -"Oh, yes! I know that! I know that, but do you know what day it is?" - -On my saying that I did not understand, she went on: - -"It is the eve of St. George's Day. Do you not know that tonight, -when the clock strikes midnight, all the evil things in the world will -have full sway? Do you know where you are going, and what you are -going to?" She was in such evident distress that I tried to comfort -her, but without effect. Finally, she went down on her knees and -implored me not to go; at least to wait a day or two before starting. - -It was all very ridiculous but I did not feel comfortable. However, -there was business to be done, and I could allow nothing to interfere -with it. - -I tried to raise her up, and said, as gravely as I could, that I -thanked her, but my duty was imperative, and that I must go. - -She then rose and dried her eyes, and taking a crucifix from her neck -offered it to me. - -I did not know what to do, for, as an English Churchman, I have been -taught to regard such things as in some measure idolatrous, and yet it -seemed so ungracious to refuse an old lady meaning so well and in such -a state of mind. - -She saw, I suppose, the doubt in my face, for she put the rosary round -my neck and said, "For your mother's sake," and went out of the room. - -I am writing up this part of the diary whilst I am waiting for the -coach, which is, of course, late; and the crucifix is still round my -neck. - -Whether it is the old lady's fear, or the many ghostly traditions of -this place, or the crucifix itself, I do not know, but I am not -feeling nearly as easy in my mind as usual. - -If this book should ever reach Mina before I do, let it bring my -goodbye. Here comes the coach! - - -5 May. The Castle.--The gray of the morning has passed, and the sun -is high over the distant horizon, which seems jagged, whether with -trees or hills I know not, for it is so far off that big things and -little are mixed. - -I am not sleepy, and, as I am not to be called till I awake, naturally -I write till sleep comes. - -There are many odd things to put down, and, lest who reads them may -fancy that I dined too well before I left Bistritz, let me put down my -dinner exactly. - -I dined on what they called "robber steak"--bits of bacon, onion, and -beef, seasoned with red pepper, and strung on sticks, and roasted over -the fire, in simple style of the London cat's meat! - -The wine was Golden Mediasch, which produces a queer sting on the -tongue, which is, however, not disagreeable. - -I had only a couple of glasses of this, and nothing else. - -When I got on the coach, the driver had not taken his seat, and I saw -him talking to the landlady. - -They were evidently talking of me, for every now and then they looked -at me, and some of the people who were sitting on the bench outside -the door--came and listened, and then looked at me, most of them -pityingly. I could hear a lot of words often repeated, queer words, -for there were many nationalities in the crowd, so I quietly got my -polyglot dictionary from my bag and looked them out. - -I must say they were not cheering to me, for amongst them were -"Ordog"--Satan, "Pokol"--hell, "stregoica"--witch, "vrolok" and -"vlkoslak"--both mean the same thing, one being Slovak and the other -Servian for something that is either werewolf or vampire. (Mem., I -must ask the Count about these superstitions.) - -When we started, the crowd round the inn door, which had by this time -swelled to a considerable size, all made the sign of the cross and -pointed two fingers towards me. - -With some difficulty, I got a fellow passenger to tell me what they -meant. He would not answer at first, but on learning that I was -English, he explained that it was a charm or guard against the evil -eye. - -This was not very pleasant for me, just starting for an unknown place -to meet an unknown man. But everyone seemed so kind-hearted, and so -sorrowful, and so sympathetic that I could not but be touched. - -I shall never forget the last glimpse which I had of the inn yard and -its crowd of picturesque figures, all crossing themselves, as they -stood round the wide archway, with its background of rich foliage of -oleander and orange trees in green tubs clustered in the centre of the -yard. - -Then our driver, whose wide linen drawers covered the whole front of -the boxseat,--"gotza" they call them--cracked his big whip over his -four small horses, which ran abreast, and we set off on our journey. - -I soon lost sight and recollection of ghostly fears in the beauty of -the scene as we drove along, although had I known the language, or -rather languages, which my fellow-passengers were speaking, I might -not have been able to throw them off so easily. Before us lay a green -sloping land full of forests and woods, with here and there steep -hills, crowned with clumps of trees or with farmhouses, the blank -gable end to the road. There was everywhere a bewildering mass of -fruit blossom--apple, plum, pear, cherry. And as we drove by I could -see the green grass under the trees spangled with the fallen petals. -In and out amongst these green hills of what they call here the -"Mittel Land" ran the road, losing itself as it swept round the grassy -curve, or was shut out by the straggling ends of pine woods, which -here and there ran down the hillsides like tongues of flame. The road -was rugged, but still we seemed to fly over it with a feverish haste. -I could not understand then what the haste meant, but the driver was -evidently bent on losing no time in reaching Borgo Prund. I was told -that this road is in summertime excellent, but that it had not yet -been put in order after the winter snows. In this respect it is -different from the general run of roads in the Carpathians, for it is -an old tradition that they are not to be kept in too good order. Of -old the Hospadars would not repair them, lest the Turk should think -that they were preparing to bring in foreign troops, and so hasten the -war which was always really at loading point. - -Beyond the green swelling hills of the Mittel Land rose mighty slopes -of forest up to the lofty steeps of the Carpathians themselves. Right -and left of us they towered, with the afternoon sun falling full upon -them and bringing out all the glorious colours of this beautiful -range, deep blue and purple in the shadows of the peaks, green and -brown where grass and rock mingled, and an endless perspective of -jagged rock and pointed crags, till these were themselves lost in the -distance, where the snowy peaks rose grandly. Here and there seemed -mighty rifts in the mountains, through which, as the sun began to -sink, we saw now and again the white gleam of falling water. One of -my companions touched my arm as we swept round the base of a hill and -opened up the lofty, snow-covered peak of a mountain, which seemed, as -we wound on our serpentine way, to be right before us. - -"Look! Isten szek!"--"God's seat!"--and he crossed himself reverently. - -As we wound on our endless way, and the sun sank lower and lower -behind us, the shadows of the evening began to creep round us. This -was emphasized by the fact that the snowy mountain-top still held the -sunset, and seemed to glow out with a delicate cool pink. Here and -there we passed Cszeks and slovaks, all in picturesque attire, but I -noticed that goitre was painfully prevalent. By the roadside were -many crosses, and as we swept by, my companions all crossed -themselves. Here and there was a peasant man or woman kneeling before -a shrine, who did not even turn round as we approached, but seemed in -the self-surrender of devotion to have neither eyes nor ears for the -outer world. There were many things new to me. For instance, -hay-ricks in the trees, and here and there very beautiful masses of -weeping birch, their white stems shining like silver through the -delicate green of the leaves. - -Now and again we passed a leiter-wagon--the ordinary peasants's -cart--with its long, snakelike vertebra, calculated to suit the -inequalities of the road. On this were sure to be seated quite a -group of homecoming peasants, the Cszeks with their white, and the -Slovaks with their coloured sheepskins, the latter carrying -lance-fashion their long staves, with axe at end. As the evening fell -it began to get very cold, and the growing twilight seemed to merge -into one dark mistiness the gloom of the trees, oak, beech, and pine, -though in the valleys which ran deep between the spurs of the hills, -as we ascended through the Pass, the dark firs stood out here and -there against the background of late-lying snow. Sometimes, as the -road was cut through the pine woods that seemed in the darkness to be -closing down upon us, great masses of greyness which here and there -bestrewed the trees, produced a peculiarly weird and solemn effect, -which carried on the thoughts and grim fancies engendered earlier in -the evening, when the falling sunset threw into strange relief the -ghost-like clouds which amongst the Carpathians seem to wind -ceaselessly through the valleys. Sometimes the hills were so steep -that, despite our driver's haste, the horses could only go slowly. I -wished to get down and walk up them, as we do at home, but the driver -would not hear of it. "No, no," he said. "You must not walk here. -The dogs are too fierce." And then he added, with what he evidently -meant for grim pleasantry--for he looked round to catch the approving -smile of the rest--"And you may have enough of such matters before you -go to sleep." The only stop he would make was a moment's pause to -light his lamps. - -When it grew dark there seemed to be some excitement amongst the -passengers, and they kept speaking to him, one after the other, as -though urging him to further speed. He lashed the horses unmercifully -with his long whip, and with wild cries of encouragement urged them on -to further exertions. Then through the darkness I could see a sort of -patch of grey light ahead of us, as though there were a cleft in the -hills. The excitement of the passengers grew greater. The crazy -coach rocked on its great leather springs, and swayed like a boat -tossed on a stormy sea. I had to hold on. The road grew more level, -and we appeared to fly along. Then the mountains seemed to come -nearer to us on each side and to frown down upon us. We were entering -on the Borgo Pass. One by one several of the passengers offered me -gifts, which they pressed upon me with an earnestness which would take -no denial. These were certainly of an odd and varied kind, but each -was given in simple good faith, with a kindly word, and a blessing, -and that same strange mixture of fear-meaning movements which I had -seen outside the hotel at Bistritz--the sign of the cross and the -guard against the evil eye. Then, as we flew along, the driver leaned -forward, and on each side the passengers, craning over the edge of the -coach, peered eagerly into the darkness. It was evident that -something very exciting was either happening or expected, but though I -asked each passenger, no one would give me the slightest explanation. -This state of excitement kept on for some little time. And at last we -saw before us the Pass opening out on the eastern side. There were -dark, rolling clouds overhead, and in the air the heavy, oppressive -sense of thunder. It seemed as though the mountain range had -separated two atmospheres, and that now we had got into the thunderous -one. I was now myself looking out for the conveyance which was to -take me to the Count. Each moment I expected to see the glare of -lamps through the blackness, but all was dark. The only light was the -flickering rays of our own lamps, in which the steam from our -hard-driven horses rose in a white cloud. We could see now the sandy -road lying white before us, but there was on it no sign of a vehicle. -The passengers drew back with a sigh of gladness, which seemed to mock -my own disappointment. I was already thinking what I had best do, -when the driver, looking at his watch, said to the others something -which I could hardly hear, it was spoken so quietly and in so low a -tone, I thought it was "An hour less than the time." Then turning to -me, he spoke in German worse than my own. - -"There is no carriage here. The Herr is not expected after all. He -will now come on to Bukovina, and return tomorrow or the next day, -better the next day." Whilst he was speaking the horses began to -neigh and snort and plunge wildly, so that the driver had to hold them -up. Then, amongst a chorus of screams from the peasants and a -universal crossing of themselves, a caleche, with four horses, drove -up behind us, overtook us, and drew up beside the coach. I could see -from the flash of our lamps as the rays fell on them, that the horses -were coal-black and splendid animals. They were driven by a tall man, -with a long brown beard and a great black hat, which seemed to hide -his face from us. I could only see the gleam of a pair of very bright -eyes, which seemed red in the lamplight, as he turned to us. - -He said to the driver, "You are early tonight, my friend." - -The man stammered in reply, "The English Herr was in a hurry." - -To which the stranger replied, "That is why, I suppose, you wished him -to go on to Bukovina. You cannot deceive me, my friend. I know too -much, and my horses are swift." - -As he spoke he smiled, and the lamplight fell on a hard-looking mouth, -with very red lips and sharp-looking teeth, as white as ivory. One of -my companions whispered to another the line from Burger's "Lenore". - -"Denn die Todten reiten Schnell." ("For the dead travel fast.") - -The strange driver evidently heard the words, for he looked up with a -gleaming smile. The passenger turned his face away, at the same time -putting out his two fingers and crossing himself. "Give me the Herr's -luggage," said the driver, and with exceeding alacrity my bags were -handed out and put in the caleche. Then I descended from the side of -the coach, as the caleche was close alongside, the driver helping me -with a hand which caught my arm in a grip of steel. His strength must -have been prodigious. - -Without a word he shook his reins, the horses turned, and we swept -into the darkness of the pass. As I looked back I saw the steam from -the horses of the coach by the light of the lamps, and projected -against it the figures of my late companions crossing themselves. -Then the driver cracked his whip and called to his horses, and off -they swept on their way to Bukovina. As they sank into the darkness I -felt a strange chill, and a lonely feeling come over me. But a cloak -was thrown over my shoulders, and a rug across my knees, and the -driver said in excellent German--"The night is chill, mein Herr, and -my master the Count bade me take all care of you. There is a flask of -slivovitz (the plum brandy of the country) underneath the seat, if you -should require it." - -I did not take any, but it was a comfort to know it was there all the -same. I felt a little strangely, and not a little frightened. I -think had there been any alternative I should have taken it, instead -of prosecuting that unknown night journey. The carriage went at a -hard pace straight along, then we made a complete turn and went along -another straight road. It seemed to me that we were simply going over -and over the same ground again, and so I took note of some salient -point, and found that this was so. I would have liked to have asked -the driver what this all meant, but I really feared to do so, for I -thought that, placed as I was, any protest would have had no effect in -case there had been an intention to delay. - -By-and-by, however, as I was curious to know how time was passing, I -struck a match, and by its flame looked at my watch. It was within a -few minutes of midnight. This gave me a sort of shock, for I suppose -the general superstition about midnight was increased by my recent -experiences. I waited with a sick feeling of suspense. - -Then a dog began to howl somewhere in a farmhouse far down the road, a -long, agonized wailing, as if from fear. The sound was taken up by -another dog, and then another and another, till, borne on the wind -which now sighed softly through the Pass, a wild howling began, which -seemed to come from all over the country, as far as the imagination -could grasp it through the gloom of the night. - -At the first howl the horses began to strain and rear, but the driver -spoke to them soothingly, and they quieted down, but shivered and -sweated as though after a runaway from sudden fright. Then, far off -in the distance, from the mountains on each side of us began a louder -and a sharper howling, that of wolves, which affected both the horses -and myself in the same way. For I was minded to jump from the caleche -and run, whilst they reared again and plunged madly, so that the -driver had to use all his great strength to keep them from bolting. -In a few minutes, however, my own ears got accustomed to the sound, -and the horses so far became quiet that the driver was able to descend -and to stand before them. - -He petted and soothed them, and whispered something in their ears, as -I have heard of horse-tamers doing, and with extraordinary effect, for -under his caresses they became quite manageable again, though they -still trembled. The driver again took his seat, and shaking his -reins, started off at a great pace. This time, after going to the far -side of the Pass, he suddenly turned down a narrow roadway which ran -sharply to the right. - -Soon we were hemmed in with trees, which in places arched right over -the roadway till we passed as through a tunnel. And again great -frowning rocks guarded us boldly on either side. Though we were in -shelter, we could hear the rising wind, for it moaned and whistled -through the rocks, and the branches of the trees crashed together as -we swept along. It grew colder and colder still, and fine, powdery -snow began to fall, so that soon we and all around us were covered -with a white blanket. The keen wind still carried the howling of the -dogs, though this grew fainter as we went on our way. The baying of -the wolves sounded nearer and nearer, as though they were closing -round on us from every side. I grew dreadfully afraid, and the horses -shared my fear. The driver, however, was not in the least disturbed. -He kept turning his head to left and right, but I could not see -anything through the darkness. - -Suddenly, away on our left I saw a faint flickering blue flame. The -driver saw it at the same moment. He at once checked the horses, and, -jumping to the ground, disappeared into the darkness. I did not know -what to do, the less as the howling of the wolves grew closer. But -while I wondered, the driver suddenly appeared again, and without a -word took his seat, and we resumed our journey. I think I must have -fallen asleep and kept dreaming of the incident, for it seemed to be -repeated endlessly, and now looking back, it is like a sort of awful -nightmare. Once the flame appeared so near the road, that even in the -darkness around us I could watch the driver's motions. He went -rapidly to where the blue flame arose, it must have been very faint, -for it did not seem to illumine the place around it at all, and -gathering a few stones, formed them into some device. - -Once there appeared a strange optical effect. When he stood between -me and the flame he did not obstruct it, for I could see its ghostly -flicker all the same. This startled me, but as the effect was only -momentary, I took it that my eyes deceived me straining through the -darkness. Then for a time there were no blue flames, and we sped -onwards through the gloom, with the howling of the wolves around us, -as though they were following in a moving circle. - -At last there came a time when the driver went further afield than he -had yet gone, and during his absence, the horses began to tremble -worse than ever and to snort and scream with fright. I could not see -any cause for it, for the howling of the wolves had ceased altogether. -But just then the moon, sailing through the black clouds, appeared -behind the jagged crest of a beetling, pine-clad rock, and by its -light I saw around us a ring of wolves, with white teeth and lolling -red tongues, with long, sinewy limbs and shaggy hair. They were a -hundred times more terrible in the grim silence which held them than -even when they howled. For myself, I felt a sort of paralysis of -fear. It is only when a man feels himself face to face with such -horrors that he can understand their true import. - -All at once the wolves began to howl as though the moonlight had had -some peculiar effect on them. The horses jumped about and reared, and -looked helplessly round with eyes that rolled in a way painful to -see. But the living ring of terror encompassed them on every side, -and they had perforce to remain within it. I called to the coachman -to come, for it seemed to me that our only chance was to try to break -out through the ring and to aid his approach, I shouted and beat the -side of the caleche, hoping by the noise to scare the wolves from the -side, so as to give him a chance of reaching the trap. How he came -there, I know not, but I heard his voice raised in a tone of imperious -command, and looking towards the sound, saw him stand in the roadway. -As he swept his long arms, as though brushing aside some impalpable -obstacle, the wolves fell back and back further still. Just then a -heavy cloud passed across the face of the moon, so that we were again -in darkness. - -When I could see again the driver was climbing into the caleche, and -the wolves disappeared. This was all so strange and uncanny that a -dreadful fear came upon me, and I was afraid to speak or move. The -time seemed interminable as we swept on our way, now in almost -complete darkness, for the rolling clouds obscured the moon. - -We kept on ascending, with occasional periods of quick descent, but in -the main always ascending. Suddenly, I became conscious of the fact -that the driver was in the act of pulling up the horses in the -courtyard of a vast ruined castle, from whose tall black windows came -no ray of light, and whose broken battlements showed a jagged line -against the sky. - - - - -CHAPTER 2 - - -Jonathan Harker's Journal Continued - -5 May.--I must have been asleep, for certainly if I had been fully -awake I must have noticed the approach of such a remarkable place. In -the gloom the courtyard looked of considerable size, and as several -dark ways led from it under great round arches, it perhaps seemed -bigger than it really is. I have not yet been able to see it by -daylight. - -When the caleche stopped, the driver jumped down and held out his hand -to assist me to alight. Again I could not but notice his prodigious -strength. His hand actually seemed like a steel vice that could have -crushed mine if he had chosen. Then he took my traps, and placed them -on the ground beside me as I stood close to a great door, old and -studded with large iron nails, and set in a projecting doorway of -massive stone. I could see even in the dim light that the stone was -massively carved, but that the carving had been much worn by time and -weather. As I stood, the driver jumped again into his seat and shook -the reins. The horses started forward, and trap and all disappeared -down one of the dark openings. - -I stood in silence where I was, for I did not know what to do. Of -bell or knocker there was no sign. Through these frowning walls and -dark window openings it was not likely that my voice could penetrate. -The time I waited seemed endless, and I felt doubts and fears crowding -upon me. What sort of place had I come to, and among what kind of -people? What sort of grim adventure was it on which I had embarked? -Was this a customary incident in the life of a solicitor's clerk sent -out to explain the purchase of a London estate to a foreigner? -Solicitor's clerk! Mina would not like that. Solicitor, for just -before leaving London I got word that my examination was successful, -and I am now a full-blown solicitor! I began to rub my eyes and pinch -myself to see if I were awake. It all seemed like a horrible -nightmare to me, and I expected that I should suddenly awake, and find -myself at home, with the dawn struggling in through the windows, as I -had now and again felt in the morning after a day of overwork. But my -flesh answered the pinching test, and my eyes were not to be -deceived. I was indeed awake and among the Carpathians. All I could -do now was to be patient, and to wait the coming of morning. - -Just as I had come to this conclusion I heard a heavy step approaching -behind the great door, and saw through the chinks the gleam of a -coming light. Then there was the sound of rattling chains and the -clanking of massive bolts drawn back. A key was turned with the loud -grating noise of long disuse, and the great door swung back. - -Within, stood a tall old man, clean shaven save for a long white -moustache, and clad in black from head to foot, without a single speck -of colour about him anywhere. He held in his hand an antique silver -lamp, in which the flame burned without a chimney or globe of any -kind, throwing long quivering shadows as it flickered in the draught -of the open door. The old man motioned me in with his right hand with -a courtly gesture, saying in excellent English, but with a strange -intonation. - -"Welcome to my house! Enter freely and of your own free will!" He -made no motion of stepping to meet me, but stood like a statue, as -though his gesture of welcome had fixed him into stone. The instant, -however, that I had stepped over the threshold, he moved impulsively -forward, and holding out his hand grasped mine with a strength which -made me wince, an effect which was not lessened by the fact that it -seemed cold as ice, more like the hand of a dead than a living man. -Again he said, - -"Welcome to my house! Enter freely. Go safely, and leave something -of the happiness you bring!" The strength of the handshake was so -much akin to that which I had noticed in the driver, whose face I had -not seen, that for a moment I doubted if it were not the same person -to whom I was speaking. So to make sure, I said interrogatively, -"Count Dracula?" - -He bowed in a courtly way as he replied, "I am Dracula, and I bid you -welcome, Mr. Harker, to my house. Come in, the night air is chill, -and you must need to eat and rest." As he was speaking, he put the lamp -on a bracket on the wall, and stepping out, took my luggage. He had -carried it in before I could forestall him. I protested, but he -insisted. - -"Nay, sir, you are my guest. It is late, and my people are not -available. Let me see to your comfort myself." He insisted on carrying -my traps along the passage, and then up a great winding stair, and -along another great passage, on whose stone floor our steps rang -heavily. At the end of this he threw open a heavy door, and I -rejoiced to see within a well-lit room in which a table was spread for -supper, and on whose mighty hearth a great fire of logs, freshly -replenished, flamed and flared. - -The Count halted, putting down my bags, closed the door, and crossing -the room, opened another door, which led into a small octagonal room -lit by a single lamp, and seemingly without a window of any sort. -Passing through this, he opened another door, and motioned me to -enter. It was a welcome sight. For here was a great bedroom well -lighted and warmed with another log fire, also added to but lately, -for the top logs were fresh, which sent a hollow roar up the wide -chimney. The Count himself left my luggage inside and withdrew, -saying, before he closed the door. - -"You will need, after your journey, to refresh yourself by making your -toilet. I trust you will find all you wish. When you are ready, come -into the other room, where you will find your supper prepared." - -The light and warmth and the Count's courteous welcome seemed to have -dissipated all my doubts and fears. Having then reached my normal -state, I discovered that I was half famished with hunger. So making a -hasty toilet, I went into the other room. - -I found supper already laid out. My host, who stood on one side of -the great fireplace, leaning against the stonework, made a graceful -wave of his hand to the table, and said, - -"I pray you, be seated and sup how you please. You will I trust, -excuse me that I do not join you, but I have dined already, and I do -not sup." - -I handed to him the sealed letter which Mr. Hawkins had entrusted to -me. He opened it and read it gravely. Then, with a charming smile, -he handed it to me to read. One passage of it, at least, gave me a -thrill of pleasure. - -"I must regret that an attack of gout, from which malady I am a -constant sufferer, forbids absolutely any travelling on my part for -some time to come. But I am happy to say I can send a sufficient -substitute, one in whom I have every possible confidence. He is a -young man, full of energy and talent in his own way, and of a very -faithful disposition. He is discreet and silent, and has grown into -manhood in my service. He shall be ready to attend on you when you -will during his stay, and shall take your instructions in all -matters." - -The count himself came forward and took off the cover of a dish, and I -fell to at once on an excellent roast chicken. This, with some cheese -and a salad and a bottle of old tokay, of which I had two glasses, was -my supper. During the time I was eating it the Count asked me many -questions as to my journey, and I told him by degrees all I had -experienced. - -By this time I had finished my supper, and by my host's desire had -drawn up a chair by the fire and begun to smoke a cigar which he -offered me, at the same time excusing himself that he did not smoke. -I had now an opportunity of observing him, and found him of a very -marked physiognomy. - -His face was a strong, a very strong, aquiline, with high bridge of -the thin nose and peculiarly arched nostrils, with lofty domed -forehead, and hair growing scantily round the temples but profusely -elsewhere. His eyebrows were very massive, almost meeting over the -nose, and with bushy hair that seemed to curl in its own profusion. -The mouth, so far as I could see it under the heavy moustache, was -fixed and rather cruel-looking, with peculiarly sharp white teeth. -These protruded over the lips, whose remarkable ruddiness showed -astonishing vitality in a man of his years. For the rest, his ears -were pale, and at the tops extremely pointed. The chin was broad and -strong, and the cheeks firm though thin. The general effect was one -of extraordinary pallor. - -Hitherto I had noticed the backs of his hands as they lay on his knees -in the firelight, and they had seemed rather white and fine. But -seeing them now close to me, I could not but notice that they were -rather coarse, broad, with squat fingers. Strange to say, there were -hairs in the centre of the palm. The nails were long and fine, and -cut to a sharp point. As the Count leaned over me and his hands -touched me, I could not repress a shudder. It may have been that his -breath was rank, but a horrible feeling of nausea came over me, which, -do what I would, I could not conceal. - -The Count, evidently noticing it, drew back. And with a grim sort of -smile, which showed more than he had yet done his protruberant teeth, -sat himself down again on his own side of the fireplace. We were both -silent for a while, and as I looked towards the window I saw the first -dim streak of the coming dawn. There seemed a strange stillness over -everything. But as I listened, I heard as if from down below in the -valley the howling of many wolves. The Count's eyes gleamed, and he -said. - -"Listen to them, the children of the night. What music they make!" -Seeing, I suppose, some expression in my face strange to him, he -added, "Ah, sir, you dwellers in the city cannot enter into the -feelings of the hunter." Then he rose and said. - -"But you must be tired. Your bedroom is all ready, and tomorrow you -shall sleep as late as you will. I have to be away till the -afternoon, so sleep well and dream well!" With a courteous bow, he -opened for me himself the door to the octagonal room, and I entered my -bedroom. - -I am all in a sea of wonders. I doubt. I fear. I think strange -things, which I dare not confess to my own soul. God keep me, if only -for the sake of those dear to me! - - -7 May.--It is again early morning, but I have rested and enjoyed the -last twenty-four hours. I slept till late in the day, and awoke of my -own accord. When I had dressed myself I went into the room where we -had supped, and found a cold breakfast laid out, with coffee kept hot -by the pot being placed on the hearth. There was a card on the table, -on which was written--"I have to be absent for a while. Do not wait -for me. D." I set to and enjoyed a hearty meal. When I had done, I -looked for a bell, so that I might let the servants know I had -finished, but I could not find one. There are certainly odd -deficiencies in the house, considering the extraordinary evidences of -wealth which are round me. The table service is of gold, and so -beautifully wrought that it must be of immense value. The curtains -and upholstery of the chairs and sofas and the hangings of my bed are -of the costliest and most beautiful fabrics, and must have been of -fabulous value when they were made, for they are centuries old, though -in excellent order. I saw something like them in Hampton Court, but -they were worn and frayed and moth-eaten. But still in none of the -rooms is there a mirror. There is not even a toilet glass on my -table, and I had to get the little shaving glass from my bag before I -could either shave or brush my hair. I have not yet seen a servant -anywhere, or heard a sound near the castle except the howling of -wolves. Some time after I had finished my meal, I do not know whether -to call it breakfast or dinner, for it was between five and six -o'clock when I had it, I looked about for something to read, for I did -not like to go about the castle until I had asked the Count's -permission. There was absolutely nothing in the room, book, -newspaper, or even writing materials, so I opened another door in the -room and found a sort of library. The door opposite mine I tried, but -found locked. - -In the library I found, to my great delight, a vast number of English -books, whole shelves full of them, and bound volumes of magazines and -newspapers. A table in the centre was littered with English magazines -and newspapers, though none of them were of very recent date. The -books were of the most varied kind, history, geography, politics, -political economy, botany, geology, law, all relating to England and -English life and customs and manners. There were even such books of -reference as the London Directory, the "Red" and "Blue" books, -Whitaker's Almanac, the Army and Navy Lists, and it somehow gladdened -my heart to see it, the Law List. - -Whilst I was looking at the books, the door opened, and the Count -entered. He saluted me in a hearty way, and hoped that I had had a -good night's rest. Then he went on. - -"I am glad you found your way in here, for I am sure there is much -that will interest you. These companions," and he laid his hand on -some of the books, "have been good friends to me, and for some years -past, ever since I had the idea of going to London, have given me -many, many hours of pleasure. Through them I have come to know your -great England, and to know her is to love her. I long to go through -the crowded streets of your mighty London, to be in the midst of the -whirl and rush of humanity, to share its life, its change, its death, -and all that makes it what it is. But alas! As yet I only know your -tongue through books. To you, my friend, I look that I know it to -speak." - -"But, Count," I said, "You know and speak English thoroughly!" He -bowed gravely. - -"I thank you, my friend, for your all too-flattering estimate, but yet -I fear that I am but a little way on the road I would travel. True, I -know the grammar and the words, but yet I know not how to speak them." - -"Indeed," I said, "You speak excellently." - -"Not so," he answered. "Well, I know that, did I move and speak in -your London, none there are who would not know me for a stranger. That -is not enough for me. Here I am noble. I am a Boyar. The common -people know me, and I am master. But a stranger in a strange land, he -is no one. Men know him not, and to know not is to care not for. I -am content if I am like the rest, so that no man stops if he sees me, -or pauses in his speaking if he hears my words, 'Ha, ha! A stranger!' -I have been so long master that I would be master still, or at least -that none other should be master of me. You come to me not alone as -agent of my friend Peter Hawkins, of Exeter, to tell me all about my -new estate in London. You shall, I trust, rest here with me a while, -so that by our talking I may learn the English intonation. And I -would that you tell me when I make error, even of the smallest, in my -speaking. I am sorry that I had to be away so long today, but you -will, I know forgive one who has so many important affairs in hand." - -Of course I said all I could about being willing, and asked if I might -come into that room when I chose. He answered, "Yes, certainly," and -added. - -"You may go anywhere you wish in the castle, except where the doors -are locked, where of course you will not wish to go. There is reason -that all things are as they are, and did you see with my eyes and know -with my knowledge, you would perhaps better understand." I said I was -sure of this, and then he went on. - -"We are in Transylvania, and Transylvania is not England. Our ways -are not your ways, and there shall be to you many strange things. Nay, -from what you have told me of your experiences already, you know -something of what strange things there may be." - -This led to much conversation, and as it was evident that he wanted to -talk, if only for talking's sake, I asked him many questions regarding -things that had already happened to me or come within my notice. -Sometimes he sheered off the subject, or turned the conversation by -pretending not to understand, but generally he answered all I asked -most frankly. Then as time went on, and I had got somewhat bolder, I -asked him of some of the strange things of the preceding night, as for -instance, why the coachman went to the places where he had seen the -blue flames. He then explained to me that it was commonly believed -that on a certain night of the year, last night, in fact, when all -evil spirits are supposed to have unchecked sway, a blue flame is seen -over any place where treasure has been concealed. - -"That treasure has been hidden," he went on, "in the region through -which you came last night, there can be but little doubt. For it was -the ground fought over for centuries by the Wallachian, the Saxon, and -the Turk. Why, there is hardly a foot of soil in all this region that -has not been enriched by the blood of men, patriots or invaders. In -the old days there were stirring times, when the Austrian and the -Hungarian came up in hordes, and the patriots went out to meet them, -men and women, the aged and the children too, and waited their coming -on the rocks above the passes, that they might sweep destruction on -them with their artificial avalanches. When the invader was -triumphant he found but little, for whatever there was had been -sheltered in the friendly soil." - -"But how," said I, "can it have remained so long undiscovered, when -there is a sure index to it if men will but take the trouble to look?" -The Count smiled, and as his lips ran back over his gums, the long, -sharp, canine teeth showed out strangely. He answered: - -"Because your peasant is at heart a coward and a fool! Those flames -only appear on one night, and on that night no man of this land will, -if he can help it, stir without his doors. And, dear sir, even if he -did he would not know what to do. Why, even the peasant that you tell -me of who marked the place of the flame would not know where to look -in daylight even for his own work. Even you would not, I dare be -sworn, be able to find these places again?" - -"There you are right," I said. "I know no more than the dead where -even to look for them." Then we drifted into other matters. - -"Come," he said at last, "tell me of London and of the house which you -have procured for me." With an apology for my remissness, I went into -my own room to get the papers from my bag. Whilst I was placing them -in order I heard a rattling of china and silver in the next room, and -as I passed through, noticed that the table had been cleared and the -lamp lit, for it was by this time deep into the dark. The lamps were -also lit in the study or library, and I found the Count lying on the -sofa, reading, of all things in the world, an English Bradshaw's -Guide. When I came in he cleared the books and papers from the table, -and with him I went into plans and deeds and figures of all sorts. He -was interested in everything, and asked me a myriad questions about -the place and its surroundings. He clearly had studied beforehand all -he could get on the subject of the neighbourhood, for he evidently at -the end knew very much more than I did. When I remarked this, he -answered. - -"Well, but, my friend, is it not needful that I should? When I go -there I shall be all alone, and my friend Harker Jonathan, nay, pardon -me. I fall into my country's habit of putting your patronymic first, -my friend Jonathan Harker will not be by my side to correct and aid -me. He will be in Exeter, miles away, probably working at papers of -the law with my other friend, Peter Hawkins. So!" - -We went thoroughly into the business of the purchase of the estate at -Purfleet. When I had told him the facts and got his signature to the -necessary papers, and had written a letter with them ready to post to -Mr. Hawkins, he began to ask me how I had come across so suitable a -place. I read to him the notes which I had made at the time, and -which I inscribe here. - -"At Purfleet, on a byroad, I came across just such a place as seemed -to be required, and where was displayed a dilapidated notice that the -place was for sale. It was surrounded by a high wall, of ancient -structure, built of heavy stones, and has not been repaired for a -large number of years. The closed gates are of heavy old oak and -iron, all eaten with rust. - -"The estate is called Carfax, no doubt a corruption of the old Quatre -Face, as the house is four sided, agreeing with the cardinal points of -the compass. It contains in all some twenty acres, quite surrounded -by the solid stone wall above mentioned. There are many trees on it, -which make it in places gloomy, and there is a deep, dark-looking pond -or small lake, evidently fed by some springs, as the water is clear -and flows away in a fair-sized stream. The house is very large and of -all periods back, I should say, to mediaeval times, for one part is of -stone immensely thick, with only a few windows high up and heavily -barred with iron. It looks like part of a keep, and is close to an -old chapel or church. I could not enter it, as I had not the key of -the door leading to it from the house, but I have taken with my Kodak -views of it from various points. The house had been added to, but in -a very straggling way, and I can only guess at the amount of ground it -covers, which must be very great. There are but few houses close at -hand, one being a very large house only recently added to and formed -into a private lunatic asylum. It is not, however, visible from the -grounds." - -When I had finished, he said, "I am glad that it is old and big. I -myself am of an old family, and to live in a new house would kill me. -A house cannot be made habitable in a day, and after all, how few days -go to make up a century. I rejoice also that there is a chapel of old -times. We Transylvanian nobles love not to think that our bones may -lie amongst the common dead. I seek not gaiety nor mirth, not the -bright voluptuousness of much sunshine and sparkling waters which -please the young and gay. I am no longer young, and my heart, through -weary years of mourning over the dead, is not attuned to mirth. Moreover, -the walls of my castle are broken. The shadows are many, and the wind -breathes cold through the broken battlements and casements. I love -the shade and the shadow, and would be alone with my thoughts when I -may." Somehow his words and his look did not seem to accord, or else -it was that his cast of face made his smile look malignant and -saturnine. - -Presently, with an excuse, he left me, asking me to pull my papers -together. He was some little time away, and I began to look at some -of the books around me. One was an atlas, which I found opened -naturally to England, as if that map had been much used. On looking -at it I found in certain places little rings marked, and on examining -these I noticed that one was near London on the east side, manifestly -where his new estate was situated. The other two were Exeter, and -Whitby on the Yorkshire coast. - -It was the better part of an hour when the Count returned. "Aha!" he -said. "Still at your books? Good! But you must not work always. -Come! I am informed that your supper is ready." He took my arm, and -we went into the next room, where I found an excellent supper ready on -the table. The Count again excused himself, as he had dined out on -his being away from home. But he sat as on the previous night, and -chatted whilst I ate. After supper I smoked, as on the last evening, -and the Count stayed with me, chatting and asking questions on every -conceivable subject, hour after hour. I felt that it was getting very -late indeed, but I did not say anything, for I felt under obligation -to meet my host's wishes in every way. I was not sleepy, as the long -sleep yesterday had fortified me, but I could not help experiencing -that chill which comes over one at the coming of the dawn, which is -like, in its way, the turn of the tide. They say that people who are -near death die generally at the change to dawn or at the turn of the -tide. Anyone who has when tired, and tied as it were to his post, -experienced this change in the atmosphere can well believe it. All at -once we heard the crow of the cock coming up with preternatural -shrillness through the clear morning air. - -Count Dracula, jumping to his feet, said, "Why there is the morning -again! How remiss I am to let you stay up so long. You must make -your conversation regarding my dear new country of England less -interesting, so that I may not forget how time flies by us," and with -a courtly bow, he quickly left me. - -I went into my room and drew the curtains, but there was little to -notice. My window opened into the courtyard, all I could see was the -warm grey of quickening sky. So I pulled the curtains again, and have -written of this day. - - -8 May.--I began to fear as I wrote in this book that I was getting too -diffuse. But now I am glad that I went into detail from the first, -for there is something so strange about this place and all in it that -I cannot but feel uneasy. I wish I were safe out of it, or that I had -never come. It may be that this strange night existence is telling on -me, but would that that were all! If there were any one to talk to I -could bear it, but there is no one. I have only the Count to speak -with, and he--I fear I am myself the only living soul within the -place. Let me be prosaic so far as facts can be. It will help me to -bear up, and imagination must not run riot with me. If it does I am -lost. Let me say at once how I stand, or seem to. - -I only slept a few hours when I went to bed, and feeling that I could -not sleep any more, got up. I had hung my shaving glass by the -window, and was just beginning to shave. Suddenly I felt a hand on my -shoulder, and heard the Count's voice saying to me, "Good morning." I -started, for it amazed me that I had not seen him, since the -reflection of the glass covered the whole room behind me. In starting -I had cut myself slightly, but did not notice it at the moment. Having -answered the Count's salutation, I turned to the glass again to see -how I had been mistaken. This time there could be no error, for the -man was close to me, and I could see him over my shoulder. But there -was no reflection of him in the mirror! The whole room behind me was -displayed, but there was no sign of a man in it, except myself. - -This was startling, and coming on the top of so many strange things, -was beginning to increase that vague feeling of uneasiness which I -always have when the Count is near. But at the instant I saw that the -cut had bled a little, and the blood was trickling over my chin. I -laid down the razor, turning as I did so half round to look for some -sticking plaster. When the Count saw my face, his eyes blazed with a -sort of demoniac fury, and he suddenly made a grab at my throat. I -drew away and his hand touched the string of beads which held the -crucifix. It made an instant change in him, for the fury passed so -quickly that I could hardly believe that it was ever there. - -"Take care," he said, "take care how you cut yourself. It is more -dangerous that you think in this country." Then seizing the shaving -glass, he went on, "And this is the wretched thing that has done the -mischief. It is a foul bauble of man's vanity. Away with it!" And -opening the window with one wrench of his terrible hand, he flung out -the glass, which was shattered into a thousand pieces on the stones of -the courtyard far below. Then he withdrew without a word. It is very -annoying, for I do not see how I am to shave, unless in my watch-case -or the bottom of the shaving pot, which is fortunately of metal. - -When I went into the dining room, breakfast was prepared, but I could -not find the Count anywhere. So I breakfasted alone. It is strange -that as yet I have not seen the Count eat or drink. He must be a very -peculiar man! After breakfast I did a little exploring in the -castle. I went out on the stairs, and found a room looking towards -the South. - -The view was magnificent, and from where I stood there was every -opportunity of seeing it. The castle is on the very edge of a -terrific precipice. A stone falling from the window would fall a -thousand feet without touching anything! As far as the eye can reach -is a sea of green tree tops, with occasionally a deep rift where there -is a chasm. Here and there are silver threads where the rivers wind -in deep gorges through the forests. - -But I am not in heart to describe beauty, for when I had seen the view -I explored further. Doors, doors, doors everywhere, and all locked -and bolted. In no place save from the windows in the castle walls is -there an available exit. The castle is a veritable prison, and I am a -prisoner! - - - - -CHAPTER 3 - - -Jonathan Harker's Journal Continued - -When I found that I was a prisoner a sort of wild feeling came over -me. I rushed up and down the stairs, trying every door and peering -out of every window I could find, but after a little the conviction of -my helplessness overpowered all other feelings. When I look back -after a few hours I think I must have been mad for the time, for I -behaved much as a rat does in a trap. When, however, the conviction -had come to me that I was helpless I sat down quietly, as quietly as I -have ever done anything in my life, and began to think over what was -best to be done. I am thinking still, and as yet have come to no -definite conclusion. Of one thing only am I certain. That it is no -use making my ideas known to the Count. He knows well that I am -imprisoned, and as he has done it himself, and has doubtless his own -motives for it, he would only deceive me if I trusted him fully with -the facts. So far as I can see, my only plan will be to keep my -knowledge and my fears to myself, and my eyes open. I am, I know, -either being deceived, like a baby, by my own fears, or else I am in -desperate straits, and if the latter be so, I need, and shall need, -all my brains to get through. - -I had hardly come to this conclusion when I heard the great door below -shut, and knew that the Count had returned. He did not come at once -into the library, so I went cautiously to my own room and found him -making the bed. This was odd, but only confirmed what I had all along -thought, that there are no servants in the house. When later I saw -him through the chink of the hinges of the door laying the table in -the dining room, I was assured of it. For if he does himself all -these menial offices, surely it is proof that there is no one else in -the castle, it must have been the Count himself who was the driver of -the coach that brought me here. This is a terrible thought, for if -so, what does it mean that he could control the wolves, as he did, by -only holding up his hand for silence? How was it that all the people -at Bistritz and on the coach had some terrible fear for me? What -meant the giving of the crucifix, of the garlic, of the wild rose, of -the mountain ash? - -Bless that good, good woman who hung the crucifix round my neck! For -it is a comfort and a strength to me whenever I touch it. It is odd -that a thing which I have been taught to regard with disfavour and as -idolatrous should in a time of loneliness and trouble be of help. Is -it that there is something in the essence of the thing itself, or that -it is a medium, a tangible help, in conveying memories of sympathy and -comfort? Some time, if it may be, I must examine this matter and try -to make up my mind about it. In the meantime I must find out all I -can about Count Dracula, as it may help me to understand. Tonight he -may talk of himself, if I turn the conversation that way. I must be -very careful, however, not to awake his suspicion. - - -Midnight.--I have had a long talk with the Count. I asked him a few -questions on Transylvania history, and he warmed up to the subject -wonderfully. In his speaking of things and people, and especially of -battles, he spoke as if he had been present at them all. This he -afterwards explained by saying that to a Boyar the pride of his house -and name is his own pride, that their glory is his glory, that their -fate is his fate. Whenever he spoke of his house he always said "we", -and spoke almost in the plural, like a king speaking. I wish I could -put down all he said exactly as he said it, for to me it was most -fascinating. It seemed to have in it a whole history of the country. -He grew excited as he spoke, and walked about the room pulling his -great white moustache and grasping anything on which he laid his hands -as though he would crush it by main strength. One thing he said which -I shall put down as nearly as I can, for it tells in its way the story -of his race. - -"We Szekelys have a right to be proud, for in our veins flows the -blood of many brave races who fought as the lion fights, for lordship. -Here, in the whirlpool of European races, the Ugric tribe bore down -from Iceland the fighting spirit which Thor and Wodin gave them, which -their Berserkers displayed to such fell intent on the seaboards of -Europe, aye, and of Asia and Africa too, till the peoples thought that -the werewolves themselves had come. Here, too, when they came, they -found the Huns, whose warlike fury had swept the earth like a living -flame, till the dying peoples held that in their veins ran the blood -of those old witches, who, expelled from Scythia had mated with the -devils in the desert. Fools, fools! What devil or what witch was -ever so great as Attila, whose blood is in these veins?" He held up -his arms. "Is it a wonder that we were a conquering race, that we -were proud, that when the Magyar, the Lombard, the Avar, the Bulgar, -or the Turk poured his thousands on our frontiers, we drove them back? -Is it strange that when Arpad and his legions swept through the -Hungarian fatherland he found us here when he reached the frontier, -that the Honfoglalas was completed there? And when the Hungarian -flood swept eastward, the Szekelys were claimed as kindred by the -victorious Magyars, and to us for centuries was trusted the guarding -of the frontier of Turkeyland. Aye, and more than that, endless duty -of the frontier guard, for as the Turks say, 'water sleeps, and the -enemy is sleepless.' Who more gladly than we throughout the Four -Nations received the 'bloody sword,' or at its warlike call flocked -quicker to the standard of the King? When was redeemed that great -shame of my nation, the shame of Cassova, when the flags of the -Wallach and the Magyar went down beneath the Crescent? Who was it but -one of my own race who as Voivode crossed the Danube and beat the Turk -on his own ground? This was a Dracula indeed! Woe was it that his -own unworthy brother, when he had fallen, sold his people to the Turk -and brought the shame of slavery on them! Was it not this Dracula, -indeed, who inspired that other of his race who in a later age again -and again brought his forces over the great river into Turkeyland, -who, when he was beaten back, came again, and again, though he had to -come alone from the bloody field where his troops were being -slaughtered, since he knew that he alone could ultimately triumph! -They said that he thought only of himself. Bah! What good are -peasants without a leader? Where ends the war without a brain and -heart to conduct it? Again, when, after the battle of Mohacs, we -threw off the Hungarian yoke, we of the Dracula blood were amongst -their leaders, for our spirit would not brook that we were not free. -Ah, young sir, the Szekelys, and the Dracula as their heart's blood, -their brains, and their swords, can boast a record that mushroom -growths like the Hapsburgs and the Romanoffs can never reach. The -warlike days are over. Blood is too precious a thing in these days of -dishonourable peace, and the glories of the great races are as a tale -that is told." - -It was by this time close on morning, and we went to bed. (Mem., this -diary seems horribly like the beginning of the "Arabian Nights," for -everything has to break off at cockcrow, or like the ghost of Hamlet's -father.) - - -12 May.--Let me begin with facts, bare, meager facts, verified by -books and figures, and of which there can be no doubt. I must not -confuse them with experiences which will have to rest on my own -observation, or my memory of them. Last evening when the Count came -from his room he began by asking me questions on legal matters and on -the doing of certain kinds of business. I had spent the day wearily -over books, and, simply to keep my mind occupied, went over some of -the matters I had been examined in at Lincoln's Inn. There was a -certain method in the Count's inquiries, so I shall try to put them -down in sequence. The knowledge may somehow or some time be useful to -me. - -First, he asked if a man in England might have two solicitors or more. -I told him he might have a dozen if he wished, but that it would not -be wise to have more than one solicitor engaged in one transaction, as -only one could act at a time, and that to change would be certain to -militate against his interest. He seemed thoroughly to understand, -and went on to ask if there would be any practical difficulty in having -one man to attend, say, to banking, and another to look after -shipping, in case local help were needed in a place far from the home -of the banking solicitor. I asked to explain more fully, so that I -might not by any chance mislead him, so he said, - -"I shall illustrate. Your friend and mine, Mr. Peter Hawkins, from -under the shadow of your beautiful cathedral at Exeter, which is far -from London, buys for me through your good self my place at London. -Good! Now here let me say frankly, lest you should think it strange -that I have sought the services of one so far off from London instead -of some one resident there, that my motive was that no local interest -might be served save my wish only, and as one of London residence -might, perhaps, have some purpose of himself or friend to serve, I -went thus afield to seek my agent, whose labours should be only to my -interest. Now, suppose I, who have much of affairs, wish to ship -goods, say, to Newcastle, or Durham, or Harwich, or Dover, might it -not be that it could with more ease be done by consigning to one in -these ports?" - -I answered that certainly it would be most easy, but that we -solicitors had a system of agency one for the other, so that local -work could be done locally on instruction from any solicitor, so that -the client, simply placing himself in the hands of one man, could have -his wishes carried out by him without further trouble. - -"But," said he, "I could be at liberty to direct myself. Is it not -so?" - -"Of course," I replied, and "Such is often done by men of business, -who do not like the whole of their affairs to be known by any one -person." - -"Good!" he said, and then went on to ask about the means of making -consignments and the forms to be gone through, and of all sorts of -difficulties which might arise, but by forethought could be guarded -against. I explained all these things to him to the best of my -ability, and he certainly left me under the impression that he would -have made a wonderful solicitor, for there was nothing that he did not -think of or foresee. For a man who was never in the country, and who -did not evidently do much in the way of business, his knowledge and -acumen were wonderful. When he had satisfied himself on these points -of which he had spoken, and I had verified all as well as I could by -the books available, he suddenly stood up and said, "Have you written -since your first letter to our friend Mr. Peter Hawkins, or to any -other?" - -It was with some bitterness in my heart that I answered that I had -not, that as yet I had not seen any opportunity of sending letters to -anybody. - -"Then write now, my young friend," he said, laying a heavy hand on my -shoulder, "write to our friend and to any other, and say, if it will -please you, that you shall stay with me until a month from now." - -"Do you wish me to stay so long?" I asked, for my heart grew cold at -the thought. - -"I desire it much, nay I will take no refusal. When your master, -employer, what you will, engaged that someone should come on his -behalf, it was understood that my needs only were to be consulted. I -have not stinted. Is it not so?" - -What could I do but bow acceptance? It was Mr. Hawkins' interest, not -mine, and I had to think of him, not myself, and besides, while Count -Dracula was speaking, there was that in his eyes and in his bearing -which made me remember that I was a prisoner, and that if I wished it -I could have no choice. The Count saw his victory in my bow, and his -mastery in the trouble of my face, for he began at once to use them, -but in his own smooth, resistless way. - -"I pray you, my good young friend, that you will not discourse of -things other than business in your letters. It will doubtless please -your friends to know that you are well, and that you look forward to -getting home to them. Is it not so?" As he spoke he handed me three -sheets of note paper and three envelopes. They were all of the -thinnest foreign post, and looking at them, then at him, and noticing -his quiet smile, with the sharp, canine teeth lying over the red -underlip, I understood as well as if he had spoken that I should be -more careful what I wrote, for he would be able to read it. So I -determined to write only formal notes now, but to write fully to Mr. -Hawkins in secret, and also to Mina, for to her I could write -shorthand, which would puzzle the Count, if he did see it. When I had -written my two letters I sat quiet, reading a book whilst the Count -wrote several notes, referring as he wrote them to some books on his -table. Then he took up my two and placed them with his own, and put -by his writing materials, after which, the instant the door had closed -behind him, I leaned over and looked at the letters, which were face -down on the table. I felt no compunction in doing so for under the -circumstances I felt that I should protect myself in every way I -could. - -One of the letters was directed to Samuel F. Billington, No. 7, The -Crescent, Whitby, another to Herr Leutner, Varna. The third was to -Coutts & Co., London, and the fourth to Herren Klopstock & Billreuth, -bankers, Buda Pesth. The second and fourth were unsealed. I was just -about to look at them when I saw the door handle move. I sank back in -my seat, having just had time to resume my book before the Count, -holding still another letter in his hand, entered the room. He took -up the letters on the table and stamped them carefully, and then -turning to me, said, - -"I trust you will forgive me, but I have much work to do in private -this evening. You will, I hope, find all things as you wish." At the -door he turned, and after a moment's pause said, "Let me advise you, -my dear young friend. Nay, let me warn you with all seriousness, that -should you leave these rooms you will not by any chance go to sleep in -any other part of the castle. It is old, and has many memories, and -there are bad dreams for those who sleep unwisely. Be warned! Should -sleep now or ever overcome you, or be like to do, then haste to your -own chamber or to these rooms, for your rest will then be safe. But -if you be not careful in this respect, then," He finished his speech -in a gruesome way, for he motioned with his hands as if he were washing -them. I quite understood. My only doubt was as to whether any dream -could be more terrible than the unnatural, horrible net of gloom and -mystery which seemed closing around me. - - -Later.--I endorse the last words written, but this time there is no -doubt in question. I shall not fear to sleep in any place where he is -not. I have placed the crucifix over the head of my bed, I imagine -that my rest is thus freer from dreams, and there it shall remain. - -When he left me I went to my room. After a little while, not hearing -any sound, I came out and went up the stone stair to where I could -look out towards the South. There was some sense of freedom in the -vast expanse, inaccessible though it was to me, as compared with the -narrow darkness of the courtyard. Looking out on this, I felt that I -was indeed in prison, and I seemed to want a breath of fresh air, -though it were of the night. I am beginning to feel this nocturnal -existence tell on me. It is destroying my nerve. I start at my own -shadow, and am full of all sorts of horrible imaginings. God knows -that there is ground for my terrible fear in this accursed place! I -looked out over the beautiful expanse, bathed in soft yellow moonlight -till it was almost as light as day. In the soft light the distant -hills became melted, and the shadows in the valleys and gorges of -velvety blackness. The mere beauty seemed to cheer me. There was -peace and comfort in every breath I drew. As I leaned from the window -my eye was caught by something moving a storey below me, and somewhat -to my left, where I imagined, from the order of the rooms, that the -windows of the Count's own room would look out. The window at which I -stood was tall and deep, stone-mullioned, and though weatherworn, was -still complete. But it was evidently many a day since the case had -been there. I drew back behind the stonework, and looked carefully -out. - -What I saw was the Count's head coming out from the window. I did not -see the face, but I knew the man by the neck and the movement of his -back and arms. In any case I could not mistake the hands which I had -had some many opportunities of studying. I was at first interested -and somewhat amused, for it is wonderful how small a matter will -interest and amuse a man when he is a prisoner. But my very feelings -changed to repulsion and terror when I saw the whole man slowly emerge -from the window and begin to crawl down the castle wall over the -dreadful abyss, face down with his cloak spreading out around him like -great wings. At first I could not believe my eyes. I thought it was -some trick of the moonlight, some weird effect of shadow, but I kept -looking, and it could be no delusion. I saw the fingers and toes -grasp the corners of the stones, worn clear of the mortar by the -stress of years, and by thus using every projection and inequality -move downwards with considerable speed, just as a lizard moves along a -wall. - -What manner of man is this, or what manner of creature, is it in the -semblance of man? I feel the dread of this horrible place -overpowering me. I am in fear, in awful fear, and there is no escape -for me. I am encompassed about with terrors that I dare not think of. - - -15 May.--Once more I have seen the count go out in his lizard fashion. -He moved downwards in a sidelong way, some hundred feet down, and a -good deal to the left. He vanished into some hole or window. When -his head had disappeared, I leaned out to try and see more, but -without avail. The distance was too great to allow a proper angle of -sight. I knew he had left the castle now, and thought to use the -opportunity to explore more than I had dared to do as yet. I went -back to the room, and taking a lamp, tried all the doors. They were -all locked, as I had expected, and the locks were comparatively new. -But I went down the stone stairs to the hall where I had entered -originally. I found I could pull back the bolts easily enough and -unhook the great chains. But the door was locked, and the key was -gone! That key must be in the Count's room. I must watch should his -door be unlocked, so that I may get it and escape. I went on to make -a thorough examination of the various stairs and passages, and to try -the doors that opened from them. One or two small rooms near the hall -were open, but there was nothing to see in them except old furniture, -dusty with age and moth-eaten. At last, however, I found one door at -the top of the stairway which, though it seemed locked, gave a little -under pressure. I tried it harder, and found that it was not really -locked, but that the resistance came from the fact that the hinges had -fallen somewhat, and the heavy door rested on the floor. Here was an -opportunity which I might not have again, so I exerted myself, and -with many efforts forced it back so that I could enter. I was now in -a wing of the castle further to the right than the rooms I knew and a -storey lower down. From the windows I could see that the suite of -rooms lay along to the south of the castle, the windows of the end -room looking out both west and south. On the latter side, as well as -to the former, there was a great precipice. The castle was built on -the corner of a great rock, so that on three sides it was quite -impregnable, and great windows were placed here where sling, or bow, -or culverin could not reach, and consequently light and comfort, -impossible to a position which had to be guarded, were secured. To -the west was a great valley, and then, rising far away, great jagged -mountain fastnesses, rising peak on peak, the sheer rock studded with -mountain ash and thorn, whose roots clung in cracks and crevices and -crannies of the stone. This was evidently the portion of the castle -occupied by the ladies in bygone days, for the furniture had more an -air of comfort than any I had seen. - -The windows were curtainless, and the yellow moonlight, flooding in -through the diamond panes, enabled one to see even colours, whilst it -softened the wealth of dust which lay over all and disguised in some -measure the ravages of time and moth. My lamp seemed to be of little -effect in the brilliant moonlight, but I was glad to have it with me, -for there was a dread loneliness in the place which chilled my heart -and made my nerves tremble. Still, it was better than living alone in -the rooms which I had come to hate from the presence of the Count, and -after trying a little to school my nerves, I found a soft quietude -come over me. Here I am, sitting at a little oak table where in old -times possibly some fair lady sat to pen, with much thought and many -blushes, her ill-spelt love letter, and writing in my diary in -shorthand all that has happened since I closed it last. It is the -nineteenth century up-to-date with a vengeance. And yet, unless my -senses deceive me, the old centuries had, and have, powers of their -own which mere "modernity" cannot kill. - - -Later: The morning of 16 May.--God preserve my sanity, for to this I -am reduced. Safety and the assurance of safety are things of the -past. Whilst I live on here there is but one thing to hope for, that -I may not go mad, if, indeed, I be not mad already. If I be sane, -then surely it is maddening to think that of all the foul things that -lurk in this hateful place the Count is the least dreadful to me, that -to him alone I can look for safety, even though this be only whilst I -can serve his purpose. Great God! Merciful God, let me be calm, for -out of that way lies madness indeed. I begin to get new lights on -certain things which have puzzled me. Up to now I never quite knew -what Shakespeare meant when he made Hamlet say, "My tablets! Quick, -my tablets! 'tis meet that I put it down," etc., For now, feeling as -though my own brain were unhinged or as if the shock had come which -must end in its undoing, I turn to my diary for repose. The habit of -entering accurately must help to soothe me. - -The Count's mysterious warning frightened me at the time. It frightens -me more not when I think of it, for in the future he has a fearful -hold upon me. I shall fear to doubt what he may say! - -When I had written in my diary and had fortunately replaced the book -and pen in my pocket I felt sleepy. The Count's warning came into my -mind, but I took pleasure in disobeying it. The sense of sleep was -upon me, and with it the obstinacy which sleep brings as outrider. The -soft moonlight soothed, and the wide expanse without gave a sense of -freedom which refreshed me. I determined not to return tonight to the -gloom-haunted rooms, but to sleep here, where, of old, ladies had sat -and sung and lived sweet lives whilst their gentle breasts were sad -for their menfolk away in the midst of remorseless wars. I drew a -great couch out of its place near the corner, so that as I lay, I -could look at the lovely view to east and south, and unthinking of and -uncaring for the dust, composed myself for sleep. I suppose I must -have fallen asleep. I hope so, but I fear, for all that followed was -startlingly real, so real that now sitting here in the broad, full -sunlight of the morning, I cannot in the least believe that it was all -sleep. - -I was not alone. The room was the same, unchanged in any way since I -came into it. I could see along the floor, in the brilliant -moonlight, my own footsteps marked where I had disturbed the long -accumulation of dust. In the moonlight opposite me were three young -women, ladies by their dress and manner. I thought at the time that I -must be dreaming when I saw them, they threw no shadow on the floor. -They came close to me, and looked at me for some time, and then -whispered together. Two were dark, and had high aquiline noses, like -the Count, and great dark, piercing eyes, that seemed to be almost red -when contrasted with the pale yellow moon. The other was fair, as -fair as can be, with great masses of golden hair and eyes like pale -sapphires. I seemed somehow to know her face, and to know it in -connection with some dreamy fear, but I could not recollect at the -moment how or where. All three had brilliant white teeth that shone -like pearls against the ruby of their voluptuous lips. There was -something about them that made me uneasy, some longing and at the same -time some deadly fear. I felt in my heart a wicked, burning desire -that they would kiss me with those red lips. It is not good to note -this down, lest some day it should meet Mina's eyes and cause her -pain, but it is the truth. They whispered together, and then they all -three laughed, such a silvery, musical laugh, but as hard as though -the sound never could have come through the softness of human lips. -It was like the intolerable, tingling sweetness of waterglasses when -played on by a cunning hand. The fair girl shook her head -coquettishly, and the other two urged her on. - -One said, "Go on! You are first, and we shall follow. Yours is the -right to begin." - -The other added, "He is young and strong. There are kisses for us -all." - -I lay quiet, looking out from under my eyelashes in an agony of -delightful anticipation. The fair girl advanced and bent over me till -I could feel the movement of her breath upon me. Sweet it was in one -sense, honey-sweet, and sent the same tingling through the nerves as -her voice, but with a bitter underlying the sweet, a bitter -offensiveness, as one smells in blood. - -I was afraid to raise my eyelids, but looked out and saw perfectly -under the lashes. The girl went on her knees, and bent over me, -simply gloating. There was a deliberate voluptuousness which was both -thrilling and repulsive, and as she arched her neck she actually -licked her lips like an animal, till I could see in the moonlight the -moisture shining on the scarlet lips and on the red tongue as it -lapped the white sharp teeth. Lower and lower went her head as the -lips went below the range of my mouth and chin and seemed to fasten on -my throat. Then she paused, and I could hear the churning sound of -her tongue as it licked her teeth and lips, and I could feel the hot -breath on my neck. Then the skin of my throat began to tingle as -one's flesh does when the hand that is to tickle it approaches nearer, -nearer. I could feel the soft, shivering touch of the lips on the -super sensitive skin of my throat, and the hard dents of two sharp -teeth, just touching and pausing there. I closed my eyes in -languorous ecstasy and waited, waited with beating heart. - -But at that instant, another sensation swept through me as quick as -lightning. I was conscious of the presence of the Count, and of his -being as if lapped in a storm of fury. As my eyes opened -involuntarily I saw his strong hand grasp the slender neck of the fair -woman and with giant's power draw it back, the blue eyes transformed -with fury, the white teeth champing with rage, and the fair cheeks -blazing red with passion. But the Count! Never did I imagine such -wrath and fury, even to the demons of the pit. His eyes were -positively blazing. The red light in them was lurid, as if the flames -of hell fire blazed behind them. His face was deathly pale, and the -lines of it were hard like drawn wires. The thick eyebrows that met -over the nose now seemed like a heaving bar of white-hot metal. With -a fierce sweep of his arm, he hurled the woman from him, and then -motioned to the others, as though he were beating them back. It was -the same imperious gesture that I had seen used to the wolves. In a -voice which, though low and almost in a whisper seemed to cut through -the air and then ring in the room he said, - -"How dare you touch him, any of you? How dare you cast eyes on him -when I had forbidden it? Back, I tell you all! This man belongs to -me! Beware how you meddle with him, or you'll have to deal with me." - -The fair girl, with a laugh of ribald coquetry, turned to answer him. -"You yourself never loved. You never love!" On this the other women -joined, and such a mirthless, hard, soulless laughter rang through the -room that it almost made me faint to hear. It seemed like the -pleasure of fiends. - -Then the Count turned, after looking at my face attentively, and said -in a soft whisper, "Yes, I too can love. You yourselves can tell it -from the past. Is it not so? Well, now I promise you that when I am -done with him you shall kiss him at your will. Now go! Go! I must -awaken him, for there is work to be done." - -"Are we to have nothing tonight?" said one of them, with a low laugh, -as she pointed to the bag which he had thrown upon the floor, and -which moved as though there were some living thing within it. For -answer he nodded his head. One of the women jumped forward and opened -it. If my ears did not deceive me there was a gasp and a low wail, as -of a half smothered child. The women closed round, whilst I was -aghast with horror. But as I looked, they disappeared, and with them -the dreadful bag. There was no door near them, and they could not -have passed me without my noticing. They simply seemed to fade into -the rays of the moonlight and pass out through the window, for I could -see outside the dim, shadowy forms for a moment before they entirely -faded away. - -Then the horror overcame me, and I sank down unconscious. - - - - -CHAPTER 4 - - -Jonathan Harker's Journal Continued - -I awoke in my own bed. If it be that I had not dreamt, the Count must -have carried me here. I tried to satisfy myself on the subject, but -could not arrive at any unquestionable result. To be sure, there were -certain small evidences, such as that my clothes were folded and laid -by in a manner which was not my habit. My watch was still unwound, -and I am rigorously accustomed to wind it the last thing before going -to bed, and many such details. But these things are no proof, for -they may have been evidences that my mind was not as usual, and, for -some cause or another, I had certainly been much upset. I must watch -for proof. Of one thing I am glad. If it was that the Count carried -me here and undressed me, he must have been hurried in his task, for -my pockets are intact. I am sure this diary would have been a mystery -to him which he would not have brooked. He would have taken or -destroyed it. As I look round this room, although it has been to me -so full of fear, it is now a sort of sanctuary, for nothing can be -more dreadful than those awful women, who were, who are, waiting to -suck my blood. - - -18 May.--I have been down to look at that room again in daylight, for -I must know the truth. When I got to the doorway at the top of the -stairs I found it closed. It had been so forcibly driven against the -jamb that part of the woodwork was splintered. I could see that the -bolt of the lock had not been shot, but the door is fastened from the -inside. I fear it was no dream, and must act on this surmise. - - -19 May.--I am surely in the toils. Last night the Count asked me in -the suavest tones to write three letters, one saying that my work here -was nearly done, and that I should start for home within a few days, -another that I was starting on the next morning from the time of the -letter, and the third that I had left the castle and arrived at -Bistritz. I would fain have rebelled, but felt that in the present -state of things it would be madness to quarrel openly with the Count -whilst I am so absolutely in his power. And to refuse would be to -excite his suspicion and to arouse his anger. He knows that I know -too much, and that I must not live, lest I be dangerous to him. My -only chance is to prolong my opportunities. Something may occur which -will give me a chance to escape. I saw in his eyes something of that -gathering wrath which was manifest when he hurled that fair woman from -him. He explained to me that posts were few and uncertain, and that -my writing now would ensure ease of mind to my friends. And he -assured me with so much impressiveness that he would countermand the -later letters, which would be held over at Bistritz until due time in -case chance would admit of my prolonging my stay, that to oppose him -would have been to create new suspicion. I therefore pretended to -fall in with his views, and asked him what dates I should put on the -letters. - -He calculated a minute, and then said, "The first should be June 12, -the second June 19, and the third June 29." - -I know now the span of my life. God help me! - - -28 May.--There is a chance of escape, or at any rate of being able to -send word home. A band of Szgany have come to the castle, and are -encamped in the courtyard. These are gipsies. I have notes of them -in my book. They are peculiar to this part of the world, though -allied to the ordinary gipsies all the world over. There are -thousands of them in Hungary and Transylvania, who are almost outside -all law. They attach themselves as a rule to some great noble or -boyar, and call themselves by his name. They are fearless and without -religion, save superstition, and they talk only their own varieties of -the Romany tongue. - -I shall write some letters home, and shall try to get them to have -them posted. I have already spoken to them through my window to begin -acquaintanceship. They took their hats off and made obeisance and -many signs, which however, I could not understand any more than I -could their spoken language . . . - -I have written the letters. Mina's is in shorthand, and I simply ask -Mr. Hawkins to communicate with her. To her I have explained my -situation, but without the horrors which I may only surmise. It would -shock and frighten her to death were I to expose my heart to her. -Should the letters not carry, then the Count shall not yet know my -secret or the extent of my knowledge. . . . - - -I have given the letters. I threw them through the bars of my window -with a gold piece, and made what signs I could to have them posted. -The man who took them pressed them to his heart and bowed, and then -put them in his cap. I could do no more. I stole back to the study, -and began to read. As the Count did not come in, I have written -here . . . - - -The Count has come. He sat down beside me, and said in his smoothest -voice as he opened two letters, "The Szgany has given me these, of -which, though I know not whence they come, I shall, of course, take -care. See!"--He must have looked at it.--"One is from you, and to my -friend Peter Hawkins. The other,"--here he caught sight of the -strange symbols as he opened the envelope, and the dark look came into -his face, and his eyes blazed wickedly,--"The other is a vile thing, -an outrage upon friendship and hospitality! It is not signed. Well! -So it cannot matter to us." And he calmly held letter and envelope in -the flame of the lamp till they were consumed. - -Then he went on, "The letter to Hawkins, that I shall, of course send -on, since it is yours. Your letters are sacred to me. Your pardon, -my friend, that unknowingly I did break the seal. Will you not cover -it again?" He held out the letter to me, and with a courteous bow -handed me a clean envelope. - -I could only redirect it and hand it to him in silence. When he went -out of the room I could hear the key turn softly. A minute later I -went over and tried it, and the door was locked. - -When, an hour or two after, the Count came quietly into the room, his -coming awakened me, for I had gone to sleep on the sofa. He was very -courteous and very cheery in his manner, and seeing that I had been -sleeping, he said, "So, my friend, you are tired? Get to bed. There -is the surest rest. I may not have the pleasure of talk tonight, -since there are many labours to me, but you will sleep, I pray." - -I passed to my room and went to bed, and, strange to say, slept -without dreaming. Despair has its own calms. - -31 May.--This morning when I woke I thought I would provide myself -with some papers and envelopes from my bag and keep them in my pocket, -so that I might write in case I should get an opportunity, but again a -surprise, again a shock! - -Every scrap of paper was gone, and with it all my notes, my memoranda, -relating to railways and travel, my letter of credit, in fact all that -might be useful to me were I once outside the castle. I sat and -pondered awhile, and then some thought occurred to me, and I made -search of my portmanteau and in the wardrobe where I had placed my -clothes. - -The suit in which I had travelled was gone, and also my overcoat and -rug. I could find no trace of them anywhere. This looked like some -new scheme of villainy . . . - - -17 June.--This morning, as I was sitting on the edge of my bed -cudgelling my brains, I heard without a crackling of whips and -pounding and scraping of horses' feet up the rocky path beyond the -courtyard. With joy I hurried to the window, and saw drive into the -yard two great leiter-wagons, each drawn by eight sturdy horses, and -at the head of each pair a Slovak, with his wide hat, great -nail-studded belt, dirty sheepskin, and high boots. They had also -their long staves in hand. I ran to the door, intending to descend -and try and join them through the main hall, as I thought that way -might be opened for them. Again a shock, my door was fastened on the -outside. - -Then I ran to the window and cried to them. They looked up at me -stupidly and pointed, but just then the "hetman" of the Szgany came -out, and seeing them pointing to my window, said something, at which -they laughed. - -Henceforth no effort of mine, no piteous cry or agonized entreaty, -would make them even look at me. They resolutely turned away. The -leiter-wagons contained great, square boxes, with handles of thick -rope. These were evidently empty by the ease with which the Slovaks -handled them, and by their resonance as they were roughly moved. - -When they were all unloaded and packed in a great heap in one corner -of the yard, the Slovaks were given some money by the Szgany, and -spitting on it for luck, lazily went each to his horse's head. -Shortly afterwards, I heard the crackling of their whips die away in -the distance. - - -24 June.--Last night the Count left me early, and locked himself into -his own room. As soon as I dared I ran up the winding stair, and -looked out of the window, which opened South. I thought I would watch -for the Count, for there is something going on. The Szgany are -quartered somewhere in the castle and are doing work of some kind. I -know it, for now and then, I hear a far-away muffled sound as of -mattock and spade, and, whatever it is, it must be the end of some -ruthless villainy. - -I had been at the window somewhat less than half an hour, when I saw -something coming out of the Count's window. I drew back and watched -carefully, and saw the whole man emerge. It was a new shock to me to -find that he had on the suit of clothes which I had worn whilst -travelling here, and slung over his shoulder the terrible bag which I -had seen the women take away. There could be no doubt as to his -quest, and in my garb, too! This, then, is his new scheme of evil, -that he will allow others to see me, as they think, so that he may -both leave evidence that I have been seen in the towns or villages -posting my own letters, and that any wickedness which he may do shall -by the local people be attributed to me. - -It makes me rage to think that this can go on, and whilst I am shut up -here, a veritable prisoner, but without that protection of the law -which is even a criminal's right and consolation. - -I thought I would watch for the Count's return, and for a long time -sat doggedly at the window. Then I began to notice that there were -some quaint little specks floating in the rays of the moonlight. They -were like the tiniest grains of dust, and they whirled round and -gathered in clusters in a nebulous sort of way. I watched them with a -sense of soothing, and a sort of calm stole over me. I leaned back in -the embrasure in a more comfortable position, so that I could enjoy -more fully the aerial gambolling. - -Something made me start up, a low, piteous howling of dogs somewhere -far below in the valley, which was hidden from my sight. Louder it -seemed to ring in my ears, and the floating moats of dust to take new -shapes to the sound as they danced in the moonlight. I felt myself -struggling to awake to some call of my instincts. Nay, my very soul -was struggling, and my half-remembered sensibilities were striving to -answer the call. I was becoming hypnotised! - -Quicker and quicker danced the dust. The moonbeams seemed to quiver -as they went by me into the mass of gloom beyond. More and more they -gathered till they seemed to take dim phantom shapes. And then I -started, broad awake and in full possession of my senses, and ran -screaming from the place. - -The phantom shapes, which were becoming gradually materialised from -the moonbeams, were those three ghostly women to whom I was doomed. - -I fled, and felt somewhat safer in my own room, where there was no -moonlight, and where the lamp was burning brightly. - -When a couple of hours had passed I heard something stirring in the -Count's room, something like a sharp wail quickly suppressed. And -then there was silence, deep, awful silence, which chilled me. With a -beating heart, I tried the door, but I was locked in my prison, and -could do nothing. I sat down and simply cried. - -As I sat I heard a sound in the courtyard without, the agonised cry of -a woman. I rushed to the window, and throwing it up, peered between -the bars. - -There, indeed, was a woman with dishevelled hair, holding her hands -over her heart as one distressed with running. She was leaning -against the corner of the gateway. When she saw my face at the window -she threw herself forward, and shouted in a voice laden with menace, -"Monster, give me my child!" - -She threw herself on her knees, and raising up her hands, cried the -same words in tones which wrung my heart. Then she tore her hair and -beat her breast, and abandoned herself to all the violences of -extravagant emotion. Finally, she threw herself forward, and though I -could not see her, I could hear the beating of her naked hands against -the door. - -Somewhere high overhead, probably on the tower, I heard the voice of -the Count calling in his harsh, metallic whisper. His call seemed to -be answered from far and wide by the howling of wolves. Before many -minutes had passed a pack of them poured, like a pent-up dam when -liberated, through the wide entrance into the courtyard. - -There was no cry from the woman, and the howling of the wolves was but -short. Before long they streamed away singly, licking their lips. - -I could not pity her, for I knew now what had become of her child, and -she was better dead. - -What shall I do? What can I do? How can I escape from this dreadful -thing of night, gloom, and fear? - - -25 June.--No man knows till he has suffered from the night how sweet -and dear to his heart and eye the morning can be. When the sun grew -so high this morning that it struck the top of the great gateway -opposite my window, the high spot which it touched seemed to me as if -the dove from the ark had lighted there. My fear fell from me as if -it had been a vaporous garment which dissolved in the warmth. - -I must take action of some sort whilst the courage of the day is upon -me. Last night one of my post-dated letters went to post, the first -of that fatal series which is to blot out the very traces of my -existence from the earth. - -Let me not think of it. Action! - -It has always been at night-time that I have been molested or -threatened, or in some way in danger or in fear. I have not yet seen -the Count in the daylight. Can it be that he sleeps when others wake, -that he may be awake whilst they sleep? If I could only get into his -room! But there is no possible way. The door is always locked, no -way for me. - -Yes, there is a way, if one dares to take it. Where his body has gone -why may not another body go? I have seen him myself crawl from his -window. Why should not I imitate him, and go in by his window? The -chances are desperate, but my need is more desperate still. I shall -risk it. At the worst it can only be death, and a man's death is not -a calf's, and the dreaded Hereafter may still be open to me. God help -me in my task! Goodbye, Mina, if I fail. Goodbye, my faithful friend -and second father. Goodbye, all, and last of all Mina! - - -Same day, later.--I have made the effort, and God helping me, have -come safely back to this room. I must put down every detail in order. -I went whilst my courage was fresh straight to the window on the south -side, and at once got outside on this side. The stones are big and -roughly cut, and the mortar has by process of time been washed away -between them. I took off my boots, and ventured out on the desperate -way. I looked down once, so as to make sure that a sudden glimpse of -the awful depth would not overcome me, but after that kept my eyes -away from it. I know pretty well the direction and distance of the -Count's window, and made for it as well as I could, having regard to -the opportunities available. I did not feel dizzy, I suppose I was -too excited, and the time seemed ridiculously short till I found -myself standing on the window sill and trying to raise up the sash. I -was filled with agitation, however, when I bent down and slid feet -foremost in through the window. Then I looked around for the Count, -but with surprise and gladness, made a discovery. The room was -empty! It was barely furnished with odd things, which seemed to have -never been used. - -The furniture was something the same style as that in the south rooms, -and was covered with dust. I looked for the key, but it was not in -the lock, and I could not find it anywhere. The only thing I found -was a great heap of gold in one corner, gold of all kinds, Roman, and -British, and Austrian, and Hungarian, and Greek and Turkish money, -covered with a film of dust, as though it had lain long in the ground. -None of it that I noticed was less than three hundred years old. -There were also chains and ornaments, some jewelled, but all of them -old and stained. - -At one corner of the room was a heavy door. I tried it, for, since I -could not find the key of the room or the key of the outer door, which -was the main object of my search, I must make further examination, or -all my efforts would be in vain. It was open, and led through a stone -passage to a circular stairway, which went steeply down. - -I descended, minding carefully where I went for the stairs were dark, -being only lit by loopholes in the heavy masonry. At the bottom there -was a dark, tunnel-like passage, through which came a deathly, sickly -odour, the odour of old earth newly turned. As I went through the -passage the smell grew closer and heavier. At last I pulled open a -heavy door which stood ajar, and found myself in an old ruined chapel, -which had evidently been used as a graveyard. The roof was broken, -and in two places were steps leading to vaults, but the ground had -recently been dug over, and the earth placed in great wooden boxes, -manifestly those which had been brought by the Slovaks. - -There was nobody about, and I made a search over every inch of the -ground, so as not to lose a chance. I went down even into the vaults, -where the dim light struggled, although to do so was a dread to my -very soul. Into two of these I went, but saw nothing except fragments -of old coffins and piles of dust. In the third, however, I made a -discovery. - -There, in one of the great boxes, of which there were fifty in all, on -a pile of newly dug earth, lay the Count! He was either dead or -asleep. I could not say which, for eyes were open and stony, but -without the glassiness of death, and the cheeks had the warmth of life -through all their pallor. The lips were as red as ever. But there -was no sign of movement, no pulse, no breath, no beating of the heart. - -I bent over him, and tried to find any sign of life, but in vain. He -could not have lain there long, for the earthy smell would have passed -away in a few hours. By the side of the box was its cover, pierced -with holes here and there. I thought he might have the keys on him, -but when I went to search I saw the dead eyes, and in them dead though -they were, such a look of hate, though unconscious of me or my -presence, that I fled from the place, and leaving the Count's room by -the window, crawled again up the castle wall. Regaining my room, I -threw myself panting upon the bed and tried to think. - - -29 June.--Today is the date of my last letter, and the Count has taken -steps to prove that it was genuine, for again I saw him leave the -castle by the same window, and in my clothes. As he went down the -wall, lizard fashion, I wished I had a gun or some lethal weapon, that -I might destroy him. But I fear that no weapon wrought along by man's -hand would have any effect on him. I dared not wait to see him -return, for I feared to see those weird sisters. I came back to the -library, and read there till I fell asleep. - -I was awakened by the Count, who looked at me as grimly as a man could -look as he said, "Tomorrow, my friend, we must part. You return to -your beautiful England, I to some work which may have such an end that -we may never meet. Your letter home has been despatched. Tomorrow I -shall not be here, but all shall be ready for your journey. In the -morning come the Szgany, who have some labours of their own here, and -also come some Slovaks. When they have gone, my carriage shall come -for you, and shall bear you to the Borgo Pass to meet the diligence -from Bukovina to Bistritz. But I am in hopes that I shall see more of -you at Castle Dracula." - -I suspected him, and determined to test his sincerity. Sincerity! It -seems like a profanation of the word to write it in connection with -such a monster, so I asked him point-blank, "Why may I not go -tonight?" - -"Because, dear sir, my coachman and horses are away on a mission." - -"But I would walk with pleasure. I want to get away at once." - -He smiled, such a soft, smooth, diabolical smile that I knew there was -some trick behind his smoothness. He said, "And your baggage?" - -"I do not care about it. I can send for it some other time." - -The Count stood up, and said, with a sweet courtesy which made me rub -my eyes, it seemed so real, "You English have a saying which is close -to my heart, for its spirit is that which rules our boyars, 'Welcome -the coming, speed the parting guest.' Come with me, my dear young -friend. Not an hour shall you wait in my house against your will, -though sad am I at your going, and that you so suddenly desire it. -Come!" With a stately gravity, he, with the lamp, preceded me down -the stairs and along the hall. Suddenly he stopped. "Hark!" - -Close at hand came the howling of many wolves. It was almost as if -the sound sprang up at the rising of his hand, just as the music of a -great orchestra seems to leap under the baton of the conductor. After -a pause of a moment, he proceeded, in his stately way, to the door, -drew back the ponderous bolts, unhooked the heavy chains, and began to -draw it open. - -To my intense astonishment I saw that it was unlocked. Suspiciously, -I looked all round, but could see no key of any kind. - -As the door began to open, the howling of the wolves without grew -louder and angrier. Their red jaws, with champing teeth, and their -blunt-clawed feet as they leaped, came in through the opening door. I -knew than that to struggle at the moment against the Count was -useless. With such allies as these at his command, I could do -nothing. - -But still the door continued slowly to open, and only the Count's body -stood in the gap. Suddenly it struck me that this might be the moment -and means of my doom. I was to be given to the wolves, and at my own -instigation. There was a diabolical wickedness in the idea great -enough for the Count, and as the last chance I cried out, "Shut the -door! I shall wait till morning." And I covered my face with my -hands to hide my tears of bitter disappointment. - -With one sweep of his powerful arm, the Count threw the door shut, and -the great bolts clanged and echoed through the hall as they shot back -into their places. - -In silence we returned to the library, and after a minute or two I went -to my own room. The last I saw of Count Dracula was his kissing his -hand to me, with a red light of triumph in his eyes, and with a smile -that Judas in hell might be proud of. - -When I was in my room and about to lie down, I thought I heard a -whispering at my door. I went to it softly and listened. Unless my -ears deceived me, I heard the voice of the Count. - -"Back! Back to your own place! Your time is not yet come. Wait! -Have patience! Tonight is mine. Tomorrow night is yours!" - -There was a low, sweet ripple of laughter, and in a rage I threw open -the door, and saw without the three terrible women licking their lips. -As I appeared, they all joined in a horrible laugh, and ran away. - -I came back to my room and threw myself on my knees. It is then so -near the end? Tomorrow! Tomorrow! Lord, help me, and those to whom -I am dear! - - -30 June.--These may be the last words I ever write in this diary. I -slept till just before the dawn, and when I woke threw myself on my -knees, for I determined that if Death came he should find me ready. - -At last I felt that subtle change in the air, and knew that the -morning had come. Then came the welcome cockcrow, and I felt that I -was safe. With a glad heart, I opened the door and ran down the hall. -I had seen that the door was unlocked, and now escape was before me. -With hands that trembled with eagerness, I unhooked the chains and -threw back the massive bolts. - -But the door would not move. Despair seized me. I pulled and pulled -at the door, and shook it till, massive as it was, it rattled in its -casement. I could see the bolt shot. It had been locked after I left -the Count. - -Then a wild desire took me to obtain the key at any risk, and I -determined then and there to scale the wall again, and gain the -Count's room. He might kill me, but death now seemed the happier -choice of evils. Without a pause I rushed up to the east window, and -scrambled down the wall, as before, into the Count's room. It was -empty, but that was as I expected. I could not see a key anywhere, -but the heap of gold remained. I went through the door in the corner -and down the winding stair and along the dark passage to the old -chapel. I knew now well enough where to find the monster I sought. - -The great box was in the same place, close against the wall, but the -lid was laid on it, not fastened down, but with the nails ready in -their places to be hammered home. - -I knew I must reach the body for the key, so I raised the lid, and -laid it back against the wall. And then I saw something which filled -my very soul with horror. There lay the Count, but looking as if his -youth had been half restored. For the white hair and moustache were -changed to dark iron-grey. The cheeks were fuller, and the white skin -seemed ruby-red underneath. The mouth was redder than ever, for on -the lips were gouts of fresh blood, which trickled from the corners of -the mouth and ran down over the chin and neck. Even the deep, burning -eyes seemed set amongst swollen flesh, for the lids and pouches -underneath were bloated. It seemed as if the whole awful creature -were simply gorged with blood. He lay like a filthy leech, exhausted -with his repletion. - -I shuddered as I bent over to touch him, and every sense in me -revolted at the contact, but I had to search, or I was lost. The -coming night might see my own body a banquet in a similar war to those -horrid three. I felt all over the body, but no sign could I find of -the key. Then I stopped and looked at the Count. There was a mocking -smile on the bloated face which seemed to drive me mad. This was the -being I was helping to transfer to London, where, perhaps, for -centuries to come he might, amongst its teeming millions, satiate his -lust for blood, and create a new and ever-widening circle of -semi-demons to batten on the helpless. - -The very thought drove me mad. A terrible desire came upon me to rid -the world of such a monster. There was no lethal weapon at hand, but -I seized a shovel which the workmen had been using to fill the cases, -and lifting it high, struck, with the edge downward, at the hateful -face. But as I did so the head turned, and the eyes fell upon me, -with all their blaze of basilisk horror. The sight seemed to paralyze -me, and the shovel turned in my hand and glanced from the face, merely -making a deep gash above the forehead. The shovel fell from my hand -across the box, and as I pulled it away the flange of the blade caught -the edge of the lid which fell over again, and hid the horrid thing -from my sight. The last glimpse I had was of the bloated face, -blood-stained and fixed with a grin of malice which would have held -its own in the nethermost hell. - -I thought and thought what should be my next move, but my brain seemed -on fire, and I waited with a despairing feeling growing over me. As I -waited I heard in the distance a gipsy song sung by merry voices -coming closer, and through their song the rolling of heavy wheels and -the cracking of whips. The Szgany and the Slovaks of whom the Count -had spoken were coming. With a last look around and at the box which -contained the vile body, I ran from the place and gained the Count's -room, determined to rush out at the moment the door should be opened. -With strained ears, I listened, and heard downstairs the grinding of -the key in the great lock and the falling back of the heavy door. -There must have been some other means of entry, or some one had a key -for one of the locked doors. - -Then there came the sound of many feet tramping and dying away in some -passage which sent up a clanging echo. I turned to run down again -towards the vault, where I might find the new entrance, but at the -moment there seemed to come a violent puff of wind, and the door to -the winding stair blew to with a shock that set the dust from the -lintels flying. When I ran to push it open, I found that it was -hopelessly fast. I was again a prisoner, and the net of doom was -closing round me more closely. - -As I write there is in the passage below a sound of many tramping feet -and the crash of weights being set down heavily, doubtless the boxes, -with their freight of earth. There was a sound of hammering. It is -the box being nailed down. Now I can hear the heavy feet tramping -again along the hall, with many other idle feet coming behind them. - -The door is shut, the chains rattle. There is a grinding of the key -in the lock. I can hear the key withdrawn, then another door opens -and shuts. I hear the creaking of lock and bolt. - -Hark! In the courtyard and down the rocky way the roll of heavy -wheels, the crack of whips, and the chorus of the Szgany as they pass -into the distance. - -I am alone in the castle with those horrible women. Faugh! Mina is a -woman, and there is nought in common. They are devils of the Pit! - -I shall not remain alone with them. I shall try to scale the castle -wall farther than I have yet attempted. I shall take some of the gold -with me, lest I want it later. I may find a way from this dreadful -place. - -And then away for home! Away to the quickest and nearest train! Away -from the cursed spot, from this cursed land, where the devil and his -children still walk with earthly feet! - -At least God's mercy is better than that of those monsters, and the -precipice is steep and high. At its foot a man may sleep, as a man. -Goodbye, all. Mina! - - - - -CHAPTER 5 - - -LETTER FROM MISS MINA MURRAY TO MISS LUCY WESTENRA - -9 May. - -My dearest Lucy, - -Forgive my long delay in writing, but I have been simply overwhelmed -with work. The life of an assistant schoolmistress is sometimes -trying. I am longing to be with you, and by the sea, where we can -talk together freely and build our castles in the air. I have been -working very hard lately, because I want to keep up with Jonathan's -studies, and I have been practicing shorthand very assiduously. -When we are married I shall be able to be useful to Jonathan, and if -I can stenograph well enough I can take down what he wants to say in -this way and write it out for him on the typewriter, at which also I -am practicing very hard. - -He and I sometimes write letters in shorthand, and he is -keeping a stenographic journal of his travels abroad. When -I am with you I shall keep a diary in the same way. I don't -mean one of those two-pages-to-the-week-with-Sunday-squeezed- -in-a-corner diaries, but a sort of journal which I can write -in whenever I feel inclined. - -I do not suppose there will be much of interest to other people, but -it is not intended for them. I may show it to Jonathan some day if -there is in it anything worth sharing, but it is really an exercise -book. I shall try to do what I see lady journalists do, -interviewing and writing descriptions and trying to remember -conversations. I am told that, with a little practice, one can -remember all that goes on or that one hears said during a day. - -However, we shall see. I will tell you of my little plans when we -meet. I have just had a few hurried lines from Jonathan from -Transylvania. He is well, and will be returning in about a week. I -am longing to hear all his news. It must be nice to see strange -countries. I wonder if we, I mean Jonathan and I, shall ever see -them together. There is the ten o'clock bell ringing. Goodbye. - -Your loving - -Mina - - -Tell me all the news when you write. You have not told me -anything for a long time. I hear rumours, and especially -of a tall, handsome, curly-haired man??? - - - -LETTER, LUCY WESTENRA TO MINA MURRAY - - -17, Chatham Street - -Wednesday - -My dearest Mina, - - -I must say you tax me very unfairly with being a bad correspondent. -I wrote you twice since we parted, and your last letter was only -your second. Besides, I have nothing to tell you. There is really -nothing to interest you. - -Town is very pleasant just now, and we go a great deal to -picture-galleries and for walks and rides in the park. As -to the tall, curly-haired man, I suppose it was the one who -was with me at the last Pop. Someone has evidently been -telling tales. - -That was Mr. Holmwood. He often comes to see us, and he and -Mamma get on very well together, they have so many things -to talk about in common. - -We met some time ago a man that would just do for you, if you were -not already engaged to Jonathan. He is an excellent parti, being -handsome, well off, and of good birth. He is a doctor and really -clever. Just fancy! He is only nine-and twenty, and he has an -immense lunatic asylum all under his own care. Mr. Holmwood -introduced him to me, and he called here to see us, and often comes -now. I think he is one of the most resolute men I ever saw, and yet -the most calm. He seems absolutely imperturbable. I can fancy what -a wonderful power he must have over his patients. He has a curious -habit of looking one straight in the face, as if trying to read -one's thoughts. He tries this on very much with me, but I flatter -myself he has got a tough nut to crack. I know that from my glass. - -Do you ever try to read your own face? I do, and I can -tell you it is not a bad study, and gives you more trouble -than you can well fancy if you have never tried it. - -He says that I afford him a curious psychological study, and -I humbly think I do. I do not, as you know, take sufficient -interest in dress to be able to describe the new fashions. -Dress is a bore. That is slang again, but never mind. Arthur -says that every day. - -There, it is all out, Mina, we have told all our secrets to -each other since we were children. We have slept together -and eaten together, and laughed and cried together, and -now, though I have spoken, I would like to speak more. Oh, -Mina, couldn't you guess? I love him. I am blushing as I -write, for although I think he loves me, he has not told me -so in words. But, oh, Mina, I love him. I love him! There, -that does me good. - -I wish I were with you, dear, sitting by the fire undressing, as we -used to sit, and I would try to tell you what I feel. I do not know -how I am writing this even to you. I am afraid to stop, or I should -tear up the letter, and I don't want to stop, for I do so want to -tell you all. Let me hear from you at once, and tell me all that you -think about it. Mina, pray for my happiness. - -Lucy - - -P.S.--I need not tell you this is a secret. -Goodnight again. L. - - - - -LETTER, LUCY WESTENRA TO MINA MURRAY - -24 May - -My dearest Mina, - -Thanks, and thanks, and thanks again for your sweet letter. It -was so nice to be able to tell you and to have your sympathy. - -My dear, it never rains but it pours. How true the old proverbs -are. Here am I, who shall be twenty in September, and yet I never -had a proposal till today, not a real proposal, and today I had -three. Just fancy! Three proposals in one day! Isn't it awful! I -feel sorry, really and truly sorry, for two of the poor fellows. -Oh, Mina, I am so happy that I don't know what to do with myself. -And three proposals! But, for goodness' sake, don't tell any of the -girls, or they would be getting all sorts of extravagant ideas, and -imagining themselves injured and slighted if in their very first day -at home they did not get six at least. Some girls are so vain! You -and I, Mina dear, who are engaged and are going to settle down soon -soberly into old married women, can despise vanity. Well, I must -tell you about the three, but you must keep it a secret, dear, from -every one except, of course, Jonathan. You will tell him, because I -would, if I were in your place, certainly tell Arthur. A woman -ought to tell her husband everything. Don't you think so, dear? And -I must be fair. Men like women, certainly their wives, to be quite -as fair as they are. And women, I am afraid, are not always quite -as fair as they should be. - -Well, my dear, number One came just before lunch. I told you of -him, Dr. John Seward, the lunatic asylum man, with the strong jaw -and the good forehead. He was very cool outwardly, but was nervous -all the same. He had evidently been schooling himself as to all -sorts of little things, and remembered them, but he almost managed -to sit down on his silk hat, which men don't generally do when they -are cool, and then when he wanted to appear at ease he kept playing -with a lancet in a way that made me nearly scream. He spoke to me, -Mina, very straightforwardly. He told me how dear I was to him, -though he had known me so little, and what his life would be with me -to help and cheer him. He was going to tell me how unhappy he would -be if I did not care for him, but when he saw me cry he said he was -a brute and would not add to my present trouble. Then he broke off -and asked if I could love him in time, and when I shook my head his -hands trembled, and then with some hesitation he asked me if I cared -already for any one else. He put it very nicely, saying that he did -not want to wring my confidence from me, but only to know, because -if a woman's heart was free a man might have hope. And then, Mina, -I felt a sort of duty to tell him that there was some one. I only -told him that much, and then he stood up, and he looked very strong -and very grave as he took both my hands in his and said he hoped I -would be happy, and that If I ever wanted a friend I must count him -one of my best. - -Oh, Mina dear, I can't help crying, and you must excuse this letter -being all blotted. Being proposed to is all very nice and all that -sort of thing, but it isn't at all a happy thing when you have to -see a poor fellow, whom you know loves you honestly, going away and -looking all broken hearted, and to know that, no matter what he may -say at the moment, you are passing out of his life. My dear, I must -stop here at present, I feel so miserable, though I am so happy. - -Evening. - -Arthur has just gone, and I feel in better spirits than when I -left off, so I can go on telling you about the day. - -Well, my dear, number Two came after lunch. He is such a nice -fellow, an American from Texas, and he looks so young and so fresh -that it seems almost impossible that he has been to so many places -and has such adventures. I sympathize with poor Desdemona when she -had such a stream poured in her ear, even by a black man. I suppose -that we women are such cowards that we think a man will save us from -fears, and we marry him. I know now what I would do if I were a man -and wanted to make a girl love me. No, I don't, for there was Mr. -Morris telling us his stories, and Arthur never told any, and -yet . . . - -My dear, I am somewhat previous. Mr. Quincy P. Morris found me -alone. It seems that a man always does find a girl alone. No, he -doesn't, for Arthur tried twice to make a chance, and I helping him -all I could, I am not ashamed to say it now. I must tell you -beforehand that Mr. Morris doesn't always speak slang, that is to -say, he never does so to strangers or before them, for he is really -well educated and has exquisite manners, but he found out that it -amused me to hear him talk American slang, and whenever I was -present, and there was no one to be shocked, he said such funny -things. I am afraid, my dear, he has to invent it all, for it fits -exactly into whatever else he has to say. But this is a way slang -has. I do not know myself if I shall ever speak slang. I do not -know if Arthur likes it, as I have never heard him use any as yet. - -Well, Mr. Morris sat down beside me and looked as happy and jolly as -he could, but I could see all the same that he was very nervous. He -took my hand in his, and said ever so sweetly . . . - -"Miss Lucy, I know I ain't good enough to regulate the fixin's of -your little shoes, but I guess if you wait till you find a man that -is you will go join them seven young women with the lamps when you -quit. Won't you just hitch up alongside of me and let us go down -the long road together, driving in double harness?" - -Well, he did look so good humoured and so jolly that it didn't seem -half so hard to refuse him as it did poor Dr. Seward. So I said, as -lightly as I could, that I did not know anything of hitching, and -that I wasn't broken to harness at all yet. Then he said that he -had spoken in a light manner, and he hoped that if he had made a -mistake in doing so on so grave, so momentous, and occasion for him, -I would forgive him. He really did look serious when he was saying -it, and I couldn't help feeling a sort of exultation that he was -number Two in one day. And then, my dear, before I could say a word -he began pouring out a perfect torrent of love-making, laying his -very heart and soul at my feet. He looked so earnest over it that I -shall never again think that a man must be playful always, and never -earnest, because he is merry at times. I suppose he saw something -in my face which checked him, for he suddenly stopped, and said with -a sort of manly fervour that I could have loved him for if I had -been free . . . - -"Lucy, you are an honest hearted girl, I know. I should not be here -speaking to you as I am now if I did not believe you clean grit, -right through to the very depths of your soul. Tell me, like one -good fellow to another, is there any one else that you care for? -And if there is I'll never trouble you a hair's breadth again, but -will be, if you will let me, a very faithful friend." - -My dear Mina, why are men so noble when we women are so little -worthy of them? Here was I almost making fun of this great hearted, -true gentleman. I burst into tears, I am afraid, my dear, you will -think this a very sloppy letter in more ways than one, and I really -felt very badly. - -Why can't they let a girl marry three men, or as many as -want her, and save all this trouble? But this is heresy, -and I must not say it. I am glad to say that, though I was -crying, I was able to look into Mr. Morris' brave eyes, and -I told him out straight . . . - -"Yes, there is some one I love, though he has not told me -yet that he even loves me." I was right to speak to him so -frankly, for quite a light came into his face, and he put -out both his hands and took mine, I think I put them into -his, and said in a hearty way . . . - -"That's my brave girl. It's better worth being late for a chance of -winning you than being in time for any other girl in the world. -Don't cry, my dear. If it's for me, I'm a hard nut to crack, and I -take it standing up. If that other fellow doesn't know his -happiness, well, he'd better look for it soon, or he'll have to deal -with me. Little girl, your honesty and pluck have made me a friend, -and that's rarer than a lover, it's more selfish anyhow. My dear, -I'm going to have a pretty lonely walk between this and Kingdom -Come. Won't you give me one kiss? It'll be something to keep off -the darkness now and then. You can, you know, if you like, for that -other good fellow, or you could not love him, hasn't spoken yet." - -That quite won me, Mina, for it was brave and sweet of him, -and noble too, to a rival, wasn't it? And he so sad, so I -leant over and kissed him. - -He stood up with my two hands in his, and as he looked down into my -face, I am afraid I was blushing very much, he said, "Little girl, I -hold your hand, and you've kissed me, and if these things don't make -us friends nothing ever will. Thank you for your sweet honesty to -me, and goodbye." - -He wrung my hand, and taking up his hat, went straight out of the -room without looking back, without a tear or a quiver or a pause, -and I am crying like a baby. - -Oh, why must a man like that be made unhappy when there are lots of -girls about who would worship the very ground he trod on? I know I -would if I were free, only I don't want to be free. My dear, this -quite upset me, and I feel I cannot write of happiness just at once, -after telling you of it, and I don't wish to tell of the number -Three until it can be all happy. Ever your loving . . . - -Lucy - - -P.S.--Oh, about number Three, I needn't tell you of number -Three, need I? Besides, it was all so confused. It seemed -only a moment from his coming into the room till both his -arms were round me, and he was kissing me. I am very, very -happy, and I don't know what I have done to deserve it. I -must only try in the future to show that I am not ungrateful -to God for all His goodness to me in sending to me such a -lover, such a husband, and such a friend. - -Goodbye. - - - -DR. SEWARD'S DIARY (Kept in phonograph) - -25 May.--Ebb tide in appetite today. Cannot eat, cannot rest, so -diary instead. Since my rebuff of yesterday I have a sort of empty -feeling. Nothing in the world seems of sufficient importance to be -worth the doing. As I knew that the only cure for this sort of thing -was work, I went amongst the patients. I picked out one who has -afforded me a study of much interest. He is so quaint that I am -determined to understand him as well as I can. Today I seemed to get -nearer than ever before to the heart of his mystery. - -I questioned him more fully than I had ever done, with a view to -making myself master of the facts of his hallucination. In my manner -of doing it there was, I now see, something of cruelty. I seemed to -wish to keep him to the point of his madness, a thing which I avoid -with the patients as I would the mouth of hell. - -(Mem., Under what circumstances would I not avoid the pit of hell?) -Omnia Romae venalia sunt. Hell has its price! If there be anything -behind this instinct it will be valuable to trace it afterwards -accurately, so I had better commence to do so, therefore . . . - -R. M, Renfield, age 59. Sanguine temperament, great physical -strength, morbidly excitable, periods of gloom, ending in some fixed -idea which I cannot make out. I presume that the sanguine temperament -itself and the disturbing influence end in a mentally-accomplished -finish, a possibly dangerous man, probably dangerous if unselfish. In -selfish men caution is as secure an armour for their foes as for -themselves. What I think of on this point is, when self is the fixed -point the centripetal force is balanced with the centrifugal. When -duty, a cause, etc., is the fixed point, the latter force is -paramount, and only accident or a series of accidents can balance it. - - - -LETTER, QUINCEY P. MORRIS TO HON. ARTHUR HOLMOOD - -25 May. - -My dear Art, - -We've told yarns by the campfire in the prairies, and dressed one -another's wounds after trying a landing at the Marquesas, and drunk -healths on the shore of Titicaca. There are more yarns to be told, -and other wounds to be healed, and another health to be drunk. -Won't you let this be at my campfire tomorrow night? I have no -hesitation in asking you, as I know a certain lady is engaged to a -certain dinner party, and that you are free. There will only be one -other, our old pal at the Korea, Jack Seward. He's coming, too, and -we both want to mingle our weeps over the wine cup, and to drink a -health with all our hearts to the happiest man in all the wide -world, who has won the noblest heart that God has made and best -worth winning. We promise you a hearty welcome, and a loving -greeting, and a health as true as your own right hand. We shall -both swear to leave you at home if you drink too deep to a certain -pair of eyes. Come! - -Yours, as ever and always, - -Quincey P. Morris - - - - - -TELEGRAM FROM ARTHUR HOLMWOOD TO QUINCEY P. MORRIS - -26 May - - -Count me in every time. I bear messages which will make both -your ears tingle. - -Art - - - - -CHAPTER 6 - - -MINA MURRAY'S JOURNAL - -24 July. Whitby.--Lucy met me at the station, looking sweeter and -lovelier than ever, and we drove up to the house at the Crescent in -which they have rooms. This is a lovely place. The little river, the -Esk, runs through a deep valley, which broadens out as it comes near -the harbour. A great viaduct runs across, with high piers, through -which the view seems somehow further away than it really is. The -valley is beautifully green, and it is so steep that when you are on -the high land on either side you look right across it, unless you are -near enough to see down. The houses of the old town--the side away -from us, are all red-roofed, and seem piled up one over the other -anyhow, like the pictures we see of Nuremberg. Right over the town is -the ruin of Whitby Abbey, which was sacked by the Danes, and which is -the scene of part of "Marmion," where the girl was built up in the -wall. It is a most noble ruin, of immense size, and full of beautiful -and romantic bits. There is a legend that a white lady is seen in one -of the windows. Between it and the town there is another church, the -parish one, round which is a big graveyard, all full of tombstones. -This is to my mind the nicest spot in Whitby, for it lies right over -the town, and has a full view of the harbour and all up the bay to -where the headland called Kettleness stretches out into the sea. It -descends so steeply over the harbour that part of the bank has fallen -away, and some of the graves have been destroyed. - -In one place part of the stonework of the graves stretches out over -the sandy pathway far below. There are walks, with seats beside them, -through the churchyard, and people go and sit there all day long -looking at the beautiful view and enjoying the breeze. - -I shall come and sit here often myself and work. Indeed, I am writing -now, with my book on my knee, and listening to the talk of three old -men who are sitting beside me. They seem to do nothing all day but -sit here and talk. - -The harbour lies below me, with, on the far side, one long granite -wall stretching out into the sea, with a curve outwards at the end of -it, in the middle of which is a lighthouse. A heavy seawall runs -along outside of it. On the near side, the seawall makes an elbow -crooked inversely, and its end too has a lighthouse. Between the two -piers there is a narrow opening into the harbour, which then suddenly -widens. - -It is nice at high water, but when the tide is out it shoals away to -nothing, and there is merely the stream of the Esk, running between -banks of sand, with rocks here and there. Outside the harbour on this -side there rises for about half a mile a great reef, the sharp of -which runs straight out from behind the south lighthouse. At the end -of it is a buoy with a bell, which swings in bad weather, and sends in -a mournful sound on the wind. - -They have a legend here that when a ship is lost bells are heard out at -sea. I must ask the old man about this. He is coming this way . . . - -He is a funny old man. He must be awfully old, for his face is -gnarled and twisted like the bark of a tree. He tells me that he is -nearly a hundred, and that he was a sailor in the Greenland fishing -fleet when Waterloo was fought. He is, I am afraid, a very sceptical -person, for when I asked him about the bells at sea and the White Lady -at the abbey he said very brusquely, - -"I wouldn't fash masel' about them, miss. Them things be all wore -out. Mind, I don't say that they never was, but I do say that they -wasn't in my time. They be all very well for comers and trippers, an' -the like, but not for a nice young lady like you. Them feet-folks -from York and Leeds that be always eatin' cured herrin's and drinkin' -tea an' lookin' out to buy cheap jet would creed aught. I wonder -masel' who'd be bothered tellin' lies to them, even the newspapers, -which is full of fool-talk." - -I thought he would be a good person to learn interesting things from, -so I asked him if he would mind telling me something about the whale -fishing in the old days. He was just settling himself to begin when -the clock struck six, whereupon he laboured to get up, and said, - -"I must gang ageeanwards home now, miss. My grand-daughter doesn't -like to be kept waitin' when the tea is ready, for it takes me time to -crammle aboon the grees, for there be a many of 'em, and miss, I lack -belly-timber sairly by the clock." - -He hobbled away, and I could see him hurrying, as well as he could, -down the steps. The steps are a great feature on the place. They -lead from the town to the church, there are hundreds of them, I do not -know how many, and they wind up in a delicate curve. The slope is so -gentle that a horse could easily walk up and down them. - -I think they must originally have had something to do with the abbey. -I shall go home too. Lucy went out, visiting with her mother, and as -they were only duty calls, I did not go. - - -1 August.--I came up here an hour ago with Lucy, and we had a most -interesting talk with my old friend and the two others who always come -and join him. He is evidently the Sir Oracle of them, and I should -think must have been in his time a most dictatorial person. - -He will not admit anything, and down faces everybody. If he can't -out-argue them he bullies them, and then takes their silence for -agreement with his views. - -Lucy was looking sweetly pretty in her white lawn frock. She has got -a beautiful colour since she has been here. - -I noticed that the old men did not lose any time in coming and sitting -near her when we sat down. She is so sweet with old people, I think -they all fell in love with her on the spot. Even my old man succumbed -and did not contradict her, but gave me double share instead. I got -him on the subject of the legends, and he went off at once into a sort -of sermon. I must try to remember it and put it down. - -"It be all fool-talk, lock, stock, and barrel, that's what it be and -nowt else. These bans an' wafts an' boh-ghosts an' bar-guests an' -bogles an' all anent them is only fit to set bairns an' dizzy women -a'belderin'. They be nowt but air-blebs. They, an' all grims an' signs -an' warnin's, be all invented by parsons an' illsome berk-bodies an' -railway touters to skeer an' scunner hafflin's, an' to get folks to do -somethin' that they don't other incline to. It makes me ireful to -think o' them. Why, it's them that, not content with printin' lies on -paper an' preachin' them out of pulpits, does want to be cuttin' them -on the tombstones. Look here all around you in what airt ye will. All -them steans, holdin' up their heads as well as they can out of their -pride, is acant, simply tumblin' down with the weight o' the lies -wrote on them, 'Here lies the body' or 'Sacred to the memory' wrote on -all of them, an' yet in nigh half of them there bean't no bodies at -all, an' the memories of them bean't cared a pinch of snuff about, -much less sacred. Lies all of them, nothin' but lies of one kind or -another! My gog, but it'll be a quare scowderment at the Day of -Judgment when they come tumblin' up in their death-sarks, all jouped -together an' trying' to drag their tombsteans with them to prove how -good they was, some of them trimmlin' an' dithering, with their hands -that dozzened an' slippery from lyin' in the sea that they can't even -keep their gurp o' them." - -I could see from the old fellow's self-satisfied air and the way in -which he looked round for the approval of his cronies that he was -"showing off," so I put in a word to keep him going. - -"Oh, Mr. Swales, you can't be serious. Surely these tombstones are -not all wrong?" - -"Yabblins! There may be a poorish few not wrong, savin' where they -make out the people too good, for there be folk that do think a -balm-bowl be like the sea, if only it be their own. The whole thing -be only lies. Now look you here. You come here a stranger, an' you -see this kirkgarth." - -I nodded, for I thought it better to assent, though I did not quite -understand his dialect. I knew it had something to do with the -church. - -He went on, "And you consate that all these steans be aboon folk that -be haped here, snod an' snog?" I assented again. "Then that be just -where the lie comes in. Why, there be scores of these laybeds that be -toom as old Dun's 'baccabox on Friday night." - -He nudged one of his companions, and they all laughed. "And, my gog! -How could they be otherwise? Look at that one, the aftest abaft the -bier-bank, read it!" - -I went over and read, "Edward Spencelagh, master mariner, murdered by -pirates off the coast of Andres, April, 1854, age 30." When I came -back Mr. Swales went on, - -"Who brought him home, I wonder, to hap him here? Murdered off the -coast of Andres! An' you consated his body lay under! Why, I could -name ye a dozen whose bones lie in the Greenland seas above," he -pointed northwards, "or where the currants may have drifted them. -There be the steans around ye. Ye can, with your young eyes, read the -small print of the lies from here. This Braithwaite Lowery, I knew -his father, lost in the Lively off Greenland in '20, or Andrew -Woodhouse, drowned in the same seas in 1777, or John Paxton, drowned -off Cape Farewell a year later, or old John Rawlings, whose -grandfather sailed with me, drowned in the Gulf of Finland in '50. Do -ye think that all these men will have to make a rush to Whitby when -the trumpet sounds? I have me antherums aboot it! I tell ye that -when they got here they'd be jommlin' and jostlin' one another that -way that it 'ud be like a fight up on the ice in the old days, when -we'd be at one another from daylight to dark, an' tryin' to tie up our -cuts by the aurora borealis." This was evidently local pleasantry, for -the old man cackled over it, and his cronies joined in with gusto. - -"But," I said, "surely you are not quite correct, for you start on the -assumption that all the poor people, or their spirits, will have to -take their tombstones with them on the Day of Judgment. Do you think -that will be really necessary?" - -"Well, what else be they tombstones for? Answer me that, miss!" - -"To please their relatives, I suppose." - -"To please their relatives, you suppose!" This he said with intense -scorn. "How will it pleasure their relatives to know that lies is -wrote over them, and that everybody in the place knows that they be -lies?" - -He pointed to a stone at our feet which had been laid down as a slab, -on which the seat was rested, close to the edge of the cliff. "Read -the lies on that thruff-stone," he said. - -The letters were upside down to me from where I sat, but Lucy was more -opposite to them, so she leant over and read, "Sacred to the memory of -George Canon, who died, in the hope of a glorious resurrection, on -July 29, 1873, falling from the rocks at Kettleness. This tomb was -erected by his sorrowing mother to her dearly beloved son. 'He was the -only son of his mother, and she was a widow.' Really, Mr. Swales, I -don't see anything very funny in that!" She spoke her comment very -gravely and somewhat severely. - -"Ye don't see aught funny! Ha-ha! But that's because ye don't gawm -the sorrowin' mother was a hell-cat that hated him because he was -acrewk'd, a regular lamiter he was, an' he hated her so that he -committed suicide in order that she mightn't get an insurance she put -on his life. He blew nigh the top of his head off with an old musket -that they had for scarin' crows with. 'Twarn't for crows then, for it -brought the clegs and the dowps to him. That's the way he fell off -the rocks. And, as to hopes of a glorious resurrection, I've often -heard him say masel' that he hoped he'd go to hell, for his mother was -so pious that she'd be sure to go to heaven, an' he didn't want to -addle where she was. Now isn't that stean at any rate," he hammered -it with his stick as he spoke, "a pack of lies? And won't it make -Gabriel keckle when Geordie comes pantin' ut the grees with the -tompstean balanced on his hump, and asks to be took as evidence!" - -I did not know what to say, but Lucy turned the conversation as she -said, rising up, "Oh, why did you tell us of this? It is my favourite -seat, and I cannot leave it, and now I find I must go on sitting over -the grave of a suicide." - -"That won't harm ye, my pretty, an' it may make poor Geordie gladsome -to have so trim a lass sittin' on his lap. That won't hurt ye. Why, -I've sat here off an' on for nigh twenty years past, an' it hasn't -done me no harm. Don't ye fash about them as lies under ye, or that -doesn' lie there either! It'll be time for ye to be getting scart -when ye see the tombsteans all run away with, and the place as bare as -a stubble-field. There's the clock, and I must gang. My service to -ye, ladies!" And off he hobbled. - -Lucy and I sat awhile, and it was all so beautiful before us that we -took hands as we sat, and she told me all over again about Arthur and -their coming marriage. That made me just a little heart-sick, for I -haven't heard from Jonathan for a whole month. - - -The same day. I came up here alone, for I am very sad. There was no -letter for me. I hope there cannot be anything the matter with -Jonathan. The clock has just struck nine. I see the lights scattered -all over the town, sometimes in rows where the streets are, and -sometimes singly. They run right up the Esk and die away in the curve -of the valley. To my left the view is cut off by a black line of roof -of the old house next to the abbey. The sheep and lambs are bleating -in the fields away behind me, and there is a clatter of donkeys' hoofs -up the paved road below. The band on the pier is playing a harsh -waltz in good time, and further along the quay there is a Salvation -Army meeting in a back street. Neither of the bands hears the other, -but up here I hear and see them both. I wonder where Jonathan is and -if he is thinking of me! I wish he were here. - - - -DR. SEWARD'S DIARY - -5 June.--The case of Renfield grows more interesting the more I get to -understand the man. He has certain qualities very largely developed, -selfishness, secrecy, and purpose. - -I wish I could get at what is the object of the latter. He seems to -have some settled scheme of his own, but what it is I do not know. -His redeeming quality is a love of animals, though, indeed, he has -such curious turns in it that I sometimes imagine he is only -abnormally cruel. His pets are of odd sorts. - -Just now his hobby is catching flies. He has at present such a -quantity that I have had myself to expostulate. To my astonishment, -he did not break out into a fury, as I expected, but took the matter -in simple seriousness. He thought for a moment, and then said, "May I -have three days? I shall clear them away." Of course, I said that -would do. I must watch him. - - -18 June.--He has turned his mind now to spiders, and has got several -very big fellows in a box. He keeps feeding them his flies, and the -number of the latter is becoming sensibly diminished, although he has -used half his food in attracting more flies from outside to his room. - - -1 July.--His spiders are now becoming as great a nuisance as his -flies, and today I told him that he must get rid of them. - -He looked very sad at this, so I said that he must some of them, at -all events. He cheerfully acquiesced in this, and I gave him the same -time as before for reduction. - -He disgusted me much while with him, for when a horrid blowfly, -bloated with some carrion food, buzzed into the room, he caught it, -held it exultantly for a few moments between his finger and thumb, and -before I knew what he was going to do, put it in his mouth and ate it. - -I scolded him for it, but he argued quietly that it was very good and -very wholesome, that it was life, strong life, and gave life to him. -This gave me an idea, or the rudiment of one. I must watch how he -gets rid of his spiders. - -He has evidently some deep problem in his mind, for he keeps a little -notebook in which he is always jotting down something. Whole pages of -it are filled with masses of figures, generally single numbers added -up in batches, and then the totals added in batches again, as though -he were focussing some account, as the auditors put it. - - -8 July.--There is a method in his madness, and the rudimentary idea in -my mind is growing. It will be a whole idea soon, and then, oh, -unconscious cerebration, you will have to give the wall to your -conscious brother. - -I kept away from my friend for a few days, so that I might notice if -there were any change. Things remain as they were except that he has -parted with some of his pets and got a new one. - -He has managed to get a sparrow, and has already partially tamed it. -His means of taming is simple, for already the spiders have -diminished. Those that do remain, however, are well fed, for he still -brings in the flies by tempting them with his food. - -19 July--We are progressing. My friend has now a whole colony of -sparrows, and his flies and spiders are almost obliterated. When I -came in he ran to me and said he wanted to ask me a great favour, a -very, very great favour. And as he spoke, he fawned on me like a dog. - -I asked him what it was, and he said, with a sort of rapture in his -voice and bearing, "A kitten, a nice, little, sleek playful kitten, -that I can play with, and teach, and feed, and feed, and feed!" - -I was not unprepared for this request, for I had noticed how his pets -went on increasing in size and vivacity, but I did not care that his -pretty family of tame sparrows should be wiped out in the same manner -as the flies and spiders. So I said I would see about it, and asked -him if he would not rather have a cat than a kitten. - -His eagerness betrayed him as he answered, "Oh, yes, I would like a -cat! I only asked for a kitten lest you should refuse me a cat. No -one would refuse me a kitten, would they?" - -I shook my head, and said that at present I feared it would not be -possible, but that I would see about it. His face fell, and I could -see a warning of danger in it, for there was a sudden fierce, sidelong -look which meant killing. The man is an undeveloped homicidal -maniac. I shall test him with his present craving and see how it will -work out, then I shall know more. - - -10 pm.--I have visited him again and found him sitting in a corner -brooding. When I came in he threw himself on his knees before me and -implored me to let him have a cat, that his salvation depended upon -it. - -I was firm, however, and told him that he could not have it, whereupon -he went without a word, and sat down, gnawing his fingers, in the -corner where I had found him. I shall see him in the morning early. - - -20 July.--Visited Renfield very early, before attendant went his -rounds. Found him up and humming a tune. He was spreading out his -sugar, which he had saved, in the window, and was manifestly beginning -his fly catching again, and beginning it cheerfully and with a good -grace. - -I looked around for his birds, and not seeing them, asked him where -they were. He replied, without turning round, that they had all flown -away. There were a few feathers about the room and on his pillow a -drop of blood. I said nothing, but went and told the keeper to report -to me if there were anything odd about him during the day. - - -11 am.--The attendant has just been to see me to say that Renfield has -been very sick and has disgorged a whole lot of feathers. "My belief -is, doctor," he said, "that he has eaten his birds, and that he just -took and ate them raw!" - - -11 pm.--I gave Renfield a strong opiate tonight, enough to make even -him sleep, and took away his pocketbook to look at it. The thought -that has been buzzing about my brain lately is complete, and the -theory proved. - -My homicidal maniac is of a peculiar kind. I shall have to invent a -new classification for him, and call him a zoophagous (life-eating) -maniac. What he desires is to absorb as many lives as he can, and he -has laid himself out to achieve it in a cumulative way. He gave many -flies to one spider and many spiders to one bird, and then wanted a -cat to eat the many birds. What would have been his later steps? - -It would almost be worth while to complete the experiment. It might -be done if there were only a sufficient cause. Men sneered at -vivisection, and yet look at its results today! Why not advance -science in its most difficult and vital aspect, the knowledge of the -brain? - -Had I even the secret of one such mind, did I hold the key to the -fancy of even one lunatic, I might advance my own branch of science to -a pitch compared with which Burdon-Sanderson's physiology or Ferrier's -brain knowledge would be as nothing. If only there were a sufficient -cause! I must not think too much of this, or I may be tempted. A -good cause might turn the scale with me, for may not I too be of an -exceptional brain, congenitally? - -How well the man reasoned. Lunatics always do within their own scope. -I wonder at how many lives he values a man, or if at only one. He has -closed the account most accurately, and today begun a new record. How -many of us begin a new record with each day of our lives? - -To me it seems only yesterday that my whole life ended with my new -hope, and that truly I began a new record. So it shall be until the -Great Recorder sums me up and closes my ledger account with a balance -to profit or loss. - -Oh, Lucy, Lucy, I cannot be angry with you, nor can I be angry with my -friend whose happiness is yours, but I must only wait on hopeless and -work. Work! Work! - -If I could have as strong a cause as my poor mad friend there, a good, -unselfish cause to make me work, that would be indeed happiness. - - - -MINA MURRAY'S JOURNAL - -26 July.--I am anxious, and it soothes me to express myself here. It -is like whispering to one's self and listening at the same time. And -there is also something about the shorthand symbols that makes it -different from writing. I am unhappy about Lucy and about Jonathan. -I had not heard from Jonathan for some time, and was very concerned, -but yesterday dear Mr. Hawkins, who is always so kind, sent me a -letter from him. I had written asking him if he had heard, and he -said the enclosed had just been received. It is only a line dated -from Castle Dracula, and says that he is just starting for home. That -is not like Jonathan. I do not understand it, and it makes me uneasy. - -Then, too, Lucy, although she is so well, has lately taken to her old -habit of walking in her sleep. Her mother has spoken to me about it, -and we have decided that I am to lock the door of our room every -night. - -Mrs. Westenra has got an idea that sleep-walkers always go out on -roofs of houses and along the edges of cliffs and then get suddenly -wakened and fall over with a despairing cry that echoes all over the -place. - -Poor dear, she is naturally anxious about Lucy, and she tells me that -her husband, Lucy's father, had the same habit, that he would get up -in the night and dress himself and go out, if he were not stopped. - -Lucy is to be married in the autumn, and she is already planning out -her dresses and how her house is to be arranged. I sympathise with -her, for I do the same, only Jonathan and I will start in life in a -very simple way, and shall have to try to make both ends meet. - -Mr. Holmwood, he is the Hon. Arthur Holmwood, only son of Lord -Godalming, is coming up here very shortly, as soon as he can leave -town, for his father is not very well, and I think dear Lucy is -counting the moments till he comes. - -She wants to take him up in the seat on the churchyard cliff and show -him the beauty of Whitby. I daresay it is the waiting which disturbs -her. She will be all right when he arrives. - - -27 July.--No news from Jonathan. I am getting quite uneasy about him, -though why I should I do not know, but I do wish that he would write, -if it were only a single line. - -Lucy walks more than ever, and each night I am awakened by her moving -about the room. Fortunately, the weather is so hot that she cannot -get cold. But still, the anxiety and the perpetually being awakened -is beginning to tell on me, and I am getting nervous and wakeful -myself. Thank God, Lucy's health keeps up. Mr. Holmwood has been -suddenly called to Ring to see his father, who has been taken -seriously ill. Lucy frets at the postponement of seeing him, but it -does not touch her looks. She is a trifle stouter, and her cheeks are -a lovely rose-pink. She has lost the anemic look which she had. I -pray it will all last. - - -3 August.--Another week gone by, and no news from Jonathan, not even -to Mr. Hawkins, from whom I have heard. Oh, I do hope he is not ill. -He surely would have written. I look at that last letter of his, but -somehow it does not satisfy me. It does not read like him, and yet it -is his writing. There is no mistake of that. - -Lucy has not walked much in her sleep the last week, but there is an -odd concentration about her which I do not understand, even in her -sleep she seems to be watching me. She tries the door, and finding it -locked, goes about the room searching for the key. - - -6 August.--Another three days, and no news. This suspense is getting -dreadful. If I only knew where to write to or where to go to, I -should feel easier. But no one has heard a word of Jonathan since -that last letter. I must only pray to God for patience. - -Lucy is more excitable than ever, but is otherwise well. Last night -was very threatening, and the fishermen say that we are in for a -storm. I must try to watch it and learn the weather signs. - -Today is a gray day, and the sun as I write is hidden in thick clouds, -high over Kettleness. Everything is gray except the green grass, -which seems like emerald amongst it, gray earthy rock, gray clouds, -tinged with the sunburst at the far edge, hang over the gray sea, into -which the sandpoints stretch like gray figures. The sea is tumbling -in over the shallows and the sandy flats with a roar, muffled in the -sea-mists drifting inland. The horizon is lost in a gray mist. All -vastness, the clouds are piled up like giant rocks, and there is a -'brool' over the sea that sounds like some passage of doom. Dark -figures are on the beach here and there, sometimes half shrouded in -the mist, and seem 'men like trees walking'. The fishing boats are -racing for home, and rise and dip in the ground swell as they sweep -into the harbour, bending to the scuppers. Here comes old Mr. Swales. -He is making straight for me, and I can see, by the way he lifts his -hat, that he wants to talk. - -I have been quite touched by the change in the poor old man. When he -sat down beside me, he said in a very gentle way, "I want to say -something to you, miss." - -I could see he was not at ease, so I took his poor old wrinkled hand in -mine and asked him to speak fully. - -So he said, leaving his hand in mine, "I'm afraid, my deary, that I -must have shocked you by all the wicked things I've been sayin' about -the dead, and such like, for weeks past, but I didn't mean them, and I -want ye to remember that when I'm gone. We aud folks that be daffled, -and with one foot abaft the krok-hooal, don't altogether like to think -of it, and we don't want to feel scart of it, and that's why I've took -to makin' light of it, so that I'd cheer up my own heart a bit. But, -Lord love ye, miss, I ain't afraid of dyin', not a bit, only I don't -want to die if I can help it. My time must be nigh at hand now, for I -be aud, and a hundred years is too much for any man to expect. And -I'm so nigh it that the Aud Man is already whettin' his scythe. Ye -see, I can't get out o' the habit of caffin' about it all at once. -The chafts will wag as they be used to. Some day soon the Angel of -Death will sound his trumpet for me. But don't ye dooal an' greet, my -deary!"--for he saw that I was crying--"if he should come this very -night I'd not refuse to answer his call. For life be, after all, only -a waitin' for somethin' else than what we're doin', and death be all -that we can rightly depend on. But I'm content, for it's comin' to -me, my deary, and comin' quick. It may be comin' while we be lookin' -and wonderin'. Maybe it's in that wind out over the sea that's -bringin' with it loss and wreck, and sore distress, and sad hearts. -Look! Look!" he cried suddenly. "There's something in that wind and -in the hoast beyont that sounds, and looks, and tastes, and smells -like death. It's in the air. I feel it comin'. Lord, make me answer -cheerful, when my call comes!" He held up his arms devoutly, and -raised his hat. His mouth moved as though he were praying. After a -few minutes' silence, he got up, shook hands with me, and blessed me, -and said goodbye, and hobbled off. It all touched me, and upset me -very much. - -I was glad when the coastguard came along, with his spyglass under his -arm. He stopped to talk with me, as he always does, but all the time -kept looking at a strange ship. - -"I can't make her out," he said. "She's a Russian, by the look of -her. But she's knocking about in the queerest way. She doesn't know -her mind a bit. She seems to see the storm coming, but can't decide -whether to run up north in the open, or to put in here. Look there -again! She is steered mighty strangely, for she doesn't mind the hand -on the wheel, changes about with every puff of wind. We'll hear more -of her before this time tomorrow." - - - - -CHAPTER 7 - - -CUTTING FROM "THE DAILYGRAPH", 8 AUGUST - - -(PASTED IN MINA MURRAY'S JOURNAL) - - -From a correspondent. - -Whitby. - -One of the greatest and suddenest storms on record has just been -experienced here, with results both strange and unique. The weather -had been somewhat sultry, but not to any degree uncommon in the -month of August. Saturday evening was as fine as was ever known, -and the great body of holiday-makers laid out yesterday for visits -to Mulgrave Woods, Robin Hood's Bay, Rig Mill, Runswick, Staithes, -and the various trips in the neighborhood of Whitby. The steamers -Emma and Scarborough made trips up and down the coast, and there was -an unusual amount of 'tripping' both to and from Whitby. The day -was unusually fine till the afternoon, when some of the gossips who -frequent the East Cliff churchyard, and from the commanding eminence -watch the wide sweep of sea visible to the north and east, called -attention to a sudden show of 'mares tails' high in the sky to the -northwest. The wind was then blowing from the south-west in the -mild degree which in barometrical language is ranked 'No. 2, light -breeze.' - -The coastguard on duty at once made report, and one old fisherman, -who for more than half a century has kept watch on weather signs -from the East Cliff, foretold in an emphatic manner the coming of a -sudden storm. The approach of sunset was so very beautiful, so -grand in its masses of splendidly coloured clouds, that there was -quite an assemblage on the walk along the cliff in the old -churchyard to enjoy the beauty. Before the sun dipped below the -black mass of Kettleness, standing boldly athwart the western sky, -its downward way was marked by myriad clouds of every sunset colour, -flame, purple, pink, green, violet, and all the tints of gold, with -here and there masses not large, but of seemingly absolute -blackness, in all sorts of shapes, as well outlined as colossal -silhouettes. The experience was not lost on the painters, and -doubtless some of the sketches of the 'Prelude to the Great Storm' -will grace the R. A and R. I. walls in May next. - -More than one captain made up his mind then and there that his -'cobble' or his 'mule', as they term the different classes of boats, -would remain in the harbour till the storm had passed. The wind -fell away entirely during the evening, and at midnight there was a -dead calm, a sultry heat, and that prevailing intensity which, on -the approach of thunder, affects persons of a sensitive nature. - -There were but few lights in sight at sea, for even the coasting -steamers, which usually hug the shore so closely, kept well to -seaward, and but few fishing boats were in sight. The only sail -noticeable was a foreign schooner with all sails set, which was -seemingly going westwards. The foolhardiness or ignorance of her -officers was a prolific theme for comment whilst she remained in -sight, and efforts were made to signal her to reduce sail in the -face of her danger. Before the night shut down she was seen with -sails idly flapping as she gently rolled on the undulating swell of -the sea. - -"As idle as a painted ship upon a painted ocean." - -Shortly before ten o'clock the stillness of the air grew quite -oppressive, and the silence was so marked that the bleating of a -sheep inland or the barking of a dog in the town was distinctly -heard, and the band on the pier, with its lively French air, was -like a dischord in the great harmony of nature's silence. A little -after midnight came a strange sound from over the sea, and high -overhead the air began to carry a strange, faint, hollow booming. - -Then without warning the tempest broke. With a rapidity which, at -the time, seemed incredible, and even afterwards is impossible to -realize, the whole aspect of nature at once became convulsed. The -waves rose in growing fury, each over-topping its fellow, till in a -very few minutes the lately glassy sea was like a roaring and -devouring monster. White-crested waves beat madly on the level -sands and rushed up the shelving cliffs. Others broke over the -piers, and with their spume swept the lanthorns of the lighthouses -which rise from the end of either pier of Whitby Harbour. - -The wind roared like thunder, and blew with such force that it was -with difficulty that even strong men kept their feet, or clung with -grim clasp to the iron stanchions. It was found necessary to clear -the entire pier from the mass of onlookers, or else the fatalities -of the night would have increased manifold. To add to the -difficulties and dangers of the time, masses of sea-fog came -drifting inland. White, wet clouds, which swept by in ghostly -fashion, so dank and damp and cold that it needed but little effort -of imagination to think that the spirits of those lost at sea were -touching their living brethren with the clammy hands of death, and -many a one shuddered as the wreaths of sea-mist swept by. - -At times the mist cleared, and the sea for some distance could be -seen in the glare of the lightning, which came thick and fast, -followed by such peals of thunder that the whole sky overhead seemed -trembling under the shock of the footsteps of the storm. - -Some of the scenes thus revealed were of immeasurable grandeur and -of absorbing interest. The sea, running mountains high, threw -skywards with each wave mighty masses of white foam, which the -tempest seemed to snatch at and whirl away into space. Here and -there a fishing boat, with a rag of sail, running madly for shelter -before the blast, now and again the white wings of a storm-tossed -seabird. On the summit of the East Cliff the new searchlight was -ready for experiment, but had not yet been tried. The officers in -charge of it got it into working order, and in the pauses of -onrushing mist swept with it the surface of the sea. Once or twice -its service was most effective, as when a fishing boat, with gunwale -under water, rushed into the harbour, able, by the guidance of the -sheltering light, to avoid the danger of dashing against the piers. -As each boat achieved the safety of the port there was a shout of -joy from the mass of people on the shore, a shout which for a moment -seemed to cleave the gale and was then swept away in its rush. - -Before long the searchlight discovered some distance away a schooner -with all sails set, apparently the same vessel which had been -noticed earlier in the evening. The wind had by this time backed to -the east, and there was a shudder amongst the watchers on the cliff -as they realized the terrible danger in which she now was. - -Between her and the port lay the great flat reef on which so many -good ships have from time to time suffered, and, with the wind -blowing from its present quarter, it would be quite impossible that -she should fetch the entrance of the harbour. - -It was now nearly the hour of high tide, but the waves were so great -that in their troughs the shallows of the shore were almost visible, -and the schooner, with all sails set, was rushing with such speed -that, in the words of one old salt, "she must fetch up somewhere, if -it was only in hell". Then came another rush of sea-fog, greater -than any hitherto, a mass of dank mist, which seemed to close on all -things like a gray pall, and left available to men only the organ of -hearing, for the roar of the tempest, and the crash of the thunder, -and the booming of the mighty billows came through the damp oblivion -even louder than before. The rays of the searchlight were kept fixed -on the harbour mouth across the East Pier, where the shock was -expected, and men waited breathless. - -The wind suddenly shifted to the northeast, and the remnant of the -sea fog melted in the blast. And then, mirabile dictu, between the -piers, leaping from wave to wave as it rushed at headlong speed, -swept the strange schooner before the blast, with all sail set, and -gained the safety of the harbour. The searchlight followed her, and -a shudder ran through all who saw her, for lashed to the helm was a -corpse, with drooping head, which swung horribly to and fro at each -motion of the ship. No other form could be seen on the deck at all. - -A great awe came on all as they realised that the ship, as if by a -miracle, had found the harbour, unsteered save by the hand of a dead -man! However, all took place more quickly than it takes to write -these words. The schooner paused not, but rushing across the -harbour, pitched herself on that accumulation of sand and gravel -washed by many tides and many storms into the southeast corner of -the pier jutting under the East Cliff, known locally as Tate Hill -Pier. - -There was of course a considerable concussion as the vessel drove up -on the sand heap. Every spar, rope, and stay was strained, and some -of the 'top-hammer' came crashing down. But, strangest of all, the -very instant the shore was touched, an immense dog sprang up on deck -from below, as if shot up by the concussion, and running forward, -jumped from the bow on the sand. - -Making straight for the steep cliff, where the churchyard hangs over -the laneway to the East Pier so steeply that some of the flat -tombstones, thruffsteans or through-stones, as they call them in -Whitby vernacular, actually project over where the sustaining cliff -has fallen away, it disappeared in the darkness, which seemed -intensified just beyond the focus of the searchlight. - -It so happened that there was no one at the moment on Tate Hill -Pier, as all those whose houses are in close proximity were either -in bed or were out on the heights above. Thus the coastguard on -duty on the eastern side of the harbour, who at once ran down to the -little pier, was the first to climb aboard. The men working the -searchlight, after scouring the entrance of the harbour without -seeing anything, then turned the light on the derelict and kept it -there. The coastguard ran aft, and when he came beside the wheel, -bent over to examine it, and recoiled at once as though under some -sudden emotion. This seemed to pique general curiosity, and quite a -number of people began to run. - -It is a good way round from the West Cliff by the Draw-bridge to -Tate Hill Pier, but your correspondent is a fairly good runner, and -came well ahead of the crowd. When I arrived, however, I found -already assembled on the pier a crowd, whom the coastguard and -police refused to allow to come on board. By the courtesy of the -chief boatman, I was, as your correspondent, permitted to climb on -deck, and was one of a small group who saw the dead seaman whilst -actually lashed to the wheel. - -It was no wonder that the coastguard was surprised, or even awed, -for not often can such a sight have been seen. The man was simply -fastened by his hands, tied one over the other, to a spoke of the -wheel. Between the inner hand and the wood was a crucifix, the set -of beads on which it was fastened being around both wrists and -wheel, and all kept fast by the binding cords. The poor fellow may -have been seated at one time, but the flapping and buffeting of the -sails had worked through the rudder of the wheel and had dragged him -to and fro, so that the cords with which he was tied had cut the -flesh to the bone. - -Accurate note was made of the state of things, and a doctor, Surgeon -J. M. Caffyn, of 33, East Elliot Place, who came immediately after -me, declared, after making examination, that the man must have been -dead for quite two days. - -In his pocket was a bottle, carefully corked, empty save for -a little roll of paper, which proved to be the addendum to -the log. - -The coastguard said the man must have tied up his own hands, -fastening the knots with his teeth. The fact that a coastguard was -the first on board may save some complications later on, in the -Admiralty Court, for coastguards cannot claim the salvage which is -the right of the first civilian entering on a derelict. Already, -however, the legal tongues are wagging, and one young law student is -loudly asserting that the rights of the owner are already completely -sacrificed, his property being held in contravention of the statues -of mortmain, since the tiller, as emblemship, if not proof, of -delegated possession, is held in a dead hand. - -It is needless to say that the dead steersman has been reverently -removed from the place where he held his honourable watch and ward -till death, a steadfastness as noble as that of the young -Casabianca, and placed in the mortuary to await inquest. - -Already the sudden storm is passing, and its fierceness is -abating. Crowds are scattering backward, and the sky is -beginning to redden over the Yorkshire wolds. - -I shall send, in time for your next issue, further details -of the derelict ship which found her way so miraculously -into harbour in the storm. - - -9 August.--The sequel to the strange arrival of the derelict in the -storm last night is almost more startling than the thing itself. It -turns out that the schooner is Russian from Varna, and is called the -Demeter. She is almost entirely in ballast of silver sand, with -only a small amount of cargo, a number of great wooden boxes filled -with mould. - -This cargo was consigned to a Whitby solicitor, Mr. S.F. Billington, -of 7, The Crescent, who this morning went aboard and took formal -possession of the goods consigned to him. - -The Russian consul, too, acting for the charter-party, took formal -possession of the ship, and paid all harbour dues, etc. - -Nothing is talked about here today except the strange coincidence. -The officials of the Board of Trade have been most exacting in -seeing that every compliance has been made with existing -regulations. As the matter is to be a 'nine days wonder', they are -evidently determined that there shall be no cause of other -complaint. - -A good deal of interest was abroad concerning the dog which landed -when the ship struck, and more than a few of the members of the -S.P.C.A., which is very strong in Whitby, have tried to befriend the -animal. To the general disappointment, however, it was not to be -found. It seems to have disappeared entirely from the town. It may -be that it was frightened and made its way on to the moors, where it -is still hiding in terror. - -There are some who look with dread on such a possibility, lest later -on it should in itself become a danger, for it is evidently a fierce -brute. Early this morning a large dog, a half-bred mastiff -belonging to a coal merchant close to Tate Hill Pier, was found dead -in the roadway opposite its master's yard. It had been fighting, -and manifestly had had a savage opponent, for its throat was torn -away, and its belly was slit open as if with a savage claw. - -Later.--By the kindness of the Board of Trade inspector, I have been -permitted to look over the log book of the Demeter, which was in -order up to within three days, but contained nothing of special -interest except as to facts of missing men. The greatest interest, -however, is with regard to the paper found in the bottle, which was -today produced at the inquest. And a more strange narrative than -the two between them unfold it has not been my lot to come across. - -As there is no motive for concealment, I am permitted to use them, -and accordingly send you a transcript, simply omitting technical -details of seamanship and supercargo. It almost seems as though the -captain had been seized with some kind of mania before he had got -well into blue water, and that this had developed persistently -throughout the voyage. Of course my statement must be taken cum -grano, since I am writing from the dictation of a clerk of the -Russian consul, who kindly translated for me, time being short. - - - - LOG OF THE "DEMETER" Varna to Whitby - - - Written 18 July, things so strange happening, that I shall - keep accurate note henceforth till we land. - - - On 6 July we finished taking in cargo, silver sand and boxes - of earth. At noon set sail. East wind, fresh. Crew, five - hands . . . two mates, cook, and myself, (captain). - - - On 11 July at dawn entered Bosphorus. Boarded by Turkish - Customs officers. Backsheesh. All correct. Under way at - 4 p.m. - - - On 12 July through Dardanelles. More Customs officers and - flagboat of guarding squadron. Backsheesh again. Work of - officers thorough, but quick. Want us off soon. At dark - passed into Archipelago. - - - On 13 July passed Cape Matapan. Crew dissatisfied about - something. Seemed scared, but would not speak out. - - - On 14 July was somewhat anxious about crew. Men all steady - fellows, who sailed with me before. Mate could not make out what - was wrong. They only told him there was SOMETHING, and crossed - themselves. Mate lost temper with one of them that day and struck - him. Expected fierce quarrel, but all was quiet. - - - On 16 July mate reported in the morning that one of the - crew, Petrofsky, was missing. Could not account for it. - Took larboard watch eight bells last night, was relieved by - Amramoff, but did not go to bunk. Men more downcast than - ever. All said they expected something of the kind, but - would not say more than there was SOMETHING aboard. Mate - getting very impatient with them. Feared some trouble - ahead. - - - On 17 July, yesterday, one of the men, Olgaren, came to my cabin, - and in an awestruck way confided to me that he thought there was a - strange man aboard the ship. He said that in his watch he had - been sheltering behind the deckhouse, as there was a rain storm, - when he saw a tall, thin man, who was not like any of the crew, - come up the companionway, and go along the deck forward and - disappear. He followed cautiously, but when he got to bows found - no one, and the hatchways were all closed. He was in a panic of - superstitious fear, and I am afraid the panic may spread. To - allay it, I shall today search the entire ship carefully from stem - to stern. - - - Later in the day I got together the whole crew, and told them, as - they evidently thought there was some one in the ship, we would - search from stem to stern. First mate angry, said it was folly, - and to yield to such foolish ideas would demoralise the men, said - he would engage to keep them out of trouble with the handspike. I - let him take the helm, while the rest began a thorough search, all - keeping abreast, with lanterns. We left no corner unsearched. As - there were only the big wooden boxes, there were no odd corners - where a man could hide. Men much relieved when search over, and - went back to work cheerfully. First mate scowled, but said - nothing. - - - 22 July.--Rough weather last three days, and all hands busy - with sails, no time to be frightened. Men seem to have - forgotten their dread. Mate cheerful again, and all on - good terms. Praised men for work in bad weather. Passed - Gibraltar and out through Straits. All well. - - - 24 July.--There seems some doom over this ship. Already a hand - short, and entering the Bay of Biscay with wild weather ahead, and - yet last night another man lost, disappeared. Like the first, he - came off his watch and was not seen again. Men all in a panic of - fear, sent a round robin, asking to have double watch, as they - fear to be alone. Mate angry. Fear there will be some trouble, - as either he or the men will do some violence. - - - 28 July.--Four days in hell, knocking about in a sort of - maelstrom, and the wind a tempest. No sleep for any one. - Men all worn out. Hardly know how to set a watch, since no - one fit to go on. Second mate volunteered to steer and - watch, and let men snatch a few hours sleep. Wind abating, - seas still terrific, but feel them less, as ship is - steadier. - - - 29 July.--Another tragedy. Had single watch tonight, as crew too - tired to double. When morning watch came on deck could find no - one except steersman. Raised outcry, and all came on deck. - Thorough search, but no one found. Are now without second mate, - and crew in a panic. Mate and I agreed to go armed henceforth and - wait for any sign of cause. - - - 30 July.--Last night. Rejoiced we are nearing England. Weather - fine, all sails set. Retired worn out, slept soundly, awakened by - mate telling me that both man of watch and steersman missing. - Only self and mate and two hands left to work ship. - - 1 August.--Two days of fog, and not a sail sighted. Had hoped - when in the English Channel to be able to signal for help or get - in somewhere. Not having power to work sails, have to run before - wind. Dare not lower, as could not raise them again. We seem to - be drifting to some terrible doom. Mate now more demoralised than - either of men. His stronger nature seems to have worked inwardly - against himself. Men are beyond fear, working stolidly and - patiently, with minds made up to worst. They are Russian, he - Roumanian. - - 2 August, midnight.--Woke up from few minutes sleep by hearing a - cry, seemingly outside my port. Could see nothing in fog. Rushed - on deck, and ran against mate. Tells me he heard cry and ran, but - no sign of man on watch. One more gone. Lord, help us! Mate - says we must be past Straits of Dover, as in a moment of fog - lifting he saw North Foreland, just as he heard the man cry out. - If so we are now off in the North Sea, and only God can guide us - in the fog, which seems to move with us, and God seems to have - deserted us. - - - 3 August.--At midnight I went to relieve the man at the - wheel and when I got to it found no one there. The wind - was steady, and as we ran before it there was no yawing. I - dared not leave it, so shouted for the mate. After a few - seconds, he rushed up on deck in his flannels. He looked - wild-eyed and haggard, and I greatly fear his reason has - given way. He came close to me and whispered hoarsely, - with his mouth to my ear, as though fearing the very air - might hear. "It is here. I know it now. On the watch - last night I saw It, like a man, tall and thin, and ghastly - pale. It was in the bows, and looking out. I crept behind - It, and gave it my knife, but the knife went through It, - empty as the air." And as he spoke he took the knife and - drove it savagely into space. Then he went on, "But It is - here, and I'll find It. It is in the hold, perhaps in one - of those boxes. I'll unscrew them one by one and see. You - work the helm." And with a warning look and his finger on - his lip, he went below. There was springing up a choppy - wind, and I could not leave the helm. I saw him come out - on deck again with a tool chest and lantern, and go down - the forward hatchway. He is mad, stark, raving mad, and - it's no use my trying to stop him. He can't hurt those big - boxes, they are invoiced as clay, and to pull them about is - as harmless a thing as he can do. So here I stay and mind - the helm, and write these notes. I can only trust in God - and wait till the fog clears. Then, if I can't steer to - any harbour with the wind that is, I shall cut down sails, - and lie by, and signal for help . . . - - It is nearly all over now. Just as I was beginning to hope - that the mate would come out calmer, for I heard him - knocking away at something in the hold, and work is good - for him, there came up the hatchway a sudden, startled - scream, which made my blood run cold, and up on the deck he - came as if shot from a gun, a raging madman, with his eyes - rolling and his face convulsed with fear. "Save me! Save - me!" he cried, and then looked round on the blanket of fog. - His horror turned to despair, and in a steady voice he - said, "You had better come too, captain, before it is too - late. He is there! I know the secret now. The sea will - save me from Him, and it is all that is left!" Before I - could say a word, or move forward to seize him, he sprang - on the bulwark and deliberately threw himself into the sea. - I suppose I know the secret too, now. It was this madman - who had got rid of the men one by one, and now he has - followed them himself. God help me! How am I to account - for all these horrors when I get to port? When I get to - port! Will that ever be? - - - 4 August.--Still fog, which the sunrise cannot pierce, I - know there is sunrise because I am a sailor, why else I - know not. I dared not go below, I dared not leave the - helm, so here all night I stayed, and in the dimness of the - night I saw it, Him! God, forgive me, but the mate was - right to jump overboard. It was better to die like a man. - To die like a sailor in blue water, no man can object. But - I am captain, and I must not leave my ship. But I shall - baffle this fiend or monster, for I shall tie my hands to - the wheel when my strength begins to fail, and along with - them I shall tie that which He, It, dare not touch. And - then, come good wind or foul, I shall save my soul, and my - honour as a captain. I am growing weaker, and the night is - coming on. If He can look me in the face again, I may not - have time to act. . . If we are wrecked, mayhap this bottle - may be found, and those who find it may understand. If - not . . . well, then all men shall know that I have been - true to my trust. God and the Blessed Virgin and the - Saints help a poor ignorant soul trying to do his duty . . . - - -Of course the verdict was an open one. There is no evidence -to adduce, and whether or not the man himself committed the -murders there is now none to say. The folk here hold almost -universally that the captain is simply a hero, and he is to be -given a public funeral. Already it is arranged that his body -is to be taken with a train of boats up the Esk for a piece -and then brought back to Tate Hill Pier and up the abbey steps, -for he is to be buried in the churchyard on the cliff. The -owners of more than a hundred boats have already given in their -names as wishing to follow him to the grave. - -No trace has ever been found of the great dog, at which there is -much mourning, for, with public opinion in its present state, he -would, I believe, be adopted by the town. Tomorrow will see the -funeral, and so will end this one more 'mystery of the sea'. - - - -MINA MURRAY'S JOURNAL - -8 August.--Lucy was very restless all night, and I too, could not -sleep. The storm was fearful, and as it boomed loudly among the -chimney pots, it made me shudder. When a sharp puff came it seemed to -be like a distant gun. Strangely enough, Lucy did not wake, but she -got up twice and dressed herself. Fortunately, each time I awoke in -time and managed to undress her without waking her, and got her back to -bed. It is a very strange thing, this sleep-walking, for as soon as -her will is thwarted in any physical way, her intention, if there be -any, disappears, and she yields herself almost exactly to the routine -of her life. - -Early in the morning we both got up and went down to the harbour to see -if anything had happened in the night. There were very few people -about, and though the sun was bright, and the air clear and fresh, the -big, grim-looking waves, that seemed dark themselves because the foam -that topped them was like snow, forced themselves in through the mouth -of the harbour, like a bullying man going through a crowd. Somehow I -felt glad that Jonathan was not on the sea last night, but on land. -But, oh, is he on land or sea? Where is he, and how? I am getting -fearfully anxious about him. If I only knew what to do, and could do -anything! - - -10 August.--The funeral of the poor sea captain today was most -touching. Every boat in the harbour seemed to be there, and the coffin -was carried by captains all the way from Tate Hill Pier up to the -churchyard. Lucy came with me, and we went early to our old seat, -whilst the cortege of boats went up the river to the Viaduct and came -down again. We had a lovely view, and saw the procession nearly all -the way. The poor fellow was laid to rest near our seat so that we -stood on it, when the time came and saw everything. - -Poor Lucy seemed much upset. She was restless and uneasy all the time, -and I cannot but think that her dreaming at night is telling on her. -She is quite odd in one thing. She will not admit to me that there is -any cause for restlessness, or if there be, she does not understand it -herself. - -There is an additional cause in that poor Mr. Swales was found dead -this morning on our seat, his neck being broken. He had evidently, as -the doctor said, fallen back in the seat in some sort of fright, for -there was a look of fear and horror on his face that the men said made -them shudder. Poor dear old man! - -Lucy is so sweet and sensitive that she feels influences more acutely -than other people do. Just now she was quite upset by a little thing -which I did not much heed, though I am myself very fond of animals. - -One of the men who came up here often to look for the boats was -followed by his dog. The dog is always with him. They are both quiet -persons, and I never saw the man angry, nor heard the dog bark. During -the service the dog would not come to its master, who was on the seat -with us, but kept a few yards off, barking and howling. Its master -spoke to it gently, and then harshly, and then angrily. But it would -neither come nor cease to make a noise. It was in a fury, with its -eyes savage, and all its hair bristling out like a cat's tail when puss -is on the war path. - -Finally the man too got angry, and jumped down and kicked the dog, and -then took it by the scruff of the neck and half dragged and half threw -it on the tombstone on which the seat is fixed. The moment it touched -the stone the poor thing began to tremble. It did not try to get away, -but crouched down, quivering and cowering, and was in such a pitiable -state of terror that I tried, though without effect, to comfort it. - -Lucy was full of pity, too, but she did not attempt to touch the dog, -but looked at it in an agonised sort of way. I greatly fear that she -is of too super sensitive a nature to go through the world without -trouble. She will be dreaming of this tonight, I am sure. The whole -agglomeration of things, the ship steered into port by a dead man, his -attitude, tied to the wheel with a crucifix and beads, the touching -funeral, the dog, now furious and now in terror, will all afford -material for her dreams. - -I think it will be best for her to go to bed tired out physically, so I -shall take her for a long walk by the cliffs to Robin Hood's Bay and -back. She ought not to have much inclination for sleep-walking then. - - - - -CHAPTER 8 - - -MINA MURRAY'S JOURNAL - -Same day, 11 o'clock P.M.--Oh, but I am tired! If it were not that I -had made my diary a duty I should not open it tonight. We had a lovely -walk. Lucy, after a while, was in gay spirits, owing, I think, to some -dear cows who came nosing towards us in a field close to the -lighthouse, and frightened the wits out of us. I believe we forgot -everything, except of course, personal fear, and it seemed to wipe the -slate clean and give us a fresh start. We had a capital 'severe tea' -at Robin Hood's Bay in a sweet little old-fashioned inn, with a bow -window right over the seaweed-covered rocks of the strand. I believe -we should have shocked the 'New Woman' with our appetites. Men are -more tolerant, bless them! Then we walked home with some, or rather -many, stoppages to rest, and with our hearts full of a constant dread -of wild bulls. - -Lucy was really tired, and we intended to creep off to bed as soon as -we could. The young curate came in, however, and Mrs. Westenra asked -him to stay for supper. Lucy and I had both a fight for it with the -dusty miller. I know it was a hard fight on my part, and I am quite -heroic. I think that some day the bishops must get together and see -about breeding up a new class of curates, who don't take supper, no -matter how hard they may be pressed to, and who will know when girls -are tired. - -Lucy is asleep and breathing softly. She has more colour in her cheeks -than usual, and looks, oh so sweet. If Mr. Holmwood fell in love with -her seeing her only in the drawing room, I wonder what he would say if -he saw her now. Some of the 'New Women' writers will some day start an -idea that men and women should be allowed to see each other asleep -before proposing or accepting. But I suppose the 'New Woman' won't -condescend in future to accept. She will do the proposing herself. And -a nice job she will make of it too! There's some consolation in that. -I am so happy tonight, because dear Lucy seems better. I really -believe she has turned the corner, and that we are over her troubles -with dreaming. I should be quite happy if I only knew if Jonathan . . . -God bless and keep him. - - -11 August.--Diary again. No sleep now, so I may as well write. I am -too agitated to sleep. We have had such an adventure, such an -agonizing experience. I fell asleep as soon as I had closed my diary. -. . . Suddenly I became broad awake, and sat up, with a horrible sense -of fear upon me, and of some feeling of emptiness around me. The room -was dark, so I could not see Lucy's bed. I stole across and felt for -her. The bed was empty. I lit a match and found that she was not in -the room. The door was shut, but not locked, as I had left it. I feared -to wake her mother, who has been more than usually ill lately, so threw -on some clothes and got ready to look for her. As I was leaving the -room it struck me that the clothes she wore might give me some clue to -her dreaming intention. Dressing-gown would mean house, dress outside. -Dressing-gown and dress were both in their places. "Thank God," I said -to myself, "she cannot be far, as she is only in her nightdress." - -I ran downstairs and looked in the sitting room. Not there! Then I -looked in all the other rooms of the house, with an ever-growing fear -chilling my heart. Finally, I came to the hall door and found it open. -It was not wide open, but the catch of the lock had not caught. The -people of the house are careful to lock the door every night, so I -feared that Lucy must have gone out as she was. There was no time to -think of what might happen. A vague over-mastering fear obscured all -details. - -I took a big, heavy shawl and ran out. The clock was striking one as I -was in the Crescent, and there was not a soul in sight. I ran along -the North Terrace, but could see no sign of the white figure which I -expected. At the edge of the West Cliff above the pier I looked across -the harbour to the East Cliff, in the hope or fear, I don't know which, -of seeing Lucy in our favourite seat. - -There was a bright full moon, with heavy black, driving clouds, which -threw the whole scene into a fleeting diorama of light and shade as -they sailed across. For a moment or two I could see nothing, as the -shadow of a cloud obscured St. Mary's Church and all around it. Then -as the cloud passed I could see the ruins of the abbey coming into -view, and as the edge of a narrow band of light as sharp as a sword-cut -moved along, the church and churchyard became gradually visible. -Whatever my expectation was, it was not disappointed, for there, on our -favourite seat, the silver light of the moon struck a half-reclining -figure, snowy white. The coming of the cloud was too quick for me to -see much, for shadow shut down on light almost immediately, but it -seemed to me as though something dark stood behind the seat where the -white figure shone, and bent over it. What it was, whether man or -beast, I could not tell. - -I did not wait to catch another glance, but flew down the steep steps -to the pier and along by the fish-market to the bridge, which was the -only way to reach the East Cliff. The town seemed as dead, for not a -soul did I see. I rejoiced that it was so, for I wanted no witness of -poor Lucy's condition. The time and distance seemed endless, and my -knees trembled and my breath came laboured as I toiled up the endless -steps to the abbey. I must have gone fast, and yet it seemed to me as -if my feet were weighted with lead, and as though every joint in my -body were rusty. - -When I got almost to the top I could see the seat and the white figure, -for I was now close enough to distinguish it even through the spells of -shadow. There was undoubtedly something, long and black, bending over -the half-reclining white figure. I called in fright, "Lucy! Lucy!" -and something raised a head, and from where I was I could see a white -face and red, gleaming eyes. - -Lucy did not answer, and I ran on to the entrance of the churchyard. -As I entered, the church was between me and the seat, and for a minute -or so I lost sight of her. When I came in view again the cloud had -passed, and the moonlight struck so brilliantly that I could see Lucy -half reclining with her head lying over the back of the seat. She was -quite alone, and there was not a sign of any living thing about. - -When I bent over her I could see that she was still asleep. Her lips -were parted, and she was breathing, not softly as usual with her, but -in long, heavy gasps, as though striving to get her lungs full at every -breath. As I came close, she put up her hand in her sleep and pulled -the collar of her nightdress close around her, as though she felt the -cold. I flung the warm shawl over her, and drew the edges tight around -her neck, for I dreaded lest she should get some deadly chill from the -night air, unclad as she was. I feared to wake her all at once, so, in -order to have my hands free to help her, I fastened the shawl at her -throat with a big safety pin. But I must have been clumsy in my -anxiety and pinched or pricked her with it, for by-and-by, when her -breathing became quieter, she put her hand to her throat again and -moaned. When I had her carefully wrapped up I put my shoes on her -feet, and then began very gently to wake her. - -At first she did not respond, but gradually she became more and more -uneasy in her sleep, moaning and sighing occasionally. At last, as -time was passing fast, and for many other reasons, I wished to get her -home at once, I shook her forcibly, till finally she opened her eyes -and awoke. She did not seem surprised to see me, as, of course, she -did not realize all at once where she was. - -Lucy always wakes prettily, and even at such a time, when her body must -have been chilled with cold, and her mind somewhat appalled at waking -unclad in a churchyard at night, she did not lose her grace. She -trembled a little, and clung to me. When I told her to come at once -with me home, she rose without a word, with the obedience of a child. -As we passed along, the gravel hurt my feet, and Lucy noticed me wince. -She stopped and wanted to insist upon my taking my shoes, but I would -not. However, when we got to the pathway outside the chruchyard, where -there was a puddle of water, remaining from the storm, I daubed my feet -with mud, using each foot in turn on the other, so that as we went -home, no one, in case we should meet any one, should notice my bare -feet. - -Fortune favoured us, and we got home without meeting a soul. Once we -saw a man, who seemed not quite sober, passing along a street in front -of us. But we hid in a door till he had disappeared up an opening such -as there are here, steep little closes, or 'wynds', as they call them -in Scotland. My heart beat so loud all the time sometimes I thought I -should faint. I was filled with anxiety about Lucy, not only for her -health, lest she should suffer from the exposure, but for her -reputation in case the story should get wind. When we got in, and had -washed our feet, and had said a prayer of thankfulness together, I -tucked her into bed. Before falling asleep she asked, even implored, -me not to say a word to any one, even her mother, about her -sleep-walking adventure. - -I hesitated at first, to promise, but on thinking of the state of her -mother's health, and how the knowledge of such a thing would fret her, -and think too, of how such a story might become distorted, nay, -infallibly would, in case it should leak out, I thought it wiser to do -so. I hope I did right. I have locked the door, and the key is tied -to my wrist, so perhaps I shall not be again disturbed. Lucy is -sleeping soundly. The reflex of the dawn is high and far over the -sea . . . - - -Same day, noon.--All goes well. Lucy slept till I woke her and seemed -not to have even changed her side. The adventure of the night does not -seem to have harmed her, on the contrary, it has benefited her, for she -looks better this morning than she has done for weeks. I was sorry to -notice that my clumsiness with the safety-pin hurt her. Indeed, it -might have been serious, for the skin of her throat was pierced. I -must have pinched up a piece of loose skin and have transfixed it, for -there are two little red points like pin-pricks, and on the band of her -nightdress was a drop of blood. When I apologised and was concerned -about it, she laughed and petted me, and said she did not even feel it. -Fortunately it cannot leave a scar, as it is so tiny. - - -Same day, night.--We passed a happy day. The air was clear, and the -sun bright, and there was a cool breeze. We took our lunch to Mulgrave -Woods, Mrs. Westenra driving by the road and Lucy and I walking by the -cliff-path and joining her at the gate. I felt a little sad myself, -for I could not but feel how absolutely happy it would have been had -Jonathan been with me. But there! I must only be patient. In the -evening we strolled in the Casino Terrace, and heard some good music by -Spohr and Mackenzie, and went to bed early. Lucy seems more restful -than she has been for some time, and fell asleep at once. I shall lock -the door and secure the key the same as before, though I do not expect -any trouble tonight. - - -12 August.--My expectations were wrong, for twice during the night I -was wakened by Lucy trying to get out. She seemed, even in her sleep, -to be a little impatient at finding the door shut, and went back to bed -under a sort of protest. I woke with the dawn, and heard the birds -chirping outside of the window. Lucy woke, too, and I was glad to see, -was even better than on the previous morning. All her old gaiety of -manner seemed to have come back, and she came and snuggled in beside me -and told me all about Arthur. I told her how anxious I was about -Jonathan, and then she tried to comfort me. Well, she succeeded -somewhat, for, though sympathy can't alter facts, it can make them more -bearable. - - -13 August.--Another quiet day, and to bed with the key on my wrist as -before. Again I awoke in the night, and found Lucy sitting up in bed, -still asleep, pointing to the window. I got up quietly, and pulling -aside the blind, looked out. It was brilliant moonlight, and the soft -effect of the light over the sea and sky, merged together in one great -silent mystery, was beautiful beyond words. Between me and the -moonlight flitted a great bat, coming and going in great whirling -circles. Once or twice it came quite close, but was, I suppose, -frightened at seeing me, and flitted away across the harbour towards -the abbey. When I came back from the window Lucy had lain down again, -and was sleeping peacefully. She did not stir again all night. - - -14 August.--On the East Cliff, reading and writing all day. Lucy seems -to have become as much in love with the spot as I am, and it is hard to -get her away from it when it is time to come home for lunch or tea or -dinner. This afternoon she made a funny remark. We were coming home -for dinner, and had come to the top of the steps up from the West Pier -and stopped to look at the view, as we generally do. The setting sun, -low down in the sky, was just dropping behind Kettleness. The red -light was thrown over on the East Cliff and the old abbey, and seemed -to bathe everything in a beautiful rosy glow. We were silent for a -while, and suddenly Lucy murmured as if to herself . . . - -"His red eyes again! They are just the same." It was such an odd -expression, coming apropos of nothing, that it quite startled me. I -slewed round a little, so as to see Lucy well without seeming to stare -at her, and saw that she was in a half dreamy state, with an odd look -on her face that I could not quite make out, so I said nothing, but -followed her eyes. She appeared to be looking over at our own seat, -whereon was a dark figure seated alone. I was quite a little startled -myself, for it seemed for an instant as if the stranger had great eyes -like burning flames, but a second look dispelled the illusion. The red -sunlight was shining on the windows of St. Mary's Church behind our -seat, and as the sun dipped there was just sufficient change in the -refraction and reflection to make it appear as if the light moved. I -called Lucy's attention to the peculiar effect, and she became herself -with a start, but she looked sad all the same. It may have been that -she was thinking of that terrible night up there. We never refer to -it, so I said nothing, and we went home to dinner. Lucy had a headache -and went early to bed. I saw her asleep, and went out for a little -stroll myself. - -I walked along the cliffs to the westward, and was full of sweet -sadness, for I was thinking of Jonathan. When coming home, it was then -bright moonlight, so bright that, though the front of our part of the -Crescent was in shadow, everything could be well seen, I threw a glance -up at our window, and saw Lucy's head leaning out. I opened my -handkerchief and waved it. She did not notice or make any movement -whatever. Just then, the moonlight crept round an angle of the -building, and the light fell on the window. There distinctly was Lucy -with her head lying up against the side of the window sill and her eyes -shut. She was fast asleep, and by her, seated on the window sill, was -something that looked like a good-sized bird. I was afraid she might -get a chill, so I ran upstairs, but as I came into the room she was -moving back to her bed, fast asleep, and breathing heavily. She was -holding her hand to her throat, as though to protect if from the cold. - -I did not wake her, but tucked her up warmly. I have taken care that -the door is locked and the window securely fastened. - -She looks so sweet as she sleeps, but she is paler than is her wont, -and there is a drawn, haggard look under her eyes which I do not like. -I fear she is fretting about something. I wish I could find out what it -is. - - -15 August.--Rose later than usual. Lucy was languid and tired, and -slept on after we had been called. We had a happy surprise at -breakfast. Arthur's father is better, and wants the marriage to come -off soon. Lucy is full of quiet joy, and her mother is glad and sorry -at once. Later on in the day she told me the cause. She is grieved to -lose Lucy as her very own, but she is rejoiced that she is soon to have -some one to protect her. Poor dear, sweet lady! She confided to me -that she has got her death warrant. She has not told Lucy, and made me -promise secrecy. Her doctor told her that within a few months, at -most, she must die, for her heart is weakening. At any time, even now, -a sudden shock would be almost sure to kill her. Ah, we were wise to -keep from her the affair of the dreadful night of Lucy's sleep-walking. - - -17 August.--No diary for two whole days. I have not had the heart to -write. Some sort of shadowy pall seems to be coming over our -happiness. No news from Jonathan, and Lucy seems to be growing weaker, -whilst her mother's hours are numbering to a close. I do not -understand Lucy's fading away as she is doing. She eats well and -sleeps well, and enjoys the fresh air, but all the time the roses in -her cheeks are fading, and she gets weaker and more languid day by day. -At night I hear her gasping as if for air. - -I keep the key of our door always fastened to my wrist at night, but -she gets up and walks about the room, and sits at the open window. -Last night I found her leaning out when I woke up, and when I tried to -wake her I could not. - -She was in a faint. When I managed to restore her, she was weak as -water, and cried silently between long, painful struggles for breath. -When I asked her how she came to be at the window she shook her head -and turned away. - -I trust her feeling ill may not be from that unlucky prick of the -safety-pin. I looked at her throat just now as she lay asleep, and the -tiny wounds seem not to have healed. They are still open, and, if -anything, larger than before, and the edges of them are faintly white. -They are like little white dots with red centres. Unless they heal -within a day or two, I shall insist on the doctor seeing about them. - - - -LETTER, SAMUEL F. BILLINGTON & SON, SOLICITORS WHITBY, -TO MESSRS. CARTER, PATERSON & CO., LONDON. - -17 August - -"Dear Sirs,--Herewith please receive invoice of goods sent by Great -Northern Railway. Same are to be delivered at Carfax, near -Purfleet, immediately on receipt at goods station King's Cross. The -house is at present empty, but enclosed please find keys, all of -which are labelled. - -"You will please deposit the boxes, fifty in number, which form the -consignment, in the partially ruined building forming part of the -house and marked 'A' on rough diagrams enclosed. Your agent will -easily recognize the locality, as it is the ancient chapel of the -mansion. The goods leave by the train at 9:30 tonight, and will be -due at King's Cross at 4:30 tomorrow afternoon. As our client -wishes the delivery made as soon as possible, we shall be obliged by -your having teams ready at King's Cross at the time named and -forthwith conveying the goods to destination. In order to obviate -any delays possible through any routine requirements as to payment -in your departments, we enclose cheque herewith for ten pounds, -receipt of which please acknowledge. Should the charge be less than -this amount, you can return balance, if greater, we shall at once -send cheque for difference on hearing from you. You are to leave -the keys on coming away in the main hall of the house, where the -proprietor may get them on his entering the house by means of his -duplicate key. - -"Pray do not take us as exceeding the bounds of business courtesy -in pressing you in all ways to use the utmost expedition. - -"We are, dear Sirs, -Faithfully yours, -SAMUEL F. BILLINGTON & SON" - - - -LETTER, MESSRS. CARTER, PATERSON & CO., LONDON, -TO MESSRS. BILLINGTON & SON, WHITBY. - -21 August. - -"Dear Sirs,--We beg to acknowledge 10 pounds received and to return -cheque of 1 pound, 17s, 9d, amount of overplus, as shown in -receipted account herewith. Goods are delivered in exact accordance -with instructions, and keys left in parcel in main hall, as -directed. - -"We are, dear Sirs, -Yours respectfully, -Pro CARTER, PATERSON & CO." - - - -MINA MURRAY'S JOURNAL. - -18 August.--I am happy today, and write sitting on the seat in the -churchyard. Lucy is ever so much better. Last night she slept well -all night, and did not disturb me once. - -The roses seem coming back already to her cheeks, though she is still -sadly pale and wan-looking. If she were in any way anemic I could -understand it, but she is not. She is in gay spirits and full of life -and cheerfulness. All the morbid reticence seems to have passed from -her, and she has just reminded me, as if I needed any reminding, of -that night, and that it was here, on this very seat, I found her -asleep. - -As she told me she tapped playfully with the heel of her boot on the -stone slab and said, - -"My poor little feet didn't make much noise then! I daresay poor old -Mr. Swales would have told me that it was because I didn't want to wake -up Geordie." - -As she was in such a communicative humour, I asked her if she had -dreamed at all that night. - -Before she answered, that sweet, puckered look came into her forehead, -which Arthur, I call him Arthur from her habit, says he loves, and -indeed, I don't wonder that he does. Then she went on in a -half-dreaming kind of way, as if trying to recall it to herself. - -"I didn't quite dream, but it all seemed to be real. I only wanted to -be here in this spot. I don't know why, for I was afraid of something, -I don't know what. I remember, though I suppose I was asleep, passing -through the streets and over the bridge. A fish leaped as I went by, -and I leaned over to look at it, and I heard a lot of dogs howling. The -whole town seemed as if it must be full of dogs all howling at once, as -I went up the steps. Then I had a vague memory of something long and -dark with red eyes, just as we saw in the sunset, and something very -sweet and very bitter all around me at once. And then I seemed sinking -into deep green water, and there was a singing in my ears, as I have -heard there is to drowning men, and then everything seemed passing away -from me. My soul seemed to go out from my body and float about the -air. I seem to remember that once the West Lighthouse was right under -me, and then there was a sort of agonizing feeling, as if I were in an -earthquake, and I came back and found you shaking my body. I saw you -do it before I felt you." - -Then she began to laugh. It seemed a little uncanny to me, and I -listened to her breathlessly. I did not quite like it, and thought it -better not to keep her mind on the subject, so we drifted on to another -subject, and Lucy was like her old self again. When we got home the -fresh breeze had braced her up, and her pale cheeks were really more -rosy. Her mother rejoiced when she saw her, and we all spent a very -happy evening together. - - -19 August.--Joy, joy, joy! Although not all joy. At last, news of -Jonathan. The dear fellow has been ill, that is why he did not write. -I am not afraid to think it or to say it, now that I know. Mr. Hawkins -sent me on the letter, and wrote himself, oh so kindly. I am to leave -in the morning and go over to Jonathan, and to help to nurse him if -necessary, and to bring him home. Mr. Hawkins says it would not be a -bad thing if we were to be married out there. I have cried over the -good Sister's letter till I can feel it wet against my bosom, where it -lies. It is of Jonathan, and must be near my heart, for he is in my -heart. My journey is all mapped out, and my luggage ready. I am only -taking one change of dress. Lucy will bring my trunk to London and -keep it till I send for it, for it may be that . . . I must write no -more. I must keep it to say to Jonathan, my husband. The letter that -he has seen and touched must comfort me till we meet. - - - -LETTER, SISTER AGATHA, HOSPITAL OF ST. JOSEPH AND -STE. MARY BUDA-PESTH, TO MISS WILLHELMINA MURRAY - -12 August, - -"Dear Madam. - -"I write by desire of Mr. Jonathan Harker, who is himself not strong -enough to write, though progressing well, thanks to God and St. -Joseph and Ste. Mary. He has been under our care for nearly six -weeks, suffering from a violent brain fever. He wishes me to convey -his love, and to say that by this post I write for him to Mr. Peter -Hawkins, Exeter, to say, with his dutiful respects, that he is sorry -for his delay, and that all of his work is completed. He will -require some few weeks' rest in our sanatorium in the hills, but -will then return. He wishes me to say that he has not sufficient -money with him, and that he would like to pay for his staying here, -so that others who need shall not be wanting for help. - -"Believe me, - -"Yours, with sympathy -and all blessings. -Sister Agatha - -"P.S.--My patient being asleep, I open this to let you know -something more. He has told me all about you, and that you are -shortly to be his wife. All blessings to you both! He has had some -fearful shock, so says our doctor, and in his delirium his ravings -have been dreadful, of wolves and poison and blood, of ghosts and -demons, and I fear to say of what. Be careful of him always that -there may be nothing to excite him of this kind for a long time to -come. The traces of such an illness as his do not lightly die away. -We should have written long ago, but we knew nothing of his friends, -and there was nothing on him, nothing that anyone could understand. -He came in the train from Klausenburg, and the guard was told by the -station master there that he rushed into the station shouting for a -ticket for home. Seeing from his violent demeanour that he was -English, they gave him a ticket for the furthest station on the way -thither that the train reached. - -"Be assured that he is well cared for. He has won all hearts by his -sweetness and gentleness. He is truly getting on well, and I have -no doubt will in a few weeks be all himself. But be careful of him -for safety's sake. There are, I pray God and St. Joseph and Ste. -Mary, many, many, happy years for you both." - - - -DR. SEWARD'S DIARY - -19 August.--Strange and sudden change in Renfield last night. About -eight o'clock he began to get excited and sniff about as a dog does -when setting. The attendant was struck by his manner, and knowing my -interest in him, encouraged him to talk. He is usually respectful to -the attendant and at times servile, but tonight, the man tells me, he -was quite haughty. Would not condescend to talk with him at all. - -All he would say was, "I don't want to talk to you. You don't count -now. The master is at hand." - -The attendant thinks it is some sudden form of religious mania which -has seized him. If so, we must look out for squalls, for a strong man -with homicidal and religious mania at once might be dangerous. The -combination is a dreadful one. - -At nine o'clock I visited him myself. His attitude to me was the same -as that to the attendant. In his sublime self-feeling the difference -between myself and the attendant seemed to him as nothing. It looks -like religious mania, and he will soon think that he himself is God. - -These infinitesimal distinctions between man and man are too paltry for -an Omnipotent Being. How these madmen give themselves away! The real -God taketh heed lest a sparrow fall. But the God created from human -vanity sees no difference between an eagle and a sparrow. Oh, if men -only knew! - -For half an hour or more Renfield kept getting excited in greater and -greater degree. I did not pretend to be watching him, but I kept -strict observation all the same. All at once that shifty look came -into his eyes which we always see when a madman has seized an idea, and -with it the shifty movement of the head and back which asylum -attendants come to know so well. He became quite quiet, and went and -sat on the edge of his bed resignedly, and looked into space with -lack-luster eyes. - -I thought I would find out if his apathy were real or only assumed, and -tried to lead him to talk of his pets, a theme which had never failed -to excite his attention. - -At first he made no reply, but at length said testily, "Bother them -all! I don't care a pin about them." - -"What?" I said. "You don't mean to tell me you don't care about -spiders?" (Spiders at present are his hobby and the notebook is filling -up with columns of small figures.) - -To this he answered enigmatically, "The Bride maidens rejoice the eyes -that wait the coming of the bride. But when the bride draweth nigh, -then the maidens shine not to the eyes that are filled." - -He would not explain himself, but remained obstinately seated on his -bed all the time I remained with him. - -I am weary tonight and low in spirits. I cannot but think of Lucy, and -how different things might have been. If I don't sleep at once, -chloral, the modern Morpheus! I must be careful not to let it grow -into a habit. No, I shall take none tonight! I have thought of Lucy, -and I shall not dishonour her by mixing the two. If need be, tonight -shall be sleepless. - - -Later.--Glad I made the resolution, gladder that I kept to it. I had -lain tossing about, and had heard the clock strike only twice, when the -night watchman came to me, sent up from the ward, to say that Renfield -had escaped. I threw on my clothes and ran down at once. My patient -is too dangerous a person to be roaming about. Those ideas of his -might work out dangerously with strangers. - -The attendant was waiting for me. He said he had seen him not ten -minutes before, seemingly asleep in his bed, when he had looked through -the observation trap in the door. His attention was called by the -sound of the window being wrenched out. He ran back and saw his feet -disappear through the window, and had at once sent up for me. He was -only in his night gear, and cannot be far off. - -The attendant thought it would be more useful to watch where he should -go than to follow him, as he might lose sight of him whilst getting out -of the building by the door. He is a bulky man, and couldn't get -through the window. - -I am thin, so, with his aid, I got out, but feet foremost, and as we -were only a few feet above ground landed unhurt. - -The attendant told me the patient had gone to the left, and had taken a -straight line, so I ran as quickly as I could. As I got through the -belt of trees I saw a white figure scale the high wall which separates -our grounds from those of the deserted house. - -I ran back at once, told the watchman to get three or four men -immediately and follow me into the grounds of Carfax, in case our -friend might be dangerous. I got a ladder myself, and crossing the -wall, dropped down on the other side. I could see Renfield's figure -just disappearing behind the angle of the house, so I ran after him. On -the far side of the house I found him pressed close against the old -iron-bound oak door of the chapel. - -He was talking, apparently to some one, but I was afraid to go near -enough to hear what he was saying, lest I might frighten him, and he -should run off. - -Chasing an errant swarm of bees is nothing to following a naked -lunatic, when the fit of escaping is upon him! After a few minutes, -however, I could see that he did not take note of anything around him, -and so ventured to draw nearer to him, the more so as my men had now -crossed the wall and were closing him in. I heard him say . . . - -"I am here to do your bidding, Master. I am your slave, and you will -reward me, for I shall be faithful. I have worshipped you long and afar -off. Now that you are near, I await your commands, and you will not -pass me by, will you, dear Master, in your distribution of good -things?" - -He is a selfish old beggar anyhow. He thinks of the loaves and fishes -even when he believes his is in a real Presence. His manias make a -startling combination. When we closed in on him he fought like a -tiger. He is immensely strong, for he was more like a wild beast than -a man. - -I never saw a lunatic in such a paroxysm of rage before, and I hope I -shall not again. It is a mercy that we have found out his strength and -his danger in good time. With strength and determination like his, he -might have done wild work before he was caged. - -He is safe now, at any rate. Jack Sheppard himself couldn't get free -from the strait waistcoat that keeps him restrained, and he's chained -to the wall in the padded room. - -His cries are at times awful, but the silences that follow are more -deadly still, for he means murder in every turn and movement. - -Just now he spoke coherent words for the first time. "I shall be -patient, Master. It is coming, coming, coming!" - -So I took the hint, and came too. I was too excited to sleep, but this -diary has quieted me, and I feel I shall get some sleep tonight. - - - - -CHAPTER 9 - - -LETTER, MINA HARKER TO LUCY WESTENRA - - -Buda-Pesth, 24 August. - -"My dearest Lucy, - -"I know you will be anxious to hear all that has happened -since we parted at the railway station at Whitby. - -"Well, my dear, I got to Hull all right, and caught the boat to -Hamburg, and then the train on here. I feel that I can hardly -recall anything of the journey, except that I knew I was coming to -Jonathan, and that as I should have to do some nursing, I had better -get all the sleep I could. I found my dear one, oh, so thin and -pale and weak-looking. All the resolution has gone out of his dear -eyes, and that quiet dignity which I told you was in his face has -vanished. He is only a wreck of himself, and he does not remember -anything that has happened to him for a long time past. At least, -he wants me to believe so, and I shall never ask. - -"He has had some terrible shock, and I fear it might tax his poor -brain if he were to try to recall it. Sister Agatha, who is a good -creature and a born nurse, tells me that he wanted her to tell me -what they were, but she would only cross herself, and say she would -never tell. That the ravings of the sick were the secrets of God, -and that if a nurse through her vocation should hear them, she -should respect her trust. - -"She is a sweet, good soul, and the next day, when she saw I was -troubled, she opened up the subject my poor dear raved about, added, -'I can tell you this much, my dear. That it was not about anything -which he has done wrong himself, and you, as his wife to be, have no -cause to be concerned. He has not forgotten you or what he owes to -you. His fear was of great and terrible things, which no mortal can -treat of.' - -"I do believe the dear soul thought I might be jealous lest my poor -dear should have fallen in love with any other girl. The idea of my -being jealous about Jonathan! And yet, my dear, let me whisper, I -felt a thrill of joy through me when I knew that no other woman was -a cause for trouble. I am now sitting by his bedside, where I can -see his face while he sleeps. He is waking! - -"When he woke he asked me for his coat, as he wanted to get -something from the pocket. I asked Sister Agatha, and she brought -all his things. I saw amongst them was his notebook, and was -going to ask him to let me look at it, for I knew that I might find -some clue to his trouble, but I suppose he must have seen my wish in -my eyes, for he sent me over to the window, saying he wanted to be -quite alone for a moment. - -"Then he called me back, and he said to me very solemnly, -'Wilhelmina', I knew then that he was in deadly earnest, for he has -never called me by that name since he asked me to marry him, 'You -know, dear, my ideas of the trust between husband and wife. There -should be no secret, no concealment. I have had a great shock, and -when I try to think of what it is I feel my head spin round, and I -do not know if it was real of the dreaming of a madman. You know I -had brain fever, and that is to be mad. The secret is here, and I -do not want to know it. I want to take up my life here, with our -marriage.' For, my dear, we had decided to be married as soon as -the formalities are complete. 'Are you willing, Wilhelmina, to -share my ignorance? Here is the book. Take it and keep it, read it -if you will, but never let me know unless, indeed, some solemn duty -should come upon me to go back to the bitter hours, asleep or awake, -sane or mad, recorded here.' He fell back exhausted, and I put the -book under his pillow, and kissed him. I have asked Sister Agatha -to beg the Superior to let our wedding be this afternoon, and am -waiting her reply . . ." - - -"She has come and told me that the Chaplain of the English mission -church has been sent for. We are to be married in an hour, or as -soon after as Jonathan awakes." - -"Lucy, the time has come and gone. I feel very solemn, but very, -very happy. Jonathan woke a little after the hour, and all was -ready, and he sat up in bed, propped up with pillows. He answered -his 'I will' firmly and strong. I could hardly speak. My heart was -so full that even those words seemed to choke me. - -"The dear sisters were so kind. Please, God, I shall never, never -forget them, nor the grave and sweet responsibilities I have taken -upon me. I must tell you of my wedding present. When the chaplain -and the sisters had left me alone with my husband--oh, Lucy, it is -the first time I have written the words 'my husband'--left me alone -with my husband, I took the book from under his pillow, and wrapped -it up in white paper, and tied it with a little bit of pale blue -ribbon which was round my neck, and sealed it over the knot with -sealing wax, and for my seal I used my wedding ring. Then I kissed -it and showed it to my husband, and told him that I would keep it -so, and then it would be an outward and visible sign for us all our -lives that we trusted each other, that I would never open it unless -it were for his own dear sake or for the sake of some stern duty. -Then he took my hand in his, and oh, Lucy, it was the first time he -took his wife's hand, and said that it was the dearest thing in all -the wide world, and that he would go through all the past again to -win it, if need be. The poor dear meant to have said a part of the -past, but he cannot think of time yet, and I shall not wonder if at -first he mixes up not only the month, but the year. - -"Well, my dear, what could I say? I could only tell him that I was -the happiest woman in all the wide world, and that I had nothing to -give him except myself, my life, and my trust, and that with these -went my love and duty for all the days of my life. And, my dear, -when he kissed me, and drew me to him with his poor weak hands, it -was like a solemn pledge between us. - -"Lucy dear, do you know why I tell you all this? It is not only -because it is all sweet to me, but because you have been, and are, -very dear to me. It was my privilege to be your friend and guide -when you came from the schoolroom to prepare for the world of life. -I want you to see now, and with the eyes of a very happy wife, -whither duty has led me, so that in your own married life you too -may be all happy, as I am. My dear, please Almighty God, your life -may be all it promises, a long day of sunshine, with no harsh wind, -no forgetting duty, no distrust. I must not wish you no pain, for -that can never be, but I do hope you will be always as happy as I am -now. Goodbye, my dear. I shall post this at once, and perhaps, -write you very soon again. I must stop, for Jonathan is waking. I -must attend my husband! - -"Your ever-loving -Mina Harker." - - - -LETTER, LUCY WESTENRA TO MINA HARKER. - -Whitby, 30 August. - -"My dearest Mina, - -"Oceans of love and millions of kisses, and may you soon be in your -own home with your husband. I wish you were coming home soon enough -to stay with us here. The strong air would soon restore Jonathan. -It has quite restored me. I have an appetite like a cormorant, am -full of life, and sleep well. You will be glad to know that I have -quite given up walking in my sleep. I think I have not stirred out -of my bed for a week, that is when I once got into it at night. -Arthur says I am getting fat. By the way, I forgot to tell you that -Arthur is here. We have such walks and drives, and rides, and -rowing, and tennis, and fishing together, and I love him more than -ever. He tells me that he loves me more, but I doubt that, for at -first he told me that he couldn't love me more than he did then. -But this is nonsense. There he is, calling to me. So no more just -at present from your loving, - -"Lucy. - -"P.S.--Mother sends her love. She seems better, poor dear. - -"P.P.S.--We are to be married on 28 September." - - - -DR. SEWARDS DIARY - -20 August.--The case of Renfield grows even more interesting. He has -now so far quieted that there are spells of cessation from his -passion. For the first week after his attack he was perpetually -violent. Then one night, just as the moon rose, he grew quiet, and -kept murmuring to himself. "Now I can wait. Now I can wait." - -The attendant came to tell me, so I ran down at once to have a look at -him. He was still in the strait waistcoat and in the padded room, but -the suffused look had gone from his face, and his eyes had something -of their old pleading. I might almost say, cringing, softness. I was -satisfied with his present condition, and directed him to be relieved. -The attendants hesitated, but finally carried out my wishes without -protest. - -It was a strange thing that the patient had humour enough to see their -distrust, for, coming close to me, he said in a whisper, all the while -looking furtively at them, "They think I could hurt you! Fancy me -hurting you! The fools!" - -It was soothing, somehow, to the feelings to find myself disassociated -even in the mind of this poor madman from the others, but all the same -I do not follow his thought. Am I to take it that I have anything in -common with him, so that we are, as it were, to stand together. Or -has he to gain from me some good so stupendous that my well being is -needful to Him? I must find out later on. Tonight he will not speak. -Even the offer of a kitten or even a full-grown cat will not tempt -him. - -He will only say, "I don't take any stock in cats. I have more to -think of now, and I can wait. I can wait." - -After a while I left him. The attendant tells me that he was quiet -until just before dawn, and that then he began to get uneasy, and at -length violent, until at last he fell into a paroxysm which exhausted -him so that he swooned into a sort of coma. - - -. . . Three nights has the same thing happened, violent all day then -quiet from moonrise to sunrise. I wish I could get some clue to the -cause. It would almost seem as if there was some influence which came -and went. Happy thought! We shall tonight play sane wits against mad -ones. He escaped before without our help. Tonight he shall escape -with it. We shall give him a chance, and have the men ready to follow -in case they are required. - - -23 August.--"The expected always happens." How well Disraeli knew -life. Our bird when he found the cage open would not fly, so all our -subtle arrangements were for nought. At any rate, we have proved one -thing, that the spells of quietness last a reasonable time. We shall -in future be able to ease his bonds for a few hours each day. I have -given orders to the night attendant merely to shut him in the padded -room, when once he is quiet, until the hour before sunrise. The poor -soul's body will enjoy the relief even if his mind cannot appreciate -it. Hark! The unexpected again! I am called. The patient has once -more escaped. - - -Later.--Another night adventure. Renfield artfully waited until the -attendant was entering the room to inspect. Then he dashed out past -him and flew down the passage. I sent word for the attendants to -follow. Again he went into the grounds of the deserted house, and we -found him in the same place, pressed against the old chapel door. -When he saw me he became furious, and had not the attendants seized -him in time, he would have tried to kill me. As we were holding him a -strange thing happened. He suddenly redoubled his efforts, and then -as suddenly grew calm. I looked round instinctively, but could see -nothing. Then I caught the patient's eye and followed it, but could -trace nothing as it looked into the moonlight sky, except a big bat, -which was flapping its silent and ghostly way to the west. Bats -usually wheel about, but this one seemed to go straight on, as if it -knew where it was bound for or had some intention of its own. - -The patient grew calmer every instant, and presently said, "You -needn't tie me. I shall go quietly!" Without trouble, we came back -to the house. I feel there is something ominous in his calm, and -shall not forget this night. - - - -LUCY WESTENRA'S DIARY - -Hillingham, 24 August.--I must imitate Mina, and keep writing things -down. Then we can have long talks when we do meet. I wonder when it -will be. I wish she were with me again, for I feel so unhappy. Last -night I seemed to be dreaming again just as I was at Whitby. Perhaps -it is the change of air, or getting home again. It is all dark and -horrid to me, for I can remember nothing. But I am full of vague -fear, and I feel so weak and worn out. When Arthur came to lunch he -looked quite grieved when he saw me, and I hadn't the spirit to try to -be cheerful. I wonder if I could sleep in mother's room tonight. I -shall make an excuse to try. - - -25 August.--Another bad night. Mother did not seem to take to my -proposal. She seems not too well herself, and doubtless she fears to -worry me. I tried to keep awake, and succeeded for a while, but when -the clock struck twelve it waked me from a doze, so I must have been -falling asleep. There was a sort of scratching or flapping at the -window, but I did not mind it, and as I remember no more, I suppose I -must have fallen asleep. More bad dreams. I wish I could remember -them. This morning I am horribly weak. My face is ghastly pale, and -my throat pains me. It must be something wrong with my lungs, for I -don't seem to be getting air enough. I shall try to cheer up when -Arthur comes, or else I know he will be miserable to see me so. - - - -LETTER, ARTHUR TO DR. SEWARD - -"Albemarle Hotel, 31 August - -"My dear Jack, - -"I want you to do me a favour. Lucy is ill, that is she has no -special disease, but she looks awful, and is getting worse every -day. I have asked her if there is any cause, I not dare to ask her -mother, for to disturb the poor lady's mind about her daughter in -her present state of health would be fatal. Mrs. Westenra has -confided to me that her doom is spoken, disease of the heart, though -poor Lucy does not know it yet. I am sure that there is something -preying on my dear girl's mind. I am almost distracted when I think -of her. To look at her gives me a pang. I told her I should ask -you to see her, and though she demurred at first, I know why, old -fellow, she finally consented. It will be a painful task for you, I -know, old friend, but it is for her sake, and I must not hesitate to -ask, or you to act. You are to come to lunch at Hillingham -tomorrow, two o'clock, so as not to arouse any suspicion in Mrs. -Westenra, and after lunch Lucy will take an opportunity of being -alone with you. I am filled with anxiety, and want to consult with -you alone as soon as I can after you have seen her. Do not fail! - -"Arthur." - - - -TELEGRAM, ARTHUR HOLMWOOD TO SEWARD - -1 September - -"Am summoned to see my father, who is worse. Am writing. Write -me fully by tonight's post to Ring. Wire me if necessary." - - - -LETTER FROM DR. SEWARD TO ARTHUR HOLMWOOD - -2 September - -"My dear old fellow, - -"With regard to Miss Westenra's health I hasten to let you know at -once that in my opinion there is not any functional disturbance or -any malady that I know of. At the same time, I am not by any means -satisfied with her appearance. She is woefully different from what -she was when I saw her last. Of course you must bear in mind that I -did not have full opportunity of examination such as I should wish. -Our very friendship makes a little difficulty which not even medical -science or custom can bridge over. I had better tell you exactly -what happened, leaving you to draw, in a measure, your own -conclusions. I shall then say what I have done and propose doing. - -"I found Miss Westenra in seemingly gay spirits. Her mother was -present, and in a few seconds I made up my mind that she was trying -all she knew to mislead her mother and prevent her from being -anxious. I have no doubt she guesses, if she does not know, what -need of caution there is. - -"We lunched alone, and as we all exerted ourselves to be cheerful, -we got, as some kind of reward for our labours, some real -cheerfulness amongst us. Then Mrs. Westenra went to lie down, and -Lucy was left with me. We went into her boudoir, and till we got -there her gaiety remained, for the servants were coming and going. - -"As soon as the door was closed, however, the mask fell from her -face, and she sank down into a chair with a great sigh, and hid her -eyes with her hand. When I saw that her high spirits had failed, I -at once took advantage of her reaction to make a diagnosis. - -"She said to me very sweetly, 'I cannot tell you how I loathe -talking about myself.' I reminded her that a doctor's confidence -was sacred, but that you were grievously anxious about her. She -caught on to my meaning at once, and settled that matter in a word. -'Tell Arthur everything you choose. I do not care for myself, but -for him!' So I am quite free. - -"I could easily see that she was somewhat bloodless, but I could not -see the usual anemic signs, and by the chance, I was able to test -the actual quality of her blood, for in opening a window which was -stiff a cord gave way, and she cut her hand slightly with broken -glass. It was a slight matter in itself, but it gave me an evident -chance, and I secured a few drops of the blood and have analysed -them. - -"The qualitative analysis give a quite normal condition, and shows, -I should infer, in itself a vigorous state of health. In other -physical matters I was quite satisfied that there is no need for -anxiety, but as there must be a cause somewhere, I have come to the -conclusion that it must be something mental. - -"She complains of difficulty breathing satisfactorily at times, and -of heavy, lethargic sleep, with dreams that frighten her, but -regarding which she can remember nothing. She says that as a child, -she used to walk in her sleep, and that when in Whitby the habit -came back, and that once she walked out in the night and went to -East Cliff, where Miss Murray found her. But she assures me that of -late the habit has not returned. - -"I am in doubt, and so have done the best thing I know of. I have -written to my old friend and master, Professor Van Helsing, of -Amsterdam, who knows as much about obscure diseases as any one in -the world. I have asked him to come over, and as you told me that -all things were to be at your charge, I have mentioned to him who -you are and your relations to Miss Westenra. This, my dear fellow, -is in obedience to your wishes, for I am only too proud and happy to -do anything I can for her. - -"Van Helsing would, I know, do anything for me for a personal -reason, so no matter on what ground he comes, we must accept his -wishes. He is a seemingly arbitrary man, this is because he knows -what he is talking about better than any one else. He is a -philosopher and a metaphysician, and one of the most advanced -scientists of his day, and he has, I believe, an absolutely open -mind. This, with an iron nerve, a temper of the ice-brook, and -indomitable resolution, self-command, and toleration exalted from -virtues to blessings, and the kindliest and truest heart that beats, -these form his equipment for the noble work that he is doing for -mankind, work both in theory and practice, for his views are as wide -as his all-embracing sympathy. I tell you these facts that you may -know why I have such confidence in him. I have asked him to come at -once. I shall see Miss Westenra tomorrow again. She is to meet me -at the Stores, so that I may not alarm her mother by too early a -repetition of my call. - -"Yours always." - -John Seward - - - - -LETTER, ABRAHAM VAN HELSING, MD, DPh, D. Lit, ETC, ETC, TO DR. SEWARD - -2 September. - -"My good Friend, - -"When I received your letter I am already coming to you. By good -fortune I can leave just at once, without wrong to any of those who -have trusted me. Were fortune other, then it were bad for those who -have trusted, for I come to my friend when he call me to aid those -he holds dear. Tell your friend that when that time you suck from -my wound so swiftly the poison of the gangrene from that knife that -our other friend, too nervous, let slip, you did more for him when -he wants my aids and you call for them than all his great fortune -could do. But it is pleasure added to do for him, your friend, it -is to you that I come. Have near at hand, and please it so arrange -that we may see the young lady not too late on tomorrow, for it is -likely that I may have to return here that night. But if need be I -shall come again in three days, and stay longer if it must. Till -then goodbye, my friend John. - -"Van Helsing." - - - -LETTER, DR. SEWARD TO HON. ARTHUR HOLMWOOD - -3 September - -"My dear Art, - -"Van Helsing has come and gone. He came on with me to Hillingham, -and found that, by Lucy's discretion, her mother was lunching out, -so that we were alone with her. - -"Van Helsing made a very careful examination of the patient. He is -to report to me, and I shall advise you, for of course I was not -present all the time. He is, I fear, much concerned, but says he -must think. When I told him of our friendship and how you trust to -me in the matter, he said, 'You must tell him all you think. Tell -him what I think, if you can guess it, if you will. Nay, I am -not jesting. This is no jest, but life and death, perhaps more.' I -asked what he meant by that, for he was very serious. This was when -we had come back to town, and he was having a cup of tea before -starting on his return to Amsterdam. He would not give me any -further clue. You must not be angry with me, Art, because his very -reticence means that all his brains are working for her good. He -will speak plainly enough when the time comes, be sure. So I told -him I would simply write an account of our visit, just as if I were -doing a descriptive special article for THE DAILY TELEGRAPH. He -seemed not to notice, but remarked that the smuts of London were not -quite so bad as they used to be when he was a student here. I am to -get his report tomorrow if he can possibly make it. In any case I -am to have a letter. - -"Well, as to the visit, Lucy was more cheerful than on the day I -first saw her, and certainly looked better. She had lost something -of the ghastly look that so upset you, and her breathing was normal. -She was very sweet to the Professor (as she always is), and tried to -make him feel at ease, though I could see the poor girl was making a -hard struggle for it. - -"I believe Van Helsing saw it, too, for I saw the quick look -under his bushy brows that I knew of old. Then he began to -chat of all things except ourselves and diseases and with -such an infinite geniality that I could see poor Lucy's -pretense of animation merge into reality. Then, without -any seeming change, he brought the conversation gently round -to his visit, and suavely said, - -"'My dear young miss, I have the so great pleasure because you are -so much beloved. That is much, my dear, even were there that which -I do not see. They told me you were down in the spirit, and that -you were of a ghastly pale. To them I say "Pouf!"' And he snapped -his fingers at me and went on. 'But you and I shall show them how -wrong they are. How can he,' and he pointed at me with the same -look and gesture as that with which he pointed me out in his class, -on, or rather after, a particular occasion which he never fails to -remind me of, 'know anything of a young ladies? He has his madmen -to play with, and to bring them back to happiness, and to those that -love them. It is much to do, and, oh, but there are rewards in that -we can bestow such happiness. But the young ladies! He has no wife -nor daughter, and the young do not tell themselves to the young, but -to the old, like me, who have known so many sorrows and the causes -of them. So, my dear, we will send him away to smoke the cigarette -in the garden, whiles you and I have little talk all to ourselves.' -I took the hint, and strolled about, and presently the professor -came to the window and called me in. He looked grave, but said, 'I -have made careful examination, but there is no functional cause. -With you I agree that there has been much blood lost, it has been -but is not. But the conditions of her are in no way anemic. I have -asked her to send me her maid, that I may ask just one or two -questions, that so I may not chance to miss nothing. I know well -what she will say. And yet there is cause. There is always cause -for everything. I must go back home and think. You must send me -the telegram every day, and if there be cause I shall come again. -The disease, for not to be well is a disease, interest me, and the -sweet, young dear, she interest me too. She charm me, and for her, -if not for you or disease, I come.' - -"As I tell you, he would not say a word more, even when we were -alone. And so now, Art, you know all I know. I shall keep stern -watch. I trust your poor father is rallying. It must be a terrible -thing to you, my dear old fellow, to be placed in such a position -between two people who are both so dear to you. I know your idea of -duty to your father, and you are right to stick to it. But if need -be, I shall send you word to come at once to Lucy, so do not be -over-anxious unless you hear from me." - - - -DR. SEWARD'S DIARY - -4 September.--Zoophagous patient still keeps up our interest in him. -He had only one outburst and that was yesterday at an unusual time. -Just before the stroke of noon he began to grow restless. The -attendant knew the symptoms, and at once summoned aid. Fortunately -the men came at a run, and were just in time, for at the stroke of -noon he became so violent that it took all their strength to hold him. -In about five minutes, however, he began to get more quiet, and -finally sank into a sort of melancholy, in which state he has remained -up to now. The attendant tells me that his screams whilst in the -paroxysm were really appalling. I found my hands full when I got in, -attending to some of the other patients who were frightened by him. -Indeed, I can quite understand the effect, for the sounds disturbed -even me, though I was some distance away. It is now after the dinner -hour of the asylum, and as yet my patient sits in a corner brooding, -with a dull, sullen, woe-begone look in his face, which seems rather -to indicate than to show something directly. I cannot quite -understand it. - - -Later.--Another change in my patient. At five o'clock I looked in on -him, and found him seemingly as happy and contented as he used to be. -He was catching flies and eating them, and was keeping note of his -capture by making nailmarks on the edge of the door between the ridges -of padding. When he saw me, he came over and apologized for his bad -conduct, and asked me in a very humble, cringing way to be led back to -his own room, and to have his notebook again. I thought it well to -humour him, so he is back in his room with the window open. He has -the sugar of his tea spread out on the window sill, and is reaping -quite a harvest of flies. He is not now eating them, but putting them -into a box, as of old, and is already examining the corners of his -room to find a spider. I tried to get him to talk about the past few -days, for any clue to his thoughts would be of immense help to me, but -he would not rise. For a moment or two he looked very sad, and said -in a sort of far away voice, as though saying it rather to himself -than to me. - -"All over! All over! He has deserted me. No hope for me now unless -I do it myself!" Then suddenly turning to me in a resolute way, he -said, "Doctor, won't you be very good to me and let me have a little -more sugar? I think it would be very good for me." - -"And the flies?" I said. - -"Yes! The flies like it, too, and I like the flies, therefore I like -it." And there are people who know so little as to think that madmen do -not argue. I procured him a double supply, and left him as happy a -man as, I suppose, any in the world. I wish I could fathom his mind. - - -Midnight.--Another change in him. I had been to see Miss Westenra, -whom I found much better, and had just returned, and was standing at -our own gate looking at the sunset, when once more I heard him -yelling. As his room is on this side of the house, I could hear it -better than in the morning. It was a shock to me to turn from the -wonderful smoky beauty of a sunset over London, with its lurid lights -and inky shadows and all the marvellous tints that come on foul clouds -even as on foul water, and to realize all the grim sternness of my own -cold stone building, with its wealth of breathing misery, and my own -desolate heart to endure it all. I reached him just as the sun was -going down, and from his window saw the red disc sink. As it sank he -became less and less frenzied, and just as it dipped he slid from the -hands that held him, an inert mass, on the floor. It is wonderful, -however, what intellectual recuperative power lunatics have, for -within a few minutes he stood up quite calmly and looked around him. I -signalled to the attendants not to hold him, for I was anxious to see -what he would do. He went straight over to the window and brushed out -the crumbs of sugar. Then he took his fly box, and emptied it -outside, and threw away the box. Then he shut the window, and -crossing over, sat down on his bed. All this surprised me, so I asked -him, "Are you going to keep flies any more?" - -"No," said he. "I am sick of all that rubbish!" He certainly is a -wonderfully interesting study. I wish I could get some glimpse of his -mind or of the cause of his sudden passion. Stop. There may be a -clue after all, if we can find why today his paroxysms came on at high -noon and at sunset. Can it be that there is a malign influence of the -sun at periods which affects certain natures, as at times the moon -does others? We shall see. - - - -TELEGRAM. SEWARD, LONDON, TO VAN HELSING, AMSTERDAM - -"4 September.--Patient still better today." - - - -TELEGRAM, SEWARD, LONDON, TO VAN HELSING, AMSTERDAM - -"5 September.--Patient greatly improved. Good appetite, sleeps -naturally, good spirits, colour coming back." - - - -TELEGRAM, SEWARD, LONDON, TO VAN HELSING, AMSTERDAM - -"6 September.--Terrible change for the worse. Come at once. -Do not lose an hour. I hold over telegram to Holmwood till -have seen you." - - - - -CHAPTER 10 - - -LETTER, DR. SEWARD TO HON. ARTHUR HOLMWOOD - - -6 September - -"My dear Art, - -"My news today is not so good. Lucy this morning had gone back a -bit. There is, however, one good thing which has arisen from it. -Mrs. Westenra was naturally anxious concerning Lucy, and has -consulted me professionally about her. I took advantage of the -opportunity, and told her that my old master, Van Helsing, the great -specialist, was coming to stay with me, and that I would put her in -his charge conjointly with myself. So now we can come and go -without alarming her unduly, for a shock to her would mean sudden -death, and this, in Lucy's weak condition, might be disastrous to -her. We are hedged in with difficulties, all of us, my poor fellow, -but, please God, we shall come through them all right. If any need -I shall write, so that, if you do not hear from me, take it for -granted that I am simply waiting for news, In haste, - -"Yours ever," - -John Seward - - - -DR. SEWARD'S DIARY - -7 September.--The first thing Van Helsing said to me when we met at -Liverpool Street was, "Have you said anything to our young friend, to -lover of her?" - -"No," I said. "I waited till I had seen you, as I said in my -telegram. I wrote him a letter simply telling him that you were -coming, as Miss Westenra was not so well, and that I should let him -know if need be." - -"Right, my friend," he said. "Quite right! Better he not know as -yet. Perhaps he will never know. I pray so, but if it be needed, -then he shall know all. And, my good friend John, let me caution you. -You deal with the madmen. All men are mad in some way or the other, -and inasmuch as you deal discreetly with your madmen, so deal with -God's madmen too, the rest of the world. You tell not your madmen -what you do nor why you do it. You tell them not what you think. So -you shall keep knowledge in its place, where it may rest, where it may -gather its kind around it and breed. You and I shall keep as yet what -we know here, and here." He touched me on the heart and on the -forehead, and then touched himself the same way. "I have for myself -thoughts at the present. Later I shall unfold to you." - -"Why not now?" I asked. "It may do some good. We may arrive at some -decision." He looked at me and said, "My friend John, when the corn is -grown, even before it has ripened, while the milk of its mother earth -is in him, and the sunshine has not yet begun to paint him with his -gold, the husbandman he pull the ear and rub him between his rough -hands, and blow away the green chaff, and say to you, 'Look! He's -good corn, he will make a good crop when the time comes.'" - -I did not see the application and told him so. For reply he reached -over and took my ear in his hand and pulled it playfully, as he used -long ago to do at lectures, and said, "The good husbandman tell you so -then because he knows, but not till then. But you do not find the -good husbandman dig up his planted corn to see if he grow. That is -for the children who play at husbandry, and not for those who take it -as of the work of their life. See you now, friend John? I have sown -my corn, and Nature has her work to do in making it sprout, if he -sprout at all, there's some promise, and I wait till the ear begins to -swell." He broke off, for he evidently saw that I understood. Then he -went on gravely, "You were always a careful student, and your case -book was ever more full than the rest. And I trust that good habit -have not fail. Remember, my friend, that knowledge is stronger than -memory, and we should not trust the weaker. Even if you have not kept -the good practice, let me tell you that this case of our dear miss is -one that may be, mind, I say may be, of such interest to us and others -that all the rest may not make him kick the beam, as your people say. -Take then good note of it. Nothing is too small. I counsel you, put -down in record even your doubts and surmises. Hereafter it may be of -interest to you to see how true you guess. We learn from failure, not -from success!" - -When I described Lucy's symptoms, the same as before, but infinitely -more marked, he looked very grave, but said nothing. He took with him -a bag in which were many instruments and drugs, "the ghastly -paraphernalia of our beneficial trade," as he once called, in one of -his lectures, the equipment of a professor of the healing craft. - -When we were shown in, Mrs. Westenra met us. She was alarmed, but not -nearly so much as I expected to find her. Nature in one of her -beneficient moods has ordained that even death has some antidote to -its own terrors. Here, in a case where any shock may prove fatal, -matters are so ordered that, from some cause or other, the things not -personal, even the terrible change in her daughter to whom she is so -attached, do not seem to reach her. It is something like the way dame -Nature gathers round a foreign body an envelope of some insensitive -tissue which can protect from evil that which it would otherwise harm -by contact. If this be an ordered selfishness, then we should pause -before we condemn any one for the vice of egoism, for there may be -deeper root for its causes than we have knowledge of. - -I used my knowledge of this phase of spiritual pathology, and set down -a rule that she should not be present with Lucy, or think of her -illness more than was absolutely required. She assented readily, so -readily that I saw again the hand of Nature fighting for life. Van -Helsing and I were shown up to Lucy's room. If I was shocked when I -saw her yesterday, I was horrified when I saw her today. - -She was ghastly, chalkily pale. The red seemed to have gone even from -her lips and gums, and the bones of her face stood out prominently. -Her breathing was painful to see or hear. Van Helsing's face grew set -as marble, and his eyebrows converged till they almost touched over his -nose. Lucy lay motionless, and did not seem to have strength to -speak, so for a while we were all silent. Then Van Helsing beckoned -to me, and we went gently out of the room. The instant we had closed -the door he stepped quickly along the passage to the next door, which -was open. Then he pulled me quickly in with him and closed the door. -"My god!" he said. "This is dreadful. There is not time to be lost. -She will die for sheer want of blood to keep the heart's action as it -should be. There must be a transfusion of blood at once. Is it you -or me?" - -"I am younger and stronger, Professor. It must be me." - -"Then get ready at once. I will bring up my bag. I am prepared." - -I went downstairs with him, and as we were going there was a knock at -the hall door. When we reached the hall, the maid had just opened the -door, and Arthur was stepping quickly in. He rushed up to me, saying -in an eager whisper, - -"Jack, I was so anxious. I read between the lines of your letter, and -have been in an agony. The dad was better, so I ran down here to see -for myself. Is not that gentleman Dr. Van Helsing? I am so thankful -to you, sir, for coming." - -When first the Professor's eye had lit upon him, he had been angry at -his interruption at such a time, but now, as he took in his stalwart -proportions and recognized the strong young manhood which seemed to -emanate from him, his eyes gleamed. Without a pause he said to him as -he held out his hand, - -"Sir, you have come in time. You are the lover of our dear miss. She -is bad, very, very bad. Nay, my child, do not go like that." For he -suddenly grew pale and sat down in a chair almost fainting. "You are -to help her. You can do more than any that live, and your courage is -your best help." - -"What can I do?" asked Arthur hoarsely. "Tell me, and I shall do it. -My life is hers, and I would give the last drop of blood in my body for -her." - -The Professor has a strongly humorous side, and I could from old -knowledge detect a trace of its origin in his answer. - -"My young sir, I do not ask so much as that, not the last!" - -"What shall I do?" There was fire in his eyes, and his open nostrils -quivered with intent. Van Helsing slapped him on the shoulder. - -"Come!" he said. "You are a man, and it is a man we want. You are -better than me, better than my friend John." Arthur looked bewildered, -and the Professor went on by explaining in a kindly way. - -"Young miss is bad, very bad. She wants blood, and blood she must -have or die. My friend John and I have consulted, and we are about to -perform what we call transfusion of blood, to transfer from full veins -of one to the empty veins which pine for him. John was to give his -blood, as he is the more young and strong than me."--Here Arthur took -my hand and wrung it hard in silence.--"But now you are here, you are -more good than us, old or young, who toil much in the world of -thought. Our nerves are not so calm and our blood so bright than -yours!" - -Arthur turned to him and said, "If you only knew how gladly I would -die for her you would understand . . ." He stopped with a sort of -choke in his voice. - -"Good boy!" said Van Helsing. "In the not-so-far-off you will be -happy that you have done all for her you love. Come now and be -silent. You shall kiss her once before it is done, but then you must -go, and you must leave at my sign. Say no word to Madame. You know -how it is with her. There must be no shock, any knowledge of this -would be one. Come!" - -We all went up to Lucy's room. Arthur by direction remained outside. -Lucy turned her head and looked at us, but said nothing. She was not -asleep, but she was simply too weak to make the effort. Her eyes -spoke to us, that was all. - -Van Helsing took some things from his bag and laid them on a little -table out of sight. Then he mixed a narcotic, and coming over to the -bed, said cheerily, "Now, little miss, here is your medicine. Drink -it off, like a good child. See, I lift you so that to swallow is -easy. Yes." She had made the effort with success. - -It astonished me how long the drug took to act. This, in fact, marked -the extent of her weakness. The time seemed endless until sleep began -to flicker in her eyelids. At last, however, the narcotic began to -manifest its potency, and she fell into a deep sleep. When the -Professor was satisfied, he called Arthur into the room, and bade him -strip off his coat. Then he added, "You may take that one little kiss -whiles I bring over the table. Friend John, help to me!" So neither -of us looked whilst he bent over her. - -Van Helsing, turning to me, said, "He is so young and strong, and of -blood so pure that we need not defibrinate it." - -Then with swiftness, but with absolute method, Van Helsing performed -the operation. As the transfusion went on, something like life seemed -to come back to poor Lucy's cheeks, and through Arthur's growing -pallor the joy of his face seemed absolutely to shine. After a bit I -began to grow anxious, for the loss of blood was telling on Arthur, -strong man as he was. It gave me an idea of what a terrible strain -Lucy's system must have undergone that what weakened Arthur only -partially restored her. - -But the Professor's face was set, and he stood watch in hand, and with -his eyes fixed now on the patient and now on Arthur. I could hear my -own heart beat. Presently, he said in a soft voice, "Do not stir an -instant. It is enough. You attend him. I will look to her." - -When all was over, I could see how much Arthur was weakened. I -dressed the wound and took his arm to bring him away, when Van Helsing -spoke without turning round, the man seems to have eyes in the back of -his head, "The brave lover, I think, deserve another kiss, which he -shall have presently." And as he had now finished his operation, he -adjusted the pillow to the patient's head. As he did so the narrow -black velvet band which she seems always to wear round her throat, -buckled with an old diamond buckle which her lover had given her, was -dragged a little up, and showed a red mark on her throat. - -Arthur did not notice it, but I could hear the deep hiss of indrawn -breath which is one of Van Helsing's ways of betraying emotion. He -said nothing at the moment, but turned to me, saying, "Now take down -our brave young lover, give him of the port wine, and let him lie down -a while. He must then go home and rest, sleep much and eat much, that -he may be recruited of what he has so given to his love. He must not -stay here. Hold a moment! I may take it, sir, that you are anxious -of result. Then bring it with you, that in all ways the operation is -successful. You have saved her life this time, and you can go home -and rest easy in mind that all that can be is. I shall tell her all -when she is well. She shall love you none the less for what you have -done. Goodbye." - -When Arthur had gone I went back to the room. Lucy was sleeping -gently, but her breathing was stronger. I could see the counterpane -move as her breast heaved. By the bedside sat Van Helsing, looking at -her intently. The velvet band again covered the red mark. I asked -the Professor in a whisper, "What do you make of that mark on her -throat?" - -"What do you make of it?" - -"I have not examined it yet," I answered, and then and there proceeded -to loose the band. Just over the external jugular vein there were two -punctures, not large, but not wholesome looking. There was no sign of -disease, but the edges were white and worn looking, as if by some -trituration. It at once occurred to me that that this wound, or -whatever it was, might be the means of that manifest loss of blood. -But I abandoned the idea as soon as it formed, for such a thing could -not be. The whole bed would have been drenched to a scarlet with the -blood which the girl must have lost to leave such a pallor as she had -before the transfusion. - -"Well?" said Van Helsing. - -"Well," said I. "I can make nothing of it." - -The Professor stood up. "I must go back to Amsterdam tonight," he -said "There are books and things there which I want. You must remain -here all night, and you must not let your sight pass from her." - -"Shall I have a nurse?" I asked. - -"We are the best nurses, you and I. You keep watch all night. See -that she is well fed, and that nothing disturbs her. You must not -sleep all the night. Later on we can sleep, you and I. I shall be -back as soon as possible. And then we may begin." - -"May begin?" I said. "What on earth do you mean?" - -"We shall see!" he answered, as he hurried out. He came back a moment -later and put his head inside the door and said with a warning finger -held up, "Remember, she is your charge. If you leave her, and harm -befall, you shall not sleep easy hereafter!" - - - -DR. SEWARD'S DIARY--CONTINUED - -8 September.--I sat up all night with Lucy. The opiate worked itself -off towards dusk, and she waked naturally. She looked a different -being from what she had been before the operation. Her spirits even -were good, and she was full of a happy vivacity, but I could see -evidences of the absolute prostration which she had undergone. When I -told Mrs. Westenra that Dr. Van Helsing had directed that I should sit -up with her, she almost pooh-poohed the idea, pointing out her -daughter's renewed strength and excellent spirits. I was firm, -however, and made preparations for my long vigil. When her maid had -prepared her for the night I came in, having in the meantime had -supper, and took a seat by the bedside. - -She did not in any way make objection, but looked at me gratefully -whenever I caught her eye. After a long spell she seemed sinking off -to sleep, but with an effort seemed to pull herself together and shook -it off. It was apparent that she did not want to sleep, so I tackled -the subject at once. - -"You do not want to sleep?" - -"No. I am afraid." - -"Afraid to go to sleep! Why so? It is the boon we all crave for." - -"Ah, not if you were like me, if sleep was to you a presage of -horror!" - -"A presage of horror! What on earth do you mean?" - -"I don't know. Oh, I don't know. And that is what is so terrible. -All this weakness comes to me in sleep, until I dread the very -thought." - -"But, my dear girl, you may sleep tonight. I am here watching you, -and I can promise that nothing will happen." - -"Ah, I can trust you!" she said. - -I seized the opportunity, and said, "I promise that if I see any -evidence of bad dreams I will wake you at once." - -"You will? Oh, will you really? How good you are to me. Then I will -sleep!" And almost at the word she gave a deep sigh of relief, and -sank back, asleep. - -All night long I watched by her. She never stirred, but slept on and -on in a deep, tranquil, life-giving, health-giving sleep. Her lips -were slightly parted, and her breast rose and fell with the regularity -of a pendulum. There was a smile on her face, and it was evident that -no bad dreams had come to disturb her peace of mind. - -In the early morning her maid came, and I left her in her care and took -myself back home, for I was anxious about many things. I sent a short -wire to Van Helsing and to Arthur, telling them of the excellent -result of the operation. My own work, with its manifold arrears, took -me all day to clear off. It was dark when I was able to inquire about -my zoophagous patient. The report was good. He had been quite quiet -for the past day and night. A telegram came from Van Helsing at -Amsterdam whilst I was at dinner, suggesting that I should be at -Hillingham tonight, as it might be well to be at hand, and stating -that he was leaving by the night mail and would join me early in the -morning. - - -9 September.--I was pretty tired and worn out when I got to -Hillingham. For two nights I had hardly had a wink of sleep, and my -brain was beginning to feel that numbness which marks cerebral -exhaustion. Lucy was up and in cheerful spirits. When she shook -hands with me she looked sharply in my face and said, - -"No sitting up tonight for you. You are worn out. I am quite well -again. Indeed, I am, and if there is to be any sitting up, it is I -who will sit up with you." - -I would not argue the point, but went and had my supper. Lucy came -with me, and, enlivened by her charming presence, I made an excellent -meal, and had a couple of glasses of the more than excellent port. -Then Lucy took me upstairs, and showed me a room next her own, where a -cozy fire was burning. - -"Now," she said. "You must stay here. I shall leave this door open -and my door too. You can lie on the sofa for I know that nothing -would induce any of you doctors to go to bed whilst there is a patient -above the horizon. If I want anything I shall call out, and you can -come to me at once." - -I could not but acquiesce, for I was dog tired, and could not have sat -up had I tried. So, on her renewing her promise to call me if she -should want anything, I lay on the sofa, and forgot all about -everything. - - - -LUCY WESTENRA'S DIARY - -9 September.--I feel so happy tonight. I have been so miserably weak, -that to be able to think and move about is like feeling sunshine after -a long spell of east wind out of a steel sky. Somehow Arthur feels -very, very close to me. I seem to feel his presence warm about me. I -suppose it is that sickness and weakness are selfish things and turn -our inner eyes and sympathy on ourselves, whilst health and strength -give love rein, and in thought and feeling he can wander where he -wills. I know where my thoughts are. If only Arthur knew! My dear, -my dear, your ears must tingle as you sleep, as mine do waking. Oh, -the blissful rest of last night! How I slept, with that dear, good -Dr. Seward watching me. And tonight I shall not fear to sleep, since -he is close at hand and within call. Thank everybody for being so -good to me. Thank God! Goodnight Arthur. - - - -DR. SEWARD'S DIARY - -10 September.--I was conscious of the Professor's hand on my head, and -started awake all in a second. That is one of the things that we -learn in an asylum, at any rate. - -"And how is our patient?" - -"Well, when I left her, or rather when she left me," I answered. - -"Come, let us see," he said. And together we went into the room. - -The blind was down, and I went over to raise it gently, whilst Van -Helsing stepped, with his soft, cat-like tread, over to the bed. - -As I raised the blind, and the morning sunlight flooded the room, I -heard the Professor's low hiss of inspiration, and knowing its rarity, -a deadly fear shot through my heart. As I passed over he moved back, -and his exclamation of horror, "Gott in Himmel!" needed no enforcement -from his agonized face. He raised his hand and pointed to the bed, -and his iron face was drawn and ashen white. I felt my knees begin to -tremble. - -There on the bed, seemingly in a swoon, lay poor Lucy, more horribly -white and wan-looking than ever. Even the lips were white, and the -gums seemed to have shrunken back from the teeth, as we sometimes see -in a corpse after a prolonged illness. - -Van Helsing raised his foot to stamp in anger, but the instinct of his -life and all the long years of habit stood to him, and he put it down -again softly. - -"Quick!" he said. "Bring the brandy." - -I flew to the dining room, and returned with the decanter. He wetted -the poor white lips with it, and together we rubbed palm and wrist and -heart. He felt her heart, and after a few moments of agonizing -suspense said, - -"It is not too late. It beats, though but feebly. All our work is -undone. We must begin again. There is no young Arthur here now. I -have to call on you yourself this time, friend John." As he spoke, he -was dipping into his bag, and producing the instruments of -transfusion. I had taken off my coat and rolled up my shirt sleeve. -There was no possibility of an opiate just at present, and no need of -one; and so, without a moment's delay, we began the operation. - -After a time, it did not seem a short time either, for the draining -away of one's blood, no matter how willingly it be given, is a -terrible feeling, Van Helsing held up a warning finger. "Do not -stir," he said. "But I fear that with growing strength she may wake, -and that would make danger, oh, so much danger. But I shall -precaution take. I shall give hypodermic injection of morphia." He -proceeded then, swiftly and deftly, to carry out his intent. - -The effect on Lucy was not bad, for the faint seemed to merge subtly -into the narcotic sleep. It was with a feeling of personal pride that -I could see a faint tinge of colour steal back into the pallid cheeks -and lips. No man knows, till he experiences it, what it is to feel -his own lifeblood drawn away into the veins of the woman he loves. - -The Professor watched me critically. "That will do," he said. -"Already?" I remonstrated. "You took a great deal more from Art." To -which he smiled a sad sort of smile as he replied, - -"He is her lover, her fiance. You have work, much work to do for her -and for others, and the present will suffice." - -When we stopped the operation, he attended to Lucy, whilst I applied -digital pressure to my own incision. I laid down, while I waited his -leisure to attend to me, for I felt faint and a little sick. By and -by he bound up my wound, and sent me downstairs to get a glass of wine -for myself. As I was leaving the room, he came after me, and half -whispered. - -"Mind, nothing must be said of this. If our young lover should turn -up unexpected, as before, no word to him. It would at once frighten -him and enjealous him, too. There must be none. So!" - -When I came back he looked at me carefully, and then said, "You are -not much the worse. Go into the room, and lie on your sofa, and rest -awhile, then have much breakfast and come here to me." - -I followed out his orders, for I knew how right and wise they were. I -had done my part, and now my next duty was to keep up my strength. I -felt very weak, and in the weakness lost something of the amazement at -what had occurred. I fell asleep on the sofa, however, wondering over -and over again how Lucy had made such a retrograde movement, and how -she could have been drained of so much blood with no sign any where to -show for it. I think I must have continued my wonder in my dreams, -for, sleeping and waking my thoughts always came back to the little -punctures in her throat and the ragged, exhausted appearance of their -edges, tiny though they were. - -Lucy slept well into the day, and when she woke she was fairly well -and strong, though not nearly so much so as the day before. When Van -Helsing had seen her, he went out for a walk, leaving me in charge, -with strict injunctions that I was not to leave her for a moment. I -could hear his voice in the hall, asking the way to the nearest -telegraph office. - -Lucy chatted with me freely, and seemed quite unconscious that -anything had happened. I tried to keep her amused and interested. -When her mother came up to see her, she did not seem to notice any -change whatever, but said to me gratefully, - -"We owe you so much, Dr. Seward, for all you have done, but you really -must now take care not to overwork yourself. You are looking pale -yourself. You want a wife to nurse and look after you a bit, that you -do!" As she spoke, Lucy turned crimson, though it was only -momentarily, for her poor wasted veins could not stand for long an -unwonted drain to the head. The reaction came in excessive pallor as -she turned imploring eyes on me. I smiled and nodded, and laid my -finger on my lips. With a sigh, she sank back amid her pillows. - -Van Helsing returned in a couple of hours, and presently said to me: -"Now you go home, and eat much and drink enough. Make yourself -strong. I stay here tonight, and I shall sit up with little miss -myself. You and I must watch the case, and we must have none other to -know. I have grave reasons. No, do not ask me. Think what you will. -Do not fear to think even the most not-improbable. Goodnight." - -In the hall two of the maids came to me, and asked if they or either -of them might not sit up with Miss Lucy. They implored me to let -them, and when I said it was Dr. Van Helsing's wish that either he or -I should sit up, they asked me quite piteously to intercede with -the 'foreign gentleman'. I was much touched by their kindness. Perhaps -it is because I am weak at present, and perhaps because it was on -Lucy's account, that their devotion was manifested. For over and over -again have I seen similar instances of woman's kindness. I got back -here in time for a late dinner, went my rounds, all well, and set this -down whilst waiting for sleep. It is coming. - - -11 September.--This afternoon I went over to Hillingham. Found Van -Helsing in excellent spirits, and Lucy much better. Shortly after I -had arrived, a big parcel from abroad came for the Professor. He -opened it with much impressment, assumed, of course, and showed a -great bundle of white flowers. - -"These are for you, Miss Lucy," he said. - -"For me? Oh, Dr. Van Helsing!" - -"Yes, my dear, but not for you to play with. These are medicines." -Here Lucy made a wry face. "Nay, but they are not to take in a -decoction or in nauseous form, so you need not snub that so charming -nose, or I shall point out to my friend Arthur what woes he may have -to endure in seeing so much beauty that he so loves so much distort. -Aha, my pretty miss, that bring the so nice nose all straight again. -This is medicinal, but you do not know how. I put him in your window, -I make pretty wreath, and hang him round your neck, so you sleep well. -Oh, yes! They, like the lotus flower, make your trouble forgotten. -It smell so like the waters of Lethe, and of that fountain of youth -that the Conquistadores sought for in the Floridas, and find him all -too late." - -Whilst he was speaking, Lucy had been examining the flowers and -smelling them. Now she threw them down saying, with half laughter, -and half disgust, - -"Oh, Professor, I believe you are only putting up a joke on me. Why, -these flowers are only common garlic." - -To my surprise, Van Helsing rose up and said with all his sternness, -his iron jaw set and his bushy eyebrows meeting, - -"No trifling with me! I never jest! There is grim purpose in what I -do, and I warn you that you do not thwart me. Take care, for the sake -of others if not for your own." Then seeing poor Lucy scared, as she -might well be, he went on more gently, "Oh, little miss, my dear, do -not fear me. I only do for your good, but there is much virtue to you -in those so common flowers. See, I place them myself in your room. I -make myself the wreath that you are to wear. But hush! No telling to -others that make so inquisitive questions. We must obey, and silence -is a part of obedience, and obedience is to bring you strong and well -into loving arms that wait for you. Now sit still a while. Come with -me, friend John, and you shall help me deck the room with my garlic, -which is all the way from Haarlem, where my friend Vanderpool raise -herb in his glass houses all the year. I had to telegraph yesterday, -or they would not have been here." - -We went into the room, taking the flowers with us. The Professor's -actions were certainly odd and not to be found in any pharmacopeia -that I ever heard of. First he fastened up the windows and latched -them securely. Next, taking a handful of the flowers, he rubbed them -all over the sashes, as though to ensure that every whiff of air that -might get in would be laden with the garlic smell. Then with the wisp -he rubbed all over the jamb of the door, above, below, and at each -side, and round the fireplace in the same way. It all seemed -grotesque to me, and presently I said, "Well, Professor, I know you -always have a reason for what you do, but this certainly puzzles me. -It is well we have no sceptic here, or he would say that you were -working some spell to keep out an evil spirit." - -"Perhaps I am!" he answered quietly as he began to make the wreath -which Lucy was to wear round her neck. - -We then waited whilst Lucy made her toilet for the night, and when she -was in bed he came and himself fixed the wreath of garlic round her -neck. The last words he said to her were, - -"Take care you do not disturb it, and even if the room feel close, do -not tonight open the window or the door." - -"I promise," said Lucy. "And thank you both a thousand times for all -your kindness to me! Oh, what have I done to be blessed with such -friends?" - -As we left the house in my fly, which was waiting, Van Helsing said, -"Tonight I can sleep in peace, and sleep I want, two nights of travel, -much reading in the day between, and much anxiety on the day to -follow, and a night to sit up, without to wink. Tomorrow in the -morning early you call for me, and we come together to see our pretty -miss, so much more strong for my 'spell' which I have work. Ho, ho!" - -He seemed so confident that I, remembering my own confidence two -nights before and with the baneful result, felt awe and vague terror. -It must have been my weakness that made me hesitate to tell it to my -friend, but I felt it all the more, like unshed tears. - - - - -CHAPTER 11 - - -LUCY WESTENRA'S DIARY - -12 September.--How good they all are to me. I quite love that dear -Dr. Van Helsing. I wonder why he was so anxious about these flowers. -He positively frightened me, he was so fierce. And yet he must have -been right, for I feel comfort from them already. Somehow, I do not -dread being alone tonight, and I can go to sleep without fear. I -shall not mind any flapping outside the window. Oh, the terrible -struggle that I have had against sleep so often of late, the pain of -sleeplessness, or the pain of the fear of sleep, and with such unknown -horrors as it has for me! How blessed are some people, whose lives -have no fears, no dreads, to whom sleep is a blessing that comes -nightly, and brings nothing but sweet dreams. Well, here I am -tonight, hoping for sleep, and lying like Ophelia in the play, with -'virgin crants and maiden strewments.' I never liked garlic before, -but tonight it is delightful! There is peace in its smell. I feel -sleep coming already. Goodnight, everybody. - - - -DR. SEWARD'S DIARY - -13 September.--Called at the Berkeley and found Van Helsing, as usual, -up to time. The carriage ordered from the hotel was waiting. The -Professor took his bag, which he always brings with him now. - -Let all be put down exactly. Van Helsing and I arrived at Hillingham -at eight o'clock. It was a lovely morning. The bright sunshine and -all the fresh feeling of early autumn seemed like the completion of -nature's annual work. The leaves were turning to all kinds of -beautiful colours, but had not yet begun to drop from the trees. When -we entered we met Mrs. Westenra coming out of the morning room. She -is always an early riser. She greeted us warmly and said, - -"You will be glad to know that Lucy is better. The dear child is -still asleep. I looked into her room and saw her, but did not go in, -lest I should disturb her." The Professor smiled, and looked quite -jubilant. He rubbed his hands together, and said, "Aha! I thought I -had diagnosed the case. My treatment is working." - -To which she replied, "You must not take all the credit to yourself, -doctor. Lucy's state this morning is due in part to me." - -"How do you mean, ma'am?" asked the Professor. - -"Well, I was anxious about the dear child in the night, and went into -her room. She was sleeping soundly, so soundly that even my coming -did not wake her. But the room was awfully stuffy. There were a lot -of those horrible, strong-smelling flowers about everywhere, and she -had actually a bunch of them round her neck. I feared that the heavy -odour would be too much for the dear child in her weak state, so I took -them all away and opened a bit of the window to let in a little fresh -air. You will be pleased with her, I am sure." - -She moved off into her boudoir, where she usually breakfasted early. -As she had spoken, I watched the Professor's face, and saw it turn -ashen gray. He had been able to retain his self-command whilst the -poor lady was present, for he knew her state and how mischievous a -shock would be. He actually smiled on her as he held open the door -for her to pass into her room. But the instant she had disappeared he -pulled me, suddenly and forcibly, into the dining room and closed the -door. - -Then, for the first time in my life, I saw Van Helsing break down. He -raised his hands over his head in a sort of mute despair, and then -beat his palms together in a helpless way. Finally he sat down on a -chair, and putting his hands before his face, began to sob, with loud, -dry sobs that seemed to come from the very racking of his heart. - -Then he raised his arms again, as though appealing to the whole -universe. "God! God! God!" he said. "What have we done, what has -this poor thing done, that we are so sore beset? Is there fate -amongst us still, send down from the pagan world of old, that such -things must be, and in such way? This poor mother, all unknowing, and -all for the best as she think, does such thing as lose her daughter -body and soul, and we must not tell her, we must not even warn her, or -she die, then both die. Oh, how we are beset! How are all the powers -of the devils against us!" - -Suddenly he jumped to his feet. "Come," he said, "come, we must see and -act. Devils or no devils, or all the devils at once, it matters not. -We must fight him all the same." He went to the hall door for his -bag, and together we went up to Lucy's room. - -Once again I drew up the blind, whilst Van Helsing went towards the -bed. This time he did not start as he looked on the poor face with -the same awful, waxen pallor as before. He wore a look of stern -sadness and infinite pity. - -"As I expected," he murmured, with that hissing inspiration of his -which meant so much. Without a word he went and locked the door, and -then began to set out on the little table the instruments for yet -another operation of transfusion of blood. I had long ago recognized -the necessity, and begun to take off my coat, but he stopped me with a -warning hand. "No!" he said. "Today you must operate. I shall -provide. You are weakened already." As he spoke he took off his coat -and rolled up his shirtsleeve. - -Again the operation. Again the narcotic. Again some return of colour -to the ashy cheeks, and the regular breathing of healthy sleep. This -time I watched whilst Van Helsing recruited himself and rested. - -Presently he took an opportunity of telling Mrs. Westenra that she -must not remove anything from Lucy's room without consulting him. -That the flowers were of medicinal value, and that the breathing of -their odour was a part of the system of cure. Then he took over the -care of the case himself, saying that he would watch this night and -the next, and would send me word when to come. - -After another hour Lucy waked from her sleep, fresh and bright and -seemingly not much the worse for her terrible ordeal. - -What does it all mean? I am beginning to wonder if my long habit of -life amongst the insane is beginning to tell upon my own brain. - - - -LUCY WESTENRA'S DIARY - -17 September.--Four days and nights of peace. I am getting so strong -again that I hardly know myself. It is as if I had passed through -some long nightmare, and had just awakened to see the beautiful -sunshine and feel the fresh air of the morning around me. I have a -dim half remembrance of long, anxious times of waiting and fearing, -darkness in which there was not even the pain of hope to make present -distress more poignant. And then long spells of oblivion, and the -rising back to life as a diver coming up through a great press of -water. Since, however, Dr. Van Helsing has been with me, all this bad -dreaming seems to have passed away. The noises that used to frighten -me out of my wits, the flapping against the windows, the distant -voices which seemed so close to me, the harsh sounds that came from I -know not where and commanded me to do I know not what, have all -ceased. I go to bed now without any fear of sleep. I do not even try -to keep awake. I have grown quite fond of the garlic, and a boxful -arrives for me every day from Haarlem. Tonight Dr. Van Helsing is -going away, as he has to be for a day in Amsterdam. But I need not be -watched. I am well enough to be left alone. - -Thank God for Mother's sake, and dear Arthur's, and for all our -friends who have been so kind! I shall not even feel the change, for -last night Dr. Van Helsing slept in his chair a lot of the time. I -found him asleep twice when I awoke. But I did not fear to go to -sleep again, although the boughs or bats or something flapped almost -angrily against the window panes. - - - - -THE PALL MALL GAZETTE 18 September. - -THE ESCAPED WOLF PERILOUS ADVENTURE OF OUR INTERVIEWER - -INTERVIEW WITH THE KEEPER IN THE ZOOLOGICAL GARDENS - -After many inquiries and almost as many refusals, and perpetually -using the words 'PALL MALL GAZETTE' as a sort of talisman, I managed -to find the keeper of the section of the Zoological Gardens in which -the wolf department is included. Thomas Bilder lives in one of the -cottages in the enclosure behind the elephant house, and was just -sitting down to his tea when I found him. Thomas and his wife are -hospitable folk, elderly, and without children, and if the specimen -I enjoyed of their hospitality be of the average kind, their lives -must be pretty comfortable. The keeper would not enter on what he -called business until the supper was over, and we were all -satisfied. Then when the table was cleared, and he had lit his -pipe, he said, - -"Now, Sir, you can go on and arsk me what you want. You'll excoose -me refoosin' to talk of perfeshunal subjucts afore meals. I gives -the wolves and the jackals and the hyenas in all our section their -tea afore I begins to arsk them questions." - -"How do you mean, ask them questions?" I queried, wishful to get him -into a talkative humor. - -"'Ittin' of them over the 'ead with a pole is one way. Scratchin' of -their ears in another, when gents as is flush wants a bit of a show-orf -to their gals. I don't so much mind the fust, the 'ittin of the -pole part afore I chucks in their dinner, but I waits till they've -'ad their sherry and kawffee, so to speak, afore I tries on with the -ear scratchin'. Mind you," he added philosophically, "there's a -deal of the same nature in us as in them theer animiles. Here's you -a-comin' and arskin' of me questions about my business, and I that -grump-like that only for your bloomin' 'arf-quid I'd 'a' seen you -blowed fust 'fore I'd answer. Not even when you arsked me sarcastic -like if I'd like you to arsk the Superintendent if you might arsk me -questions. Without offence did I tell yer to go to 'ell?" - -"You did." - -"An' when you said you'd report me for usin' obscene language that -was 'ittin' me over the 'ead. But the 'arf-quid made that all -right. I weren't a-goin' to fight, so I waited for the food, and -did with my 'owl as the wolves and lions and tigers does. But, lor' -love yer 'art, now that the old 'ooman has stuck a chunk of her -tea-cake in me, an' rinsed me out with her bloomin' old teapot, and I've -lit hup, you may scratch my ears for all you're worth, and won't -even get a growl out of me. Drive along with your questions. I -know what yer a-comin' at, that 'ere escaped wolf." - -"Exactly. I want you to give me your view of it. Just tell me how -it happened, and when I know the facts I'll get you to say what you -consider was the cause of it, and how you think the whole affair -will end." - -"All right, guv'nor. This 'ere is about the 'ole story. -That 'ere wolf what we called Bersicker was one of three gray -ones that came from Norway to Jamrach's, which we bought -off him four years ago. He was a nice well-behaved wolf, -that never gave no trouble to talk of. I'm more surprised -at 'im for wantin' to get out nor any other animile in the -place. But, there, you can't trust wolves no more nor women." - -"Don't you mind him, Sir!" broke in Mrs. Tom, with a cheery -laugh. "'E's got mindin' the animiles so long that blest -if he ain't like a old wolf 'isself! But there ain't no -'arm in 'im." - -"Well, Sir, it was about two hours after feedin' yesterday when I -first hear my disturbance. I was makin' up a litter in the monkey -house for a young puma which is ill. But when I heard the yelpin' -and 'owlin' I kem away straight. There was Bersicker a-tearin' like -a mad thing at the bars as if he wanted to get out. There wasn't -much people about that day, and close at hand was only one man, a -tall, thin chap, with a 'ook nose and a pointed beard, with a few -white hairs runnin' through it. He had a 'ard, cold look and red -eyes, and I took a sort of mislike to him, for it seemed as if it -was 'im as they was hirritated at. He 'ad white kid gloves on 'is -'ands, and he pointed out the animiles to me and says, 'Keeper, -these wolves seem upset at something.' - -"'Maybe it's you,' says I, for I did not like the airs as he -give 'isself. He didn't get angry, as I 'oped he would, but -he smiled a kind of insolent smile, with a mouth full of white, -sharp teeth. 'Oh no, they wouldn't like me,' 'e says. - -"'Ow yes, they would,' says I, a-imitatin' of him. 'They -always like a bone or two to clean their teeth on about tea -time, which you 'as a bagful.' - -"Well, it was a odd thing, but when the animiles see us -a-talkin' they lay down, and when I went over to Bersicker -he let me stroke his ears same as ever. That there man kem -over, and blessed but if he didn't put in his hand and stroke -the old wolf's ears too! - -"'Tyke care,' says I. 'Bersicker is quick.' - -"'Never mind,' he says. I'm used to 'em!' - -"'Are you in the business yourself?' I says, tyking off my -'at, for a man what trades in wolves, anceterer, is a good -friend to keepers. - -"'Nom,' says he, 'not exactly in the business, but I 'ave made pets -of several.' And with that he lifts his 'at as perlite as a lord, -and walks away. Old Bersicker kep' a-lookin' arter 'im till 'e was -out of sight, and then went and lay down in a corner and wouldn't -come hout the 'ole hevening. Well, larst night, so soon as the moon -was hup, the wolves here all began a-'owling. There warn't nothing -for them to 'owl at. There warn't no one near, except some one that -was evidently a-callin' a dog somewheres out back of the gardings in -the Park road. Once or twice I went out to see that all was right, -and it was, and then the 'owling stopped. Just before twelve -o'clock I just took a look round afore turnin' in, an', bust me, but -when I kem opposite to old Bersicker's cage I see the rails broken -and twisted about and the cage empty. And that's all I know for -certing." - -"Did any one else see anything?" - -"One of our gard'ners was a-comin' 'ome about that time from a -'armony, when he sees a big gray dog comin' out through the garding -'edges. At least, so he says, but I don't give much for it myself, -for if he did 'e never said a word about it to his missis when 'e -got 'ome, and it was only after the escape of the wolf was made -known, and we had been up all night a-huntin' of the Park for -Bersicker, that he remembered seein' anything. My own belief was -that the 'armony 'ad got into his 'ead." - -"Now, Mr. Bilder, can you account in any way for the escape -of the wolf?" - -"Well, Sir," he said, with a suspicious sort of modesty, "I think I -can, but I don't know as 'ow you'd be satisfied with the theory." - -"Certainly I shall. If a man like you, who knows the animals from -experience, can't hazard a good guess at any rate, who is even to -try?" - -"Well then, Sir, I accounts for it this way. It seems to me that -'ere wolf escaped--simply because he wanted to get out." - -From the hearty way that both Thomas and his wife laughed at the -joke I could see that it had done service before, and that the whole -explanation was simply an elaborate sell. I couldn't cope in -badinage with the worthy Thomas, but I thought I knew a surer way to -his heart, so I said, "Now, Mr. Bilder, we'll consider that first -half-sovereign worked off, and this brother of his is waiting to be -claimed when you've told me what you think will happen." - -"Right y'are, Sir," he said briskly. "Ye'll excoose me, I -know, for a-chaffin' of ye, but the old woman here winked at -me, which was as much as telling me to go on." - -"Well, I never!" said the old lady. - -"My opinion is this: that 'ere wolf is a'idin' of, somewheres. The -gard'ner wot didn't remember said he was a-gallopin' northward -faster than a horse could go, but I don't believe him, for, yer see, -Sir, wolves don't gallop no more nor dogs does, they not bein' built -that way. Wolves is fine things in a storybook, and I dessay when -they gets in packs and does be chivyin' somethin' that's more -afeared than they is they can make a devil of a noise and chop it -up, whatever it is. But, Lor' bless you, in real life a wolf is -only a low creature, not half so clever or bold as a good dog, and -not half a quarter so much fight in 'im. This one ain't been used -to fightin' or even to providin' for hisself, and more like he's -somewhere round the Park a'hidin' an' a'shiverin' of, and if he -thinks at all, wonderin' where he is to get his breakfast from. Or -maybe he's got down some area and is in a coal cellar. My eye, -won't some cook get a rum start when she sees his green eyes -a-shinin' at her out of the dark! If he can't get food he's bound to -look for it, and mayhap he may chance to light on a butcher's shop -in time. If he doesn't, and some nursemaid goes out walkin' or orf -with a soldier, leavin' of the hinfant in the perambulator--well, -then I shouldn't be surprised if the census is one babby the less. -That's all." - -I was handing him the half-sovereign, when something came bobbing up -against the window, and Mr. Bilder's face doubled its natural length -with surprise. - -"God bless me!" he said. "If there ain't old Bersicker come back by -'isself!" - -He went to the door and opened it, a most unnecessary proceeding it -seemed to me. I have always thought that a wild animal never looks -so well as when some obstacle of pronounced durability is between -us. A personal experience has intensified rather than diminished -that idea. - -After all, however, there is nothing like custom, for neither Bilder -nor his wife thought any more of the wolf than I should of a dog. -The animal itself was a peaceful and well-behaved as that father of -all picture-wolves, Red Riding Hood's quondam friend, whilst moving -her confidence in masquerade. - -The whole scene was a unutterable mixture of comedy and -pathos. The wicked wolf that for a half a day had -paralyzed London and set all the children in town shivering -in their shoes, was there in a sort of penitent mood, and -was received and petted like a sort of vulpine prodigal -son. Old Bilder examined him all over with most tender -solicitude, and when he had finished with his penitent -said, - -"There, I knew the poor old chap would get into some kind of -trouble. Didn't I say it all along? Here's his head all -cut and full of broken glass. 'E's been a-gettin' over -some bloomin' wall or other. It's a shyme that people are -allowed to top their walls with broken bottles. This 'ere's -what comes of it. Come along, Bersicker." - -He took the wolf and locked him up in a cage, with a piece -of meat that satisfied, in quantity at any rate, the elementary -conditions of the fatted calf, and went off to report. - -I came off too, to report the only exclusive information -that is given today regarding the strange escapade at the -Zoo. - - - -DR. SEWARD'S DIARY - -17 September.--I was engaged after dinner in my study posting up my -books, which, through press of other work and the many visits to Lucy, -had fallen sadly into arrear. Suddenly the door was burst open, and -in rushed my patient, with his face distorted with passion. I was -thunderstruck, for such a thing as a patient getting of his own accord -into the Superintendent's study is almost unknown. - -Without an instant's notice he made straight at me. He had a dinner -knife in his hand, and as I saw he was dangerous, I tried to keep the -table between us. He was too quick and too strong for me, however, -for before I could get my balance he had struck at me and cut my left -wrist rather severely. - -Before he could strike again, however, I got in my right hand and he -was sprawling on his back on the floor. My wrist bled freely, and -quite a little pool trickled on to the carpet. I saw that my friend -was not intent on further effort, and occupied myself binding up my -wrist, keeping a wary eye on the prostrate figure all the time. When -the attendants rushed in, and we turned our attention to him, his -employment positively sickened me. He was lying on his belly on the -floor licking up, like a dog, the blood which had fallen from my -wounded wrist. He was easily secured, and to my surprise, went with -the attendants quite placidly, simply repeating over and over again, -"The blood is the life! The blood is the life!" - -I cannot afford to lose blood just at present. I have lost too much -of late for my physical good, and then the prolonged strain of Lucy's -illness and its horrible phases is telling on me. I am over excited -and weary, and I need rest, rest, rest. Happily Van Helsing has not -summoned me, so I need not forego my sleep. Tonight I could not well -do without it. - - - -TELEGRAM, VAN HELSING, ANTWERP, TO SEWARD, CARFAX - -(Sent to Carfax, Sussex, as no county given, delivered late -by twenty-two hours.) - -17 September.--Do not fail to be at Hilllingham tonight. -If not watching all the time, frequently visit and see that -flowers are as placed, very important, do not fail. Shall -be with you as soon as possible after arrival. - - - -DR. SEWARD'S DIARY - -18 September.--Just off train to London. The arrival of Van -Helsing's telegram filled me with dismay. A whole night lost, -and I know by bitter experience what may happen in a night. -Of course it is possible that all may be well, but what may -have happened? Surely there is some horrible doom hanging over us -that every possible accident should thwart us in all we try to do. -I shall take this cylinder with me, and then I can complete -my entry on Lucy's phonograph. - - - - -MEMORANDUM LEFT BY LUCY WESTENRA - -17 September, Night.--I write this and leave it to be seen, -so that no one may by any chance get into trouble through -me. This is an exact record of what took place tonight. I -feel I am dying of weakness, and have barely strength to -write, but it must be done if I die in the doing. - -I went to bed as usual, taking care that the flowers were -placed as Dr. Van Helsing directed, and soon fell asleep. - -I was waked by the flapping at the window, which had begun after -that sleep-walking on the cliff at Whitby when Mina saved me, and -which now I know so well. I was not afraid, but I did wish that -Dr. Seward was in the next room, as Dr. Van Helsing said he would -be, so that I might have called him. I tried to sleep, but I -could not. Then there came to me the old fear of sleep, and I -determined to keep awake. Perversely sleep would try to come then -when I did not want it. So, as I feared to be alone, I opened my -door and called out, "Is there anybody there?" There was no -answer. I was afraid to wake mother, and so closed my door -again. Then outside in the shrubbery I heard a sort of howl like -a dog's, but more fierce and deeper. I went to the window and -looked out, but could see nothing, except a big bat, which had -evidently been buffeting its wings against the window. So I went -back to bed again, but determined not to go to sleep. Presently -the door opened, and mother looked in. Seeing by my moving that -I was not asleep, she came in and sat by me. She said to me even -more sweetly and softly than her wont, - -"I was uneasy about you, darling, and came in to see that -you were all right." - -I feared she might catch cold sitting there, and asked her -to come in and sleep with me, so she came into bed, and lay -down beside me. She did not take off her dressing gown, -for she said she would only stay a while and then go back -to her own bed. As she lay there in my arms, and I in hers -the flapping and buffeting came to the window again. She -was startled and a little frightened, and cried out, "What -is that?" - -I tried to pacify her, and at last succeeded, and she lay -quiet. But I could hear her poor dear heart still beating -terribly. After a while there was the howl again out in -the shrubbery, and shortly after there was a crash at the -window, and a lot of broken glass was hurled on the floor. -The window blind blew back with the wind that rushed in, -and in the aperture of the broken panes there was the head -of a great, gaunt gray wolf. - -Mother cried out in a fright, and struggled up into a -sitting posture, and clutched wildly at anything that would -help her. Amongst other things, she clutched the wreath of -flowers that Dr. Van Helsing insisted on my wearing round -my neck, and tore it away from me. For a second or two she -sat up, pointing at the wolf, and there was a strange and -horrible gurgling in her throat. Then she fell over, as if -struck with lightning, and her head hit my forehead and -made me dizzy for a moment or two. - -The room and all round seemed to spin round. I kept my eyes -fixed on the window, but the wolf drew his head back, and a whole -myriad of little specks seems to come blowing in through the -broken window, and wheeling and circling round like the pillar of -dust that travellers describe when there is a simoon in the -desert. I tried to stir, but there was some spell upon me, and -dear Mother's poor body, which seemed to grow cold already, for -her dear heart had ceased to beat, weighed me down, and I -remembered no more for a while. - -The time did not seem long, but very, very awful, till I -recovered consciousness again. Somewhere near, a passing -bell was tolling. The dogs all round the neighbourhood were -howling, and in our shrubbery, seemingly just outside, a -nightingale was singing. I was dazed and stupid with pain -and terror and weakness, but the sound of the nightingale -seemed like the voice of my dead mother come back to comfort me. -The sounds seemed to have awakened the maids, too, for I could -hear their bare feet pattering outside my door. I called to -them, and they came in, and when they saw what had happened, and -what it was that lay over me on the bed, they screamed out. The -wind rushed in through the broken window, and the door slammed -to. They lifted off the body of my dear mother, and laid her, -covered up with a sheet, on the bed after I had got up. They -were all so frightened and nervous that I directed them to go to -the dining room and each have a glass of wine. The door flew -open for an instant and closed again. The maids shrieked, and -then went in a body to the dining room, and I laid what flowers I -had on my dear mother's breast. When they were there I -remembered what Dr. Van Helsing had told me, but I didn't like to -remove them, and besides, I would have some of the servants to -sit up with me now. I was surprised that the maids did not come -back. I called them, but got no answer, so I went to the dining -room to look for them. - -My heart sank when I saw what had happened. They all four -lay helpless on the floor, breathing heavily. The decanter -of sherry was on the table half full, but there was a queer, -acrid smell about. I was suspicious, and examined the decanter. -It smelt of laudanum, and looking on the sideboard, I found that -the bottle which Mother's doctor uses for her--oh! did use--was -empty. What am I to do? What am I to do? I am back in the room -with Mother. I cannot leave her, and I am alone, save for the -sleeping servants, whom some one has drugged. Alone with the -dead! I dare not go out, for I can hear the low howl of the wolf -through the broken window. - -The air seems full of specks, floating and circling in the -draught from the window, and the lights burn blue and dim. -What am I to do? God shield me from harm this night! I -shall hide this paper in my breast, where they shall find -it when they come to lay me out. My dear mother gone! It -is time that I go too. Goodbye, dear Arthur, if I should -not survive this night. God keep you, dear, and God help -me! - - - - -CHAPTER 12 - - -DR. SEWARD'S DIARY - -18 September.--I drove at once to Hillingham and arrived early. -Keeping my cab at the gate, I went up the avenue alone. I knocked -gently and rang as quietly as possible, for I feared to disturb Lucy -or her mother, and hoped to only bring a servant to the door. After a -while, finding no response, I knocked and rang again, still no -answer. I cursed the laziness of the servants that they should lie -abed at such an hour, for it was now ten o'clock, and so rang and -knocked again, but more impatiently, but still without response. -Hitherto I had blamed only the servants, but now a terrible fear began -to assail me. Was this desolation but another link in the chain of -doom which seemed drawing tight round us? Was it indeed a house of -death to which I had come, too late? I know that minutes, even -seconds of delay, might mean hours of danger to Lucy, if she had had -again one of those frightful relapses, and I went round the house to -try if I could find by chance an entry anywhere. - -I could find no means of ingress. Every window and door was fastened -and locked, and I returned baffled to the porch. As I did so, I heard -the rapid pit-pat of a swiftly driven horse's feet. They stopped at -the gate, and a few seconds later I met Van Helsing running up the -avenue. When he saw me, he gasped out, "Then it was you, and just -arrived. How is she? Are we too late? Did you not get my telegram?" - -I answered as quickly and coherently as I could that I had only got -his telegram early in the morning, and had not a minute in coming -here, and that I could not make any one in the house hear me. He -paused and raised his hat as he said solemnly, "Then I fear we are too -late. God's will be done!" - -With his usual recuperative energy, he went on, "Come. If there be no -way open to get in, we must make one. Time is all in all to us now." - -We went round to the back of the house, where there was a kitchen -window. The Professor took a small surgical saw from his case, and -handing it to me, pointed to the iron bars which guarded the window. -I attacked them at once and had very soon cut through three of them. -Then with a long, thin knife we pushed back the fastening of the -sashes and opened the window. I helped the Professor in, and followed -him. There was no one in the kitchen or in the servants' rooms, which -were close at hand. We tried all the rooms as we went along, and in -the dining room, dimly lit by rays of light through the shutters, -found four servant women lying on the floor. There was no need to -think them dead, for their stertorous breathing and the acrid smell of -laudanum in the room left no doubt as to their condition. - -Van Helsing and I looked at each other, and as we moved away he said, -"We can attend to them later." Then we ascended to Lucy's room. For an -instant or two we paused at the door to listen, but there was no sound -that we could hear. With white faces and trembling hands, we opened -the door gently, and entered the room. - -How shall I describe what we saw? On the bed lay two women, Lucy and -her mother. The latter lay farthest in, and she was covered with a -white sheet, the edge of which had been blown back by the drought -through the broken window, showing the drawn, white, face, with a look -of terror fixed upon it. By her side lay Lucy, with face white and -still more drawn. The flowers which had been round her neck we found -upon her mother's bosom, and her throat was bare, showing the two -little wounds which we had noticed before, but looking horribly white -and mangled. Without a word the Professor bent over the bed, his head -almost touching poor Lucy's breast. Then he gave a quick turn of his -head, as of one who listens, and leaping to his feet, he cried out to -me, "It is not yet too late! Quick! Quick! Bring the brandy!" - -I flew downstairs and returned with it, taking care to smell and taste -it, lest it, too, were drugged like the decanter of sherry which I -found on the table. The maids were still breathing, but more -restlessly, and I fancied that the narcotic was wearing off. I did -not stay to make sure, but returned to Van Helsing. He rubbed the -brandy, as on another occasion, on her lips and gums and on her wrists -and the palms of her hands. He said to me, "I can do this, all that -can be at the present. You go wake those maids. Flick them in the -face with a wet towel, and flick them hard. Make them get heat and -fire and a warm bath. This poor soul is nearly as cold as that beside -her. She will need be heated before we can do anything more." - -I went at once, and found little difficulty in waking three of the -women. The fourth was only a young girl, and the drug had evidently -affected her more strongly so I lifted her on the sofa and let her -sleep. - -The others were dazed at first, but as remembrance came back to them -they cried and sobbed in a hysterical manner. I was stern with them, -however, and would not let them talk. I told them that one life was -bad enough to lose, and if they delayed they would sacrifice Miss -Lucy. So, sobbing and crying they went about their way, half clad as -they were, and prepared fire and water. Fortunately, the kitchen and -boiler fires were still alive, and there was no lack of hot water. We -got a bath and carried Lucy out as she was and placed her in it. -Whilst we were busy chafing her limbs there was a knock at the hall -door. One of the maids ran off, hurried on some more clothes, and -opened it. Then she returned and whispered to us that there was a -gentleman who had come with a message from Mr. Holmwood. I bade her -simply tell him that he must wait, for we could see no one now. She -went away with the message, and, engrossed with our work, I clean -forgot all about him. - -I never saw in all my experience the Professor work in such deadly -earnest. I knew, as he knew, that it was a stand-up fight with death, -and in a pause told him so. He answered me in a way that I did not -understand, but with the sternest look that his face could wear. - -"If that were all, I would stop here where we are now, and let her -fade away into peace, for I see no light in life over her horizon." He -went on with his work with, if possible, renewed and more frenzied -vigour. - -Presently we both began to be conscious that the heat was beginning to -be of some effect. Lucy's heart beat a trifle more audibly to the -stethoscope, and her lungs had a perceptible movement. Van Helsing's -face almost beamed, and as we lifted her from the bath and rolled her -in a hot sheet to dry her he said to me, "The first gain is ours! -Check to the King!" - -We took Lucy into another room, which had by now been prepared, and -laid her in bed and forced a few drops of brandy down her throat. I -noticed that Van Helsing tied a soft silk handkerchief round her -throat. She was still unconscious, and was quite as bad as, if not -worse than, we had ever seen her. - -Van Helsing called in one of the women, and told her to stay with her -and not to take her eyes off her till we returned, and then beckoned -me out of the room. - -"We must consult as to what is to be done," he said as we descended -the stairs. In the hall he opened the dining room door, and we passed -in, he closing the door carefully behind him. The shutters had been -opened, but the blinds were already down, with that obedience to the -etiquette of death which the British woman of the lower classes always -rigidly observes. The room was, therefore, dimly dark. It was, -however, light enough for our purposes. Van Helsing's sternness was -somewhat relieved by a look of perplexity. He was evidently torturing -his mind about something, so I waited for an instant, and he spoke. - -"What are we to do now? Where are we to turn for help? We must have -another transfusion of blood, and that soon, or that poor girl's life -won't be worth an hour's purchase. You are exhausted already. I am -exhausted too. I fear to trust those women, even if they would have -courage to submit. What are we to do for some one who will open his -veins for her?" - -"What's the matter with me, anyhow?" - -The voice came from the sofa across the room, and its tones brought -relief and joy to my heart, for they were those of Quincey Morris. - -Van Helsing started angrily at the first sound, but his face softened -and a glad look came into his eyes as I cried out, "Quincey Morris!" -and rushed towards him with outstretched hands. - -"What brought you here?" I cried as our hands met. - -"I guess Art is the cause." - -He handed me a telegram.--'Have not heard from Seward for three days, -and am terribly anxious. Cannot leave. Father still in same -condition. Send me word how Lucy is. Do not delay.--Holmwood.' - -"I think I came just in the nick of time. You know you have only to -tell me what to do." - -Van Helsing strode forward, and took his hand, looking him straight in -the eyes as he said, "A brave man's blood is the best thing on this -earth when a woman is in trouble. You're a man and no mistake. Well, -the devil may work against us for all he's worth, but God sends us men -when we want them." - -Once again we went through that ghastly operation. I have not the -heart to go through with the details. Lucy had got a terrible shock -and it told on her more than before, for though plenty of blood went -into her veins, her body did not respond to the treatment as well as -on the other occasions. Her struggle back into life was something -frightful to see and hear. However, the action of both heart and -lungs improved, and Van Helsing made a sub-cutaneous injection of -morphia, as before, and with good effect. Her faint became a profound -slumber. The Professor watched whilst I went downstairs with Quincey -Morris, and sent one of the maids to pay off one of the cabmen who -were waiting. - -I left Quincey lying down after having a glass of wine, and told the -cook to get ready a good breakfast. Then a thought struck me, and I -went back to the room where Lucy now was. When I came softly in, I -found Van Helsing with a sheet or two of note paper in his hand. He -had evidently read it, and was thinking it over as he sat with his -hand to his brow. There was a look of grim satisfaction in his face, -as of one who has had a doubt solved. He handed me the paper saying -only, "It dropped from Lucy's breast when we carried her to the bath." - -When I had read it, I stood looking at the Professor, and after a -pause asked him, "In God's name, what does it all mean? Was she, or -is she, mad, or what sort of horrible danger is it?" I was so -bewildered that I did not know what to say more. Van Helsing put out -his hand and took the paper, saying, - -"Do not trouble about it now. Forget it for the present. You shall -know and understand it all in good time, but it will be later. And -now what is it that you came to me to say?" This brought me back to -fact, and I was all myself again. - -"I came to speak about the certificate of death. If we do not act -properly and wisely, there may be an inquest, and that paper would -have to be produced. I am in hopes that we need have no inquest, for -if we had it would surely kill poor Lucy, if nothing else did. I -know, and you know, and the other doctor who attended her knows, that -Mrs. Westenra had disease of the heart, and we can certify that she -died of it. Let us fill up the certificate at once, and I shall take -it myself to the registrar and go on to the undertaker." - -"Good, oh my friend John! Well thought of! Truly Miss Lucy, if she -be sad in the foes that beset her, is at least happy in the friends -that love her. One, two, three, all open their veins for her, besides -one old man. Ah, yes, I know, friend John. I am not blind! I love -you all the more for it! Now go." - -In the hall I met Quincey Morris, with a telegram for Arthur telling -him that Mrs. Westenra was dead, that Lucy also had been ill, but was -now going on better, and that Van Helsing and I were with her. I told -him where I was going, and he hurried me out, but as I was going said, - -"When you come back, Jack, may I have two words with you all to -ourselves?" I nodded in reply and went out. I found no difficulty -about the registration, and arranged with the local undertaker to come -up in the evening to measure for the coffin and to make arrangements. - -When I got back Quincey was waiting for me. I told him I would see -him as soon as I knew about Lucy, and went up to her room. She was -still sleeping, and the Professor seemingly had not moved from his -seat at her side. From his putting his finger to his lips, I gathered -that he expected her to wake before long and was afraid of -fore-stalling nature. So I went down to Quincey and took him into the -breakfast room, where the blinds were not drawn down, and which was a -little more cheerful, or rather less cheerless, than the other rooms. - -When we were alone, he said to me, "Jack Seward, I don't want to shove -myself in anywhere where I've no right to be, but this is no ordinary -case. You know I loved that girl and wanted to marry her, but -although that's all past and gone, I can't help feeling anxious about -her all the same. What is it that's wrong with her? The Dutchman, -and a fine old fellow he is, I can see that, said that time you two -came into the room, that you must have another transfusion of blood, -and that both you and he were exhausted. Now I know well that you -medical men speak in camera, and that a man must not expect to know -what they consult about in private. But this is no common matter, and -whatever it is, I have done my part. Is not that so?" - -"That's so," I said, and he went on. - -"I take it that both you and Van Helsing had done already what I did -today. Is not that so?" - -"That's so." - -"And I guess Art was in it too. When I saw him four days ago down at -his own place he looked queer. I have not seen anything pulled down -so quick since I was on the Pampas and had a mare that I was fond of -go to grass all in a night. One of those big bats that they call -vampires had got at her in the night, and what with his gorge and the -vein left open, there wasn't enough blood in her to let her stand up, -and I had to put a bullet through her as she lay. Jack, if you may -tell me without betraying confidence, Arthur was the first, is not -that so?" - -As he spoke the poor fellow looked terribly anxious. He was in a -torture of suspense regarding the woman he loved, and his utter -ignorance of the terrible mystery which seemed to surround her -intensified his pain. His very heart was bleeding, and it took all -the manhood of him, and there was a royal lot of it, too, to keep him -from breaking down. I paused before answering, for I felt that I must -not betray anything which the Professor wished kept secret, but -already he knew so much, and guessed so much, that there could be no -reason for not answering, so I answered in the same phrase. - -"That's so." - -"And how long has this been going on?" - -"About ten days." - -"Ten days! Then I guess, Jack Seward, that that poor pretty creature -that we all love has had put into her veins within that time the blood -of four strong men. Man alive, her whole body wouldn't hold it." Then -coming close to me, he spoke in a fierce half-whisper. "What took it -out?" - -I shook my head. "That," I said, "is the crux. Van Helsing is simply -frantic about it, and I am at my wits' end. I can't even hazard a -guess. There has been a series of little circumstances which have -thrown out all our calculations as to Lucy being properly watched. -But these shall not occur again. Here we stay until all be well, or -ill." - -Quincey held out his hand. "Count me in," he said. "You and the -Dutchman will tell me what to do, and I'll do it." - -When she woke late in the afternoon, Lucy's first movement was to feel -in her breast, and to my surprise, produced the paper which Van -Helsing had given me to read. The careful Professor had replaced it -where it had come from, lest on waking she should be alarmed. Her -eyes then lit on Van Helsing and on me too, and gladdened. Then she -looked round the room, and seeing where she was, shuddered. She gave -a loud cry, and put her poor thin hands before her pale face. - -We both understood what was meant, that she had realized to the full -her mother's death. So we tried what we could to comfort her. -Doubtless sympathy eased her somewhat, but she was very low in thought -and spirit, and wept silently and weakly for a long time. We told her -that either or both of us would now remain with her all the time, and -that seemed to comfort her. Towards dusk she fell into a doze. Here -a very odd thing occurred. Whilst still asleep she took the paper -from her breast and tore it in two. Van Helsing stepped over and took -the pieces from her. All the same, however, she went on with the -action of tearing, as though the material were still in her hands. -Finally she lifted her hands and opened them as though scattering the -fragments. Van Helsing seemed surprised, and his brows gathered as if -in thought, but he said nothing. - - -19 September.--All last night she slept fitfully, being always afraid -to sleep, and something weaker when she woke from it. The Professor -and I took in turns to watch, and we never left her for a moment -unattended. Quincey Morris said nothing about his intention, but I -knew that all night long he patrolled round and round the house. - -When the day came, its searching light showed the ravages in poor -Lucy's strength. She was hardly able to turn her head, and the little -nourishment which she could take seemed to do her no good. At times -she slept, and both Van Helsing and I noticed the difference in her, -between sleeping and waking. Whilst asleep she looked stronger, -although more haggard, and her breathing was softer. Her open mouth -showed the pale gums drawn back from the teeth, which looked -positively longer and sharper than usual. When she woke the softness -of her eyes evidently changed the expression, for she looked her own -self, although a dying one. In the afternoon she asked for Arthur, -and we telegraphed for him. Quincey went off to meet him at the -station. - -When he arrived it was nearly six o'clock, and the sun was setting -full and warm, and the red light streamed in through the window and -gave more colour to the pale cheeks. When he saw her, Arthur was -simply choking with emotion, and none of us could speak. In the hours -that had passed, the fits of sleep, or the comatose condition that -passed for it, had grown more frequent, so that the pauses when -conversation was possible were shortened. Arthur's presence, however, -seemed to act as a stimulant. She rallied a little, and spoke to him -more brightly than she had done since we arrived. He too pulled -himself together, and spoke as cheerily as he could, so that the best -was made of everything. - -It is now nearly one o'clock, and he and Van Helsing are sitting with -her. I am to relieve them in a quarter of an hour, and I am entering -this on Lucy's phonograph. Until six o'clock they are to try to rest. -I fear that tomorrow will end our watching, for the shock has been too -great. The poor child cannot rally. God help us all. - - - - -LETTER MINA HARKER TO LUCY WESTENRA - -(Unopened by her) - -17 September - -My dearest Lucy, - -"It seems an age since I heard from you, or indeed since I -wrote. You will pardon me, I know, for all my faults when -you have read all my budget of news. Well, I got my husband back -all right. When we arrived at Exeter there was a carriage -waiting for us, and in it, though he had an attack of gout, Mr. -Hawkins. He took us to his house, where there were rooms for us -all nice and comfortable, and we dined together. After dinner -Mr. Hawkins said, - -"'My dears, I want to drink your health and prosperity, and -may every blessing attend you both. I know you both from -children, and have, with love and pride, seen you grow up. -Now I want you to make your home here with me. I have left -to me neither chick nor child. All are gone, and in my -will I have left you everything.' I cried, Lucy dear, as -Jonathan and the old man clasped hands. Our evening was a -very, very happy one. - -"So here we are, installed in this beautiful old house, and -from both my bedroom and the drawing room I can see the -great elms of the cathedral close, with their great black -stems standing out against the old yellow stone of the cathedral, -and I can hear the rooks overhead cawing and cawing and -chattering and chattering and gossiping all day, after the manner -of rooks--and humans. I am busy, I need not tell you, arranging -things and housekeeping. Jonathan and Mr. Hawkins are busy all -day, for now that Jonathan is a partner, Mr. Hawkins wants to -tell him all about the clients. - -"How is your dear mother getting on? I wish I could run up -to town for a day or two to see you, dear, but I dare not -go yet, with so much on my shoulders, and Jonathan wants -looking after still. He is beginning to put some flesh on -his bones again, but he was terribly weakened by the long -illness. Even now he sometimes starts out of his sleep in -a sudden way and awakes all trembling until I can coax him -back to his usual placidity. However, thank God, these -occasions grow less frequent as the days go on, and they -will in time pass away altogether, I trust. And now I have -told you my news, let me ask yours. When are you to be -married, and where, and who is to perform the ceremony, and -what are you to wear, and is it to be a public or private -wedding? Tell me all about it, dear, tell me all about -everything, for there is nothing which interests you which -will not be dear to me. Jonathan asks me to send his 'respectful -duty', but I do not think that is good enough from the junior -partner of the important firm Hawkins & Harker. And so, as you -love me, and he loves me, and I love you with all the moods and -tenses of the verb, I send you simply his 'love' instead. -Goodbye, my dearest Lucy, and blessings on you. - -"Yours, - -"Mina Harker" - - - -REPORT FROM PATRICK HENNESSEY, MD, MRCSLK, QCPI, ETC, ETC, -TO JOHN SEWARD, MD - -20 September - -My dear Sir: - -"In accordance with your wishes, I enclose report of the -conditions of everything left in my charge. With regard to -patient, Renfield, there is more to say. He has had another -outbreak, which might have had a dreadful ending, but which, as -it fortunately happened, was unattended with any unhappy results. -This afternoon a carrier's cart with two men made a call at the -empty house whose grounds abut on ours, the house to which, you -will remember, the patient twice ran away. The men stopped at -our gate to ask the porter their way, as they were strangers. - -"I was myself looking out of the study window, having a -smoke after dinner, and saw one of them come up to the -house. As he passed the window of Renfield's room, the -patient began to rate him from within, and called him all -the foul names he could lay his tongue to. The man, who -seemed a decent fellow enough, contented himself by telling -him to 'shut up for a foul-mouthed beggar', whereon our man -accused him of robbing him and wanting to murder him and -said that he would hinder him if he were to swing for it. -I opened the window and signed to the man not to notice, so -he contented himself after looking the place over and making up -his mind as to what kind of place he had got to by saying, 'Lor' -bless yer, sir, I wouldn't mind what was said to me in a bloomin' -madhouse. I pity ye and the guv'nor for havin' to live in the -house with a wild beast like that.' - -"Then he asked his way civilly enough, and I told him where -the gate of the empty house was. He went away followed by -threats and curses and revilings from our man. I went down -to see if I could make out any cause for his anger, since -he is usually such a well-behaved man, and except his violent -fits nothing of the kind had ever occurred. I found him, to my -astonishment, quite composed and most genial in his manner. I -tried to get him to talk of the incident, but he blandly asked me -questions as to what I meant, and led me to believe that he was -completely oblivious of the affair. It was, I am sorry to say, -however, only another instance of his cunning, for within half an -hour I heard of him again. This time he had broken out through -the window of his room, and was running down the avenue. I -called to the attendants to follow me, and ran after him, for I -feared he was intent on some mischief. My fear was justified -when I saw the same cart which had passed before coming down the -road, having on it some great wooden boxes. The men were wiping -their foreheads, and were flushed in the face, as if with violent -exercise. Before I could get up to him, the patient rushed at -them, and pulling one of them off the cart, began to knock his -head against the ground. If I had not seized him just at the -moment, I believe he would have killed the man there and then. -The other fellow jumped down and struck him over the head with -the butt end of his heavy whip. It was a horrible blow, but he -did not seem to mind it, but seized him also, and struggled with -the three of us, pulling us to and fro as if we were kittens. -You know I am no lightweight, and the others were both burly men. -At first he was silent in his fighting, but as we began to master -him, and the attendants were putting a strait waistcoat on him, -he began to shout, 'I'll frustrate them! They shan't rob me! -They shan't murder me by inches! I'll fight for my Lord and -Master!' and all sorts of similar incoherent ravings. It was -with very considerable difficulty that they got him back to the -house and put him in the padded room. One of the attendants, -Hardy, had a finger broken. However, I set it all right, and he -is going on well. - -"The two carriers were at first loud in their threats of -actions for damages, and promised to rain all the penalties -of the law on us. Their threats were, however, mingled -with some sort of indirect apology for the defeat of the -two of them by a feeble madman. They said that if it had -not been for the way their strength had been spent in carrying -and raising the heavy boxes to the cart they would have made -short work of him. They gave as another reason for their defeat -the extraordinary state of drouth to which they had been reduced -by the dusty nature of their occupation and the reprehensible -distance from the scene of their labors of any place of public -entertainment. I quite understood their drift, and after a stiff -glass of strong grog, or rather more of the same, and with each a -sovereign in hand, they made light of the attack, and swore that -they would encounter a worse madman any day for the pleasure of -meeting so 'bloomin' good a bloke' as your correspondent. I took -their names and addresses, in case they might be needed. They -are as follows: Jack Smollet, of Dudding's Rents, King George's -Road, Great Walworth, and Thomas Snelling, Peter Farley's Row, -Guide Court, Bethnal Green. They are both in the employment of -Harris & Sons, Moving and Shipment Company, Orange Master's Yard, -Soho. - -"I shall report to you any matter of interest occurring here, and -shall wire you at once if there is anything of importance. - -"Believe me, dear Sir, - -"Yours faithfully, - -"Patrick Hennessey." - - - -LETTER, MINA HARKER TO LUCY WESTENRA (Unopened by her) - -18 September - -"My dearest Lucy, - -"Such a sad blow has befallen us. Mr. Hawkins has died very -suddenly. Some may not think it so sad for us, but we had -both come to so love him that it really seems as though we -had lost a father. I never knew either father or mother, -so that the dear old man's death is a real blow to me. Jonathan -is greatly distressed. It is not only that he feels sorrow, deep -sorrow, for the dear, good man who has befriended him all his -life, and now at the end has treated him like his own son and -left him a fortune which to people of our modest bringing up is -wealth beyond the dream of avarice, but Jonathan feels it on -another account. He says the amount of responsibility which it -puts upon him makes him nervous. He begins to doubt himself. I -try to cheer him up, and my belief in him helps him to have a -belief in himself. But it is here that the grave shock that he -experienced tells upon him the most. Oh, it is too hard that a -sweet, simple, noble, strong nature such as his, a nature which -enabled him by our dear, good friend's aid to rise from clerk to -master in a few years, should be so injured that the very essence -of its strength is gone. Forgive me, dear, if I worry you with my -troubles in the midst of your own happiness, but Lucy dear, I -must tell someone, for the strain of keeping up a brave and -cheerful appearance to Jonathan tries me, and I have no one here -that I can confide in. I dread coming up to London, as we must -do that day after tomorrow, for poor Mr. Hawkins left in his will -that he was to be buried in the grave with his father. As there -are no relations at all, Jonathan will have to be chief mourner. -I shall try to run over to see you, dearest, if only for a few -minutes. Forgive me for troubling you. With all blessings, - -"Your loving - -"Mina Harker" - - - -DR. SEWARD'S DIARY - -20 September.--Only resolution and habit can let me make an entry -tonight. I am too miserable, too low spirited, too sick of the world -and all in it, including life itself, that I would not care if I heard -this moment the flapping of the wings of the angel of death. And he -has been flapping those grim wings to some purpose of late, Lucy's -mother and Arthur's father, and now . . . Let me get on with my work. - -I duly relieved Van Helsing in his watch over Lucy. We wanted Arthur -to go to rest also, but he refused at first. It was only when I told -him that we should want him to help us during the day, and that we -must not all break down for want of rest, lest Lucy should suffer, -that he agreed to go. - -Van Helsing was very kind to him. "Come, my child," he said. "Come -with me. You are sick and weak, and have had much sorrow and much -mental pain, as well as that tax on your strength that we know of. -You must not be alone, for to be alone is to be full of fears and -alarms. Come to the drawing room, where there is a big fire, and -there are two sofas. You shall lie on one, and I on the other, and -our sympathy will be comfort to each other, even though we do not -speak, and even if we sleep." - -Arthur went off with him, casting back a longing look on Lucy's face, -which lay in her pillow, almost whiter than the lawn. She lay quite -still, and I looked around the room to see that all was as it should -be. I could see that the Professor had carried out in this room, as -in the other, his purpose of using the garlic. The whole of the -window sashes reeked with it, and round Lucy's neck, over the silk -handkerchief which Van Helsing made her keep on, was a rough chaplet -of the same odorous flowers. - -Lucy was breathing somewhat stertorously, and her face was at its -worst, for the open mouth showed the pale gums. Her teeth, in the -dim, uncertain light, seemed longer and sharper than they had been in -the morning. In particular, by some trick of the light, the canine -teeth looked longer and sharper than the rest. - -I sat down beside her, and presently she moved uneasily. At the same -moment there came a sort of dull flapping or buffeting at the window. -I went over to it softly, and peeped out by the corner of the blind. -There was a full moonlight, and I could see that the noise was made by -a great bat, which wheeled around, doubtless attracted by the light, -although so dim, and every now and again struck the window with its -wings. When I came back to my seat, I found that Lucy had moved -slightly, and had torn away the garlic flowers from her throat. I -replaced them as well as I could, and sat watching her. - -Presently she woke, and I gave her food, as Van Helsing had -prescribed. She took but a little, and that languidly. There did not -seem to be with her now the unconscious struggle for life and strength -that had hitherto so marked her illness. It struck me as curious that -the moment she became conscious she pressed the garlic flowers close -to her. It was certainly odd that whenever she got into that -lethargic state, with the stertorous breathing, she put the flowers -from her, but that when she waked she clutched them close. There was -no possibility of making any mistake about this, for in the long hours -that followed, she had many spells of sleeping and waking and repeated -both actions many times. - -At six o'clock Van Helsing came to relieve me. Arthur had then fallen -into a doze, and he mercifully let him sleep on. When he saw Lucy's -face I could hear the hissing indraw of breath, and he said to me in a -sharp whisper. "Draw up the blind. I want light!" Then he bent down, -and, with his face almost touching Lucy's, examined her carefully. He -removed the flowers and lifted the silk handkerchief from her throat. -As he did so he started back and I could hear his ejaculation, "Mein -Gott!" as it was smothered in his throat. I bent over and looked, -too, and as I noticed some queer chill came over me. The wounds on -the throat had absolutely disappeared. - -For fully five minutes Van Helsing stood looking at her, with his face -at its sternest. Then he turned to me and said calmly, "She is -dying. It will not be long now. It will be much difference, mark me, -whether she dies conscious or in her sleep. Wake that poor boy, and -let him come and see the last. He trusts us, and we have promised -him." - -I went to the dining room and waked him. He was dazed for a moment, -but when he saw the sunlight streaming in through the edges of the -shutters he thought he was late, and expressed his fear. I assured -him that Lucy was still asleep, but told him as gently as I could that -both Van Helsing and I feared that the end was near. He covered his -face with his hands, and slid down on his knees by the sofa, where he -remained, perhaps a minute, with his head buried, praying, whilst his -shoulders shook with grief. I took him by the hand and raised him up. -"Come," I said, "my dear old fellow, summon all your fortitude. It -will be best and easiest for her." - -When we came into Lucy's room I could see that Van Helsing had, with -his usual forethought, been putting matters straight and making -everything look as pleasing as possible. He had even brushed Lucy's -hair, so that it lay on the pillow in its usual sunny ripples. When -we came into the room she opened her eyes, and seeing him, whispered -softly, "Arthur! Oh, my love, I am so glad you have come!" - -He was stooping to kiss her, when Van Helsing motioned him back. -"No," he whispered, "not yet! Hold her hand, it will comfort her -more." - -So Arthur took her hand and knelt beside her, and she looked her best, -with all the soft lines matching the angelic beauty of her eyes. Then -gradually her eyes closed, and she sank to sleep. For a little bit -her breast heaved softly, and her breath came and went like a tired -child's. - -And then insensibly there came the strange change which I had noticed -in the night. Her breathing grew stertorous, the mouth opened, and -the pale gums, drawn back, made the teeth look longer and sharper than -ever. In a sort of sleep-waking, vague, unconscious way she opened -her eyes, which were now dull and hard at once, and said in a soft, -voluptuous voice, such as I had never heard from her lips, "Arthur! -Oh, my love, I am so glad you have come! Kiss me!" - -Arthur bent eagerly over to kiss her, but at that instant Van Helsing, -who, like me, had been startled by her voice, swooped upon him, and -catching him by the neck with both hands, dragged him back with a fury -of strength which I never thought he could have possessed, and -actually hurled him almost across the room. - -"Not on your life!" he said, "not for your living soul and hers!" And -he stood between them like a lion at bay. - -Arthur was so taken aback that he did not for a moment know what to do -or say, and before any impulse of violence could seize him he realized -the place and the occasion, and stood silent, waiting. - -I kept my eyes fixed on Lucy, as did Van Helsing, and we saw a spasm -as of rage flit like a shadow over her face. The sharp teeth clamped -together. Then her eyes closed, and she breathed heavily. - -Very shortly after she opened her eyes in all their softness, and -putting out her poor, pale, thin hand, took Van Helsing's great brown -one, drawing it close to her, she kissed it. "My true friend," she -said, in a faint voice, but with untellable pathos, "My true friend, -and his! Oh, guard him, and give me peace!" - -"I swear it!" he said solemnly, kneeling beside her and holding up his -hand, as one who registers an oath. Then he turned to Arthur, and -said to him, "Come, my child, take her hand in yours, and kiss her on -the forehead, and only once." - -Their eyes met instead of their lips, and so they parted. Lucy's eyes -closed, and Van Helsing, who had been watching closely, took Arthur's -arm, and drew him away. - -And then Lucy's breathing became stertorous again, and all at once it -ceased. - -"It is all over," said Van Helsing. "She is dead!" - -I took Arthur by the arm, and led him away to the drawing room, where -he sat down, and covered his face with his hands, sobbing in a way -that nearly broke me down to see. - -I went back to the room, and found Van Helsing looking at poor Lucy, -and his face was sterner than ever. Some change had come over her -body. Death had given back part of her beauty, for her brow and -cheeks had recovered some of their flowing lines. Even the lips had -lost their deadly pallor. It was as if the blood, no longer needed -for the working of the heart, had gone to make the harshness of death -as little rude as might be. - -"We thought her dying whilst she slept, and sleeping when she died." - - -I stood beside Van Helsing, and said, "Ah well, poor girl, there is -peace for her at last. It is the end!" - -He turned to me, and said with grave solemnity, "Not so, alas! Not -so. It is only the beginning!" - -When I asked him what he meant, he only shook his head and answered, -"We can do nothing as yet. Wait and see." - - - - -CHAPTER 13 - - -DR. SEWARD'S DIARY--cont. - -The funeral was arranged for the next succeeding day, so that Lucy and -her mother might be buried together. I attended to all the ghastly -formalities, and the urbane undertaker proved that his staff was -afflicted, or blessed, with something of his own obsequious suavity. -Even the woman who performed the last offices for the dead remarked to -me, in a confidential, brother-professional way, when she had come out -from the death chamber, - -"She makes a very beautiful corpse, sir. It's quite a privilege to -attend on her. It's not too much to say that she will do credit to -our establishment!" - -I noticed that Van Helsing never kept far away. This was possible -from the disordered state of things in the household. There were no -relatives at hand, and as Arthur had to be back the next day to attend -at his father's funeral, we were unable to notify any one who should -have been bidden. Under the circumstances, Van Helsing and I took it -upon ourselves to examine papers, etc. He insisted upon looking over -Lucy's papers himself. I asked him why, for I feared that he, being a -foreigner, might not be quite aware of English legal requirements, and -so might in ignorance make some unnecessary trouble. - -He answered me, "I know, I know. You forget that I am a lawyer as -well as a doctor. But this is not altogether for the law. You knew -that, when you avoided the coroner. I have more than him to avoid. -There may be papers more, such as this." - -As he spoke he took from his pocket book the memorandum which had been -in Lucy's breast, and which she had torn in her sleep. - -"When you find anything of the solicitor who is for the late Mrs. -Westenra, seal all her papers, and write him tonight. For me, I watch -here in the room and in Miss Lucy's old room all night, and I myself -search for what may be. It is not well that her very thoughts go into -the hands of strangers." - -I went on with my part of the work, and in another half hour had found -the name and address of Mrs. Westenra's solicitor and had written to -him. All the poor lady's papers were in order. Explicit directions -regarding the place of burial were given. I had hardly sealed the -letter, when, to my surprise, Van Helsing walked into the room, -saying, - -"Can I help you friend John? I am free, and if I may, my service is -to you." - -"Have you got what you looked for?" I asked. - -To which he replied, "I did not look for any specific thing. I only -hoped to find, and find I have, all that there was, only some letters -and a few memoranda, and a diary new begun. But I have them here, and -we shall for the present say nothing of them. I shall see that poor -lad tomorrow evening, and, with his sanction, I shall use some." - -When we had finished the work in hand, he said to me, "And now, friend -John, I think we may to bed. We want sleep, both you and I, and rest -to recuperate. Tomorrow we shall have much to do, but for the tonight -there is no need of us. Alas!" - -Before turning in we went to look at poor Lucy. The undertaker had -certainly done his work well, for the room was turned into a small -chapelle ardente. There was a wilderness of beautiful white flowers, -and death was made as little repulsive as might be. The end of the -winding sheet was laid over the face. When the Professor bent over -and turned it gently back, we both started at the beauty before us. -The tall wax candles showing a sufficient light to note it well. All -Lucy's loveliness had come back to her in death, and the hours that -had passed, instead of leaving traces of 'decay's effacing fingers', -had but restored the beauty of life, till positively I could not -believe my eyes that I was looking at a corpse. - -The Professor looked sternly grave. He had not loved her as I had, -and there was no need for tears in his eyes. He said to me, "Remain -till I return," and left the room. He came back with a handful of -wild garlic from the box waiting in the hall, but which had not been -opened, and placed the flowers amongst the others on and around the -bed. Then he took from his neck, inside his collar, a little gold -crucifix, and placed it over the mouth. He restored the sheet to its -place, and we came away. - -I was undressing in my own room, when, with a premonitory tap at the -door, he entered, and at once began to speak. - -"Tomorrow I want you to bring me, before night, a set of post-mortem -knives." - -"Must we make an autopsy?" I asked. - -"Yes and no. I want to operate, but not what you think. Let me tell -you now, but not a word to another. I want to cut off her head and -take out her heart. Ah! You a surgeon, and so shocked! You, whom I -have seen with no tremble of hand or heart, do operations of life and -death that make the rest shudder. Oh, but I must not forget, my dear -friend John, that you loved her, and I have not forgotten it for is I -that shall operate, and you must not help. I would like to do it -tonight, but for Arthur I must not. He will be free after his -father's funeral tomorrow, and he will want to see her, to see it. -Then, when she is coffined ready for the next day, you and I shall -come when all sleep. We shall unscrew the coffin lid, and shall do -our operation, and then replace all, so that none know, save we -alone." - -"But why do it at all? The girl is dead. Why mutilate her poor body -without need? And if there is no necessity for a post-mortem and -nothing to gain by it, no good to her, to us, to science, to human -knowledge, why do it? Without such it is monstrous." - -For answer he put his hand on my shoulder, and said, with infinite -tenderness, "Friend John, I pity your poor bleeding heart, and I love -you the more because it does so bleed. If I could, I would take on -myself the burden that you do bear. But there are things that you -know not, but that you shall know, and bless me for knowing, though -they are not pleasant things. John, my child, you have been my friend -now many years, and yet did you ever know me to do any without good -cause? I may err, I am but man, but I believe in all I do. Was it -not for these causes that you send for me when the great trouble -came? Yes! Were you not amazed, nay horrified, when I would not let -Arthur kiss his love, though she was dying, and snatched him away by -all my strength? Yes! And yet you saw how she thanked me, with her -so beautiful dying eyes, her voice, too, so weak, and she kiss my -rough old hand and bless me? Yes! And did you not hear me swear -promise to her, that so she closed her eyes grateful? Yes! - -"Well, I have good reason now for all I want to do. You have for many -years trust me. You have believe me weeks past, when there be things -so strange that you might have well doubt. Believe me yet a little, -friend John. If you trust me not, then I must tell what I think, and -that is not perhaps well. And if I work, as work I shall, no matter -trust or no trust, without my friend trust in me, I work with heavy -heart and feel oh so lonely when I want all help and courage that may -be!" He paused a moment and went on solemnly, "Friend John, there are -strange and terrible days before us. Let us not be two, but one, that -so we work to a good end. Will you not have faith in me?" - -I took his hand, and promised him. I held my door open as he went -away, and watched him go to his room and close the door. As I stood -without moving, I saw one of the maids pass silently along the -passage, she had her back to me, so did not see me, and go into the -room where Lucy lay. The sight touched me. Devotion is so rare, and -we are so grateful to those who show it unasked to those we love. Here -was a poor girl putting aside the terrors which she naturally had of -death to go watch alone by the bier of the mistress whom she loved, so -that the poor clay might not be lonely till laid to eternal rest. - -I must have slept long and soundly, for it was broad daylight when Van -Helsing waked me by coming into my room. He came over to my bedside -and said, "You need not trouble about the knives. We shall not do -it." - -"Why not?" I asked. For his solemnity of the night before had -greatly impressed me. - -"Because," he said sternly, "it is too late, or too early. See!" -Here he held up the little golden crucifix. - -"This was stolen in the night." - -"How stolen," I asked in wonder, "since you have it now?" - -"Because I get it back from the worthless wretch who stole it, from -the woman who robbed the dead and the living. Her punishment will -surely come, but not through me. She knew not altogether what she -did, and thus unknowing, she only stole. Now we must wait." He went -away on the word, leaving me with a new mystery to think of, a new -puzzle to grapple with. - -The forenoon was a dreary time, but at noon the solicitor came, Mr. -Marquand, of Wholeman, Sons, Marquand & Lidderdale. He was very -genial and very appreciative of what we had done, and took off our -hands all cares as to details. During lunch he told us that Mrs. -Westenra had for some time expected sudden death from her heart, and -had put her affairs in absolute order. He informed us that, with the -exception of a certain entailed property of Lucy's father which now, -in default of direct issue, went back to a distant branch of the -family, the whole estate, real and personal, was left absolutely to -Arthur Holmwood. When he had told us so much he went on, - -"Frankly we did our best to prevent such a testamentary disposition, -and pointed out certain contingencies that might leave her daughter -either penniless or not so free as she should be to act regarding a -matrimonial alliance. Indeed, we pressed the matter so far that we -almost came into collision, for she asked us if we were or were not -prepared to carry out her wishes. Of course, we had then no -alternative but to accept. We were right in principle, and -ninety-nine times out of a hundred we should have proved, by the logic -of events, the accuracy of our judgment. - -"Frankly, however, I must admit that in this case any other form of -disposition would have rendered impossible the carrying out of her -wishes. For by her predeceasing her daughter the latter would have -come into possession of the property, and, even had she only survived -her mother by five minutes, her property would, in case there were no -will, and a will was a practical impossibility in such a case, have -been treated at her decease as under intestacy. In which case Lord -Godalming, though so dear a friend, would have had no claim in the -world. And the inheritors, being remote, would not be likely to -abandon their just rights, for sentimental reasons regarding an entire -stranger. I assure you, my dear sirs, I am rejoiced at the result, -perfectly rejoiced." - -He was a good fellow, but his rejoicing at the one little part, in -which he was officially interested, of so great a tragedy, was an -object-lesson in the limitations of sympathetic understanding. - -He did not remain long, but said he would look in later in the day and -see Lord Godalming. His coming, however, had been a certain comfort -to us, since it assured us that we should not have to dread hostile -criticism as to any of our acts. Arthur was expected at five o'clock, -so a little before that time we visited the death chamber. It was so -in very truth, for now both mother and daughter lay in it. The -undertaker, true to his craft, had made the best display he could of -his goods, and there was a mortuary air about the place that lowered -our spirits at once. - -Van Helsing ordered the former arrangement to be adhered to, -explaining that, as Lord Godalming was coming very soon, it would be -less harrowing to his feelings to see all that was left of his fiancee -quite alone. - -The undertaker seemed shocked at his own stupidity and exerted himself -to restore things to the condition in which we left them the night -before, so that when Arthur came such shocks to his feelings as we -could avoid were saved. - -Poor fellow! He looked desperately sad and broken. Even his stalwart -manhood seemed to have shrunk somewhat under the strain of his -much-tried emotions. He had, I knew, been very genuinely and -devotedly attached to his father, and to lose him, and at such a time, -was a bitter blow to him. With me he was warm as ever, and to Van -Helsing he was sweetly courteous. But I could not help seeing that -there was some constraint with him. The professor noticed it too, and -motioned me to bring him upstairs. I did so, and left him at the door -of the room, as I felt he would like to be quite alone with her, but -he took my arm and led me in, saying huskily, - -"You loved her too, old fellow. She told me all about it, and there -was no friend had a closer place in her heart than you. I don't know -how to thank you for all you have done for her. I can't think -yet . . ." - -Here he suddenly broke down, and threw his arms round my shoulders and -laid his head on my breast, crying, "Oh, Jack! Jack! What shall I -do? The whole of life seems gone from me all at once, and there is -nothing in the wide world for me to live for." - -I comforted him as well as I could. In such cases men do not need -much expression. A grip of the hand, the tightening of an arm over -the shoulder, a sob in unison, are expressions of sympathy dear to a -man's heart. I stood still and silent till his sobs died away, and -then I said softly to him, "Come and look at her." - -Together we moved over to the bed, and I lifted the lawn from her -face. God! How beautiful she was. Every hour seemed to be enhancing -her loveliness. It frightened and amazed me somewhat. And as for -Arthur, he fell to trembling, and finally was shaken with doubt as -with an ague. At last, after a long pause, he said to me in a faint -whisper, "Jack, is she really dead?" - -I assured him sadly that it was so, and went on to suggest, for I felt -that such a horrible doubt should not have life for a moment longer -than I could help, that it often happened that after death faces -become softened and even resolved into their youthful beauty, that -this was especially so when death had been preceded by any acute or -prolonged suffering. I seemed to quite do away with any doubt, and -after kneeling beside the couch for a while and looking at her -lovingly and long, he turned aside. I told him that that must be -goodbye, as the coffin had to be prepared, so he went back and took -her dead hand in his and kissed it, and bent over and kissed her -forehead. He came away, fondly looking back over his shoulder at her -as he came. - -I left him in the drawing room, and told Van Helsing that he had said -goodbye, so the latter went to the kitchen to tell the undertaker's -men to proceed with the preparations and to screw up the coffin. When -he came out of the room again I told him of Arthur's question, and he -replied, "I am not surprised. Just now I doubted for a moment -myself!" - -We all dined together, and I could see that poor Art was trying to -make the best of things. Van Helsing had been silent all dinner time, -but when we had lit our cigars he said, "Lord . . ." but Arthur -interrupted him. - -"No, no, not that, for God's sake! Not yet at any rate. Forgive me, -sir. I did not mean to speak offensively. It is only because my loss -is so recent." - -The Professor answered very sweetly, "I only used that name because I -was in doubt. I must not call you 'Mr.' and I have grown to love you, -yes, my dear boy, to love you, as Arthur." - -Arthur held out his hand, and took the old man's warmly. "Call me -what you will," he said. "I hope I may always have the title of a -friend. And let me say that I am at a loss for words to thank you for -your goodness to my poor dear." He paused a moment, and went on, "I -know that she understood your goodness even better than I do. And if -I was rude or in any way wanting at that time you acted so, you -remember"--the Professor nodded--"you must forgive me." - -He answered with a grave kindness, "I know it was hard for you to -quite trust me then, for to trust such violence needs to understand, -and I take it that you do not, that you cannot, trust me now, for you -do not yet understand. And there may be more times when I shall want -you to trust when you cannot, and may not, and must not yet -understand. But the time will come when your trust shall be whole and -complete in me, and when you shall understand as though the sunlight -himself shone through. Then you shall bless me from first to last for -your own sake, and for the sake of others, and for her dear sake to -whom I swore to protect." - -"And indeed, indeed, sir," said Arthur warmly. "I shall in all ways -trust you. I know and believe you have a very noble heart, and you -are Jack's friend, and you were hers. You shall do what you like." - -The Professor cleared his throat a couple of times, as though about to -speak, and finally said, "May I ask you something now?" - -"Certainly." - -"You know that Mrs. Westenra left you all her property?" - -"No, poor dear. I never thought of it." - -"And as it is all yours, you have a right to deal with it as you will. -I want you to give me permission to read all Miss Lucy's papers and -letters. Believe me, it is no idle curiosity. I have a motive of -which, be sure, she would have approved. I have them all here. I -took them before we knew that all was yours, so that no strange hand -might touch them, no strange eye look through words into her soul. I -shall keep them, if I may. Even you may not see them yet, but I shall -keep them safe. No word shall be lost, and in the good time I shall -give them back to you. It is a hard thing that I ask, but you will do -it, will you not, for Lucy's sake?" - -Arthur spoke out heartily, like his old self, "Dr. Van Helsing, you -may do what you will. I feel that in saying this I am doing what my -dear one would have approved. I shall not trouble you with questions -till the time comes." - -The old Professor stood up as he said solemnly, "And you are right. -There will be pain for us all, but it will not be all pain, nor will -this pain be the last. We and you too, you most of all, dear boy, -will have to pass through the bitter water before we reach the sweet. -But we must be brave of heart and unselfish, and do our duty, and all -will be well!" - -I slept on a sofa in Arthur's room that night. Van Helsing did not go -to bed at all. He went to and fro, as if patroling the house, and was -never out of sight of the room where Lucy lay in her coffin, strewn -with the wild garlic flowers, which sent through the odour of lily and -rose, a heavy, overpowering smell into the night. - - - - -MINA HARKER'S JOURNAL - -22 September.--In the train to Exeter. Jonathan sleeping. It seems -only yesterday that the last entry was made, and yet how much between -then, in Whitby and all the world before me, Jonathan away and no news -of him, and now, married to Jonathan, Jonathan a solicitor, a partner, -rich, master of his business, Mr. Hawkins dead and buried, and -Jonathan with another attack that may harm him. Some day he may ask -me about it. Down it all goes. I am rusty in my shorthand, see what -unexpected prosperity does for us, so it may be as well to freshen it -up again with an exercise anyhow. - -The service was very simple and very solemn. There were only -ourselves and the servants there, one or two old friends of his from -Exeter, his London agent, and a gentleman representing Sir John -Paxton, the President of the Incorporated Law Society. Jonathan and I -stood hand in hand, and we felt that our best and dearest friend was -gone from us. - -We came back to town quietly, taking a bus to Hyde Park Corner. -Jonathan thought it would interest me to go into the Row for a while, -so we sat down. But there were very few people there, and it was -sad-looking and desolate to see so many empty chairs. It made us -think of the empty chair at home. So we got up and walked down -Piccadilly. Jonathan was holding me by the arm, the way he used to in -the old days before I went to school. I felt it very improper, for -you can't go on for some years teaching etiquette and decorum to other -girls without the pedantry of it biting into yourself a bit. But it -was Jonathan, and he was my husband, and we didn't know anybody who -saw us, and we didn't care if they did, so on we walked. I was -looking at a very beautiful girl, in a big cart-wheel hat, sitting in -a victoria outside Guiliano's, when I felt Jonathan clutch my arm so -tight that he hurt me, and he said under his breath, "My God!" - -I am always anxious about Jonathan, for I fear that some nervous fit -may upset him again. So I turned to him quickly, and asked him what -it was that disturbed him. - -He was very pale, and his eyes seemed bulging out as, half in terror -and half in amazement, he gazed at a tall, thin man, with a beaky nose -and black moustache and pointed beard, who was also observing the -pretty girl. He was looking at her so hard that he did not see either -of us, and so I had a good view of him. His face was not a good -face. It was hard, and cruel, and sensual, and big white teeth, that -looked all the whiter because his lips were so red, were pointed like -an animal's. Jonathan kept staring at him, till I was afraid he would -notice. I feared he might take it ill, he looked so fierce and nasty. -I asked Jonathan why he was disturbed, and he answered, evidently -thinking that I knew as much about it as he did, "Do you see who it -is?" - -"No, dear," I said. "I don't know him, who is it?" His answer seemed -to shock and thrill me, for it was said as if he did not know that it -was me, Mina, to whom he was speaking. "It is the man himself!" - -The poor dear was evidently terrified at something, very greatly -terrified. I do believe that if he had not had me to lean on and to -support him he would have sunk down. He kept staring. A man came out -of the shop with a small parcel, and gave it to the lady, who then -drove off. The dark man kept his eyes fixed on her, and when the -carriage moved up Piccadilly he followed in the same direction, and -hailed a hansom. Jonathan kept looking after him, and said, as if to -himself, - -"I believe it is the Count, but he has grown young. My God, if this -be so! Oh, my God! My God! If only I knew! If only I knew!" He was -distressing himself so much that I feared to keep his mind on the -subject by asking him any questions, so I remained silent. I drew -away quietly, and he, holding my arm, came easily. We walked a little -further, and then went in and sat for a while in the Green Park. It -was a hot day for autumn, and there was a comfortable seat in a shady -place. After a few minutes' staring at nothing, Jonathan's eyes -closed, and he went quickly into a sleep, with his head on my -shoulder. I thought it was the best thing for him, so did not disturb -him. In about twenty minutes he woke up, and said to me quite -cheerfully, - -"Why, Mina, have I been asleep! Oh, do forgive me for being so rude. -Come, and we'll have a cup of tea somewhere." - -He had evidently forgotten all about the dark stranger, as in his -illness he had forgotten all that this episode had reminded him of. I -don't like this lapsing into forgetfulness. It may make or continue -some injury to the brain. I must not ask him, for fear I shall do -more harm than good, but I must somehow learn the facts of his journey -abroad. The time is come, I fear, when I must open the parcel, and -know what is written. Oh, Jonathan, you will, I know, forgive me if I -do wrong, but it is for your own dear sake. - - -Later.--A sad homecoming in every way, the house empty of the dear -soul who was so good to us. Jonathan still pale and dizzy under a -slight relapse of his malady, and now a telegram from Van Helsing, -whoever he may be. "You will be grieved to hear that Mrs. Westenra -died five days ago, and that Lucy died the day before yesterday. They -were both buried today." - -Oh, what a wealth of sorrow in a few words! Poor Mrs. Westenra! Poor -Lucy! Gone, gone, never to return to us! And poor, poor Arthur, to -have lost such a sweetness out of his life! God help us all to bear -our troubles. - - - -DR. SEWARD'S DIARY-CONT. - -22 September.--It is all over. Arthur has gone back to Ring, and has -taken Quincey Morris with him. What a fine fellow is Quincey! I -believe in my heart of hearts that he suffered as much about Lucy's -death as any of us, but he bore himself through it like a moral -Viking. If America can go on breeding men like that, she will be a -power in the world indeed. Van Helsing is lying down, having a rest -preparatory to his journey. He goes to Amsterdam tonight, but says he -returns tomorrow night, that he only wants to make some arrangements -which can only be made personally. He is to stop with me then, if he -can. He says he has work to do in London which may take him some -time. Poor old fellow! I fear that the strain of the past week has -broken down even his iron strength. All the time of the burial he -was, I could see, putting some terrible restraint on himself. When it -was all over, we were standing beside Arthur, who, poor fellow, was -speaking of his part in the operation where his blood had been -transfused to his Lucy's veins. I could see Van Helsing's face grow -white and purple by turns. Arthur was saying that he felt since then -as if they two had been really married, and that she was his wife in -the sight of God. None of us said a word of the other operations, and -none of us ever shall. Arthur and Quincey went away together to the -station, and Van Helsing and I came on here. The moment we were alone -in the carriage he gave way to a regular fit of hysterics. He has -denied to me since that it was hysterics, and insisted that it was -only his sense of humor asserting itself under very terrible -conditions. He laughed till he cried, and I had to draw down the -blinds lest any one should see us and misjudge. And then he cried, -till he laughed again, and laughed and cried together, just as a woman -does. I tried to be stern with him, as one is to a woman under the -circumstances, but it had no effect. Men and women are so different -in manifestations of nervous strength or weakness! Then when his face -grew grave and stern again I asked him why his mirth, and why at such -a time. His reply was in a way characteristic of him, for it was -logical and forceful and mysterious. He said, - -"Ah, you don't comprehend, friend John. Do not think that I am not -sad, though I laugh. See, I have cried even when the laugh did choke -me. But no more think that I am all sorry when I cry, for the laugh -he come just the same. Keep it always with you that laughter who -knock at your door and say, 'May I come in?' is not true laughter. -No! He is a king, and he come when and how he like. He ask no -person, he choose no time of suitability. He say, 'I am here.' -Behold, in example I grieve my heart out for that so sweet young -girl. I give my blood for her, though I am old and worn. I give my -time, my skill, my sleep. I let my other sufferers want that she may -have all. And yet I can laugh at her very grave, laugh when the clay -from the spade of the sexton drop upon her coffin and say 'Thud, -thud!' to my heart, till it send back the blood from my cheek. My -heart bleed for that poor boy, that dear boy, so of the age of mine -own boy had I been so blessed that he live, and with his hair and eyes -the same. - -"There, you know now why I love him so. And yet when he say things -that touch my husband-heart to the quick, and make my father-heart -yearn to him as to no other man, not even you, friend John, for we are -more level in experiences than father and son, yet even at such a -moment King Laugh he come to me and shout and bellow in my ear, 'Here I -am! Here I am!' till the blood come dance back and bring some of the -sunshine that he carry with him to my cheek. Oh, friend John, it is a -strange world, a sad world, a world full of miseries, and woes, and -troubles. And yet when King Laugh come, he make them all dance to the -tune he play. Bleeding hearts, and dry bones of the churchyard, and -tears that burn as they fall, all dance together to the music that he -make with that smileless mouth of him. And believe me, friend John, -that he is good to come, and kind. Ah, we men and women are like -ropes drawn tight with strain that pull us different ways. Then tears -come, and like the rain on the ropes, they brace us up, until perhaps -the strain become too great, and we break. But King Laugh he come -like the sunshine, and he ease off the strain again, and we bear to go -on with our labor, what it may be." - -I did not like to wound him by pretending not to see his idea, but as -I did not yet understand the cause of his laughter, I asked him. As -he answered me his face grew stern, and he said in quite a different -tone, - -"Oh, it was the grim irony of it all, this so lovely lady garlanded -with flowers, that looked so fair as life, till one by one we wondered -if she were truly dead, she laid in that so fine marble house in that -lonely churchyard, where rest so many of her kin, laid there with the -mother who loved her, and whom she loved, and that sacred bell going -'Toll! Toll! Toll!' so sad and slow, and those holy men, with the -white garments of the angel, pretending to read books, and yet all the -time their eyes never on the page, and all of us with the bowed head. -And all for what? She is dead, so! Is it not?" - -"Well, for the life of me, Professor," I said, "I can't see anything -to laugh at in all that. Why, your expression makes it a harder -puzzle than before. But even if the burial service was comic, what -about poor Art and his trouble? Why his heart was simply breaking." - -"Just so. Said he not that the transfusion of his blood to her veins -had made her truly his bride?" - -"Yes, and it was a sweet and comforting idea for him." - -"Quite so. But there was a difficulty, friend John. If so that, then -what about the others? Ho, ho! Then this so sweet maid is a -polyandrist, and me, with my poor wife dead to me, but alive by -Church's law, though no wits, all gone, even I, who am faithful -husband to this now-no-wife, am bigamist." - -"I don't see where the joke comes in there either!" I said, and I did -not feel particularly pleased with him for saying such things. He -laid his hand on my arm, and said, - -"Friend John, forgive me if I pain. I showed not my feeling to others -when it would wound, but only to you, my old friend, whom I can trust. -If you could have looked into my heart then when I want to laugh, if -you could have done so when the laugh arrived, if you could do so now, -when King Laugh have pack up his crown, and all that is to him, for he -go far, far away from me, and for a long, long time, maybe you would -perhaps pity me the most of all." - -I was touched by the tenderness of his tone, and asked why. - -"Because I know!" - -And now we are all scattered, and for many a long day loneliness will -sit over our roofs with brooding wings. Lucy lies in the tomb of her -kin, a lordly death house in a lonely churchyard, away from teeming -London, where the air is fresh, and the sun rises over Hampstead Hill, -and where wild flowers grow of their own accord. - -So I can finish this diary, and God only knows if I shall ever begin -another. If I do, or if I even open this again, it will be to deal -with different people and different themes, for here at the end, where -the romance of my life is told, ere I go back to take up the thread of -my life-work, I say sadly and without hope, "FINIS". - - - - -THE WESTMINSTER GAZETTE, 25 SEPTEMBER A HAMPSTEAD MYSTERY - -The neighborhood of Hampstead is just at present exercised -with a series of events which seem to run on lines parallel -to those of what was known to the writers of headlines as -"The Kensington Horror," or "The Stabbing Woman," or "The -Woman in Black." During the past two or three days several -cases have occurred of young children straying from home or -neglecting to return from their playing on the Heath. In -all these cases the children were too young to give any -properly intelligible account of themselves, but the -consensus of their excuses is that they had been with a -"bloofer lady." It has always been late in the evening when -they have been missed, and on two occasions the children -have not been found until early in the following morning. -It is generally supposed in the neighborhood that, as the -first child missed gave as his reason for being away that a -"bloofer lady" had asked him to come for a walk, the others -had picked up the phrase and used it as occasion served. This -is the more natural as the favourite game of the little ones -at present is luring each other away by wiles. A correspondent -writes us that to see some of the tiny tots pretending to be the -"bloofer lady" is supremely funny. Some of our caricaturists -might, he says, take a lesson in the irony of grotesque by -comparing the reality and the picture. It is only in accordance -with general principles of human nature that the "bloofer lady" -should be the popular role at these al fresco performances. Our -correspondent naively says that even Ellen Terry could not be so -winningly attractive as some of these grubby-faced little -children pretend, and even imagine themselves, to be. - -There is, however, possibly a serious side to the question, -for some of the children, indeed all who have been missed -at night, have been slightly torn or wounded in the throat. -The wounds seem such as might be made by a rat or a small -dog, and although of not much importance individually, would tend -to show that whatever animal inflicts them has a system or method -of its own. The police of the division have been instructed to -keep a sharp lookout for straying children, especially when very -young, in and around Hampstead Heath, and for any stray dog which -may be about. - - - - -THE WESTMINSTER GAZETTE, 25 SEPTEMBER EXTRA SPECIAL - -THE HAMPSTEAD HORROR - - -ANOTHER CHILD INJURED - -THE "BLOOFER LADY" - -We have just received intelligence that another child, -missed last night, was only discovered late in the morning -under a furze bush at the Shooter's Hill side of Hampstead -Heath, which is perhaps, less frequented than the other -parts. It has the same tiny wound in the throat as has -been noticed in other cases. It was terribly weak, and -looked quite emaciated. It too, when partially restored, -had the common story to tell of being lured away by the -"bloofer lady". - - - - -CHAPTER 14 - - -MINA HARKER'S JOURNAL - -23 September.--Jonathan is better after a bad night. I am so glad -that he has plenty of work to do, for that keeps his mind off the -terrible things, and oh, I am rejoiced that he is not now weighed down -with the responsibility of his new position. I knew he would be true -to himself, and now how proud I am to see my Jonathan rising to the -height of his advancement and keeping pace in all ways with the duties -that come upon him. He will be away all day till late, for he said he -could not lunch at home. My household work is done, so I shall take -his foreign journal, and lock myself up in my room and read it. - - -24 September.--I hadn't the heart to write last night, that terrible -record of Jonathan's upset me so. Poor dear! How he must have -suffered, whether it be true or only imagination. I wonder if there -is any truth in it at all. Did he get his brain fever, and then write -all those terrible things, or had he some cause for it all? I suppose -I shall never know, for I dare not open the subject to him. And yet -that man we saw yesterday! He seemed quite certain of him, poor -fellow! I suppose it was the funeral upset him and sent his mind back -on some train of thought. - -He believes it all himself. I remember how on our wedding day he said -"Unless some solemn duty come upon me to go back to the bitter hours, -asleep or awake, mad or sane . . ." There seems to be through it all -some thread of continuity. That fearful Count was coming to London. -If it should be, and he came to London, with its teeming millions . . . -There may be a solemn duty, and if it come we must not shrink from -it. I shall be prepared. I shall get my typewriter this very hour -and begin transcribing. Then we shall be ready for other eyes if -required. And if it be wanted, then, perhaps, if I am ready, poor -Jonathan may not be upset, for I can speak for him and never let him -be troubled or worried with it at all. If ever Jonathan quite gets -over the nervousness he may want to tell me of it all, and I can ask -him questions and find out things, and see how I may comfort him. - - - - -LETTER, VAN HELSING TO MRS. HARKER - -24 September - -(Confidence) - -"Dear Madam, - -"I pray you to pardon my writing, in that I am so far -friend as that I sent to you sad news of Miss Lucy -Westenra's death. By the kindness of Lord Godalming, I am -empowered to read her letters and papers, for I am deeply -concerned about certain matters vitally important. In them -I find some letters from you, which show how great friends -you were and how you love her. Oh, Madam Mina, by that -love, I implore you, help me. It is for others' good that -I ask, to redress great wrong, and to lift much and terrible -troubles, that may be more great than you can know. May it be -that I see you? You can trust me. I am friend of Dr. John -Seward and of Lord Godalming (that was Arthur of Miss Lucy). I -must keep it private for the present from all. I should come to -Exeter to see you at once if you tell me I am privilege to come, -and where and when. I implore your pardon, Madam. I have read -your letters to poor Lucy, and know how good you are and how your -husband suffer. So I pray you, if it may be, enlighten him not, -least it may harm. Again your pardon, and forgive me. - -"VAN HELSING" - - - - -TELEGRAM, MRS. HARKER TO VAN HELSING - -25 September.--Come today by quarter past ten train if you -can catch it. Can see you any time you call. - -"WILHELMINA HARKER" - - - - -MINA HARKER'S JOURNAL - -25 September.--I cannot help feeling terribly excited as the time -draws near for the visit of Dr. Van Helsing, for somehow I expect that -it will throw some light upon Jonathan's sad experience, and as he -attended poor dear Lucy in her last illness, he can tell me all about -her. That is the reason of his coming. It is concerning Lucy and her -sleep-walking, and not about Jonathan. Then I shall never know the -real truth now! How silly I am. That awful journal gets hold of my -imagination and tinges everything with something of its own colour. Of -course it is about Lucy. That habit came back to the poor dear, and -that awful night on the cliff must have made her ill. I had almost -forgotten in my own affairs how ill she was afterwards. She must have -told him of her sleep-walking adventure on the cliff, and that I knew -all about it, and now he wants me to tell him what I know, so that he -may understand. I hope I did right in not saying anything of it to -Mrs. Westenra. I should never forgive myself if any act of mine, were -it even a negative one, brought harm on poor dear Lucy. I hope too, -Dr. Van Helsing will not blame me. I have had so much trouble and -anxiety of late that I feel I cannot bear more just at present. - -I suppose a cry does us all good at times, clears the air as other -rain does. Perhaps it was reading the journal yesterday that upset -me, and then Jonathan went away this morning to stay away from me a -whole day and night, the first time we have been parted since our -marriage. I do hope the dear fellow will take care of himself, and -that nothing will occur to upset him. It is two o'clock, and the -doctor will be here soon now. I shall say nothing of Jonathan's -journal unless he asks me. I am so glad I have typewritten out my own -journal, so that, in case he asks about Lucy, I can hand it to him. -It will save much questioning. - -Later.--He has come and gone. Oh, what a strange meeting, and how it -all makes my head whirl round. I feel like one in a dream. Can it be -all possible, or even a part of it? If I had not read Jonathan's -journal first, I should never have accepted even a possibility. Poor, -poor, dear Jonathan! How he must have suffered. Please the good God, -all this may not upset him again. I shall try to save him from it. -But it may be even a consolation and a help to him, terrible though it -be and awful in its consequences, to know for certain that his eyes -and ears and brain did not deceive him, and that it is all true. It -may be that it is the doubt which haunts him, that when the doubt is -removed, no matter which, waking or dreaming, may prove the truth, he -will be more satisfied and better able to bear the shock. Dr. Van -Helsing must be a good man as well as a clever one if he is Arthur's -friend and Dr. Seward's, and if they brought him all the way from -Holland to look after Lucy. I feel from having seen him that he is -good and kind and of a noble nature. When he comes tomorrow I shall -ask him about Jonathan. And then, please God, all this sorrow and -anxiety may lead to a good end. I used to think I would like to -practice interviewing. Jonathan's friend on "The Exeter News" told -him that memory is everything in such work, that you must be able to -put down exactly almost every word spoken, even if you had to refine -some of it afterwards. Here was a rare interview. I shall try to -record it verbatim. - -It was half-past two o'clock when the knock came. I took my courage a -deux mains and waited. In a few minutes Mary opened the door, and -announced "Dr. Van Helsing". - -I rose and bowed, and he came towards me, a man of medium weight, -strongly built, with his shoulders set back over a broad, deep chest -and a neck well balanced on the trunk as the head is on the neck. The -poise of the head strikes me at once as indicative of thought and -power. The head is noble, well-sized, broad, and large behind the -ears. The face, clean-shaven, shows a hard, square chin, a large -resolute, mobile mouth, a good-sized nose, rather straight, but with -quick, sensitive nostrils, that seem to broaden as the big bushy brows -come down and the mouth tightens. The forehead is broad and fine, -rising at first almost straight and then sloping back above two bumps -or ridges wide apart, such a forehead that the reddish hair cannot -possibly tumble over it, but falls naturally back and to the sides. -Big, dark blue eyes are set widely apart, and are quick and tender or -stern with the man's moods. He said to me, - -"Mrs. Harker, is it not?" I bowed assent. - -"That was Miss Mina Murray?" Again I assented. - -"It is Mina Murray that I came to see that was friend of that poor dear -child Lucy Westenra. Madam Mina, it is on account of the dead that I -come." - -"Sir," I said, "you could have no better claim on me than that you -were a friend and helper of Lucy Westenra." And I held out my hand. -He took it and said tenderly, - -"Oh, Madam Mina, I know that the friend of that poor little girl must -be good, but I had yet to learn . . ." He finished his speech with a -courtly bow. I asked him what it was that he wanted to see me about, -so he at once began. - -"I have read your letters to Miss Lucy. Forgive me, but I had to -begin to inquire somewhere, and there was none to ask. I know that -you were with her at Whitby. She sometimes kept a diary, you need not -look surprised, Madam Mina. It was begun after you had left, and was -an imitation of you, and in that diary she traces by inference certain -things to a sleep-walking in which she puts down that you saved her. -In great perplexity then I come to you, and ask you out of your so -much kindness to tell me all of it that you can remember." - -"I can tell you, I think, Dr. Van Helsing, all about it." - -"Ah, then you have good memory for facts, for details? It is not -always so with young ladies." - -"No, doctor, but I wrote it all down at the time. I can show it to -you if you like." - -"Oh, Madam Mina, I well be grateful. You will do me much favour." - -I could not resist the temptation of mystifying him a bit, I suppose -it is some taste of the original apple that remains still in our -mouths, so I handed him the shorthand diary. He took it with a -grateful bow, and said, "May I read it?" - -"If you wish," I answered as demurely as I could. He opened it, and -for an instant his face fell. Then he stood up and bowed. - -"Oh, you so clever woman!" he said. "I knew long that Mr. Jonathan -was a man of much thankfulness, but see, his wife have all the good -things. And will you not so much honour me and so help me as to read -it for me? Alas! I know not the shorthand." - -By this time my little joke was over, and I was almost ashamed. So I -took the typewritten copy from my work basket and handed it to him. - -"Forgive me," I said. "I could not help it, but I had been thinking -that it was of dear Lucy that you wished to ask, and so that you might -not have time to wait, not on my account, but because I know your time -must be precious, I have written it out on the typewriter for you." - -He took it and his eyes glistened. "You are so good," he said. "And -may I read it now? I may want to ask you some things when I have -read." - -"By all means," I said, "read it over whilst I order lunch, and then -you can ask me questions whilst we eat." - -He bowed and settled himself in a chair with his back to the light, -and became so absorbed in the papers, whilst I went to see after lunch -chiefly in order that he might not be disturbed. When I came back, I -found him walking hurriedly up and down the room, his face all ablaze -with excitement. He rushed up to me and took me by both hands. - -"Oh, Madam Mina," he said, "how can I say what I owe to you? This -paper is as sunshine. It opens the gate to me. I am dazed, I am -dazzled, with so much light, and yet clouds roll in behind the light -every time. But that you do not, cannot comprehend. Oh, but I am -grateful to you, you so clever woman. Madame," he said this very -solemnly, "if ever Abraham Van Helsing can do anything for you or -yours, I trust you will let me know. It will be pleasure and delight -if I may serve you as a friend, as a friend, but all I have ever -learned, all I can ever do, shall be for you and those you love. There -are darknesses in life, and there are lights. You are one of the -lights. You will have a happy life and a good life, and your husband -will be blessed in you." - -"But, doctor, you praise me too much, and you do not know me." - -"Not know you, I, who am old, and who have studied all my life men and -women, I who have made my specialty the brain and all that belongs to -him and all that follow from him! And I have read your diary that you -have so goodly written for me, and which breathes out truth in every -line. I, who have read your so sweet letter to poor Lucy of your -marriage and your trust, not know you! Oh, Madam Mina, good women -tell all their lives, and by day and by hour and by minute, such -things that angels can read. And we men who wish to know have in us -something of angels' eyes. Your husband is noble nature, and you are -noble too, for you trust, and trust cannot be where there is mean -nature. And your husband, tell me of him. Is he quite well? Is all -that fever gone, and is he strong and hearty?" - -I saw here an opening to ask him about Jonathan, so I said, "He was -almost recovered, but he has been greatly upset by Mr. Hawkins death." - -He interrupted, "Oh, yes. I know. I know. I have read your last two -letters." - -I went on, "I suppose this upset him, for when we were in town on -Thursday last he had a sort of shock." - -"A shock, and after brain fever so soon! That is not good. What kind -of shock was it?" - -"He thought he saw some one who recalled something terrible, something -which led to his brain fever." And here the whole thing seemed to -overwhelm me in a rush. The pity for Jonathan, the horror which he -experienced, the whole fearful mystery of his diary, and the fear that -has been brooding over me ever since, all came in a tumult. I suppose -I was hysterical, for I threw myself on my knees and held up my hands -to him, and implored him to make my husband well again. He took my -hands and raised me up, and made me sit on the sofa, and sat by me. He -held my hand in his, and said to me with, oh, such infinite sweetness, - -"My life is a barren and lonely one, and so full of work that I have -not had much time for friendships, but since I have been summoned to -here by my friend John Seward I have known so many good people and -seen such nobility that I feel more than ever, and it has grown with -my advancing years, the loneliness of my life. Believe me, then, that -I come here full of respect for you, and you have given me hope, hope, -not in what I am seeking of, but that there are good women still left -to make life happy, good women, whose lives and whose truths may make -good lesson for the children that are to be. I am glad, glad, that I -may here be of some use to you. For if your husband suffer, he suffer -within the range of my study and experience. I promise you that I -will gladly do all for him that I can, all to make his life strong and -manly, and your life a happy one. Now you must eat. You are -overwrought and perhaps over-anxious. Husband Jonathan would not like -to see you so pale, and what he like not where he love, is not to his -good. Therefore for his sake you must eat and smile. You have told -me about Lucy, and so now we shall not speak of it, lest it distress. -I shall stay in Exeter tonight, for I want to think much over what you -have told me, and when I have thought I will ask you questions, if I -may. And then too, you will tell me of husband Jonathan's trouble so -far as you can, but not yet. You must eat now, afterwards you shall -tell me all." - -After lunch, when we went back to the drawing room, he said to me, -"And now tell me all about him." - -When it came to speaking to this great learned man, I began to fear -that he would think me a weak fool, and Jonathan a madman, that -journal is all so strange, and I hesitated to go on. But he was so -sweet and kind, and he had promised to help, and I trusted him, so I -said, - -"Dr. Van Helsing, what I have to tell you is so queer that you must -not laugh at me or at my husband. I have been since yesterday in a -sort of fever of doubt. You must be kind to me, and not think me -foolish that I have even half believed some very strange things." - -He reassured me by his manner as well as his words when he said, "Oh, -my dear, if you only know how strange is the matter regarding which I -am here, it is you who would laugh. I have learned not to think -little of any one's belief, no matter how strange it may be. I have -tried to keep an open mind, and it is not the ordinary things of life -that could close it, but the strange things, the extraordinary things, -the things that make one doubt if they be mad or sane." - -"Thank you, thank you a thousand times! You have taken a weight off my -mind. If you will let me, I shall give you a paper to read. It is -long, but I have typewritten it out. It will tell you my trouble and -Jonathan's. It is the copy of his journal when abroad, and all that -happened. I dare not say anything of it. You will read for yourself -and judge. And then when I see you, perhaps, you will be very kind -and tell me what you think." - -"I promise," he said as I gave him the papers. "I shall in the -morning, as soon as I can, come to see you and your husband, if I -may." - -"Jonathan will be here at half-past eleven, and you must come to lunch -with us and see him then. You could catch the quick 3:34 train, which -will leave you at Paddington before eight." He was surprised at my -knowledge of the trains offhand, but he does not know that I have made -up all the trains to and from Exeter, so that I may help Jonathan in -case he is in a hurry. - -So he took the papers with him and went away, and I sit here thinking, -thinking I don't know what. - - - - -LETTER (by hand), VAN HELSING TO MRS. HARKER - -25 September, 6 o'clock - -"Dear Madam Mina, - -"I have read your husband's so wonderful diary. You may -sleep without doubt. Strange and terrible as it is, it is -true! I will pledge my life on it. It may be worse for -others, but for him and you there is no dread. He is a -noble fellow, and let me tell you from experience of men, -that one who would do as he did in going down that wall and -to that room, aye, and going a second time, is not one to -be injured in permanence by a shock. His brain and his -heart are all right, this I swear, before I have even seen -him, so be at rest. I shall have much to ask him of other -things. I am blessed that today I come to see you, for I -have learn all at once so much that again I am dazzled, -dazzled more than ever, and I must think. - -"Yours the most faithful, - -"Abraham Van Helsing." - - -LETTER, MRS. HARKER TO VAN HELSING - -25 September, 6:30 P.M. - -"My dear Dr. Van Helsing, - -"A thousand thanks for your kind letter, which has taken a -great weight off my mind. And yet, if it be true, what -terrible things there are in the world, and what an awful -thing if that man, that monster, be really in London! I -fear to think. I have this moment, whilst writing, had a -wire from Jonathan, saying that he leaves by the 6:25 tonight -from Launceston and will be here at 10:18, so that I shall have -no fear tonight. Will you, therefore, instead of lunching with -us, please come to breakfast at eight o'clock, if this be not too -early for you? You can get away, if you are in a hurry, by the -10:30 train, which will bring you to Paddington by 2:35. Do not -answer this, as I shall take it that, if I do not hear, you will -come to breakfast. - -"Believe me, - -"Your faithful and grateful friend, - -"Mina Harker." - - - - - -JONATHAN HARKER'S JOURNAL - -26 September.--I thought never to write in this diary again, but the -time has come. When I got home last night Mina had supper ready, and -when we had supped she told me of Van Helsing's visit, and of her -having given him the two diaries copied out, and of how anxious she -has been about me. She showed me in the doctor's letter that all I -wrote down was true. It seems to have made a new man of me. It was -the doubt as to the reality of the whole thing that knocked me over. -I felt impotent, and in the dark, and distrustful. But, now that I -know, I am not afraid, even of the Count. He has succeeded after all, -then, in his design in getting to London, and it was he I saw. He has -got younger, and how? Van Helsing is the man to unmask him and hunt -him out, if he is anything like what Mina says. We sat late, and -talked it over. Mina is dressing, and I shall call at the hotel in a -few minutes and bring him over. - - -He was, I think, surprised to see me. When I came into the room where -he was, and introduced myself, he took me by the shoulder, and turned -my face round to the light, and said, after a sharp scrutiny, - -"But Madam Mina told me you were ill, that you had had a shock." - -It was so funny to hear my wife called 'Madam Mina' by this kindly, -strong-faced old man. I smiled, and said, "I was ill, I have had a -shock, but you have cured me already." - -"And how?" - -"By your letter to Mina last night. I was in doubt, and then -everything took a hue of unreality, and I did not know what to trust, -even the evidence of my own senses. Not knowing what to trust, I did -not know what to do, and so had only to keep on working in what had -hitherto been the groove of my life. The groove ceased to avail me, -and I mistrusted myself. Doctor, you don't know what it is to doubt -everything, even yourself. No, you don't, you couldn't with eyebrows -like yours." - -He seemed pleased, and laughed as he said, "So! You are a -physiognomist. I learn more here with each hour. I am with so much -pleasure coming to you to breakfast, and, oh, sir, you will pardon -praise from an old man, but you are blessed in your wife." - -I would listen to him go on praising Mina for a day, so I simply -nodded and stood silent. - -"She is one of God's women, fashioned by His own hand to show us men -and other women that there is a heaven where we can enter, and that -its light can be here on earth. So true, so sweet, so noble, so -little an egoist, and that, let me tell you, is much in this age, so -sceptical and selfish. And you, sir . . . I have read all the letters -to poor Miss Lucy, and some of them speak of you, so I know you since -some days from the knowing of others, but I have seen your true self -since last night. You will give me your hand, will you not? And let -us be friends for all our lives." - -We shook hands, and he was so earnest and so kind that it made me -quite choky. - -"And now," he said, "may I ask you for some more help? I have a great -task to do, and at the beginning it is to know. You can help me -here. Can you tell me what went before your going to Transylvania? -Later on I may ask more help, and of a different kind, but at first -this will do." - -"Look here, Sir," I said, "does what you have to do concern the -Count?" - -"It does," he said solemnly. - -"Then I am with you heart and soul. As you go by the 10:30 train, you -will not have time to read them, but I shall get the bundle of papers. -You can take them with you and read them in the train." - -After breakfast I saw him to the station. When we were parting he -said, "Perhaps you will come to town if I send for you, and take Madam -Mina too." - -"We shall both come when you will," I said. - -I had got him the morning papers and the London papers of the previous -night, and while we were talking at the carriage window, waiting for -the train to start, he was turning them over. His eyes suddenly -seemed to catch something in one of them, "The Westminster Gazette", I -knew it by the colour, and he grew quite white. He read something -intently, groaning to himself, "Mein Gott! Mein Gott! So soon! So -soon!" I do not think he remembered me at the moment. Just then the -whistle blew, and the train moved off. This recalled him to himself, -and he leaned out of the window and waved his hand, calling out, "Love -to Madam Mina. I shall write so soon as ever I can." - - - - -DR. SEWARD'S DIARY - -26 September.--Truly there is no such thing as finality. Not a week -since I said "Finis," and yet here I am starting fresh again, or -rather going on with the record. Until this afternoon I had no cause -to think of what is done. Renfield had become, to all intents, as -sane as he ever was. He was already well ahead with his fly business, -and he had just started in the spider line also, so he had not been of -any trouble to me. I had a letter from Arthur, written on Sunday, and -from it I gather that he is bearing up wonderfully well. Quincey -Morris is with him, and that is much of a help, for he himself is a -bubbling well of good spirits. Quincey wrote me a line too, and from -him I hear that Arthur is beginning to recover something of his old -buoyancy, so as to them all my mind is at rest. As for myself, I was -settling down to my work with the enthusiasm which I used to have for -it, so that I might fairly have said that the wound which poor Lucy -left on me was becoming cicatrised. - -Everything is, however, now reopened, and what is to be the end God -only knows. I have an idea that Van Helsing thinks he knows, too, but -he will only let out enough at a time to whet curiosity. He went to -Exeter yesterday, and stayed there all night. Today he came back, and -almost bounded into the room at about half-past five o'clock, and -thrust last night's "Westminster Gazette" into my hand. - -"What do you think of that?" he asked as he stood back and folded his -arms. - -I looked over the paper, for I really did not know what he meant, but -he took it from me and pointed out a paragraph about children being -decoyed away at Hampstead. It did not convey much to me, until I -reached a passage where it described small puncture wounds on their -throats. An idea struck me, and I looked up. - -"Well?" he said. - -"It is like poor Lucy's." - -"And what do you make of it?" - -"Simply that there is some cause in common. Whatever it was that -injured her has injured them." I did not quite understand his answer. - -"That is true indirectly, but not directly." - -"How do you mean, Professor?" I asked. I was a little inclined to -take his seriousness lightly, for, after all, four days of rest and -freedom from burning, harrowing, anxiety does help to restore one's -spirits, but when I saw his face, it sobered me. Never, even in the -midst of our despair about poor Lucy, had he looked more stern. - -"Tell me!" I said. "I can hazard no opinion. I do not know what to -think, and I have no data on which to found a conjecture." - -"Do you mean to tell me, friend John, that you have no suspicion as to -what poor Lucy died of, not after all the hints given, not only by -events, but by me?" - -"Of nervous prostration following a great loss or waste of blood." - -"And how was the blood lost or wasted?" I shook my head. - -He stepped over and sat down beside me, and went on, "You are a clever -man, friend John. You reason well, and your wit is bold, but you are -too prejudiced. You do not let your eyes see nor your ears hear, and -that which is outside your daily life is not of account to you. Do -you not think that there are things which you cannot understand, and -yet which are, that some people see things that others cannot? But -there are things old and new which must not be contemplated by men's -eyes, because they know, or think they know, some things which other -men have told them. Ah, it is the fault of our science that it wants -to explain all, and if it explain not, then it says there is nothing -to explain. But yet we see around us every day the growth of new -beliefs, which think themselves new, and which are yet but the old, -which pretend to be young, like the fine ladies at the opera. I -suppose now you do not believe in corporeal transference. No? Nor in -materialization. No? Nor in astral bodies. No? Nor in the reading -of thought. No? Nor in hypnotism . . ." - -"Yes," I said. "Charcot has proved that pretty well." - -He smiled as he went on, "Then you are satisfied as to it. Yes? And -of course then you understand how it act, and can follow the mind of -the great Charcot, alas that he is no more, into the very soul of the -patient that he influence. No? Then, friend John, am I to take it -that you simply accept fact, and are satisfied to let from premise to -conclusion be a blank? No? Then tell me, for I am a student of the -brain, how you accept hypnotism and reject the thought reading. Let -me tell you, my friend, that there are things done today in electrical -science which would have been deemed unholy by the very man who -discovered electricity, who would themselves not so long before been -burned as wizards. There are always mysteries in life. Why was it -that Methuselah lived nine hundred years, and 'Old Parr' one hundred -and sixty-nine, and yet that poor Lucy, with four men's blood in her -poor veins, could not live even one day? For, had she live one more -day, we could save her. Do you know all the mystery of life and -death? Do you know the altogether of comparative anatomy and can say -wherefore the qualities of brutes are in some men, and not in others? -Can you tell me why, when other spiders die small and soon, that one -great spider lived for centuries in the tower of the old Spanish -church and grew and grew, till, on descending, he could drink the oil -of all the church lamps? Can you tell me why in the Pampas, ay and -elsewhere, there are bats that come out at night and open the veins of -cattle and horses and suck dry their veins, how in some islands of the -Western seas there are bats which hang on the trees all day, and those -who have seen describe as like giant nuts or pods, and that when the -sailors sleep on the deck, because that it is hot, flit down on them -and then, and then in the morning are found dead men, white as even -Miss Lucy was?" - -"Good God, Professor!" I said, starting up. "Do you mean to tell me -that Lucy was bitten by such a bat, and that such a thing is here in -London in the nineteenth century?" - -He waved his hand for silence, and went on, "Can you tell me why the -tortoise lives more long than generations of men, why the elephant -goes on and on till he have sees dynasties, and why the parrot never -die only of bite of cat of dog or other complaint? Can you tell me -why men believe in all ages and places that there are men and women -who cannot die? We all know, because science has vouched for the -fact, that there have been toads shut up in rocks for thousands of -years, shut in one so small hole that only hold him since the youth of -the world. Can you tell me how the Indian fakir can make himself to -die and have been buried, and his grave sealed and corn sowed on it, -and the corn reaped and be cut and sown and reaped and cut again, and -then men come and take away the unbroken seal and that there lie the -Indian fakir, not dead, but that rise up and walk amongst them as -before?" - -Here I interrupted him. I was getting bewildered. He so crowded on -my mind his list of nature's eccentricities and possible -impossibilities that my imagination was getting fired. I had a dim -idea that he was teaching me some lesson, as long ago he used to do in -his study at Amsterdam. But he used them to tell me the thing, so -that I could have the object of thought in mind all the time. But now -I was without his help, yet I wanted to follow him, so I said, - -"Professor, let me be your pet student again. Tell me the thesis, so -that I may apply your knowledge as you go on. At present I am going -in my mind from point to point as a madman, and not a sane one, -follows an idea. I feel like a novice lumbering through a bog in a -midst, jumping from one tussock to another in the mere blind effort to -move on without knowing where I am going." - -"That is a good image," he said. "Well, I shall tell you. My thesis -is this, I want you to believe." - -"To believe what?" - -"To believe in things that you cannot. Let me illustrate. I heard -once of an American who so defined faith, 'that faculty which enables -us to believe things which we know to be untrue.' For one, I follow -that man. He meant that we shall have an open mind, and not let a -little bit of truth check the rush of the big truth, like a small rock -does a railway truck. We get the small truth first. Good! We keep -him, and we value him, but all the same we must not let him think -himself all the truth in the universe." - -"Then you want me not to let some previous conviction inure the -receptivity of my mind with regard to some strange matter. Do I read -your lesson aright?" - -"Ah, you are my favourite pupil still. It is worth to teach you. Now -that you are willing to understand, you have taken the first step to -understand. You think then that those so small holes in the -children's throats were made by the same that made the holes in Miss -Lucy?" - -"I suppose so." - -He stood up and said solemnly, "Then you are wrong. Oh, would it were -so! But alas! No. It is worse, far, far worse." - -"In God's name, Professor Van Helsing, what do you mean?" I cried. - -He threw himself with a despairing gesture into a chair, and placed -his elbows on the table, covering his face with his hands as he spoke. - -"They were made by Miss Lucy!" - - - - -CHAPTER 15 - - -DR. SEWARD'S DIARY--cont. - -For a while sheer anger mastered me. It was as if he had during her -life struck Lucy on the face. I smote the table hard and rose up as I -said to him, "Dr. Van Helsing, are you mad?" - -He raised his head and looked at me, and somehow the tenderness of his -face calmed me at once. "Would I were!" he said. "Madness were easy -to bear compared with truth like this. Oh, my friend, why, think -you, did I go so far round, why take so long to tell so simple a -thing? Was it because I hate you and have hated you all my life? Was -it because I wished to give you pain? Was it that I wanted, now so -late, revenge for that time when you saved my life, and from a fearful -death? Ah no!" - -"Forgive me," said I. - -He went on, "My friend, it was because I wished to be gentle in the -breaking to you, for I know you have loved that so sweet lady. But -even yet I do not expect you to believe. It is so hard to accept at -once any abstract truth, that we may doubt such to be possible when we -have always believed the 'no' of it. It is more hard still to accept -so sad a concrete truth, and of such a one as Miss Lucy. Tonight I go -to prove it. Dare you come with me?" - -This staggered me. A man does not like to prove such a truth, Byron -excepted from the category, jealousy. - - "And prove the very truth he most abhorred." - -He saw my hesitation, and spoke, "The logic is simple, no madman's -logic this time, jumping from tussock to tussock in a misty bog. If -it not be true, then proof will be relief. At worst it will not harm. -If it be true! Ah, there is the dread. Yet every dread should help my -cause, for in it is some need of belief. Come, I tell you what I -propose. First, that we go off now and see that child in the -hospital. Dr. Vincent, of the North Hospital, where the papers say -the child is, is a friend of mine, and I think of yours since you were -in class at Amsterdam. He will let two scientists see his case, if he -will not let two friends. We shall tell him nothing, but only that we -wish to learn. And then . . ." - -"And then?" - -He took a key from his pocket and held it up. "And then we spend the -night, you and I, in the churchyard where Lucy lies. This is the key -that lock the tomb. I had it from the coffin man to give to Arthur." - -My heart sank within me, for I felt that there was some fearful ordeal -before us. I could do nothing, however, so I plucked up what heart I -could and said that we had better hasten, as the afternoon was -passing. - -We found the child awake. It had had a sleep and taken some food, and -altogether was going on well. Dr. Vincent took the bandage from its -throat, and showed us the punctures. There was no mistaking the -similarity to those which had been on Lucy's throat. They were -smaller, and the edges looked fresher, that was all. We asked Vincent -to what he attributed them, and he replied that it must have been a -bite of some animal, perhaps a rat, but for his own part, he was -inclined to think it was one of the bats which are so numerous on the -northern heights of London. "Out of so many harmless ones," he said, -"there may be some wild specimen from the South of a more malignant -species. Some sailor may have brought one home, and it managed to -escape, or even from the Zoological Gardens a young one may have got -loose, or one be bred there from a vampire. These things do occur, -you, know. Only ten days ago a wolf got out, and was, I believe, -traced up in this direction. For a week after, the children were -playing nothing but Red Riding Hood on the Heath and in every alley in -the place until this 'bloofer lady' scare came along, since then it -has been quite a gala time with them. Even this poor little mite, -when he woke up today, asked the nurse if he might go away. When she -asked him why he wanted to go, he said he wanted to play with the -'bloofer lady'." - -"I hope," said Van Helsing, "that when you are sending the child home -you will caution its parents to keep strict watch over it. These -fancies to stray are most dangerous, and if the child were to remain -out another night, it would probably be fatal. But in any case I -suppose you will not let it away for some days?" - -"Certainly not, not for a week at least, longer if the wound is not -healed." - -Our visit to the hospital took more time than we had reckoned on, and -the sun had dipped before we came out. When Van Helsing saw how dark -it was, he said, - -"There is not hurry. It is more late than I thought. Come, let us -seek somewhere that we may eat, and then we shall go on our way." - -We dined at 'Jack Straw's Castle' along with a little crowd of -bicyclists and others who were genially noisy. About ten o'clock we -started from the inn. It was then very dark, and the scattered lamps -made the darkness greater when we were once outside their individual -radius. The Professor had evidently noted the road we were to go, for -he went on unhesitatingly, but, as for me, I was in quite a mixup as -to locality. As we went further, we met fewer and fewer people, till -at last we were somewhat surprised when we met even the patrol of -horse police going their usual suburban round. At last we reached the -wall of the churchyard, which we climbed over. With some little -difficulty, for it was very dark, and the whole place seemed so -strange to us, we found the Westenra tomb. The Professor took the -key, opened the creaky door, and standing back, politely, but quite -unconsciously, motioned me to precede him. There was a delicious -irony in the offer, in the courtliness of giving preference on such a -ghastly occasion. My companion followed me quickly, and cautiously -drew the door to, after carefully ascertaining that the lock was a -falling, and not a spring one. In the latter case we should have been -in a bad plight. Then he fumbled in his bag, and taking out a -matchbox and a piece of candle, proceeded to make a light. The tomb -in the daytime, and when wreathed with fresh flowers, had looked grim -and gruesome enough, but now, some days afterwards, when the flowers -hung lank and dead, their whites turning to rust and their greens to -browns, when the spider and the beetle had resumed their accustomed -dominance, when the time-discoloured stone, and dust-encrusted mortar, -and rusty, dank iron, and tarnished brass, and clouded silver-plating -gave back the feeble glimmer of a candle, the effect was more -miserable and sordid than could have been imagined. It conveyed -irresistibly the idea that life, animal life, was not the only thing -which could pass away. - -Van Helsing went about his work systematically. Holding his candle so -that he could read the coffin plates, and so holding it that the sperm -dropped in white patches which congealed as they touched the metal, he -made assurance of Lucy's coffin. Another search in his bag, and he -took out a turnscrew. - -"What are you going to do?" I asked. - -"To open the coffin. You shall yet be convinced." - -Straightway he began taking out the screws, and finally lifted off the -lid, showing the casing of lead beneath. The sight was almost too -much for me. It seemed to be as much an affront to the dead as it -would have been to have stripped off her clothing in her sleep whilst -living. I actually took hold of his hand to stop him. - -He only said, "You shall see," and again fumbling in his bag took out -a tiny fret saw. Striking the turnscrew through the lead with a swift -downward stab, which made me wince, he made a small hole, which was, -however, big enough to admit the point of the saw. I had expected a -rush of gas from the week-old corpse. We doctors, who have had to -study our dangers, have to become accustomed to such things, and I -drew back towards the door. But the Professor never stopped for a -moment. He sawed down a couple of feet along one side of the lead -coffin, and then across, and down the other side. Taking the edge of -the loose flange, he bent it back towards the foot of the coffin, and -holding up the candle into the aperture, motioned to me to look. - -I drew near and looked. The coffin was empty. It was certainly a -surprise to me, and gave me a considerable shock, but Van Helsing was -unmoved. He was now more sure than ever of his ground, and so -emboldened to proceed in his task. "Are you satisfied now, friend -John?" he asked. - -I felt all the dogged argumentativeness of my nature awake within me as -I answered him, "I am satisfied that Lucy's body is not in that -coffin, but that only proves one thing." - -"And what is that, friend John?" - -"That it is not there." - -"That is good logic," he said, "so far as it goes. But how do you, -how can you, account for it not being there?" - -"Perhaps a body-snatcher," I suggested. "Some of the undertaker's -people may have stolen it." I felt that I was speaking folly, and yet -it was the only real cause which I could suggest. - -The Professor sighed. "Ah well!" he said, "we must have more proof. -Come with me." - -He put on the coffin lid again, gathered up all his things and placed -them in the bag, blew out the light, and placed the candle also in the -bag. We opened the door, and went out. Behind us he closed the door -and locked it. He handed me the key, saying, "Will you keep it? You -had better be assured." - -I laughed, it was not a very cheerful laugh, I am bound to say, as I -motioned him to keep it. "A key is nothing," I said, "there are many -duplicates, and anyhow it is not difficult to pick a lock of this -kind." - -He said nothing, but put the key in his pocket. Then he told me to -watch at one side of the churchyard whilst he would watch at the -other. - -I took up my place behind a yew tree, and I saw his dark figure move -until the intervening headstones and trees hid it from my sight. - -It was a lonely vigil. Just after I had taken my place I heard a -distant clock strike twelve, and in time came one and two. I was -chilled and unnerved, and angry with the Professor for taking me on -such an errand and with myself for coming. I was too cold and too -sleepy to be keenly observant, and not sleepy enough to betray my -trust, so altogether I had a dreary, miserable time. - -Suddenly, as I turned round, I thought I saw something like a white -streak, moving between two dark yew trees at the side of the -churchyard farthest from the tomb. At the same time a dark mass moved -from the Professor's side of the ground, and hurriedly went towards -it. Then I too moved, but I had to go round headstones and railed-off -tombs, and I stumbled over graves. The sky was overcast, and -somewhere far off an early cock crew. A little ways off, beyond a -line of scattered juniper trees, which marked the pathway to the -church, a white dim figure flitted in the direction of the tomb. The -tomb itself was hidden by trees, and I could not see where the figure -had disappeared. I heard the rustle of actual movement where I had -first seen the white figure, and coming over, found the Professor -holding in his arms a tiny child. When he saw me he held it out to -me, and said, "Are you satisfied now?" - -"No," I said, in a way that I felt was aggressive. - -"Do you not see the child?" - -"Yes, it is a child, but who brought it here? And is it wounded?" - -"We shall see," said the Professor, and with one impulse we took our -way out of the churchyard, he carrying the sleeping child. - -When we had got some little distance away, we went into a clump of -trees, and struck a match, and looked at the child's throat. It was -without a scratch or scar of any kind. - -"Was I right?" I asked triumphantly. - -"We were just in time," said the Professor thankfully. - -We had now to decide what we were to do with the child, and so -consulted about it. If we were to take it to a police station we -should have to give some account of our movements during the night. -At least, we should have had to make some statement as to how we had -come to find the child. So finally we decided that we would take it -to the Heath, and when we heard a policeman coming, would leave it -where he could not fail to find it. We would then seek our way home -as quickly as we could. All fell out well. At the edge of Hampstead -Heath we heard a policeman's heavy tramp, and laying the child on the -pathway, we waited and watched until he saw it as he flashed his -lantern to and fro. We heard his exclamation of astonishment, and -then we went away silently. By good chance we got a cab near the -'Spainiards,' and drove to town. - -I cannot sleep, so I make this entry. But I must try to get a few -hours' sleep, as Van Helsing is to call for me at noon. He insists -that I go with him on another expedition. - - -27 September.--It was two o'clock before we found a suitable -opportunity for our attempt. The funeral held at noon was all -completed, and the last stragglers of the mourners had taken -themselves lazily away, when, looking carefully from behind a clump of -alder trees, we saw the sexton lock the gate after him. We knew that -we were safe till morning did we desire it, but the Professor told me -that we should not want more than an hour at most. Again I felt that -horrid sense of the reality of things, in which any effort of -imagination seemed out of place, and I realized distinctly the perils -of the law which we were incurring in our unhallowed work. Besides, I -felt it was all so useless. Outrageous as it was to open a leaden -coffin, to see if a woman dead nearly a week were really dead, it now -seemed the height of folly to open the tomb again, when we knew, from -the evidence of our own eyesight, that the coffin was empty. I -shrugged my shoulders, however, and rested silent, for Van Helsing had -a way of going on his own road, no matter who remonstrated. He took -the key, opened the vault, and again courteously motioned me to -precede. The place was not so gruesome as last night, but oh, how -unutterably mean looking when the sunshine streamed in. Van Helsing -walked over to Lucy's coffin, and I followed. He bent over and again -forced back the leaden flange, and a shock of surprise and dismay shot -through me. - -There lay Lucy, seemingly just as we had seen her the night before her -funeral. She was, if possible, more radiantly beautiful than ever, -and I could not believe that she was dead. The lips were red, nay -redder than before, and on the cheeks was a delicate bloom. - -"Is this a juggle?" I said to him. - -"Are you convinced now?" said the Professor, in response, and as he -spoke he put over his hand, and in a way that made me shudder, pulled -back the dead lips and showed the white teeth. "See," he went on, -"they are even sharper than before. With this and this," and he -touched one of the canine teeth and that below it, "the little -children can be bitten. Are you of belief now, friend John?" - -Once more argumentative hostility woke within me. I could not accept -such an overwhelming idea as he suggested. So, with an attempt to -argue of which I was even at the moment ashamed, I said, "She may have -been placed here since last night." - -"Indeed? That is so, and by whom?" - -"I do not know. Someone has done it." - -"And yet she has been dead one week. Most peoples in that time would -not look so." - -I had no answer for this, so was silent. Van Helsing did not seem to -notice my silence. At any rate, he showed neither chagrin nor -triumph. He was looking intently at the face of the dead woman, -raising the eyelids and looking at the eyes, and once more opening the -lips and examining the teeth. Then he turned to me and said, - -"Here, there is one thing which is different from all recorded. Here -is some dual life that is not as the common. She was bitten by the -vampire when she was in a trance, sleep-walking, oh, you start. You -do not know that, friend John, but you shall know it later, and in -trance could he best come to take more blood. In trance she dies, and -in trance she is UnDead, too. So it is that she differ from all -other. Usually when the UnDead sleep at home," as he spoke he made a -comprehensive sweep of his arm to designate what to a vampire was -'home', "their face show what they are, but this so sweet that was -when she not UnDead she go back to the nothings of the common dead. -There is no malign there, see, and so it make hard that I must kill -her in her sleep." - -This turned my blood cold, and it began to dawn upon me that I was -accepting Van Helsing's theories. But if she were really dead, what -was there of terror in the idea of killing her? - -He looked up at me, and evidently saw the change in my face, for he -said almost joyously, "Ah, you believe now?" - -I answered, "Do not press me too hard all at once. I am willing to -accept. How will you do this bloody work?" - -"I shall cut off her head and fill her mouth with garlic, and I shall -drive a stake through her body." - -It made me shudder to think of so mutilating the body of the woman -whom I had loved. And yet the feeling was not so strong as I had -expected. I was, in fact, beginning to shudder at the presence of -this being, this UnDead, as Van Helsing called it, and to loathe it. -Is it possible that love is all subjective, or all objective? - -I waited a considerable time for Van Helsing to begin, but he stood as -if wrapped in thought. Presently he closed the catch of his bag with -a snap, and said, - -"I have been thinking, and have made up my mind as to what is best. -If I did simply follow my inclining I would do now, at this moment, -what is to be done. But there are other things to follow, and things -that are thousand times more difficult in that them we do not know. -This is simple. She have yet no life taken, though that is of time, -and to act now would be to take danger from her forever. But then we -may have to want Arthur, and how shall we tell him of this? If you, -who saw the wounds on Lucy's throat, and saw the wounds so similar on -the child's at the hospital, if you, who saw the coffin empty last -night and full today with a woman who have not change only to be more -rose and more beautiful in a whole week, after she die, if you know of -this and know of the white figure last night that brought the child to -the churchyard, and yet of your own senses you did not believe, how -then, can I expect Arthur, who know none of those things, to believe? - -"He doubted me when I took him from her kiss when she was dying. I -know he has forgiven me because in some mistaken idea I have done -things that prevent him say goodbye as he ought, and he may think that -in some more mistaken idea this woman was buried alive, and that in -most mistake of all we have killed her. He will then argue back that -it is we, mistaken ones, that have killed her by our ideas, and so he -will be much unhappy always. Yet he never can be sure, and that is -the worst of all. And he will sometimes think that she he loved was -buried alive, and that will paint his dreams with horrors of what she -must have suffered, and again, he will think that we may be right, and -that his so beloved was, after all, an UnDead. No! I told him once, -and since then I learn much. Now, since I know it is all true, a -hundred thousand times more do I know that he must pass through the -bitter waters to reach the sweet. He, poor fellow, must have one hour -that will make the very face of heaven grow black to him, then we can -act for good all round and send him peace. My mind is made up. Let -us go. You return home for tonight to your asylum, and see that all -be well. As for me, I shall spend the night here in this churchyard -in my own way. Tomorrow night you will come to me to the Berkeley -Hotel at ten of the clock. I shall send for Arthur to come too, and -also that so fine young man of America that gave his blood. Later we -shall all have work to do. I come with you so far as Piccadilly and -there dine, for I must be back here before the sun set." - -So we locked the tomb and came away, and got over the wall of the -churchyard, which was not much of a task, and drove back to -Piccadilly. - - - - -NOTE LEFT BY VAN HELSING IN HIS PORTMANTEAU, BERKELEY HOTEL DIRECTED TO -JOHN SEWARD, M. D. (Not Delivered) - -27 September - -"Friend John, - -"I write this in case anything should happen. I go alone to -watch in that churchyard. It pleases me that the UnDead, -Miss Lucy, shall not leave tonight, that so on the morrow -night she may be more eager. Therefore I shall fix some -things she like not, garlic and a crucifix, and so seal up -the door of the tomb. She is young as UnDead, and will -heed. Moreover, these are only to prevent her coming out. -They may not prevail on her wanting to get in, for then the -UnDead is desperate, and must find the line of least resistance, -whatsoever it may be. I shall be at hand all the night from -sunset till after sunrise, and if there be aught that may be -learned I shall learn it. For Miss Lucy or from her, I have no -fear, but that other to whom is there that she is UnDead, he have -not the power to seek her tomb and find shelter. He is cunning, -as I know from Mr. Jonathan and from the way that all along he -have fooled us when he played with us for Miss Lucy's life, and -we lost, and in many ways the UnDead are strong. He have always -the strength in his hand of twenty men, even we four who gave our -strength to Miss Lucy it also is all to him. Besides, he can -summon his wolf and I know not what. So if it be that he came -thither on this night he shall find me. But none other shall, -until it be too late. But it may be that he will not attempt the -place. There is no reason why he should. His hunting ground is -more full of game than the churchyard where the UnDead woman -sleeps, and the one old man watch. - -"Therefore I write this in case . . . Take the papers that -are with this, the diaries of Harker and the rest, and read -them, and then find this great UnDead, and cut off his head -and burn his heart or drive a stake through it, so that the -world may rest from him. - -"If it be so, farewell. - -"VAN HELSING." - - - - -DR. SEWARD'S DIARY - -28 September.--It is wonderful what a good night's sleep will do for -one. Yesterday I was almost willing to accept Van Helsing's monstrous -ideas, but now they seem to start out lurid before me as outrages on -common sense. I have no doubt that he believes it all. I wonder if -his mind can have become in any way unhinged. Surely there must be -some rational explanation of all these mysterious things. Is it -possible that the Professor can have done it himself? He is so -abnormally clever that if he went off his head he would carry out his -intent with regard to some fixed idea in a wonderful way. I am loathe -to think it, and indeed it would be almost as great a marvel as the -other to find that Van Helsing was mad, but anyhow I shall watch him -carefully. I may get some light on the mystery. - - -29 September.--Last night, at a little before ten o'clock, Arthur and -Quincey came into Van Helsing's room. He told us all what he wanted -us to do, but especially addressing himself to Arthur, as if all our -wills were centred in his. He began by saying that he hoped we would -all come with him too, "for," he said, "there is a grave duty to be -done there. You were doubtless surprised at my letter?" This query -was directly addressed to Lord Godalming. - -"I was. It rather upset me for a bit. There has been so much trouble -around my house of late that I could do without any more. I have been -curious, too, as to what you mean. - -"Quincey and I talked it over, but the more we talked, the more -puzzled we got, till now I can say for myself that I'm about up a tree -as to any meaning about anything." - -"Me too," said Quincey Morris laconically. - -"Oh," said the Professor, "then you are nearer the beginning, both of -you, than friend John here, who has to go a long way back before he -can even get so far as to begin." - -It was evident that he recognized my return to my old doubting frame -of mind without my saying a word. Then, turning to the other two, he -said with intense gravity, - -"I want your permission to do what I think good this night. It is, I -know, much to ask, and when you know what it is I propose to do you -will know, and only then how much. Therefore may I ask that you -promise me in the dark, so that afterwards, though you may be angry -with me for a time, I must not disguise from myself the possibility -that such may be, you shall not blame yourselves for anything." - -"That's frank anyhow," broke in Quincey. "I'll answer for the -Professor. I don't quite see his drift, but I swear he's honest, and -that's good enough for me." - -"I thank you, Sir," said Van Helsing proudly. "I have done myself the -honour of counting you one trusting friend, and such endorsement is -dear to me." He held out a hand, which Quincey took. - -Then Arthur spoke out, "Dr. Van Helsing, I don't quite like to 'buy a -pig in a poke', as they say in Scotland, and if it be anything in -which my honour as a gentleman or my faith as a Christian is -concerned, I cannot make such a promise. If you can assure me that -what you intend does not violate either of these two, then I give my -consent at once, though for the life of me, I cannot understand what -you are driving at." - -"I accept your limitation," said Van Helsing, "and all I ask of you is -that if you feel it necessary to condemn any act of mine, you will -first consider it well and be satisfied that it does not violate your -reservations." - -"Agreed!" said Arthur. "That is only fair. And now that the -pourparlers are over, may I ask what it is we are to do?" - -"I want you to come with me, and to come in secret, to the churchyard -at Kingstead." - -Arthur's face fell as he said in an amazed sort of way, - -"Where poor Lucy is buried?" - -The Professor bowed. - -Arthur went on, "And when there?" - -"To enter the tomb!" - -Arthur stood up. "Professor, are you in earnest, or is it some -monstrous joke? Pardon me, I see that you are in earnest." He sat -down again, but I could see that he sat firmly and proudly, as one who -is on his dignity. There was silence until he asked again, "And when -in the tomb?" - -"To open the coffin." - -"This is too much!" he said, angrily rising again. "I am willing to -be patient in all things that are reasonable, but in this, this -desecration of the grave, of one who . . ." He fairly choked with -indignation. - -The Professor looked pityingly at him. "If I could spare you one pang, -my poor friend," he said, "God knows I would. But this night our feet -must tread in thorny paths, or later, and for ever, the feet you love -must walk in paths of flame!" - -Arthur looked up with set white face and said, "Take care, sir, take -care!" - -"Would it not be well to hear what I have to say?" said Van Helsing. -"And then you will at least know the limit of my purpose. Shall I go -on?" - -"That's fair enough," broke in Morris. - -After a pause Van Helsing went on, evidently with an effort, "Miss -Lucy is dead, is it not so? Yes! Then there can be no wrong to her. -But if she be not dead . . ." - -Arthur jumped to his feet, "Good God!" he cried. "What do you mean? -Has there been any mistake, has she been buried alive?" He groaned in -anguish that not even hope could soften. - -"I did not say she was alive, my child. I did not think it. I go no -further than to say that she might be UnDead." - -"UnDead! Not alive! What do you mean? Is this all a nightmare, or -what is it?" - -"There are mysteries which men can only guess at, which age by age -they may solve only in part. Believe me, we are now on the verge of -one. But I have not done. May I cut off the head of dead Miss Lucy?" - -"Heavens and earth, no!" cried Arthur in a storm of passion. "Not for -the wide world will I consent to any mutilation of her dead body. Dr. -Van Helsing, you try me too far. What have I done to you that you -should torture me so? What did that poor, sweet girl do that you -should want to cast such dishonour on her grave? Are you mad, that you -speak of such things, or am I mad to listen to them? Don't dare think -more of such a desecration. I shall not give my consent to anything -you do. I have a duty to do in protecting her grave from outrage, and -by God, I shall do it!" - -Van Helsing rose up from where he had all the time been seated, and -said, gravely and sternly, "My Lord Godalming, I too, have a duty to -do, a duty to others, a duty to you, a duty to the dead, and by God, I -shall do it! All I ask you now is that you come with me, that you -look and listen, and if when later I make the same request you do not -be more eager for its fulfillment even than I am, then, I shall do my -duty, whatever it may seem to me. And then, to follow your Lordship's -wishes I shall hold myself at your disposal to render an account to -you, when and where you will." His voice broke a little, and he went -on with a voice full of pity. - -"But I beseech you, do not go forth in anger with me. In a long life -of acts which were often not pleasant to do, and which sometimes did -wring my heart, I have never had so heavy a task as now. Believe me -that if the time comes for you to change your mind towards me, one -look from you will wipe away all this so sad hour, for I would do what -a man can to save you from sorrow. Just think. For why should I give -myself so much labor and so much of sorrow? I have come here from my -own land to do what I can of good, at the first to please my friend -John, and then to help a sweet young lady, whom too, I come to love. -For her, I am ashamed to say so much, but I say it in kindness, I gave -what you gave, the blood of my veins. I gave it, I who was not, like -you, her lover, but only her physician and her friend. I gave her my -nights and days, before death, after death, and if my death can do her -good even now, when she is the dead UnDead, she shall have it freely." -He said this with a very grave, sweet pride, and Arthur was much -affected by it. - -He took the old man's hand and said in a broken voice, "Oh, it is hard -to think of it, and I cannot understand, but at least I shall go with -you and wait." - - - - -CHAPTER 16 - - -DR. SEWARD'S DIARY--cont. - -It was just a quarter before twelve o'clock when we got into the -churchyard over the low wall. The night was dark with occasional -gleams of moonlight between the dents of the heavy clouds that scudded -across the sky. We all kept somehow close together, with Van Helsing -slightly in front as he led the way. When we had come close to the -tomb I looked well at Arthur, for I feared the proximity to a place -laden with so sorrowful a memory would upset him, but he bore himself -well. I took it that the very mystery of the proceeding was in some -way a counteractant to his grief. The Professor unlocked the door, -and seeing a natural hesitation amongst us for various reasons, solved -the difficulty by entering first himself. The rest of us followed, -and he closed the door. He then lit a dark lantern and pointed to a -coffin. Arthur stepped forward hesitatingly. Van Helsing said to me, -"You were with me here yesterday. Was the body of Miss Lucy in that -coffin?" - -"It was." - -The Professor turned to the rest saying, "You hear, and yet there is -no one who does not believe with me." - -He took his screwdriver and again took off the lid of the coffin. -Arthur looked on, very pale but silent. When the lid was removed he -stepped forward. He evidently did not know that there was a leaden -coffin, or at any rate, had not thought of it. When he saw the rent -in the lead, the blood rushed to his face for an instant, but as -quickly fell away again, so that he remained of a ghastly whiteness. -He was still silent. Van Helsing forced back the leaden flange, and -we all looked in and recoiled. - -The coffin was empty! - -For several minutes no one spoke a word. The silence was broken by -Quincey Morris, "Professor, I answered for you. Your word is all I -want. I wouldn't ask such a thing ordinarily, I wouldn't so dishonour -you as to imply a doubt, but this is a mystery that goes beyond any -honour or dishonour. Is this your doing?" - -"I swear to you by all that I hold sacred that I have not removed or -touched her. What happened was this. Two nights ago my friend Seward -and I came here, with good purpose, believe me. I opened that coffin, -which was then sealed up, and we found it as now, empty. We then -waited, and saw something white come through the trees. The next day -we came here in daytime and she lay there. Did she not, friend John? - -"Yes." - -"That night we were just in time. One more so small child was -missing, and we find it, thank God, unharmed amongst the graves. -Yesterday I came here before sundown, for at sundown the UnDead can -move. I waited here all night till the sun rose, but I saw nothing. -It was most probable that it was because I had laid over the clamps of -those doors garlic, which the UnDead cannot bear, and other things -which they shun. Last night there was no exodus, so tonight before -the sundown I took away my garlic and other things. And so it is we -find this coffin empty. But bear with me. So far there is much that -is strange. Wait you with me outside, unseen and unheard, and things -much stranger are yet to be. So," here he shut the dark slide of his -lantern, "now to the outside." He opened the door, and we filed out, -he coming last and locking the door behind him. - -Oh! But it seemed fresh and pure in the night air after the terror of -that vault. How sweet it was to see the clouds race by, and the -passing gleams of the moonlight between the scudding clouds crossing -and passing, like the gladness and sorrow of a man's life. How sweet -it was to breathe the fresh air, that had no taint of death and decay. -How humanizing to see the red lighting of the sky beyond the hill, and -to hear far away the muffled roar that marks the life of a great -city. Each in his own way was solemn and overcome. Arthur was -silent, and was, I could see, striving to grasp the purpose and the -inner meaning of the mystery. I was myself tolerably patient, and -half inclined again to throw aside doubt and to accept Van Helsing's -conclusions. Quincey Morris was phlegmatic in the way of a man who -accepts all things, and accepts them in the spirit of cool bravery, -with hazard of all he has at stake. Not being able to smoke, he cut -himself a good-sized plug of tobacco and began to chew. As to Van -Helsing, he was employed in a definite way. First he took from his -bag a mass of what looked like thin, wafer-like biscuit, which was -carefully rolled up in a white napkin. Next he took out a double -handful of some whitish stuff, like dough or putty. He crumbled the -wafer up fine and worked it into the mass between his hands. This he -then took, and rolling it into thin strips, began to lay them into the -crevices between the door and its setting in the tomb. I was somewhat -puzzled at this, and being close, asked him what it was that he was -doing. Arthur and Quincey drew near also, as they too were curious. - -He answered, "I am closing the tomb so that the UnDead may not enter." - -"And is that stuff you have there going to do it?" - -"It is." - -"What is that which you are using?" This time the question was by -Arthur. Van Helsing reverently lifted his hat as he answered. - -"The Host. I brought it from Amsterdam. I have an Indulgence." - -It was an answer that appalled the most sceptical of us, and we felt -individually that in the presence of such earnest purpose as the -Professor's, a purpose which could thus use the to him most sacred of -things, it was impossible to distrust. In respectful silence we took -the places assigned to us close round the tomb, but hidden from the -sight of any one approaching. I pitied the others, especially Arthur. -I had myself been apprenticed by my former visits to this watching -horror, and yet I, who had up to an hour ago repudiated the proofs, -felt my heart sink within me. Never did tombs look so ghastly white. -Never did cypress, or yew, or juniper so seem the embodiment of -funeral gloom. Never did tree or grass wave or rustle so ominously. -Never did bough creak so mysteriously, and never did the far-away -howling of dogs send such a woeful presage through the night. - -There was a long spell of silence, big, aching, void, and then from -the Professor a keen "S-s-s-s!" He pointed, and far down the avenue of -yews we saw a white figure advance, a dim white figure, which held -something dark at its breast. The figure stopped, and at the moment a -ray of moonlight fell upon the masses of driving clouds, and showed in -startling prominence a dark-haired woman, dressed in the cerements of -the grave. We could not see the face, for it was bent down over what -we saw to be a fair-haired child. There was a pause and a sharp -little cry, such as a child gives in sleep, or a dog as it lies before -the fire and dreams. We were starting forward, but the Professor's -warning hand, seen by us as he stood behind a yew tree, kept us back. -And then as we looked the white figure moved forwards again. It was -now near enough for us to see clearly, and the moonlight still held. -My own heart grew cold as ice, and I could hear the gasp of Arthur, as -we recognized the features of Lucy Westenra. Lucy Westenra, but yet -how changed. The sweetness was turned to adamantine, heartless -cruelty, and the purity to voluptuous wantonness. - -Van Helsing stepped out, and obedient to his gesture, we all advanced -too. The four of us ranged in a line before the door of the tomb. Van -Helsing raised his lantern and drew the slide. By the concentrated -light that fell on Lucy's face we could see that the lips were crimson -with fresh blood, and that the stream had trickled over her chin and -stained the purity of her lawn death-robe. - -We shuddered with horror. I could see by the tremulous light that -even Van Helsing's iron nerve had failed. Arthur was next to me, and -if I had not seized his arm and held him up, he would have fallen. - -When Lucy, I call the thing that was before us Lucy because it bore -her shape, saw us she drew back with an angry snarl, such as a cat -gives when taken unawares, then her eyes ranged over us. Lucy's eyes -in form and colour, but Lucy's eyes unclean and full of hell fire, -instead of the pure, gentle orbs we knew. At that moment the remnant -of my love passed into hate and loathing. Had she then to be killed, -I could have done it with savage delight. As she looked, her eyes -blazed with unholy light, and the face became wreathed with a -voluptuous smile. Oh, God, how it made me shudder to see it! With a -careless motion, she flung to the ground, callous as a devil, the -child that up to now she had clutched strenuously to her breast, -growling over it as a dog growls over a bone. The child gave a sharp -cry, and lay there moaning. There was a cold-bloodedness in the act -which wrung a groan from Arthur. When she advanced to him with -outstretched arms and a wanton smile he fell back and hid his face in -his hands. - -She still advanced, however, and with a languorous, voluptuous grace, -said, "Come to me, Arthur. Leave these others and come to me. My -arms are hungry for you. Come, and we can rest together. Come, my -husband, come!" - -There was something diabolically sweet in her tones, something of the -tinkling of glass when struck, which rang through the brains even of -us who heard the words addressed to another. - -As for Arthur, he seemed under a spell, moving his hands from his -face, he opened wide his arms. She was leaping for them, when Van -Helsing sprang forward and held between them his little golden -crucifix. She recoiled from it, and, with a suddenly distorted face, -full of rage, dashed past him as if to enter the tomb. - -When within a foot or two of the door, however, she stopped, as if -arrested by some irresistible force. Then she turned, and her face -was shown in the clear burst of moonlight and by the lamp, which had -now no quiver from Van Helsing's nerves. Never did I see such baffled -malice on a face, and never, I trust, shall such ever be seen again by -mortal eyes. The beautiful colour became livid, the eyes seemed to -throw out sparks of hell fire, the brows were wrinkled as though the -folds of flesh were the coils of Medusa's snakes, and the lovely, -blood-stained mouth grew to an open square, as in the passion masks of -the Greeks and Japanese. If ever a face meant death, if looks could -kill, we saw it at that moment. - -And so for full half a minute, which seemed an eternity, she remained -between the lifted crucifix and the sacred closing of her means of -entry. - -Van Helsing broke the silence by asking Arthur, "Answer me, oh my -friend! Am I to proceed in my work?" - -"Do as you will, friend. Do as you will. There can be no horror like -this ever any more." And he groaned in spirit. - -Quincey and I simultaneously moved towards him, and took his arms. We -could hear the click of the closing lantern as Van Helsing held it -down. Coming close to the tomb, he began to remove from the chinks -some of the sacred emblem which he had placed there. We all looked on -with horrified amazement as we saw, when he stood back, the woman, -with a corporeal body as real at that moment as our own, pass through -the interstice where scarce a knife blade could have gone. We all -felt a glad sense of relief when we saw the Professor calmly restoring -the strings of putty to the edges of the door. - -When this was done, he lifted the child and said, "Come now, my -friends. We can do no more till tomorrow. There is a funeral at -noon, so here we shall all come before long after that. The friends -of the dead will all be gone by two, and when the sexton locks the -gate we shall remain. Then there is more to do, but not like this of -tonight. As for this little one, he is not much harmed, and by -tomorrow night he shall be well. We shall leave him where the police -will find him, as on the other night, and then to home." - -Coming close to Arthur, he said, "My friend Arthur, you have had a sore -trial, but after, when you look back, you will see how it was -necessary. You are now in the bitter waters, my child. By this time -tomorrow you will, please God, have passed them, and have drunk of the -sweet waters. So do not mourn over-much. Till then I shall not ask -you to forgive me." - -Arthur and Quincey came home with me, and we tried to cheer each other -on the way. We had left behind the child in safety, and were tired. -So we all slept with more or less reality of sleep. - - -29 September, night.--A little before twelve o'clock we three, Arthur, -Quincey Morris, and myself, called for the Professor. It was odd to -notice that by common consent we had all put on black clothes. Of -course, Arthur wore black, for he was in deep mourning, but the rest -of us wore it by instinct. We got to the graveyard by half-past one, -and strolled about, keeping out of official observation, so that when -the gravediggers had completed their task and the sexton, under the -belief that every one had gone, had locked the gate, we had the place -all to ourselves. Van Helsing, instead of his little black bag, had -with him a long leather one, something like a cricketing bag. It was -manifestly of fair weight. - -When we were alone and had heard the last of the footsteps die out up -the road, we silently, and as if by ordered intention, followed the -Professor to the tomb. He unlocked the door, and we entered, closing -it behind us. Then he took from his bag the lantern, which he lit, -and also two wax candles, which, when lighted, he stuck by melting -their own ends, on other coffins, so that they might give light -sufficient to work by. When he again lifted the lid off Lucy's coffin -we all looked, Arthur trembling like an aspen, and saw that the corpse -lay there in all its death beauty. But there was no love in my own -heart, nothing but loathing for the foul Thing which had taken Lucy's -shape without her soul. I could see even Arthur's face grow hard as -he looked. Presently he said to Van Helsing, "Is this really Lucy's -body, or only a demon in her shape?" - -"It is her body, and yet not it. But wait a while, and you shall see -her as she was, and is." - -She seemed like a nightmare of Lucy as she lay there, the pointed -teeth, the blood stained, voluptuous mouth, which made one shudder to -see, the whole carnal and unspirited appearance, seeming like a -devilish mockery of Lucy's sweet purity. Van Helsing, with his usual -methodicalness, began taking the various contents from his bag and -placing them ready for use. First he took out a soldering iron and -some plumbing solder, and then small oil lamp, which gave out, when -lit in a corner of the tomb, gas which burned at a fierce heat with a -blue flame, then his operating knives, which he placed to hand, and -last a round wooden stake, some two and a half or three inches thick -and about three feet long. One end of it was hardened by charring in -the fire, and was sharpened to a fine point. With this stake came a -heavy hammer, such as in households is used in the coal cellar for -breaking the lumps. To me, a doctor's preparations for work of any -kind are stimulating and bracing, but the effect of these things on -both Arthur and Quincey was to cause them a sort of consternation. -They both, however, kept their courage, and remained silent and quiet. - -When all was ready, Van Helsing said, "Before we do anything, let me -tell you this. It is out of the lore and experience of the ancients -and of all those who have studied the powers of the UnDead. When they -become such, there comes with the change the curse of immortality. -They cannot die, but must go on age after age adding new victims and -multiplying the evils of the world. For all that die from the preying -of the Undead become themselves Undead, and prey on their kind. And -so the circle goes on ever widening, like as the ripples from a stone -thrown in the water. Friend Arthur, if you had met that kiss which -you know of before poor Lucy die, or again, last night when you open -your arms to her, you would in time, when you had died, have become -nosferatu, as they call it in Eastern Europe, and would for all time -make more of those Un-Deads that so have filled us with horror. The -career of this so unhappy dear lady is but just begun. Those children -whose blood she sucked are not as yet so much the worse, but if she -lives on, UnDead, more and more they lose their blood and by her power -over them they come to her, and so she draw their blood with that so -wicked mouth. But if she die in truth, then all cease. The tiny -wounds of the throats disappear, and they go back to their play -unknowing ever of what has been. But of the most blessed of all, when -this now UnDead be made to rest as true dead, then the soul of the -poor lady whom we love shall again be free. Instead of working -wickedness by night and growing more debased in the assimilating of it -by day, she shall take her place with the other Angels. So that, my -friend, it will be a blessed hand for her that shall strike the blow -that sets her free. To this I am willing, but is there none amongst -us who has a better right? Will it be no joy to think of hereafter in -the silence of the night when sleep is not, 'It was my hand that sent -her to the stars. It was the hand of him that loved her best, the -hand that of all she would herself have chosen, had it been to her to -choose?' Tell me if there be such a one amongst us?" - -We all looked at Arthur. He saw too, what we all did, the infinite -kindness which suggested that his should be the hand which would -restore Lucy to us as a holy, and not an unholy, memory. He stepped -forward and said bravely, though his hand trembled, and his face was -as pale as snow, "My true friend, from the bottom of my broken heart I -thank you. Tell me what I am to do, and I shall not falter!" - -Van Helsing laid a hand on his shoulder, and said, "Brave lad! A -moment's courage, and it is done. This stake must be driven through -her. It well be a fearful ordeal, be not deceived in that, but it -will be only a short time, and you will then rejoice more than your -pain was great. From this grim tomb you will emerge as though you -tread on air. But you must not falter when once you have begun. Only -think that we, your true friends, are round you, and that we pray for -you all the time." - -"Go on," said Arthur hoarsely. "Tell me what I am to do." - -"Take this stake in your left hand, ready to place to the point over -the heart, and the hammer in your right. Then when we begin our -prayer for the dead, I shall read him, I have here the book, and the -others shall follow, strike in God's name, that so all may be well -with the dead that we love and that the UnDead pass away." - -Arthur took the stake and the hammer, and when once his mind was set -on action his hands never trembled nor even quivered. Van Helsing -opened his missal and began to read, and Quincey and I followed as -well as we could. - -Arthur placed the point over the heart, and as I looked I could see its -dint in the white flesh. Then he struck with all his might. - -The thing in the coffin writhed, and a hideous, blood-curdling screech -came from the opened red lips. The body shook and quivered and -twisted in wild contortions. The sharp white teeth champed together till -the lips were cut, and the mouth was smeared with a crimson foam. But -Arthur never faltered. He looked like a figure of Thor as his -untrembling arm rose and fell, driving deeper and deeper the -mercy-bearing stake, whilst the blood from the pierced heart welled -and spurted up around it. His face was set, and high duty seemed to -shine through it. The sight of it gave us courage so that our voices -seemed to ring through the little vault. - -And then the writhing and quivering of the body became less, and the -teeth seemed to champ, and the face to quiver. Finally it lay still. -The terrible task was over. - -The hammer fell from Arthur's hand. He reeled and would have fallen -had we not caught him. The great drops of sweat sprang from his -forehead, and his breath came in broken gasps. It had indeed been an -awful strain on him, and had he not been forced to his task by more -than human considerations he could never have gone through with it. -For a few minutes we were so taken up with him that we did not look -towards the coffin. When we did, however, a murmur of startled -surprise ran from one to the other of us. We gazed so eagerly that -Arthur rose, for he had been seated on the ground, and came and looked -too, and then a glad strange light broke over his face and dispelled -altogether the gloom of horror that lay upon it. - -There, in the coffin lay no longer the foul Thing that we had so -dreaded and grown to hate that the work of her destruction was yielded -as a privilege to the one best entitled to it, but Lucy as we had seen -her in life, with her face of unequalled sweetness and purity. True -that there were there, as we had seen them in life, the traces of care -and pain and waste. But these were all dear to us, for they marked -her truth to what we knew. One and all we felt that the holy calm -that lay like sunshine over the wasted face and form was only an -earthly token and symbol of the calm that was to reign for ever. - -Van Helsing came and laid his hand on Arthur's shoulder, and said to -him, "And now, Arthur my friend, dear lad, am I not forgiven?" - -The reaction of the terrible strain came as he took the old man's hand -in his, and raising it to his lips, pressed it, and said, "Forgiven! -God bless you that you have given my dear one her soul again, and me -peace." He put his hands on the Professor's shoulder, and laying his -head on his breast, cried for a while silently, whilst we stood -unmoving. - -When he raised his head Van Helsing said to him, "And now, my child, -you may kiss her. Kiss her dead lips if you will, as she would have -you to, if for her to choose. For she is not a grinning devil now, -not any more a foul Thing for all eternity. No longer she is the -devil's UnDead. She is God's true dead, whose soul is with Him!" - -Arthur bent and kissed her, and then we sent him and Quincey out of the -tomb. The Professor and I sawed the top off the stake, leaving the -point of it in the body. Then we cut off the head and filled the -mouth with garlic. We soldered up the leaden coffin, screwed on the -coffin lid, and gathering up our belongings, came away. When the -Professor locked the door he gave the key to Arthur. - -Outside the air was sweet, the sun shone, and the birds sang, and it -seemed as if all nature were tuned to a different pitch. There was -gladness and mirth and peace everywhere, for we were at rest ourselves -on one account, and we were glad, though it was with a tempered joy. - -Before we moved away Van Helsing said, "Now, my friends, one step of -our work is done, one the most harrowing to ourselves. But there -remains a greater task: to find out the author of all this our sorrow -and to stamp him out. I have clues which we can follow, but it is a -long task, and a difficult one, and there is danger in it, and pain. -Shall you not all help me? We have learned to believe, all of us, is -it not so? And since so, do we not see our duty? Yes! And do we not -promise to go on to the bitter end?" - -Each in turn, we took his hand, and the promise was made. Then said -the Professor as we moved off, "Two nights hence you shall meet with -me and dine together at seven of the clock with friend John. I shall -entreat two others, two that you know not as yet, and I shall be ready -to all our work show and our plans unfold. Friend John, you come with -me home, for I have much to consult you about, and you can help me. -Tonight I leave for Amsterdam, but shall return tomorrow night. And -then begins our great quest. But first I shall have much to say, so -that you may know what to do and to dread. Then our promise shall be -made to each other anew. For there is a terrible task before us, and -once our feet are on the ploughshare we must not draw back." - - - - -CHAPTER 17 - - -DR. SEWARD'S DIARY--cont. - -When we arrived at the Berkely Hotel, Van Helsing found a telegram -waiting for him. - -"Am coming up by train. Jonathan at Whitby. Important news. Mina -Harker." - - -The Professor was delighted. "Ah, that wonderful Madam Mina," he -said, "pearl among women! She arrive, but I cannot stay. She must go -to your house, friend John. You must meet her at the station. -Telegraph her en route so that she may be prepared." - -When the wire was dispatched he had a cup of tea. Over it he told me -of a diary kept by Jonathan Harker when abroad, and gave me a -typewritten copy of it, as also of Mrs. Harker's diary at Whitby. -"Take these," he said, "and study them well. When I have returned you -will be master of all the facts, and we can then better enter on our -inquisition. Keep them safe, for there is in them much of treasure. -You will need all your faith, even you who have had such an experience -as that of today. What is here told," he laid his hand heavily and -gravely on the packet of papers as he spoke, "may be the beginning of -the end to you and me and many another, or it may sound the knell of -the UnDead who walk the earth. Read all, I pray you, with the open -mind, and if you can add in any way to the story here told do so, for -it is all important. You have kept a diary of all these so strange -things, is it not so? Yes! Then we shall go through all these -together when we meet." He then made ready for his departure and -shortly drove off to Liverpool Street. I took my way to Paddington, -where I arrived about fifteen minutes before the train came in. - -The crowd melted away, after the bustling fashion common to arrival -platforms, and I was beginning to feel uneasy, lest I might miss my -guest, when a sweet-faced, dainty looking girl stepped up to me, and -after a quick glance said, "Dr. Seward, is it not?" - -"And you are Mrs. Harker!" I answered at once, whereupon she held out -her hand. - -"I knew you from the description of poor dear Lucy, but . . ." She -stopped suddenly, and a quick blush overspread her face. - -The blush that rose to my own cheeks somehow set us both at ease, for -it was a tacit answer to her own. I got her luggage, which included a -typewriter, and we took the Underground to Fenchurch Street, after I -had sent a wire to my housekeeper to have a sitting room and a bedroom -prepared at once for Mrs. Harker. - -In due time we arrived. She knew, of course, that the place was a -lunatic asylum, but I could see that she was unable to repress a -shudder when we entered. - -She told me that, if she might, she would come presently to my study, -as she had much to say. So here I am finishing my entry in my -phonograph diary whilst I await her. As yet I have not had the chance -of looking at the papers which Van Helsing left with me, though they -lie open before me. I must get her interested in something, so that I -may have an opportunity of reading them. She does not know how -precious time is, or what a task we have in hand. I must be careful -not to frighten her. Here she is! - - - - -MINA HARKER'S JOURNAL - -29 September.--After I had tidied myself, I went down to Dr. Seward's -study. At the door I paused a moment, for I thought I heard him -talking with some one. As, however, he had pressed me to be quick, I -knocked at the door, and on his calling out, "Come in," I entered. - -To my intense surprise, there was no one with him. He was quite -alone, and on the table opposite him was what I knew at once from the -description to be a phonograph. I had never seen one, and was much -interested. - -"I hope I did not keep you waiting," I said, "but I stayed at the door -as I heard you talking, and thought there was someone with you." - -"Oh," he replied with a smile, "I was only entering my diary." - -"Your diary?" I asked him in surprise. - -"Yes," he answered. "I keep it in this." As he spoke he laid his -hand on the phonograph. I felt quite excited over it, and blurted -out, "Why, this beats even shorthand! May I hear it say something?" - -"Certainly," he replied with alacrity, and stood up to put it in train -for speaking. Then he paused, and a troubled look overspread his -face. - -"The fact is," he began awkwardly, "I only keep my diary in it, and as -it is entirely, almost entirely, about my cases it may be awkward, -that is, I mean . . ." He stopped, and I tried to help him out of his -embarrassment. - -"You helped to attend dear Lucy at the end. Let me hear how she died, -for all that I know of her, I shall be very grateful. She was very, -very dear to me." - -To my surprise, he answered, with a horrorstruck look in his face, -"Tell you of her death? Not for the wide world!" - -"Why not?" I asked, for some grave, terrible feeling was coming over me. - -Again he paused, and I could see that he was trying to invent an -excuse. At length, he stammered out, "You see, I do not know how to -pick out any particular part of the diary." - -Even while he was speaking an idea dawned upon him, and he said with -unconscious simplicity, in a different voice, and with the naivete of -a child, "that's quite true, upon my honour. Honest Indian!" - -I could not but smile, at which he grimaced. "I gave myself away that -time!" he said. "But do you know that, although I have kept the diary -for months past, it never once struck me how I was going to find any -particular part of it in case I wanted to look it up?" - -By this time my mind was made up that the diary of a doctor who -attended Lucy might have something to add to the sum of our knowledge -of that terrible Being, and I said boldly, "Then, Dr. Seward, you had -better let me copy it out for you on my typewriter." - -He grew to a positively deathly pallor as he said, "No! No! No! For -all the world. I wouldn't let you know that terrible story!" - -Then it was terrible. My intuition was right! For a moment, I -thought, and as my eyes ranged the room, unconsciously looking for -something or some opportunity to aid me, they lit on a great batch of -typewriting on the table. His eyes caught the look in mine, and -without his thinking, followed their direction. As they saw the -parcel he realized my meaning. - -"You do not know me," I said. "When you have read those papers, my -own diary and my husband's also, which I have typed, you will know me -better. I have not faltered in giving every thought of my own heart -in this cause. But, of course, you do not know me, yet, and I must -not expect you to trust me so far." - -He is certainly a man of noble nature. Poor dear Lucy was right about -him. He stood up and opened a large drawer, in which were arranged in -order a number of hollow cylinders of metal covered with dark wax, and -said, - -"You are quite right. I did not trust you because I did not know -you. But I know you now, and let me say that I should have known you -long ago. I know that Lucy told you of me. She told me of you too. -May I make the only atonement in my power? Take the cylinders and -hear them. The first half-dozen of them are personal to me, and they -will not horrify you. Then you will know me better. Dinner will by -then be ready. In the meantime I shall read over some of these -documents, and shall be better able to understand certain things." - -He carried the phonograph himself up to my sitting room and adjusted -it for me. Now I shall learn something pleasant, I am sure. For it -will tell me the other side of a true love episode of which I know one -side already. - - - - -DR. SEWARD'S DIARY - -29 September.--I was so absorbed in that wonderful diary of Jonathan -Harker and that other of his wife that I let the time run on without -thinking. Mrs. Harker was not down when the maid came to announce -dinner, so I said, "She is possibly tired. Let dinner wait an hour," -and I went on with my work. I had just finished Mrs. Harker's diary, -when she came in. She looked sweetly pretty, but very sad, and her -eyes were flushed with crying. This somehow moved me much. Of late I -have had cause for tears, God knows! But the relief of them was -denied me, and now the sight of those sweet eyes, brightened by recent -tears, went straight to my heart. So I said as gently as I could, "I -greatly fear I have distressed you." - -"Oh, no, not distressed me," she replied. "But I have been more -touched than I can say by your grief. That is a wonderful machine, -but it is cruelly true. It told me, in its very tones, the anguish of -your heart. It was like a soul crying out to Almighty God. No one -must hear them spoken ever again! See, I have tried to be useful. I -have copied out the words on my typewriter, and none other need now -hear your heart beat, as I did." - -"No one need ever know, shall ever know," I said in a low voice. She -laid her hand on mine and said very gravely, "Ah, but they must!" - -"Must! But why?" I asked. - -"Because it is a part of the terrible story, a part of poor Lucy's -death and all that led to it. Because in the struggle which we have -before us to rid the earth of this terrible monster we must have all -the knowledge and all the help which we can get. I think that the -cylinders which you gave me contained more than you intended me to -know. But I can see that there are in your record many lights to this -dark mystery. You will let me help, will you not? I know all up to a -certain point, and I see already, though your diary only took me to 7 -September, how poor Lucy was beset, and how her terrible doom was -being wrought out. Jonathan and I have been working day and night -since Professor Van Helsing saw us. He is gone to Whitby to get more -information, and he will be here tomorrow to help us. We need have no -secrets amongst us. Working together and with absolute trust, we can -surely be stronger than if some of us were in the dark." - -She looked at me so appealingly, and at the same time manifested such -courage and resolution in her bearing, that I gave in at once to her -wishes. "You shall," I said, "do as you like in the matter. God -forgive me if I do wrong! There are terrible things yet to learn of, -but if you have so far traveled on the road to poor Lucy's death, you -will not be content, I know, to remain in the dark. Nay, the end, the -very end, may give you a gleam of peace. Come, there is dinner. We -must keep one another strong for what is before us. We have a cruel -and dreadful task. When you have eaten you shall learn the rest, and -I shall answer any questions you ask, if there be anything which you -do not understand, though it was apparent to us who were present." - - - -MINA HARKER'S JOURNAL - -29 September.--After dinner I came with Dr. Seward to his study. He -brought back the phonograph from my room, and I took a chair, and -arranged the phonograph so that I could touch it without getting up, -and showed me how to stop it in case I should want to pause. Then he -very thoughtfully took a chair, with his back to me, so that I might -be as free as possible, and began to read. I put the forked metal to -my ears and listened. - -When the terrible story of Lucy's death, and all that followed, was -done, I lay back in my chair powerless. Fortunately I am not of a -fainting disposition. When Dr. Seward saw me he jumped up with a -horrified exclamation, and hurriedly taking a case bottle from the -cupboard, gave me some brandy, which in a few minutes somewhat -restored me. My brain was all in a whirl, and only that there came -through all the multitude of horrors, the holy ray of light that my -dear Lucy was at last at peace, I do not think I could have borne it -without making a scene. It is all so wild and mysterious, and strange -that if I had not known Jonathan's experience in Transylvania I could -not have believed. As it was, I didn't know what to believe, and so -got out of my difficulty by attending to something else. I took the -cover off my typewriter, and said to Dr. Seward, - -"Let me write this all out now. We must be ready for Dr. Van Helsing -when he comes. I have sent a telegram to Jonathan to come on here -when he arrives in London from Whitby. In this matter dates are -everything, and I think that if we get all of our material ready, and -have every item put in chronological order, we shall have done much. - -"You tell me that Lord Godalming and Mr. Morris are coming too. Let -us be able to tell them when they come." - -He accordingly set the phonograph at a slow pace, and I began to -typewrite from the beginning of the seventeenth cylinder. I used -manifold, and so took three copies of the diary, just as I had done -with the rest. It was late when I got through, but Dr. Seward went -about his work of going his round of the patients. When he had -finished he came back and sat near me, reading, so that I did not feel -too lonely whilst I worked. How good and thoughtful he is. The world -seems full of good men, even if there are monsters in it. - -Before I left him I remembered what Jonathan put in his diary of the -Professor's perturbation at reading something in an evening paper at -the station at Exeter, so, seeing that Dr. Seward keeps his -newspapers, I borrowed the files of 'The Westminster Gazette' and 'The -Pall Mall Gazette' and took them to my room. I remember how much the -'Dailygraph' and 'The Whitby Gazette', of which I had made cuttings, -had helped us to understand the terrible events at Whitby when Count -Dracula landed, so I shall look through the evening papers since then, -and perhaps I shall get some new light. I am not sleepy, and the work -will help to keep me quiet. - - - - -DR. SEWARD'S DIARY - -30 September.--Mr. Harker arrived at nine o'clock. He got his wife's -wire just before starting. He is uncommonly clever, if one can judge -from his face, and full of energy. If this journal be true, and -judging by one's own wonderful experiences, it must be, he is also a -man of great nerve. That going down to the vault a second time was a -remarkable piece of daring. After reading his account of it I was -prepared to meet a good specimen of manhood, but hardly the quiet, -businesslike gentleman who came here today. - - -LATER.--After lunch Harker and his wife went back to their own room, -and as I passed a while ago I heard the click of the typewriter. They -are hard at it. Mrs. Harker says that they are knitting together in -chronological order every scrap of evidence they have. Harker has got -the letters between the consignee of the boxes at Whitby and the -carriers in London who took charge of them. He is now reading his -wife's transcript of my diary. I wonder what they make out of it. -Here it is . . . - -Strange that it never struck me that the very next house might be the -Count's hiding place! Goodness knows that we had enough clues from -the conduct of the patient Renfield! The bundle of letters relating -to the purchase of the house were with the transcript. Oh, if we had -only had them earlier we might have saved poor Lucy! Stop! That way -madness lies! Harker has gone back, and is again collecting material. -He says that by dinner time they will be able to show a whole -connected narrative. He thinks that in the meantime I should see -Renfield, as hitherto he has been a sort of index to the coming and -going of the Count. I hardly see this yet, but when I get at the -dates I suppose I shall. What a good thing that Mrs. Harker put my -cylinders into type! We never could have found the dates otherwise. - -I found Renfield sitting placidly in his room with his hands folded, -smiling benignly. At the moment he seemed as sane as any one I ever -saw. I sat down and talked with him on a lot of subjects, all of -which he treated naturally. He then, of his own accord, spoke of -going home, a subject he has never mentioned to my knowledge during -his sojourn here. In fact, he spoke quite confidently of getting his -discharge at once. I believe that, had I not had the chat with Harker -and read the letters and the dates of his outbursts, I should have -been prepared to sign for him after a brief time of observation. As -it is, I am darkly suspicious. All those out-breaks were in some way -linked with the proximity of the Count. What then does this absolute -content mean? Can it be that his instinct is satisfied as to the -vampire's ultimate triumph? Stay. He is himself zoophagous, and in -his wild ravings outside the chapel door of the deserted house he -always spoke of 'master'. This all seems confirmation of our idea. -However, after a while I came away. My friend is just a little too -sane at present to make it safe to probe him too deep with questions. -He might begin to think, and then . . . So I came away. I mistrust -these quiet moods of his, so I have given the attendant a hint to -look closely after him, and to have a strait waistcoat ready in case -of need. - - - - - -JOHNATHAN HARKER'S JOURNAL - -29 September, in train to London.--When I received Mr. Billington's -courteous message that he would give me any information in his power I -thought it best to go down to Whitby and make, on the spot, such -inquiries as I wanted. It was now my object to trace that horrid -cargo of the Count's to its place in London. Later, we may be able to -deal with it. Billington junior, a nice lad, met me at the station, -and brought me to his father's house, where they had decided that I -must spend the night. They are hospitable, with true Yorkshire -hospitality, give a guest everything and leave him to do as he likes. -They all knew that I was busy, and that my stay was short, and Mr. -Billington had ready in his office all the papers concerning the -consignment of boxes. It gave me almost a turn to see again one of -the letters which I had seen on the Count's table before I knew of his -diabolical plans. Everything had been carefully thought out, and done -systematically and with precision. He seemed to have been prepared -for every obstacle which might be placed by accident in the way of his -intentions being carried out. To use an Americanism, he had 'taken no -chances', and the absolute accuracy with which his instructions were -fulfilled was simply the logical result of his care. I saw the -invoice, and took note of it. 'Fifty cases of common earth, to be used -for experimental purposes'. Also the copy of the letter to Carter -Paterson, and their reply. Of both these I got copies. This was all -the information Mr. Billington could give me, so I went down to the -port and saw the coastguards, the Customs Officers and the harbour -master, who kindly put me in communication with the men who had -actually received the boxes. Their tally was exact with the list, and -they had nothing to add to the simple description 'fifty cases of -common earth', except that the boxes were 'main and mortal heavy', and -that shifting them was dry work. One of them added that it was hard -lines that there wasn't any gentleman 'such like as like yourself, -squire', to show some sort of appreciation of their efforts in a -liquid form. Another put in a rider that the thirst then generated -was such that even the time which had elapsed had not completely -allayed it. Needless to add, I took care before leaving to lift, -forever and adequately, this source of reproach. - -30 September.--The station master was good enough to give me a line to -his old companion the station master at King's Cross, so that when I -arrived there in the morning I was able to ask him about the arrival -of the boxes. He, too put me at once in communication with the proper -officials, and I saw that their tally was correct with the original -invoice. The opportunities of acquiring an abnormal thirst had been -here limited. A noble use of them had, however, been made, and again -I was compelled to deal with the result in ex post facto manner. - -From thence I went to Carter Paterson's central office, where I met -with the utmost courtesy. They looked up the transaction in their day -book and letter book, and at once telephoned to their King's Cross -office for more details. By good fortune, the men who did the teaming -were waiting for work, and the official at once sent them over, -sending also by one of them the way-bill and all the papers connected -with the delivery of the boxes at Carfax. Here again I found the -tally agreeing exactly. The carriers' men were able to supplement the -paucity of the written words with a few more details. These were, I -shortly found, connected almost solely with the dusty nature of the -job, and the consequent thirst engendered in the operators. On my -affording an opportunity, through the medium of the currency of the -realm, of the allaying, at a later period, this beneficial evil, one -of the men remarked, - -"That 'ere 'ouse, guv'nor, is the rummiest I ever was in. Blyme! But -it ain't been touched sence a hundred years. There was dust that -thick in the place that you might have slep' on it without 'urtin' of -yer bones. An' the place was that neglected that yer might 'ave -smelled ole Jerusalem in it. But the old chapel, that took the cike, -that did! Me and my mate, we thort we wouldn't never git out quick -enough. Lor', I wouldn't take less nor a quid a moment to stay there -arter dark." - -Having been in the house, I could well believe him, but if he knew -what I know, he would, I think have raised his terms. - -Of one thing I am now satisfied. That all those boxes which arrived at -Whitby from Varna in the Demeter were safely deposited in the old -chapel at Carfax. There should be fifty of them there, unless any -have since been removed, as from Dr. Seward's diary I fear. - - -Later.--Mina and I have worked all day, and we have put all the papers -into order. - - - - -MINA HARKER'S JOURNAL - -30 September.--I am so glad that I hardly know how to contain myself. -It is, I suppose, the reaction from the haunting fear which I have -had, that this terrible affair and the reopening of his old wound -might act detrimentally on Jonathan. I saw him leave for Whitby with -as brave a face as could, but I was sick with apprehension. The -effort has, however, done him good. He was never so resolute, never -so strong, never so full of volcanic energy, as at present. It is -just as that dear, good Professor Van Helsing said, he is true grit, -and he improves under strain that would kill a weaker nature. He came -back full of life and hope and determination. We have got everything -in order for tonight. I feel myself quite wild with excitement. I -suppose one ought to pity anything so hunted as the Count. That is -just it. This thing is not human, not even a beast. To read Dr. -Seward's account of poor Lucy's death, and what followed, is enough to -dry up the springs of pity in one's heart. - - -Later.--Lord Godalming and Mr. Morris arrived earlier than we -expected. Dr. Seward was out on business, and had taken Jonathan with -him, so I had to see them. It was to me a painful meeting, for it -brought back all poor dear Lucy's hopes of only a few months ago. Of -course they had heard Lucy speak of me, and it seemed that Dr. Van -Helsing, too, had been quite 'blowing my trumpet', as Mr. Morris -expressed it. Poor fellows, neither of them is aware that I know all -about the proposals they made to Lucy. They did not quite know what -to say or do, as they were ignorant of the amount of my knowledge. So -they had to keep on neutral subjects. However, I thought the matter -over, and came to the conclusion that the best thing I could do would -be to post them on affairs right up to date. I knew from Dr. Seward's -diary that they had been at Lucy's death, her real death, and that I -need not fear to betray any secret before the time. So I told them, -as well as I could, that I had read all the papers and diaries, and -that my husband and I, having typewritten them, had just finished -putting them in order. I gave them each a copy to read in the -library. When Lord Godalming got his and turned it over, it does make -a pretty good pile, he said, "Did you write all this, Mrs. Harker?" - -I nodded, and he went on. - -"I don't quite see the drift of it, but you people are all so good and -kind, and have been working so earnestly and so energetically, that -all I can do is to accept your ideas blindfold and try to help you. I -have had one lesson already in accepting facts that should make a man -humble to the last hour of his life. Besides, I know you loved my -Lucy . . ." - -Here he turned away and covered his face with his hands. I could hear -the tears in his voice. Mr. Morris, with instinctive delicacy, just -laid a hand for a moment on his shoulder, and then walked quietly out -of the room. I suppose there is something in a woman's nature that -makes a man free to break down before her and express his feelings on -the tender or emotional side without feeling it derogatory to his -manhood. For when Lord Godalming found himself alone with me he sat -down on the sofa and gave way utterly and openly. I sat down beside -him and took his hand. I hope he didn't think it forward of me, and -that if he ever thinks of it afterwards he never will have such a -thought. There I wrong him. I know he never will. He is too true a -gentleman. I said to him, for I could see that his heart was -breaking, "I loved dear Lucy, and I know what she was to you, and what -you were to her. She and I were like sisters, and now she is gone, -will you not let me be like a sister to you in your trouble? I know -what sorrows you have had, though I cannot measure the depth of them. -If sympathy and pity can help in your affliction, won't you let me be -of some little service, for Lucy's sake?" - -In an instant the poor dear fellow was overwhelmed with grief. It -seemed to me that all that he had of late been suffering in silence -found a vent at once. He grew quite hysterical, and raising his open -hands, beat his palms together in a perfect agony of grief. He stood -up and then sat down again, and the tears rained down his cheeks. I -felt an infinite pity for him, and opened my arms unthinkingly. With -a sob he laid his head on my shoulder and cried like a wearied child, -whilst he shook with emotion. - -We women have something of the mother in us that makes us rise above -smaller matters when the mother spirit is invoked. I felt this big -sorrowing man's head resting on me, as though it were that of a baby -that some day may lie on my bosom, and I stroked his hair as though he -were my own child. I never thought at the time how strange it all -was. - -After a little bit his sobs ceased, and he raised himself with an -apology, though he made no disguise of his emotion. He told me that -for days and nights past, weary days and sleepless nights, he had been -unable to speak with any one, as a man must speak in his time of -sorrow. There was no woman whose sympathy could be given to him, or -with whom, owing to the terrible circumstance with which his sorrow -was surrounded, he could speak freely. - -"I know now how I suffered," he said, as he dried his eyes, "but I do -not know even yet, and none other can ever know, how much your sweet -sympathy has been to me today. I shall know better in time, and -believe me that, though I am not ungrateful now, my gratitude will -grow with my understanding. You will let me be like a brother, will -you not, for all our lives, for dear Lucy's sake?" - -"For dear Lucy's sake," I said as we clasped hands. "Ay, and for your -own sake," he added, "for if a man's esteem and gratitude are ever -worth the winning, you have won mine today. If ever the future should -bring to you a time when you need a man's help, believe me, you will -not call in vain. God grant that no such time may ever come to you to -break the sunshine of your life, but if it should ever come, promise -me that you will let me know." - -He was so earnest, and his sorrow was so fresh, that I felt it would -comfort him, so I said, "I promise." - -As I came along the corridor I saw Mr. Morris looking out of a window. -He turned as he heard my footsteps. "How is Art?" he said. Then -noticing my red eyes, he went on, "Ah, I see you have been comforting -him. Poor old fellow! He needs it. No one but a woman can help a -man when he is in trouble of the heart, and he had no one to comfort -him." - -He bore his own trouble so bravely that my heart bled for him. I saw -the manuscript in his hand, and I knew that when he read it he would -realize how much I knew, so I said to him, "I wish I could comfort all -who suffer from the heart. Will you let me be your friend, and will -you come to me for comfort if you need it? You will know later why I -speak." - -He saw that I was in earnest, and stooping, took my hand, and raising -it to his lips, kissed it. It seemed but poor comfort to so brave and -unselfish a soul, and impulsively I bent over and kissed him. The -tears rose in his eyes, and there was a momentary choking in his -throat. He said quite calmly, "Little girl, you will never forget -that true hearted kindness, so long as ever you live!" Then he went -into the study to his friend. - -"Little girl!" The very words he had used to Lucy, and, oh, but he -proved himself a friend. - - - - -CHAPTER 18 - - -DR. SEWARD'S DIARY - -30 September.--I got home at five o'clock, and found that Godalming -and Morris had not only arrived, but had already studied the -transcript of the various diaries and letters which Harker had not yet -returned from his visit to the carriers' men, of whom Dr. Hennessey -had written to me. Mrs. Harker gave us a cup of tea, and I can -honestly say that, for the first time since I have lived in it, this -old house seemed like home. When we had finished, Mrs. Harker said, - -"Dr. Seward, may I ask a favour? I want to see your patient, Mr. -Renfield. Do let me see him. What you have said of him in your diary -interests me so much!" - -She looked so appealing and so pretty that I could not refuse her, and -there was no possible reason why I should, so I took her with me. -When I went into the room, I told the man that a lady would like to see -him, to which he simply answered, "Why?" - -"She is going through the house, and wants to see every one in it," I -answered. - -"Oh, very well," he said, "let her come in, by all means, but just -wait a minute till I tidy up the place." - -His method of tidying was peculiar, he simply swallowed all the flies -and spiders in the boxes before I could stop him. It was quite -evident that he feared, or was jealous of, some interference. When he -had got through his disgusting task, he said cheerfully, "Let the lady -come in," and sat down on the edge of his bed with his head down, but -with his eyelids raised so that he could see her as she entered. For -a moment I thought that he might have some homicidal intent. I -remembered how quiet he had been just before he attacked me in my own -study, and I took care to stand where I could seize him at once if he -attempted to make a spring at her. - -She came into the room with an easy gracefulness which would at once -command the respect of any lunatic, for easiness is one of the -qualities mad people most respect. She walked over to him, smiling -pleasantly, and held out her hand. - -"Good evening, Mr. Renfield," said she. "You see, I know you, for Dr. -Seward has told me of you." He made no immediate reply, but eyed her -all over intently with a set frown on his face. This look gave way to -one of wonder, which merged in doubt, then to my intense astonishment -he said, "You're not the girl the doctor wanted to marry, are you? You -can't be, you know, for she's dead." - -Mrs. Harker smiled sweetly as she replied, "Oh no! I have a husband -of my own, to whom I was married before I ever saw Dr. Seward, or he -me. I am Mrs. Harker." - -"Then what are you doing here?" - -"My husband and I are staying on a visit with Dr. Seward." - -"Then don't stay." - -"But why not?" - -I thought that this style of conversation might not be pleasant to -Mrs. Harker, any more than it was to me, so I joined in, "How did you -know I wanted to marry anyone?" - -His reply was simply contemptuous, given in a pause in which he turned -his eyes from Mrs. Harker to me, instantly turning them back again, -"What an asinine question!" - -"I don't see that at all, Mr. Renfield," said Mrs. Harker, at once -championing me. - -He replied to her with as much courtesy and respect as he had shown -contempt to me, "You will, of course, understand, Mrs. Harker, that -when a man is so loved and honoured as our host is, everything -regarding him is of interest in our little community. Dr. Seward is -loved not only by his household and his friends, but even by his -patients, who, being some of them hardly in mental equilibrium, are -apt to distort causes and effects. Since I myself have been an inmate -of a lunatic asylum, I cannot but notice that the sophistic tendencies -of some of its inmates lean towards the errors of non causa and -ignoratio elenche." - -I positively opened my eyes at this new development. Here was my own -pet lunatic, the most pronounced of his type that I had ever met with, -talking elemental philosophy, and with the manner of a polished -gentleman. I wonder if it was Mrs. Harker's presence which had -touched some chord in his memory. If this new phase was spontaneous, -or in any way due to her unconscious influence, she must have some -rare gift or power. - -We continued to talk for some time, and seeing that he was seemingly -quite reasonable, she ventured, looking at me questioningly as she -began, to lead him to his favourite topic. I was again astonished, -for he addressed himself to the question with the impartiality of -the completest sanity. He even took himself as an example when he -mentioned certain things. - -"Why, I myself am an instance of a man who had a strange belief. -Indeed, it was no wonder that my friends were alarmed, and insisted on -my being put under control. I used to fancy that life was a positive -and perpetual entity, and that by consuming a multitude of live -things, no matter how low in the scale of creation, one might -indefinitely prolong life. At times I held the belief so strongly -that I actually tried to take human life. The doctor here will bear -me out that on one occasion I tried to kill him for the purpose of -strengthening my vital powers by the assimilation with my own body of -his life through the medium of his blood, relying of course, upon the -Scriptural phrase, 'For the blood is the life.' Though, indeed, the -vendor of a certain nostrum has vulgarized the truism to the very -point of contempt. Isn't that true, doctor?" - -I nodded assent, for I was so amazed that I hardly knew what to either -think or say, it was hard to imagine that I had seen him eat up his -spiders and flies not five minutes before. Looking at my watch, I saw -that I should go to the station to meet Van Helsing, so I told Mrs. -Harker that it was time to leave. - -She came at once, after saying pleasantly to Mr. Renfield, "Goodbye, -and I hope I may see you often, under auspices pleasanter to -yourself." - -To which, to my astonishment, he replied, "Goodbye, my dear. I pray -God I may never see your sweet face again. May He bless and keep -you!" - -When I went to the station to meet Van Helsing I left the boys behind -me. Poor Art seemed more cheerful than he has been since Lucy first -took ill, and Quincey is more like his own bright self than he has -been for many a long day. - -Van Helsing stepped from the carriage with the eager nimbleness of a -boy. He saw me at once, and rushed up to me, saying, "Ah, friend -John, how goes all? Well? So! I have been busy, for I come here to -stay if need be. All affairs are settled with me, and I have much to -tell. Madam Mina is with you? Yes. And her so fine husband? And -Arthur and my friend Quincey, they are with you, too? Good!" - -As I drove to the house I told him of what had passed, and of how my -own diary had come to be of some use through Mrs. Harker's suggestion, -at which the Professor interrupted me. - -"Ah, that wonderful Madam Mina! She has man's brain, a brain that a -man should have were he much gifted, and a woman's heart. The good -God fashioned her for a purpose, believe me, when He made that so good -combination. Friend John, up to now fortune has made that woman of -help to us, after tonight she must not have to do with this so -terrible affair. It is not good that she run a risk so great. We men -are determined, nay, are we not pledged, to destroy this monster? But -it is no part for a woman. Even if she be not harmed, her heart may -fail her in so much and so many horrors and hereafter she may suffer, -both in waking, from her nerves, and in sleep, from her dreams. And, -besides, she is young woman and not so long married, there may be -other things to think of some time, if not now. You tell me she has -wrote all, then she must consult with us, but tomorrow she say goodbye -to this work, and we go alone." - -I agreed heartily with him, and then I told him what we had found in -his absence, that the house which Dracula had bought was the very next -one to my own. He was amazed, and a great concern seemed to come on -him. - -"Oh that we had known it before!" he said, "for then we might have -reached him in time to save poor Lucy. However, 'the milk that is -spilt cries not out afterwards,' as you say. We shall not think of -that, but go on our way to the end." Then he fell into a silence that -lasted till we entered my own gateway. Before we went to prepare for -dinner he said to Mrs. Harker, "I am told, Madam Mina, by my friend -John that you and your husband have put up in exact order all things -that have been, up to this moment." - -"Not up to this moment, Professor," she said impulsively, "but up to -this morning." - -"But why not up to now? We have seen hitherto how good light all the -little things have made. We have told our secrets, and yet no one who -has told is the worse for it." - -Mrs. Harker began to blush, and taking a paper from her pockets, she -said, "Dr. Van Helsing, will you read this, and tell me if it must go -in. It is my record of today. I too have seen the need of putting -down at present everything, however trivial, but there is little in -this except what is personal. Must it go in?" - -The Professor read it over gravely, and handed it back, saying, "It -need not go in if you do not wish it, but I pray that it may. It can -but make your husband love you the more, and all us, your friends, -more honour you, as well as more esteem and love." She took it back -with another blush and a bright smile. - -And so now, up to this very hour, all the records we have are complete -and in order. The Professor took away one copy to study after dinner, -and before our meeting, which is fixed for nine o'clock. The rest of -us have already read everything, so when we meet in the study we shall -all be informed as to facts, and can arrange our plan of battle with -this terrible and mysterious enemy. - - - - - -MINA HARKER'S JOURNAL - -30 September.--When we met in Dr. Seward's study two hours after -dinner, which had been at six o'clock, we unconsciously formed a sort -of board or committee. Professor Van Helsing took the head of the -table, to which Dr. Seward motioned him as he came into the room. He -made me sit next to him on his right, and asked me to act as -secretary. Jonathan sat next to me. Opposite us were Lord Godalming, -Dr. Seward, and Mr. Morris, Lord Godalming being next the Professor, -and Dr. Seward in the centre. - -The Professor said, "I may, I suppose, take it that we are all -acquainted with the facts that are in these papers." We all expressed -assent, and he went on, "Then it were, I think, good that I tell you -something of the kind of enemy with which we have to deal. I shall -then make known to you something of the history of this man, which has -been ascertained for me. So we then can discuss how we shall act, and -can take our measure according. - -"There are such beings as vampires, some of us have evidence that they -exist. Even had we not the proof of our own unhappy experience, the -teachings and the records of the past give proof enough for sane -peoples. I admit that at the first I was sceptic. Were it not that -through long years I have trained myself to keep an open mind, I could -not have believed until such time as that fact thunder on my ear. 'See! -See! I prove, I prove.' Alas! Had I known at first what now I know, -nay, had I even guess at him, one so precious life had been spared to -many of us who did love her. But that is gone, and we must so work, -that other poor souls perish not, whilst we can save. The nosferatu -do not die like the bee when he sting once. He is only stronger, and -being stronger, have yet more power to work evil. This vampire which -is amongst us is of himself so strong in person as twenty men, he is -of cunning more than mortal, for his cunning be the growth of ages, he -have still the aids of necromancy, which is, as his etymology imply, -the divination by the dead, and all the dead that he can come nigh to -are for him at command; he is brute, and more than brute; he is devil -in callous, and the heart of him is not; he can, within his range, -direct the elements, the storm, the fog, the thunder; he can command -all the meaner things, the rat, and the owl, and the bat, the moth, -and the fox, and the wolf, he can grow and become small; and he can at -times vanish and come unknown. How then are we to begin our strike to -destroy him? How shall we find his where, and having found it, how -can we destroy? My friends, this is much, it is a terrible task that -we undertake, and there may be consequence to make the brave shudder. -For if we fail in this our fight he must surely win, and then where -end we? Life is nothings, I heed him not. But to fail here, is not -mere life or death. It is that we become as him, that we henceforward -become foul things of the night like him, without heart or conscience, -preying on the bodies and the souls of those we love best. To us -forever are the gates of heaven shut, for who shall open them to us -again? We go on for all time abhorred by all, a blot on the face of -God's sunshine, an arrow in the side of Him who died for man. But we -are face to face with duty, and in such case must we shrink? For me, -I say no, but then I am old, and life, with his sunshine, his fair -places, his song of birds, his music and his love, lie far behind. You -others are young. Some have seen sorrow, but there are fair days yet -in store. What say you?" - -Whilst he was speaking, Jonathan had taken my hand. I feared, oh so -much, that the appalling nature of our danger was overcoming him when -I saw his hand stretch out, but it was life to me to feel its touch, -so strong, so self reliant, so resolute. A brave man's hand can speak -for itself, it does not even need a woman's love to hear its music. - -When the Professor had done speaking my husband looked in my eyes, and -I in his, there was no need for speaking between us. - -"I answer for Mina and myself," he said. - -"Count me in, Professor," said Mr. Quincey Morris, laconically as -usual. - -"I am with you," said Lord Godalming, "for Lucy's sake, if for no -other reason." - -Dr. Seward simply nodded. - -The Professor stood up and, after laying his golden crucifix on the -table, held out his hand on either side. I took his right hand, and -Lord Godalming his left, Jonathan held my right with his left and -stretched across to Mr. Morris. So as we all took hands our solemn -compact was made. I felt my heart icy cold, but it did not even occur -to me to draw back. We resumed our places, and Dr. Van Helsing went -on with a sort of cheerfulness which showed that the serious work had -begun. It was to be taken as gravely, and in as businesslike a way, -as any other transaction of life. - -"Well, you know what we have to contend against, but we too, are not -without strength. We have on our side power of combination, a power -denied to the vampire kind, we have sources of science, we are free to -act and think, and the hours of the day and the night are ours -equally. In fact, so far as our powers extend, they are unfettered, -and we are free to use them. We have self devotion in a cause and an -end to achieve which is not a selfish one. These things are much. - -"Now let us see how far the general powers arrayed against us are -restrict, and how the individual cannot. In fine, let us consider the -limitations of the vampire in general, and of this one in particular. - -"All we have to go upon are traditions and superstitions. These do -not at the first appear much, when the matter is one of life and -death, nay of more than either life or death. Yet must we be -satisfied, in the first place because we have to be, no other means is -at our control, and secondly, because, after all these things, -tradition and superstition, are everything. Does not the belief in -vampires rest for others, though not, alas! for us, on them? A year -ago which of us would have received such a possibility, in the midst -of our scientific, sceptical, matter-of-fact nineteenth century? We -even scouted a belief that we saw justified under our very eyes. Take -it, then, that the vampire, and the belief in his limitations and his -cure, rest for the moment on the same base. For, let me tell you, he -is known everywhere that men have been. In old Greece, in old Rome, -he flourish in Germany all over, in France, in India, even in the -Chermosese, and in China, so far from us in all ways, there even is -he, and the peoples for him at this day. He have follow the wake of -the berserker Icelander, the devil-begotten Hun, the Slav, the Saxon, -the Magyar. - -"So far, then, we have all we may act upon, and let me tell you that -very much of the beliefs are justified by what we have seen in our own -so unhappy experience. The vampire live on, and cannot die by mere -passing of the time, he can flourish when that he can fatten on the -blood of the living. Even more, we have seen amongst us that he can -even grow younger, that his vital faculties grow strenuous, and seem -as though they refresh themselves when his special pabulum is plenty. - -"But he cannot flourish without this diet, he eat not as others. Even -friend Jonathan, who lived with him for weeks, did never see him eat, -never! He throws no shadow, he make in the mirror no reflect, as -again Jonathan observe. He has the strength of many of his hand, -witness again Jonathan when he shut the door against the wolves, and -when he help him from the diligence too. He can transform himself to -wolf, as we gather from the ship arrival in Whitby, when he tear open -the dog, he can be as bat, as Madam Mina saw him on the window at -Whitby, and as friend John saw him fly from this so near house, and as -my friend Quincey saw him at the window of Miss Lucy. - -"He can come in mist which he create, that noble ship's captain proved -him of this, but, from what we know, the distance he can make this -mist is limited, and it can only be round himself. - -"He come on moonlight rays as elemental dust, as again Jonathan saw -those sisters in the castle of Dracula. He become so small, we -ourselves saw Miss Lucy, ere she was at peace, slip through a -hairbreadth space at the tomb door. He can, when once he find his -way, come out from anything or into anything, no matter how close it -be bound or even fused up with fire, solder you call it. He can see -in the dark, no small power this, in a world which is one half shut -from the light. Ah, but hear me through. - -"He can do all these things, yet he is not free. Nay, he is even more -prisoner than the slave of the galley, than the madman in his cell. -He cannot go where he lists, he who is not of nature has yet to obey -some of nature's laws, why we know not. He may not enter anywhere at -the first, unless there be some one of the household who bid him to -come, though afterwards he can come as he please. His power ceases, -as does that of all evil things, at the coming of the day. - -"Only at certain times can he have limited freedom. If he be not at -the place whither he is bound, he can only change himself at noon or -at exact sunrise or sunset. These things we are told, and in this -record of ours we have proof by inference. Thus, whereas he can do as -he will within his limit, when he have his earth-home, his -coffin-home, his hell-home, the place unhallowed, as we saw when he -went to the grave of the suicide at Whitby, still at other time he can -only change when the time come. It is said, too, that he can only -pass running water at the slack or the flood of the tide. Then there -are things which so afflict him that he has no power, as the garlic -that we know of, and as for things sacred, as this symbol, my -crucifix, that was amongst us even now when we resolve, to them he is -nothing, but in their presence he take his place far off and silent -with respect. There are others, too, which I shall tell you of, lest -in our seeking we may need them. - -"The branch of wild rose on his coffin keep him that he move not from -it, a sacred bullet fired into the coffin kill him so that he be true -dead, and as for the stake through him, we know already of its peace, -or the cut off head that giveth rest. We have seen it with our eyes. - -"Thus when we find the habitation of this man-that-was, we can confine -him to his coffin and destroy him, if we obey what we know. But he is -clever. I have asked my friend Arminius, of Buda-Pesth University, to -make his record, and from all the means that are, he tell me of what -he has been. He must, indeed, have been that Voivode Dracula who won -his name against the Turk, over the great river on the very frontier -of Turkeyland. If it be so, then was he no common man, for in that -time, and for centuries after, he was spoken of as the cleverest and -the most cunning, as well as the bravest of the sons of the 'land -beyond the forest.' That mighty brain and that iron resolution went -with him to his grave, and are even now arrayed against us. The -Draculas were, says Arminius, a great and noble race, though now and -again were scions who were held by their coevals to have had dealings -with the Evil One. They learned his secrets in the Scholomance, -amongst the mountains over Lake Hermanstadt, where the devil claims -the tenth scholar as his due. In the records are such words as -'stregoica' witch, 'ordog' and 'pokol' Satan and hell, and in one -manuscript this very Dracula is spoken of as 'wampyr,' which we all -understand too well. There have been from the loins of this very one -great men and good women, and their graves make sacred the earth where -alone this foulness can dwell. For it is not the least of its terrors -that this evil thing is rooted deep in all good, in soil barren of -holy memories it cannot rest." - -Whilst they were talking Mr. Morris was looking steadily at the -window, and he now got up quietly, and went out of the room. There -was a little pause, and then the Professor went on. - -"And now we must settle what we do. We have here much data, and we -must proceed to lay out our campaign. We know from the inquiry of -Jonathan that from the castle to Whitby came fifty boxes of earth, all -of which were delivered at Carfax, we also know that at least some of -these boxes have been removed. It seems to me, that our first step -should be to ascertain whether all the rest remain in the house beyond -that wall where we look today, or whether any more have been removed. -If the latter, we must trace . . ." - -Here we were interrupted in a very startling way. Outside the house -came the sound of a pistol shot, the glass of the window was shattered -with a bullet, which ricochetting from the top of the embrasure, -struck the far wall of the room. I am afraid I am at heart a coward, -for I shrieked out. The men all jumped to their feet, Lord Godalming -flew over to the window and threw up the sash. As he did so we heard -Mr. Morris' voice without, "Sorry! I fear I have alarmed you. I -shall come in and tell you about it." - -A minute later he came in and said, "It was an idiotic thing of me to -do, and I ask your pardon, Mrs. Harker, most sincerely, I fear I must -have frightened you terribly. But the fact is that whilst the -Professor was talking there came a big bat and sat on the window sill. -I have got such a horror of the damned brutes from recent events that -I cannot stand them, and I went out to have a shot, as I have been -doing of late of evenings, whenever I have seen one. You used to -laugh at me for it then, Art." - -"Did you hit it?" asked Dr. Van Helsing. - -"I don't know, I fancy not, for it flew away into the wood." Without -saying any more he took his seat, and the Professor began to resume -his statement. - -"We must trace each of these boxes, and when we are ready, we must -either capture or kill this monster in his lair, or we must, so to -speak, sterilize the earth, so that no more he can seek safety in it. -Thus in the end we may find him in his form of man between the hours -of noon and sunset, and so engage with him when he is at his most -weak. - -"And now for you, Madam Mina, this night is the end until all be well. -You are too precious to us to have such risk. When we part tonight, -you no more must question. We shall tell you all in good time. We -are men and are able to bear, but you must be our star and our hope, -and we shall act all the more free that you are not in the danger, -such as we are." - -All the men, even Jonathan, seemed relieved, but it did not seem to me -good that they should brave danger and, perhaps lessen their safety, -strength being the best safety, through care of me, but their minds -were made up, and though it was a bitter pill for me to swallow, I -could say nothing, save to accept their chivalrous care of me. - -Mr. Morris resumed the discussion, "As there is no time to lose, I -vote we have a look at his house right now. Time is everything with -him, and swift action on our part may save another victim." - -I own that my heart began to fail me when the time for action came so -close, but I did not say anything, for I had a greater fear that if I -appeared as a drag or a hindrance to their work, they might even leave -me out of their counsels altogether. They have now gone off to -Carfax, with means to get into the house. - -Manlike, they had told me to go to bed and sleep, as if a woman can -sleep when those she loves are in danger! I shall lie down, and -pretend to sleep, lest Jonathan have added anxiety about me when he -returns. - - - - -DR. SEWARD'S DIARY - -1 October, 4 A.M.--Just as we were about to leave the house, an urgent -message was brought to me from Renfield to know if I would see him at -once, as he had something of the utmost importance to say to me. I -told the messenger to say that I would attend to his wishes in the -morning, I was busy just at the moment. - -The attendant added, "He seems very importunate, sir. I have never -seen him so eager. I don't know but what, if you don't see him soon, -he will have one of his violent fits." I knew the man would not have -said this without some cause, so I said, "All right, I'll go now," and -I asked the others to wait a few minutes for me, as I had to go and -see my patient. - -"Take me with you, friend John," said the Professor. "His case in your -diary interest me much, and it had bearing, too, now and again on our -case. I should much like to see him, and especial when his mind is -disturbed." - -"May I come also?" asked Lord Godalming. - -"Me too?" said Quincey Morris. "May I come?" said Harker. I nodded, -and we all went down the passage together. - -We found him in a state of considerable excitement, but far more -rational in his speech and manner than I had ever seen him. There was -an unusual understanding of himself, which was unlike anything I had -ever met with in a lunatic, and he took it for granted that his -reasons would prevail with others entirely sane. We all five went -into the room, but none of the others at first said anything. His -request was that I would at once release him from the asylum and send -him home. This he backed up with arguments regarding his complete -recovery, and adduced his own existing sanity. - -"I appeal to your friends," he said, "they will, perhaps, not mind -sitting in judgement on my case. By the way, you have not introduced -me." - -I was so much astonished, that the oddness of introducing a madman in -an asylum did not strike me at the moment, and besides, there was a -certain dignity in the man's manner, so much of the habit of equality, -that I at once made the introduction, "Lord Godalming, Professor Van -Helsing, Mr. Quincey Morris, of Texas, Mr. Jonathan Harker, Mr. -Renfield." - -He shook hands with each of them, saying in turn, "Lord Godalming, I -had the honour of seconding your father at the Windham; I grieve to -know, by your holding the title, that he is no more. He was a man -loved and honoured by all who knew him, and in his youth was, I have -heard, the inventor of a burnt rum punch, much patronized on Derby -night. Mr. Morris, you should be proud of your great state. Its -reception into the Union was a precedent which may have far-reaching -effects hereafter, when the Pole and the Tropics may hold alliance to -the Stars and Stripes. The power of Treaty may yet prove a vast -engine of enlargement, when the Monroe doctrine takes its true place -as a political fable. What shall any man say of his pleasure at -meeting Van Helsing? Sir, I make no apology for dropping all forms of -conventional prefix. When an individual has revolutionized -therapeutics by his discovery of the continuous evolution of brain -matter, conventional forms are unfitting, since they would seem to -limit him to one of a class. You, gentlemen, who by nationality, by -heredity, or by the possession of natural gifts, are fitted to hold -your respective places in the moving world, I take to witness that I -am as sane as at least the majority of men who are in full possession -of their liberties. And I am sure that you, Dr. Seward, humanitarian -and medico-jurist as well as scientist, will deem it a moral duty to -deal with me as one to be considered as under exceptional -circumstances." He made this last appeal with a courtly air of -conviction which was not without its own charm. - -I think we were all staggered. For my own part, I was under the -conviction, despite my knowledge of the man's character and history, -that his reason had been restored, and I felt under a strong impulse -to tell him that I was satisfied as to his sanity, and would see about -the necessary formalities for his release in the morning. I thought -it better to wait, however, before making so grave a statement, for of -old I knew the sudden changes to which this particular patient was -liable. So I contented myself with making a general statement that he -appeared to be improving very rapidly, that I would have a longer chat -with him in the morning, and would then see what I could do in the -direction of meeting his wishes. - -This did not at all satisfy him, for he said quickly, "But I fear, Dr. -Seward, that you hardly apprehend my wish. I desire to go at once, -here, now, this very hour, this very moment, if I may. Time presses, -and in our implied agreement with the old scytheman it is of the -essence of the contract. I am sure it is only necessary to put before -so admirable a practitioner as Dr. Seward so simple, yet so momentous -a wish, to ensure its fulfilment." - -He looked at me keenly, and seeing the negative in my face, turned to -the others, and scrutinized them closely. Not meeting any sufficient -response, he went on, "Is it possible that I have erred in my -supposition?" - -"You have," I said frankly, but at the same time, as I felt, brutally. - -There was a considerable pause, and then he said slowly, "Then I -suppose I must only shift my ground of request. Let me ask for this -concession, boon, privilege, what you will. I am content to implore -in such a case, not on personal grounds, but for the sake of others. I -am not at liberty to give you the whole of my reasons, but you may, I -assure you, take it from me that they are good ones, sound and -unselfish, and spring from the highest sense of duty. - -"Could you look, sir, into my heart, you would approve to the full the -sentiments which animate me. Nay, more, you would count me amongst -the best and truest of your friends." - -Again he looked at us all keenly. I had a growing conviction that -this sudden change of his entire intellectual method was but yet -another phase of his madness, and so determined to let him go on a -little longer, knowing from experience that he would, like all -lunatics, give himself away in the end. Van Helsing was gazing at him -with a look of utmost intensity, his bushy eyebrows almost meeting -with the fixed concentration of his look. He said to Renfield in a -tone which did not surprise me at the time, but only when I thought of -it afterwards, for it was as of one addressing an equal, "Can you not -tell frankly your real reason for wishing to be free tonight? I will -undertake that if you will satisfy even me, a stranger, without -prejudice, and with the habit of keeping an open mind, Dr. Seward will -give you, at his own risk and on his own responsibility, the privilege -you seek." - -He shook his head sadly, and with a look of poignant regret on his -face. The Professor went on, "Come, sir, bethink yourself. You claim -the privilege of reason in the highest degree, since you seek to -impress us with your complete reasonableness. You do this, whose -sanity we have reason to doubt, since you are not yet released from -medical treatment for this very defect. If you will not help us in -our effort to choose the wisest course, how can we perform the duty -which you yourself put upon us? Be wise, and help us, and if we can -we shall aid you to achieve your wish." - -He still shook his head as he said, "Dr. Van Helsing, I have nothing to -say. Your argument is complete, and if I were free to speak I should -not hesitate a moment, but I am not my own master in the matter. I -can only ask you to trust me. If I am refused, the responsibility -does not rest with me." - -I thought it was now time to end the scene, which was becoming too -comically grave, so I went towards the door, simply saying, "Come, my -friends, we have work to do. Goodnight." - -As, however, I got near the door, a new change came over the patient. -He moved towards me so quickly that for the moment I feared that he -was about to make another homicidal attack. My fears, however, were -groundless, for he held up his two hands imploringly, and made his -petition in a moving manner. As he saw that the very excess of his -emotion was militating against him, by restoring us more to our old -relations, he became still more demonstrative. I glanced at Van -Helsing, and saw my conviction reflected in his eyes, so I became a -little more fixed in my manner, if not more stern, and motioned to him -that his efforts were unavailing. I had previously seen something of -the same constantly growing excitement in him when he had to make some -request of which at the time he had thought much, such for instance, -as when he wanted a cat, and I was prepared to see the collapse into -the same sullen acquiescence on this occasion. - -My expectation was not realized, for when he found that his appeal -would not be successful, he got into quite a frantic condition. He -threw himself on his knees, and held up his hands, wringing them in -plaintive supplication, and poured forth a torrent of entreaty, with -the tears rolling down his cheeks, and his whole face and form -expressive of the deepest emotion. - -"Let me entreat you, Dr. Seward, oh, let me implore you, to let me out -of this house at once. Send me away how you will and where you will, -send keepers with me with whips and chains, let them take me in a -strait waistcoat, manacled and leg-ironed, even to gaol, but let me go -out of this. You don't know what you do by keeping me here. I am -speaking from the depths of my heart, of my very soul. You don't know -whom you wrong, or how, and I may not tell. Woe is me! I may not -tell. By all you hold sacred, by all you hold dear, by your love that -is lost, by your hope that lives, for the sake of the Almighty, take -me out of this and save my soul from guilt! Can't you hear me, man? -Can't you understand? Will you never learn? Don't you know that I am -sane and earnest now, that I am no lunatic in a mad fit, but a sane -man fighting for his soul? Oh, hear me! Hear me! Let me go, let me -go, let me go!" - -I thought that the longer this went on the wilder he would get, and so -would bring on a fit, so I took him by the hand and raised him up. - -"Come," I said sternly, "no more of this, we have had quite enough -already. Get to your bed and try to behave more discreetly." - -He suddenly stopped and looked at me intently for several moments. -Then, without a word, he rose and moving over, sat down on the side of -the bed. The collapse had come, as on former occasions, just as I had -expected. - -When I was leaving the room, last of our party, he said to me in a -quiet, well-bred voice, "You will, I trust, Dr. Seward, do me the -justice to bear in mind, later on, that I did what I could to convince -you tonight." - - - - -CHAPTER 19 - - -JONATHAN HARKER'S JOURNAL - -1 October, 5 A.M.--I went with the party to the search with an easy -mind, for I think I never saw Mina so absolutely strong and well. I -am so glad that she consented to hold back and let us men do the work. -Somehow, it was a dread to me that she was in this fearful business at -all, but now that her work is done, and that it is due to her energy -and brains and foresight that the whole story is put together in such -a way that every point tells, she may well feel that her part is -finished, and that she can henceforth leave the rest to us. We were, -I think, all a little upset by the scene with Mr. Renfield. When we -came away from his room we were silent till we got back to the study. - -Then Mr. Morris said to Dr. Seward, "Say, Jack, if that man wasn't -attempting a bluff, he is about the sanest lunatic I ever saw. I'm -not sure, but I believe that he had some serious purpose, and if he -had, it was pretty rough on him not to get a chance." - -Lord Godalming and I were silent, but Dr. Van Helsing added, "Friend -John, you know more lunatics than I do, and I'm glad of it, for I fear -that if it had been to me to decide I would before that last -hysterical outburst have given him free. But we live and learn, and -in our present task we must take no chance, as my friend Quincey would -say. All is best as they are." - -Dr. Seward seemed to answer them both in a dreamy kind of way, "I -don't know but that I agree with you. If that man had been an -ordinary lunatic I would have taken my chance of trusting him, but he -seems so mixed up with the Count in an indexy kind of way that I am -afraid of doing anything wrong by helping his fads. I can't forget -how he prayed with almost equal fervor for a cat, and then tried to -tear my throat out with his teeth. Besides, he called the Count 'lord -and master', and he may want to get out to help him in some diabolical -way. That horrid thing has the wolves and the rats and his own kind -to help him, so I suppose he isn't above trying to use a respectable -lunatic. He certainly did seem earnest, though. I only hope we have -done what is best. These things, in conjunction with the wild work we -have in hand, help to unnerve a man." - -The Professor stepped over, and laying his hand on his shoulder, said -in his grave, kindly way, "Friend John, have no fear. We are trying -to do our duty in a very sad and terrible case, we can only do as we -deem best. What else have we to hope for, except the pity of the good -God?" - -Lord Godalming had slipped away for a few minutes, but now he -returned. He held up a little silver whistle as he remarked, "That -old place may be full of rats, and if so, I've got an antidote on -call." - -Having passed the wall, we took our way to the house, taking care to -keep in the shadows of the trees on the lawn when the moonlight shone -out. When we got to the porch the Professor opened his bag and took -out a lot of things, which he laid on the step, sorting them into four -little groups, evidently one for each. Then he spoke. - -"My friends, we are going into a terrible danger, and we need arms of -many kinds. Our enemy is not merely spiritual. Remember that he has -the strength of twenty men, and that, though our necks or our -windpipes are of the common kind, and therefore breakable or -crushable, his are not amenable to mere strength. A stronger man, or -a body of men more strong in all than him, can at certain times hold -him, but they cannot hurt him as we can be hurt by him. We must, -therefore, guard ourselves from his touch. Keep this near your -heart." As he spoke he lifted a little silver crucifix and held it -out to me, I being nearest to him, "put these flowers round your -neck," here he handed to me a wreath of withered garlic blossoms, "for -other enemies more mundane, this revolver and this knife, and for aid -in all, these so small electric lamps, which you can fasten to your -breast, and for all, and above all at the last, this, which we must -not desecrate needless." - -This was a portion of Sacred Wafer, which he put in an envelope and -handed to me. Each of the others was similarly equipped. - -"Now," he said, "friend John, where are the skeleton keys? If so that -we can open the door, we need not break house by the window, as before -at Miss Lucy's." - -Dr. Seward tried one or two skeleton keys, his mechanical dexterity as -a surgeon standing him in good stead. Presently he got one to suit, -after a little play back and forward the bolt yielded, and with a -rusty clang, shot back. We pressed on the door, the rusty hinges -creaked, and it slowly opened. It was startlingly like the image -conveyed to me in Dr. Seward's diary of the opening of Miss Westenra's -tomb, I fancy that the same idea seemed to strike the others, for with -one accord they shrank back. The Professor was the first to move -forward, and stepped into the open door. - -"In manus tuas, Domine!" he said, crossing himself as he passed over -the threshold. We closed the door behind us, lest when we should have -lit our lamps we should possibly attract attention from the road. The -Professor carefully tried the lock, lest we might not be able to open -it from within should we be in a hurry making our exit. Then we all -lit our lamps and proceeded on our search. - -The light from the tiny lamps fell in all sorts of odd forms, as the -rays crossed each other, or the opacity of our bodies threw great -shadows. I could not for my life get away from the feeling that there -was someone else amongst us. I suppose it was the recollection, so -powerfully brought home to me by the grim surroundings, of that -terrible experience in Transylvania. I think the feeling was common -to us all, for I noticed that the others kept looking over their -shoulders at every sound and every new shadow, just as I felt myself -doing. - -The whole place was thick with dust. The floor was seemingly inches -deep, except where there were recent footsteps, in which on holding -down my lamp I could see marks of hobnails where the dust was cracked. -The walls were fluffy and heavy with dust, and in the corners were -masses of spider's webs, whereon the dust had gathered till they -looked like old tattered rags as the weight had torn them partly down. -On a table in the hall was a great bunch of keys, with a time-yellowed -label on each. They had been used several times, for on the table -were several similar rents in the blanket of dust, similar to that -exposed when the Professor lifted them. - -He turned to me and said, "You know this place, Jonathan. You have -copied maps of it, and you know it at least more than we do. Which is -the way to the chapel?" - -I had an idea of its direction, though on my former visit I had not -been able to get admission to it, so I led the way, and after a few -wrong turnings found myself opposite a low, arched oaken door, ribbed -with iron bands. - -"This is the spot," said the Professor as he turned his lamp on a -small map of the house, copied from the file of my original -correspondence regarding the purchase. With a little trouble we found -the key on the bunch and opened the door. We were prepared for some -unpleasantness, for as we were opening the door a faint, malodorous -air seemed to exhale through the gaps, but none of us ever expected -such an odour as we encountered. None of the others had met the Count -at all at close quarters, and when I had seen him he was either in the -fasting stage of his existence in his rooms or, when he was bloated -with fresh blood, in a ruined building open to the air, but here the -place was small and close, and the long disuse had made the air -stagnant and foul. There was an earthy smell, as of some dry miasma, -which came through the fouler air. But as to the odour itself, how -shall I describe it? It was not alone that it was composed of all the -ills of mortality and with the pungent, acrid smell of blood, but it -seemed as though corruption had become itself corrupt. Faugh! It -sickens me to think of it. Every breath exhaled by that monster -seemed to have clung to the place and intensified its loathsomeness. - -Under ordinary circumstances such a stench would have brought our -enterprise to an end, but this was no ordinary case, and the high and -terrible purpose in which we were involved gave us a strength which -rose above merely physical considerations. After the involuntary -shrinking consequent on the first nauseous whiff, we one and all set -about our work as though that loathsome place were a garden of roses. - -We made an accurate examination of the place, the Professor saying as -we began, "The first thing is to see how many of the boxes are left, -we must then examine every hole and corner and cranny and see if we -cannot get some clue as to what has become of the rest." - -A glance was sufficient to show how many remained, for the great earth -chests were bulky, and there was no mistaking them. - -There were only twenty-nine left out of the fifty! Once I got a -fright, for, seeing Lord Godalming suddenly turn and look out of the -vaulted door into the dark passage beyond, I looked too, and for an -instant my heart stood still. Somewhere, looking out from the shadow, -I seemed to see the high lights of the Count's evil face, the ridge of -the nose, the red eyes, the red lips, the awful pallor. It was only -for a moment, for, as Lord Godalming said, "I thought I saw a face, -but it was only the shadows," and resumed his inquiry, I turned my -lamp in the direction, and stepped into the passage. There was no -sign of anyone, and as there were no corners, no doors, no aperture of -any kind, but only the solid walls of the passage, there could be no -hiding place even for him. I took it that fear had helped -imagination, and said nothing. - -A few minutes later I saw Morris step suddenly back from a corner, -which he was examining. We all followed his movements with our eyes, -for undoubtedly some nervousness was growing on us, and we saw a whole -mass of phosphorescence, which twinkled like stars. We all -instinctively drew back. The whole place was becoming alive with -rats. - -For a moment or two we stood appalled, all save Lord Godalming, who -was seemingly prepared for such an emergency. Rushing over to the -great iron-bound oaken door, which Dr. Seward had described from the -outside, and which I had seen myself, he turned the key in the lock, -drew the huge bolts, and swung the door open. Then, taking his little -silver whistle from his pocket, he blew a low, shrill call. It was -answered from behind Dr. Seward's house by the yelping of dogs, and -after about a minute three terriers came dashing round the corner of -the house. Unconsciously we had all moved towards the door, and as we -moved I noticed that the dust had been much disturbed. The boxes -which had been taken out had been brought this way. But even in the -minute that had elapsed the number of the rats had vastly increased. -They seemed to swarm over the place all at once, till the lamplight, -shining on their moving dark bodies and glittering, baleful eyes, made -the place look like a bank of earth set with fireflies. The dogs -dashed on, but at the threshold suddenly stopped and snarled, and -then, simultaneously lifting their noses, began to howl in most -lugubrious fashion. The rats were multiplying in thousands, and we -moved out. - -Lord Godalming lifted one of the dogs, and carrying him in, placed him -on the floor. The instant his feet touched the ground he seemed to -recover his courage, and rushed at his natural enemies. They fled -before him so fast that before he had shaken the life out of a score, -the other dogs, who had by now been lifted in the same manner, had but -small prey ere the whole mass had vanished. - -With their going it seemed as if some evil presence had departed, for -the dogs frisked about and barked merrily as they made sudden darts at -their prostrate foes, and turned them over and over and tossed them in -the air with vicious shakes. We all seemed to find our spirits rise. -Whether it was the purifying of the deadly atmosphere by the opening -of the chapel door, or the relief which we experienced by finding -ourselves in the open I know not, but most certainly the shadow of -dread seemed to slip from us like a robe, and the occasion of our -coming lost something of its grim significance, though we did not -slacken a whit in our resolution. We closed the outer door and barred -and locked it, and bringing the dogs with us, began our search of the -house. We found nothing throughout except dust in extraordinary -proportions, and all untouched save for my own footsteps when I had -made my first visit. Never once did the dogs exhibit any symptom of -uneasiness, and even when we returned to the chapel they frisked about -as though they had been rabbit hunting in a summer wood. - -The morning was quickening in the east when we emerged from the front. -Dr. Van Helsing had taken the key of the hall door from the bunch, and -locked the door in orthodox fashion, putting the key into his pocket -when he had done. - -"So far," he said, "our night has been eminently successful. No harm -has come to us such as I feared might be and yet we have ascertained -how many boxes are missing. More than all do I rejoice that this, our -first, and perhaps our most difficult and dangerous, step has been -accomplished without the bringing thereinto our most sweet Madam Mina -or troubling her waking or sleeping thoughts with sights and sounds -and smells of horror which she might never forget. One lesson, too, -we have learned, if it be allowable to argue a particulari, that the -brute beasts which are to the Count's command are yet themselves not -amenable to his spiritual power, for look, these rats that would come -to his call, just as from his castle top he summon the wolves to your -going and to that poor mother's cry, though they come to him, they run -pell-mell from the so little dogs of my friend Arthur. We have other -matters before us, other dangers, other fears, and that monster . . . -He has not used his power over the brute world for the only or the -last time tonight. So be it that he has gone elsewhere. Good! It -has given us opportunity to cry 'check' in some ways in this chess -game, which we play for the stake of human souls. And now let us go -home. The dawn is close at hand, and we have reason to be content -with our first night's work. It may be ordained that we have many -nights and days to follow, if full of peril, but we must go on, and -from no danger shall we shrink." - -The house was silent when we got back, save for some poor creature who -was screaming away in one of the distant wards, and a low, moaning -sound from Renfield's room. The poor wretch was doubtless torturing -himself, after the manner of the insane, with needless thoughts of -pain. - -I came tiptoe into our own room, and found Mina asleep, breathing so -softly that I had to put my ear down to hear it. She looks paler than -usual. I hope the meeting tonight has not upset her. I am truly -thankful that she is to be left out of our future work, and even of -our deliberations. It is too great a strain for a woman to bear. I -did not think so at first, but I know better now. Therefore I am glad -that it is settled. There may be things which would frighten her to -hear, and yet to conceal them from her might be worse than to tell her -if once she suspected that there was any concealment. Henceforth our -work is to be a sealed book to her, till at least such time as we can -tell her that all is finished, and the earth free from a monster of -the nether world. I daresay it will be difficult to begin to keep -silence after such confidence as ours, but I must be resolute, and -tomorrow I shall keep dark over tonight's doings, and shall refuse to -speak of anything that has happened. I rest on the sofa, so as not to -disturb her. - - -1 October, later.--I suppose it was natural that we should have all -overslept ourselves, for the day was a busy one, and the night had no -rest at all. Even Mina must have felt its exhaustion, for though I -slept till the sun was high, I was awake before her, and had to call -two or three times before she awoke. Indeed, she was so sound asleep -that for a few seconds she did not recognize me, but looked at me with -a sort of blank terror, as one looks who has been waked out of a bad -dream. She complained a little of being tired, and I let her rest -till later in the day. We now know of twenty-one boxes having been -removed, and if it be that several were taken in any of these removals -we may be able to trace them all. Such will, of course, immensely -simplify our labor, and the sooner the matter is attended to the -better. I shall look up Thomas Snelling today. - - - -DR. SEWARD'S DIARY - -1 October.--It was towards noon when I was awakened by the Professor -walking into my room. He was more jolly and cheerful than usual, and -it is quite evident that last night's work has helped to take some of -the brooding weight off his mind. - -After going over the adventure of the night he suddenly said, "Your -patient interests me much. May it be that with you I visit him this -morning? Or if that you are too occupy, I can go alone if it may be. -It is a new experience to me to find a lunatic who talk philosophy, -and reason so sound." - -I had some work to do which pressed, so I told him that if he would go -alone I would be glad, as then I should not have to keep him waiting, -so I called an attendant and gave him the necessary instructions. -Before the Professor left the room I cautioned him against getting any -false impression from my patient. - -"But," he answered, "I want him to talk of himself and of his delusion -as to consuming live things. He said to Madam Mina, as I see in your -diary of yesterday, that he had once had such a belief. Why do you -smile, friend John?" - -"Excuse me," I said, "but the answer is here." I laid my hand on the -typewritten matter. "When our sane and learned lunatic made that very -statement of how he used to consume life, his mouth was actually -nauseous with the flies and spiders which he had eaten just before -Mrs. Harker entered the room." - -Van Helsing smiled in turn. "Good!" he said. "Your memory is true, -friend John. I should have remembered. And yet it is this very -obliquity of thought and memory which makes mental disease such a -fascinating study. Perhaps I may gain more knowledge out of the folly -of this madman than I shall from the teaching of the most wise. Who -knows?" - -I went on with my work, and before long was through that in hand. It -seemed that the time had been very short indeed, but there was Van -Helsing back in the study. - -"Do I interrupt?" he asked politely as he stood at the door. - -"Not at all," I answered. "Come in. My work is finished, and I am -free. I can go with you now, if you like." - -"It is needless, I have seen him!" - -"Well?" - -"I fear that he does not appraise me at much. Our interview was -short. When I entered his room he was sitting on a stool in the -centre, with his elbows on his knees, and his face was the picture of -sullen discontent. I spoke to him as cheerfully as I could, and with -such a measure of respect as I could assume. He made no reply -whatever. 'Don't you know me?' I asked. His answer was not -reassuring: 'I know you well enough; you are the old fool Van -Helsing. I wish you would take yourself and your idiotic brain -theories somewhere else. Damn all thick-headed Dutchmen!' Not a word -more would he say, but sat in his implacable sullenness as indifferent -to me as though I had not been in the room at all. Thus departed for -this time my chance of much learning from this so clever lunatic, so I -shall go, if I may, and cheer myself with a few happy words with that -sweet soul Madam Mina. Friend John, it does rejoice me unspeakable -that she is no more to be pained, no more to be worried with our -terrible things. Though we shall much miss her help, it is better -so." - -"I agree with you with all my heart," I answered earnestly, for I did -not want him to weaken in this matter. "Mrs. Harker is better out of -it. Things are quite bad enough for us, all men of the world, and who -have been in many tight places in our time, but it is no place for a -woman, and if she had remained in touch with the affair, it would in -time infallibly have wrecked her." - -So Van Helsing has gone to confer with Mrs. Harker and Harker, Quincey -and Art are all out following up the clues as to the earth boxes. I -shall finish my round of work and we shall meet tonight. - - - - - -MINA HARKER'S JOURNAL - -1 October.--It is strange to me to be kept in the dark as I am today, -after Jonathan's full confidence for so many years, to see him -manifestly avoid certain matters, and those the most vital of all. -This morning I slept late after the fatigues of yesterday, and though -Jonathan was late too, he was the earlier. He spoke to me before he -went out, never more sweetly or tenderly, but he never mentioned a -word of what had happened in the visit to the Count's house. And yet -he must have known how terribly anxious I was. Poor dear fellow! I -suppose it must have distressed him even more than it did me. They -all agreed that it was best that I should not be drawn further into -this awful work, and I acquiesced. But to think that he keeps -anything from me! And now I am crying like a silly fool, when I know -it comes from my husband's great love and from the good, good wishes -of those other strong men. - -That has done me good. Well, some day Jonathan will tell me all. And -lest it should ever be that he should think for a moment that I kept -anything from him, I still keep my journal as usual. Then if he has -feared of my trust I shall show it to him, with every thought of my -heart put down for his dear eyes to read. I feel strangely sad and -low-spirited today. I suppose it is the reaction from the terrible -excitement. - -Last night I went to bed when the men had gone, simply because they -told me to. I didn't feel sleepy, and I did feel full of devouring -anxiety. I kept thinking over everything that has been ever since -Jonathan came to see me in London, and it all seems like a horrible -tragedy, with fate pressing on relentlessly to some destined end. -Everything that one does seems, no matter how right it may be, to bring -on the very thing which is most to be deplored. If I hadn't gone to -Whitby, perhaps poor dear Lucy would be with us now. She hadn't taken -to visiting the churchyard till I came, and if she hadn't come there -in the day time with me she wouldn't have walked in her sleep. And if -she hadn't gone there at night and asleep, that monster couldn't have -destroyed her as he did. Oh, why did I ever go to Whitby? There now, -crying again! I wonder what has come over me today. I must hide it -from Jonathan, for if he knew that I had been crying twice in one -morning . . . I, who never cried on my own account, and whom he has -never caused to shed a tear, the dear fellow would fret his heart out. -I shall put a bold face on, and if I do feel weepy, he shall never see -it. I suppose it is just one of the lessons that we poor women have -to learn . . . - -I can't quite remember how I fell asleep last night. I remember -hearing the sudden barking of the dogs and a lot of queer sounds, like -praying on a very tumultuous scale, from Mr. Renfield's room, which is -somewhere under this. And then there was silence over everything, -silence so profound that it startled me, and I got up and looked out -of the window. All was dark and silent, the black shadows thrown by -the moonlight seeming full of a silent mystery of their own. Not a -thing seemed to be stirring, but all to be grim and fixed as death or -fate, so that a thin streak of white mist, that crept with almost -imperceptible slowness across the grass towards the house, seemed to -have a sentience and a vitality of its own. I think that the -digression of my thoughts must have done me good, for when I got back -to bed I found a lethargy creeping over me. I lay a while, but could -not quite sleep, so I got out and looked out of the window again. The -mist was spreading, and was now close up to the house, so that I could -see it lying thick against the wall, as though it were stealing up to -the windows. The poor man was more loud than ever, and though I could -not distinguish a word he said, I could in some way recognize in his -tones some passionate entreaty on his part. Then there was the sound -of a struggle, and I knew that the attendants were dealing with him. -I was so frightened that I crept into bed, and pulled the clothes over -my head, putting my fingers in my ears. I was not then a bit sleepy, -at least so I thought, but I must have fallen asleep, for except -dreams, I do not remember anything until the morning, when Jonathan -woke me. I think that it took me an effort and a little time to -realize where I was, and that it was Jonathan who was bending over me. -My dream was very peculiar, and was almost typical of the way that -waking thoughts become merged in, or continued in, dreams. - -I thought that I was asleep, and waiting for Jonathan to come back. I -was very anxious about him, and I was powerless to act, my feet, and -my hands, and my brain were weighted, so that nothing could proceed at -the usual pace. And so I slept uneasily and thought. Then it began -to dawn upon me that the air was heavy, and dank, and cold. I put -back the clothes from my face, and found, to my surprise, that all was -dim around. The gaslight which I had left lit for Jonathan, but -turned down, came only like a tiny red spark through the fog, which -had evidently grown thicker and poured into the room. Then it -occurred to me that I had shut the window before I had come to bed. I -would have got out to make certain on the point, but some leaden -lethargy seemed to chain my limbs and even my will. I lay still and -endured, that was all. I closed my eyes, but could still see through -my eyelids. (It is wonderful what tricks our dreams play us, and how -conveniently we can imagine.) The mist grew thicker and thicker and I -could see now how it came in, for I could see it like smoke, or with -the white energy of boiling water, pouring in, not through the window, -but through the joinings of the door. It got thicker and thicker, -till it seemed as if it became concentrated into a sort of pillar of -cloud in the room, through the top of which I could see the light of -the gas shining like a red eye. Things began to whirl through my -brain just as the cloudy column was now whirling in the room, and -through it all came the scriptural words "a pillar of cloud by day and -of fire by night." Was it indeed such spiritual guidance that was -coming to me in my sleep? But the pillar was composed of both the day -and the night guiding, for the fire was in the red eye, which at the -thought got a new fascination for me, till, as I looked, the fire -divided, and seemed to shine on me through the fog like two red eyes, -such as Lucy told me of in her momentary mental wandering when, on the -cliff, the dying sunlight struck the windows of St. Mary's Church. -Suddenly the horror burst upon me that it was thus that Jonathan had -seen those awful women growing into reality through the whirling mist -in the moonlight, and in my dream I must have fainted, for all became -black darkness. The last conscious effort which imagination made was -to show me a livid white face bending over me out of the mist. - -I must be careful of such dreams, for they would unseat one's reason if -there were too much of them. I would get Dr. Van Helsing or Dr. -Seward to prescribe something for me which would make me sleep, only -that I fear to alarm them. Such a dream at the present time would -become woven into their fears for me. Tonight I shall strive hard to -sleep naturally. If I do not, I shall tomorrow night get them to give -me a dose of chloral, that cannot hurt me for once, and it will give -me a good night's sleep. Last night tired me more than if I had not -slept at all. - - -2 October 10 P.M.--Last night I slept, but did not dream. I must have -slept soundly, for I was not waked by Jonathan coming to bed, but the -sleep has not refreshed me, for today I feel terribly weak and -spiritless. I spent all yesterday trying to read, or lying down -dozing. In the afternoon, Mr. Renfield asked if he might see me. Poor -man, he was very gentle, and when I came away he kissed my hand and -bade God bless me. Some way it affected me much. I am crying when I -think of him. This is a new weakness, of which I must be careful. -Jonathan would be miserable if he knew I had been crying. He and the -others were out till dinner time, and they all came in tired. I did -what I could to brighten them up, and I suppose that the effort did me -good, for I forgot how tired I was. After dinner they sent me to bed, -and all went off to smoke together, as they said, but I knew that they -wanted to tell each other of what had occurred to each during the day. -I could see from Jonathan's manner that he had something important to -communicate. I was not so sleepy as I should have been, so before -they went I asked Dr. Seward to give me a little opiate of some kind, -as I had not slept well the night before. He very kindly made me up a -sleeping draught, which he gave to me, telling me that it would do me -no harm, as it was very mild . . . I have taken it, and am waiting for -sleep, which still keeps aloof. I hope I have not done wrong, for as -sleep begins to flirt with me, a new fear comes: that I may have been -foolish in thus depriving myself of the power of waking. I might want -it. Here comes sleep. Goodnight. - - - - -CHAPTER 20 - - -JONATHAN HARKER'S JOURNAL - -1 October, evening.--I found Thomas Snelling in his house at Bethnal -Green, but unhappily he was not in a condition to remember anything. -The very prospect of beer which my expected coming had opened to him -had proved too much, and he had begun too early on his expected -debauch. I learned, however, from his wife, who seemed a decent, poor -soul, that he was only the assistant of Smollet, who of the two mates -was the responsible person. So off I drove to Walworth, and found Mr. -Joseph Smollet at home and in his shirtsleeves, taking a late tea out -of a saucer. He is a decent, intelligent fellow, distinctly a good, -reliable type of workman, and with a headpiece of his own. He -remembered all about the incident of the boxes, and from a wonderful -dog-eared notebook, which he produced from some mysterious receptacle -about the seat of his trousers, and which had hieroglyphical entries -in thick, half-obliterated pencil, he gave me the destinations of the -boxes. There were, he said, six in the cartload which he took from -Carfax and left at 197 Chicksand Street, Mile End New Town, and -another six which he deposited at Jamaica Lane, Bermondsey. If then -the Count meant to scatter these ghastly refuges of his over London, -these places were chosen as the first of delivery, so that later he -might distribute more fully. The systematic manner in which this was -done made me think that he could not mean to confine himself to two -sides of London. He was now fixed on the far east on the northern -shore, on the east of the southern shore, and on the south. The north -and west were surely never meant to be left out of his diabolical -scheme, let alone the City itself and the very heart of fashionable -London in the south-west and west. I went back to Smollet, and asked -him if he could tell us if any other boxes had been taken from Carfax. - -He replied, "Well guv'nor, you've treated me very 'an'some", I had -given him half a sovereign, "an I'll tell yer all I know. I heard a -man by the name of Bloxam say four nights ago in the 'Are an' 'Ounds, -in Pincher's Alley, as 'ow he an' his mate 'ad 'ad a rare dusty job in -a old 'ouse at Purfleet. There ain't a many such jobs as this 'ere, -an' I'm thinkin' that maybe Sam Bloxam could tell ye summut." - -I asked if he could tell me where to find him. I told him that if he -could get me the address it would be worth another half sovereign to -him. So he gulped down the rest of his tea and stood up, saying that -he was going to begin the search then and there. - -At the door he stopped, and said, "Look 'ere, guv'nor, there ain't no -sense in me a keepin' you 'ere. I may find Sam soon, or I mayn't, but -anyhow he ain't like to be in a way to tell ye much tonight. Sam is a -rare one when he starts on the booze. If you can give me a envelope -with a stamp on it, and put yer address on it, I'll find out where Sam -is to be found and post it ye tonight. But ye'd better be up arter -'im soon in the mornin', never mind the booze the night afore." - -This was all practical, so one of the children went off with a penny -to buy an envelope and a sheet of paper, and to keep the change. When -she came back, I addressed the envelope and stamped it, and when -Smollet had again faithfully promised to post the address when found, -I took my way to home. We're on the track anyhow. I am tired -tonight, and I want to sleep. Mina is fast asleep, and looks a little -too pale. Her eyes look as though she had been crying. Poor dear, -I've no doubt it frets her to be kept in the dark, and it may make her -doubly anxious about me and the others. But it is best as it is. It -is better to be disappointed and worried in such a way now than to -have her nerve broken. The doctors were quite right to insist on her -being kept out of this dreadful business. I must be firm, for on me -this particular burden of silence must rest. I shall not ever enter -on the subject with her under any circumstances. Indeed, It may not -be a hard task, after all, for she herself has become reticent on the -subject, and has not spoken of the Count or his doings ever since we -told her of our decision. - - -2 October, evening--A long and trying and exciting day. By the first -post I got my directed envelope with a dirty scrap of paper enclosed, -on which was written with a carpenter's pencil in a sprawling hand, -"Sam Bloxam, Korkrans, 4 Poters Cort, Bartel Street, Walworth. Arsk -for the depite." - -I got the letter in bed, and rose without waking Mina. She looked -heavy and sleepy and pale, and far from well. I determined not to -wake her, but that when I should return from this new search, I would -arrange for her going back to Exeter. I think she would be happier in -our own home, with her daily tasks to interest her, than in being here -amongst us and in ignorance. I only saw Dr. Seward for a moment, and -told him where I was off to, promising to come back and tell the rest -so soon as I should have found out anything. I drove to Walworth and -found, with some difficulty, Potter's Court. Mr. Smollet's spelling -misled me, as I asked for Poter's Court instead of Potter's Court. -However, when I had found the court, I had no difficulty in -discovering Corcoran's lodging house. - -When I asked the man who came to the door for the "depite," he shook -his head, and said, "I dunno 'im. There ain't no such a person 'ere. -I never 'eard of 'im in all my bloomin' days. Don't believe there -ain't nobody of that kind livin' 'ere or anywheres." - -I took out Smollet's letter, and as I read it it seemed to me that the -lesson of the spelling of the name of the court might guide me. "What -are you?" I asked. - -"I'm the depity," he answered. - -I saw at once that I was on the right track. Phonetic spelling had -again misled me. A half crown tip put the deputy's knowledge at my -disposal, and I learned that Mr. Bloxam, who had slept off the remains -of his beer on the previous night at Corcoran's, had left for his work -at Poplar at five o'clock that morning. He could not tell me where -the place of work was situated, but he had a vague idea that it was -some kind of a "new-fangled ware'us," and with this slender clue I had -to start for Poplar. It was twelve o'clock before I got any -satisfactory hint of such a building, and this I got at a coffee shop, -where some workmen were having their dinner. One of them suggested -that there was being erected at Cross Angel Street a new "cold -storage" building, and as this suited the condition of a "new-fangled -ware'us," I at once drove to it. An interview with a surly gatekeeper -and a surlier foreman, both of whom were appeased with the coin of the -realm, put me on the track of Bloxam. He was sent for on my -suggestion that I was willing to pay his days wages to his foreman for -the privilege of asking him a few questions on a private matter. He -was a smart enough fellow, though rough of speech and bearing. When I -had promised to pay for his information and given him an earnest, he -told me that he had made two journeys between Carfax and a house in -Piccadilly, and had taken from this house to the latter nine great -boxes, "main heavy ones," with a horse and cart hired by him for this -purpose. - -I asked him if he could tell me the number of the house in Piccadilly, -to which he replied, "Well, guv'nor, I forgits the number, but it was -only a few door from a big white church, or somethink of the kind, not -long built. It was a dusty old 'ouse, too, though nothin' to the -dustiness of the 'ouse we tooked the bloomin' boxes from." - -"How did you get in if both houses were empty?" - -"There was the old party what engaged me a waitin' in the 'ouse at -Purfleet. He 'elped me to lift the boxes and put them in the dray. -Curse me, but he was the strongest chap I ever struck, an' him a old -feller, with a white moustache, one that thin you would think he -couldn't throw a shadder." - -How this phrase thrilled through me! - -"Why, 'e took up 'is end o' the boxes like they was pounds of tea, and -me a puffin' an' a blowin' afore I could upend mine anyhow, an' I'm no -chicken, neither." - -"How did you get into the house in Piccadilly?" I asked. - -"He was there too. He must 'a started off and got there afore me, for -when I rung of the bell he kem an' opened the door 'isself an' 'elped -me carry the boxes into the 'all." - -"The whole nine?" I asked. - -"Yus, there was five in the first load an' four in the second. It was -main dry work, an' I don't so well remember 'ow I got 'ome." - -I interrupted him, "Were the boxes left in the hall?" - -"Yus, it was a big 'all, an' there was nothin' else in it." - -I made one more attempt to further matters. "You didn't have any -key?" - -"Never used no key nor nothink. The old gent, he opened the door -'isself an' shut it again when I druv off. I don't remember the last -time, but that was the beer." - -"And you can't remember the number of the house?" - -"No, sir. But ye needn't have no difficulty about that. It's a 'igh -'un with a stone front with a bow on it, an' 'igh steps up to the -door. I know them steps, 'avin' 'ad to carry the boxes up with three -loafers what come round to earn a copper. The old gent give them -shillin's, an' they seein' they got so much, they wanted more. But 'e -took one of them by the shoulder and was like to throw 'im down the -steps, till the lot of them went away cussin'." - -I thought that with this description I could find the house, so having -paid my friend for his information, I started off for Piccadilly. I -had gained a new painful experience. The Count could, it was evident, -handle the earth boxes himself. If so, time was precious, for now -that he had achieved a certain amount of distribution, he could, by -choosing his own time, complete the task unobserved. At Piccadilly -Circus I discharged my cab, and walked westward. Beyond the Junior -Constitutional I came across the house described and was satisfied -that this was the next of the lairs arranged by Dracula. The house -looked as though it had been long untenanted. The windows were -encrusted with dust, and the shutters were up. All the framework was -black with time, and from the iron the paint had mostly scaled away. -It was evident that up to lately there had been a large notice board -in front of the balcony. It had, however, been roughly torn away, the -uprights which had supported it still remaining. Behind the rails of -the balcony I saw there were some loose boards, whose raw edges looked -white. I would have given a good deal to have been able to see the -notice board intact, as it would, perhaps, have given some clue to the -ownership of the house. I remembered my experience of the investigation -and purchase of Carfax, and I could not but feel that if I could find -the former owner there might be some means discovered of gaining access -to the house. - -There was at present nothing to be learned from the Piccadilly side, -and nothing could be done, so I went around to the back to see if -anything could be gathered from this quarter. The mews were active, -the Piccadilly houses being mostly in occupation. I asked one or two -of the grooms and helpers whom I saw around if they could tell me -anything about the empty house. One of them said that he heard it had -lately been taken, but he couldn't say from whom. He told me, -however, that up to very lately there had been a notice board of "For -Sale" up, and that perhaps Mitchell, Sons, & Candy the house agents -could tell me something, as he thought he remembered seeing the name -of that firm on the board. I did not wish to seem too eager, or to -let my informant know or guess too much, so thanking him in the usual -manner, I strolled away. It was now growing dusk, and the autumn -night was closing in, so I did not lose any time. Having learned the -address of Mitchell, Sons, & Candy from a directory at the Berkeley, I -was soon at their office in Sackville Street. - -The gentleman who saw me was particularly suave in manner, but -uncommunicative in equal proportion. Having once told me that the -Piccadilly house, which throughout our interview he called a -"mansion," was sold, he considered my business as concluded. When I -asked who had purchased it, he opened his eyes a thought wider, and -paused a few seconds before replying, "It is sold, sir." - -"Pardon me," I said, with equal politeness, "but I have a special -reason for wishing to know who purchased it." - -Again he paused longer, and raised his eyebrows still more. "It is -sold, sir," was again his laconic reply. - -"Surely," I said, "you do not mind letting me know so much." - -"But I do mind," he answered. "The affairs of their clients are -absolutely safe in the hands of Mitchell, Sons, & Candy." - -This was manifestly a prig of the first water, and there was no use -arguing with him. I thought I had best meet him on his own ground, so -I said, "Your clients, sir, are happy in having so resolute a guardian -of their confidence. I am myself a professional man." - -Here I handed him my card. "In this instance I am not prompted by -curiosity, I act on the part of Lord Godalming, who wishes to know -something of the property which was, he understood, lately for sale." - -These words put a different complexion on affairs. He said, "I would -like to oblige you if I could, Mr. Harker, and especially would I like -to oblige his lordship. We once carried out a small matter of renting -some chambers for him when he was the honourable Arthur Holmwood. If -you will let me have his lordship's address I will consult the House -on the subject, and will, in any case, communicate with his lordship -by tonight's post. It will be a pleasure if we can so far deviate -from our rules as to give the required information to his lordship." - -I wanted to secure a friend, and not to make an enemy, so I thanked -him, gave the address at Dr. Seward's and came away. It was now dark, -and I was tired and hungry. I got a cup of tea at the Aerated Bread -Company and came down to Purfleet by the next train. - -I found all the others at home. Mina was looking tired and pale, but -she made a gallant effort to be bright and cheerful. It wrung my -heart to think that I had had to keep anything from her and so caused -her inquietude. Thank God, this will be the last night of her looking -on at our conferences, and feeling the sting of our not showing our -confidence. It took all my courage to hold to the wise resolution of -keeping her out of our grim task. She seems somehow more reconciled, -or else the very subject seems to have become repugnant to her, for -when any accidental allusion is made she actually shudders. I am glad -we made our resolution in time, as with such a feeling as this, our -growing knowledge would be torture to her. - -I could not tell the others of the day's discovery till we were alone, -so after dinner, followed by a little music to save appearances even -amongst ourselves, I took Mina to her room and left her to go to bed. -The dear girl was more affectionate with me than ever, and clung to me -as though she would detain me, but there was much to be talked of and -I came away. Thank God, the ceasing of telling things has made no -difference between us. - -When I came down again I found the others all gathered round the fire -in the study. In the train I had written my diary so far, and simply -read it off to them as the best means of letting them get abreast of -my own information. - -When I had finished Van Helsing said, "This has been a great day's -work, friend Jonathan. Doubtless we are on the track of the missing -boxes. If we find them all in that house, then our work is near the -end. But if there be some missing, we must search until we find them. -Then shall we make our final coup, and hunt the wretch to his real -death." - -We all sat silent awhile and all at once Mr. Morris spoke, "Say! How -are we going to get into that house?" - -"We got into the other," answered Lord Godalming quickly. - -"But, Art, this is different. We broke house at Carfax, but we had -night and a walled park to protect us. It will be a mighty different -thing to commit burglary in Piccadilly, either by day or night. I -confess I don't see how we are going to get in unless that agency duck -can find us a key of some sort." - -Lord Godalming's brows contracted, and he stood up and walked about the -room. By-and-by he stopped and said, turning from one to another of -us, "Quincey's head is level. This burglary business is getting -serious. We got off once all right, but we have now a rare job on -hand. Unless we can find the Count's key basket." - -As nothing could well be done before morning, and as it would be at -least advisable to wait till Lord Godalming should hear from -Mitchell's, we decided not to take any active step before breakfast -time. For a good while we sat and smoked, discussing the matter in -its various lights and bearings. I took the opportunity of bringing -this diary right up to the moment. I am very sleepy and shall go to -bed . . . - -Just a line. Mina sleeps soundly and her breathing is regular. Her -forehead is puckered up into little wrinkles, as though she thinks -even in her sleep. She is still too pale, but does not look so -haggard as she did this morning. Tomorrow will, I hope, mend all -this. She will be herself at home in Exeter. Oh, but I am sleepy! - - - - -DR. SEWARD'S DIARY - -1 October.--I am puzzled afresh about Renfield. His moods change so -rapidly that I find it difficult to keep touch of them, and as they -always mean something more than his own well-being, they form a more -than interesting study. This morning, when I went to see him after -his repulse of Van Helsing, his manner was that of a man commanding -destiny. He was, in fact, commanding destiny, subjectively. He did -not really care for any of the things of mere earth, he was in the -clouds and looked down on all the weaknesses and wants of us poor -mortals. - -I thought I would improve the occasion and learn something, so I asked -him, "What about the flies these times?" - -He smiled on me in quite a superior sort of way, such a smile as would -have become the face of Malvolio, as he answered me, "The fly, my dear -sir, has one striking feature. It's wings are typical of the aerial -powers of the psychic faculties. The ancients did well when they -typified the soul as a butterfly!" - -I thought I would push his analogy to its utmost logically, so I said -quickly, "Oh, it is a soul you are after now, is it?" - -His madness foiled his reason, and a puzzled look spread over his face -as, shaking his head with a decision which I had but seldom seen in -him. - -He said, "Oh, no, oh no! I want no souls. Life is all I want." Here -he brightened up. "I am pretty indifferent about it at present. Life -is all right. I have all I want. You must get a new patient, doctor, -if you wish to study zoophagy!" - -This puzzled me a little, so I drew him on. "Then you command life. -You are a god, I suppose?" - -He smiled with an ineffably benign superiority. "Oh no! Far be it -from me to arrogate to myself the attributes of the Deity. I am not -even concerned in His especially spiritual doings. If I may state my -intellectual position I am, so far as concerns things purely -terrestrial, somewhat in the position which Enoch occupied -spiritually!" - -This was a poser to me. I could not at the moment recall Enoch's -appositeness, so I had to ask a simple question, though I felt that by -so doing I was lowering myself in the eyes of the lunatic. "And why -with Enoch?" - -"Because he walked with God." - -I could not see the analogy, but did not like to admit it, so I harked -back to what he had denied. "So you don't care about life and you -don't want souls. Why not?" I put my question quickly and somewhat -sternly, on purpose to disconcert him. - -The effort succeeded, for an instant he unconsciously relapsed into -his old servile manner, bent low before me, and actually fawned upon -me as he replied. "I don't want any souls, indeed, indeed! I don't. -I couldn't use them if I had them. They would be no manner of use to -me. I couldn't eat them or . . ." - -He suddenly stopped and the old cunning look spread over his face, -like a wind sweep on the surface of the water. - -"And doctor, as to life, what is it after all? When you've got all -you require, and you know that you will never want, that is all. I -have friends, good friends, like you, Dr. Seward." This was said with -a leer of inexpressible cunning. "I know that I shall never lack the -means of life!" - -I think that through the cloudiness of his insanity he saw some -antagonism in me, for he at once fell back on the last refuge of such -as he, a dogged silence. After a short time I saw that for the -present it was useless to speak to him. He was sulky, and so I came -away. - -Later in the day he sent for me. Ordinarily I would not have come -without special reason, but just at present I am so interested in him -that I would gladly make an effort. Besides, I am glad to have -anything to help pass the time. Harker is out, following up clues, -and so are Lord Godalming and Quincey. Van Helsing sits in my study -poring over the record prepared by the Harkers. He seems to think -that by accurate knowledge of all details he will light up on some -clue. He does not wish to be disturbed in the work, without cause. I -would have taken him with me to see the patient, only I thought that -after his last repulse he might not care to go again. There was also -another reason. Renfield might not speak so freely before a third -person as when he and I were alone. - -I found him sitting in the middle of the floor on his stool, a pose -which is generally indicative of some mental energy on his part. When -I came in, he said at once, as though the question had been waiting on -his lips. "What about souls?" - -It was evident then that my surmise had been correct. Unconscious -cerebration was doing its work, even with the lunatic. I determined -to have the matter out. - -"What about them yourself?" I asked. - -He did not reply for a moment but looked all around him, and up and -down, as though he expected to find some inspiration for an answer. - -"I don't want any souls!" he said in a feeble, apologetic way. The -matter seemed preying on his mind, and so I determined to use it, to -"be cruel only to be kind." So I said, "You like life, and you want -life?" - -"Oh yes! But that is all right. You needn't worry about that!" - -"But," I asked, "how are we to get the life without getting the soul -also?" - -This seemed to puzzle him, so I followed it up, "A nice time you'll -have some time when you're flying out here, with the souls of -thousands of flies and spiders and birds and cats buzzing and -twittering and moaning all around you. You've got their lives, you -know, and you must put up with their souls!" - -Something seemed to affect his imagination, for he put his fingers to -his ears and shut his eyes, screwing them up tightly just as a small -boy does when his face is being soaped. There was something pathetic -in it that touched me. It also gave me a lesson, for it seemed that -before me was a child, only a child, though the features were worn, -and the stubble on the jaws was white. It was evident that he was -undergoing some process of mental disturbance, and knowing how his -past moods had interpreted things seemingly foreign to himself, I -thought I would enter into his mind as well as I could and go with him. - -The first step was to restore confidence, so I asked him, speaking -pretty loud so that he would hear me through his closed ears, "Would -you like some sugar to get your flies around again?" - -He seemed to wake up all at once, and shook his head. With a laugh he -replied, "Not much! Flies are poor things, after all!" After a pause -he added, "But I don't want their souls buzzing round me, all the -same." - -"Or spiders?" I went on. - -"Blow spiders! What's the use of spiders? There isn't anything in -them to eat or . . ." He stopped suddenly as though reminded of a -forbidden topic. - -"So, so!" I thought to myself, "this is the second time he has -suddenly stopped at the word 'drink'. What does it mean?" - -Renfield seemed himself aware of having made a lapse, for he hurried -on, as though to distract my attention from it, "I don't take any -stock at all in such matters. 'Rats and mice and such small deer,' as -Shakespeare has it, 'chicken feed of the larder' they might be called. -I'm past all that sort of nonsense. You might as well ask a man to -eat molecules with a pair of chopsticks, as to try to interest me -about the less carnivora, when I know of what is before me." - -"I see," I said. "You want big things that you can make your teeth -meet in? How would you like to breakfast on an elephant?" - -"What ridiculous nonsense you are talking?" He was getting too wide -awake, so I thought I would press him hard. - -"I wonder," I said reflectively, "what an elephant's soul is like!" - -The effect I desired was obtained, for he at once fell from his -high-horse and became a child again. - -"I don't want an elephant's soul, or any soul at all!" he said. For a -few moments he sat despondently. Suddenly he jumped to his feet, with -his eyes blazing and all the signs of intense cerebral excitement. -"To hell with you and your souls!" he shouted. "Why do you plague me -about souls? Haven't I got enough to worry, and pain, to distract me -already, without thinking of souls?" - -He looked so hostile that I thought he was in for another homicidal -fit, so I blew my whistle. - -The instant, however, that I did so he became calm, and said -apologetically, "Forgive me, Doctor. I forgot myself. You do not -need any help. I am so worried in my mind that I am apt to be -irritable. If you only knew the problem I have to face, and that I am -working out, you would pity, and tolerate, and pardon me. Pray do not -put me in a strait waistcoat. I want to think and I cannot think -freely when my body is confined. I am sure you will understand!" - -He had evidently self-control, so when the attendants came I told them -not to mind, and they withdrew. Renfield watched them go. When the -door was closed he said with considerable dignity and sweetness, "Dr. -Seward, you have been very considerate towards me. Believe me that I -am very, very grateful to you!" - -I thought it well to leave him in this mood, and so I came away. -There is certainly something to ponder over in this man's state. -Several points seem to make what the American interviewer calls "a -story," if one could only get them in proper order. Here they are: - - Will not mention "drinking." - - Fears the thought of being burdened with the "soul" of anything. - - Has no dread of wanting "life" in the future. - - Despises the meaner forms of life altogether, though he dreads - being haunted by their souls. - - Logically all these things point one way! He has assurance of - some kind that he will acquire some higher life. - - He dreads the consequence, the burden of a soul. Then it is a - human life he looks to! - - And the assurance . . .? - -Merciful God! The Count has been to him, and there is some new scheme -of terror afoot! - - -Later.--I went after my round to Van Helsing and told him my -suspicion. He grew very grave, and after thinking the matter over for -a while asked me to take him to Renfield. I did so. As we came to -the door we heard the lunatic within singing gaily, as he used to do -in the time which now seems so long ago. - -When we entered we saw with amazement that he had spread out his sugar -as of old. The flies, lethargic with the autumn, were beginning to -buzz into the room. We tried to make him talk of the subject of our -previous conversation, but he would not attend. He went on with his -singing, just as though we had not been present. He had got a scrap -of paper and was folding it into a notebook. We had to come away as -ignorant as we went in. - -His is a curious case indeed. We must watch him tonight. - - - - - -LETTER, MITCHELL, SONS & CANDY TO LORD GODALMING. - -"1 October. - -"My Lord, - -"We are at all times only too happy to meet your wishes. We beg, -with regard to the desire of your Lordship, expressed by Mr. -Harker on your behalf, to supply the following information -concerning the sale and purchase of No. 347, Piccadilly. The -original vendors are the executors of the late Mr. Archibald -Winter-Suffield. The purchaser is a foreign nobleman, Count de -Ville, who effected the purchase himself paying the purchase -money in notes 'over the counter,' if your Lordship will pardon -us using so vulgar an expression. Beyond this we know nothing -whatever of him. - -"We are, my Lord, - -"Your Lordship's humble servants, - -"MITCHELL, SONS & CANDY." - - - - -DR. SEWARD'S DIARY - -2 October.--I placed a man in the corridor last night, and told him to -make an accurate note of any sound he might hear from Renfield's room, -and gave him instructions that if there should be anything strange he -was to call me. After dinner, when we had all gathered round the fire -in the study, Mrs. Harker having gone to bed, we discussed the -attempts and discoveries of the day. Harker was the only one who had -any result, and we are in great hopes that his clue may be an -important one. - -Before going to bed I went round to the patient's room and looked in -through the observation trap. He was sleeping soundly, his heart rose -and fell with regular respiration. - -This morning the man on duty reported to me that a little after -midnight he was restless and kept saying his prayers somewhat loudly. -I asked him if that was all. He replied that it was all he heard. -There was something about his manner, so suspicious that I asked him -point blank if he had been asleep. He denied sleep, but admitted to -having "dozed" for a while. It is too bad that men cannot be trusted -unless they are watched. - -Today Harker is out following up his clue, and Art and Quincey are -looking after horses. Godalming thinks that it will be well to have -horses always in readiness, for when we get the information which we -seek there will be no time to lose. We must sterilize all the -imported earth between sunrise and sunset. We shall thus catch the -Count at his weakest, and without a refuge to fly to. Van Helsing is -off to the British Museum looking up some authorities on ancient -medicine. The old physicians took account of things which their -followers do not accept, and the Professor is searching for witch and -demon cures which may be useful to us later. - -I sometimes think we must be all mad and that we shall wake to sanity -in strait waistcoats. - -Later.--We have met again. We seem at last to be on the track, and -our work of tomorrow may be the beginning of the end. I wonder if -Renfield's quiet has anything to do with this. His moods have so -followed the doings of the Count, that the coming destruction of the -monster may be carried to him some subtle way. If we could only get -some hint as to what passed in his mind, between the time of my -argument with him today and his resumption of fly-catching, it might -afford us a valuable clue. He is now seemingly quiet for a spell . . . -Is he? That wild yell seemed to come from his room . . . - -The attendant came bursting into my room and told me that Renfield had -somehow met with some accident. He had heard him yell, and when he -went to him found him lying on his face on the floor, all covered with -blood. I must go at once . . . - - - - -CHAPTER 21 - - -DR. SEWARD'S DIARY - -3 October.--Let me put down with exactness all that happened, as well -as I can remember, since last I made an entry. Not a detail that I -can recall must be forgotten. In all calmness I must proceed. - -When I came to Renfield's room I found him lying on the floor on his -left side in a glittering pool of blood. When I went to move him, it -became at once apparent that he had received some terrible injuries. -There seemed none of the unity of purpose between the parts of the -body which marks even lethargic sanity. As the face was exposed I -could see that it was horribly bruised, as though it had been beaten -against the floor. Indeed it was from the face wounds that the pool -of blood originated. - -The attendant who was kneeling beside the body said to me as we turned -him over, "I think, sir, his back is broken. See, both his right arm -and leg and the whole side of his face are paralysed." How such a -thing could have happened puzzled the attendant beyond measure. He -seemed quite bewildered, and his brows were gathered in as he said, "I -can't understand the two things. He could mark his face like that by -beating his own head on the floor. I saw a young woman do it once at -the Eversfield Asylum before anyone could lay hands on her. And I -suppose he might have broken his neck by falling out of bed, if he got -in an awkward kink. But for the life of me I can't imagine how the -two things occurred. If his back was broke, he couldn't beat his -head, and if his face was like that before the fall out of bed, there -would be marks of it." - -I said to him, "Go to Dr. Van Helsing, and ask him to kindly come here -at once. I want him without an instant's delay." - -The man ran off, and within a few minutes the Professor, in his -dressing gown and slippers, appeared. When he saw Renfield on the -ground, he looked keenly at him a moment, and then turned to me. I -think he recognized my thought in my eyes, for he said very quietly, -manifestly for the ears of the attendant, "Ah, a sad accident! He -will need very careful watching, and much attention. I shall stay -with you myself, but I shall first dress myself. If you will remain I -shall in a few minutes join you." - -The patient was now breathing stertorously and it was easy to see that -he had suffered some terrible injury. - -Van Helsing returned with extraordinary celerity, bearing with him a -surgical case. He had evidently been thinking and had his mind made -up, for almost before he looked at the patient, he whispered to me, -"Send the attendant away. We must be alone with him when he becomes -conscious, after the operation." - -I said, "I think that will do now, Simmons. We have done all that we -can at present. You had better go your round, and Dr. Van Helsing -will operate. Let me know instantly if there be anything unusual -anywhere." - -The man withdrew, and we went into a strict examination of the -patient. The wounds of the face were superficial. The real injury -was a depressed fracture of the skull, extending right up through the -motor area. - -The Professor thought a moment and said, "We must reduce the pressure -and get back to normal conditions, as far as can be. The rapidity of -the suffusion shows the terrible nature of his injury. The whole -motor area seems affected. The suffusion of the brain will increase -quickly, so we must trephine at once or it may be too late." - -As he was speaking there was a soft tapping at the door. I went over -and opened it and found in the corridor without, Arthur and Quincey in -pajamas and slippers; the former spoke, "I heard your man call up Dr. -Van Helsing and tell him of an accident. So I woke Quincey or rather -called for him as he was not asleep. Things are moving too quickly -and too strangely for sound sleep for any of us these times. I've -been thinking that tomorrow night will not see things as they have -been. We'll have to look back, and forward a little more than we have -done. May we come in?" - -I nodded, and held the door open till they had entered, then I closed -it again. When Quincey saw the attitude and state of the patient, and -noted the horrible pool on the floor, he said softly, "My God! What -has happened to him? Poor, poor devil!" - -I told him briefly, and added that we expected he would recover -consciousness after the operation, for a short time, at all events. -He went at once and sat down on the edge of the bed, with Godalming -beside him. We all watched in patience. - -"We shall wait," said Van Helsing, "just long enough to fix the best -spot for trephining, so that we may most quickly and perfectly remove -the blood clot, for it is evident that the haemorrhage is increasing." - -The minutes during which we waited passed with fearful slowness. I -had a horrible sinking in my heart, and from Van Helsing's face I -gathered that he felt some fear or apprehension as to what was to -come. I dreaded the words Renfield might speak. I was positively -afraid to think. But the conviction of what was coming was on me, as -I have read of men who have heard the death watch. The poor man's -breathing came in uncertain gasps. Each instant he seemed as though -he would open his eyes and speak, but then would follow a prolonged -stertorous breath, and he would relapse into a more fixed -insensibility. Inured as I was to sick beds and death, this suspense -grew and grew upon me. I could almost hear the beating of my own -heart, and the blood surging through my temples sounded like blows -from a hammer. The silence finally became agonizing. I looked at my -companions, one after another, and saw from their flushed faces and -damp brows that they were enduring equal torture. There was a nervous -suspense over us all, as though overhead some dread bell would peal -out powerfully when we should least expect it. - -At last there came a time when it was evident that the patient was -sinking fast. He might die at any moment. I looked up at the -Professor and caught his eyes fixed on mine. His face was sternly set -as he spoke, "There is no time to lose. His words may be worth many -lives. I have been thinking so, as I stood here. It may be there is -a soul at stake! We shall operate just above the ear." - -Without another word he made the operation. For a few moments the -breathing continued to be stertorous. Then there came a breath so -prolonged that it seemed as though it would tear open his chest. -Suddenly his eyes opened, and became fixed in a wild, helpless stare. -This was continued for a few moments, then it was softened into a glad -surprise, and from his lips came a sigh of relief. He moved -convulsively, and as he did so, said, "I'll be quiet, Doctor. Tell -them to take off the strait waistcoat. I have had a terrible dream, -and it has left me so weak that I cannot move. What's wrong with my -face? It feels all swollen, and it smarts dreadfully." - -He tried to turn his head, but even with the effort his eyes seemed to -grow glassy again so I gently put it back. Then Van Helsing said in a -quiet grave tone, "Tell us your dream, Mr. Renfield." - -As he heard the voice his face brightened, through its mutilation, and -he said, "That is Dr. Van Helsing. How good it is of you to be here. -Give me some water, my lips are dry, and I shall try to tell you. I -dreamed . . ." - -He stopped and seemed fainting. I called quietly to Quincey, "The -brandy, it is in my study, quick!" He flew and returned with a glass, -the decanter of brandy and a carafe of water. We moistened the -parched lips, and the patient quickly revived. - -It seemed, however, that his poor injured brain had been working in -the interval, for when he was quite conscious, he looked at me -piercingly with an agonized confusion which I shall never forget, and -said, "I must not deceive myself. It was no dream, but all a grim -reality." Then his eyes roved round the room. As they caught sight -of the two figures sitting patiently on the edge of the bed he went -on, "If I were not sure already, I would know from them." - -For an instant his eyes closed, not with pain or sleep but -voluntarily, as though he were bringing all his faculties to bear. -When he opened them he said, hurriedly, and with more energy than he -had yet displayed, "Quick, Doctor, quick, I am dying! I feel that I -have but a few minutes, and then I must go back to death, or worse! -Wet my lips with brandy again. I have something that I must say -before I die. Or before my poor crushed brain dies anyhow. Thank -you! It was that night after you left me, when I implored you to let -me go away. I couldn't speak then, for I felt my tongue was tied. -But I was as sane then, except in that way, as I am now. I was in an -agony of despair for a long time after you left me, it seemed hours. -Then there came a sudden peace to me. My brain seemed to become cool -again, and I realized where I was. I heard the dogs bark behind our -house, but not where He was!" - -As he spoke, Van Helsing's eyes never blinked, but his hand came out -and met mine and gripped it hard. He did not, however, betray -himself. He nodded slightly and said, "Go on," in a low voice. - -Renfield proceeded. "He came up to the window in the mist, as I had -seen him often before, but he was solid then, not a ghost, and his -eyes were fierce like a man's when angry. He was laughing with his -red mouth, the sharp white teeth glinted in the moonlight when he -turned to look back over the belt of trees, to where the dogs were -barking. I wouldn't ask him to come in at first, though I knew he -wanted to, just as he had wanted all along. Then he began promising -me things, not in words but by doing them." - -He was interrupted by a word from the Professor, "How?" - -"By making them happen. Just as he used to send in the flies when the -sun was shining. Great big fat ones with steel and sapphire on their -wings. And big moths, in the night, with skull and cross-bones on -their backs." - -Van Helsing nodded to him as he whispered to me unconsciously, "The -Acherontia Atropos of the Sphinges, what you call the 'Death's-head -Moth'?" - -The patient went on without stopping, "Then he began to whisper. 'Rats, -rats, rats! Hundreds, thousands, millions of them, and every one a -life. And dogs to eat them, and cats too. All lives! All red blood, -with years of life in it, and not merely buzzing flies!' I laughed at -him, for I wanted to see what he could do. Then the dogs howled, away -beyond the dark trees in His house. He beckoned me to the window. I -got up and looked out, and He raised his hands, and seemed to call out -without using any words. A dark mass spread over the grass, coming on -like the shape of a flame of fire. And then He moved the mist to the -right and left, and I could see that there were thousands of rats with -their eyes blazing red, like His only smaller. He held up his hand, -and they all stopped, and I thought he seemed to be saying, 'All these -lives will I give you, ay, and many more and greater, through -countless ages, if you will fall down and worship me!' And then a red -cloud, like the colour of blood, seemed to close over my eyes, and -before I knew what I was doing, I found myself opening the sash and -saying to Him, 'Come in, Lord and Master!' The rats were all gone, but -He slid into the room through the sash, though it was only open an -inch wide, just as the Moon herself has often come in through the -tiniest crack and has stood before me in all her size and splendour." - -His voice was weaker, so I moistened his lips with the brandy again, -and he continued, but it seemed as though his memory had gone on -working in the interval for his story was further advanced. I was -about to call him back to the point, but Van Helsing whispered to me, -"Let him go on. Do not interrupt him. He cannot go back, and maybe -could not proceed at all if once he lost the thread of his thought." - -He proceeded, "All day I waited to hear from him, but he did not send -me anything, not even a blowfly, and when the moon got up I was pretty -angry with him. When he did slide in through the window, though it -was shut, and did not even knock, I got mad with him. He sneered at -me, and his white face looked out of the mist with his red eyes -gleaming, and he went on as though he owned the whole place, and I was -no one. He didn't even smell the same as he went by me. I couldn't -hold him. I thought that, somehow, Mrs. Harker had come into the -room." - -The two men sitting on the bed stood up and came over, standing behind -him so that he could not see them, but where they could hear better. -They were both silent, but the Professor started and quivered. His -face, however, grew grimmer and sterner still. Renfield went on -without noticing, "When Mrs. Harker came in to see me this afternoon -she wasn't the same. It was like tea after the teapot has been -watered." Here we all moved, but no one said a word. - -He went on, "I didn't know that she was here till she spoke, and she -didn't look the same. I don't care for the pale people. I like them -with lots of blood in them, and hers all seemed to have run out. I -didn't think of it at the time, but when she went away I began to -think, and it made me mad to know that He had been taking the life out -of her." I could feel that the rest quivered, as I did; but we -remained otherwise still. "So when He came tonight I was ready for -Him. I saw the mist stealing in, and I grabbed it tight. I had heard -that madmen have unnatural strength. And as I knew I was a madman, at -times anyhow, I resolved to use my power. Ay, and He felt it too, for -He had to come out of the mist to struggle with me. I held tight, and -I thought I was going to win, for I didn't mean Him to take any more -of her life, till I saw His eyes. They burned into me, and my -strength became like water. He slipped through it, and when I tried -to cling to Him, He raised me up and flung me down. There was a red -cloud before me, and a noise like thunder, and the mist seemed to -steal away under the door." - -His voice was becoming fainter and his breath more stertorous. Van -Helsing stood up instinctively. - -"We know the worst now," he said. "He is here, and we know his -purpose. It may not be too late. Let us be armed, the same as we -were the other night, but lose no time, there is not an instant to -spare." - -There was no need to put our fear, nay our conviction, into words, we -shared them in common. We all hurried and took from our rooms the -same things that we had when we entered the Count's house. The -Professor had his ready, and as we met in the corridor he pointed to -them significantly as he said, "They never leave me, and they shall -not till this unhappy business is over. Be wise also, my friends. It -is no common enemy that we deal with Alas! Alas! That dear Madam -Mina should suffer!" He stopped, his voice was breaking, and I do not -know if rage or terror predominated in my own heart. - -Outside the Harkers' door we paused. Art and Quincey held back, and -the latter said, "Should we disturb her?" - -"We must," said Van Helsing grimly. "If the door be locked, I shall -break it in." - -"May it not frighten her terribly? It is unusual to break into a -lady's room!" - -Van Helsing said solemnly, "You are always right. But this is life -and death. All chambers are alike to the doctor. And even were they -not they are all as one to me tonight. Friend John, when I turn the -handle, if the door does not open, do you put your shoulder down and -shove; and you too, my friends. Now!" - -He turned the handle as he spoke, but the door did not yield. We -threw ourselves against it. With a crash it burst open, and we almost -fell headlong into the room. The Professor did actually fall, and I -saw across him as he gathered himself up from hands and knees. What I -saw appalled me. I felt my hair rise like bristles on the back of my -neck, and my heart seemed to stand still. - -The moonlight was so bright that through the thick yellow blind the -room was light enough to see. On the bed beside the window lay -Jonathan Harker, his face flushed and breathing heavily as though in a -stupor. Kneeling on the near edge of the bed facing outwards was the -white-clad figure of his wife. By her side stood a tall, thin man, -clad in black. His face was turned from us, but the instant we saw we -all recognized the Count, in every way, even to the scar on his -forehead. With his left hand he held both Mrs. Harker's hands, -keeping them away with her arms at full tension. His right hand -gripped her by the back of the neck, forcing her face down on his -bosom. Her white nightdress was smeared with blood, and a thin stream -trickled down the man's bare chest which was shown by his torn-open -dress. The attitude of the two had a terrible resemblance to a child -forcing a kitten's nose into a saucer of milk to compel it to drink. -As we burst into the room, the Count turned his face, and the hellish -look that I had heard described seemed to leap into it. His eyes -flamed red with devilish passion. The great nostrils of the white -aquiline nose opened wide and quivered at the edge, and the white -sharp teeth, behind the full lips of the blood dripping mouth, clamped -together like those of a wild beast. With a wrench, which threw his -victim back upon the bed as though hurled from a height, he turned and -sprang at us. But by this time the Professor had gained his feet, and -was holding towards him the envelope which contained the Sacred Wafer. -The Count suddenly stopped, just as poor Lucy had done outside the -tomb, and cowered back. Further and further back he cowered, as we, -lifting our crucifixes, advanced. The moonlight suddenly failed, as a -great black cloud sailed across the sky. And when the gaslight sprang -up under Quincey's match, we saw nothing but a faint vapour. This, as -we looked, trailed under the door, which with the recoil from its -bursting open, had swung back to its old position. Van Helsing, Art, -and I moved forward to Mrs. Harker, who by this time had drawn her -breath and with it had given a scream so wild, so ear-piercing, so -despairing that it seems to me now that it will ring in my ears till -my dying day. For a few seconds she lay in her helpless attitude and -disarray. Her face was ghastly, with a pallor which was accentuated -by the blood which smeared her lips and cheeks and chin. From her -throat trickled a thin stream of blood. Her eyes were mad with -terror. Then she put before her face her poor crushed hands, which -bore on their whiteness the red mark of the Count's terrible grip, and -from behind them came a low desolate wail which made the terrible -scream seem only the quick expression of an endless grief. Van -Helsing stepped forward and drew the coverlet gently over her body, -whilst Art, after looking at her face for an instant despairingly, ran -out of the room. - -Van Helsing whispered to me, "Jonathan is in a stupor such as we know -the Vampire can produce. We can do nothing with poor Madam Mina for a -few moments till she recovers herself. I must wake him!" - -He dipped the end of a towel in cold water and with it began to flick -him on the face, his wife all the while holding her face between her -hands and sobbing in a way that was heart breaking to hear. I raised -the blind, and looked out of the window. There was much moonshine, -and as I looked I could see Quincey Morris run across the lawn and -hide himself in the shadow of a great yew tree. It puzzled me to -think why he was doing this. But at the instant I heard Harker's -quick exclamation as he woke to partial consciousness, and turned to -the bed. On his face, as there might well be, was a look of wild -amazement. He seemed dazed for a few seconds, and then full -consciousness seemed to burst upon him all at once, and he started up. - -His wife was aroused by the quick movement, and turned to him with her -arms stretched out, as though to embrace him. Instantly, however, she -drew them in again, and putting her elbows together, held her hands -before her face, and shuddered till the bed beneath her shook. - -"In God's name what does this mean?" Harker cried out. "Dr. Seward, -Dr. Van Helsing, what is it? What has happened? What is wrong? Mina, -dear what is it? What does that blood mean? My God, my God! Has it -come to this!" And, raising himself to his knees, he beat his hands -wildly together. "Good God help us! Help her! Oh, help her!" - -With a quick movement he jumped from bed, and began to pull on his -clothes, all the man in him awake at the need for instant exertion. -"What has happened? Tell me all about it!" he cried without pausing. -"Dr. Van Helsing, you love Mina, I know. Oh, do something to save her. -It cannot have gone too far yet. Guard her while I look for him!" - -His wife, through her terror and horror and distress, saw some sure -danger to him. Instantly forgetting her own grief, she seized hold of -him and cried out. - -"No! No! Jonathan, you must not leave me. I have suffered enough -tonight, God knows, without the dread of his harming you. You must -stay with me. Stay with these friends who will watch over you!" Her -expression became frantic as she spoke. And, he yielding to her, she -pulled him down sitting on the bedside, and clung to him fiercely. - -Van Helsing and I tried to calm them both. The Professor held up his -golden crucifix, and said with wonderful calmness, "Do not fear, my -dear. We are here, and whilst this is close to you no foul thing can -approach. You are safe for tonight, and we must be calm and take -counsel together." - -She shuddered and was silent, holding down her head on her husband's -breast. When she raised it, his white nightrobe was stained with -blood where her lips had touched, and where the thin open wound in the -neck had sent forth drops. The instant she saw it she drew back, with -a low wail, and whispered, amidst choking sobs. - -"Unclean, unclean! I must touch him or kiss him no more. Oh, that it -should be that it is I who am now his worst enemy, and whom he may -have most cause to fear." - -To this he spoke out resolutely, "Nonsense, Mina. It is a shame to me -to hear such a word. I would not hear it of you. And I shall not -hear it from you. May God judge me by my deserts, and punish me with -more bitter suffering than even this hour, if by any act or will of -mine anything ever come between us!" - -He put out his arms and folded her to his breast. And for a while she -lay there sobbing. He looked at us over her bowed head, with eyes -that blinked damply above his quivering nostrils. His mouth was set -as steel. - -After a while her sobs became less frequent and more faint, and then -he said to me, speaking with a studied calmness which I felt tried his -nervous power to the utmost. - -"And now, Dr. Seward, tell me all about it. Too well I know the broad -fact. Tell me all that has been." - -I told him exactly what had happened and he listened with seeming -impassiveness, but his nostrils twitched and his eyes blazed as I told -how the ruthless hands of the Count had held his wife in that terrible -and horrid position, with her mouth to the open wound in his breast. -It interested me, even at that moment, to see that whilst the face of -white set passion worked convulsively over the bowed head, the hands -tenderly and lovingly stroked the ruffled hair. Just as I had -finished, Quincey and Godalming knocked at the door. They entered in -obedience to our summons. Van Helsing looked at me questioningly. I -understood him to mean if we were to take advantage of their coming to -divert if possible the thoughts of the unhappy husband and wife from -each other and from themselves. So on nodding acquiescence to him he -asked them what they had seen or done. To which Lord Godalming -answered. - -"I could not see him anywhere in the passage, or in any of our rooms. -I looked in the study but, though he had been there, he had gone. He -had, however . . ." He stopped suddenly, looking at the poor drooping -figure on the bed. - -Van Helsing said gravely, "Go on, friend Arthur. We want here no more -concealments. Our hope now is in knowing all. Tell freely!" - -So Art went on, "He had been there, and though it could only have been -for a few seconds, he made rare hay of the place. All the manuscript -had been burned, and the blue flames were flickering amongst the white -ashes. The cylinders of your phonograph too were thrown on the fire, -and the wax had helped the flames." - -Here I interrupted. "Thank God there is the other copy in the safe!" - -His face lit for a moment, but fell again as he went on. "I ran -downstairs then, but could see no sign of him. I looked into -Renfield's room, but there was no trace there except . . ." Again he -paused. - -"Go on," said Harker hoarsely. So he bowed his head and moistening his -lips with his tongue, added, "except that the poor fellow is dead." - -Mrs. Harker raised her head, looking from one to the other of us she -said solemnly, "God's will be done!" - -I could not but feel that Art was keeping back something. But, as I -took it that it was with a purpose, I said nothing. - -Van Helsing turned to Morris and asked, "And you, friend Quincey, have -you any to tell?" - -"A little," he answered. "It may be much eventually, but at present I -can't say. I thought it well to know if possible where the Count -would go when he left the house. I did not see him, but I saw a bat -rise from Renfield's window, and flap westward. I expected to see him -in some shape go back to Carfax, but he evidently sought some other -lair. He will not be back tonight, for the sky is reddening in the -east, and the dawn is close. We must work tomorrow!" - -He said the latter words through his shut teeth. For a space of -perhaps a couple of minutes there was silence, and I could fancy that -I could hear the sound of our hearts beating. - -Then Van Helsing said, placing his hand tenderly on Mrs. Harker's -head, "And now, Madam Mina, poor dear, dear, Madam Mina, tell us -exactly what happened. God knows that I do not want that you be -pained, but it is need that we know all. For now more than ever has -all work to be done quick and sharp, and in deadly earnest. The day -is close to us that must end all, if it may be so, and now is the -chance that we may live and learn." - -The poor dear lady shivered, and I could see the tension of her nerves -as she clasped her husband closer to her and bent her head lower and -lower still on his breast. Then she raised her head proudly, and held -out one hand to Van Helsing who took it in his, and after stooping and -kissing it reverently, held it fast. The other hand was locked in -that of her husband, who held his other arm thrown round her -protectingly. After a pause in which she was evidently ordering her -thoughts, she began. - -"I took the sleeping draught which you had so kindly given me, but for -a long time it did not act. I seemed to become more wakeful, and -myriads of horrible fancies began to crowd in upon my mind. All of -them connected with death, and vampires, with blood, and pain, and -trouble." Her husband involuntarily groaned as she turned to him and -said lovingly, "Do not fret, dear. You must be brave and strong, and -help me through the horrible task. If you only knew what an effort it -is to me to tell of this fearful thing at all, you would understand -how much I need your help. Well, I saw I must try to help the -medicine to its work with my will, if it was to do me any good, so I -resolutely set myself to sleep. Sure enough sleep must soon have come -to me, for I remember no more. Jonathan coming in had not waked me, -for he lay by my side when next I remember. There was in the room the -same thin white mist that I had before noticed. But I forget now if -you know of this. You will find it in my diary which I shall show you -later. I felt the same vague terror which had come to me before and -the same sense of some presence. I turned to wake Jonathan, but found -that he slept so soundly that it seemed as if it was he who had taken -the sleeping draught, and not I. I tried, but I could not wake him. -This caused me a great fear, and I looked around terrified. Then -indeed, my heart sank within me. Beside the bed, as if he had stepped -out of the mist, or rather as if the mist had turned into his figure, -for it had entirely disappeared, stood a tall, thin man, all in -black. I knew him at once from the description of the others. The -waxen face, the high aquiline nose, on which the light fell in a thin -white line, the parted red lips, with the sharp white teeth showing -between, and the red eyes that I had seemed to see in the sunset on -the windows of St. Mary's Church at Whitby. I knew, too, the red scar -on his forehead where Jonathan had struck him. For an instant my -heart stood still, and I would have screamed out, only that I was -paralyzed. In the pause he spoke in a sort of keen, cutting whisper, -pointing as he spoke to Jonathan. - -"'Silence! If you make a sound I shall take him and dash his brains -out before your very eyes.' I was appalled and was too bewildered to -do or say anything. With a mocking smile, he placed one hand upon my -shoulder and, holding me tight, bared my throat with the other, saying -as he did so, 'First, a little refreshment to reward my exertions. -You may as well be quiet. It is not the first time, or the second, -that your veins have appeased my thirst!' I was bewildered, and -strangely enough, I did not want to hinder him. I suppose it is a -part of the horrible curse that such is, when his touch is on his -victim. And oh, my God, my God, pity me! He placed his reeking lips -upon my throat!" Her husband groaned again. She clasped his hand -harder, and looked at him pityingly, as if he were the injured one, -and went on. - -"I felt my strength fading away, and I was in a half swoon. How long -this horrible thing lasted I know not, but it seemed that a long time -must have passed before he took his foul, awful, sneering mouth away. -I saw it drip with the fresh blood!" The remembrance seemed for a while -to overpower her, and she drooped and would have sunk down but for her -husband's sustaining arm. With a great effort she recovered herself -and went on. - -"Then he spoke to me mockingly, 'And so you, like the others, would -play your brains against mine. You would help these men to hunt me -and frustrate me in my design! You know now, and they know in part -already, and will know in full before long, what it is to cross my -path. They should have kept their energies for use closer to home. -Whilst they played wits against me, against me who commanded nations, -and intrigued for them, and fought for them, hundreds of years before -they were born, I was countermining them. And you, their best beloved -one, are now to me, flesh of my flesh, blood of my blood, kin of my -kin, my bountiful wine-press for a while, and shall be later on my -companion and my helper. You shall be avenged in turn, for not one of -them but shall minister to your needs. But as yet you are to be -punished for what you have done. You have aided in thwarting me. Now -you shall come to my call. When my brain says "Come!" to you, you -shall cross land or sea to do my bidding. And to that end this!' - -"With that he pulled open his shirt, and with his long sharp nails -opened a vein in his breast. When the blood began to spurt out, he -took my hands in one of his, holding them tight, and with the other -seized my neck and pressed my mouth to the wound, so that I must -either suffocate or swallow some to the . . . Oh, my God! My God! -What have I done? What have I done to deserve such a fate, I who have -tried to walk in meekness and righteousness all my days. God pity -me! Look down on a poor soul in worse than mortal peril. And in -mercy pity those to whom she is dear!" Then she began to rub her lips -as though to cleanse them from pollution. - -As she was telling her terrible story, the eastern sky began to -quicken, and everything became more and more clear. Harker was still -and quiet; but over his face, as the awful narrative went on, came a -grey look which deepened and deepened in the morning light, till when -the first red streak of the coming dawn shot up, the flesh stood -darkly out against the whitening hair. - -We have arranged that one of us is to stay within call of the unhappy -pair till we can meet together and arrange about taking action. - -Of this I am sure. The sun rises today on no more miserable house in -all the great round of its daily course. - - - - -CHAPTER 22 - - -JONATHAN HARKER'S JOURNAL - -3 October.--As I must do something or go mad, I write this diary. It -is now six o'clock, and we are to meet in the study in half an hour -and take something to eat, for Dr. Van Helsing and Dr. Seward are -agreed that if we do not eat we cannot work our best. Our best will -be, God knows, required today. I must keep writing at every chance, -for I dare not stop to think. All, big and little, must go down. -Perhaps at the end the little things may teach us most. The teaching, -big or little, could not have landed Mina or me anywhere worse than we -are today. However, we must trust and hope. Poor Mina told me just -now, with the tears running down her dear cheeks, that it is in -trouble and trial that our faith is tested. That we must keep on -trusting, and that God will aid us up to the end. The end! Oh my -God! What end? . . . To work! To work! - -When Dr. Van Helsing and Dr. Seward had come back from seeing poor -Renfield, we went gravely into what was to be done. First, Dr. Seward -told us that when he and Dr. Van Helsing had gone down to the room -below they had found Renfield lying on the floor, all in a heap. His -face was all bruised and crushed in, and the bones of the neck were -broken. - -Dr. Seward asked the attendant who was on duty in the passage if he -had heard anything. He said that he had been sitting down, he -confessed to half dozing, when he heard loud voices in the room, and -then Renfield had called out loudly several times, "God! God! God!" -After that there was a sound of falling, and when he entered the room -he found him lying on the floor, face down, just as the doctors had -seen him. Van Helsing asked if he had heard "voices" or "a voice," -and he said he could not say. That at first it had seemed to him as -if there were two, but as there was no one in the room it could have -been only one. He could swear to it, if required, that the word "God" -was spoken by the patient. - -Dr. Seward said to us, when we were alone, that he did not wish to go -into the matter. The question of an inquest had to be considered, and -it would never do to put forward the truth, as no one would believe -it. As it was, he thought that on the attendant's evidence he could -give a certificate of death by misadventure in falling from bed. In -case the coroner should demand it, there would be a formal inquest, -necessarily to the same result. - -When the question began to be discussed as to what should be our next -step, the very first thing we decided was that Mina should be in full -confidence. That nothing of any sort, no matter how painful, should -be kept from her. She herself agreed as to its wisdom, and it was -pitiful to see her so brave and yet so sorrowful, and in such a depth -of despair. - -"There must be no concealment," she said. "Alas! We have had too -much already. And besides there is nothing in all the world that can -give me more pain than I have already endured, than I suffer now! -Whatever may happen, it must be of new hope or of new courage to me!" - -Van Helsing was looking at her fixedly as she spoke, and said, -suddenly but quietly, "But dear Madam Mina, are you not afraid. Not -for yourself, but for others from yourself, after what has happened?" - -Her face grew set in its lines, but her eyes shone with the devotion -of a martyr as she answered, "Ah no! For my mind is made up!" - -"To what?" he asked gently, whilst we were all very still, for each in -our own way we had a sort of vague idea of what she meant. - -Her answer came with direct simplicity, as though she was simply -stating a fact, "Because if I find in myself, and I shall watch keenly -for it, a sign of harm to any that I love, I shall die!" - -"You would not kill yourself?" he asked, hoarsely. - -"I would. If there were no friend who loved me, who would save me -such a pain, and so desperate an effort!" She looked at him meaningly -as she spoke. - -He was sitting down, but now he rose and came close to her and put his -hand on her head as he said solemnly. "My child, there is such an one -if it were for your good. For myself I could hold it in my account -with God to find such an euthanasia for you, even at this moment if it -were best. Nay, were it safe! But my child . . ." - -For a moment he seemed choked, and a great sob rose in his throat. He -gulped it down and went on, "There are here some who would stand -between you and death. You must not die. You must not die by any -hand, but least of all your own. Until the other, who has fouled your -sweet life, is true dead you must not die. For if he is still with -the quick Undead, your death would make you even as he is. No, you -must live! You must struggle and strive to live, though death would -seem a boon unspeakable. You must fight Death himself, though he come -to you in pain or in joy. By the day, or the night, in safety or in -peril! On your living soul I charge you that you do not die. Nay, -nor think of death, till this great evil be past." - -The poor dear grew white as death, and shook and shivered, as I have -seen a quicksand shake and shiver at the incoming of the tide. We -were all silent. We could do nothing. At length she grew more calm -and turning to him said sweetly, but oh so sorrowfully, as she held -out her hand, "I promise you, my dear friend, that if God will let me -live, I shall strive to do so. Till, if it may be in His good time, -this horror may have passed away from me." - -She was so good and brave that we all felt that our hearts were -strengthened to work and endure for her, and we began to discuss what -we were to do. I told her that she was to have all the papers in the -safe, and all the papers or diaries and phonographs we might hereafter -use, and was to keep the record as she had done before. She was -pleased with the prospect of anything to do, if "pleased" could be -used in connection with so grim an interest. - -As usual Van Helsing had thought ahead of everyone else, and was -prepared with an exact ordering of our work. - -"It is perhaps well," he said, "that at our meeting after our visit to -Carfax we decided not to do anything with the earth boxes that lay -there. Had we done so, the Count must have guessed our purpose, and -would doubtless have taken measures in advance to frustrate such an -effort with regard to the others. But now he does not know our -intentions. Nay, more, in all probability, he does not know that such -a power exists to us as can sterilize his lairs, so that he cannot use -them as of old. - -"We are now so much further advanced in our knowledge as to their -disposition that, when we have examined the house in Piccadilly, we may -track the very last of them. Today then, is ours, and in it rests our -hope. The sun that rose on our sorrow this morning guards us in its -course. Until it sets tonight, that monster must retain whatever form -he now has. He is confined within the limitations of his earthly -envelope. He cannot melt into thin air nor disappear through cracks -or chinks or crannies. If he go through a doorway, he must open the -door like a mortal. And so we have this day to hunt out all his lairs -and sterilize them. So we shall, if we have not yet catch him and -destroy him, drive him to bay in some place where the catching and the -destroying shall be, in time, sure." - -Here I started up for I could not contain myself at the thought that -the minutes and seconds so preciously laden with Mina's life and -happiness were flying from us, since whilst we talked action was -impossible. But Van Helsing held up his hand warningly. - -"Nay, friend Jonathan," he said, "in this, the quickest way home is -the longest way, so your proverb say. We shall all act and act with -desperate quick, when the time has come. But think, in all probable -the key of the situation is in that house in Piccadilly. The Count -may have many houses which he has bought. Of them he will have deeds -of purchase, keys and other things. He will have paper that he write -on. He will have his book of cheques. There are many belongings that -he must have somewhere. Why not in this place so central, so quiet, -where he come and go by the front or the back at all hours, when in -the very vast of the traffic there is none to notice. We shall go -there and search that house. And when we learn what it holds, then we -do what our friend Arthur call, in his phrases of hunt 'stop the -earths' and so we run down our old fox, so? Is it not?" - -"Then let us come at once," I cried, "we are wasting the precious, -precious time!" - -The Professor did not move, but simply said, "And how are we to get -into that house in Piccadilly?" - -"Any way!" I cried. "We shall break in if need be." - -"And your police? Where will they be, and what will they say?" - -I was staggered, but I knew that if he wished to delay he had a good -reason for it. So I said, as quietly as I could, "Don't wait more -than need be. You know, I am sure, what torture I am in." - -"Ah, my child, that I do. And indeed there is no wish of me to add to -your anguish. But just think, what can we do, until all the world be -at movement. Then will come our time. I have thought and thought, -and it seems to me that the simplest way is the best of all. Now we -wish to get into the house, but we have no key. Is it not so?" I -nodded. - -"Now suppose that you were, in truth, the owner of that house, and -could not still get in. And think there was to you no conscience of -the housebreaker, what would you do?" - -"I should get a respectable locksmith, and set him to work to pick the -lock for me." - -"And your police, they would interfere, would they not?" - -"Oh no! Not if they knew the man was properly employed." - -"Then," he looked at me as keenly as he spoke, "all that is in doubt -is the conscience of the employer, and the belief of your policemen as -to whether or not that employer has a good conscience or a bad one. -Your police must indeed be zealous men and clever, oh so clever, in -reading the heart, that they trouble themselves in such matter. No, -no, my friend Jonathan, you go take the lock off a hundred empty -houses in this your London, or of any city in the world, and if you do -it as such things are rightly done, and at the time such things are -rightly done, no one will interfere. I have read of a gentleman who -owned a so fine house in London, and when he went for months of summer -to Switzerland and lock up his house, some burglar come and broke -window at back and got in. Then he went and made open the shutters in -front and walk out and in through the door, before the very eyes of -the police. Then he have an auction in that house, and advertise it, -and put up big notice. And when the day come he sell off by a great -auctioneer all the goods of that other man who own them. Then he go -to a builder, and he sell him that house, making an agreement that he -pull it down and take all away within a certain time. And your police -and other authority help him all they can. And when that owner come -back from his holiday in Switzerland he find only an empty hole where -his house had been. This was all done en regle, and in our work we -shall be en regle too. We shall not go so early that the policemen -who have then little to think of, shall deem it strange. But we shall -go after ten o'clock, when there are many about, and such things would -be done were we indeed owners of the house." - -I could not but see how right he was and the terrible despair of -Mina's face became relaxed in thought. There was hope in such good -counsel. - -Van Helsing went on, "When once within that house we may find more -clues. At any rate some of us can remain there whilst the rest find -the other places where there be more earth boxes, at Bermondsey and -Mile End." - -Lord Godalming stood up. "I can be of some use here," he said. "I -shall wire to my people to have horses and carriages where they will -be most convenient." - -"Look here, old fellow," said Morris, "it is a capital idea to have -all ready in case we want to go horse backing, but don't you think -that one of your snappy carriages with its heraldic adornments in a -byway of Walworth or Mile End would attract too much attention for our -purpose? It seems to me that we ought to take cabs when we go south -or east. And even leave them somewhere near the neighbourhood we are -going to." - -"Friend Quincey is right!" said the Professor. "His head is what you -call in plane with the horizon. It is a difficult thing that we go to -do, and we do not want no peoples to watch us if so it may." - -Mina took a growing interest in everything and I was rejoiced to see -that the exigency of affairs was helping her to forget for a time the -terrible experience of the night. She was very, very pale, almost -ghastly, and so thin that her lips were drawn away, showing her teeth -in somewhat of prominence. I did not mention this last, lest it -should give her needless pain, but it made my blood run cold in my -veins to think of what had occurred with poor Lucy when the Count had -sucked her blood. As yet there was no sign of the teeth growing -sharper, but the time as yet was short, and there was time for fear. - -When we came to the discussion of the sequence of our efforts and of -the disposition of our forces, there were new sources of doubt. It -was finally agreed that before starting for Piccadilly we should -destroy the Count's lair close at hand. In case he should find it out -too soon, we should thus be still ahead of him in our work of -destruction. And his presence in his purely material shape, and at -his weakest, might give us some new clue. - -As to the disposal of forces, it was suggested by the Professor that, -after our visit to Carfax, we should all enter the house in -Piccadilly. That the two doctors and I should remain there, whilst -Lord Godalming and Quincey found the lairs at Walworth and Mile End -and destroyed them. It was possible, if not likely, the Professor -urged, that the Count might appear in Piccadilly during the day, and -that if so we might be able to cope with him then and there. At any -rate, we might be able to follow him in force. To this plan I -strenuously objected, and so far as my going was concerned, for I said -that I intended to stay and protect Mina. I thought that my mind was -made up on the subject, but Mina would not listen to my objection. She -said that there might be some law matter in which I could be useful. -That amongst the Count's papers might be some clue which I could -understand out of my experience in Transylvania. And that, as it was, -all the strength we could muster was required to cope with the Count's -extraordinary power. I had to give in, for Mina's resolution was -fixed. She said that it was the last hope for her that we should all -work together. - -"As for me," she said, "I have no fear. Things have been as bad as -they can be. And whatever may happen must have in it some element of -hope or comfort. Go, my husband! God can, if He wishes it, guard me -as well alone as with any one present." - -So I started up crying out, "Then in God's name let us come at once, -for we are losing time. The Count may come to Piccadilly earlier than -we think." - -"Not so!" said Van Helsing, holding up his hand. - -"But why?" I asked. - -"Do you forget," he said, with actually a smile, "that last night he -banqueted heavily, and will sleep late?" - -Did I forget! Shall I ever . . . can I ever! Can any of us ever -forget that terrible scene! Mina struggled hard to keep her brave -countenance, but the pain overmastered her and she put her hands -before her face, and shuddered whilst she moaned. Van Helsing had not -intended to recall her frightful experience. He had simply lost sight -of her and her part in the affair in his intellectual effort. - -When it struck him what he said, he was horrified at his -thoughtlessness and tried to comfort her. - -"Oh, Madam Mina," he said, "dear, dear, Madam Mina, alas! That I of -all who so reverence you should have said anything so forgetful. These -stupid old lips of mine and this stupid old head do not deserve so, -but you will forget it, will you not?" He bent low beside her as he -spoke. - -She took his hand, and looking at him through her tears, said -hoarsely, "No, I shall not forget, for it is well that I remember. -And with it I have so much in memory of you that is sweet, that I take -it all together. Now, you must all be going soon. Breakfast is -ready, and we must all eat that we may be strong." - -Breakfast was a strange meal to us all. We tried to be cheerful and -encourage each other, and Mina was the brightest and most cheerful of -us. When it was over, Van Helsing stood up and said, "Now, my dear -friends, we go forth to our terrible enterprise. Are we all armed, as -we were on that night when first we visited our enemy's lair. Armed -against ghostly as well as carnal attack?" - -We all assured him. - -"Then it is well. Now, Madam Mina, you are in any case quite safe -here until the sunset. And before then we shall return . . . if . . . -We shall return! But before we go let me see you armed against personal -attack. I have myself, since you came down, prepared your chamber by -the placing of things of which we know, so that He may not enter. Now -let me guard yourself. On your forehead I touch this piece of Sacred -Wafer in the name of the Father, the Son, and . . ." - -There was a fearful scream which almost froze our hearts to hear. As -he had placed the Wafer on Mina's forehead, it had seared it . . . had -burned into the flesh as though it had been a piece of white-hot metal. -My poor darling's brain had told her the significance of the fact as -quickly as her nerves received the pain of it, and the two so -overwhelmed her that her overwrought nature had its voice in that -dreadful scream. - -But the words to her thought came quickly. The echo of the scream had -not ceased to ring on the air when there came the reaction, and she -sank on her knees on the floor in an agony of abasement. Pulling her -beautiful hair over her face, as the leper of old his mantle, she -wailed out. - -"Unclean! Unclean! Even the Almighty shuns my polluted flesh! I -must bear this mark of shame upon my forehead until the Judgement -Day." - -They all paused. I had thrown myself beside her in an agony of -helpless grief, and putting my arms around held her tight. For a few -minutes our sorrowful hearts beat together, whilst the friends around -us turned away their eyes that ran tears silently. Then Van Helsing -turned and said gravely. So gravely that I could not help feeling -that he was in some way inspired, and was stating things outside -himself. - -"It may be that you may have to bear that mark till God himself see -fit, as He most surely shall, on the Judgement Day, to redress all -wrongs of the earth and of His children that He has placed thereon. -And oh, Madam Mina, my dear, my dear, may we who love you be there to -see, when that red scar, the sign of God's knowledge of what has been, -shall pass away, and leave your forehead as pure as the heart we know. -For so surely as we live, that scar shall pass away when God sees -right to lift the burden that is hard upon us. Till then we bear our -Cross, as His Son did in obedience to His Will. It may be that we are -chosen instruments of His good pleasure, and that we ascend to His -bidding as that other through stripes and shame. Through tears and -blood. Through doubts and fear, and all that makes the difference -between God and man." - -There was hope in his words, and comfort. And they made for -resignation. Mina and I both felt so, and simultaneously we each took -one of the old man's hands and bent over and kissed it. Then without -a word we all knelt down together, and all holding hands, swore to be -true to each other. We men pledged ourselves to raise the veil of -sorrow from the head of her whom, each in his own way, we loved. And -we prayed for help and guidance in the terrible task which lay before -us. It was then time to start. So I said farewell to Mina, a parting -which neither of us shall forget to our dying day, and we set out. - -To one thing I have made up my mind. If we find out that Mina must be -a vampire in the end, then she shall not go into that unknown and -terrible land alone. I suppose it is thus that in old times one -vampire meant many. Just as their hideous bodies could only rest in -sacred earth, so the holiest love was the recruiting sergeant for -their ghastly ranks. - -We entered Carfax without trouble and found all things the same as on -the first occasion. It was hard to believe that amongst so prosaic -surroundings of neglect and dust and decay there was any ground for -such fear as already we knew. Had not our minds been made up, and had -there not been terrible memories to spur us on, we could hardly have -proceeded with our task. We found no papers, or any sign of use in -the house. And in the old chapel the great boxes looked just as we -had seen them last. - -Dr. Van Helsing said to us solemnly as we stood before him, "And now, -my friends, we have a duty here to do. We must sterilize this earth, -so sacred of holy memories, that he has brought from a far distant -land for such fell use. He has chosen this earth because it has been -holy. Thus we defeat him with his own weapon, for we make it more -holy still. It was sanctified to such use of man, now we sanctify it -to God." - -As he spoke he took from his bag a screwdriver and a wrench, and very -soon the top of one of the cases was thrown open. The earth smelled -musty and close, but we did not somehow seem to mind, for our -attention was concentrated on the Professor. Taking from his box a -piece of the Sacred Wafer he laid it reverently on the earth, and then -shutting down the lid began to screw it home, we aiding him as he -worked. - -One by one we treated in the same way each of the great boxes, and -left them as we had found them to all appearance. But in each was a -portion of the Host. When we closed the door behind us, the Professor -said solemnly, "So much is already done. It may be that with all the -others we can be so successful, then the sunset of this evening may -shine of Madam Mina's forehead all white as ivory and with no stain!" - -As we passed across the lawn on our way to the station to catch our -train we could see the front of the asylum. I looked eagerly, and in -the window of my own room saw Mina. I waved my hand to her, and -nodded to tell that our work there was successfully accomplished. She -nodded in reply to show that she understood. The last I saw, she was -waving her hand in farewell. It was with a heavy heart that we sought -the station and just caught the train, which was steaming in as we -reached the platform. I have written this in the train. - - -Piccadilly, 12:30 o'clock.--Just before we reached Fenchurch Street -Lord Godalming said to me, "Quincey and I will find a locksmith. You -had better not come with us in case there should be any difficulty. -For under the circumstances it wouldn't seem so bad for us to break -into an empty house. But you are a solicitor and the Incorporated Law -Society might tell you that you should have known better." - -I demurred as to my not sharing any danger even of odium, but he went -on, "Besides, it will attract less attention if there are not too many -of us. My title will make it all right with the locksmith, and with -any policeman that may come along. You had better go with Jack and -the Professor and stay in the Green Park. Somewhere in sight of the -house, and when you see the door opened and the smith has gone away, -do you all come across. We shall be on the lookout for you, and shall -let you in." - -"The advice is good!" said Van Helsing, so we said no more. Godalming -and Morris hurried off in a cab, we following in another. At the -corner of Arlington Street our contingent got out and strolled into -the Green Park. My heart beat as I saw the house on which so much of -our hope was centred, looming up grim and silent in its deserted -condition amongst its more lively and spruce-looking neighbours. We -sat down on a bench within good view, and began to smoke cigars so as -to attract as little attention as possible. The minutes seemed to -pass with leaden feet as we waited for the coming of the others. - -At length we saw a four-wheeler drive up. Out of it, in leisurely -fashion, got Lord Godalming and Morris. And down from the box -descended a thick-set working man with his rush-woven basket of tools. -Morris paid the cabman, who touched his hat and drove away. Together -the two ascended the steps, and Lord Godalming pointed out what he -wanted done. The workman took off his coat leisurely and hung it on -one of the spikes of the rail, saying something to a policeman who -just then sauntered along. The policeman nodded acquiescence, and the -man kneeling down placed his bag beside him. After searching through -it, he took out a selection of tools which he proceeded to lay beside -him in orderly fashion. Then he stood up, looked in the keyhole, blew -into it, and turning to his employers, made some remark. Lord -Godalming smiled, and the man lifted a good sized bunch of keys. -Selecting one of them, he began to probe the lock, as if feeling his -way with it. After fumbling about for a bit he tried a second, and -then a third. All at once the door opened under a slight push from -him, and he and the two others entered the hall. We sat still. My -own cigar burnt furiously, but Van Helsing's went cold altogether. We -waited patiently as we saw the workman come out and bring his bag. -Then he held the door partly open, steadying it with his knees, whilst -he fitted a key to the lock. This he finally handed to Lord -Godalming, who took out his purse and gave him something. The man -touched his hat, took his bag, put on his coat and departed. Not a -soul took the slightest notice of the whole transaction. - -When the man had fairly gone, we three crossed the street and knocked -at the door. It was immediately opened by Quincey Morris, beside whom -stood Lord Godalming lighting a cigar. - -"The place smells so vilely," said the latter as we came in. It did -indeed smell vilely. Like the old chapel at Carfax. And with our -previous experience it was plain to us that the Count had been using -the place pretty freely. We moved to explore the house, all keeping -together in case of attack, for we knew we had a strong and wily enemy -to deal with, and as yet we did not know whether the Count might not -be in the house. - -In the dining room, which lay at the back of the hall, we found eight -boxes of earth. Eight boxes only out of the nine which we sought! -Our work was not over, and would never be until we should have found -the missing box. - -First we opened the shutters of the window which looked out across a -narrow stone flagged yard at the blank face of a stable, pointed to -look like the front of a miniature house. There were no windows in -it, so we were not afraid of being overlooked. We did not lose any -time in examining the chests. With the tools which we had brought -with us we opened them, one by one, and treated them as we had treated -those others in the old chapel. It was evident to us that the Count -was not at present in the house, and we proceeded to search for any of -his effects. - -After a cursory glance at the rest of the rooms, from basement to -attic, we came to the conclusion that the dining room contained any -effects which might belong to the Count. And so we proceeded to -minutely examine them. They lay in a sort of orderly disorder on the -great dining room table. - -There were title deeds of the Piccadilly house in a great bundle, -deeds of the purchase of the houses at Mile End and Bermondsey, -notepaper, envelopes, and pens and ink. All were covered up in thin -wrapping paper to keep them from the dust. There were also a clothes -brush, a brush and comb, and a jug and basin. The latter containing -dirty water which was reddened as if with blood. Last of all was a -little heap of keys of all sorts and sizes, probably those belonging -to the other houses. - -When we had examined this last find, Lord Godalming and Quincey Morris -taking accurate notes of the various addresses of the houses in the -East and the South, took with them the keys in a great bunch, and set -out to destroy the boxes in these places. The rest of us are, with -what patience we can, waiting their return, or the coming of the -Count. - - - - -CHAPTER 23 - - -DR. SEWARD'S DIARY - -3 October.--The time seemed terribly long whilst we were waiting for -the coming of Godalming and Quincey Morris. The Professor tried to -keep our minds active by using them all the time. I could see his -beneficent purpose, by the side glances which he threw from time to -time at Harker. The poor fellow is overwhelmed in a misery that is -appalling to see. Last night he was a frank, happy-looking man, with -strong, youthful face, full of energy, and with dark brown hair. -Today he is a drawn, haggard old man, whose white hair matches well -with the hollow burning eyes and grief-written lines of his face. His -energy is still intact. In fact, he is like a living flame. This may -yet be his salvation, for if all go well, it will tide him over the -despairing period. He will then, in a kind of way, wake again to the -realities of life. Poor fellow, I thought my own trouble was bad -enough, but his . . . ! - -The Professor knows this well enough, and is doing his best to keep -his mind active. What he has been saying was, under the -circumstances, of absorbing interest. So well as I can remember, here -it is: - -"I have studied, over and over again since they came into my hands, -all the papers relating to this monster, and the more I have studied, -the greater seems the necessity to utterly stamp him out. All through -there are signs of his advance. Not only of his power, but of his -knowledge of it. As I learned from the researches of my friend -Arminius of Buda-Pesth, he was in life a most wonderful man. Soldier, -statesman, and alchemist--which latter was the highest development of -the science knowledge of his time. He had a mighty brain, a learning -beyond compare, and a heart that knew no fear and no remorse. He -dared even to attend the Scholomance, and there was no branch of -knowledge of his time that he did not essay. - -"Well, in him the brain powers survived the physical death. Though it -would seem that memory was not all complete. In some faculties of -mind he has been, and is, only a child. But he is growing, and some -things that were childish at the first are now of man's stature. He -is experimenting, and doing it well. And if it had not been that we -have crossed his path he would be yet, he may be yet if we fail, the -father or furtherer of a new order of beings, whose road must lead -through Death, not Life." - -Harker groaned and said, "And this is all arrayed against my darling! -But how is he experimenting? The knowledge may help us to defeat -him!" - -"He has all along, since his coming, been trying his power, slowly but -surely. That big child-brain of his is working. Well for us, it is -as yet a child-brain. For had he dared, at the first, to attempt -certain things he would long ago have been beyond our power. However, -he means to succeed, and a man who has centuries before him can afford -to wait and to go slow. Festina lente may well be his motto." - -"I fail to understand," said Harker wearily. "Oh, do be more plain to -me! Perhaps grief and trouble are dulling my brain." - -The Professor laid his hand tenderly on his shoulder as he spoke, "Ah, -my child, I will be plain. Do you not see how, of late, this monster -has been creeping into knowledge experimentally. How he has been -making use of the zoophagous patient to effect his entry into friend -John's home. For your Vampire, though in all afterwards he can come -when and how he will, must at the first make entry only when asked -thereto by an inmate. But these are not his most important -experiments. Do we not see how at the first all these so great boxes -were moved by others. He knew not then but that must be so. But all -the time that so great child-brain of his was growing, and he began to -consider whether he might not himself move the box. So he began to -help. And then, when he found that this be all right, he try to move -them all alone. And so he progress, and he scatter these graves of -him. And none but he know where they are hidden. - -"He may have intend to bury them deep in the ground. So that only he -use them in the night, or at such time as he can change his form, they -do him equal well, and none may know these are his hiding place! But, -my child, do not despair, this knowledge came to him just too late! -Already all of his lairs but one be sterilize as for him. And before -the sunset this shall be so. Then he have no place where he can move -and hide. I delayed this morning that so we might be sure. Is there -not more at stake for us than for him? Then why not be more careful -than him? By my clock it is one hour and already, if all be well, -friend Arthur and Quincey are on their way to us. Today is our day, -and we must go sure, if slow, and lose no chance. See! There are -five of us when those absent ones return." - -Whilst we were speaking we were startled by a knock at the hall door, -the double postman's knock of the telegraph boy. We all moved out to -the hall with one impulse, and Van Helsing, holding up his hand to us -to keep silence, stepped to the door and opened it. The boy handed in -a dispatch. The Professor closed the door again, and after looking at -the direction, opened it and read aloud. - -"Look out for D. He has just now, 12:45, come from Carfax -hurriedly and hastened towards the South. He seems to be -going the round and may want to see you: Mina." - -There was a pause, broken by Jonathan Harker's voice, "Now, God be -thanked, we shall soon meet!" - -Van Helsing turned to him quickly and said, "God will act in His own -way and time. Do not fear, and do not rejoice as yet. For what we -wish for at the moment may be our own undoings." - -"I care for nothing now," he answered hotly, "except to wipe out this -brute from the face of creation. I would sell my soul to do it!" - -"Oh, hush, hush, my child!" said Van Helsing. "God does not purchase -souls in this wise, and the Devil, though he may purchase, does not -keep faith. But God is merciful and just, and knows your pain and -your devotion to that dear Madam Mina. Think you, how her pain would -be doubled, did she but hear your wild words. Do not fear any of us, -we are all devoted to this cause, and today shall see the end. The -time is coming for action. Today this Vampire is limit to the powers -of man, and till sunset he may not change. It will take him time to -arrive here, see it is twenty minutes past one, and there are yet some -times before he can hither come, be he never so quick. What we must -hope for is that my Lord Arthur and Quincey arrive first." - -About half an hour after we had received Mrs. Harker's telegram, there -came a quiet, resolute knock at the hall door. It was just an -ordinary knock, such as is given hourly by thousands of gentlemen, but -it made the Professor's heart and mine beat loudly. We looked at each -other, and together moved out into the hall. We each held ready to -use our various armaments, the spiritual in the left hand, the mortal -in the right. Van Helsing pulled back the latch, and holding the door -half open, stood back, having both hands ready for action. The -gladness of our hearts must have shown upon our faces when on the -step, close to the door, we saw Lord Godalming and Quincey Morris. -They came quickly in and closed the door behind them, the former -saying, as they moved along the hall: - -"It is all right. We found both places. Six boxes in each and we -destroyed them all." - -"Destroyed?" asked the Professor. - -"For him!" We were silent for a minute, and then Quincey said, -"There's nothing to do but to wait here. If, however, he doesn't turn -up by five o'clock, we must start off. For it won't do to leave Mrs. -Harker alone after sunset." - -"He will be here before long now," said Van Helsing, who had been -consulting his pocketbook. "Nota bene, in Madam's telegram he went -south from Carfax. That means he went to cross the river, and he -could only do so at slack of tide, which should be something before -one o'clock. That he went south has a meaning for us. He is as yet -only suspicious, and he went from Carfax first to the place where he -would suspect interference least. You must have been at Bermondsey -only a short time before him. That he is not here already shows that -he went to Mile End next. This took him some time, for he would then -have to be carried over the river in some way. Believe me, my -friends, we shall not have long to wait now. We should have ready -some plan of attack, so that we may throw away no chance. Hush, there -is no time now. Have all your arms! Be ready!" He held up a warning -hand as he spoke, for we all could hear a key softly inserted in the -lock of the hall door. - -I could not but admire, even at such a moment, the way in which a -dominant spirit asserted itself. In all our hunting parties and -adventures in different parts of the world, Quincey Morris had always -been the one to arrange the plan of action, and Arthur and I had been -accustomed to obey him implicitly. Now, the old habit seemed to be -renewed instinctively. With a swift glance around the room, he at -once laid out our plan of attack, and without speaking a word, with a -gesture, placed us each in position. Van Helsing, Harker, and I were -just behind the door, so that when it was opened the Professor could -guard it whilst we two stepped between the incomer and the door. -Godalming behind and Quincey in front stood just out of sight ready to -move in front of the window. We waited in a suspense that made the -seconds pass with nightmare slowness. The slow, careful steps came -along the hall. The Count was evidently prepared for some surprise, -at least he feared it. - -Suddenly with a single bound he leaped into the room. Winning a way -past us before any of us could raise a hand to stay him. There was -something so pantherlike in the movement, something so unhuman, that -it seemed to sober us all from the shock of his coming. The first to -act was Harker, who with a quick movement, threw himself before the -door leading into the room in the front of the house. As the Count -saw us, a horrible sort of snarl passed over his face, showing the -eyeteeth long and pointed. But the evil smile as quickly passed into -a cold stare of lion-like disdain. His expression again changed as, -with a single impulse, we all advanced upon him. It was a pity that -we had not some better organized plan of attack, for even at the -moment I wondered what we were to do. I did not myself know whether -our lethal weapons would avail us anything. - -Harker evidently meant to try the matter, for he had ready his great -Kukri knife and made a fierce and sudden cut at him. The blow was a -powerful one; only the diabolical quickness of the Count's leap back -saved him. A second less and the trenchant blade had shorn through -his heart. As it was, the point just cut the cloth of his coat, -making a wide gap whence a bundle of bank notes and a stream -of gold fell out. The expression of the Count's face was so hellish, -that for a moment I feared for Harker, though I saw him throw the -terrible knife aloft again for another stroke. Instinctively I moved -forward with a protective impulse, holding the Crucifix and Wafer in -my left hand. I felt a mighty power fly along my arm, and it was -without surprise that I saw the monster cower back before a similar -movement made spontaneously by each one of us. It would be impossible -to describe the expression of hate and baffled malignity, of anger and -hellish rage, which came over the Count's face. His waxen hue became -greenish-yellow by the contrast of his burning eyes, and the red scar -on the forehead showed on the pallid skin like a palpitating wound. -The next instant, with a sinuous dive he swept under Harker's arm, ere -his blow could fall, and grasping a handful of the money from the -floor, dashed across the room, threw himself at the window. Amid the -crash and glitter of the falling glass, he tumbled into the flagged -area below. Through the sound of the shivering glass I could hear the -"ting" of the gold, as some of the sovereigns fell on the flagging. - -We ran over and saw him spring unhurt from the ground. He, rushing up -the steps, crossed the flagged yard, and pushed open the stable door. -There he turned and spoke to us. - -"You think to baffle me, you with your pale faces all in a row, like -sheep in a butcher's. You shall be sorry yet, each one of you! You -think you have left me without a place to rest, but I have more. My -revenge is just begun! I spread it over centuries, and time is on my -side. Your girls that you all love are mine already. And through -them you and others shall yet be mine, my creatures, to do my bidding -and to be my jackals when I want to feed. Bah!" - -With a contemptuous sneer, he passed quickly through the door, and we -heard the rusty bolt creak as he fastened it behind him. A door -beyond opened and shut. The first of us to speak was the Professor. -Realizing the difficulty of following him through the stable, we moved -toward the hall. - -"We have learnt something . . . much! Notwithstanding his brave words, -he fears us. He fears time, he fears want! For if not, why he hurry -so? His very tone betray him, or my ears deceive. Why take that -money? You follow quick. You are hunters of the wild beast, and -understand it so. For me, I make sure that nothing here may be of use -to him, if so that he returns." - -As he spoke he put the money remaining in his pocket, took the title -deeds in the bundle as Harker had left them, and swept the remaining -things into the open fireplace, where he set fire to them with a -match. - -Godalming and Morris had rushed out into the yard, and Harker had -lowered himself from the window to follow the Count. He had, however, -bolted the stable door, and by the time they had forced it open there -was no sign of him. Van Helsing and I tried to make inquiry at the -back of the house. But the mews was deserted and no one had seen him -depart. - -It was now late in the afternoon, and sunset was not far off. We had -to recognize that our game was up. With heavy hearts we agreed with -the Professor when he said, "Let us go back to Madam Mina. Poor, poor -dear Madam Mina. All we can do just now is done, and we can there, at -least, protect her. But we need not despair. There is but one more -earth box, and we must try to find it. When that is done all may yet -be well." - -I could see that he spoke as bravely as he could to comfort Harker. -The poor fellow was quite broken down, now and again he gave a low -groan which he could not suppress. He was thinking of his wife. - -With sad hearts we came back to my house, where we found Mrs. Harker -waiting us, with an appearance of cheerfulness which did honour to her -bravery and unselfishness. When she saw our faces, her own became as -pale as death. For a second or two her eyes were closed as if she -were in secret prayer. - -And then she said cheerfully, "I can never thank you all enough. Oh, -my poor darling!" - -As she spoke, she took her husband's grey head in her hands and kissed -it. - -"Lay your poor head here and rest it. All will yet be well, dear! God -will protect us if He so will it in His good intent." The poor fellow -groaned. There was no place for words in his sublime misery. - -We had a sort of perfunctory supper together, and I think it cheered -us all up somewhat. It was, perhaps, the mere animal heat of food to -hungry people, for none of us had eaten anything since breakfast, or -the sense of companionship may have helped us, but anyhow we were all -less miserable, and saw the morrow as not altogether without hope. - -True to our promise, we told Mrs. Harker everything which had passed. -And although she grew snowy white at times when danger had seemed to -threaten her husband, and red at others when his devotion to her was -manifested, she listened bravely and with calmness. When we came to -the part where Harker had rushed at the Count so recklessly, she clung -to her husband's arm, and held it tight as though her clinging could -protect him from any harm that might come. She said nothing, however, -till the narration was all done, and matters had been brought up to -the present time. - -Then without letting go her husband's hand she stood up amongst us and -spoke. Oh, that I could give any idea of the scene. Of that sweet, -sweet, good, good woman in all the radiant beauty of her youth and -animation, with the red scar on her forehead, of which she was -conscious, and which we saw with grinding of our teeth, remembering -whence and how it came. Her loving kindness against our grim hate. -Her tender faith against all our fears and doubting. And we, knowing -that so far as symbols went, she with all her goodness and purity and -faith, was outcast from God. - -"Jonathan," she said, and the word sounded like music on her lips it -was so full of love and tenderness, "Jonathan dear, and you all my -true, true friends, I want you to bear something in mind through all -this dreadful time. I know that you must fight. That you must -destroy even as you destroyed the false Lucy so that the true Lucy -might live hereafter. But it is not a work of hate. That poor soul -who has wrought all this misery is the saddest case of all. Just -think what will be his joy when he, too, is destroyed in his worser -part that his better part may have spiritual immortality. You must be -pitiful to him, too, though it may not hold your hands from his -destruction." - -As she spoke I could see her husband's face darken and draw together, -as though the passion in him were shriveling his being to its core. -Instinctively the clasp on his wife's hand grew closer, till his -knuckles looked white. She did not flinch from the pain which I knew -she must have suffered, but looked at him with eyes that were more -appealing than ever. - -As she stopped speaking he leaped to his feet, almost tearing his hand -from hers as he spoke. - -"May God give him into my hand just for long enough to destroy that -earthly life of him which we are aiming at. If beyond it I could send -his soul forever and ever to burning hell I would do it!" - -"Oh, hush! Oh, hush in the name of the good God. Don't say such -things, Jonathan, my husband, or you will crush me with fear and -horror. Just think, my dear . . . I have been thinking all this long, -long day of it . . . that . . . perhaps . . . some day . . . I, too, may -need such pity, and that some other like you, and with equal cause for -anger, may deny it to me! Oh, my husband! My husband, indeed I would -have spared you such a thought had there been another way. But I pray -that God may not have treasured your wild words, except as the -heart-broken wail of a very loving and sorely stricken man. Oh, God, -let these poor white hairs go in evidence of what he has suffered, who -all his life has done no wrong, and on whom so many sorrows have -come." - -We men were all in tears now. There was no resisting them, and we -wept openly. She wept, too, to see that her sweeter counsels had -prevailed. Her husband flung himself on his knees beside her, and -putting his arms round her, hid his face in the folds of her dress. -Van Helsing beckoned to us and we stole out of the room, leaving the -two loving hearts alone with their God. - -Before they retired the Professor fixed up the room against any coming -of the Vampire, and assured Mrs. Harker that she might rest in peace. -She tried to school herself to the belief, and manifestly for her -husband's sake, tried to seem content. It was a brave struggle, and -was, I think and believe, not without its reward. Van Helsing had -placed at hand a bell which either of them was to sound in case of any -emergency. When they had retired, Quincey, Godalming, and I arranged -that we should sit up, dividing the night between us, and watch over -the safety of the poor stricken lady. The first watch falls to -Quincey, so the rest of us shall be off to bed as soon as we can. - -Godalming has already turned in, for his is the second watch. Now -that my work is done I, too, shall go to bed. - - - -JONATHAN HARKER'S JOURNAL - -3-4 October, close to midnight.--I thought yesterday would never end. -There was over me a yearning for sleep, in some sort of blind belief -that to wake would be to find things changed, and that any change must -now be for the better. Before we parted, we discussed what our next -step was to be, but we could arrive at no result. All we knew was -that one earth box remained, and that the Count alone knew where it -was. If he chooses to lie hidden, he may baffle us for years. And in -the meantime, the thought is too horrible, I dare not think of it even -now. This I know, that if ever there was a woman who was all -perfection, that one is my poor wronged darling. I loved her a -thousand times more for her sweet pity of last night, a pity that made -my own hate of the monster seem despicable. Surely God will not -permit the world to be the poorer by the loss of such a creature. This -is hope to me. We are all drifting reefwards now, and faith is our -only anchor. Thank God! Mina is sleeping, and sleeping without -dreams. I fear what her dreams might be like, with such terrible -memories to ground them in. She has not been so calm, within my -seeing, since the sunset. Then, for a while, there came over her face -a repose which was like spring after the blasts of March. I thought -at the time that it was the softness of the red sunset on her face, -but somehow now I think it has a deeper meaning. I am not sleepy -myself, though I am weary . . . weary to death. However, I must try -to sleep. For there is tomorrow to think of, and there is no rest for -me until . . . - - -Later--I must have fallen asleep, for I was awakened by Mina, who was -sitting up in bed, with a startled look on her face. I could see -easily, for we did not leave the room in darkness. She had placed a -warning hand over my mouth, and now she whispered in my ear, "Hush! -There is someone in the corridor!" I got up softly, and crossing the -room, gently opened the door. - -Just outside, stretched on a mattress, lay Mr. Morris, wide awake. He -raised a warning hand for silence as he whispered to me, "Hush! Go -back to bed. It is all right. One of us will be here all night. We -don't mean to take any chances!" - -His look and gesture forbade discussion, so I came back and told Mina. -She sighed and positively a shadow of a smile stole over her poor, -pale face as she put her arms round me and said softly, "Oh, thank God -for good brave men!" With a sigh she sank back again to sleep. I -write this now as I am not sleepy, though I must try again. - - -4 October, morning.--Once again during the night I was wakened by -Mina. This time we had all had a good sleep, for the grey of the -coming dawn was making the windows into sharp oblongs, and the gas -flame was like a speck rather than a disc of light. - -She said to me hurriedly, "Go, call the Professor. I want to see him -at once." - -"Why?" I asked. - -"I have an idea. I suppose it must have come in the night, and -matured without my knowing it. He must hypnotize me before the dawn, -and then I shall be able to speak. Go quick, dearest, the time is -getting close." - -I went to the door. Dr. Seward was resting on the mattress, and -seeing me, he sprang to his feet. - -"Is anything wrong?" he asked, in alarm. - -"No," I replied. "But Mina wants to see Dr. Van Helsing at once." - -"I will go," he said, and hurried into the Professor's room. - -Two or three minutes later Van Helsing was in the room in his dressing -gown, and Mr. Morris and Lord Godalming were with Dr. Seward at the -door asking questions. When the Professor saw Mina a smile, a -positive smile ousted the anxiety of his face. - -He rubbed his hands as he said, "Oh, my dear Madam Mina, this is -indeed a change. See! Friend Jonathan, we have got our dear Madam -Mina, as of old, back to us today!" Then turning to her, he said -cheerfully, "And what am I to do for you? For at this hour you do not -want me for nothing." - -"I want you to hypnotize me!" she said. "Do it before the dawn, for I -feel that then I can speak, and speak freely. Be quick, for the time -is short!" Without a word he motioned her to sit up in bed. - -Looking fixedly at her, he commenced to make passes in front of her, -from over the top of her head downward, with each hand in turn. Mina -gazed at him fixedly for a few minutes, during which my own heart beat -like a trip hammer, for I felt that some crisis was at hand. -Gradually her eyes closed, and she sat, stock still. Only by the -gentle heaving of her bosom could one know that she was alive. The -Professor made a few more passes and then stopped, and I could see -that his forehead was covered with great beads of perspiration. Mina -opened her eyes, but she did not seem the same woman. There was a -far-away look in her eyes, and her voice had a sad dreaminess which -was new to me. Raising his hand to impose silence, the Professor -motioned to me to bring the others in. They came on tiptoe, closing -the door behind them, and stood at the foot of the bed, looking on. -Mina appeared not to see them. The stillness was broken by Van -Helsing's voice speaking in a low level tone which would not break the -current of her thoughts. - -"Where are you?" The answer came in a neutral way. - -"I do not know. Sleep has no place it can call its own." For several -minutes there was silence. Mina sat rigid, and the Professor stood -staring at her fixedly. - -The rest of us hardly dared to breathe. The room was growing lighter. -Without taking his eyes from Mina's face, Dr. Van Helsing motioned me -to pull up the blind. I did so, and the day seemed just upon us. A -red streak shot up, and a rosy light seemed to diffuse itself through -the room. On the instant the Professor spoke again. - -"Where are you now?" - -The answer came dreamily, but with intention. It were as though she -were interpreting something. I have heard her use the same tone when -reading her shorthand notes. - -"I do not know. It is all strange to me!" - -"What do you see?" - -"I can see nothing. It is all dark." - -"What do you hear?" I could detect the strain in the Professor's -patient voice. - -"The lapping of water. It is gurgling by, and little waves leap. I -can hear them on the outside." - -"Then you are on a ship?'" - -We all looked at each other, trying to glean something each from the -other. We were afraid to think. - -The answer came quick, "Oh, yes!" - -"What else do you hear?" - -"The sound of men stamping overhead as they run about. There is the -creaking of a chain, and the loud tinkle as the check of the capstan -falls into the ratchet." - -"What are you doing?" - -"I am still, oh so still. It is like death!" The voice faded away -into a deep breath as of one sleeping, and the open eyes closed again. - -By this time the sun had risen, and we were all in the full light of -day. Dr. Van Helsing placed his hands on Mina's shoulders, and laid -her head down softly on her pillow. She lay like a sleeping child for -a few moments, and then, with a long sigh, awoke and stared in wonder -to see us all around her. - -"Have I been talking in my sleep?" was all she said. She seemed, -however, to know the situation without telling, though she was eager -to know what she had told. The Professor repeated the conversation, -and she said, "Then there is not a moment to lose. It may not be yet -too late!" - -Mr. Morris and Lord Godalming started for the door but the Professor's -calm voice called them back. - -"Stay, my friends. That ship, wherever it was, was weighing anchor at -the moment in your so great Port of London. Which of them is it that -you seek? God be thanked that we have once again a clue, though -whither it may lead us we know not. We have been blind somewhat. -Blind after the manner of men, since we can look back we see what we -might have seen looking forward if we had been able to see what we -might have seen! Alas, but that sentence is a puddle, is it not? We -can know now what was in the Count's mind, when he seize that money, -though Jonathan's so fierce knife put him in the danger that even he -dread. He meant escape. Hear me, ESCAPE! He saw that with but one -earth box left, and a pack of men following like dogs after a fox, -this London was no place for him. He have take his last earth box on -board a ship, and he leave the land. He think to escape, but no! We -follow him. Tally Ho! As friend Arthur would say when he put on his -red frock! Our old fox is wily. Oh! So wily, and we must follow -with wile. I, too, am wily and I think his mind in a little while. -In meantime we may rest and in peace, for there are between us which -he do not want to pass, and which he could not if he would. Unless -the ship were to touch the land, and then only at full or slack tide. -See, and the sun is just rose, and all day to sunset is us. Let us -take bath, and dress, and have breakfast which we all need, and which -we can eat comfortably since he be not in the same land with us." - -Mina looked at him appealingly as she asked, "But why need we seek him -further, when he is gone away from us?" - -He took her hand and patted it as he replied, "Ask me nothing as yet. -When we have breakfast, then I answer all questions." He would say no -more, and we separated to dress. - -After breakfast Mina repeated her question. He looked at her gravely -for a minute and then said sorrowfully, "Because my dear, dear Madam -Mina, now more than ever must we find him even if we have to follow -him to the jaws of Hell!" - -She grew paler as she asked faintly, "Why?" - -"Because," he answered solemnly, "he can live for centuries, and you -are but mortal woman. Time is now to be dreaded, since once he put -that mark upon your throat." - -I was just in time to catch her as she fell forward in a faint. - - - - -CHAPTER 24 - - -DR. SEWARD'S PHONOGRAPH DIARY - -SPOKEN BY VAN HELSING - -This to Jonathan Harker. - -You are to stay with your dear Madam Mina. We shall go to make our -search, if I can call it so, for it is not search but knowing, and we -seek confirmation only. But do you stay and take care of her today. -This is your best and most holiest office. This day nothing can find -him here. - -Let me tell you that so you will know what we four know already, for I -have tell them. He, our enemy, have gone away. He have gone back to -his Castle in Transylvania. I know it so well, as if a great hand of -fire wrote it on the wall. He have prepare for this in some way, and -that last earth box was ready to ship somewheres. For this he took -the money. For this he hurry at the last, lest we catch him before -the sun go down. It was his last hope, save that he might hide in the -tomb that he think poor Miss Lucy, being as he thought like him, keep -open to him. But there was not of time. When that fail he make -straight for his last resource, his last earth-work I might say did I -wish double entente. He is clever, oh so clever! He know that his -game here was finish. And so he decide he go back home. He find ship -going by the route he came, and he go in it. - -We go off now to find what ship, and whither bound. When we have -discover that, we come back and tell you all. Then we will comfort -you and poor Madam Mina with new hope. For it will be hope when you -think it over, that all is not lost. This very creature that we -pursue, he take hundreds of years to get so far as London. And yet in -one day, when we know of the disposal of him we drive him out. He is -finite, though he is powerful to do much harm and suffers not as we -do. But we are strong, each in our purpose, and we are all more -strong together. Take heart afresh, dear husband of Madam Mina. This -battle is but begun and in the end we shall win. So sure as that God -sits on high to watch over His children. Therefore be of much comfort -till we return. - -VAN HELSING. - - - - - -JONATHAN HARKER'S JOURNAL - -4 October.--When I read to Mina, Van Helsing's message in the -phonograph, the poor girl brightened up considerably. Already the -certainty that the Count is out of the country has given her comfort. -And comfort is strength to her. For my own part, now that his -horrible danger is not face to face with us, it seems almost -impossible to believe in it. Even my own terrible experiences in -Castle Dracula seem like a long forgotten dream. Here in the crisp -autumn air in the bright sunlight. - -Alas! How can I disbelieve! In the midst of my thought my eye fell -on the red scar on my poor darling's white forehead. Whilst that -lasts, there can be no disbelief. Mina and I fear to be idle, so we -have been over all the diaries again and again. Somehow, although the -reality seem greater each time, the pain and the fear seem less. There -is something of a guiding purpose manifest throughout, which is -comforting. Mina says that perhaps we are the instruments of ultimate -good. It may be! I shall try to think as she does. We have never -spoken to each other yet of the future. It is better to wait till we -see the Professor and the others after their investigations. - -The day is running by more quickly than I ever thought a day could run -for me again. It is now three o'clock. - - - - - -MINA HARKER'S JOURNAL - -5 October, 5 P.M.--Our meeting for report. Present: Professor Van -Helsing, Lord Godalming, Dr. Seward, Mr. Quincey Morris, Jonathan -Harker, Mina Harker. - -Dr. Van Helsing described what steps were taken during the day to -discover on what boat and whither bound Count Dracula made his escape. - -"As I knew that he wanted to get back to Transylvania, I felt sure -that he must go by the Danube mouth, or by somewhere in the Black Sea, -since by that way he come. It was a dreary blank that was before us. -Omme ignotum pro magnifico, and so with heavy hearts we start to find -what ships leave for the Black Sea last night. He was in sailing -ship, since Madam Mina tell of sails being set. These not so -important as to go in your list of the shipping in the Times, and so -we go, by suggestion of Lord Godalming, to your Lloyd's, where are -note of all ships that sail, however so small. There we find that -only one Black Sea bound ship go out with the tide. She is the -Czarina Catherine, and she sail from Doolittle's Wharf for Varna, and -thence to other ports and up the Danube. 'So!' said I, 'this is the -ship whereon is the Count.' So off we go to Doolittle's Wharf, and -there we find a man in an office. From him we inquire of the goings -of the Czarina Catherine. He swear much, and he red face and loud of -voice, but he good fellow all the same. And when Quincey give him -something from his pocket which crackle as he roll it up, and put it -in a so small bag which he have hid deep in his clothing, he still -better fellow and humble servant to us. He come with us, and ask many -men who are rough and hot. These be better fellows too when they have -been no more thirsty. They say much of blood and bloom, and of others -which I comprehend not, though I guess what they mean. But -nevertheless they tell us all things which we want to know. - -"They make known to us among them, how last afternoon at about five -o'clock comes a man so hurry. A tall man, thin and pale, with high -nose and teeth so white, and eyes that seem to be burning. That he be -all in black, except that he have a hat of straw which suit not him or -the time. That he scatter his money in making quick inquiry as to -what ship sails for the Black Sea and for where. Some took him to the -office and then to the ship, where he will not go aboard but halt at -shore end of gangplank, and ask that the captain come to him. The -captain come, when told that he will be pay well, and though he swear -much at the first he agree to term. Then the thin man go and some one -tell him where horse and cart can be hired. He go there and soon he -come again, himself driving cart on which a great box. This he -himself lift down, though it take several to put it on truck for the -ship. He give much talk to captain as to how and where his box is to -be place. But the captain like it not and swear at him in many -tongues, and tell him that if he like he can come and see where it -shall be. But he say 'no,' that he come not yet, for that he have -much to do. Whereupon the captain tell him that he had better be -quick, with blood, for that his ship will leave the place, of blood, -before the turn of the tide, with blood. Then the thin man smile and -say that of course he must go when he think fit, but he will be -surprise if he go quite so soon. The captain swear again, polyglot, -and the thin man make him bow, and thank him, and say that he will so -far intrude on his kindness as to come aboard before the sailing. -Final the captain, more red than ever, and in more tongues, tell him -that he doesn't want no Frenchmen, with bloom upon them and also with -blood, in his ship, with blood on her also. And so, after asking -where he might purchase ship forms, he departed. - -"No one knew where he went 'or bloomin' well cared' as they said, for -they had something else to think of, well with blood again. For it -soon became apparent to all that the Czarina Catherine would not sail -as was expected. A thin mist began to creep up from the river, and it -grew, and grew. Till soon a dense fog enveloped the ship and all -around her. The captain swore polyglot, very polyglot, polyglot with -bloom and blood, but he could do nothing. The water rose and rose, -and he began to fear that he would lose the tide altogether. He was -in no friendly mood, when just at full tide, the thin man came up the -gangplank again and asked to see where his box had been stowed. Then -the captain replied that he wished that he and his box, old and with -much bloom and blood, were in hell. But the thin man did not be -offend, and went down with the mate and saw where it was place, and -came up and stood awhile on deck in fog. He must have come off by -himself, for none notice him. Indeed they thought not of him, for -soon the fog begin to melt away, and all was clear again. My friends -of the thirst and the language that was of bloom and blood laughed, as -they told how the captain's swears exceeded even his usual polyglot, -and was more than ever full of picturesque, when on questioning other -mariners who were on movement up and down the river that hour, he -found that few of them had seen any of fog at all, except where it lay -round the wharf. However, the ship went out on the ebb tide, and was -doubtless by morning far down the river mouth. She was then, when -they told us, well out to sea. - -"And so, my dear Madam Mina, it is that we have to rest for a time, -for our enemy is on the sea, with the fog at his command, on his way -to the Danube mouth. To sail a ship takes time, go she never so -quick. And when we start to go on land more quick, and we meet him -there. Our best hope is to come on him when in the box between -sunrise and sunset. For then he can make no struggle, and we may deal -with him as we should. There are days for us, in which we can make -ready our plan. We know all about where he go. For we have seen the -owner of the ship, who have shown us invoices and all papers that can -be. The box we seek is to be landed in Varna, and to be given to an -agent, one Ristics who will there present his credentials. And so our -merchant friend will have done his part. When he ask if there be any -wrong, for that so, he can telegraph and have inquiry made at Varna, -we say 'no,' for what is to be done is not for police or of the -customs. It must be done by us alone and in our own way." - -When Dr. Van Helsing had done speaking, I asked him if he were certain -that the Count had remained on board the ship. He replied, "We have -the best proof of that, your own evidence, when in the hypnotic trance -this morning." - -I asked him again if it were really necessary that they should pursue -the Count, for oh! I dread Jonathan leaving me, and I know that he -would surely go if the others went. He answered in growing passion, -at first quietly. As he went on, however, he grew more angry and more -forceful, till in the end we could not but see wherein was at least -some of that personal dominance which made him so long a master -amongst men. - -"Yes, it is necessary, necessary, necessary! For your sake in the -first, and then for the sake of humanity. This monster has done much -harm already, in the narrow scope where he find himself, and in the -short time when as yet he was only as a body groping his so small -measure in darkness and not knowing. All this have I told these -others. You, my dear Madam Mina, will learn it in the phonograph of -my friend John, or in that of your husband. I have told them how the -measure of leaving his own barren land, barren of peoples, and coming -to a new land where life of man teems till they are like the multitude -of standing corn, was the work of centuries. Were another of the -Undead, like him, to try to do what he has done, perhaps not all the -centuries of the world that have been, or that will be, could aid him. -With this one, all the forces of nature that are occult and deep and -strong must have worked together in some wonderous way. The very -place, where he have been alive, Undead for all these centuries, is -full of strangeness of the geologic and chemical world. There are -deep caverns and fissures that reach none know whither. There have -been volcanoes, some of whose openings still send out waters of -strange properties, and gases that kill or make to vivify. Doubtless, -there is something magnetic or electric in some of these combinations -of occult forces which work for physical life in strange way, and in -himself were from the first some great qualities. In a hard and -warlike time he was celebrate that he have more iron nerve, more -subtle brain, more braver heart, than any man. In him some vital -principle have in strange way found their utmost. And as his body -keep strong and grow and thrive, so his brain grow too. All this -without that diabolic aid which is surely to him. For it have to -yield to the powers that come from, and are, symbolic of good. And -now this is what he is to us. He have infect you, oh forgive me, my -dear, that I must say such, but it is for good of you that I speak. He -infect you in such wise, that even if he do no more, you have only to -live, to live in your own old, sweet way, and so in time, death, which -is of man's common lot and with God's sanction, shall make you like to -him. This must not be! We have sworn together that it must not. -Thus are we ministers of God's own wish. That the world, and men for -whom His Son die, will not be given over to monsters, whose very -existence would defame Him. He have allowed us to redeem one soul -already, and we go out as the old knights of the Cross to redeem -more. Like them we shall travel towards the sunrise. And like them, -if we fall, we fall in good cause." - -He paused and I said, "But will not the Count take his rebuff wisely? -Since he has been driven from England, will he not avoid it, as a -tiger does the village from which he has been hunted?" - -"Aha!" he said, "your simile of the tiger good, for me, and I shall -adopt him. Your maneater, as they of India call the tiger who has -once tasted blood of the human, care no more for the other prey, but -prowl unceasing till he get him. This that we hunt from our village -is a tiger, too, a maneater, and he never cease to prowl. Nay, in -himself he is not one to retire and stay afar. In his life, his -living life, he go over the Turkey frontier and attack his enemy on -his own ground. He be beaten back, but did he stay? No! He come -again, and again, and again. Look at his persistence and endurance. -With the child-brain that was to him he have long since conceive the -idea of coming to a great city. What does he do? He find out the -place of all the world most of promise for him. Then he deliberately -set himself down to prepare for the task. He find in patience just -how is his strength, and what are his powers. He study new tongues. -He learn new social life, new environment of old ways, the politics, -the law, the finance, the science, the habit of a new land and a new -people who have come to be since he was. His glimpse that he have -had, whet his appetite only and enkeen his desire. Nay, it help him -to grow as to his brain. For it all prove to him how right he was at -the first in his surmises. He have done this alone, all alone! From -a ruin tomb in a forgotten land. What more may he not do when the -greater world of thought is open to him. He that can smile at death, -as we know him. Who can flourish in the midst of diseases that kill -off whole peoples. Oh! If such an one was to come from God, and not -the Devil, what a force for good might he not be in this old world of -ours. But we are pledged to set the world free. Our toil must be in -silence, and our efforts all in secret. For in this enlightened age, -when men believe not even what they see, the doubting of wise men -would be his greatest strength. It would be at once his sheath and -his armor, and his weapons to destroy us, his enemies, who are willing -to peril even our own souls for the safety of one we love. For the -good of mankind, and for the honour and glory of God." - -After a general discussion it was determined that for tonight nothing -be definitely settled. That we should all sleep on the facts, and try -to think out the proper conclusions. Tomorrow, at breakfast, we are -to meet again, and after making our conclusions known to one another, -we shall decide on some definite cause of action . . . - -I feel a wonderful peace and rest tonight. It is as if some haunting -presence were removed from me. Perhaps . . . - -My surmise was not finished, could not be, for I caught sight in the -mirror of the red mark upon my forehead, and I knew that I was still -unclean. - - - - -DR. SEWARD'S DIARY - -5 October.--We all arose early, and I think that sleep did much for -each and all of us. When we met at early breakfast there was more -general cheerfulness than any of us had ever expected to experience -again. - -It is really wonderful how much resilience there is in human nature. -Let any obstructing cause, no matter what, be removed in any way, even -by death, and we fly back to first principles of hope and enjoyment. -More than once as we sat around the table, my eyes opened in wonder -whether the whole of the past days had not been a dream. It was only -when I caught sight of the red blotch on Mrs. Harker's forehead that I -was brought back to reality. Even now, when I am gravely revolving -the matter, it is almost impossible to realize that the cause of all -our trouble is still existent. Even Mrs. Harker seems to lose sight -of her trouble for whole spells. It is only now and again, when -something recalls it to her mind, that she thinks of her terrible -scar. We are to meet here in my study in half an hour and decide on -our course of action. I see only one immediate difficulty, I know it -by instinct rather than reason. We shall all have to speak frankly. -And yet I fear that in some mysterious way poor Mrs. Harker's tongue -is tied. I know that she forms conclusions of her own, and from all -that has been I can guess how brilliant and how true they must be. -But she will not, or cannot, give them utterance. I have mentioned -this to Van Helsing, and he and I are to talk it over when we are -alone. I suppose it is some of that horrid poison which has got into -her veins beginning to work. The Count had his own purposes when he -gave her what Van Helsing called "the Vampire's baptism of blood." -Well, there may be a poison that distills itself out of good things. -In an age when the existence of ptomaines is a mystery we should not -wonder at anything! One thing I know, that if my instinct be true -regarding poor Mrs. Harker's silences, then there is a terrible -difficulty, an unknown danger, in the work before us. The same power -that compels her silence may compel her speech. I dare not think -further, for so I should in my thoughts dishonour a noble woman! - - -Later.--When the Professor came in, we talked over the state of -things. I could see that he had something on his mind, which he -wanted to say, but felt some hesitancy about broaching the subject. -After beating about the bush a little, he said, "Friend John, there is -something that you and I must talk of alone, just at the first at any -rate. Later, we may have to take the others into our confidence." - -Then he stopped, so I waited. He went on, "Madam Mina, our poor, dear -Madam Mina is changing." - -A cold shiver ran through me to find my worst fears thus endorsed. -Van Helsing continued. - -"With the sad experience of Miss Lucy, we must this time be warned -before things go too far. Our task is now in reality more difficult -than ever, and this new trouble makes every hour of the direst -importance. I can see the characteristics of the vampire coming in -her face. It is now but very, very slight. But it is to be seen if -we have eyes to notice without prejudge. Her teeth are sharper, and -at times her eyes are more hard. But these are not all, there is to -her the silence now often, as so it was with Miss Lucy. She did not -speak, even when she wrote that which she wished to be known later. -Now my fear is this. If it be that she can, by our hypnotic trance, -tell what the Count see and hear, is it not more true that he who have -hypnotize her first, and who have drink of her very blood and make her -drink of his, should if he will, compel her mind to disclose to him -that which she know?" - -I nodded acquiescence. He went on, "Then, what we must do is to -prevent this. We must keep her ignorant of our intent, and so she -cannot tell what she know not. This is a painful task! Oh, so -painful that it heartbreak me to think of it, but it must be. When -today we meet, I must tell her that for reason which we will not to -speak she must not more be of our council, but be simply guarded by -us." - -He wiped his forehead, which had broken out in profuse perspiration at -the thought of the pain which he might have to inflict upon the poor -soul already so tortured. I knew that it would be some sort of -comfort to him if I told him that I also had come to the same -conclusion. For at any rate it would take away the pain of doubt. I -told him, and the effect was as I expected. - -It is now close to the time of our general gathering. Van Helsing has -gone away to prepare for the meeting, and his painful part of it. I -really believe his purpose is to be able to pray alone. - - -Later.--At the very outset of our meeting a great personal relief was -experienced by both Van Helsing and myself. Mrs. Harker had sent a -message by her husband to say that she would not join us at present, -as she thought it better that we should be free to discuss our -movements without her presence to embarrass us. The Professor and I -looked at each other for an instant, and somehow we both seemed -relieved. For my own part, I thought that if Mrs. Harker realized the -danger herself, it was much pain as well as much danger averted. -Under the circumstances we agreed, by a questioning look and answer, -with finger on lip, to preserve silence in our suspicions, until we -should have been able to confer alone again. We went at once into our -Plan of Campaign. - -Van Helsing roughly put the facts before us first, "The Czarina -Catherine left the Thames yesterday morning. It will take her at the -quickest speed she has ever made at least three weeks to reach Varna. -But we can travel overland to the same place in three days. Now, if -we allow for two days less for the ship's voyage, owing to such -weather influences as we know that the Count can bring to bear, and if -we allow a whole day and night for any delays which may occur to us, -then we have a margin of nearly two weeks. - -"Thus, in order to be quite safe, we must leave here on 17th at -latest. Then we shall at any rate be in Varna a day before the ship -arrives, and able to make such preparations as may be necessary. Of -course we shall all go armed, armed against evil things, spiritual as -well as physical." - -Here Quincey Morris added, "I understand that the Count comes from a -wolf country, and it may be that he shall get there before us. I -propose that we add Winchesters to our armament. I have a kind of -belief in a Winchester when there is any trouble of that sort around. -Do you remember, Art, when we had the pack after us at Tobolsk? What -wouldn't we have given then for a repeater apiece!" - -"Good!" said Van Helsing, "Winchesters it shall be. Quincey's head is -level at times, but most so when there is to hunt, metaphor be more -dishonour to science than wolves be of danger to man. In the meantime -we can do nothing here. And as I think that Varna is not familiar to -any of us, why not go there more soon? It is as long to wait here as -there. Tonight and tomorrow we can get ready, and then if all be -well, we four can set out on our journey." - -"We four?" said Harker interrogatively, looking from one to another of -us. - -"Of course!" answered the Professor quickly. "You must remain to take -care of your so sweet wife!" - -Harker was silent for awhile and then said in a hollow voice, "Let us -talk of that part of it in the morning. I want to consult with Mina." - -I thought that now was the time for Van Helsing to warn him not to -disclose our plan to her, but he took no notice. I looked at him -significantly and coughed. For answer he put his finger to his lips -and turned away. - - - -JONATHAN HARKER'S JOURNAL - -5 October, afternoon.--For some time after our meeting this morning I -could not think. The new phases of things leave my mind in a state of -wonder which allows no room for active thought. Mina's determination -not to take any part in the discussion set me thinking. And as I -could not argue the matter with her, I could only guess. I am as far -as ever from a solution now. The way the others received it, too -puzzled me. The last time we talked of the subject we agreed that -there was to be no more concealment of anything amongst us. Mina is -sleeping now, calmly and sweetly like a little child. Her lips are -curved and her face beams with happiness. Thank God, there are such -moments still for her. - - -Later.--How strange it all is. I sat watching Mina's happy sleep, and -I came as near to being happy myself as I suppose I shall ever be. As -the evening drew on, and the earth took its shadows from the sun -sinking lower, the silence of the room grew more and more solemn to -me. - -All at once Mina opened her eyes, and looking at me tenderly said, -"Jonathan, I want you to promise me something on your word of honour. -A promise made to me, but made holily in God's hearing, and not to be -broken though I should go down on my knees and implore you with bitter -tears. Quick, you must make it to me at once." - -"Mina," I said, "a promise like that, I cannot make at once. I may -have no right to make it." - -"But, dear one," she said, with such spiritual intensity that her eyes -were like pole stars, "it is I who wish it. And it is not for myself. -You can ask Dr. Van Helsing if I am not right. If he disagrees you -may do as you will. Nay, more if you all agree, later you are -absolved from the promise." - -"I promise!" I said, and for a moment she looked supremely happy. -Though to me all happiness for her was denied by the red scar on her -forehead. - -She said, "Promise me that you will not tell me anything of the plans -formed for the campaign against the Count. Not by word, or inference, -or implication, not at any time whilst this remains to me!" And she -solemnly pointed to the scar. I saw that she was in earnest, and said -solemnly, "I promise!" and as I said it I felt that from that instant -a door had been shut between us. - - -Later, midnight.--Mina has been bright and cheerful all the evening. -So much so that all the rest seemed to take courage, as if infected -somewhat with her gaiety. As a result even I myself felt as if the -pall of gloom which weighs us down were somewhat lifted. We all -retired early. Mina is now sleeping like a little child. It is -wonderful thing that her faculty of sleep remains to her in the midst -of her terrible trouble. Thank God for it, for then at least she can -forget her care. Perhaps her example may affect me as her gaiety did -tonight. I shall try it. Oh! For a dreamless sleep. - -6 October, morning.--Another surprise. Mina woke me early, about the -same time as yesterday, and asked me to bring Dr. Van Helsing. I -thought that it was another occasion for hypnotism, and without -question went for the Professor. He had evidently expected some such -call, for I found him dressed in his room. His door was ajar, so that -he could hear the opening of the door of our room. He came at once. -As he passed into the room, he asked Mina if the others might come, -too. - -"No," she said quite simply, "it will not be necessary. You can tell -them just as well. I must go with you on your journey." - -Dr. Van Helsing was as startled as I was. After a moment's pause he -asked, "But why?" - -"You must take me with you. I am safer with you, and you shall be -safer, too." - -"But why, dear Madam Mina? You know that your safety is our solemnest -duty. We go into danger, to which you are, or may be, more liable -than any of us from . . . from circumstances . . . things that have -been." He paused embarrassed. - -As she replied, she raised her finger and pointed to her forehead. "I -know. That is why I must go. I can tell you now, whilst the sun is -coming up. I may not be able again. I know that when the Count wills -me I must go. I know that if he tells me to come in secret, I must by -wile. By any device to hoodwink, even Jonathan." God saw the look -that she turned on me as she spoke, and if there be indeed a Recording -Angel that look is noted to her ever-lasting honour. I could only -clasp her hand. I could not speak. My emotion was too great for even -the relief of tears. - -She went on. "You men are brave and strong. You are strong in your -numbers, for you can defy that which would break down the human -endurance of one who had to guard alone. Besides, I may be of -service, since you can hypnotize me and so learn that which even I -myself do not know." - -Dr. Van Helsing said gravely, "Madam Mina, you are, as always, most -wise. You shall with us come. And together we shall do that which we -go forth to achieve." - -When he had spoken, Mina's long spell of silence made me look at her. -She had fallen back on her pillow asleep. She did not even wake when -I had pulled up the blind and let in the sunlight which flooded the -room. Van Helsing motioned to me to come with him quietly. We went -to his room, and within a minute Lord Godalming, Dr. Seward, and Mr. -Morris were with us also. - -He told them what Mina had said, and went on. "In the morning we -shall leave for Varna. We have now to deal with a new factor, Madam -Mina. Oh, but her soul is true. It is to her an agony to tell us so -much as she has done. But it is most right, and we are warned in -time. There must be no chance lost, and in Varna we must be ready to -act the instant when that ship arrives." - -"What shall we do exactly?" asked Mr. Morris laconically. - -The Professor paused before replying, "We shall at the first board -that ship. Then, when we have identified the box, we shall place a -branch of the wild rose on it. This we shall fasten, for when it is -there none can emerge, so that at least says the superstition. And to -superstition must we trust at the first. It was man's faith in the -early, and it have its root in faith still. Then, when we get the -opportunity that we seek, when none are near to see, we shall open the -box, and . . . and all will be well." - -"I shall not wait for any opportunity," said Morris. "When I see the -box I shall open it and destroy the monster, though there were a -thousand men looking on, and if I am to be wiped out for it the next -moment!" I grasped his hand instinctively and found it as firm as a -piece of steel. I think he understood my look. I hope he did. - -"Good boy," said Dr. Van Helsing. "Brave boy. Quincey is all man. -God bless him for it. My child, believe me none of us shall lag -behind or pause from any fear. I do but say what we may do . . . what -we must do. But, indeed, indeed we cannot say what we may do. There -are so many things which may happen, and their ways and their ends are -so various that until the moment we may not say. We shall all be -armed, in all ways. And when the time for the end has come, our -effort shall not be lack. Now let us today put all our affairs in -order. Let all things which touch on others dear to us, and who on us -depend, be complete. For none of us can tell what, or when, or how, -the end may be. As for me, my own affairs are regulate, and as I have -nothing else to do, I shall go make arrangements for the travel. I -shall have all tickets and so forth for our journey." - -There was nothing further to be said, and we parted. I shall now -settle up all my affairs of earth, and be ready for whatever may come. - - -Later.--It is done. My will is made, and all complete. Mina if she -survive is my sole heir. If it should not be so, then the others who -have been so good to us shall have remainder. - -It is now drawing towards the sunset. Mina's uneasiness calls my -attention to it. I am sure that there is something on her mind which -the time of exact sunset will reveal. These occasions are becoming -harrowing times for us all. For each sunrise and sunset opens up some -new danger, some new pain, which however, may in God's will be means -to a good end. I write all these things in the diary since my darling -must not hear them now. But if it may be that she can see them again, -they shall be ready. She is calling to me. - - - - -CHAPTER 25 - - -DR. SEWARD'S DIARY - -11 October, Evening.--Jonathan Harker has asked me to note this, as he -says he is hardly equal to the task, and he wants an exact record -kept. - -I think that none of us were surprised when we were asked to see Mrs. -Harker a little before the time of sunset. We have of late come to -understand that sunrise and sunset are to her times of peculiar -freedom. When her old self can be manifest without any controlling -force subduing or restraining her, or inciting her to action. This -mood or condition begins some half hour or more before actual sunrise -or sunset, and lasts till either the sun is high, or whilst the clouds -are still aglow with the rays streaming above the horizon. At first -there is a sort of negative condition, as if some tie were loosened, -and then the absolute freedom quickly follows. When, however, the -freedom ceases the change back or relapse comes quickly, preceded -only by a spell of warning silence. - -Tonight, when we met, she was somewhat constrained, and bore all the -signs of an internal struggle. I put it down myself to her making a -violent effort at the earliest instant she could do so. - -A very few minutes, however, gave her complete control of herself. -Then, motioning her husband to sit beside her on the sofa where she -was half reclining, she made the rest of us bring chairs up close. - -Taking her husband's hand in hers, she began, "We are all here -together in freedom, for perhaps the last time! I know that you will -always be with me to the end." This was to her husband whose hand had, -as we could see, tightened upon her. "In the morning we go out upon -our task, and God alone knows what may be in store for any of us. You -are going to be so good to me to take me with you. I know that all -that brave earnest men can do for a poor weak woman, whose soul -perhaps is lost, no, no, not yet, but is at any rate at stake, you -will do. But you must remember that I am not as you are. There is a -poison in my blood, in my soul, which may destroy me, which must -destroy me, unless some relief comes to us. Oh, my friends, you know -as well as I do, that my soul is at stake. And though I know there is -one way out for me, you must not and I must not take it!" She looked -appealingly to us all in turn, beginning and ending with her husband. - -"What is that way?" asked Van Helsing in a hoarse voice. "What is -that way, which we must not, may not, take?" - -"That I may die now, either by my own hand or that of another, before -the greater evil is entirely wrought. I know, and you know, that were -I once dead you could and would set free my immortal spirit, even as -you did my poor Lucy's. Were death, or the fear of death, the only -thing that stood in the way I would not shrink to die here now, amidst -the friends who love me. But death is not all. I cannot believe that -to die in such a case, when there is hope before us and a bitter task -to be done, is God's will. Therefore, I on my part, give up here the -certainty of eternal rest, and go out into the dark where may be the -blackest things that the world or the nether world holds!" - -We were all silent, for we knew instinctively that this was only a -prelude. The faces of the others were set, and Harker's grew ashen -grey. Perhaps, he guessed better than any of us what was coming. - -She continued, "This is what I can give into the hotch-pot." I could -not but note the quaint legal phrase which she used in such a place, -and with all seriousness. "What will each of you give? Your lives I -know," she went on quickly, "that is easy for brave men. Your lives -are God's, and you can give them back to Him, but what will you give -to me?" She looked again questioningly, but this time avoided her -husband's face. Quincey seemed to understand, he nodded, and her face -lit up. "Then I shall tell you plainly what I want, for there must be -no doubtful matter in this connection between us now. You must -promise me, one and all, even you, my beloved husband, that should the -time come, you will kill me." - -"What is that time?" The voice was Quincey's, but it was low and -strained. - -"When you shall be convinced that I am so changed that it is better -that I die that I may live. When I am thus dead in the flesh, then -you will, without a moment's delay, drive a stake through me and cut -off my head, or do whatever else may be wanting to give me rest!" - -Quincey was the first to rise after the pause. He knelt down before -her and taking her hand in his said solemnly, "I'm only a rough -fellow, who hasn't, perhaps, lived as a man should to win such a -distinction, but I swear to you by all that I hold sacred and dear -that, should the time ever come, I shall not flinch from the duty that -you have set us. And I promise you, too, that I shall make all -certain, for if I am only doubtful I shall take it that the time has -come!" - -"My true friend!" was all she could say amid her fast-falling tears, -as bending over, she kissed his hand. - -"I swear the same, my dear Madam Mina!" said Van Helsing. "And I!" -said Lord Godalming, each of them in turn kneeling to her to take the -oath. I followed, myself. - -Then her husband turned to her wan-eyed and with a greenish pallor -which subdued the snowy whiteness of his hair, and asked, "And must I, -too, make such a promise, oh, my wife?" - -"You too, my dearest," she said, with infinite yearning of pity in her -voice and eyes. "You must not shrink. You are nearest and dearest -and all the world to me. Our souls are knit into one, for all life -and all time. Think, dear, that there have been times when brave men -have killed their wives and their womenkind, to keep them from falling -into the hands of the enemy. Their hands did not falter any the more -because those that they loved implored them to slay them. It is men's -duty towards those whom they love, in such times of sore trial! And -oh, my dear, if it is to be that I must meet death at any hand, let it -be at the hand of him that loves me best. Dr. Van Helsing, I have not -forgotten your mercy in poor Lucy's case to him who loved." She -stopped with a flying blush, and changed her phrase, "to him who had -best right to give her peace. If that time shall come again, I look -to you to make it a happy memory of my husband's life that it was his -loving hand which set me free from the awful thrall upon me." - -"Again I swear!" came the Professor's resonant voice. - -Mrs. Harker smiled, positively smiled, as with a sigh of relief she -leaned back and said, "And now one word of warning, a warning which -you must never forget. This time, if it ever come, may come quickly -and unexpectedly, and in such case you must lose no time in using your -opportunity. At such a time I myself might be . . . nay! If the time -ever come, shall be, leagued with your enemy against you. - -"One more request," she became very solemn as she said this, "it is -not vital and necessary like the other, but I want you to do one thing -for me, if you will." - -We all acquiesced, but no one spoke. There was no need to speak. - -"I want you to read the Burial Service." She was interrupted by a -deep groan from her husband. Taking his hand in hers, she held it -over her heart, and continued. "You must read it over me some day. -Whatever may be the issue of all this fearful state of things, it will -be a sweet thought to all or some of us. You, my dearest, will I hope -read it, for then it will be in your voice in my memory forever, come -what may!" - -"But oh, my dear one," he pleaded, "death is afar off from you." - -"Nay," she said, holding up a warning hand. "I am deeper in death at -this moment than if the weight of an earthly grave lay heavy upon me!" - -"Oh, my wife, must I read it?" he said, before he began. - -"It would comfort me, my husband!" was all she said, and he began to -read when she had got the book ready. - -How can I, how could anyone, tell of that strange scene, its -solemnity, its gloom, its sadness, its horror, and withal, its -sweetness. Even a sceptic, who can see nothing but a travesty of -bitter truth in anything holy or emotional, would have been melted to -the heart had he seen that little group of loving and devoted friends -kneeling round that stricken and sorrowing lady; or heard the tender -passion of her husband's voice, as in tones so broken and emotional -that often he had to pause, he read the simple and beautiful service -from the Burial of the Dead. I cannot go on . . . words . . . and -v-voices . . . f-fail m-me! - -She was right in her instinct. Strange as it was, bizarre as it may -hereafter seem even to us who felt its potent influence at the time, -it comforted us much. And the silence, which showed Mrs. Harker's -coming relapse from her freedom of soul, did not seem so full of -despair to any of us as we had dreaded. - - - - - -JONATHAN HARKER'S JOURNAL - -15 October, Varna.--We left Charing Cross on the morning of the 12th, -got to Paris the same night, and took the places secured for us in the -Orient Express. We traveled night and day, arriving here at about -five o'clock. Lord Godalming went to the Consulate to see if any -telegram had arrived for him, whilst the rest of us came on to this -hotel, "the Odessus." The journey may have had incidents. I was, -however, too eager to get on, to care for them. Until the Czarina -Catherine comes into port there will be no interest for me in anything -in the wide world. Thank God! Mina is well, and looks to be getting -stronger. Her colour is coming back. She sleeps a great deal. -Throughout the journey she slept nearly all the time. Before sunrise -and sunset, however, she is very wakeful and alert. And it has become -a habit for Van Helsing to hypnotize her at such times. At first, -some effort was needed, and he had to make many passes. But now, she -seems to yield at once, as if by habit, and scarcely any action is -needed. He seems to have power at these particular moments to simply -will, and her thoughts obey him. He always asks her what she can see -and hear. - -She answers to the first, "Nothing, all is dark." - -And to the second, "I can hear the waves lapping against the ship, and -the water rushing by. Canvas and cordage strain and masts and yards -creak. The wind is high . . . I can hear it in the shrouds, and the -bow throws back the foam." - -It is evident that the Czarina Catherine is still at sea, hastening on -her way to Varna. Lord Godalming has just returned. He had four -telegrams, one each day since we started, and all to the same effect. -That the Czarina Catherine had not been reported to Lloyd's from -anywhere. He had arranged before leaving London that his agent should -send him every day a telegram saying if the ship had been reported. -He was to have a message even if she were not reported, so that he -might be sure that there was a watch being kept at the other end of -the wire. - -We had dinner and went to bed early. Tomorrow we are to see the Vice -Consul, and to arrange, if we can, about getting on board the ship as -soon as she arrives. Van Helsing says that our chance will be to get -on the boat between sunrise and sunset. The Count, even if he takes -the form of a bat, cannot cross the running water of his own volition, -and so cannot leave the ship. As he dare not change to man's form -without suspicion, which he evidently wishes to avoid, he must remain -in the box. If, then, we can come on board after sunrise, he is at -our mercy, for we can open the box and make sure of him, as we did of -poor Lucy, before he wakes. What mercy he shall get from us all will -not count for much. We think that we shall not have much trouble with -officials or the seamen. Thank God! This is the country where -bribery can do anything, and we are well supplied with money. We have -only to make sure that the ship cannot come into port between sunset -and sunrise without our being warned, and we shall be safe. Judge -Moneybag will settle this case, I think! - - -16 October.--Mina's report still the same. Lapping waves and rushing -water, darkness and favouring winds. We are evidently in good time, -and when we hear of the Czarina Catherine we shall be ready. As she -must pass the Dardanelles we are sure to have some report. - - -17 October.--Everything is pretty well fixed now, I think, to welcome -the Count on his return from his tour. Godalming told the shippers -that he fancied that the box sent aboard might contain something -stolen from a friend of his, and got a half consent that he might open -it at his own risk. The owner gave him a paper telling the Captain to -give him every facility in doing whatever he chose on board the ship, -and also a similar authorization to his agent at Varna. We have seen -the agent, who was much impressed with Godalming's kindly manner to -him, and we are all satisfied that whatever he can do to aid our -wishes will be done. - -We have already arranged what to do in case we get the box open. If -the Count is there, Van Helsing and Seward will cut off his head at -once and drive a stake through his heart. Morris and Godalming and I -shall prevent interference, even if we have to use the arms which we -shall have ready. The Professor says that if we can so treat the -Count's body, it will soon after fall into dust. In such case there -would be no evidence against us, in case any suspicion of murder were -aroused. But even if it were not, we should stand or fall by our act, -and perhaps some day this very script may be evidence to come between -some of us and a rope. For myself, I should take the chance only too -thankfully if it were to come. We mean to leave no stone unturned to -carry out our intent. We have arranged with certain officials that -the instant the Czarina Catherine is seen, we are to be informed by a -special messenger. - - -24 October.--A whole week of waiting. Daily telegrams to Godalming, -but only the same story. "Not yet reported." Mina's morning and -evening hypnotic answer is unvaried. Lapping waves, rushing water, -and creaking masts. - - - - -TELEGRAM, OCTOBER 24TH RUFUS SMITH, LLOYD'S, LONDON, -TO LORD GODALMING, CARE OF H. B. M. VICE CONSUL, VARNA - -"Czarina Catherine reported this morning from Dardanelles." - - - -DR. SEWARD'S DIARY - -25 October.--How I miss my phonograph! To write a diary with a pen is -irksome to me! But Van Helsing says I must. We were all wild with -excitement yesterday when Godalming got his telegram from Lloyd's. I -know now what men feel in battle when the call to action is heard. -Mrs. Harker, alone of our party, did not show any signs of emotion. -After all, it is not strange that she did not, for we took special -care not to let her know anything about it, and we all tried not to -show any excitement when we were in her presence. In old days she -would, I am sure, have noticed, no matter how we might have tried to -conceal it. But in this way she is greatly changed during the past -three weeks. The lethargy grows upon her, and though she seems strong -and well, and is getting back some of her colour, Van Helsing and I are -not satisfied. We talk of her often. We have not, however, said a -word to the others. It would break poor Harker's heart, certainly his -nerve, if he knew that we had even a suspicion on the subject. Van -Helsing examines, he tells me, her teeth very carefully, whilst she is -in the hypnotic condition, for he says that so long as they do not -begin to sharpen there is no active danger of a change in her. If -this change should come, it would be necessary to take steps! We both -know what those steps would have to be, though we do not mention our -thoughts to each other. We should neither of us shrink from the task, -awful though it be to contemplate. "Euthanasia" is an excellent and a -comforting word! I am grateful to whoever invented it. - -It is only about 24 hours' sail from the Dardanelles to here, at the -rate the Czarina Catherine has come from London. She should therefore -arrive some time in the morning, but as she cannot possibly get in -before noon, we are all about to retire early. We shall get up at one -o'clock, so as to be ready. - - -25 October, Noon.--No news yet of the ship's arrival. Mrs. Harker's -hypnotic report this morning was the same as usual, so it is possible -that we may get news at any moment. We men are all in a fever of -excitement, except Harker, who is calm. His hands are cold as ice, -and an hour ago I found him whetting the edge of the great Ghoorka -knife which he now always carries with him. It will be a bad lookout -for the Count if the edge of that "Kukri" ever touches his throat, -driven by that stern, ice-cold hand! - -Van Helsing and I were a little alarmed about Mrs. Harker today. -About noon she got into a sort of lethargy which we did not like. -Although we kept silence to the others, we were neither of us happy -about it. She had been restless all the morning, so that we were at -first glad to know that she was sleeping. When, however, her husband -mentioned casually that she was sleeping so soundly that he could not -wake her, we went to her room to see for ourselves. She was breathing -naturally and looked so well and peaceful that we agreed that the -sleep was better for her than anything else. Poor girl, she has so -much to forget that it is no wonder that sleep, if it brings oblivion -to her, does her good. - - -Later.--Our opinion was justified, for when after a refreshing sleep -of some hours she woke up, she seemed brighter and better than she had -been for days. At sunset she made the usual hypnotic report. -Wherever he may be in the Black Sea, the Count is hurrying to his -destination. To his doom, I trust! - - - -26 October.--Another day and no tidings of the Czarina Catherine. She -ought to be here by now. That she is still journeying somewhere is -apparent, for Mrs. Harker's hypnotic report at sunrise was still the -same. It is possible that the vessel may be lying by, at times, for -fog. Some of the steamers which came in last evening reported patches -of fog both to north and south of the port. We must continue our -watching, as the ship may now be signalled any moment. - - -27 October, Noon.--Most strange. No news yet of the ship we wait for. -Mrs. Harker reported last night and this morning as usual. "Lapping -waves and rushing water," though she added that "the waves were very -faint." The telegrams from London have been the same, "no further -report." Van Helsing is terribly anxious, and told me just now that he -fears the Count is escaping us. - -He added significantly, "I did not like that lethargy of Madam Mina's. -Souls and memories can do strange things during trance." I was about -to ask him more, but Harker just then came in, and he held up a -warning hand. We must try tonight at sunset to make her speak more -fully when in her hypnotic state. - - -28 October.--Telegram. Rufus Smith, London, to Lord Godalming, care -H. B. M. Vice Consul, Varna - -"Czarina Catherine reported entering Galatz at one o'clock today." - - - - -DR. SEWARD'S DIARY - -28 October.--When the telegram came announcing the arrival in Galatz I -do not think it was such a shock to any of us as might have been -expected. True, we did not know whence, or how, or when, the bolt -would come. But I think we all expected that something strange would -happen. The day of arrival at Varna made us individually satisfied -that things would not be just as we had expected. We only waited to -learn where the change would occur. None the less, however, it was a -surprise. I suppose that nature works on such a hopeful basis that we -believe against ourselves that things will be as they ought to be, not -as we should know that they will be. Transcendentalism is a beacon to -the angels, even if it be a will-o'-the-wisp to man. Van Helsing -raised his hand over his head for a moment, as though in remonstrance -with the Almighty. But he said not a word, and in a few seconds stood -up with his face sternly set. - -Lord Godalming grew very pale, and sat breathing heavily. I was -myself half stunned and looked in wonder at one after another. -Quincey Morris tightened his belt with that quick movement which I -knew so well. In our old wandering days it meant "action." Mrs. -Harker grew ghastly white, so that the scar on her forehead seemed to -burn, but she folded her hands meekly and looked up in prayer. Harker -smiled, actually smiled, the dark, bitter smile of one who is without -hope, but at the same time his action belied his words, for his hands -instinctively sought the hilt of the great Kukri knife and rested -there. - -"When does the next train start for Galatz?" said Van Helsing to us -generally. - -"At 6:30 tomorrow morning!" We all started, for the answer came from -Mrs. Harker. - -"How on earth do you know?" said Art. - -"You forget, or perhaps you do not know, though Jonathan does and so -does Dr. Van Helsing, that I am the train fiend. At home in Exeter I -always used to make up the time tables, so as to be helpful to my -husband. I found it so useful sometimes, that I always make a study -of the time tables now. I knew that if anything were to take us to -Castle Dracula we should go by Galatz, or at any rate through -Bucharest, so I learned the times very carefully. Unhappily there are -not many to learn, as the only train tomorrow leaves as I say." - -"Wonderful woman!" murmured the Professor. - -"Can't we get a special?" asked Lord Godalming. - -Van Helsing shook his head, "I fear not. This land is very different -from yours or mine. Even if we did have a special, it would probably -not arrive as soon as our regular train. Moreover, we have something -to prepare. We must think. Now let us organize. You, friend Arthur, -go to the train and get the tickets and arrange that all be ready for -us to go in the morning. Do you, friend Jonathan, go to the agent of -the ship and get from him letters to the agent in Galatz, with -authority to make a search of the ship just as it was here. Quincey -Morris, you see the Vice Consul, and get his aid with his fellow in -Galatz and all he can do to make our way smooth, so that no times be -lost when over the Danube. John will stay with Madam Mina and me, and -we shall consult. For so if time be long you may be delayed. And it -will not matter when the sun set, since I am here with Madam to make -report." - -"And I," said Mrs. Harker brightly, and more like her old self than -she had been for many a long day, "shall try to be of use in all ways, -and shall think and write for you as I used to do. Something is -shifting from me in some strange way, and I feel freer than I have -been of late!" - -The three younger men looked happier at the moment as they seemed to -realize the significance of her words. But Van Helsing and I, turning -to each other, met each a grave and troubled glance. We said nothing -at the time, however. - -When the three men had gone out to their tasks Van Helsing asked Mrs. -Harker to look up the copy of the diaries and find him the part of -Harker's journal at the Castle. She went away to get it. - -When the door was shut upon her he said to me, "We mean the same! -Speak out!" - -"Here is some change. It is a hope that makes me sick, for it may -deceive us." - -"Quite so. Do you know why I asked her to get the manuscript?" - -"No!" said I, "unless it was to get an opportunity of seeing me -alone." - -"You are in part right, friend John, but only in part. I want to tell -you something. And oh, my friend, I am taking a great, a terrible, -risk. But I believe it is right. In the moment when Madam Mina said -those words that arrest both our understanding, an inspiration came to -me. In the trance of three days ago the Count sent her his spirit to -read her mind. Or more like he took her to see him in his earth box -in the ship with water rushing, just as it go free at rise and set of -sun. He learn then that we are here, for she have more to tell in her -open life with eyes to see ears to hear than he, shut as he is, in his -coffin box. Now he make his most effort to escape us. At present he -want her not. - -"He is sure with his so great knowledge that she will come at his -call. But he cut her off, take her, as he can do, out of his own -power, that so she come not to him. Ah! There I have hope that our -man brains that have been of man so long and that have not lost the -grace of God, will come higher than his child-brain that lie in his -tomb for centuries, that grow not yet to our stature, and that do only -work selfish and therefore small. Here comes Madam Mina. Not a word -to her of her trance! She knows it not, and it would overwhelm her -and make despair just when we want all her hope, all her courage, when -most we want all her great brain which is trained like man's brain, -but is of sweet woman and have a special power which the Count give -her, and which he may not take away altogether, though he think not -so. Hush! Let me speak, and you shall learn. Oh, John, my friend, -we are in awful straits. I fear, as I never feared before. We can -only trust the good God. Silence! Here she comes!" - -I thought that the Professor was going to break down and have -hysterics, just as he had when Lucy died, but with a great effort he -controlled himself and was at perfect nervous poise when Mrs. Harker -tripped into the room, bright and happy looking and, in the doing of -work, seemingly forgetful of her misery. As she came in, she handed a -number of sheets of typewriting to Van Helsing. He looked over them -gravely, his face brightening up as he read. - -Then holding the pages between his finger and thumb he said, "Friend -John, to you with so much experience already, and you too, dear Madam -Mina, that are young, here is a lesson. Do not fear ever to think. A -half thought has been buzzing often in my brain, but I fear to let him -loose his wings. Here now, with more knowledge, I go back to where -that half thought come from and I find that he be no half thought at -all. That be a whole thought, though so young that he is not yet -strong to use his little wings. Nay, like the 'Ugly Duck' of my -friend Hans Andersen, he be no duck thought at all, but a big swan -thought that sail nobly on big wings, when the time come for him to -try them. See I read here what Jonathan have written. - -"That other of his race who, in a later age, again and again, brought -his forces over The Great River into Turkey Land, who when he was -beaten back, came again, and again, and again, though he had to come -alone from the bloody field where his troops were being slaughtered, -since he knew that he alone could ultimately triumph. - -"What does this tell us? Not much? No! The Count's child thought -see nothing, therefore he speak so free. Your man thought see -nothing. My man thought see nothing, till just now. No! But there -comes another word from some one who speak without thought because -she, too, know not what it mean, what it might mean. Just as there -are elements which rest, yet when in nature's course they move on -their way and they touch, the pouf! And there comes a flash of light, -heaven wide, that blind and kill and destroy some. But that show up -all earth below for leagues and leagues. Is it not so? Well, I shall -explain. To begin, have you ever study the philosophy of crime? -'Yes' and 'No.' You, John, yes, for it is a study of insanity. You, -no, Madam Mina, for crime touch you not, not but once. Still, your -mind works true, and argues not a particulari ad universale. There is -this peculiarity in criminals. It is so constant, in all countries -and at all times, that even police, who know not much from philosophy, -come to know it empirically, that it is. That is to be empiric. The -criminal always work at one crime, that is the true criminal who seems -predestinate to crime, and who will of none other. This criminal has -not full man brain. He is clever and cunning and resourceful, but he -be not of man stature as to brain. He be of child brain in much. Now -this criminal of ours is predestinate to crime also. He, too, have -child brain, and it is of the child to do what he have done. The -little bird, the little fish, the little animal learn not by -principle, but empirically. And when he learn to do, then there is to -him the ground to start from to do more. 'Dos pou sto,' said -Archimedes. 'Give me a fulcrum, and I shall move the world!' To do -once, is the fulcrum whereby child brain become man brain. And until -he have the purpose to do more, he continue to do the same again every -time, just as he have done before! Oh, my dear, I see that your eyes -are opened, and that to you the lightning flash show all the leagues," -for Mrs. Harker began to clap her hands and her eyes sparkled. - -He went on, "Now you shall speak. Tell us two dry men of science what -you see with those so bright eyes." He took her hand and held it -whilst he spoke. His finger and thumb closed on her pulse, as I -thought instinctively and unconsciously, as she spoke. - -"The Count is a criminal and of criminal type. Nordau and Lombroso -would so classify him, and qua criminal he is of an imperfectly formed -mind. Thus, in a difficulty he has to seek resource in habit. His -past is a clue, and the one page of it that we know, and that from his -own lips, tells that once before, when in what Mr. Morris would call -a 'tight place,' he went back to his own country from the land he had -tried to invade, and thence, without losing purpose, prepared himself -for a new effort. He came again better equipped for his work, and -won. So he came to London to invade a new land. He was beaten, and -when all hope of success was lost, and his existence in danger, he -fled back over the sea to his home. Just as formerly he had fled back -over the Danube from Turkey Land." - -"Good, good! Oh, you so clever lady!" said Van Helsing, -enthusiastically, as he stooped and kissed her hand. A moment later -he said to me, as calmly as though we had been having a sick room -consultation, "Seventy-two only, and in all this excitement. I have -hope." - -Turning to her again, he said with keen expectation, "But go on. Go -on! There is more to tell if you will. Be not afraid. John and I -know. I do in any case, and shall tell you if you are right. Speak, -without fear!" - -"I will try to. But you will forgive me if I seem too egotistical." - -"Nay! Fear not, you must be egotist, for it is of you that we think." - -"Then, as he is criminal he is selfish. And as his intellect is small -and his action is based on selfishness, he confines himself to one -purpose. That purpose is remorseless. As he fled back over the -Danube, leaving his forces to be cut to pieces, so now he is intent on -being safe, careless of all. So his own selfishness frees my soul -somewhat from the terrible power which he acquired over me on that -dreadful night. I felt it! Oh, I felt it! Thank God, for His great -mercy! My soul is freer than it has been since that awful hour. And -all that haunts me is a fear lest in some trance or dream he may have -used my knowledge for his ends." - -The Professor stood up, "He has so used your mind, and by it he has -left us here in Varna, whilst the ship that carried him rushed through -enveloping fog up to Galatz, where, doubtless, he had made preparation -for escaping from us. But his child mind only saw so far. And it may -be that as ever is in God's Providence, the very thing that the evil -doer most reckoned on for his selfish good, turns out to be his -chiefest harm. The hunter is taken in his own snare, as the great -Psalmist says. For now that he think he is free from every trace of -us all, and that he has escaped us with so many hours to him, then his -selfish child brain will whisper him to sleep. He think, too, that as -he cut himself off from knowing your mind, there can be no knowledge -of him to you. There is where he fail! That terrible baptism of -blood which he give you makes you free to go to him in spirit, as you -have as yet done in your times of freedom, when the sun rise and set. -At such times you go by my volition and not by his. And this power to -good of you and others, you have won from your suffering at his hands. -This is now all more precious that he know it not, and to guard -himself have even cut himself off from his knowledge of our where. -We, however, are not selfish, and we believe that God is with us -through all this blackness, and these many dark hours. We shall -follow him, and we shall not flinch, even if we peril ourselves that -we become like him. Friend John, this has been a great hour, and it -have done much to advance us on our way. You must be scribe and write -him all down, so that when the others return from their work you can -give it to them, then they shall know as we do." - -And so I have written it whilst we wait their return, and Mrs. Harker -has written with the typewriter all since she brought the MS to us. - - - - -CHAPTER 26 - - -DR. SEWARD'S DIARY - -29 October.--This is written in the train from Varna to Galatz. Last -night we all assembled a little before the time of sunset. Each of us -had done his work as well as he could, so far as thought, and -endeavour, and opportunity go, we are prepared for the whole of our -journey, and for our work when we get to Galatz. When the usual time -came round Mrs. Harker prepared herself for her hypnotic effort, and -after a longer and more serious effort on the part of Van Helsing than -has been usually necessary, she sank into the trance. Usually she -speaks on a hint, but this time the Professor had to ask her -questions, and to ask them pretty resolutely, before we could learn -anything. At last her answer came. - -"I can see nothing. We are still. There are no waves lapping, but -only a steady swirl of water softly running against the hawser. I can -hear men's voices calling, near and far, and the roll and creak of -oars in the rowlocks. A gun is fired somewhere, the echo of it seems -far away. There is tramping of feet overhead, and ropes and chains -are dragged along. What is this? There is a gleam of light. I can -feel the air blowing upon me." - -Here she stopped. She had risen, as if impulsively, from where she -lay on the sofa, and raised both her hands, palms upwards, as if -lifting a weight. Van Helsing and I looked at each other with -understanding. Quincey raised his eyebrows slightly and looked at her -intently, whilst Harker's hand instinctively closed round the hilt of -his Kukri. There was a long pause. We all knew that the time when -she could speak was passing, but we felt that it was useless to say -anything. - -Suddenly she sat up, and as she opened her eyes said sweetly, "Would -none of you like a cup of tea? You must all be so tired!" - -We could only make her happy, and so acqueisced. She bustled off to -get tea. When she had gone Van Helsing said, "You see, my friends. He -is close to land. He has left his earth chest. But he has yet to get -on shore. In the night he may lie hidden somewhere, but if he be not -carried on shore, or if the ship do not touch it, he cannot achieve -the land. In such case he can, if it be in the night, change his form -and jump or fly on shore, then, unless he be carried he cannot escape. -And if he be carried, then the customs men may discover what the box -contain. Thus, in fine, if he escape not on shore tonight, or before -dawn, there will be the whole day lost to him. We may then arrive in -time. For if he escape not at night we shall come on him in daytime, -boxed up and at our mercy. For he dare not be his true self, awake -and visible, lest he be discovered." - -There was no more to be said, so we waited in patience until the dawn, -at which time we might learn more from Mrs. Harker. - -Early this morning we listened, with breathless anxiety, for her -response in her trance. The hypnotic stage was even longer in coming -than before, and when it came the time remaining until full sunrise -was so short that we began to despair. Van Helsing seemed to throw -his whole soul into the effort. At last, in obedience to his will she -made reply. - -"All is dark. I hear lapping water, level with me, and some creaking -as of wood on wood." She paused, and the red sun shot up. We must -wait till tonight. - -And so it is that we are travelling towards Galatz in an agony of -expectation. We are due to arrive between two and three in the -morning. But already, at Bucharest, we are three hours late, so we -cannot possibly get in till well after sunup. Thus we shall have two -more hypnotic messages from Mrs. Harker! Either or both may possibly -throw more light on what is happening. - - -Later.--Sunset has come and gone. Fortunately it came at a time when -there was no distraction. For had it occurred whilst we were at a -station, we might not have secured the necessary calm and isolation. -Mrs. Harker yielded to the hypnotic influence even less readily than -this morning. I am in fear that her power of reading the Count's -sensations may die away, just when we want it most. It seems to me -that her imagination is beginning to work. Whilst she has been in the -trance hitherto she has confined herself to the simplest of facts. If -this goes on it may ultimately mislead us. If I thought that the -Count's power over her would die away equally with her power of -knowledge it would be a happy thought. But I am afraid that it may -not be so. - -When she did speak, her words were enigmatical, "Something is going -out. I can feel it pass me like a cold wind. I can hear, far off, -confused sounds, as of men talking in strange tongues, fierce falling -water, and the howling of wolves." She stopped and a shudder ran -through her, increasing in intensity for a few seconds, till at the -end, she shook as though in a palsy. She said no more, even in answer -to the Professor's imperative questioning. When she woke from the -trance, she was cold, and exhausted, and languid, but her mind was all -alert. She could not remember anything, but asked what she had said. -When she was told, she pondered over it deeply for a long time and in -silence. - - -30 October, 7 A.M.--We are near Galatz now, and I may not have time to -write later. Sunrise this morning was anxiously looked for by us all. -Knowing of the increasing difficulty of procuring the hypnotic trance, -Van Helsing began his passes earlier than usual. They produced no -effect, however, until the regular time, when she yielded with a still -greater difficulty, only a minute before the sun rose. The Professor -lost no time in his questioning. - -Her answer came with equal quickness, "All is dark. I hear water -swirling by, level with my ears, and the creaking of wood on wood. -Cattle low far off. There is another sound, a queer one like . . ." -She stopped and grew white, and whiter still. - -"Go on, go on! Speak, I command you!" said Van Helsing in an agonized -voice. At the same time there was despair in his eyes, for the risen -sun was reddening even Mrs. Harker's pale face. She opened her eyes, -and we all started as she said, sweetly and seemingly with the utmost -unconcern. - -"Oh, Professor, why ask me to do what you know I can't? I don't -remember anything." Then, seeing the look of amazement on our faces, -she said, turning from one to the other with a troubled look, "What -have I said? What have I done? I know nothing, only that I was lying -here, half asleep, and heard you say 'go on! speak, I command you!' It -seemed so funny to hear you order me about, as if I were a bad child!" - -"Oh, Madam Mina," he said, sadly, "it is proof, if proof be needed, of -how I love and honour you, when a word for your good, spoken more -earnest than ever, can seem so strange because it is to order her whom -I am proud to obey!" - -The whistles are sounding. We are nearing Galatz. We are on fire -with anxiety and eagerness. - - - -MINA HARKER'S JOURNAL - -30 October.--Mr. Morris took me to the hotel where our rooms had been -ordered by telegraph, he being the one who could best be spared, since -he does not speak any foreign language. The forces were distributed -much as they had been at Varna, except that Lord Godalming went to the -Vice Consul, as his rank might serve as an immediate guarantee of some -sort to the official, we being in extreme hurry. Jonathan and the two -doctors went to the shipping agent to learn particulars of the arrival -of the Czarina Catherine. - - -Later.--Lord Godalming has returned. The Consul is away, and the Vice -Consul sick. So the routine work has been attended to by a clerk. He -was very obliging, and offered to do anything in his power. - - - -JONATHAN HARKER'S JOURNAL - -30 October.--At nine o'clock Dr. Van Helsing, Dr. Seward, and I called -on Messrs. Mackenzie & Steinkoff, the agents of the London firm of -Hapgood. They had received a wire from London, in answer to Lord -Godalming's telegraphed request, asking them to show us any civility -in their power. They were more than kind and courteous, and took us -at once on board the Czarina Catherine, which lay at anchor out in the -river harbor. There we saw the Captain, Donelson by name, who told us -of his voyage. He said that in all his life he had never had so -favourable a run. - -"Man!" he said, "but it made us afeard, for we expect it that we -should have to pay for it wi' some rare piece o' ill luck, so as to -keep up the average. It's no canny to run frae London to the Black -Sea wi' a wind ahint ye, as though the Deil himself were blawin' on -yer sail for his ain purpose. An' a' the time we could no speer a -thing. Gin we were nigh a ship, or a port, or a headland, a fog fell -on us and travelled wi' us, till when after it had lifted and we -looked out, the deil a thing could we see. We ran by Gibraltar wi' -oot bein' able to signal. An' til we came to the Dardanelles and had -to wait to get our permit to pass, we never were within hail o' -aught. At first I inclined to slack off sail and beat about till the -fog was lifted. But whiles, I thocht that if the Deil was minded to -get us into the Black Sea quick, he was like to do it whether we would -or no. If we had a quick voyage it would be no to our miscredit -wi' the owners, or no hurt to our traffic, an' the Old Mon who had -served his ain purpose wad be decently grateful to us for no hinderin' -him." - -This mixture of simplicity and cunning, of superstition and commercial -reasoning, aroused Van Helsing, who said, "Mine friend, that Devil is -more clever than he is thought by some, and he know when he meet his -match!" - -The skipper was not displeased with the compliment, and went on, "When -we got past the Bosphorus the men began to grumble. Some o' them, the -Roumanians, came and asked me to heave overboard a big box which had -been put on board by a queer lookin' old man just before we had -started frae London. I had seen them speer at the fellow, and put out -their twa fingers when they saw him, to guard them against the evil -eye. Man! but the supersteetion of foreigners is pairfectly -rideeculous! I sent them aboot their business pretty quick, but as -just after a fog closed in on us I felt a wee bit as they did anent -something, though I wouldn't say it was again the big box. Well, on -we went, and as the fog didn't let up for five days I joost let the -wind carry us, for if the Deil wanted to get somewheres, well, he -would fetch it up a'reet. An' if he didn't, well, we'd keep a sharp -lookout anyhow. Sure eneuch, we had a fair way and deep water all the -time. And two days ago, when the mornin' sun came through the fog, we -found ourselves just in the river opposite Galatz. The Roumanians -were wild, and wanted me right or wrong to take out the box and fling -it in the river. I had to argy wi' them aboot it wi' a handspike. An' -when the last o' them rose off the deck wi' his head in his hand, I -had convinced them that, evil eye or no evil eye, the property and the -trust of my owners were better in my hands than in the river Danube. -They had, mind ye, taken the box on the deck ready to fling in, and as -it was marked Galatz via Varna, I thocht I'd let it lie till we -discharged in the port an' get rid o't althegither. We didn't do much -clearin' that day, an' had to remain the nicht at anchor. But in the -mornin', braw an' airly, an hour before sunup, a man came aboard wi' -an order, written to him from England, to receive a box marked for one -Count Dracula. Sure eneuch the matter was one ready to his hand. He -had his papers a' reet, an' glad I was to be rid o' the dam' thing, -for I was beginnin' masel' to feel uneasy at it. If the Deil did have -any luggage aboord the ship, I'm thinkin' it was nane ither than that -same!" - -"What was the name of the man who took it?" asked Dr. Van Helsing with -restrained eagerness. - -"I'll be tellin' ye quick!" he answered, and stepping down to his -cabin, produced a receipt signed "Immanuel Hildesheim." Burgen-strasse -16 was the address. We found out that this was all the Captain knew, -so with thanks we came away. - -We found Hildesheim in his office, a Hebrew of rather the Adelphi -Theatre type, with a nose like a sheep, and a fez. His arguments were -pointed with specie, we doing the punctuation, and with a little -bargaining he told us what he knew. This turned out to be simple but -important. He had received a letter from Mr. de Ville of London, -telling him to receive, if possible before sunrise so as to avoid -customs, a box which would arrive at Galatz in the Czarina Catherine. -This he was to give in charge to a certain Petrof Skinsky, who dealt -with the Slovaks who traded down the river to the port. He had been -paid for his work by an English bank note, which had been duly cashed -for gold at the Danube International Bank. When Skinsky had come to -him, he had taken him to the ship and handed over the box, so as to -save porterage. That was all he knew. - -We then sought for Skinsky, but were unable to find him. One of his -neighbors, who did not seem to bear him any affection, said that he -had gone away two days before, no one knew whither. This was -corroborated by his landlord, who had received by messenger the key of -the house together with the rent due, in English money. This had been -between ten and eleven o'clock last night. We were at a standstill -again. - -Whilst we were talking one came running and breathlessly gasped out -that the body of Skinsky had been found inside the wall of the -churchyard of St. Peter, and that the throat had been torn open as if -by some wild animal. Those we had been speaking with ran off to see -the horror, the women crying out. "This is the work of a Slovak!" We -hurried away lest we should have been in some way drawn into the -affair, and so detained. - -As we came home we could arrive at no definite conclusion. We were -all convinced that the box was on its way, by water, to somewhere, but -where that might be we would have to discover. With heavy hearts we -came home to the hotel to Mina. - -When we met together, the first thing was to consult as to taking Mina -again into our confidence. Things are getting desperate, and it is at -least a chance, though a hazardous one. As a preliminary step, I was -released from my promise to her. - - - - - -MINA HARKER'S JOURNAL - -30 October, evening.--They were so tired and worn out and dispirited -that there was nothing to be done till they had some rest, so I asked -them all to lie down for half an hour whilst I should enter everything -up to the moment. I feel so grateful to the man who invented the -"Traveller's" typewriter, and to Mr. Morris for getting this one for -me. I should have felt quite astray doing the work if I had to write -with a pen . . . - -It is all done. Poor dear, dear Jonathan, what he must have suffered, -what he must be suffering now. He lies on the sofa hardly seeming to -breathe, and his whole body appears in collapse. His brows are knit. -His face is drawn with pain. Poor fellow, maybe he is thinking, and I -can see his face all wrinkled up with the concentration of his -thoughts. Oh! if I could only help at all. I shall do what I can. - -I have asked Dr. Van Helsing, and he has got me all the papers that I -have not yet seen. Whilst they are resting, I shall go over all -carefully, and perhaps I may arrive at some conclusion. I shall try -to follow the Professor's example, and think without prejudice on the -facts before me . . . - -I do believe that under God's providence I have made a discovery. I -shall get the maps and look over them. - -I am more than ever sure that I am right. My new conclusion is ready, -so I shall get our party together and read it. They can judge it. It -is well to be accurate, and every minute is precious. - - - -MINA HARKER'S MEMORANDUM - -(ENTERED IN HER JOURNAL) - - -Ground of inquiry.--Count Dracula's problem is to get back -to his own place. - -(a) He must be brought back by some one. This is evident; -for had he power to move himself as he wished he could go -either as man, or wolf, or bat, or in some other way. He -evidently fears discovery or interference, in the state of -helplessness in which he must be, confined as he is between -dawn and sunset in his wooden box. - -(b) How is he to be taken?--Here a process of exclusions may -help us. By road, by rail, by water? - -1. By Road.--There are endless difficulties, especially in -leaving the city. - -(x) There are people. And people are curious, and -investigate. A hint, a surmise, a doubt as to what might -be in the box, would destroy him. - -(y) There are, or there may be, customs and octroi officers -to pass. - -(z) His pursuers might follow. This is his highest fear. -And in order to prevent his being betrayed he has repelled, -so far as he can, even his victim, me! - -2. By Rail.--There is no one in charge of the box. It -would have to take its chance of being delayed, and delay -would be fatal, with enemies on the track. True, he might -escape at night. But what would he be, if left in a strange -place with no refuge that he could fly to? This is not what he -intends, and he does not mean to risk it. - -3. By Water.--Here is the safest way, in one respect, but -with most danger in another. On the water he is powerless -except at night. Even then he can only summon fog and storm and -snow and his wolves. But were he wrecked, the living water would -engulf him, helpless, and he would indeed be lost. He could have -the vessel drive to land, but if it were unfriendly land, wherein -he was not free to move, his position would still be desperate. - -We know from the record that he was on the water, so what -we have to do is to ascertain what water. - -The first thing is to realize exactly what he has done as -yet. We may, then, get a light on what his task is to be. - -Firstly.--We must differentiate between what he did in -London as part of his general plan of action, when he was -pressed for moments and had to arrange as best he could. - -Secondly.--We must see, as well as we can surmise it from the -facts we know of, what he has done here. - -As to the first, he evidently intended to arrive at Galatz, -and sent invoice to Varna to deceive us lest we should ascertain -his means of exit from England. His immediate and sole purpose -then was to escape. The proof of this, is the letter of -instructions sent to Immanuel Hildesheim to clear and take away -the box before sunrise. There is also the instruction to Petrof -Skinsky. These we must only guess at, but there must have been -some letter or message, since Skinsky came to Hildesheim. - -That, so far, his plans were successful we know. The Czarina -Catherine made a phenomenally quick journey. So much so that -Captain Donelson's suspicions were aroused. But his superstition -united with his canniness played the Count's game for him, and he -ran with his favouring wind through fogs and all till he brought -up blindfold at Galatz. That the Count's arrangements were well -made, has been proved. Hildesheim cleared the box, took it off, -and gave it to Skinsky. Skinsky took it, and here we lose the -trail. We only know that the box is somewhere on the water, -moving along. The customs and the octroi, if there be any, have -been avoided. - -Now we come to what the Count must have done after his -arrival, on land, at Galatz. - -The box was given to Skinsky before sunrise. At sunrise -the Count could appear in his own form. Here, we ask why -Skinsky was chosen at all to aid in the work? In my husband's -diary, Skinsky is mentioned as dealing with the Slovaks who trade -down the river to the port. And the man's remark, that the -murder was the work of a Slovak, showed the general feeling -against his class. The Count wanted isolation. - -My surmise is this, that in London the Count decided to get -back to his castle by water, as the most safe and secret -way. He was brought from the castle by Szgany, and probably they -delivered their cargo to Slovaks who took the boxes to Varna, for -there they were shipped to London. Thus the Count had knowledge -of the persons who could arrange this service. When the box was -on land, before sunrise or after sunset, he came out from his -box, met Skinsky and instructed him what to do as to arranging -the carriage of the box up some river. When this was done, and -he knew that all was in train, he blotted out his traces, as he -thought, by murdering his agent. - -I have examined the map and find that the river most -suitable for the Slovaks to have ascended is either the -Pruth or the Sereth. I read in the typescript that in my -trance I heard cows low and water swirling level with my -ears and the creaking of wood. The Count in his box, then, -was on a river in an open boat, propelled probably either -by oars or poles, for the banks are near and it is working -against stream. There would be no such if floating down -stream. - -Of course it may not be either the Sereth or the Pruth, but -we may possibly investigate further. Now of these two, the -Pruth is the more easily navigated, but the Sereth is, at -Fundu, joined by the Bistritza which runs up round the Borgo -Pass. The loop it makes is manifestly as close to Dracula's -castle as can be got by water. - - - -MINA HARKER'S JOURNAL--CONTINUED - -When I had done reading, Jonathan took me in his arms and kissed me. -The others kept shaking me by both hands, and Dr. Van Helsing said, -"Our dear Madam Mina is once more our teacher. Her eyes have been -where we were blinded. Now we are on the track once again, and this -time we may succeed. Our enemy is at his most helpless. And if we -can come on him by day, on the water, our task will be over. He has a -start, but he is powerless to hasten, as he may not leave this box -lest those who carry him may suspect. For them to suspect would be to -prompt them to throw him in the stream where he perish. This he -knows, and will not. Now men, to our Council of War, for here and -now, we must plan what each and all shall do." - -"I shall get a steam launch and follow him," said Lord Godalming. - -"And I, horses to follow on the bank lest by chance he land," said Mr. -Morris. - -"Good!" said the Professor, "both good. But neither must go alone. -There must be force to overcome force if need be. The Slovak is -strong and rough, and he carries rude arms." All the men smiled, for -amongst them they carried a small arsenal. - -Said Mr. Morris, "I have brought some Winchesters. They are pretty -handy in a crowd, and there may be wolves. The Count, if you -remember, took some other precautions. He made some requisitions on -others that Mrs. Harker could not quite hear or understand. We must -be ready at all points." - -Dr. Seward said, "I think I had better go with Quincey. We have been -accustomed to hunt together, and we two, well armed, will be a match -for whatever may come along. You must not be alone, Art. It may be -necessary to fight the Slovaks, and a chance thrust, for I don't -suppose these fellows carry guns, would undo all our plans. There -must be no chances, this time. We shall not rest until the Count's -head and body have been separated, and we are sure that he cannot -reincarnate." - -He looked at Jonathan as he spoke, and Jonathan looked at me. I could -see that the poor dear was torn about in his mind. Of course he -wanted to be with me. But then the boat service would, most likely, -be the one which would destroy the . . . the . . . Vampire. (Why did -I hesitate to write the word?) - -He was silent awhile, and during his silence Dr. Van Helsing spoke, -"Friend Jonathan, this is to you for twice reasons. First, because -you are young and brave and can fight, and all energies may be needed -at the last. And again that it is your right to destroy him. That, -which has wrought such woe to you and yours. Be not afraid for Madam -Mina. She will be my care, if I may. I am old. My legs are not so -quick to run as once. And I am not used to ride so long or to pursue -as need be, or to fight with lethal weapons. But I can be of other -service. I can fight in other way. And I can die, if need be, as -well as younger men. Now let me say that what I would is this. While -you, my Lord Godalming and friend Jonathan go in your so swift little -steamboat up the river, and whilst John and Quincey guard the bank -where perchance he might be landed, I will take Madam Mina right into -the heart of the enemy's country. Whilst the old fox is tied in his -box, floating on the running stream whence he cannot escape to land, -where he dares not raise the lid of his coffin box lest his Slovak -carriers should in fear leave him to perish, we shall go in the track -where Jonathan went, from Bistritz over the Borgo, and find our way to -the Castle of Dracula. Here, Madam Mina's hypnotic power will surely -help, and we shall find our way, all dark and unknown otherwise, after -the first sunrise when we are near that fateful place. There is much -to be done, and other places to be made sanctify, so that that nest of -vipers be obliterated." - -Here Jonathan interrupted him hotly, "Do you mean to say, Professor -Van Helsing, that you would bring Mina, in her sad case and tainted as -she is with that devil's illness, right into the jaws of his -deathtrap? Not for the world! Not for Heaven or Hell!" - -He became almost speechless for a minute, and then went on, "Do you -know what the place is? Have you seen that awful den of hellish -infamy, with the very moonlight alive with grisly shapes, and every -speck of dust that whirls in the wind a devouring monster in embryo? -Have you felt the Vampire's lips upon your throat?" - -Here he turned to me, and as his eyes lit on my forehead he threw up -his arms with a cry, "Oh, my God, what have we done to have this -terror upon us?" and he sank down on the sofa in a collapse of misery. - -The Professor's voice, as he spoke in clear, sweet tones, which seemed -to vibrate in the air, calmed us all. - -"Oh, my friend, it is because I would save Madam Mina from that awful -place that I would go. God forbid that I should take her into that -place. There is work, wild work, to be done before that place can be -purify. Remember that we are in terrible straits. If the Count -escape us this time, and he is strong and subtle and cunning, he may -choose to sleep him for a century, and then in time our dear one," he -took my hand, "would come to him to keep him company, and would be as -those others that you, Jonathan, saw. You have told us of their -gloating lips. You heard their ribald laugh as they clutched the -moving bag that the Count threw to them. You shudder, and well may it -be. Forgive me that I make you so much pain, but it is necessary. My -friend, is it not a dire need for that which I am giving, possibly my -life? If it were that any one went into that place to stay, it is I -who would have to go to keep them company." - -"Do as you will," said Jonathan, with a sob that shook him all over, -"we are in the hands of God!" - - -Later.--Oh, it did me good to see the way that these brave men worked. -How can women help loving men when they are so earnest, and so true, -and so brave! And, too, it made me think of the wonderful power of -money! What can it not do when basely used. I felt so thankful that -Lord Godalming is rich, and both he and Mr. Morris, who also has -plenty of money, are willing to spend it so freely. For if they did -not, our little expedition could not start, either so promptly or so -well equipped, as it will within another hour. It is not three hours -since it was arranged what part each of us was to do. And now Lord -Godalming and Jonathan have a lovely steam launch, with steam up ready -to start at a moment's notice. Dr. Seward and Mr. Morris have half a -dozen good horses, well appointed. We have all the maps and -appliances of various kinds that can be had. Professor Van Helsing -and I are to leave by the 11:40 train tonight for Veresti, where we -are to get a carriage to drive to the Borgo Pass. We are bringing a -good deal of ready money, as we are to buy a carriage and horses. We -shall drive ourselves, for we have no one whom we can trust in the -matter. The Professor knows something of a great many languages, so -we shall get on all right. We have all got arms, even for me a large -bore revolver. Jonathan would not be happy unless I was armed like -the rest. Alas! I cannot carry one arm that the rest do, the scar on -my forehead forbids that. Dear Dr. Van Helsing comforts me by telling -me that I am fully armed as there may be wolves. The weather is -getting colder every hour, and there are snow flurries which come and -go as warnings. - - -Later.--It took all my courage to say goodbye to my darling. We may -never meet again. Courage, Mina! The Professor is looking at you -keenly. His look is a warning. There must be no tears now, unless it -may be that God will let them fall in gladness. - - - -JONATHAN HARKER'S JOURNAL - -30 October, night.--I am writing this in the light from the furnace -door of the steam launch. Lord Godalming is firing up. He is an -experienced hand at the work, as he has had for years a launch of his -own on the Thames, and another on the Norfolk Broads. Regarding our -plans, we finally decided that Mina's guess was correct, and that if -any waterway was chosen for the Count's escape back to his Castle, the -Sereth and then the Bistritza at its junction, would be the one. We -took it, that somewhere about the 47th degree, north latitude, would -be the place chosen for crossing the country between the river and the -Carpathians. We have no fear in running at good speed up the river at -night. There is plenty of water, and the banks are wide enough apart -to make steaming, even in the dark, easy enough. Lord Godalming tells -me to sleep for a while, as it is enough for the present for one to be -on watch. But I cannot sleep, how can I with the terrible danger -hanging over my darling, and her going out into that awful place . . . - -My only comfort is that we are in the hands of God. Only for that -faith it would be easier to die than to live, and so be quit of all -the trouble. Mr. Morris and Dr. Seward were off on their long ride -before we started. They are to keep up the right bank, far enough off -to get on higher lands where they can see a good stretch of river and -avoid the following of its curves. They have, for the first stages, -two men to ride and lead their spare horses, four in all, so as not to -excite curiosity. When they dismiss the men, which shall be shortly, -they shall themselves look after the horses. It may be necessary for -us to join forces. If so they can mount our whole party. One of the -saddles has a moveable horn, and can be easily adapted for Mina, if -required. - -It is a wild adventure we are on. Here, as we are rushing along -through the darkness, with the cold from the river seeming to rise up -and strike us, with all the mysterious voices of the night around us, -it all comes home. We seem to be drifting into unknown places and -unknown ways. Into a whole world of dark and dreadful things. -Godalming is shutting the furnace door . . . - - -31 October.--Still hurrying along. The day has come, and Godalming is -sleeping. I am on watch. The morning is bitterly cold, the furnace -heat is grateful, though we have heavy fur coats. As yet we have -passed only a few open boats, but none of them had on board any box or -package of anything like the size of the one we seek. The men were -scared every time we turned our electric lamp on them, and fell on -their knees and prayed. - - -1 November, evening.--No news all day. We have found nothing of the -kind we seek. We have now passed into the Bistritza, and if we are -wrong in our surmise our chance is gone. We have overhauled every -boat, big and little. Early this morning, one crew took us for a -Government boat, and treated us accordingly. We saw in this a way of -smoothing matters, so at Fundu, where the Bistritza runs into the -Sereth, we got a Roumanian flag which we now fly conspicuously. With -every boat which we have overhauled since then this trick has -succeeded. We have had every deference shown to us, and not once any -objection to whatever we chose to ask or do. Some of the Slovaks tell -us that a big boat passed them, going at more than usual speed as she -had a double crew on board. This was before they came to Fundu, so -they could not tell us whether the boat turned into the Bistritza or -continued on up the Sereth. At Fundu we could not hear of any such -boat, so she must have passed there in the night. I am feeling very -sleepy. The cold is perhaps beginning to tell upon me, and nature -must have rest some time. Godalming insists that he shall keep the -first watch. God bless him for all his goodness to poor dear Mina and -me. - - -2 November, morning.--It is broad daylight. That good fellow would -not wake me. He says it would have been a sin to, for I slept -peacefully and was forgetting my trouble. It seems brutally selfish -to me to have slept so long, and let him watch all night, but he was -quite right. I am a new man this morning. And, as I sit here and -watch him sleeping, I can do all that is necessary both as to minding -the engine, steering, and keeping watch. I can feel that my strength -and energy are coming back to me. I wonder where Mina is now, and Van -Helsing. They should have got to Veresti about noon on Wednesday. It -would take them some time to get the carriage and horses. So if they -had started and travelled hard, they would be about now at the Borgo -Pass. God guide and help them! I am afraid to think what may -happen. If we could only go faster. But we cannot. The engines are -throbbing and doing their utmost. I wonder how Dr. Seward and Mr. -Morris are getting on. There seem to be endless streams running down -the mountains into this river, but as none of them are very large, at -present, at all events, though they are doubtless terrible in winter -and when the snow melts, the horsemen may not have met much -obstruction. I hope that before we get to Strasba we may see them. -For if by that time we have not overtaken the Count, it may be -necessary to take counsel together what to do next. - - - - - -DR. SEWARD'S DIARY - -2 November.--Three days on the road. No news, and no time to write it -if there had been, for every moment is precious. We have had only the -rest needful for the horses. But we are both bearing it wonderfully. -Those adventurous days of ours are turning up useful. We must push -on. We shall never feel happy till we get the launch in sight again. - - -3 November.--We heard at Fundu that the launch had gone up the -Bistritza. I wish it wasn't so cold. There are signs of snow coming. -And if it falls heavy it will stop us. In such case we must get a -sledge and go on, Russian fashion. - -4 November.--Today we heard of the launch having been detained by an -accident when trying to force a way up the rapids. The Slovak boats -get up all right, by aid of a rope and steering with knowledge. Some -went up only a few hours before. Godalming is an amateur fitter -himself, and evidently it was he who put the launch in trim again. - -Finally, they got up the rapids all right, with local help, and are off -on the chase afresh. I fear that the boat is not any better for the -accident, the peasantry tell us that after she got upon smooth water -again, she kept stopping every now and again so long as she was in -sight. We must push on harder than ever. Our help may be wanted -soon. - - - - - -MINA HARKER'S JOURNAL - -31 October.--Arrived at Veresti at noon. The Professor tells me that -this morning at dawn he could hardly hypnotize me at all, and that all -I could say was, "dark and quiet." He is off now buying a carriage -and horses. He says that he will later on try to buy additional -horses, so that we may be able to change them on the way. We have -something more than 70 miles before us. The country is lovely, and -most interesting. If only we were under different conditions, how -delightful it would be to see it all. If Jonathan and I were driving -through it alone what a pleasure it would be. To stop and see people, -and learn something of their life, and to fill our minds and memories -with all the colour and picturesqueness of the whole wild, beautiful -country and the quaint people! But, alas! - - -Later.--Dr. Van Helsing has returned. He has got the carriage and -horses. We are to have some dinner, and to start in an hour. The -landlady is putting us up a huge basket of provisions. It seems -enough for a company of soldiers. The Professor encourages her, and -whispers to me that it may be a week before we can get any food again. -He has been shopping too, and has sent home such a wonderful lot of -fur coats and wraps, and all sorts of warm things. There will not be -any chance of our being cold. - -We shall soon be off. I am afraid to think what may happen to us. We -are truly in the hands of God. He alone knows what may be, and I pray -Him, with all the strength of my sad and humble soul, that He will -watch over my beloved husband. That whatever may happen, Jonathan may -know that I loved him and honoured him more than I can say, and that my -latest and truest thought will be always for him. - - - - -CHAPTER 27 - - -MINA HARKER'S JOURNAL - -1 November.--All day long we have travelled, and at a good speed. The -horses seem to know that they are being kindly treated, for they go -willingly their full stage at best speed. We have now had so many -changes and find the same thing so constantly that we are encouraged -to think that the journey will be an easy one. Dr. Van Helsing is -laconic, he tells the farmers that he is hurrying to Bistritz, and -pays them well to make the exchange of horses. We get hot soup, or -coffee, or tea, and off we go. It is a lovely country. Full of -beauties of all imaginable kinds, and the people are brave, and -strong, and simple, and seem full of nice qualities. They are very, -very superstitious. In the first house where we stopped, when the -woman who served us saw the scar on my forehead, she crossed herself -and put out two fingers towards me, to keep off the evil eye. I -believe they went to the trouble of putting an extra amount of garlic -into our food, and I can't abide garlic. Ever since then I have taken -care not to take off my hat or veil, and so have escaped their -suspicions. We are travelling fast, and as we have no driver with us -to carry tales, we go ahead of scandal. But I daresay that fear of -the evil eye will follow hard behind us all the way. The Professor -seems tireless. All day he would not take any rest, though he made me -sleep for a long spell. At sunset time he hypnotized me, and he says -I answered as usual, "darkness, lapping water and creaking wood." So -our enemy is still on the river. I am afraid to think of Jonathan, -but somehow I have now no fear for him, or for myself. I write this -whilst we wait in a farmhouse for the horses to be ready. Dr. Van -Helsing is sleeping. Poor dear, he looks very tired and old and grey, -but his mouth is set as firmly as a conqueror's. Even in his sleep he -is intense with resolution. When we have well started I must make him -rest whilst I drive. I shall tell him that we have days before us, -and he must not break down when most of all his strength will be -needed . . . All is ready. We are off shortly. - - -2 November, morning.--I was successful, and we took turns driving all -night. Now the day is on us, bright though cold. There is a strange -heaviness in the air. I say heaviness for want of a better word. I -mean that it oppresses us both. It is very cold, and only our warm -furs keep us comfortable. At dawn Van Helsing hypnotized me. He says -I answered "darkness, creaking wood and roaring water," so the river -is changing as they ascend. I do hope that my darling will not run -any chance of danger, more than need be, but we are in God's hands. - - -2 November, night.--All day long driving. The country gets wilder as -we go, and the great spurs of the Carpathians, which at Veresti seemed -so far from us and so low on the horizon, now seem to gather round us -and tower in front. We both seem in good spirits. I think we make an -effort each to cheer the other, in the doing so we cheer ourselves. -Dr. Van Helsing says that by morning we shall reach the Borgo Pass. -The houses are very few here now, and the Professor says that the last -horse we got will have to go on with us, as we may not be able to -change. He got two in addition to the two we changed, so that now we -have a rude four-in-hand. The dear horses are patient and good, and -they give us no trouble. We are not worried with other travellers, -and so even I can drive. We shall get to the Pass in daylight. We do -not want to arrive before. So we take it easy, and have each a long -rest in turn. Oh, what will tomorrow bring to us? We go to seek the -place where my poor darling suffered so much. God grant that we may -be guided aright, and that He will deign to watch over my husband and -those dear to us both, and who are in such deadly peril. As for me, I -am not worthy in His sight. Alas! I am unclean to His eyes, and -shall be until He may deign to let me stand forth in His sight as one -of those who have not incurred His wrath. - - - - - -MEMORANDUM BY ABRAHAM VAN HELSING - -4 November.--This to my old and true friend John Seward, M.D., -of Purfleet, London, in case I may not see him. It may -explain. It is morning, and I write by a fire which all -the night I have kept alive, Madam Mina aiding me. It is -cold, cold. So cold that the grey heavy sky is full of -snow, which when it falls will settle for all winter as the -ground is hardening to receive it. It seems to have affected -Madam Mina. She has been so heavy of head all day that she was -not like herself. She sleeps, and sleeps, and sleeps! She who -is usual so alert, have done literally nothing all the day. She -even have lost her appetite. She make no entry into her little -diary, she who write so faithful at every pause. Something -whisper to me that all is not well. However, tonight she is more -_vif_. Her long sleep all day have refresh and restore her, for -now she is all sweet and bright as ever. At sunset I try to -hypnotize her, but alas! with no effect. The power has grown -less and less with each day, and tonight it fail me altogether. -Well, God's will be done, whatever it may be, and whithersoever -it may lead! - -Now to the historical, for as Madam Mina write not in her -stenography, I must, in my cumbrous old fashion, that so -each day of us may not go unrecorded. - -We got to the Borgo Pass just after sunrise yesterday -morning. When I saw the signs of the dawn I got ready for -the hypnotism. We stopped our carriage, and got down so -that there might be no disturbance. I made a couch with -furs, and Madam Mina, lying down, yield herself as usual, -but more slow and more short time than ever, to the hypnotic -sleep. As before, came the answer, "darkness and the swirling of -water." Then she woke, bright and radiant and we go on our way -and soon reach the Pass. At this time and place, she become all -on fire with zeal. Some new guiding power be in her manifested, -for she point to a road and say, "This is the way." - -"How know you it?" I ask. - -"Of course I know it," she answer, and with a pause, add, -"Have not my Jonathan travelled it and wrote of his travel?" - -At first I think somewhat strange, but soon I see that there be -only one such byroad. It is used but little, and very different -from the coach road from the Bukovina to Bistritz, which is more -wide and hard, and more of use. - -So we came down this road. When we meet other ways, not -always were we sure that they were roads at all, for they -be neglect and light snow have fallen, the horses know and -they only. I give rein to them, and they go on so patient. By -and by we find all the things which Jonathan have note in that -wonderful diary of him. Then we go on for long, long hours and -hours. At the first, I tell Madam Mina to sleep. She try, and -she succeed. She sleep all the time, till at the last, I feel -myself to suspicious grow, and attempt to wake her. But she -sleep on, and I may not wake her though I try. I do not wish to -try too hard lest I harm her. For I know that she have suffer -much, and sleep at times be all-in-all to her. I think I drowse -myself, for all of sudden I feel guilt, as though I have done -something. I find myself bolt up, with the reins in my hand, and -the good horses go along jog, jog, just as ever. I look down and -find Madam Mina still asleep. It is now not far off sunset time, -and over the snow the light of the sun flow in big yellow flood, -so that we throw great long shadow on where the mountain rise so -steep. For we are going up, and up, and all is oh so wild and -rocky, as though it were the end of the world. - -Then I arouse Madam Mina. This time she wake with not much -trouble, and then I try to put her to hypnotic sleep. But -she sleep not, being as though I were not. Still I try and -try, till all at once I find her and myself in dark, so I -look round, and find that the sun have gone down. Madam -Mina laugh, and I turn and look at her. She is now quite -awake, and look so well as I never saw her since that night -at Carfax when we first enter the Count's house. I am amaze, and -not at ease then. But she is so bright and tender and thoughtful -for me that I forget all fear. I light a fire, for we have -brought supply of wood with us, and she prepare food while I undo -the horses and set them, tethered in shelter, to feed. Then when -I return to the fire she have my supper ready. I go to help her, -but she smile, and tell me that she have eat already. That she -was so hungry that she would not wait. I like it not, and I have -grave doubts. But I fear to affright her, and so I am silent of -it. She help me and I eat alone, and then we wrap in fur and lie -beside the fire, and I tell her to sleep while I watch. But -presently I forget all of watching. And when I sudden remember -that I watch, I find her lying quiet, but awake, and looking at -me with so bright eyes. Once, twice more the same occur, and I -get much sleep till before morning. When I wake I try to -hypnotize her, but alas! though she shut her eyes obedient, she -may not sleep. The sun rise up, and up, and up, and then sleep -come to her too late, but so heavy that she will not wake. I -have to lift her up, and place her sleeping in the carriage when -I have harnessed the horses and made all ready. Madam still -sleep, and she look in her sleep more healthy and more redder -than before. And I like it not. And I am afraid, afraid, -afraid! I am afraid of all things, even to think but I must go -on my way. The stake we play for is life and death, or more than -these, and we must not flinch. - - -5 November, morning.--Let me be accurate in everything, for -though you and I have seen some strange things together, -you may at the first think that I, Van Helsing, am mad. -That the many horrors and the so long strain on nerves has -at the last turn my brain. - -All yesterday we travel, always getting closer to the -mountains, and moving into a more and more wild and desert -land. There are great, frowning precipices and much falling -water, and Nature seem to have held sometime her carnival. Madam -Mina still sleep and sleep. And though I did have hunger and -appeased it, I could not waken her, even for food. I began to -fear that the fatal spell of the place was upon her, tainted as -she is with that Vampire baptism. "Well," said I to myself, "if -it be that she sleep all the day, it shall also be that I do not -sleep at night." As we travel on the rough road, for a road of -an ancient and imperfect kind there was, I held down my head and -slept. - -Again I waked with a sense of guilt and of time passed, and -found Madam Mina still sleeping, and the sun low down. But -all was indeed changed. The frowning mountains seemed further -away, and we were near the top of a steep rising hill, on summit -of which was such a castle as Jonathan tell of in his diary. At -once I exulted and feared. For now, for good or ill, the end was -near. - -I woke Madam Mina, and again tried to hypnotize her, but -alas! unavailing till too late. Then, ere the great dark -came upon us, for even after down sun the heavens reflected -the gone sun on the snow, and all was for a time in a great -twilight. I took out the horses and fed them in what shelter I -could. Then I make a fire, and near it I make Madam Mina, now -awake and more charming than ever, sit comfortable amid her rugs. -I got ready food, but she would not eat, simply saying that she -had not hunger. I did not press her, knowing her unavailingness. -But I myself eat, for I must needs now be strong for all. Then, -with the fear on me of what might be, I drew a ring so big for -her comfort, round where Madam Mina sat. And over the ring I -passed some of the wafer, and I broke it fine so that all was -well guarded. She sat still all the time, so still as one dead. -And she grew whiter and even whiter till the snow was not more -pale, and no word she said. But when I drew near, she clung to -me, and I could know that the poor soul shook her from head to -feet with a tremor that was pain to feel. - -I said to her presently, when she had grown more quiet, -"Will you not come over to the fire?" for I wished to make -a test of what she could. She rose obedient, but when she -have made a step she stopped, and stood as one stricken. - -"Why not go on?" I asked. She shook her head, and coming -back, sat down in her place. Then, looking at me with open -eyes, as of one waked from sleep, she said simply, "I cannot!" -and remained silent. I rejoiced, for I knew that what she could -not, none of those that we dreaded could. Though there might be -danger to her body, yet her soul was safe! - -Presently the horses began to scream, and tore at their -tethers till I came to them and quieted them. When they -did feel my hands on them, they whinnied low as in joy, and -licked at my hands and were quiet for a time. Many times -through the night did I come to them, till it arrive to the -cold hour when all nature is at lowest, and every time my -coming was with quiet of them. In the cold hour the fire -began to die, and I was about stepping forth to replenish -it, for now the snow came in flying sweeps and with it a -chill mist. Even in the dark there was a light of some -kind, as there ever is over snow, and it seemed as though -the snow flurries and the wreaths of mist took shape as of -women with trailing garments. All was in dead, grim silence only -that the horses whinnied and cowered, as if in terror of the -worst. I began to fear, horrible fears. But then came to me the -sense of safety in that ring wherein I stood. I began too, to -think that my imaginings were of the night, and the gloom, and -the unrest that I have gone through, and all the terrible -anxiety. It was as though my memories of all Jonathan's horrid -experience were befooling me. For the snow flakes and the mist -began to wheel and circle round, till I could get as though a -shadowy glimpse of those women that would have kissed him. And -then the horses cowered lower and lower, and moaned in terror as -men do in pain. Even the madness of fright was not to them, so -that they could break away. I feared for my dear Madam Mina when -these weird figures drew near and circled round. I looked at her, -but she sat calm, and smiled at me. When I would have stepped to -the fire to replenish it, she caught me and held me back, and -whispered, like a voice that one hears in a dream, so low it was. - -"No! No! Do not go without. Here you are safe!" - -I turned to her, and looking in her eyes said, "But you? -It is for you that I fear!" - -Whereat she laughed, a laugh low and unreal, and said, "Fear -for me! Why fear for me? None safer in all the world from -them than I am," and as I wondered at the meaning of her -words, a puff of wind made the flame leap up, and I see the -red scar on her forehead. Then, alas! I knew. Did I not, -I would soon have learned, for the wheeling figures of mist -and snow came closer, but keeping ever without the Holy -circle. Then they began to materialize till, if God have -not taken away my reason, for I saw it through my eyes. -There were before me in actual flesh the same three women -that Jonathan saw in the room, when they would have kissed -his throat. I knew the swaying round forms, the bright -hard eyes, the white teeth, the ruddy colour, the voluptuous -lips. They smiled ever at poor dear Madam Mina. And as -their laugh came through the silence of the night, they -twined their arms and pointed to her, and said in those so -sweet tingling tones that Jonathan said were of the intolerable -sweetness of the water glasses, "Come, sister. Come to us. -Come!" - -In fear I turned to my poor Madam Mina, and my heart with -gladness leapt like flame. For oh! the terror in her sweet -eyes, the repulsion, the horror, told a story to my heart -that was all of hope. God be thanked she was not, yet, of -them. I seized some of the firewood which was by me, and -holding out some of the Wafer, advanced on them towards the -fire. They drew back before me, and laughed their low horrid -laugh. I fed the fire, and feared them not. For I knew that we -were safe within the ring, which she could not leave no more than -they could enter. The horses had ceased to moan, and lay still -on the ground. The snow fell on them softly, and they grew -whiter. I knew that there was for the poor beasts no more of -terror. - -And so we remained till the red of the dawn began to fall -through the snow gloom. I was desolate and afraid, and -full of woe and terror. But when that beautiful sun began -to climb the horizon life was to me again. At the first -coming of the dawn the horrid figures melted in the whirling -mist and snow. The wreaths of transparent gloom moved away -towards the castle, and were lost. - -Instinctively, with the dawn coming, I turned to Madam Mina, -intending to hypnotize her. But she lay in a deep and sudden -sleep, from which I could not wake her. I tried to hypnotize -through her sleep, but she made no response, none at all, and the -day broke. I fear yet to stir. I have made my fire and have -seen the horses, they are all dead. Today I have much to do here, -and I keep waiting till the sun is up high. For there may be -places where I must go, where that sunlight, though snow and mist -obscure it, will be to me a safety. - -I will strengthen me with breakfast, and then I will do my -terrible work. Madam Mina still sleeps, and God be thanked! She -is calm in her sleep . . . - - - -JONATHAN HARKER'S JOURNAL - -4 November, evening.--The accident to the launch has been a terrible -thing for us. Only for it we should have overtaken the boat long ago, -and by now my dear Mina would have been free. I fear to think of her, -off on the wolds near that horrid place. We have got horses, and we -follow on the track. I note this whilst Godalming is getting ready. -We have our arms. The Szgany must look out if they mean to fight. Oh, -if only Morris and Seward were with us. We must only hope! If I -write no more Goodby Mina! God bless and keep you. - - - -DR. SEWARD'S DIARY - -5 November.--With the dawn we saw the body of Szgany before us dashing -away from the river with their leiter wagon. They surrounded it in a -cluster, and hurried along as though beset. The snow is falling -lightly and there is a strange excitement in the air. It may be our -own feelings, but the depression is strange. Far off I hear the -howling of wolves. The snow brings them down from the mountains, and -there are dangers to all of us, and from all sides. The horses are -nearly ready, and we are soon off. We ride to death of some one. God -alone knows who, or where, or what, or when, or how it may be . . . - - - - - -DR. VAN HELSING'S MEMORANDUM - -5 November, afternoon.--I am at least sane. Thank God for -that mercy at all events, though the proving it has been -dreadful. When I left Madam Mina sleeping within the Holy -circle, I took my way to the castle. The blacksmith hammer -which I took in the carriage from Veresti was useful, though the -doors were all open I broke them off the rusty hinges, lest some -ill intent or ill chance should close them, so that being entered -I might not get out. Jonathan's bitter experience served me -here. By memory of his diary I found my way to the old chapel, -for I knew that here my work lay. The air was oppressive. It -seemed as if there was some sulphurous fume, which at times made -me dizzy. Either there was a roaring in my ears or I heard afar -off the howl of wolves. Then I bethought me of my dear Madam -Mina, and I was in terrible plight. The dilemma had me between -his horns. - -Her, I had not dare to take into this place, but left safe -from the Vampire in that Holy circle. And yet even there -would be the wolf! I resolve me that my work lay here, and -that as to the wolves we must submit, if it were God's will. At -any rate it was only death and freedom beyond. So did I choose -for her. Had it but been for myself the choice had been easy, -the maw of the wolf were better to rest in than the grave of the -Vampire! So I make my choice to go on with my work. - -I knew that there were at least three graves to find, graves -that are inhabit. So I search, and search, and I find one -of them. She lay in her Vampire sleep, so full of life and -voluptuous beauty that I shudder as though I have come to -do murder. Ah, I doubt not that in the old time, when such -things were, many a man who set forth to do such a task as -mine, found at the last his heart fail him, and then his -nerve. So he delay, and delay, and delay, till the mere -beauty and the fascination of the wanton Undead have hypnotize -him. And he remain on and on, till sunset come, and the Vampire -sleep be over. Then the beautiful eyes of the fair woman open -and look love, and the voluptuous mouth present to a kiss, and -the man is weak. And there remain one more victim in the -Vampire fold. One more to swell the grim and grisly ranks -of the Undead! . . . - -There is some fascination, surely, when I am moved by the -mere presence of such an one, even lying as she lay in a -tomb fretted with age and heavy with the dust of centuries, -though there be that horrid odour such as the lairs of the -Count have had. Yes, I was moved. I, Van Helsing, with -all my purpose and with my motive for hate. I was moved to -a yearning for delay which seemed to paralyze my faculties -and to clog my very soul. It may have been that the need -of natural sleep, and the strange oppression of the air -were beginning to overcome me. Certain it was that I was -lapsing into sleep, the open eyed sleep of one who yields -to a sweet fascination, when there came through the snow-stilled -air a long, low wail, so full of woe and pity that it woke me -like the sound of a clarion. For it was the voice of my dear -Madam Mina that I heard. - -Then I braced myself again to my horrid task, and found by -wrenching away tomb tops one other of the sisters, the other dark -one. I dared not pause to look on her as I had on her sister, -lest once more I should begin to be enthrall. But I go on -searching until, presently, I find in a high great tomb as if -made to one much beloved that other fair sister which, like -Jonathan I had seen to gather herself out of the atoms of the -mist. She was so fair to look on, so radiantly beautiful, so -exquisitely voluptuous, that the very instinct of man in me, -which calls some of my sex to love and to protect one of hers, -made my head whirl with new emotion. But God be thanked, that -soul wail of my dear Madam Mina had not died out of my ears. -And, before the spell could be wrought further upon me, I had -nerved myself to my wild work. By this time I had searched all -the tombs in the chapel, so far as I could tell. And as there -had been only three of these Undead phantoms around us in the -night, I took it that there were no more of active Undead -existent. There was one great tomb more lordly than all the -rest. Huge it was, and nobly proportioned. On it was but one -word. - - - DRACULA - - -This then was the Undead home of the King Vampire, to whom -so many more were due. Its emptiness spoke eloquent to -make certain what I knew. Before I began to restore these -women to their dead selves through my awful work, I laid in -Dracula's tomb some of the Wafer, and so banished him from -it, Undead, for ever. - -Then began my terrible task, and I dreaded it. Had it been -but one, it had been easy, comparative. But three! To -begin twice more after I had been through a deed of horror. -For it was terrible with the sweet Miss Lucy, what would it -not be with these strange ones who had survived through -centuries, and who had been strengthened by the passing of -the years. Who would, if they could, have fought for their -foul lives . . . - -Oh, my friend John, but it was butcher work. Had I not -been nerved by thoughts of other dead, and of the living -over whom hung such a pall of fear, I could not have gone -on. I tremble and tremble even yet, though till all was -over, God be thanked, my nerve did stand. Had I not seen -the repose in the first place, and the gladness that stole -over it just ere the final dissolution came, as realization -that the soul had been won, I could not have gone further -with my butchery. I could not have endured the horrid screeching -as the stake drove home, the plunging of writhing form, and lips -of bloody foam. I should have fled in terror and left my work -undone. But it is over! And the poor souls, I can pity them now -and weep, as I think of them placid each in her full sleep of -death for a short moment ere fading. For, friend John, hardly -had my knife severed the head of each, before the whole body -began to melt away and crumble into its native dust, as though -the death that should have come centuries ago had at last assert -himself and say at once and loud, "I am here!" - -Before I left the castle I so fixed its entrances that never -more can the Count enter there Undead. - -When I stepped into the circle where Madam Mina slept, she -woke from her sleep and, seeing me, cried out in pain that -I had endured too much. - -"Come!" she said, "come away from this awful place! Let us -go to meet my husband who is, I know, coming towards us." -She was looking thin and pale and weak. But her eyes were -pure and glowed with fervour. I was glad to see her paleness and -her illness, for my mind was full of the fresh horror of that -ruddy vampire sleep. - -And so with trust and hope, and yet full of fear, we go -eastward to meet our friends, and him, whom Madam Mina tell -me that she know are coming to meet us. - - - - - -MINA HARKER'S JOURNAL - -6 November.--It was late in the afternoon when the Professor and I -took our way towards the east whence I knew Jonathan was coming. We -did not go fast, though the way was steeply downhill, for we had to -take heavy rugs and wraps with us. We dared not face the possibility -of being left without warmth in the cold and the snow. We had to take -some of our provisions too, for we were in a perfect desolation, and -so far as we could see through the snowfall, there was not even the -sign of habitation. When we had gone about a mile, I was tired with -the heavy walking and sat down to rest. Then we looked back and saw -where the clear line of Dracula's castle cut the sky. For we were so -deep under the hill whereon it was set that the angle of perspective -of the Carpathian mountains was far below it. We saw it in all its -grandeur, perched a thousand feet on the summit of a sheer precipice, -and with seemingly a great gap between it and the steep of the -adjacent mountain on any side. There was something wild and uncanny -about the place. We could hear the distant howling of wolves. They -were far off, but the sound, even though coming muffled through the -deadening snowfall, was full of terror. I knew from the way Dr. Van -Helsing was searching about that he was trying to seek some strategic -point, where we would be less exposed in case of attack. The rough -roadway still led downwards. We could trace it through the drifted -snow. - -In a little while the Professor signalled to me, so I got up and -joined him. He had found a wonderful spot, a sort of natural hollow -in a rock, with an entrance like a doorway between two boulders. He -took me by the hand and drew me in. - -"See!" he said, "here you will be in shelter. And if the wolves do -come I can meet them one by one." - -He brought in our furs, and made a snug nest for me, and got out some -provisions and forced them upon me. But I could not eat, to even try -to do so was repulsive to me, and much as I would have liked to please -him, I could not bring myself to the attempt. He looked very sad, but -did not reproach me. Taking his field glasses from the case, he stood -on the top of the rock, and began to search the horizon. - -Suddenly he called out, "Look! Madam Mina, look! Look!" - -I sprang up and stood beside him on the rock. He handed me his -glasses and pointed. The snow was now falling more heavily, and -swirled about fiercely, for a high wind was beginning to blow. -However, there were times when there were pauses between the snow -flurries and I could see a long way round. From the height where we -were it was possible to see a great distance. And far off, beyond the -white waste of snow, I could see the river lying like a black ribbon -in kinks and curls as it wound its way. Straight in front of us and -not far off, in fact so near that I wondered we had not noticed -before, came a group of mounted men hurrying along. In the midst of -them was a cart, a long leiter wagon which swept from side to side, -like a dog's tail wagging, with each stern inequality of the road. -Outlined against the snow as they were, I could see from the men's -clothes that they were peasants or gypsies of some kind. - -On the cart was a great square chest. My heart leaped as I saw it, for -I felt that the end was coming. The evening was now drawing close, -and well I knew that at sunset the Thing, which was till then -imprisoned there, would take new freedom and could in any of many -forms elude pursuit. In fear I turned to the Professor. To my -consternation, however, he was not there. An instant later, I saw him -below me. Round the rock he had drawn a circle, such as we had found -shelter in last night. - -When he had completed it he stood beside me again saying, "At least -you shall be safe here from him!" He took the glasses from me, and at -the next lull of the snow swept the whole space below us. "See," he -said, "they come quickly. They are flogging the horses, and galloping -as hard as they can." - -He paused and went on in a hollow voice, "They are racing for the -sunset. We may be too late. God's will be done!" Down came another -blinding rush of driving snow, and the whole landscape was blotted -out. It soon passed, however, and once more his glasses were fixed on -the plain. - -Then came a sudden cry, "Look! Look! Look! See, two horsemen follow -fast, coming up from the south. It must be Quincey and John. Take -the glass. Look before the snow blots it all out!" I took it and -looked. The two men might be Dr. Seward and Mr. Morris. I knew at -all events that neither of them was Jonathan. At the same time I knew -that Jonathan was not far off. Looking around I saw on the north side -of the coming party two other men, riding at breakneck speed. One of -them I knew was Jonathan, and the other I took, of course, to be Lord -Godalming. They too, were pursuing the party with the cart. When I -told the Professor he shouted in glee like a schoolboy, and after -looking intently till a snow fall made sight impossible, he laid his -Winchester rifle ready for use against the boulder at the opening of -our shelter. - -"They are all converging," he said. "When the time comes we shall have -gypsies on all sides." I got out my revolver ready to hand, for -whilst we were speaking the howling of wolves came louder and closer. -When the snow storm abated a moment we looked again. It was strange -to see the snow falling in such heavy flakes close to us, and beyond, -the sun shining more and more brightly as it sank down towards the far -mountain tops. Sweeping the glass all around us I could see here and -there dots moving singly and in twos and threes and larger numbers. -The wolves were gathering for their prey. - -Every instant seemed an age whilst we waited. The wind came now in -fierce bursts, and the snow was driven with fury as it swept upon us -in circling eddies. At times we could not see an arm's length before -us. But at others, as the hollow sounding wind swept by us, it seemed -to clear the air space around us so that we could see afar off. We -had of late been so accustomed to watch for sunrise and sunset, that -we knew with fair accuracy when it would be. And we knew that before -long the sun would set. It was hard to believe that by our watches it -was less than an hour that we waited in that rocky shelter before the -various bodies began to converge close upon us. The wind came now -with fiercer and more bitter sweeps, and more steadily from the -north. It seemingly had driven the snow clouds from us, for with only -occasional bursts, the snow fell. We could distinguish clearly the -individuals of each party, the pursued and the pursuers. Strangely -enough those pursued did not seem to realize, or at least to care, -that they were pursued. They seemed, however, to hasten with -redoubled speed as the sun dropped lower and lower on the mountain -tops. - -Closer and closer they drew. The Professor and I crouched down behind -our rock, and held our weapons ready. I could see that he was -determined that they should not pass. One and all were quite unaware -of our presence. - -All at once two voices shouted out to "Halt!" One was my Jonathan's, -raised in a high key of passion. The other Mr. Morris' strong -resolute tone of quiet command. The gypsies may not have known the -language, but there was no mistaking the tone, in whatever tongue the -words were spoken. Instinctively they reined in, and at the instant -Lord Godalming and Jonathan dashed up at one side and Dr. Seward and -Mr. Morris on the other. The leader of the gypsies, a splendid -looking fellow who sat his horse like a centaur, waved them back, and -in a fierce voice gave to his companions some word to proceed. They -lashed the horses which sprang forward. But the four men raised their -Winchester rifles, and in an unmistakable way commanded them to stop. -At the same moment Dr. Van Helsing and I rose behind the rock and -pointed our weapons at them. Seeing that they were surrounded the men -tightened their reins and drew up. The leader turned to them and gave -a word at which every man of the gypsy party drew what weapon he -carried, knife or pistol, and held himself in readiness to attack. -Issue was joined in an instant. - -The leader, with a quick movement of his rein, threw his horse out in -front, and pointed first to the sun, now close down on the hill tops, -and then to the castle, said something which I did not understand. -For answer, all four men of our party threw themselves from their -horses and dashed towards the cart. I should have felt terrible fear -at seeing Jonathan in such danger, but that the ardor of battle must -have been upon me as well as the rest of them. I felt no fear, but -only a wild, surging desire to do something. Seeing the quick -movement of our parties, the leader of the gypsies gave a command. His -men instantly formed round the cart in a sort of undisciplined -endeavour, each one shouldering and pushing the other in his eagerness -to carry out the order. - -In the midst of this I could see that Jonathan on one side of the ring -of men, and Quincey on the other, were forcing a way to the cart. It -was evident that they were bent on finishing their task before the sun -should set. Nothing seemed to stop or even to hinder them. Neither -the levelled weapons nor the flashing knives of the gypsies in front, -nor the howling of the wolves behind, appeared to even attract their -attention. Jonathan's impetuosity, and the manifest singleness of his -purpose, seemed to overawe those in front of him. Instinctively they -cowered aside and let him pass. In an instant he had jumped upon the -cart, and with a strength which seemed incredible, raised the great -box, and flung it over the wheel to the ground. In the meantime, Mr. -Morris had had to use force to pass through his side of the ring of -Szgany. All the time I had been breathlessly watching Jonathan I had, -with the tail of my eye, seen him pressing desperately forward, and -had seen the knives of the gypsies flash as he won a way through them, -and they cut at him. He had parried with his great bowie knife, and -at first I thought that he too had come through in safety. But as he -sprang beside Jonathan, who had by now jumped from the cart, I could -see that with his left hand he was clutching at his side, and that the -blood was spurting through his fingers. He did not delay -notwithstanding this, for as Jonathan, with desperate energy, attacked -one end of the chest, attempting to prize off the lid with his great -Kukri knife, he attacked the other frantically with his bowie. Under -the efforts of both men the lid began to yield. The nails drew with a -screeching sound, and the top of the box was thrown back. - -By this time the gypsies, seeing themselves covered by the -Winchesters, and at the mercy of Lord Godalming and Dr. Seward, had -given in and made no further resistance. The sun was almost down on -the mountain tops, and the shadows of the whole group fell upon the -snow. I saw the Count lying within the box upon the earth, some of -which the rude falling from the cart had scattered over him. He was -deathly pale, just like a waxen image, and the red eyes glared with -the horrible vindictive look which I knew so well. - -As I looked, the eyes saw the sinking sun, and the look of hate in -them turned to triumph. - -But, on the instant, came the sweep and flash of Jonathan's great -knife. I shrieked as I saw it shear through the throat. Whilst at -the same moment Mr. Morris's bowie knife plunged into the heart. - -It was like a miracle, but before our very eyes, and almost in the -drawing of a breath, the whole body crumbled into dust and passed from -our sight. - -I shall be glad as long as I live that even in that moment of final -dissolution, there was in the face a look of peace, such as I never -could have imagined might have rested there. - -The Castle of Dracula now stood out against the red sky, and every -stone of its broken battlements was articulated against the light of -the setting sun. - -The gypsies, taking us as in some way the cause of the extraordinary -disappearance of the dead man, turned, without a word, and rode away -as if for their lives. Those who were unmounted jumped upon the -leiter wagon and shouted to the horsemen not to desert them. The -wolves, which had withdrawn to a safe distance, followed in their -wake, leaving us alone. - -Mr. Morris, who had sunk to the ground, leaned on his elbow, holding -his hand pressed to his side. The blood still gushed through his -fingers. I flew to him, for the Holy circle did not now keep me back; -so did the two doctors. Jonathan knelt behind him and the wounded man -laid back his head on his shoulder. With a sigh he took, with a -feeble effort, my hand in that of his own which was unstained. - -He must have seen the anguish of my heart in my face, for he smiled at -me and said, "I am only too happy to have been of service! Oh, God!" -he cried suddenly, struggling to a sitting posture and pointing to me. -"It was worth for this to die! Look! Look!" - -The sun was now right down upon the mountain top, and the red gleams -fell upon my face, so that it was bathed in rosy light. With one -impulse the men sank on their knees and a deep and earnest "Amen" -broke from all as their eyes followed the pointing of his finger. - -The dying man spoke, "Now God be thanked that all has not been in -vain! See! The snow is not more stainless than her forehead! The -curse has passed away!" - -And, to our bitter grief, with a smile and in silence, he died, a -gallant gentleman. - - - - - -NOTE - - -Seven years ago we all went through the flames. And the happiness of -some of us since then is, we think, well worth the pain we endured. -It is an added joy to Mina and to me that our boy's birthday is the -same day as that on which Quincey Morris died. His mother holds, I -know, the secret belief that some of our brave friend's spirit has -passed into him. His bundle of names links all our little band of men -together. But we call him Quincey. - -In the summer of this year we made a journey to Transylvania, and went -over the old ground which was, and is, to us so full of vivid and -terrible memories. It was almost impossible to believe that the -things which we had seen with our own eyes and heard with our own ears -were living truths. Every trace of all that had been was blotted -out. The castle stood as before, reared high above a waste of -desolation. - -When we got home we were talking of the old time, which we could all -look back on without despair, for Godalming and Seward are both -happily married. I took the papers from the safe where they had been -ever since our return so long ago. We were struck with the fact, that -in all the mass of material of which the record is composed, there is -hardly one authentic document. Nothing but a mass of typewriting, -except the later notebooks of Mina and Seward and myself, and Van -Helsing's memorandum. We could hardly ask any one, even did we wish -to, to accept these as proofs of so wild a story. Van Helsing summed -it all up as he said, with our boy on his knee. - -"We want no proofs. We ask none to believe us! This boy will some -day know what a brave and gallant woman his mother is. Already he -knows her sweetness and loving care. Later on he will understand how -some men so loved her, that they did dare much for her sake." - -JONATHAN HARKER - - - - - - - - - -End of the Project Gutenberg EBook of Dracula, by Bram Stoker - -*** END OF THIS PROJECT GUTENBERG EBOOK DRACULA *** - -***** This file should be named 345.txt or 345.zip ***** -This and all associated files of various formats will be found in: - http://www.gutenberg.org/3/4/345/ - - - -Updated editions will replace the previous one--the old editions -will be renamed. - -Creating the works from public domain print editions means that no -one owns a United States copyright in these works, so the Foundation -(and you!) can copy and distribute it in the United States without -permission and without paying copyright royalties. Special rules, -set forth in the General Terms of Use part of this license, apply to -copying and distributing Project Gutenberg-tm electronic works to -protect the PROJECT GUTENBERG-tm concept and trademark. Project -Gutenberg is a registered trademark, and may not be used if you -charge for the eBooks, unless you receive specific permission. If you -do not charge anything for copies of this eBook, complying with the -rules is very easy. You may use this eBook for nearly any purpose -such as creation of derivative works, reports, performances and -research. They may be modified and printed and given away--you may do -practically ANYTHING with public domain eBooks. Redistribution is -subject to the trademark license, especially commercial -redistribution. - - - -*** START: FULL LICENSE *** - -THE FULL PROJECT GUTENBERG LICENSE -PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK - -To protect the Project Gutenberg-tm mission of promoting the free -distribution of electronic works, by using or distributing this work -(or any other work associated in any way with the phrase "Project -Gutenberg"), you agree to comply with all the terms of the Full Project -Gutenberg-tm License (available with this file or online at -http://gutenberg.net/license). - - -Section 1. General Terms of Use and Redistributing Project Gutenberg-tm -electronic works - -1.A. By reading or using any part of this Project Gutenberg-tm -electronic work, you indicate that you have read, understand, agree to -and accept all the terms of this license and intellectual property -(trademark/copyright) agreement. If you do not agree to abide by all -the terms of this agreement, you must cease using and return or destroy -all copies of Project Gutenberg-tm electronic works in your possession. -If you paid a fee for obtaining a copy of or access to a Project -Gutenberg-tm electronic work and you do not agree to be bound by the -terms of this agreement, you may obtain a refund from the person or -entity to whom you paid the fee as set forth in paragraph 1.E.8. - -1.B. "Project Gutenberg" is a registered trademark. It may only be -used on or associated in any way with an electronic work by people who -agree to be bound by the terms of this agreement. There are a few -things that you can do with most Project Gutenberg-tm electronic works -even without complying with the full terms of this agreement. See -paragraph 1.C below. There are a lot of things you can do with Project -Gutenberg-tm electronic works if you follow the terms of this agreement -and help preserve free future access to Project Gutenberg-tm electronic -works. See paragraph 1.E below. - -1.C. The Project Gutenberg Literary Archive Foundation ("the Foundation" -or PGLAF), owns a compilation copyright in the collection of Project -Gutenberg-tm electronic works. Nearly all the individual works in the -collection are in the public domain in the United States. If an -individual work is in the public domain in the United States and you are -located in the United States, we do not claim a right to prevent you from -copying, distributing, performing, displaying or creating derivative -works based on the work as long as all references to Project Gutenberg -are removed. Of course, we hope that you will support the Project -Gutenberg-tm mission of promoting free access to electronic works by -freely sharing Project Gutenberg-tm works in compliance with the terms of -this agreement for keeping the Project Gutenberg-tm name associated with -the work. You can easily comply with the terms of this agreement by -keeping this work in the same format with its attached full Project -Gutenberg-tm License when you share it without charge with others. - -1.D. The copyright laws of the place where you are located also govern -what you can do with this work. Copyright laws in most countries are in -a constant state of change. If you are outside the United States, check -the laws of your country in addition to the terms of this agreement -before downloading, copying, displaying, performing, distributing or -creating derivative works based on this work or any other Project -Gutenberg-tm work. The Foundation makes no representations concerning -the copyright status of any work in any country outside the United -States. - -1.E. Unless you have removed all references to Project Gutenberg: - -1.E.1. The following sentence, with active links to, or other immediate -access to, the full Project Gutenberg-tm License must appear prominently -whenever any copy of a Project Gutenberg-tm work (any work on which the -phrase "Project Gutenberg" appears, or with which the phrase "Project -Gutenberg" is associated) is accessed, displayed, performed, viewed, -copied or distributed: - -This eBook is for the use of anyone anywhere at no cost and with -almost no restrictions whatsoever. You may copy it, give it away or -re-use it under the terms of the Project Gutenberg License included -with this eBook or online at www.gutenberg.net - -1.E.2. If an individual Project Gutenberg-tm electronic work is derived -from the public domain (does not contain a notice indicating that it is -posted with permission of the copyright holder), the work can be copied -and distributed to anyone in the United States without paying any fees -or charges. If you are redistributing or providing access to a work -with the phrase "Project Gutenberg" associated with or appearing on the -work, you must comply either with the requirements of paragraphs 1.E.1 -through 1.E.7 or obtain permission for the use of the work and the -Project Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or -1.E.9. - -1.E.3. If an individual Project Gutenberg-tm electronic work is posted -with the permission of the copyright holder, your use and distribution -must comply with both paragraphs 1.E.1 through 1.E.7 and any additional -terms imposed by the copyright holder. Additional terms will be linked -to the Project Gutenberg-tm License for all works posted with the -permission of the copyright holder found at the beginning of this work. - -1.E.4. Do not unlink or detach or remove the full Project Gutenberg-tm -License terms from this work, or any files containing a part of this -work or any other work associated with Project Gutenberg-tm. - -1.E.5. Do not copy, display, perform, distribute or redistribute this -electronic work, or any part of this electronic work, without -prominently displaying the sentence set forth in paragraph 1.E.1 with -active links or immediate access to the full terms of the Project -Gutenberg-tm License. - -1.E.6. You may convert to and distribute this work in any binary, -compressed, marked up, nonproprietary or proprietary form, including any -word processing or hypertext form. However, if you provide access to or -distribute copies of a Project Gutenberg-tm work in a format other than -"Plain Vanilla ASCII" or other format used in the official version -posted on the official Project Gutenberg-tm web site (www.gutenberg.net), -you must, at no additional cost, fee or expense to the user, provide a -copy, a means of exporting a copy, or a means of obtaining a copy upon -request, of the work in its original "Plain Vanilla ASCII" or other -form. Any alternate format must include the full Project Gutenberg-tm -License as specified in paragraph 1.E.1. - -1.E.7. Do not charge a fee for access to, viewing, displaying, -performing, copying or distributing any Project Gutenberg-tm works -unless you comply with paragraph 1.E.8 or 1.E.9. - -1.E.8. You may charge a reasonable fee for copies of or providing -access to or distributing Project Gutenberg-tm electronic works provided -that - -- You pay a royalty fee of 20% of the gross profits you derive from - the use of Project Gutenberg-tm works calculated using the method - you already use to calculate your applicable taxes. The fee is - owed to the owner of the Project Gutenberg-tm trademark, but he - has agreed to donate royalties under this paragraph to the - Project Gutenberg Literary Archive Foundation. Royalty payments - must be paid within 60 days following each date on which you - prepare (or are legally required to prepare) your periodic tax - returns. Royalty payments should be clearly marked as such and - sent to the Project Gutenberg Literary Archive Foundation at the - address specified in Section 4, "Information about donations to - the Project Gutenberg Literary Archive Foundation." - -- You provide a full refund of any money paid by a user who notifies - you in writing (or by e-mail) within 30 days of receipt that s/he - does not agree to the terms of the full Project Gutenberg-tm - License. You must require such a user to return or - destroy all copies of the works possessed in a physical medium - and discontinue all use of and all access to other copies of - Project Gutenberg-tm works. - -- You provide, in accordance with paragraph 1.F.3, a full refund of any - money paid for a work or a replacement copy, if a defect in the - electronic work is discovered and reported to you within 90 days - of receipt of the work. - -- You comply with all other terms of this agreement for free - distribution of Project Gutenberg-tm works. - -1.E.9. If you wish to charge a fee or distribute a Project Gutenberg-tm -electronic work or group of works on different terms than are set -forth in this agreement, you must obtain permission in writing from -both the Project Gutenberg Literary Archive Foundation and Michael -Hart, the owner of the Project Gutenberg-tm trademark. Contact the -Foundation as set forth in Section 3 below. - -1.F. - -1.F.1. Project Gutenberg volunteers and employees expend considerable -effort to identify, do copyright research on, transcribe and proofread -public domain works in creating the Project Gutenberg-tm -collection. Despite these efforts, Project Gutenberg-tm electronic -works, and the medium on which they may be stored, may contain -"Defects," such as, but not limited to, incomplete, inaccurate or -corrupt data, transcription errors, a copyright or other intellectual -property infringement, a defective or damaged disk or other medium, a -computer virus, or computer codes that damage or cannot be read by -your equipment. - -1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the "Right -of Replacement or Refund" described in paragraph 1.F.3, the Project -Gutenberg Literary Archive Foundation, the owner of the Project -Gutenberg-tm trademark, and any other party distributing a Project -Gutenberg-tm electronic work under this agreement, disclaim all -liability to you for damages, costs and expenses, including legal -fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT -LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE -PROVIDED IN PARAGRAPH F3. YOU AGREE THAT THE FOUNDATION, THE -TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE -LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR -INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH -DAMAGE. - -1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a -defect in this electronic work within 90 days of receiving it, you can -receive a refund of the money (if any) you paid for it by sending a -written explanation to the person you received the work from. If you -received the work on a physical medium, you must return the medium with -your written explanation. The person or entity that provided you with -the defective work may elect to provide a replacement copy in lieu of a -refund. If you received the work electronically, the person or entity -providing it to you may choose to give you a second opportunity to -receive the work electronically in lieu of a refund. If the second copy -is also defective, you may demand a refund in writing without further -opportunities to fix the problem. - -1.F.4. Except for the limited right of replacement or refund set forth -in paragraph 1.F.3, this work is provided to you 'AS-IS' WITH NO OTHER -WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO -WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE. - -1.F.5. Some states do not allow disclaimers of certain implied -warranties or the exclusion or limitation of certain types of damages. -If any disclaimer or limitation set forth in this agreement violates the -law of the state applicable to this agreement, the agreement shall be -interpreted to make the maximum disclaimer or limitation permitted by -the applicable state law. The invalidity or unenforceability of any -provision of this agreement shall not void the remaining provisions. - -1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation, the -trademark owner, any agent or employee of the Foundation, anyone -providing copies of Project Gutenberg-tm electronic works in accordance -with this agreement, and any volunteers associated with the production, -promotion and distribution of Project Gutenberg-tm electronic works, -harmless from all liability, costs and expenses, including legal fees, -that arise directly or indirectly from any of the following which you do -or cause to occur: (a) distribution of this or any Project Gutenberg-tm -work, (b) alteration, modification, or additions or deletions to any -Project Gutenberg-tm work, and (c) any Defect you cause. - - -Section 2. Information about the Mission of Project Gutenberg-tm - -Project Gutenberg-tm is synonymous with the free distribution of -electronic works in formats readable by the widest variety of computers -including obsolete, old, middle-aged and new computers. It exists -because of the efforts of hundreds of volunteers and donations from -people in all walks of life. - -Volunteers and financial support to provide volunteers with the -assistance they need, is critical to reaching Project Gutenberg-tm's -goals and ensuring that the Project Gutenberg-tm collection will -remain freely available for generations to come. In 2001, the Project -Gutenberg Literary Archive Foundation was created to provide a secure -and permanent future for Project Gutenberg-tm and future generations. -To learn more about the Project Gutenberg Literary Archive Foundation -and how your efforts and donations can help, see Sections 3 and 4 -and the Foundation web page at http://www.pglaf.org. - - -Section 3. Information about the Project Gutenberg Literary Archive -Foundation - -The Project Gutenberg Literary Archive Foundation is a non profit -501(c)(3) educational corporation organized under the laws of the -state of Mississippi and granted tax exempt status by the Internal -Revenue Service. The Foundation's EIN or federal tax identification -number is 64-6221541. Its 501(c)(3) letter is posted at -http://pglaf.org/fundraising. Contributions to the Project Gutenberg -Literary Archive Foundation are tax deductible to the full extent -permitted by U.S. federal laws and your state's laws. - -The Foundation's principal office is located at 4557 Melan Dr. S. -Fairbanks, AK, 99712., but its volunteers and employees are scattered -throughout numerous locations. Its business office is located at -809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email -business@pglaf.org. Email contact links and up to date contact -information can be found at the Foundation's web site and official -page at http://pglaf.org - -For additional contact information: - Dr. Gregory B. Newby - Chief Executive and Director - gbnewby@pglaf.org - - -Section 4. Information about Donations to the Project Gutenberg -Literary Archive Foundation - -Project Gutenberg-tm depends upon and cannot survive without wide -spread public support and donations to carry out its mission of -increasing the number of public domain and licensed works that can be -freely distributed in machine readable form accessible by the widest -array of equipment including outdated equipment. Many small donations -($1 to $5,000) are particularly important to maintaining tax exempt -status with the IRS. - -The Foundation is committed to complying with the laws regulating -charities and charitable donations in all 50 states of the United -States. Compliance requirements are not uniform and it takes a -considerable effort, much paperwork and many fees to meet and keep up -with these requirements. We do not solicit donations in locations -where we have not received written confirmation of compliance. To -SEND DONATIONS or determine the status of compliance for any -particular state visit http://pglaf.org - -While we cannot and do not solicit contributions from states where we -have not met the solicitation requirements, we know of no prohibition -against accepting unsolicited donations from donors in such states who -approach us with offers to donate. - -International donations are gratefully accepted, but we cannot make -any statements concerning tax treatment of donations received from -outside the United States. U.S. laws alone swamp our small staff. - -Please check the Project Gutenberg Web pages for current donation -methods and addresses. Donations are accepted in a number of other -ways including including checks, online payments and credit card -donations. To donate, please visit: http://pglaf.org/donate - - -Section 5. General Information About Project Gutenberg-tm electronic -works. - -Professor Michael S. Hart is the originator of the Project Gutenberg-tm -concept of a library of electronic works that could be freely shared -with anyone. For thirty years, he produced and distributed Project -Gutenberg-tm eBooks with only a loose network of volunteer support. - - -Project Gutenberg-tm eBooks are often created from several printed -editions, all of which are confirmed as Public Domain in the U.S. -unless a copyright notice is included. Thus, we do not necessarily -keep eBooks in compliance with any particular paper edition. - - -Most people start at our Web site which has the main PG search facility: - - http://www.gutenberg.net - -This Web site includes information about Project Gutenberg-tm, -including how to make donations to the Project Gutenberg Literary -Archive Foundation, how to help produce our new eBooks, and how to -subscribe to our email newsletter to hear about new eBooks. diff --git a/mode/examples/Topics/Advanced Data/HashMapClass/data/hamlet.txt b/mode/examples/Topics/Advanced Data/HashMapClass/data/hamlet.txt deleted file mode 100644 index eb151b8d0..000000000 --- a/mode/examples/Topics/Advanced Data/HashMapClass/data/hamlet.txt +++ /dev/null @@ -1,6771 +0,0 @@ -HAMLET, PRINCE OF DENMARK - -by William Shakespeare - - - - -PERSONS REPRESENTED. - -Claudius, King of Denmark. -Hamlet, Son to the former, and Nephew to the present King. -Polonius, Lord Chamberlain. -Horatio, Friend to Hamlet. -Laertes, Son to Polonius. -Voltimand, Courtier. -Cornelius, Courtier. -Rosencrantz, Courtier. -Guildenstern, Courtier. -Osric, Courtier. -A Gentleman, Courtier. -A Priest. -Marcellus, Officer. -Bernardo, Officer. -Francisco, a Soldier -Reynaldo, Servant to Polonius. -Players. -Two Clowns, Grave-diggers. -Fortinbras, Prince of Norway. -A Captain. -English Ambassadors. -Ghost of Hamlet's Father. - -Gertrude, Queen of Denmark, and Mother of Hamlet. -Ophelia, Daughter to Polonius. - -Lords, Ladies, Officers, Soldiers, Sailors, Messengers, and other -Attendants. - -SCENE. Elsinore. - - - -ACT I. - -Scene I. Elsinore. A platform before the Castle. - -[Francisco at his post. Enter to him Bernardo.] - -Ber. -Who's there? - -Fran. -Nay, answer me: stand, and unfold yourself. - -Ber. -Long live the king! - -Fran. -Bernardo? - -Ber. -He. - -Fran. -You come most carefully upon your hour. - -Ber. -'Tis now struck twelve. Get thee to bed, Francisco. - -Fran. -For this relief much thanks: 'tis bitter cold, -And I am sick at heart. - -Ber. -Have you had quiet guard? - -Fran. -Not a mouse stirring. - -Ber. -Well, good night. -If you do meet Horatio and Marcellus, -The rivals of my watch, bid them make haste. - -Fran. -I think I hear them.--Stand, ho! Who is there? - -[Enter Horatio and Marcellus.] - -Hor. -Friends to this ground. - -Mar. -And liegemen to the Dane. - -Fran. -Give you good-night. - -Mar. -O, farewell, honest soldier; -Who hath reliev'd you? - -Fran. -Bernardo has my place. -Give you good-night. - -[Exit.] - -Mar. -Holla! Bernardo! - -Ber. -Say. -What, is Horatio there? - -Hor. -A piece of him. - -Ber. -Welcome, Horatio:--Welcome, good Marcellus. - -Mar. -What, has this thing appear'd again to-night? - -Ber. -I have seen nothing. - -Mar. -Horatio says 'tis but our fantasy, -And will not let belief take hold of him -Touching this dreaded sight, twice seen of us: -Therefore I have entreated him along -With us to watch the minutes of this night; -That, if again this apparition come -He may approve our eyes and speak to it. - -Hor. -Tush, tush, 'twill not appear. - -Ber. -Sit down awhile, -And let us once again assail your ears, -That are so fortified against our story, -What we two nights have seen. - -Hor. -Well, sit we down, -And let us hear Bernardo speak of this. - -Ber. -Last night of all, -When yond same star that's westward from the pole -Had made his course to illume that part of heaven -Where now it burns, Marcellus and myself, -The bell then beating one,-- - -Mar. -Peace, break thee off; look where it comes again! - -[Enter Ghost, armed.] - -Ber. -In the same figure, like the king that's dead. - -Mar. -Thou art a scholar; speak to it, Horatio. - -Ber. -Looks it not like the King? mark it, Horatio. - -Hor. -Most like:--it harrows me with fear and wonder. - -Ber. -It would be spoke to. - -Mar. -Question it, Horatio. - -Hor. -What art thou, that usurp'st this time of night, -Together with that fair and warlike form -In which the majesty of buried Denmark -Did sometimes march? By heaven I charge thee, speak! - -Mar. -It is offended. - -Ber. -See, it stalks away! - -Hor. -Stay! speak, speak! I charge thee speak! - -[Exit Ghost.] - -Mar. -'Tis gone, and will not answer. - -Ber. -How now, Horatio! You tremble and look pale: -Is not this something more than fantasy? -What think you on't? - -Hor. -Before my God, I might not this believe -Without the sensible and true avouch -Of mine own eyes. - -Mar. -Is it not like the King? - -Hor. -As thou art to thyself: -Such was the very armour he had on -When he the ambitious Norway combated; -So frown'd he once when, in an angry parle, -He smote the sledded Polacks on the ice. -'Tis strange. - -Mar. -Thus twice before, and jump at this dead hour, -With martial stalk hath he gone by our watch. - -Hor. -In what particular thought to work I know not; -But, in the gross and scope of my opinion, -This bodes some strange eruption to our state. - -Mar. -Good now, sit down, and tell me, he that knows, -Why this same strict and most observant watch -So nightly toils the subject of the land; -And why such daily cast of brazen cannon, -And foreign mart for implements of war; -Why such impress of shipwrights, whose sore task -Does not divide the Sunday from the week; -What might be toward, that this sweaty haste -Doth make the night joint-labourer with the day: -Who is't that can inform me? - -Hor. -That can I; -At least, the whisper goes so. Our last king, -Whose image even but now appear'd to us, -Was, as you know, by Fortinbras of Norway, -Thereto prick'd on by a most emulate pride, -Dar'd to the combat; in which our valiant Hamlet,-- -For so this side of our known world esteem'd him,-- -Did slay this Fortinbras; who, by a seal'd compact, -Well ratified by law and heraldry, -Did forfeit, with his life, all those his lands, -Which he stood seiz'd of, to the conqueror: -Against the which, a moiety competent -Was gaged by our king; which had return'd -To the inheritance of Fortinbras, -Had he been vanquisher; as by the same cov'nant, -And carriage of the article design'd, -His fell to Hamlet. Now, sir, young Fortinbras, -Of unimproved mettle hot and full, -Hath in the skirts of Norway, here and there, -Shark'd up a list of lawless resolutes, -For food and diet, to some enterprise -That hath a stomach in't; which is no other,-- -As it doth well appear unto our state,-- -But to recover of us, by strong hand, -And terms compulsatory, those foresaid lands -So by his father lost: and this, I take it, -Is the main motive of our preparations, -The source of this our watch, and the chief head -Of this post-haste and romage in the land. - -Ber. -I think it be no other but e'en so: -Well may it sort, that this portentous figure -Comes armed through our watch; so like the king -That was and is the question of these wars. - -Hor. -A mote it is to trouble the mind's eye. -In the most high and palmy state of Rome, -A little ere the mightiest Julius fell, -The graves stood tenantless, and the sheeted dead -Did squeak and gibber in the Roman streets; -As, stars with trains of fire and dews of blood, -Disasters in the sun; and the moist star, -Upon whose influence Neptune's empire stands, -Was sick almost to doomsday with eclipse: -And even the like precurse of fierce events,-- -As harbingers preceding still the fates, -And prologue to the omen coming on,-- -Have heaven and earth together demonstrated -Unto our climature and countrymen.-- -But, soft, behold! lo, where it comes again! - -[Re-enter Ghost.] - -I'll cross it, though it blast me.--Stay, illusion! -If thou hast any sound, or use of voice, -Speak to me: -If there be any good thing to be done, -That may to thee do ease, and, race to me, -Speak to me: -If thou art privy to thy country's fate, -Which, happily, foreknowing may avoid, -O, speak! -Or if thou hast uphoarded in thy life -Extorted treasure in the womb of earth, -For which, they say, you spirits oft walk in death, -[The cock crows.] -Speak of it:--stay, and speak!--Stop it, Marcellus! - -Mar. -Shall I strike at it with my partisan? - -Hor. -Do, if it will not stand. - -Ber. -'Tis here! - -Hor. -'Tis here! - -Mar. -'Tis gone! - -[Exit Ghost.] - -We do it wrong, being so majestical, -To offer it the show of violence; -For it is, as the air, invulnerable, -And our vain blows malicious mockery. - -Ber. -It was about to speak, when the cock crew. - -Hor. -And then it started, like a guilty thing -Upon a fearful summons. I have heard -The cock, that is the trumpet to the morn, -Doth with his lofty and shrill-sounding throat -Awake the god of day; and at his warning, -Whether in sea or fire, in earth or air, -The extravagant and erring spirit hies -To his confine: and of the truth herein -This present object made probation. - -Mar. -It faded on the crowing of the cock. -Some say that ever 'gainst that season comes -Wherein our Saviour's birth is celebrated, -The bird of dawning singeth all night long; -And then, they say, no spirit dare stir abroad; -The nights are wholesome; then no planets strike, -No fairy takes, nor witch hath power to charm; -So hallow'd and so gracious is the time. - -Hor. -So have I heard, and do in part believe it. -But, look, the morn, in russet mantle clad, -Walks o'er the dew of yon high eastward hill: -Break we our watch up: and by my advice, -Let us impart what we have seen to-night -Unto young Hamlet; for, upon my life, -This spirit, dumb to us, will speak to him: -Do you consent we shall acquaint him with it, -As needful in our loves, fitting our duty? - -Mar. -Let's do't, I pray; and I this morning know -Where we shall find him most conveniently. - -[Exeunt.] - - - -Scene II. Elsinore. A room of state in the Castle. - -[Enter the King, Queen, Hamlet, Polonius, Laertes, Voltimand, -Cornelius, Lords, and Attendant.] - -King. -Though yet of Hamlet our dear brother's death -The memory be green, and that it us befitted -To bear our hearts in grief, and our whole kingdom -To be contracted in one brow of woe; -Yet so far hath discretion fought with nature -That we with wisest sorrow think on him, -Together with remembrance of ourselves. -Therefore our sometime sister, now our queen, -Th' imperial jointress to this warlike state, -Have we, as 'twere with a defeated joy,-- -With an auspicious and one dropping eye, -With mirth in funeral, and with dirge in marriage, -In equal scale weighing delight and dole,-- -Taken to wife; nor have we herein barr'd -Your better wisdoms, which have freely gone -With this affair along:--or all, our thanks. -Now follows, that you know, young Fortinbras, -Holding a weak supposal of our worth, -Or thinking by our late dear brother's death -Our state to be disjoint and out of frame, -Colleagued with this dream of his advantage, -He hath not fail'd to pester us with message, -Importing the surrender of those lands -Lost by his father, with all bonds of law, -To our most valiant brother. So much for him,-- -Now for ourself and for this time of meeting: -Thus much the business is:--we have here writ -To Norway, uncle of young Fortinbras,-- -Who, impotent and bed-rid, scarcely hears -Of this his nephew's purpose,--to suppress -His further gait herein; in that the levies, -The lists, and full proportions are all made -Out of his subject:--and we here dispatch -You, good Cornelius, and you, Voltimand, -For bearers of this greeting to old Norway; -Giving to you no further personal power -To business with the king, more than the scope -Of these dilated articles allow. -Farewell; and let your haste commend your duty. - -Cor. and Volt. -In that and all things will we show our duty. - -King. -We doubt it nothing: heartily farewell. - -[Exeunt Voltimand and Cornelius.] - -And now, Laertes, what's the news with you? -You told us of some suit; what is't, Laertes? -You cannot speak of reason to the Dane, -And lose your voice: what wouldst thou beg, Laertes, -That shall not be my offer, not thy asking? -The head is not more native to the heart, -The hand more instrumental to the mouth, -Than is the throne of Denmark to thy father. -What wouldst thou have, Laertes? - -Laer. -Dread my lord, -Your leave and favour to return to France; -From whence though willingly I came to Denmark, -To show my duty in your coronation; -Yet now, I must confess, that duty done, -My thoughts and wishes bend again toward France, -And bow them to your gracious leave and pardon. - -King. -Have you your father's leave? What says Polonius? - -Pol. -He hath, my lord, wrung from me my slow leave -By laboursome petition; and at last -Upon his will I seal'd my hard consent: -I do beseech you, give him leave to go. - -King. -Take thy fair hour, Laertes; time be thine, -And thy best graces spend it at thy will!-- -But now, my cousin Hamlet, and my son-- - -Ham. -[Aside.] A little more than kin, and less than kind! - -King. -How is it that the clouds still hang on you? - -Ham. -Not so, my lord; I am too much i' the sun. - -Queen. -Good Hamlet, cast thy nighted colour off, -And let thine eye look like a friend on Denmark. -Do not for ever with thy vailed lids -Seek for thy noble father in the dust: -Thou know'st 'tis common,--all that lives must die, -Passing through nature to eternity. - -Ham. -Ay, madam, it is common. - -Queen. -If it be, -Why seems it so particular with thee? - -Ham. -Seems, madam! Nay, it is; I know not seems. -'Tis not alone my inky cloak, good mother, -Nor customary suits of solemn black, -Nor windy suspiration of forc'd breath, -No, nor the fruitful river in the eye, -Nor the dejected 'havior of the visage, -Together with all forms, moods, shows of grief, -That can denote me truly: these, indeed, seem; -For they are actions that a man might play; -But I have that within which passeth show; -These but the trappings and the suits of woe. - -King. -'Tis sweet and commendable in your nature, Hamlet, -To give these mourning duties to your father; -But, you must know, your father lost a father; -That father lost, lost his; and the survivor bound, -In filial obligation, for some term -To do obsequious sorrow: but to persevere -In obstinate condolement is a course -Of impious stubbornness; 'tis unmanly grief; -It shows a will most incorrect to heaven; -A heart unfortified, a mind impatient; -An understanding simple and unschool'd; -For what we know must be, and is as common -As any the most vulgar thing to sense, -Why should we, in our peevish opposition, -Take it to heart? Fie! 'tis a fault to heaven, -A fault against the dead, a fault to nature, -To reason most absurd; whose common theme -Is death of fathers, and who still hath cried, -From the first corse till he that died to-day, -'This must be so.' We pray you, throw to earth -This unprevailing woe; and think of us -As of a father: for let the world take note -You are the most immediate to our throne; -And with no less nobility of love -Than that which dearest father bears his son -Do I impart toward you. For your intent -In going back to school in Wittenberg, -It is most retrograde to our desire: -And we beseech you bend you to remain -Here in the cheer and comfort of our eye, -Our chiefest courtier, cousin, and our son. - -Queen. -Let not thy mother lose her prayers, Hamlet: -I pray thee stay with us; go not to Wittenberg. - -Ham. -I shall in all my best obey you, madam. - -King. -Why, 'tis a loving and a fair reply: -Be as ourself in Denmark.--Madam, come; -This gentle and unforc'd accord of Hamlet -Sits smiling to my heart: in grace whereof, -No jocund health that Denmark drinks to-day -But the great cannon to the clouds shall tell; -And the king's rouse the heaven shall bruit again, -Re-speaking earthly thunder. Come away. - -[Exeunt all but Hamlet.] - -Ham. -O that this too too solid flesh would melt, -Thaw, and resolve itself into a dew! -Or that the Everlasting had not fix'd -His canon 'gainst self-slaughter! O God! O God! -How weary, stale, flat, and unprofitable -Seem to me all the uses of this world! -Fie on't! O fie! 'tis an unweeded garden, -That grows to seed; things rank and gross in nature -Possess it merely. That it should come to this! -But two months dead!--nay, not so much, not two: -So excellent a king; that was, to this, -Hyperion to a satyr; so loving to my mother, -That he might not beteem the winds of heaven -Visit her face too roughly. Heaven and earth! -Must I remember? Why, she would hang on him -As if increase of appetite had grown -By what it fed on: and yet, within a month,-- -Let me not think on't,--Frailty, thy name is woman!-- -A little month; or ere those shoes were old -With which she followed my poor father's body -Like Niobe, all tears;--why she, even she,-- -O God! a beast that wants discourse of reason, -Would have mourn'd longer,--married with mine uncle, -My father's brother; but no more like my father -Than I to Hercules: within a month; -Ere yet the salt of most unrighteous tears -Had left the flushing in her galled eyes, -She married:-- O, most wicked speed, to post -With such dexterity to incestuous sheets! -It is not, nor it cannot come to good; -But break my heart,--for I must hold my tongue! - -[Enter Horatio, Marcellus, and Bernardo.] - -Hor. -Hail to your lordship! - -Ham. -I am glad to see you well: -Horatio,--or I do forget myself. - -Hor. -The same, my lord, and your poor servant ever. - -Ham. -Sir, my good friend; I'll change that name with you: -And what make you from Wittenberg, Horatio?-- -Marcellus? - -Mar. -My good lord,-- - -Ham. -I am very glad to see you.--Good even, sir.-- -But what, in faith, make you from Wittenberg? - -Hor. -A truant disposition, good my lord. - -Ham. -I would not hear your enemy say so; -Nor shall you do my ear that violence, -To make it truster of your own report -Against yourself: I know you are no truant. -But what is your affair in Elsinore? -We'll teach you to drink deep ere you depart. - -Hor. -My lord, I came to see your father's funeral. - -Ham. -I prithee do not mock me, fellow-student. -I think it was to see my mother's wedding. - -Hor. -Indeed, my lord, it follow'd hard upon. - -Ham. -Thrift, thrift, Horatio! The funeral bak'd meats -Did coldly furnish forth the marriage tables. -Would I had met my dearest foe in heaven -Or ever I had seen that day, Horatio!-- -My father,--methinks I see my father. - -Hor. -Where, my lord? - -Ham. -In my mind's eye, Horatio. - -Hor. -I saw him once; he was a goodly king. - -Ham. -He was a man, take him for all in all, -I shall not look upon his like again. - -Hor. -My lord, I think I saw him yesternight. - -Ham. -Saw who? - -Hor. -My lord, the king your father. - -Ham. -The King my father! - -Hor. -Season your admiration for awhile -With an attent ear, till I may deliver, -Upon the witness of these gentlemen, -This marvel to you. - -Ham. -For God's love let me hear. - -Hor. -Two nights together had these gentlemen, -Marcellus and Bernardo, on their watch -In the dead vast and middle of the night, -Been thus encounter'd. A figure like your father, -Armed at point exactly, cap-a-pe, -Appears before them and with solemn march -Goes slow and stately by them: thrice he walk'd -By their oppress'd and fear-surprised eyes, -Within his truncheon's length; whilst they, distill'd -Almost to jelly with the act of fear, -Stand dumb, and speak not to him. This to me -In dreadful secrecy impart they did; -And I with them the third night kept the watch: -Where, as they had deliver'd, both in time, -Form of the thing, each word made true and good, -The apparition comes: I knew your father; -These hands are not more like. - -Ham. -But where was this? - -Mar. -My lord, upon the platform where we watch'd. - -Ham. -Did you not speak to it? - -Hor. -My lord, I did; -But answer made it none: yet once methought -It lifted up it head, and did address -Itself to motion, like as it would speak: -But even then the morning cock crew loud, -And at the sound it shrunk in haste away, -And vanish'd from our sight. - -Ham. -'Tis very strange. - -Hor. -As I do live, my honour'd lord, 'tis true; -And we did think it writ down in our duty -To let you know of it. - -Ham. -Indeed, indeed, sirs, but this troubles me. -Hold you the watch to-night? - -Mar. and Ber. -We do, my lord. - -Ham. -Arm'd, say you? - -Both. -Arm'd, my lord. - -Ham. -From top to toe? - -Both. -My lord, from head to foot. - -Ham. -Then saw you not his face? - -Hor. -O, yes, my lord: he wore his beaver up. - -Ham. -What, look'd he frowningly? - -Hor. -A countenance more in sorrow than in anger. - -Ham. -Pale or red? - -Hor. -Nay, very pale. - -Ham. -And fix'd his eyes upon you? - -Hor. -Most constantly. - -Ham. -I would I had been there. - -Hor. -It would have much amaz'd you. - -Ham. -Very like, very like. Stay'd it long? - -Hor. -While one with moderate haste might tell a hundred. - -Mar. and Ber. -Longer, longer. - -Hor. -Not when I saw't. - -Ham. -His beard was grizzled,--no? - -Hor. -It was, as I have seen it in his life, -A sable silver'd. - -Ham. -I will watch to-night; -Perchance 'twill walk again. - -Hor. -I warr'nt it will. - -Ham. -If it assume my noble father's person, -I'll speak to it, though hell itself should gape -And bid me hold my peace. I pray you all, -If you have hitherto conceal'd this sight, -Let it be tenable in your silence still; -And whatsoever else shall hap to-night, -Give it an understanding, but no tongue: -I will requite your loves. So, fare ye well: -Upon the platform, 'twixt eleven and twelve, -I'll visit you. - -All. -Our duty to your honour. - -Ham. -Your loves, as mine to you: farewell. - -[Exeunt Horatio, Marcellus, and Bernardo.] - -My father's spirit in arms! All is not well; -I doubt some foul play: would the night were come! -Till then sit still, my soul: foul deeds will rise, -Though all the earth o'erwhelm them, to men's eyes. - -[Exit.] - - - -Scene III. A room in Polonius's house. - -[Enter Laertes and Ophelia.] - -Laer. -My necessaries are embark'd: farewell: -And, sister, as the winds give benefit -And convoy is assistant, do not sleep, -But let me hear from you. - -Oph. -Do you doubt that? - -Laer. -For Hamlet, and the trifling of his favour, -Hold it a fashion, and a toy in blood: -A violet in the youth of primy nature, -Forward, not permanent, sweet, not lasting; -The perfume and suppliance of a minute; -No more. - -Oph. -No more but so? - -Laer. -Think it no more: -For nature, crescent, does not grow alone -In thews and bulk; but as this temple waxes, -The inward service of the mind and soul -Grows wide withal. Perhaps he loves you now; -And now no soil nor cautel doth besmirch -The virtue of his will: but you must fear, -His greatness weigh'd, his will is not his own; -For he himself is subject to his birth: -He may not, as unvalu'd persons do, -Carve for himself; for on his choice depends -The safety and health of this whole state; -And therefore must his choice be circumscrib'd -Unto the voice and yielding of that body -Whereof he is the head. Then if he says he loves you, -It fits your wisdom so far to believe it -As he in his particular act and place -May give his saying deed; which is no further -Than the main voice of Denmark goes withal. -Then weigh what loss your honour may sustain -If with too credent ear you list his songs, -Or lose your heart, or your chaste treasure open -To his unmaster'd importunity. -Fear it, Ophelia, fear it, my dear sister; -And keep you in the rear of your affection, -Out of the shot and danger of desire. -The chariest maid is prodigal enough -If she unmask her beauty to the moon: -Virtue itself scopes not calumnious strokes: -The canker galls the infants of the spring -Too oft before their buttons be disclos'd: -And in the morn and liquid dew of youth -Contagious blastments are most imminent. -Be wary then; best safety lies in fear: -Youth to itself rebels, though none else near. - -Oph. -I shall th' effect of this good lesson keep -As watchman to my heart. But, good my brother, -Do not, as some ungracious pastors do, -Show me the steep and thorny way to heaven; -Whilst, like a puff'd and reckless libertine, -Himself the primrose path of dalliance treads -And recks not his own read. - -Laer. -O, fear me not. -I stay too long:--but here my father comes. - -[Enter Polonius.] - -A double blessing is a double grace; -Occasion smiles upon a second leave. - -Pol. -Yet here, Laertes! aboard, aboard, for shame! -The wind sits in the shoulder of your sail, -And you are stay'd for. There,--my blessing with thee! - -[Laying his hand on Laertes's head.] - -And these few precepts in thy memory -Look thou character. Give thy thoughts no tongue, -Nor any unproportion'd thought his act. -Be thou familiar, but by no means vulgar. -Those friends thou hast, and their adoption tried, -Grapple them unto thy soul with hoops of steel; -But do not dull thy palm with entertainment -Of each new-hatch'd, unfledg'd comrade. Beware -Of entrance to a quarrel; but, being in, -Bear't that the opposed may beware of thee. -Give every man thine ear, but few thy voice: -Take each man's censure, but reserve thy judgment. -Costly thy habit as thy purse can buy, -But not express'd in fancy; rich, not gaudy: -For the apparel oft proclaims the man; -And they in France of the best rank and station -Are most select and generous chief in that. -Neither a borrower nor a lender be: -For loan oft loses both itself and friend; -And borrowing dulls the edge of husbandry. -This above all,--to thine own self be true; -And it must follow, as the night the day, -Thou canst not then be false to any man. -Farewell: my blessing season this in thee! - -Laer. -Most humbly do I take my leave, my lord. - -Pol. -The time invites you; go, your servants tend. - -Laer. -Farewell, Ophelia; and remember well -What I have said to you. - -Oph. -'Tis in my memory lock'd, -And you yourself shall keep the key of it. - -Laer. -Farewell. - -[Exit.] - -Pol. -What is't, Ophelia, he hath said to you? - -Oph. -So please you, something touching the Lord Hamlet. - -Pol. -Marry, well bethought: -'Tis told me he hath very oft of late -Given private time to you; and you yourself -Have of your audience been most free and bounteous; -If it be so,--as so 'tis put on me, -And that in way of caution,--I must tell you -You do not understand yourself so clearly -As it behooves my daughter and your honour. -What is between you? give me up the truth. - -Oph. -He hath, my lord, of late made many tenders -Of his affection to me. - -Pol. -Affection! pooh! you speak like a green girl, -Unsifted in such perilous circumstance. -Do you believe his tenders, as you call them? - -Oph. -I do not know, my lord, what I should think. - -Pol. -Marry, I'll teach you: think yourself a baby; -That you have ta'en these tenders for true pay, -Which are not sterling. Tender yourself more dearly; -Or,--not to crack the wind of the poor phrase, -Wronging it thus,--you'll tender me a fool. - -Oph. -My lord, he hath importun'd me with love -In honourable fashion. - -Pol. -Ay, fashion you may call it; go to, go to. - -Oph. -And hath given countenance to his speech, my lord, -With almost all the holy vows of heaven. - -Pol. -Ay, springes to catch woodcocks. I do know, -When the blood burns, how prodigal the soul -Lends the tongue vows: these blazes, daughter, -Giving more light than heat,--extinct in both, -Even in their promise, as it is a-making,-- -You must not take for fire. From this time -Be something scanter of your maiden presence; -Set your entreatments at a higher rate -Than a command to parley. For Lord Hamlet, -Believe so much in him, that he is young; -And with a larger tether may he walk -Than may be given you: in few, Ophelia, -Do not believe his vows; for they are brokers,-- -Not of that dye which their investments show, -But mere implorators of unholy suits, -Breathing like sanctified and pious bawds, -The better to beguile. This is for all,-- -I would not, in plain terms, from this time forth -Have you so slander any moment leisure -As to give words or talk with the Lord Hamlet. -Look to't, I charge you; come your ways. - -Oph. -I shall obey, my lord. - -[Exeunt.] - - - -Scene IV. The platform. - -[Enter Hamlet, Horatio, and Marcellus.] - -Ham. -The air bites shrewdly; it is very cold. - -Hor. -It is a nipping and an eager air. - -Ham. -What hour now? - -Hor. -I think it lacks of twelve. - -Mar. -No, it is struck. - -Hor. -Indeed? I heard it not: then draws near the season -Wherein the spirit held his wont to walk. - -[A flourish of trumpets, and ordnance shot off within.] - -What does this mean, my lord? - -Ham. -The King doth wake to-night and takes his rouse, -Keeps wassail, and the swaggering up-spring reels; -And, as he drains his draughts of Rhenish down, -The kettle-drum and trumpet thus bray out -The triumph of his pledge. - -Hor. -Is it a custom? - -Ham. -Ay, marry, is't; -But to my mind,--though I am native here, -And to the manner born,--it is a custom -More honour'd in the breach than the observance. -This heavy-headed revel east and west -Makes us traduc'd and tax'd of other nations: -They clepe us drunkards, and with swinish phrase -Soil our addition; and, indeed, it takes -From our achievements, though perform'd at height, -The pith and marrow of our attribute. -So oft it chances in particular men -That, for some vicious mole of nature in them, -As in their birth,--wherein they are not guilty, -Since nature cannot choose his origin,-- -By the o'ergrowth of some complexion, -Oft breaking down the pales and forts of reason; -Or by some habit, that too much o'er-leavens -The form of plausive manners;--that these men,-- -Carrying, I say, the stamp of one defect, -Being nature's livery, or fortune's star,-- -Their virtues else,--be they as pure as grace, -As infinite as man may undergo,-- -Shall in the general censure take corruption -From that particular fault: the dram of eale -Doth all the noble substance often doubt -To his own scandal. - -Hor. -Look, my lord, it comes! - -[Enter Ghost.] - -Ham. -Angels and ministers of grace defend us!-- -Be thou a spirit of health or goblin damn'd, -Bring with thee airs from heaven or blasts from hell, -Be thy intents wicked or charitable, -Thou com'st in such a questionable shape -That I will speak to thee: I'll call thee Hamlet, -King, father, royal Dane; O, answer me! -Let me not burst in ignorance; but tell -Why thy canoniz'd bones, hearsed in death, -Have burst their cerements; why the sepulchre, -Wherein we saw thee quietly in-urn'd, -Hath op'd his ponderous and marble jaws -To cast thee up again! What may this mean, -That thou, dead corse, again in complete steel, -Revisit'st thus the glimpses of the moon, -Making night hideous, and we fools of nature -So horridly to shake our disposition -With thoughts beyond the reaches of our souls? -Say, why is this? wherefore? what should we do? - -[Ghost beckons Hamlet.] - -Hor. -It beckons you to go away with it, -As if it some impartment did desire -To you alone. - -Mar. -Look with what courteous action -It waves you to a more removed ground: -But do not go with it! - -Hor. -No, by no means. - -Ham. -It will not speak; then will I follow it. - -Hor. -Do not, my lord. - -Ham. -Why, what should be the fear? -I do not set my life at a pin's fee; -And for my soul, what can it do to that, -Being a thing immortal as itself? -It waves me forth again;--I'll follow it. - -Hor. -What if it tempt you toward the flood, my lord, -Or to the dreadful summit of the cliff -That beetles o'er his base into the sea, -And there assume some other horrible form -Which might deprive your sovereignty of reason, -And draw you into madness? think of it: -The very place puts toys of desperation, -Without more motive, into every brain -That looks so many fadoms to the sea -And hears it roar beneath. - -Ham. -It waves me still.-- -Go on; I'll follow thee. - -Mar. -You shall not go, my lord. - -Ham. -Hold off your hands. - -Hor. -Be rul'd; you shall not go. - -Ham. -My fate cries out, -And makes each petty artery in this body -As hardy as the Nemean lion's nerve.-- - -[Ghost beckons.] - -Still am I call'd;--unhand me, gentlemen;-- - -[Breaking free from them.] - -By heaven, I'll make a ghost of him that lets me!-- -I say, away!--Go on; I'll follow thee. - -[Exeunt Ghost and Hamlet.] - -Hor. -He waxes desperate with imagination. - -Mar. -Let's follow; 'tis not fit thus to obey him. - -Hor. -Have after.--To what issue will this come? - -Mar. -Something is rotten in the state of Denmark. - -Hor. -Heaven will direct it. - -Mar. -Nay, let's follow him. - -[Exeunt.] - - - -Scene V. A more remote part of the Castle. - -[Enter Ghost and Hamlet.] - -Ham. -Whither wilt thou lead me? speak! I'll go no further. - -Ghost. -Mark me. - -Ham. -I will. - -Ghost. -My hour is almost come, -When I to sulph'uous and tormenting flames -Must render up myself. - -Ham. -Alas, poor ghost! - -Ghost. -Pity me not, but lend thy serious hearing -To what I shall unfold. - -Ham. -Speak;I am bound to hear. - -Ghost. -So art thou to revenge, when thou shalt hear. - -Ham. -What? - -Ghost. -I am thy father's spirit; -Doom'd for a certain term to walk the night, -And for the day confin'd to wastein fires, -Till the foul crimes done in my days of nature -Are burnt and purg'd away. But that I am forbid -To tell the secrets of my prison-house, -I could a tale unfold whose lightest word -Would harrow up thy soul; freeze thy young blood; -Make thy two eyes, like stars, start from their spheres; -Thy knotted and combined locks to part, -And each particular hair to stand on end -Like quills upon the fretful porcupine: -But this eternal blazon must not be -To ears of flesh and blood.--List, list, O, list!-- -If thou didst ever thy dear father love-- - -Ham. -O God! - -Ghost. -Revenge his foul and most unnatural murder. - -Ham. -Murder! - -Ghost. -Murder most foul, as in the best it is; -But this most foul, strange, and unnatural. - -Ham. -Haste me to know't, that I, with wings as swift -As meditation or the thoughts of love, -May sweep to my revenge. - -Ghost. -I find thee apt; -And duller shouldst thou be than the fat weed -That rots itself in ease on Lethe wharf, -Wouldst thou not stir in this. Now, Hamlet, hear. -'Tis given out that, sleeping in my orchard, -A serpent stung me; so the whole ear of Denmark -Is by a forged process of my death -Rankly abus'd; but know, thou noble youth, -The serpent that did sting thy father's life -Now wears his crown. - -Ham. -O my prophetic soul! -Mine uncle! - -Ghost. -Ay, that incestuous, that adulterate beast, -With witchcraft of his wit, with traitorous gifts,-- -O wicked wit and gifts, that have the power -So to seduce!--won to his shameful lust -The will of my most seeming-virtuous queen: -O Hamlet, what a falling-off was there! -From me, whose love was of that dignity -That it went hand in hand even with the vow -I made to her in marriage; and to decline -Upon a wretch whose natural gifts were poor -To those of mine! -But virtue, as it never will be mov'd, -Though lewdness court it in a shape of heaven; -So lust, though to a radiant angel link'd, -Will sate itself in a celestial bed -And prey on garbage. -But soft! methinks I scent the morning air; -Brief let me be.--Sleeping within my orchard, -My custom always of the afternoon, -Upon my secure hour thy uncle stole, -With juice of cursed hebenon in a vial, -And in the porches of my ears did pour -The leperous distilment; whose effect -Holds such an enmity with blood of man -That, swift as quicksilver, it courses through -The natural gates and alleys of the body; -And with a sudden vigour it doth posset -And curd, like eager droppings into milk, -The thin and wholesome blood; so did it mine; -And a most instant tetter bark'd about, -Most lazar-like, with vile and loathsome crust -All my smooth body. -Thus was I, sleeping, by a brother's hand, -Of life, of crown, of queen, at once dispatch'd: -Cut off even in the blossoms of my sin, -Unhous'led, disappointed, unanel'd; -No reckoning made, but sent to my account -With all my imperfections on my head: -O, horrible! O, horrible! most horrible! -If thou hast nature in thee, bear it not; -Let not the royal bed of Denmark be -A couch for luxury and damned incest. -But, howsoever thou pursu'st this act, -Taint not thy mind, nor let thy soul contrive -Against thy mother aught: leave her to heaven, -And to those thorns that in her bosom lodge, -To prick and sting her. Fare thee well at once! -The glowworm shows the matin to be near, -And 'gins to pale his uneffectual fire: -Adieu, adieu! Hamlet, remember me. - -[Exit.] - -Ham. -O all you host of heaven! O earth! what else? -And shall I couple hell? O, fie!--Hold, my heart; -And you, my sinews, grow not instant old, -But bear me stiffly up.--Remember thee! -Ay, thou poor ghost, while memory holds a seat -In this distracted globe. Remember thee! -Yea, from the table of my memory -I'll wipe away all trivial fond records, -All saws of books, all forms, all pressures past, -That youth and observation copied there; -And thy commandment all alone shall live -Within the book and volume of my brain, -Unmix'd with baser matter: yes, by heaven!-- -O most pernicious woman! -O villain, villain, smiling, damned villain! -My tables,--meet it is I set it down, -That one may smile, and smile, and be a villain; -At least, I am sure, it may be so in Denmark: - -[Writing.] - -So, uncle, there you are. Now to my word; -It is 'Adieu, adieu! remember me:' -I have sworn't. - -Hor. -[Within.] My lord, my lord,-- - -Mar. -[Within.] Lord Hamlet,-- - -Hor. -[Within.] Heaven secure him! - -Ham. -So be it! - -Mar. -[Within.] Illo, ho, ho, my lord! - -Ham. -Hillo, ho, ho, boy! Come, bird, come. - -[Enter Horatio and Marcellus.] - -Mar. -How is't, my noble lord? - -Hor. -What news, my lord? - -Ham. -O, wonderful! - -Hor. -Good my lord, tell it. - -Ham. -No; you'll reveal it. - -Hor. -Not I, my lord, by heaven. - -Mar. -Nor I, my lord. - -Ham. -How say you then; would heart of man once think it?-- -But you'll be secret? - -Hor. and Mar. -Ay, by heaven, my lord. - -Ham. -There's ne'er a villain dwelling in all Denmark -But he's an arrant knave. - -Hor. -There needs no ghost, my lord, come from the grave -To tell us this. - -Ham. -Why, right; you are i' the right; -And so, without more circumstance at all, -I hold it fit that we shake hands and part: -You, as your business and desires shall point you,-- -For every man hath business and desire, -Such as it is;--and for my own poor part, -Look you, I'll go pray. - -Hor. -These are but wild and whirling words, my lord. - -Ham. -I'm sorry they offend you, heartily; -Yes, faith, heartily. - -Hor. -There's no offence, my lord. - -Ham. -Yes, by Saint Patrick, but there is, Horatio, -And much offence too. Touching this vision here,-- -It is an honest ghost, that let me tell you: -For your desire to know what is between us, -O'ermaster't as you may. And now, good friends, -As you are friends, scholars, and soldiers, -Give me one poor request. - -Hor. -What is't, my lord? we will. - -Ham. -Never make known what you have seen to-night. - -Hor. and Mar. -My lord, we will not. - -Ham. -Nay, but swear't. - -Hor. -In faith, -My lord, not I. - -Mar. -Nor I, my lord, in faith. - -Ham. -Upon my sword. - -Mar. -We have sworn, my lord, already. - -Ham. -Indeed, upon my sword, indeed. - -Ghost. -[Beneath.] Swear. - -Ham. -Ha, ha boy! say'st thou so? art thou there, truepenny?-- -Come on!--you hear this fellow in the cellarage,-- -Consent to swear. - -Hor. -Propose the oath, my lord. - -Ham. -Never to speak of this that you have seen, -Swear by my sword. - -Ghost. -[Beneath.] Swear. - -Ham. -Hic et ubique? then we'll shift our ground.-- -Come hither, gentlemen, -And lay your hands again upon my sword: -Never to speak of this that you have heard, -Swear by my sword. - -Ghost. -[Beneath.] Swear. - -Ham. -Well said, old mole! canst work i' the earth so fast? -A worthy pioner!--Once more remove, good friends. - -Hor. -O day and night, but this is wondrous strange! - -Ham. -And therefore as a stranger give it welcome. -There are more things in heaven and earth, Horatio, -Than are dreamt of in your philosophy. -But come;-- -Here, as before, never, so help you mercy, -How strange or odd soe'er I bear myself,-- -As I, perchance, hereafter shall think meet -To put an antic disposition on,-- -That you, at such times seeing me, never shall, -With arms encumber'd thus, or this head-shake, -Or by pronouncing of some doubtful phrase, -As 'Well, well, we know'; or 'We could, an if we would';-- -Or 'If we list to speak'; or 'There be, an if they might';-- -Or such ambiguous giving out, to note -That you know aught of me:--this is not to do, -So grace and mercy at your most need help you, -Swear. - -Ghost. -[Beneath.] Swear. - -Ham. -Rest, rest, perturbed spirit!--So, gentlemen, -With all my love I do commend me to you: -And what so poor a man as Hamlet is -May do, to express his love and friending to you, -God willing, shall not lack. Let us go in together; -And still your fingers on your lips, I pray. -The time is out of joint:--O cursed spite, -That ever I was born to set it right!-- -Nay, come, let's go together. - -[Exeunt.] - - - -Act II. - -Scene I. A room in Polonius's house. - -[Enter Polonius and Reynaldo.] - -Pol. -Give him this money and these notes, Reynaldo. - -Rey. -I will, my lord. - -Pol. -You shall do marvellous wisely, good Reynaldo, -Before You visit him, to make inquiry -Of his behaviour. - -Rey. -My lord, I did intend it. - -Pol. -Marry, well said; very well said. Look you, sir, -Enquire me first what Danskers are in Paris; -And how, and who, what means, and where they keep, -What company, at what expense; and finding, -By this encompassment and drift of question, -That they do know my son, come you more nearer -Than your particular demands will touch it: -Take you, as 'twere, some distant knowledge of him; -As thus, 'I know his father and his friends, -And in part hi;m;--do you mark this, Reynaldo? - -Rey. -Ay, very well, my lord. - -Pol. -'And in part him;--but,' you may say, 'not well: -But if't be he I mean, he's very wild; -Addicted so and so;' and there put on him -What forgeries you please; marry, none so rank -As may dishonour him; take heed of that; -But, sir, such wanton, wild, and usual slips -As are companions noted and most known -To youth and liberty. - -Rey. -As gaming, my lord. - -Pol. -Ay, or drinking, fencing, swearing, quarrelling, -Drabbing:--you may go so far. - -Rey. -My lord, that would dishonour him. - -Pol. -Faith, no; as you may season it in the charge. -You must not put another scandal on him, -That he is open to incontinency; -That's not my meaning: but breathe his faults so quaintly -That they may seem the taints of liberty; -The flash and outbreak of a fiery mind; -A savageness in unreclaimed blood, -Of general assault. - -Rey. -But, my good lord,-- - -Pol. -Wherefore should you do this? - -Rey. -Ay, my lord, -I would know that. - -Pol. -Marry, sir, here's my drift; -And I believe it is a fetch of warrant: -You laying these slight sullies on my son -As 'twere a thing a little soil'd i' the working, -Mark you, -Your party in converse, him you would sound, -Having ever seen in the prenominate crimes -The youth you breathe of guilty, be assur'd -He closes with you in this consequence; -'Good sir,' or so; or 'friend,' or 'gentleman'-- -According to the phrase or the addition -Of man and country. - -Rey. -Very good, my lord. - -Pol. -And then, sir, does he this,--he does--What was I about to say?-- -By the mass, I was about to say something:--Where did I leave? - -Rey. -At 'closes in the consequence,' at 'friend or so,' and -gentleman.' - -Pol. -At--closes in the consequence'--ay, marry! -He closes with you thus:--'I know the gentleman; -I saw him yesterday, or t'other day, -Or then, or then; with such, or such; and, as you say, -There was he gaming; there o'ertook in's rouse; -There falling out at tennis': or perchance, -'I saw him enter such a house of sale,'-- -Videlicet, a brothel,--or so forth.-- -See you now; -Your bait of falsehood takes this carp of truth: -And thus do we of wisdom and of reach, -With windlaces, and with assays of bias, -By indirections find directions out: -So, by my former lecture and advice, -Shall you my son. You have me, have you not? - -Rey. -My lord, I have. - -Pol. -God b' wi' you, fare you well. - -Rey. -Good my lord! - -Pol. -Observe his inclination in yourself. - -Rey. -I shall, my lord. - -Pol. -And let him ply his music. - -Rey. -Well, my lord. - -Pol. -Farewell! - -[Exit Reynaldo.] - -[Enter Ophelia.] - -How now, Ophelia! what's the matter? - -Oph. -Alas, my lord, I have been so affrighted! - -Pol. -With what, i' the name of God? - -Oph. -My lord, as I was sewing in my chamber, -Lord Hamlet,--with his doublet all unbrac'd; -No hat upon his head; his stockings foul'd, -Ungart'red, and down-gyved to his ankle; -Pale as his shirt; his knees knocking each other; -And with a look so piteous in purport -As if he had been loosed out of hell -To speak of horrors,--he comes before me. - -Pol. -Mad for thy love? - -Oph. -My lord, I do not know; -But truly I do fear it. - -Pol. -What said he? - -Oph. -He took me by the wrist, and held me hard; -Then goes he to the length of all his arm; -And with his other hand thus o'er his brow, -He falls to such perusal of my face -As he would draw it. Long stay'd he so; -At last,--a little shaking of mine arm, -And thrice his head thus waving up and down,-- -He rais'd a sigh so piteous and profound -As it did seem to shatter all his bulk -And end his being: that done, he lets me go: -And, with his head over his shoulder turn'd -He seem'd to find his way without his eyes; -For out o' doors he went without their help, -And to the last bended their light on me. - -Pol. -Come, go with me: I will go seek the king. -This is the very ecstasy of love; -Whose violent property fordoes itself, -And leads the will to desperate undertakings, -As oft as any passion under heaven -That does afflict our natures. I am sorry,-- -What, have you given him any hard words of late? - -Oph. -No, my good lord; but, as you did command, -I did repel his letters and denied -His access to me. - -Pol. -That hath made him mad. -I am sorry that with better heed and judgment -I had not quoted him: I fear'd he did but trifle, -And meant to wreck thee; but beshrew my jealousy! -It seems it as proper to our age -To cast beyond ourselves in our opinions -As it is common for the younger sort -To lack discretion. Come, go we to the king: -This must be known; which, being kept close, might move -More grief to hide than hate to utter love. - -[Exeunt.] - - - -Scene II. A room in the Castle. - -[Enter King, Rosencrantz, Guildenstern, and Attendants.] - -King. -Welcome, dear Rosencrantz and Guildenstern! -Moreover that we much did long to see you, -The need we have to use you did provoke -Our hasty sending. Something have you heard -Of Hamlet's transformation; so I call it, -Since nor the exterior nor the inward man -Resembles that it was. What it should be, -More than his father's death, that thus hath put him -So much from the understanding of himself, -I cannot dream of: I entreat you both -That, being of so young days brought up with him, -And since so neighbour'd to his youth and humour, -That you vouchsafe your rest here in our court -Some little time: so by your companies -To draw him on to pleasures, and to gather, -So much as from occasion you may glean, -Whether aught, to us unknown, afflicts him thus, -That, open'd, lies within our remedy. - -Queen. -Good gentlemen, he hath much talk'd of you, -And sure I am two men there are not living -To whom he more adheres. If it will please you -To show us so much gentry and good-will -As to expend your time with us awhile, -For the supply and profit of our hope, -Your visitation shall receive such thanks -As fits a king's remembrance. - -Ros. -Both your majesties -Might, by the sovereign power you have of us, -Put your dread pleasures more into command -Than to entreaty. - -Guil. -We both obey, -And here give up ourselves, in the full bent, -To lay our service freely at your feet, -To be commanded. - -King. -Thanks, Rosencrantz and gentle Guildenstern. - -Queen. -Thanks, Guildenstern and gentle Rosencrantz: -And I beseech you instantly to visit -My too-much-changed son.--Go, some of you, -And bring these gentlemen where Hamlet is. - -Guil. -Heavens make our presence and our practices -Pleasant and helpful to him! - -Queen. -Ay, amen! - -[Exeunt Rosencrantz, Guildenstern, and some Attendants]. - -[Enter Polonius.] - -Pol. -Th' ambassadors from Norway, my good lord, -Are joyfully return'd. - -King. -Thou still hast been the father of good news. - -Pol. -Have I, my lord? Assure you, my good liege, -I hold my duty, as I hold my soul, -Both to my God and to my gracious king: -And I do think,--or else this brain of mine -Hunts not the trail of policy so sure -As it hath us'd to do,--that I have found -The very cause of Hamlet's lunacy. - -King. -O, speak of that; that do I long to hear. - -Pol. -Give first admittance to the ambassadors; -My news shall be the fruit to that great feast. - -King. -Thyself do grace to them, and bring them in. - -[Exit Polonius.] - -He tells me, my sweet queen, he hath found -The head and source of all your son's distemper. - -Queen. -I doubt it is no other but the main,-- -His father's death and our o'erhasty marriage. - -King. -Well, we shall sift him. - -[Enter Polonius, with Voltimand and Cornelius.] - -Welcome, my good friends! -Say, Voltimand, what from our brother Norway? - -Volt. -Most fair return of greetings and desires. -Upon our first, he sent out to suppress -His nephew's levies; which to him appear'd -To be a preparation 'gainst the Polack; -But, better look'd into, he truly found -It was against your highness; whereat griev'd,-- -That so his sickness, age, and impotence -Was falsely borne in hand,--sends out arrests -On Fortinbras; which he, in brief, obeys; -Receives rebuke from Norway; and, in fine, -Makes vow before his uncle never more -To give th' assay of arms against your majesty. -Whereon old Norway, overcome with joy, -Gives him three thousand crowns in annual fee; -And his commission to employ those soldiers, -So levied as before, against the Polack: -With an entreaty, herein further shown, -[Gives a paper.] -That it might please you to give quiet pass -Through your dominions for this enterprise, -On such regards of safety and allowance -As therein are set down. - -King. -It likes us well; -And at our more consider'd time we'll read, -Answer, and think upon this business. -Meantime we thank you for your well-took labour: -Go to your rest; at night we'll feast together: -Most welcome home! - -[Exeunt Voltimand and Cornelius.] - -Pol. -This business is well ended.-- -My liege, and madam,--to expostulate -What majesty should be, what duty is, -Why day is day, night is night, and time is time. -Were nothing but to waste night, day, and time. -Therefore, since brevity is the soul of wit, -And tediousness the limbs and outward flourishes, -I will be brief:--your noble son is mad: -Mad call I it; for to define true madness, -What is't but to be nothing else but mad? -But let that go. - -Queen. -More matter, with less art. - -Pol. -Madam, I swear I use no art at all. -That he is mad, 'tis true: 'tis true 'tis pity; -And pity 'tis 'tis true: a foolish figure; -But farewell it, for I will use no art. -Mad let us grant him then: and now remains -That we find out the cause of this effect; -Or rather say, the cause of this defect, -For this effect defective comes by cause: -Thus it remains, and the remainder thus. -Perpend. -I have a daughter,--have whilst she is mine,-- -Who, in her duty and obedience, mark, -Hath given me this: now gather, and surmise. -[Reads.] -'To the celestial, and my soul's idol, the most beautified -Ophelia,'-- -That's an ill phrase, a vile phrase; 'beautified' is a vile -phrase: but you shall hear. Thus: -[Reads.] -'In her excellent white bosom, these, &c.' - -Queen. -Came this from Hamlet to her? - -Pol. -Good madam, stay awhile; I will be faithful. -[Reads.] - 'Doubt thou the stars are fire; - Doubt that the sun doth move; - Doubt truth to be a liar; - But never doubt I love. -'O dear Ophelia, I am ill at these numbers; I have not art to -reckon my groans: but that I love thee best, O most best, believe -it. Adieu. - 'Thine evermore, most dear lady, whilst this machine is to him, - HAMLET.' -This, in obedience, hath my daughter show'd me; -And more above, hath his solicitings, -As they fell out by time, by means, and place, -All given to mine ear. - -King. -But how hath she -Receiv'd his love? - -Pol. -What do you think of me? - -King. -As of a man faithful and honourable. - -Pol. -I would fain prove so. But what might you think, -When I had seen this hot love on the wing,-- -As I perceiv'd it, I must tell you that, -Before my daughter told me,-- what might you, -Or my dear majesty your queen here, think, -If I had play'd the desk or table-book, -Or given my heart a winking, mute and dumb; -Or look'd upon this love with idle sight;-- -What might you think? No, I went round to work, -And my young mistress thus I did bespeak: -'Lord Hamlet is a prince, out of thy sphere; -This must not be:' and then I precepts gave her, -That she should lock herself from his resort, -Admit no messengers, receive no tokens. -Which done, she took the fruits of my advice; -And he, repulsed,--a short tale to make,-- -Fell into a sadness; then into a fast; -Thence to a watch; thence into a weakness; -Thence to a lightness; and, by this declension, -Into the madness wherein now he raves, -And all we wail for. - -King. -Do you think 'tis this? - -Queen. -It may be, very likely. - -Pol. -Hath there been such a time,--I'd fain know that-- -That I have positively said ''Tis so,' -When it prov'd otherwise? - -King. -Not that I know. - -Pol. -Take this from this, if this be otherwise: -[Points to his head and shoulder.] -If circumstances lead me, I will find -Where truth is hid, though it were hid indeed -Within the centre. - -King. -How may we try it further? - -Pol. -You know sometimes he walks for hours together -Here in the lobby. - -Queen. -So he does indeed. - -Pol. -At such a time I'll loose my daughter to him: -Be you and I behind an arras then; -Mark the encounter: if he love her not, -And he not from his reason fall'n thereon -Let me be no assistant for a state, -But keep a farm and carters. - -King. -We will try it. - -Queen. -But look where sadly the poor wretch comes reading. - -Pol. -Away, I do beseech you, both away -I'll board him presently:--O, give me leave. - -[Exeunt King, Queen, and Attendants.] - -[Enter Hamlet, reading.] - -How does my good Lord Hamlet? - -Ham. -Well, God-a-mercy. - -Pol. -Do you know me, my lord? - -Ham. -Excellent well; you're a fishmonger. - -Pol. -Not I, my lord. - -Ham. -Then I would you were so honest a man. - -Pol. -Honest, my lord! - -Ham. -Ay, sir; to be honest, as this world goes, is to be one man -picked out of ten thousand. - -Pol. -That's very true, my lord. - -Ham. -For if the sun breed maggots in a dead dog, being a god-kissing -carrion,--Have you a daughter? - -Pol. -I have, my lord. - -Ham. -Let her not walk i' the sun: conception is a blessing, but not -as your daughter may conceive:--friend, look to't. - -Pol. -How say you by that?--[Aside.] Still harping on my daughter:--yet -he knew me not at first; he said I was a fishmonger: he is far -gone, far gone: and truly in my youth I suffered much extremity -for love; very near this. I'll speak to him again.--What do you -read, my lord? - -Ham. -Words, words, words. - -Pol. -What is the matter, my lord? - -Ham. -Between who? - -Pol. -I mean, the matter that you read, my lord. - -Ham. -Slanders, sir: for the satirical slave says here that old men -have grey beards; that their faces are wrinkled; their eyes -purging thick amber and plum-tree gum; and that they have a -plentiful lack of wit, together with most weak hams: all which, -sir, though I most powerfully and potently believe, yet I hold it -not honesty to have it thus set down; for you yourself, sir, -should be old as I am, if, like a crab, you could go backward. - -Pol. -[Aside.] Though this be madness, yet there is a method in't.-- -Will you walk out of the air, my lord? - -Ham. -Into my grave? - -Pol. -Indeed, that is out o' the air. [Aside.] How pregnant sometimes -his replies are! a happiness that often madness hits on, which -reason and sanity could not so prosperously be delivered of. I -will leave him and suddenly contrive the means of meeting between -him and my daughter.--My honourable lord, I will most humbly take -my leave of you. - -Ham. -You cannot, sir, take from me anything that I will more -willingly part withal,--except my life, except my life, except my -life. - -Pol. -Fare you well, my lord. - -Ham. -These tedious old fools! - -[Enter Rosencrantz and Guildenstern.] - -Pol. -You go to seek the Lord Hamlet; there he is. - -Ros. -[To Polonius.] God save you, sir! - -[Exit Polonius.] - -Guil. -My honoured lord! - -Ros. -My most dear lord! - -Ham. -My excellent good friends! How dost thou, Guildenstern? Ah, -Rosencrantz! Good lads, how do ye both? - -Ros. -As the indifferent children of the earth. - -Guil. -Happy in that we are not over-happy; -On fortune's cap we are not the very button. - -Ham. -Nor the soles of her shoe? - -Ros. -Neither, my lord. - -Ham. -Then you live about her waist, or in the middle of her -favours? - -Guil. -Faith, her privates we. - -Ham. -In the secret parts of fortune? O, most true; she is a -strumpet. What's the news? - -Ros. -None, my lord, but that the world's grown honest. - -Ham. -Then is doomsday near; but your news is not true. Let me -question more in particular: what have you, my good friends, -deserved at the hands of fortune, that she sends you to prison -hither? - -Guil. -Prison, my lord! - -Ham. -Denmark's a prison. - -Ros. -Then is the world one. - -Ham. -A goodly one; in which there are many confines, wards, and -dungeons, Denmark being one o' the worst. - -Ros. -We think not so, my lord. - -Ham. -Why, then 'tis none to you; for there is nothing either good -or bad but thinking makes it so: to me it is a prison. - -Ros. -Why, then, your ambition makes it one; 'tis too narrow for your -mind. - -Ham. -O God, I could be bounded in a nutshell, and count myself a -king of infinite space, were it not that I have bad dreams. - -Guil. -Which dreams, indeed, are ambition; for the very substance of -the ambitious is merely the shadow of a dream. - -Ham. -A dream itself is but a shadow. - -Ros. -Truly, and I hold ambition of so airy and light a quality that -it is but a shadow's shadow. - -Ham. -Then are our beggars bodies, and our monarchs and outstretch'd -heroes the beggars' shadows. Shall we to the court? for, by my -fay, I cannot reason. - -Ros. and Guild. -We'll wait upon you. - -Ham. -No such matter: I will not sort you with the rest of my -servants; for, to speak to you like an honest man, I am most -dreadfully attended. But, in the beaten way of friendship, what -make you at Elsinore? - -Ros. -To visit you, my lord; no other occasion. - -Ham. -Beggar that I am, I am even poor in thanks; but I thank you: -and sure, dear friends, my thanks are too dear a halfpenny. Were -you not sent for? Is it your own inclining? Is it a free -visitation? Come, deal justly with me: come, come; nay, speak. - -Guil. -What should we say, my lord? - -Ham. -Why, anything--but to the purpose. You were sent for; and -there is a kind of confession in your looks, which your modesties -have not craft enough to colour: I know the good king and queen -have sent for you. - -Ros. -To what end, my lord? - -Ham. -That you must teach me. But let me conjure you, by the rights -of our fellowship, by the consonancy of our youth, by the -obligation of our ever-preserved love, and by what more dear a -better proposer could charge you withal, be even and direct with -me, whether you were sent for or no. - -Ros. -[To Guildenstern.] What say you? - -Ham. -[Aside.] Nay, then, I have an eye of you.--If you love me, hold -not off. - -Guil. -My lord, we were sent for. - -Ham. -I will tell you why; so shall my anticipation prevent your -discovery, and your secrecy to the king and queen moult no -feather. I have of late,--but wherefore I know not,--lost all my -mirth, forgone all custom of exercises; and indeed, it goes so -heavily with my disposition that this goodly frame, the earth, -seems to me a sterile promontory; this most excellent canopy, the -air, look you, this brave o'erhanging firmament, this majestical -roof fretted with golden fire,--why, it appears no other thing -to me than a foul and pestilent congregation of vapours. What a -piece of work is man! How noble in reason! how infinite in -faculties! in form and moving, how express and admirable! in -action how like an angel! in apprehension, how like a god! the -beauty of the world! the paragon of animals! And yet, to me, what -is this quintessence of dust? Man delights not me; no, nor woman -neither, though by your smiling you seem to say so. - -Ros. -My lord, there was no such stuff in my thoughts. - -Ham. -Why did you laugh then, when I said 'Man delights not me'? - -Ros. -To think, my lord, if you delight not in man, what lenten -entertainment the players shall receive from you: we coted them -on the way; and hither are they coming to offer you service. - -Ham. -He that plays the king shall be welcome,--his majesty shall -have tribute of me; the adventurous knight shall use his foil and -target; the lover shall not sigh gratis; the humorous man shall -end his part in peace; the clown shall make those laugh whose -lungs are tickle o' the sere; and the lady shall say her mind -freely, or the blank verse shall halt for't. What players are -they? - -Ros. -Even those you were wont to take such delight in,--the -tragedians of the city. - -Ham. -How chances it they travel? their residence, both in -reputation and profit, was better both ways. - -Ros. -I think their inhibition comes by the means of the late -innovation. - -Ham. -Do they hold the same estimation they did when I was in the -city? Are they so followed? - -Ros. -No, indeed, are they not. - -Ham. -How comes it? do they grow rusty? - -Ros. -Nay, their endeavour keeps in the wonted pace: but there is, -sir, an aery of children, little eyases, that cry out on the top -of question, and are most tyrannically clapped for't: these are -now the fashion; and so berattle the common stages,--so they call -them,--that many wearing rapiers are afraid of goose-quills and -dare scarce come thither. - -Ham. -What, are they children? who maintains 'em? How are they -escoted? Will they pursue the quality no longer than they can -sing? will they not say afterwards, if they should grow -themselves to common players,--as it is most like, if their means -are no better,--their writers do them wrong to make them exclaim -against their own succession? - -Ros. -Faith, there has been much to do on both sides; and the nation -holds it no sin to tarre them to controversy: there was, for -awhile, no money bid for argument unless the poet and the player -went to cuffs in the question. - -Ham. -Is't possible? - -Guil. -O, there has been much throwing about of brains. - -Ham. -Do the boys carry it away? - -Ros. -Ay, that they do, my lord; Hercules and his load too. - -Ham. -It is not very strange; for my uncle is king of Denmark, and -those that would make mouths at him while my father lived, give -twenty, forty, fifty, a hundred ducats a-piece for his picture in -little. 'Sblood, there is something in this more than natural, if -philosophy could find it out. - -[Flourish of trumpets within.] - -Guil. -There are the players. - -Ham. -Gentlemen, you are welcome to Elsinore. Your hands, come: the -appurtenance of welcome is fashion and ceremony: let me comply -with you in this garb; lest my extent to the players, which I -tell you must show fairly outward, should more appear like -entertainment than yours. You are welcome: but my uncle-father -and aunt-mother are deceived. - -Guil. -In what, my dear lord? - -Ham. -I am but mad north-north-west: when the wind is southerly I -know a hawk from a handsaw. - -[Enter Polonius.] - -Pol. -Well be with you, gentlemen! - -Ham. -Hark you, Guildenstern;--and you too;--at each ear a hearer: that -great baby you see there is not yet out of his swaddling clouts. - -Ros. -Happily he's the second time come to them; for they say an old -man is twice a child. - -Ham. -I will prophesy he comes to tell me of the players; mark it.--You -say right, sir: o' Monday morning; 'twas so indeed. - -Pol. -My lord, I have news to tell you. - -Ham. -My lord, I have news to tell you. When Roscius was an actor in -Rome,-- - -Pol. -The actors are come hither, my lord. - -Ham. -Buzz, buzz! - -Pol. -Upon my honour,-- - -Ham. -Then came each actor on his ass,-- - -Pol. -The best actors in the world, either for tragedy, comedy, -history, pastoral, pastoral-comical, historical-pastoral, -tragical-historical, tragical-comical-historical-pastoral, scene -individable, or poem unlimited: Seneca cannot be too heavy nor -Plautus too light. For the law of writ and the liberty, these are -the only men. - -Ham. -O Jephthah, judge of Israel, what a treasure hadst thou! - -Pol. -What treasure had he, my lord? - -Ham. -Why-- - 'One fair daughter, and no more, - The which he loved passing well.' - - -Pol. -[Aside.] Still on my daughter. - -Ham. -Am I not i' the right, old Jephthah? - -Pol. -If you call me Jephthah, my lord, I have a daughter that I -love passing well. - -Ham. -Nay, that follows not. - -Pol. -What follows, then, my lord? - -Ham. -Why-- - 'As by lot, God wot,' -and then, you know, - 'It came to pass, as most like it was--' -The first row of the pious chanson will show you more; for look -where my abridgment comes. - -[Enter four or five Players.] - -You are welcome, masters; welcome, all:--I am glad to see thee -well.--welcome, good friends.--O, my old friend! Thy face is -valanc'd since I saw thee last; comest thou to beard me in -Denmark?--What, my young lady and mistress! By'r lady, your -ladyship is nearer to heaven than when I saw you last, by the -altitude of a chopine. Pray God, your voice, like a piece of -uncurrent gold, be not cracked within the ring.--Masters, you are -all welcome. We'll e'en to't like French falconers, fly at -anything we see: we'll have a speech straight: come, give us a -taste of your quality: come, a passionate speech. - -I Play. -What speech, my lord? - -Ham. -I heard thee speak me a speech once,--but it was never acted; -or if it was, not above once; for the play, I remember, pleased -not the million, 'twas caviare to the general; but it was,--as I -received it, and others, whose judgments in such matters cried in -the top of mine,--an excellent play, well digested in the scenes, -set down with as much modesty as cunning. I remember, one said -there were no sallets in the lines to make the matter savoury, -nor no matter in the phrase that might indite the author of -affectation; but called it an honest method, as wholesome as -sweet, and by very much more handsome than fine. One speech in it -I chiefly loved: 'twas AEneas' tale to Dido, and thereabout of it -especially where he speaks of Priam's slaughter: if it live in -your memory, begin at this line;--let me see, let me see:-- - -The rugged Pyrrhus, like th' Hyrcanian beast,-- - -it is not so:-- it begins with Pyrrhus:-- - - 'The rugged Pyrrhus,--he whose sable arms, - Black as his purpose,did the night resemble - When he lay couched in the ominous horse,-- - Hath now this dread and black complexion smear'd - With heraldry more dismal; head to foot - Now is be total gules; horridly trick'd - With blood of fathers, mothers, daughters, sons, - Bak'd and impasted with the parching streets, - That lend a tyrannous and a damned light - To their vile murders: roasted in wrath and fire, - And thus o'ersized with coagulate gore, - With eyes like carbuncles, the hellish Pyrrhus - Old grandsire Priam seeks.' - -So, proceed you. - -Pol. -'Fore God, my lord, well spoken, with good accent and good -discretion. - -I Play. - Anon he finds him, - Striking too short at Greeks: his antique sword, - Rebellious to his arm, lies where it falls, - Repugnant to command: unequal match'd, - Pyrrhus at Priam drives; in rage strikes wide; - But with the whiff and wind of his fell sword - The unnerved father falls. Then senseless Ilium, - Seeming to feel this blow, with flaming top - Stoops to his base; and with a hideous crash - Takes prisoner Pyrrhus' ear: for lo! his sword, - Which was declining on the milky head - Of reverend Priam, seem'd i' the air to stick: - So, as a painted tyrant, Pyrrhus stood; - And, like a neutral to his will and matter, - Did nothing. - But as we often see, against some storm, - A silence in the heavens, the rack stand still, - The bold winds speechless, and the orb below - As hush as death, anon the dreadful thunder - Doth rend the region; so, after Pyrrhus' pause, - A roused vengeance sets him new a-work; - And never did the Cyclops' hammers fall - On Mars's armour, forg'd for proof eterne, - With less remorse than Pyrrhus' bleeding sword - Now falls on Priam.-- - Out, out, thou strumpet, Fortune! All you gods, - In general synod, take away her power; - Break all the spokes and fellies from her wheel, - And bowl the round nave down the hill of heaven, - As low as to the fiends! - -Pol. -This is too long. - -Ham. -It shall to the barber's, with your beard.--Pr'ythee say on.-- -He's for a jig or a tale of bawdry, or he sleeps:--say on; come -to Hecuba. - -I Play. - But who, O who, had seen the mobled queen,-- - -Ham. -'The mobled queen'? - -Pol. -That's good! 'Mobled queen' is good. - -I Play. - Run barefoot up and down, threatening the flames - With bisson rheum; a clout upon that head - Where late the diadem stood, and for a robe, - About her lank and all o'erteemed loins, - A blanket, in the alarm of fear caught up;-- - Who this had seen, with tongue in venom steep'd, - 'Gainst Fortune's state would treason have pronounc'd: - But if the gods themselves did see her then, - When she saw Pyrrhus make malicious sport - In mincing with his sword her husband's limbs, - The instant burst of clamour that she made,-- - Unless things mortal move them not at all,-- - Would have made milch the burning eyes of heaven, - And passion in the gods. - -Pol. -Look, whether he has not turn'd his colour, and has tears in's -eyes.--Pray you, no more! - -Ham. -'Tis well. I'll have thee speak out the rest of this soon.-- -Good my lord, will you see the players well bestowed? Do you -hear? Let them be well used; for they are the abstracts and brief -chronicles of the time; after your death you were better have a -bad epitaph than their ill report while you live. - -Pol. -My lord, I will use them according to their desert. - -Ham. -Odd's bodikin, man, better: use every man after his -desert, and who should scape whipping? Use them after your own -honour and dignity: the less they deserve, the more merit is in -your bounty. Take them in. - -Pol. -Come, sirs. - -Ham. -Follow him, friends. we'll hear a play to-morrow. - -[Exeunt Polonius with all the Players but the First.] - -Dost thou hear me, old friend? Can you play 'The Murder of -Gonzago'? - -I Play. -Ay, my lord. - -Ham. -We'll ha't to-morrow night. You could, for a need, study a -speech of some dozen or sixteen lines which I would set down and -insert in't? could you not? - -I Play. -Ay, my lord. - -Ham. -Very well.--Follow that lord; and look you mock him not. - -[Exit First Player.] - ---My good friends [to Ros. and Guild.], I'll leave you till -night: you are welcome to Elsinore. - -Ros. -Good my lord! - -[Exeunt Rosencrantz and Guildenstern.] - -Ham. -Ay, so, God b' wi' ye! -Now I am alone. -O, what a rogue and peasant slave am I! -Is it not monstrous that this player here, -But in a fiction, in a dream of passion, -Could force his soul so to his own conceit -That from her working all his visage wan'd; -Tears in his eyes, distraction in's aspect, -A broken voice, and his whole function suiting -With forms to his conceit? And all for nothing! -For Hecuba? -What's Hecuba to him, or he to Hecuba, -That he should weep for her? What would he do, -Had he the motive and the cue for passion -That I have? He would drown the stage with tears -And cleave the general ear with horrid speech; -Make mad the guilty, and appal the free; -Confound the ignorant, and amaze, indeed, -The very faculties of eyes and ears. -Yet I, -A dull and muddy-mettled rascal, peak, -Like John-a-dreams, unpregnant of my cause, -And can say nothing; no, not for a king -Upon whose property and most dear life -A damn'd defeat was made. Am I a coward? -Who calls me villain? breaks my pate across? -Plucks off my beard and blows it in my face? -Tweaks me by the nose? gives me the lie i' the throat -As deep as to the lungs? who does me this, ha? -'Swounds, I should take it: for it cannot be -But I am pigeon-liver'd, and lack gall -To make oppression bitter; or ere this -I should have fatted all the region kites -With this slave's offal: bloody, bawdy villain! -Remorseless, treacherous, lecherous, kindless villain! -O, vengeance! -Why, what an ass am I! This is most brave, -That I, the son of a dear father murder'd, -Prompted to my revenge by heaven and hell, -Must, like a whore, unpack my heart with words -And fall a-cursing like a very drab, -A scullion! -Fie upon't! foh!--About, my brain! I have heard -That guilty creatures, sitting at a play, -Have by the very cunning of the scene -Been struck so to the soul that presently -They have proclaim'd their malefactions; -For murder, though it have no tongue, will speak -With most miraculous organ, I'll have these players -Play something like the murder of my father -Before mine uncle: I'll observe his looks; -I'll tent him to the quick: if he but blench, -I know my course. The spirit that I have seen -May be the devil: and the devil hath power -To assume a pleasing shape; yea, and perhaps -Out of my weakness and my melancholy,-- -As he is very potent with such spirits,-- -Abuses me to damn me: I'll have grounds -More relative than this.--the play's the thing -Wherein I'll catch the conscience of the king. - -[Exit.] - - - - -ACT III. - -Scene I. A room in the Castle. - -[Enter King, Queen, Polonius, Ophelia, Rosencrantz, and -Guildenstern.] - -King. -And can you, by no drift of circumstance, -Get from him why he puts on this confusion, -Grating so harshly all his days of quiet -With turbulent and dangerous lunacy? - -Ros. -He does confess he feels himself distracted, -But from what cause he will by no means speak. - -Guil. -Nor do we find him forward to be sounded, -But, with a crafty madness, keeps aloof -When we would bring him on to some confession -Of his true state. - -Queen. -Did he receive you well? - -Ros. -Most like a gentleman. - -Guil. -But with much forcing of his disposition. - -Ros. -Niggard of question; but, of our demands, -Most free in his reply. - -Queen. -Did you assay him -To any pastime? - -Ros. -Madam, it so fell out that certain players -We o'er-raught on the way: of these we told him, -And there did seem in him a kind of joy -To hear of it: they are about the court, -And, as I think, they have already order -This night to play before him. - -Pol. -'Tis most true; -And he beseech'd me to entreat your majesties -To hear and see the matter. - -King. -With all my heart; and it doth much content me -To hear him so inclin'd.-- -Good gentlemen, give him a further edge, -And drive his purpose on to these delights. - -Ros. -We shall, my lord. - -[Exeunt Rosencrantz and Guildenstern.] - -King. -Sweet Gertrude, leave us too; -For we have closely sent for Hamlet hither, -That he, as 'twere by accident, may here -Affront Ophelia: -Her father and myself,--lawful espials,-- -Will so bestow ourselves that, seeing, unseen, -We may of their encounter frankly judge; -And gather by him, as he is behav'd, -If't be the affliction of his love or no -That thus he suffers for. - -Queen. -I shall obey you:-- -And for your part, Ophelia, I do wish -That your good beauties be the happy cause -Of Hamlet's wildness: so shall I hope your virtues -Will bring him to his wonted way again, -To both your honours. - -Oph. -Madam, I wish it may. - -[Exit Queen.] - -Pol. -Ophelia, walk you here.--Gracious, so please you, -We will bestow ourselves.--[To Ophelia.] Read on this book; -That show of such an exercise may colour -Your loneliness.--We are oft to blame in this,-- -'Tis too much prov'd,--that with devotion's visage -And pious action we do sugar o'er -The Devil himself. - -King. -[Aside.] O, 'tis too true! -How smart a lash that speech doth give my conscience! -The harlot's cheek, beautied with plastering art, -Is not more ugly to the thing that helps it -Than is my deed to my most painted word: -O heavy burden! - -Pol. -I hear him coming: let's withdraw, my lord. - -[Exeunt King and Polonius.] - -[Enter Hamlet.] - -Ham. -To be, or not to be,--that is the question:-- -Whether 'tis nobler in the mind to suffer -The slings and arrows of outrageous fortune -Or to take arms against a sea of troubles, -And by opposing end them?--To die,--to sleep,-- -No more; and by a sleep to say we end -The heartache, and the thousand natural shocks -That flesh is heir to,--'tis a consummation -Devoutly to be wish'd. To die,--to sleep;-- -To sleep! perchance to dream:--ay, there's the rub; -For in that sleep of death what dreams may come, -When we have shuffled off this mortal coil, -Must give us pause: there's the respect -That makes calamity of so long life; -For who would bear the whips and scorns of time, -The oppressor's wrong, the proud man's contumely, -The pangs of despis'd love, the law's delay, -The insolence of office, and the spurns -That patient merit of the unworthy takes, -When he himself might his quietus make -With a bare bodkin? who would these fardels bear, -To grunt and sweat under a weary life, -But that the dread of something after death,-- -The undiscover'd country, from whose bourn -No traveller returns,--puzzles the will, -And makes us rather bear those ills we have -Than fly to others that we know not of? -Thus conscience does make cowards of us all; -And thus the native hue of resolution -Is sicklied o'er with the pale cast of thought; -And enterprises of great pith and moment, -With this regard, their currents turn awry, -And lose the name of action.--Soft you now! -The fair Ophelia!--Nymph, in thy orisons -Be all my sins remember'd. - -Oph. -Good my lord, -How does your honour for this many a day? - -Ham. -I humbly thank you; well, well, well. - -Oph. -My lord, I have remembrances of yours -That I have longed long to re-deliver. -I pray you, now receive them. - -Ham. -No, not I; -I never gave you aught. - -Oph. -My honour'd lord, you know right well you did; -And with them words of so sweet breath compos'd -As made the things more rich; their perfume lost, -Take these again; for to the noble mind -Rich gifts wax poor when givers prove unkind. -There, my lord. - -Ham. -Ha, ha! are you honest? - -Oph. -My lord? - -Ham. -Are you fair? - -Oph. -What means your lordship? - -Ham. -That if you be honest and fair, your honesty should admit no -discourse to your beauty. - -Oph. -Could beauty, my lord, have better commerce than with honesty? - -Ham. -Ay, truly; for the power of beauty will sooner transform -honesty from what it is to a bawd than the force of honesty can -translate beauty into his likeness: this was sometime a paradox, -but now the time gives it proof. I did love you once. - -Oph. -Indeed, my lord, you made me believe so. - -Ham. -You should not have believ'd me; for virtue cannot so -inoculate our old stock but we shall relish of it: I loved you -not. - -Oph. -I was the more deceived. - -Ham. -Get thee to a nunnery: why wouldst thou be a breeder of -sinners? I am myself indifferent honest; but yet I could accuse -me of such things that it were better my mother had not borne me: -I am very proud, revengeful, ambitious; with more offences at my -beck than I have thoughts to put them in, imagination to give -them shape, or time to act them in. What should such fellows as I -do crawling between earth and heaven? We are arrant knaves, all; -believe none of us. Go thy ways to a nunnery. Where's your -father? - -Oph. -At home, my lord. - -Ham. -Let the doors be shut upon him, that he may play the fool -nowhere but in's own house. Farewell. - -Oph. -O, help him, you sweet heavens! - -Ham. -If thou dost marry, I'll give thee this plague for thy dowry,-- -be thou as chaste as ice, as pure as snow, thou shalt not escape -calumny. Get thee to a nunnery, go: farewell. Or, if thou wilt -needs marry, marry a fool; for wise men know well enough what -monsters you make of them. To a nunnery, go; and quickly too. -Farewell. - -Oph. -O heavenly powers, restore him! - -Ham. -I have heard of your paintings too, well enough; God hath -given you one face, and you make yourselves another: you jig, you -amble, and you lisp, and nickname God's creatures, and make your -wantonness your ignorance. Go to, I'll no more on't; it hath made -me mad. I say, we will have no more marriages: those that are -married already, all but one, shall live; the rest shall keep as -they are. To a nunnery, go. - -[Exit.] - -Oph. -O, what a noble mind is here o'erthrown! -The courtier's, scholar's, soldier's, eye, tongue, sword, -The expectancy and rose of the fair state, -The glass of fashion and the mould of form, -The observ'd of all observers,--quite, quite down! -And I, of ladies most deject and wretched -That suck'd the honey of his music vows, -Now see that noble and most sovereign reason, -Like sweet bells jangled, out of tune and harsh; -That unmatch'd form and feature of blown youth -Blasted with ecstasy: O, woe is me, -To have seen what I have seen, see what I see! - -[Re-enter King and Polonius.] - -King. -Love! his affections do not that way tend; -Nor what he spake, though it lack'd form a little, -Was not like madness. There's something in his soul -O'er which his melancholy sits on brood; -And I do doubt the hatch and the disclose -Will be some danger: which for to prevent, -I have in quick determination -Thus set it down:--he shall with speed to England -For the demand of our neglected tribute: -Haply the seas, and countries different, -With variable objects, shall expel -This something-settled matter in his heart; -Whereon his brains still beating puts him thus -From fashion of himself. What think you on't? - -Pol. -It shall do well: but yet do I believe -The origin and commencement of his grief -Sprung from neglected love.--How now, Ophelia! -You need not tell us what Lord Hamlet said; -We heard it all.--My lord, do as you please; -But if you hold it fit, after the play, -Let his queen mother all alone entreat him -To show his grief: let her be round with him; -And I'll be plac'd, so please you, in the ear -Of all their conference. If she find him not, -To England send him; or confine him where -Your wisdom best shall think. - -King. -It shall be so: -Madness in great ones must not unwatch'd go. - -[Exeunt.] - - - -Scene II. A hall in the Castle. - -[Enter Hamlet and cartain Players.] - -Ham. -Speak the speech, I pray you, as I pronounced it to you, -trippingly on the tongue: but if you mouth it, as many of your -players do, I had as lief the town crier spoke my lines. Nor do -not saw the air too much with your hand, thus, but use all -gently: for in the very torrent, tempest, and, as I may say, -whirlwind of passion, you must acquire and beget a -temperance that may give it smoothness. O, it offends me to the -soul, to hear a robustious periwig-pated fellow tear a passion to -tatters, to very rags, to split the cars of the groundlings, who, -for the most part, are capable of nothing but inexplicable dumb -shows and noise: I would have such a fellow whipped for o'erdoing -Termagant; it out-herods Herod: pray you avoid it. - -I Player. -I warrant your honour. - -Ham. -Be not too tame neither; but let your own discretion be your -tutor: suit the action to the word, the word to the action; with -this special observance, that you o'erstep not the modesty of -nature: for anything so overdone is from the purpose of playing, -whose end, both at the first and now, was and is, to hold, as -'twere, the mirror up to nature; to show virtue her own image, -scorn her own image, and the very age and body of the time his -form and pressure. Now, this overdone, or come tardy off, though -it make the unskilful laugh, cannot but make the judicious -grieve; the censure of the which one must in your allowance, -o'erweigh a whole theatre of others. O, there be players that I -have seen play,--and heard others praise, and that highly,--not -to speak it profanely, that, neither having the accent of -Christians, nor the gait of Christian, pagan, nor man, have so -strutted and bellowed that I have thought some of nature's -journeymen had made men, and not made them well, they imitated -humanity so abominably. - -I Player. -I hope we have reform'd that indifferently with us, sir. - -Ham. -O, reform it altogether. And let those that play your clowns -speak no more than is set down for them: for there be of them -that will themselves laugh, to set on some quantity of barren -spectators to laugh too, though in the meantime some necessary -question of the play be then to be considered: that's villanous -and shows a most pitiful ambition in the fool that uses it. Go -make you ready. - -[Exeunt Players.] - -[Enter Polonius, Rosencrantz, and Guildenstern.] - -How now, my lord! will the king hear this piece of work? - -Pol. -And the queen too, and that presently. - -Ham. -Bid the players make haste. - -[Exit Polonius.] - -Will you two help to hasten them? - -Ros. and Guil. -We will, my lord. - -[Exeunt Ros. and Guil.] - -Ham. -What, ho, Horatio! - -[Enter Horatio.] - -Hor. -Here, sweet lord, at your service. - -Ham. -Horatio, thou art e'en as just a man -As e'er my conversation cop'd withal. - -Hor. -O, my dear lord,-- - -Ham. -Nay, do not think I flatter; -For what advancement may I hope from thee, -That no revenue hast, but thy good spirits, -To feed and clothe thee? Why should the poor be flatter'd? -No, let the candied tongue lick absurd pomp; -And crook the pregnant hinges of the knee -Where thrift may follow fawning. Dost thou hear? -Since my dear soul was mistress of her choice, -And could of men distinguish, her election -Hath seal'd thee for herself: for thou hast been -As one, in suffering all, that suffers nothing; -A man that Fortune's buffets and rewards -Hast ta'en with equal thanks: and bles'd are those -Whose blood and judgment are so well commingled -That they are not a pipe for Fortune's finger -To sound what stop she please. Give me that man -That is not passion's slave, and I will wear him -In my heart's core, ay, in my heart of heart, -As I do thee.--Something too much of this.-- -There is a play to-night before the king; -One scene of it comes near the circumstance, -Which I have told thee, of my father's death: -I pr'ythee, when thou see'st that act a-foot, -Even with the very comment of thy soul -Observe mine uncle: if his occulted guilt -Do not itself unkennel in one speech, -It is a damned ghost that we have seen; -And my imaginations are as foul -As Vulcan's stithy. Give him heedful note; -For I mine eyes will rivet to his face; -And, after, we will both our judgments join -In censure of his seeming. - -Hor. -Well, my lord: -If he steal aught the whilst this play is playing, -And scape detecting, I will pay the theft. - -Ham. -They are coming to the play. I must be idle: -Get you a place. - -[Danish march. A flourish. Enter King, Queen, Polonius, Ophelia, -Rosencrantz, Guildenstern, and others.] - -King. -How fares our cousin Hamlet? - -Ham. -Excellent, i' faith; of the chameleon's dish: I eat the air, -promise-crammed: you cannot feed capons so. - -King. -I have nothing with this answer, Hamlet; these words are not -mine. - -Ham. -No, nor mine now. My lord, you play'd once i' the university, you -say? [To Polonius.] - -Pol. -That did I, my lord, and was accounted a good actor. - -Ham. -What did you enact? - -Pol. -I did enact Julius Caesar; I was kill'd i' the Capitol; Brutus -killed me. - -Ham. -It was a brute part of him to kill so capital a calf there.--Be -the players ready? - -Ros. -Ay, my lord; they stay upon your patience. - -Queen. -Come hither, my dear Hamlet, sit by me. - -Ham. -No, good mother, here's metal more attractive. - -Pol. -O, ho! do you mark that? [To the King.] - -Ham. -Lady, shall I lie in your lap? -[Lying down at Ophelia's feet.] - -Oph. -No, my lord. - -Ham. -I mean, my head upon your lap? - -Oph. -Ay, my lord. - -Ham. -Do you think I meant country matters? - -Oph. -I think nothing, my lord. - -Ham. -That's a fair thought to lie between maids' legs. - -Oph. -What is, my lord? - -Ham. -Nothing. - -Oph. -You are merry, my lord. - -Ham. -Who, I? - -Oph. -Ay, my lord. - -Ham. -O, your only jig-maker! What should a man do but be merry? -for look you how cheerfully my mother looks, and my father died -within 's two hours. - -Oph. -Nay, 'tis twice two months, my lord. - -Ham. -So long? Nay then, let the devil wear black, for I'll have a -suit of sables. O heavens! die two months ago, and not forgotten -yet? Then there's hope a great man's memory may outlive his life -half a year: but, by'r lady, he must build churches then; or else -shall he suffer not thinking on, with the hobby-horse, whose -epitaph is 'For, O, for, O, the hobby-horse is forgot!' - -[Trumpets sound. The dumb show enters.] - -[Enter a King and a Queen very lovingly; the Queen embracing -him and he her. She kneels, and makes show of protestation -unto him. He takes her up, and declines his head upon her -neck: lays him down upon a bank of flowers: she, seeing -him asleep, leaves him. Anon comes in a fellow, takes off his -crown, kisses it, pours poison in the king's ears, and exit. The -Queen returns, finds the King dead, and makes passionate action. -The Poisoner with some three or four Mutes, comes in again, -seeming to lament with her. The dead body is carried away. The -Poisoner wooes the Queen with gifts; she seems loth and unwilling -awhile, but in the end accepts his love.] - -[Exeunt.] - -Oph. -What means this, my lord? - -Ham. -Marry, this is miching mallecho; it means mischief. - -Oph. -Belike this show imports the argument of the play. - -[Enter Prologue.] - -Ham. -We shall know by this fellow: the players cannot keep counsel; -they'll tell all. - -Oph. -Will he tell us what this show meant? - -Ham. -Ay, or any show that you'll show him: be not you ashamed to -show, he'll not shame to tell you what it means. - -Oph. -You are naught, you are naught: I'll mark the play. - -Pro. - For us, and for our tragedy, - Here stooping to your clemency, - We beg your hearing patiently. - -Ham. -Is this a prologue, or the posy of a ring? - -Oph. -'Tis brief, my lord. - -Ham. -As woman's love. - -[Enter a King and a Queen.] - -P. King. -Full thirty times hath Phoebus' cart gone round -Neptune's salt wash and Tellus' orbed ground, -And thirty dozen moons with borrow'd sheen -About the world have times twelve thirties been, -Since love our hearts, and Hymen did our hands, -Unite commutual in most sacred bands. - -P. Queen. -So many journeys may the sun and moon -Make us again count o'er ere love be done! -But, woe is me, you are so sick of late, -So far from cheer and from your former state. -That I distrust you. Yet, though I distrust, -Discomfort you, my lord, it nothing must: -For women's fear and love holds quantity; -In neither aught, or in extremity. -Now, what my love is, proof hath made you know; -And as my love is siz'd, my fear is so: -Where love is great, the littlest doubts are fear; -Where little fears grow great, great love grows there. - -P. King. -Faith, I must leave thee, love, and shortly too; -My operant powers their functions leave to do: -And thou shalt live in this fair world behind, -Honour'd, belov'd, and haply one as kind -For husband shalt thou,-- - -P. Queen. -O, confound the rest! -Such love must needs be treason in my breast: -In second husband let me be accurst! -None wed the second but who kill'd the first. - -Ham. -[Aside.] Wormwood, wormwood! - -P. Queen. -The instances that second marriage move -Are base respects of thrift, but none of love. -A second time I kill my husband dead -When second husband kisses me in bed. - -P. King. -I do believe you think what now you speak; -But what we do determine oft we break. -Purpose is but the slave to memory; -Of violent birth, but poor validity: -Which now, like fruit unripe, sticks on the tree; -But fall unshaken when they mellow be. -Most necessary 'tis that we forget -To pay ourselves what to ourselves is debt: -What to ourselves in passion we propose, -The passion ending, doth the purpose lose. -The violence of either grief or joy -Their own enactures with themselves destroy: -Where joy most revels, grief doth most lament; -Grief joys, joy grieves, on slender accident. -This world is not for aye; nor 'tis not strange -That even our loves should with our fortunes change; -For 'tis a question left us yet to prove, -Whether love lead fortune, or else fortune love. -The great man down, you mark his favourite flies, -The poor advanc'd makes friends of enemies; -And hitherto doth love on fortune tend: -For who not needs shall never lack a friend; -And who in want a hollow friend doth try, -Directly seasons him his enemy. -But, orderly to end where I begun,-- -Our wills and fates do so contrary run -That our devices still are overthrown; -Our thoughts are ours, their ends none of our own: -So think thou wilt no second husband wed; -But die thy thoughts when thy first lord is dead. - -P. Queen. -Nor earth to me give food, nor heaven light! -Sport and repose lock from me day and night! -To desperation turn my trust and hope! -An anchor's cheer in prison be my scope! -Each opposite that blanks the face of joy -Meet what I would have well, and it destroy! -Both here and hence pursue me lasting strife, -If, once a widow, ever I be wife! - -Ham. -If she should break it now! [To Ophelia.] - -P. King. -'Tis deeply sworn. Sweet, leave me here awhile; -My spirits grow dull, and fain I would beguile -The tedious day with sleep. -[Sleeps.] - -P. Queen. -Sleep rock thy brain, -And never come mischance between us twain! - -[Exit.] - -Ham. -Madam, how like you this play? - -Queen. -The lady protests too much, methinks. - -Ham. -O, but she'll keep her word. - -King. -Have you heard the argument? Is there no offence in't? - -Ham. -No, no! They do but jest, poison in jest; no offence i' the -world. - -King. -What do you call the play? - -Ham. -The Mouse-trap. Marry, how? Tropically. This play is the -image of a murder done in Vienna: Gonzago is the duke's name; -his wife, Baptista: you shall see anon; 'tis a knavish piece of -work: but what o' that? your majesty, and we that have free -souls, it touches us not: let the gall'd jade wince; our withers -are unwrung. - -[Enter Lucianus.] - -This is one Lucianus, nephew to the King. - -Oph. -You are a good chorus, my lord. - -Ham. -I could interpret between you and your love, if I could see -the puppets dallying. - -Oph. -You are keen, my lord, you are keen. - -Ham. -It would cost you a groaning to take off my edge. - -Oph. -Still better, and worse. - -Ham. -So you must take your husbands.--Begin, murderer; pox, leave -thy damnable faces, and begin. Come:--'The croaking raven doth -bellow for revenge.' - -Luc. -Thoughts black, hands apt, drugs fit, and time agreeing; -Confederate season, else no creature seeing; -Thou mixture rank, of midnight weeds collected, -With Hecate's ban thrice blasted, thrice infected, -Thy natural magic and dire property -On wholesome life usurp immediately. - -[Pours the poison into the sleeper's ears.] - -Ham. -He poisons him i' the garden for's estate. His name's Gonzago: -The story is extant, and written in very choice Italian; you -shall see anon how the murderer gets the love of Gonzago's wife. - -Oph. -The King rises. - -Ham. -What, frighted with false fire! - -Queen. -How fares my lord? - -Pol. -Give o'er the play. - -King. -Give me some light:--away! - -All. -Lights, lights, lights! - -[Exeunt all but Hamlet and Horatio.] - -Ham. - Why, let the strucken deer go weep, - The hart ungalled play; - For some must watch, while some must sleep: - So runs the world away.-- -Would not this, sir, and a forest of feathers--if the rest of my -fortunes turn Turk with me,--with two Provincial roses on my -razed shoes, get me a fellowship in a cry of players, sir? - -Hor. -Half a share. - -Ham. - A whole one, I. - For thou dost know, O Damon dear, - This realm dismantled was - Of Jove himself; and now reigns here - A very, very--pajock. - -Hor. -You might have rhymed. - -Ham. -O good Horatio, I'll take the ghost's word for a thousand -pound! Didst perceive? - -Hor. -Very well, my lord. - -Ham. -Upon the talk of the poisoning?-- - -Hor. -I did very well note him. - -Ham. -Ah, ha!--Come, some music! Come, the recorders!-- - For if the king like not the comedy, - Why then, belike he likes it not, perdy. -Come, some music! - -[Enter Rosencrantz and Guildenstern.] - -Guil. -Good my lord, vouchsafe me a word with you. - -Ham. -Sir, a whole history. - -Guil. -The king, sir-- - -Ham. -Ay, sir, what of him? - -Guil. -Is, in his retirement, marvellous distempered. - -Ham. -With drink, sir? - -Guil. -No, my lord; rather with choler. - -Ham. -Your wisdom should show itself more richer to signify this to -the doctor; for me to put him to his purgation would perhaps -plunge him into far more choler. - -Guil. -Good my lord, put your discourse into some frame, and start -not so wildly from my affair. - -Ham. -I am tame, sir:--pronounce. - -Guil. -The queen, your mother, in most great affliction of spirit, -hath sent me to you. - -Ham. -You are welcome. - -Guil. -Nay, good my lord, this courtesy is not of the right breed. -If it shall please you to make me a wholesome answer, I will do -your mother's commandment: if not, your pardon and my return -shall be the end of my business. - -Ham. -Sir, I cannot. - -Guil. -What, my lord? - -Ham. -Make you a wholesome answer; my wit's diseased: but, sir, such -answer as I can make, you shall command; or rather, as you say, -my mother: therefore no more, but to the matter: my mother, you -say,-- - -Ros. -Then thus she says: your behaviour hath struck her into -amazement and admiration. - -Ham. -O wonderful son, that can so stonish a mother!--But is there no -sequel at the heels of this mother's admiration? - -Ros. -She desires to speak with you in her closet ere you go to bed. - -Ham. -We shall obey, were she ten times our mother. Have you any -further trade with us? - -Ros. -My lord, you once did love me. - -Ham. -And so I do still, by these pickers and stealers. - -Ros. -Good my lord, what is your cause of distemper? you do, surely, -bar the door upon your own liberty if you deny your griefs to -your friend. - -Ham. -Sir, I lack advancement. - -Ros. -How can that be, when you have the voice of the king himself -for your succession in Denmark? - -Ham. -Ay, sir, but 'While the grass grows'--the proverb is something -musty. - -[Re-enter the Players, with recorders.] - -O, the recorders:--let me see one.--To withdraw with you:--why do -you go about to recover the wind of me, as if you would drive me -into a toil? - -Guil. -O my lord, if my duty be too bold, my love is too unmannerly. - -Ham. -I do not well understand that. Will you play upon this pipe? - -Guil. -My lord, I cannot. - -Ham. -I pray you. - -Guil. -Believe me, I cannot. - -Ham. -I do beseech you. - -Guil. -I know, no touch of it, my lord. - -Ham. -'Tis as easy as lying: govern these ventages with your -finger and thumb, give it breath with your mouth, and it will -discourse most eloquent music. Look you, these are the stops. - -Guil. -But these cannot I command to any utterance of harmony; I -have not the skill. - -Ham. -Why, look you now, how unworthy a thing you make of me! You -would play upon me; you would seem to know my stops; you would -pluck out the heart of my mystery; you would sound me from my -lowest note to the top of my compass; and there is much music, -excellent voice, in this little organ, yet cannot you make it -speak. 'Sblood, do you think I am easier to be played on than a -pipe? Call me what instrument you will, though you can fret me, -you cannot play upon me. - -[Enter Polonius.] - -God bless you, sir! - -Pol. -My lord, the queen would speak with you, and presently. - -Ham. -Do you see yonder cloud that's almost in shape of a camel? - -Pol. -By the mass, and 'tis like a camel indeed. - -Ham. -Methinks it is like a weasel. - -Pol. -It is backed like a weasel. - -Ham. -Or like a whale. - -Pol. -Very like a whale. - -Ham. -Then will I come to my mother by and by.--They fool me to the -top of my bent.--I will come by and by. - -Pol. -I will say so. - -[Exit.] - -Ham. -By-and-by is easily said. - -[Exit Polonius.] - ---Leave me, friends. - -[Exeunt Ros, Guil., Hor., and Players.] - -'Tis now the very witching time of night, -When churchyards yawn, and hell itself breathes out -Contagion to this world: now could I drink hot blood, -And do such bitter business as the day -Would quake to look on. Soft! now to my mother.-- -O heart, lose not thy nature; let not ever -The soul of Nero enter this firm bosom: -Let me be cruel, not unnatural; -I will speak daggers to her, but use none; -My tongue and soul in this be hypocrites,-- -How in my words somever she be shent, -To give them seals never, my soul, consent! - -[Exit.] - - - -Scene III. A room in the Castle. - -[Enter King, Rosencrantz, and Guildenstern.] - -King. -I like him not; nor stands it safe with us -To let his madness range. Therefore prepare you; -I your commission will forthwith dispatch, -And he to England shall along with you: -The terms of our estate may not endure -Hazard so near us as doth hourly grow -Out of his lunacies. - -Guil. -We will ourselves provide: -Most holy and religious fear it is -To keep those many many bodies safe -That live and feed upon your majesty. - -Ros. -The single and peculiar life is bound, -With all the strength and armour of the mind, -To keep itself from 'noyance; but much more -That spirit upon whose weal depend and rest -The lives of many. The cease of majesty -Dies not alone; but like a gulf doth draw -What's near it with it: it is a massy wheel, -Fix'd on the summit of the highest mount, -To whose huge spokes ten thousand lesser things -Are mortis'd and adjoin'd; which, when it falls, -Each small annexment, petty consequence, -Attends the boisterous ruin. Never alone -Did the king sigh, but with a general groan. - -King. -Arm you, I pray you, to this speedy voyage; -For we will fetters put upon this fear, -Which now goes too free-footed. - -Ros and Guil. -We will haste us. - -[Exeunt Ros. and Guil.] - -[Enter Polonius.] - -Pol. -My lord, he's going to his mother's closet: -Behind the arras I'll convey myself -To hear the process; I'll warrant she'll tax him home: -And, as you said, and wisely was it said, -'Tis meet that some more audience than a mother, -Since nature makes them partial, should o'erhear -The speech, of vantage. Fare you well, my liege: -I'll call upon you ere you go to bed, -And tell you what I know. - -King. -Thanks, dear my lord. - -[Exit Polonius.] - -O, my offence is rank, it smells to heaven; -It hath the primal eldest curse upon't,-- -A brother's murder!--Pray can I not, -Though inclination be as sharp as will: -My stronger guilt defeats my strong intent; -And, like a man to double business bound, -I stand in pause where I shall first begin, -And both neglect. What if this cursed hand -Were thicker than itself with brother's blood,-- -Is there not rain enough in the sweet heavens -To wash it white as snow? Whereto serves mercy -But to confront the visage of offence? -And what's in prayer but this twofold force,-- -To be forestalled ere we come to fall, -Or pardon'd being down? Then I'll look up; -My fault is past. But, O, what form of prayer -Can serve my turn? Forgive me my foul murder!-- -That cannot be; since I am still possess'd -Of those effects for which I did the murder,-- -My crown, mine own ambition, and my queen. -May one be pardon'd and retain the offence? -In the corrupted currents of this world -Offence's gilded hand may shove by justice; -And oft 'tis seen the wicked prize itself -Buys out the law; but 'tis not so above; -There is no shuffling;--there the action lies -In his true nature; and we ourselves compell'd, -Even to the teeth and forehead of our faults, -To give in evidence. What then? what rests? -Try what repentance can: what can it not? -Yet what can it when one cannot repent? -O wretched state! O bosom black as death! -O limed soul, that, struggling to be free, -Art more engag'd! Help, angels! Make assay: -Bow, stubborn knees; and, heart, with strings of steel, -Be soft as sinews of the new-born babe! -All may be well. - -[Retires and kneels.] - -[Enter Hamlet.] - -Ham. -Now might I do it pat, now he is praying; -And now I'll do't;--and so he goes to heaven; -And so am I reveng'd.--that would be scann'd: -A villain kills my father; and for that, -I, his sole son, do this same villain send -To heaven. -O, this is hire and salary, not revenge. -He took my father grossly, full of bread; -With all his crimes broad blown, as flush as May; -And how his audit stands, who knows save heaven? -But in our circumstance and course of thought, -'Tis heavy with him: and am I, then, reveng'd, -To take him in the purging of his soul, -When he is fit and season'd for his passage? -No. -Up, sword, and know thou a more horrid hent: -When he is drunk asleep; or in his rage; -Or in the incestuous pleasure of his bed; -At gaming, swearing; or about some act -That has no relish of salvation in't;-- -Then trip him, that his heels may kick at heaven; -And that his soul may be as damn'd and black -As hell, whereto it goes. My mother stays: -This physic but prolongs thy sickly days. - -[Exit.] - -[The King rises and advances.] - -King. -My words fly up, my thoughts remain below: -Words without thoughts never to heaven go. - -[Exit.] - - - -Scene IV. Another room in the castle. - -[Enter Queen and Polonius.] - -Pol. -He will come straight. Look you lay home to him: -Tell him his pranks have been too broad to bear with, -And that your grace hath screen'd and stood between -Much heat and him. I'll silence me e'en here. -Pray you, be round with him. - -Ham. -[Within.] Mother, mother, mother! - -Queen. -I'll warrant you: -Fear me not:--withdraw; I hear him coming. - -[Polonius goes behind the arras.] - -[Enter Hamlet.] - -Ham. -Now, mother, what's the matter? - -Queen. -Hamlet, thou hast thy father much offended. - -Ham. -Mother, you have my father much offended. - -Queen. -Come, come, you answer with an idle tongue. - -Ham. -Go, go, you question with a wicked tongue. - -Queen. -Why, how now, Hamlet! - -Ham. -What's the matter now? - -Queen. -Have you forgot me? - -Ham. -No, by the rood, not so: -You are the Queen, your husband's brother's wife, -And,--would it were not so!--you are my mother. - -Queen. -Nay, then, I'll set those to you that can speak. - -Ham. -Come, come, and sit you down; you shall not budge; -You go not till I set you up a glass -Where you may see the inmost part of you. - -Queen. -What wilt thou do? thou wilt not murder me?-- -Help, help, ho! - -Pol. -[Behind.] What, ho! help, help, help! - -Ham. -How now? a rat? [Draws.] -Dead for a ducat, dead! - -[Makes a pass through the arras.] - -Pol. -[Behind.] O, I am slain! - -[Falls and dies.] - -Queen. -O me, what hast thou done? - -Ham. -Nay, I know not: is it the king? - -[Draws forth Polonius.] - -Queen. -O, what a rash and bloody deed is this! - -Ham. -A bloody deed!--almost as bad, good mother, -As kill a king and marry with his brother. - -Queen. -As kill a king! - -Ham. -Ay, lady, 'twas my word.-- -Thou wretched, rash, intruding fool, farewell! -[To Polonius.] -I took thee for thy better: take thy fortune; -Thou find'st to be too busy is some danger.-- -Leave wringing of your hands: peace! sit you down, -And let me wring your heart: for so I shall, -If it be made of penetrable stuff; -If damned custom have not braz'd it so -That it is proof and bulwark against sense. - -Queen. -What have I done, that thou dar'st wag thy tongue -In noise so rude against me? - -Ham. -Such an act -That blurs the grace and blush of modesty; -Calls virtue hypocrite; takes off the rose -From the fair forehead of an innocent love, -And sets a blister there; makes marriage-vows -As false as dicers' oaths: O, such a deed -As from the body of contraction plucks -The very soul, and sweet religion makes -A rhapsody of words: heaven's face doth glow; -Yea, this solidity and compound mass, -With tristful visage, as against the doom, -Is thought-sick at the act. - -Queen. -Ah me, what act, -That roars so loud, and thunders in the index? - -Ham. -Look here upon this picture, and on this,-- -The counterfeit presentment of two brothers. -See what a grace was seated on this brow; -Hyperion's curls; the front of Jove himself; -An eye like Mars, to threaten and command; -A station like the herald Mercury -New lighted on a heaven-kissing hill: -A combination and a form, indeed, -Where every god did seem to set his seal, -To give the world assurance of a man; -This was your husband.--Look you now what follows: -Here is your husband, like a milldew'd ear -Blasting his wholesome brother. Have you eyes? -Could you on this fair mountain leave to feed, -And batten on this moor? Ha! have you eyes? -You cannot call it love; for at your age -The hey-day in the blood is tame, it's humble, -And waits upon the judgment: and what judgment -Would step from this to this? Sense, sure, you have, -Else could you not have motion: but sure that sense -Is apoplex'd; for madness would not err; -Nor sense to ecstacy was ne'er so thrall'd -But it reserv'd some quantity of choice -To serve in such a difference. What devil was't -That thus hath cozen'd you at hoodman-blind? -Eyes without feeling, feeling without sight, -Ears without hands or eyes, smelling sans all, -Or but a sickly part of one true sense -Could not so mope. -O shame! where is thy blush? Rebellious hell, -If thou canst mutine in a matron's bones, -To flaming youth let virtue be as wax, -And melt in her own fire: proclaim no shame -When the compulsive ardour gives the charge, -Since frost itself as actively doth burn, -And reason panders will. - -Queen. -O Hamlet, speak no more: -Thou turn'st mine eyes into my very soul; -And there I see such black and grained spots -As will not leave their tinct. - -Ham. -Nay, but to live -In the rank sweat of an enseamed bed, -Stew'd in corruption, honeying and making love -Over the nasty sty,-- - -Queen. -O, speak to me no more; -These words like daggers enter in mine ears; -No more, sweet Hamlet. - -Ham. -A murderer and a villain; -A slave that is not twentieth part the tithe -Of your precedent lord; a vice of kings; -A cutpurse of the empire and the rule, -That from a shelf the precious diadem stole -And put it in his pocket! - -Queen. -No more. - -Ham. -A king of shreds and patches!-- - -[Enter Ghost.] - -Save me and hover o'er me with your wings, -You heavenly guards!--What would your gracious figure? - -Queen. -Alas, he's mad! - -Ham. -Do you not come your tardy son to chide, -That, laps'd in time and passion, lets go by -The important acting of your dread command? -O, say! - -Ghost. -Do not forget. This visitation -Is but to whet thy almost blunted purpose. -But, look, amazement on thy mother sits: -O, step between her and her fighting soul,-- -Conceit in weakest bodies strongest works,-- -Speak to her, Hamlet. - -Ham. -How is it with you, lady? - -Queen. -Alas, how is't with you, -That you do bend your eye on vacancy, -And with the incorporal air do hold discourse? -Forth at your eyes your spirits wildly peep; -And, as the sleeping soldiers in the alarm, -Your bedded hairs, like life in excrements, -Start up and stand an end. O gentle son, -Upon the heat and flame of thy distemper -Sprinkle cool patience! Whereon do you look? - -Ham. -On him, on him! Look you how pale he glares! -His form and cause conjoin'd, preaching to stones, -Would make them capable.--Do not look upon me; -Lest with this piteous action you convert -My stern effects: then what I have to do -Will want true colour; tears perchance for blood. - -Queen. -To whom do you speak this? - -Ham. -Do you see nothing there? - -Queen. -Nothing at all; yet all that is I see. - -Ham. -Nor did you nothing hear? - -Queen. -No, nothing but ourselves. - -Ham. -Why, look you there! look how it steals away! -My father, in his habit as he liv'd! -Look, where he goes, even now out at the portal! - -[Exit Ghost.] - -Queen. -This is the very coinage of your brain: -This bodiless creation ecstasy -Is very cunning in. - -Ham. -Ecstasy! -My pulse, as yours, doth temperately keep time, -And makes as healthful music: it is not madness -That I have utter'd: bring me to the test, -And I the matter will re-word; which madness -Would gambol from. Mother, for love of grace, -Lay not that flattering unction to your soul -That not your trespass, but my madness speaks: -It will but skin and film the ulcerous place, -Whilst rank corruption, mining all within, -Infects unseen. Confess yourself to heaven; -Repent what's past; avoid what is to come; -And do not spread the compost on the weeds, -To make them ranker. Forgive me this my virtue; -For in the fatness of these pursy times -Virtue itself of vice must pardon beg, -Yea, curb and woo for leave to do him good. - -Queen. -O Hamlet, thou hast cleft my heart in twain. - -Ham. -O, throw away the worser part of it, -And live the purer with the other half. -Good night: but go not to mine uncle's bed; -Assume a virtue, if you have it not. -That monster custom, who all sense doth eat, -Of habits evil, is angel yet in this,-- -That to the use of actions fair and good -He likewise gives a frock or livery -That aptly is put on. Refrain to-night; -And that shall lend a kind of easiness -To the next abstinence: the next more easy; -For use almost can change the stamp of nature, -And either curb the devil, or throw him out -With wondrous potency. Once more, good-night: -And when you are desirous to be bles'd, -I'll blessing beg of you.--For this same lord -[Pointing to Polonius.] -I do repent; but heaven hath pleas'd it so, -To punish me with this, and this with me, -That I must be their scourge and minister. -I will bestow him, and will answer well -The death I gave him. So again, good-night.-- -I must be cruel, only to be kind: -Thus bad begins, and worse remains behind.-- -One word more, good lady. - -Queen. -What shall I do? - -Ham. -Not this, by no means, that I bid you do: -Let the bloat king tempt you again to bed; -Pinch wanton on your cheek; call you his mouse; -And let him, for a pair of reechy kisses, -Or paddling in your neck with his damn'd fingers, -Make you to ravel all this matter out, -That I essentially am not in madness, -But mad in craft. 'Twere good you let him know; -For who that's but a queen, fair, sober, wise, -Would from a paddock, from a bat, a gib, -Such dear concernings hide? who would do so? -No, in despite of sense and secrecy, -Unpeg the basket on the house's top, -Let the birds fly, and, like the famous ape, -To try conclusions, in the basket creep -And break your own neck down. - -Queen. -Be thou assur'd, if words be made of breath, -And breath of life, I have no life to breathe -What thou hast said to me. - -Ham. -I must to England; you know that? - -Queen. -Alack, -I had forgot: 'tis so concluded on. - -Ham. -There's letters seal'd: and my two schoolfellows,-- -Whom I will trust as I will adders fang'd,-- -They bear the mandate; they must sweep my way -And marshal me to knavery. Let it work; -For 'tis the sport to have the enginer -Hoist with his own petard: and 't shall go hard -But I will delve one yard below their mines -And blow them at the moon: O, 'tis most sweet, -When in one line two crafts directly meet.-- -This man shall set me packing: -I'll lug the guts into the neighbour room.-- -Mother, good-night.--Indeed, this counsellor -Is now most still, most secret, and most grave, -Who was in life a foolish peating knave. -Come, sir, to draw toward an end with you:-- -Good night, mother. - -[Exeunt severally; Hamlet, dragging out Polonius.] - - - -ACT IV. - -Scene I. A room in the Castle. - -[Enter King, Queen, Rosencrantz and Guildenstern.] - -King. -There's matter in these sighs. These profound heaves -You must translate: 'tis fit we understand them. -Where is your son? - -Queen. -Bestow this place on us a little while. - -[To Rosencrantz and Guildenstern, who go out.] - -Ah, my good lord, what have I seen to-night! - -King. -What, Gertrude? How does Hamlet? - -Queen. -Mad as the sea and wind, when both contend -Which is the mightier: in his lawless fit -Behind the arras hearing something stir, -Whips out his rapier, cries 'A rat, a rat!' -And in this brainish apprehension, kills -The unseen good old man. - -King. -O heavy deed! -It had been so with us, had we been there: -His liberty is full of threats to all; -To you yourself, to us, to every one. -Alas, how shall this bloody deed be answer'd? -It will be laid to us, whose providence -Should have kept short, restrain'd, and out of haunt -This mad young man. But so much was our love -We would not understand what was most fit; -But, like the owner of a foul disease, -To keep it from divulging, let it feed -Even on the pith of life. Where is he gone? - -Queen. -To draw apart the body he hath kill'd: -O'er whom his very madness, like some ore -Among a mineral of metals base, -Shows itself pure: he weeps for what is done. - -King. -O Gertrude, come away! -The sun no sooner shall the mountains touch -But we will ship him hence: and this vile deed -We must with all our majesty and skill -Both countenance and excuse.--Ho, Guildenstern! - -[Re-enter Rosencrantz and Guildenstern.] - -Friends both, go join you with some further aid: -Hamlet in madness hath Polonius slain, -And from his mother's closet hath he dragg'd him: -Go seek him out; speak fair, and bring the body -Into the chapel. I pray you, haste in this. - -[Exeunt Rosencrantz and Guildenstern.] - -Come, Gertrude, we'll call up our wisest friends; -And let them know both what we mean to do -And what's untimely done: so haply slander,-- -Whose whisper o'er the world's diameter, -As level as the cannon to his blank, -Transports his poison'd shot,--may miss our name, -And hit the woundless air.--O, come away! -My soul is full of discord and dismay. - -[Exeunt.] - -Scene II. Another room in the Castle. - -[Enter Hamlet.] - -Ham. -Safely stowed. - -Ros. and Guil. -[Within.] Hamlet! Lord Hamlet! - -Ham. -What noise? who calls on Hamlet? O, here they come. - -[Enter Rosencrantz and Guildenstern.] - -Ros. -What have you done, my lord, with the dead body? - -Ham. -Compounded it with dust, whereto 'tis kin. - -Ros. -Tell us where 'tis, that we may take it thence, -And bear it to the chapel. - -Ham. -Do not believe it. - -Ros. -Believe what? - -Ham. -That I can keep your counsel, and not mine own. Besides, to be -demanded of a sponge!--what replication should be made by the son -of a king? - -Ros. -Take you me for a sponge, my lord? - -Ham. -Ay, sir; that soaks up the King's countenance, his rewards, -his authorities. But such officers do the king best service in -the end: he keeps them, like an ape, in the corner of his jaw; -first mouthed, to be last swallowed: when he needs what you have -gleaned, it is but squeezing you, and, sponge, you shall be dry -again. - -Ros. -I understand you not, my lord. - -Ham. -I am glad of it: a knavish speech sleeps in a foolish ear. - -Ros. -My lord, you must tell us where the body is and go with us to -the king. - -Ham. -The body is with the king, but the king is not with the body. -The king is a thing,-- - -Guil. -A thing, my lord! - -Ham. -Of nothing: bring me to him. Hide fox, and all after. - -[Exeunt.] - - - -Scene III. Another room in the Castle. - -[Enter King,attended.] - -King. -I have sent to seek him and to find the body. -How dangerous is it that this man goes loose! -Yet must not we put the strong law on him: -He's lov'd of the distracted multitude, -Who like not in their judgment, but their eyes; -And where 'tis so, the offender's scourge is weigh'd, -But never the offence. To bear all smooth and even, -This sudden sending him away must seem -Deliberate pause: diseases desperate grown -By desperate appliance are reliev'd, -Or not at all. - -[Enter Rosencrantz.] - -How now! what hath befall'n? - -Ros. -Where the dead body is bestow'd, my lord, -We cannot get from him. - -King. -But where is he? - -Ros. -Without, my lord; guarded, to know your pleasure. - -King. -Bring him before us. - -Ros. -Ho, Guildenstern! bring in my lord. - -[Enter Hamlet and Guildenstern.] - -King. -Now, Hamlet, where's Polonius? - -Ham. -At supper. - -King. -At supper! where? - -Ham. -Not where he eats, but where he is eaten: a certain -convocation of politic worms are e'en at him. Your worm is your -only emperor for diet: we fat all creatures else to fat us, and -we fat ourselves for maggots: your fat king and your lean beggar -is but variable service,--two dishes, but to one table: that's -the end. - -King. -Alas, alas! - -Ham. -A man may fish with the worm that hath eat of a king, and eat -of the fish that hath fed of that worm. - -King. -What dost thou mean by this? - -Ham. -Nothing but to show you how a king may go a progress through -the guts of a beggar. - -King. -Where is Polonius? - -Ham. -In heaven: send thither to see: if your messenger find him not -there, seek him i' the other place yourself. But, indeed, if you -find him not within this month, you shall nose him as you go up -the stairs into the lobby. - -King. -Go seek him there. [To some Attendants.] - -Ham. -He will stay till you come. - -[Exeunt Attendants.] - -King. -Hamlet, this deed, for thine especial safety,-- -Which we do tender, as we dearly grieve -For that which thou hast done,--must send thee hence -With fiery quickness: therefore prepare thyself; -The bark is ready, and the wind at help, -The associates tend, and everything is bent -For England. - -Ham. -For England! - -King. -Ay, Hamlet. - -Ham. -Good. - -King. -So is it, if thou knew'st our purposes. - -Ham. -I see a cherub that sees them.--But, come; for England!-- -Farewell, dear mother. - -King. -Thy loving father, Hamlet. - -Ham. -My mother: father and mother is man and wife; man and wife is -one flesh; and so, my mother.--Come, for England! - -[Exit.] - -King. -Follow him at foot; tempt him with speed aboard; -Delay it not; I'll have him hence to-night: -Away! for everything is seal'd and done -That else leans on the affair: pray you, make haste. - -[Exeunt Rosencrantz and Guildenstern.] - -And, England, if my love thou hold'st at aught,-- -As my great power thereof may give thee sense, -Since yet thy cicatrice looks raw and red -After the Danish sword, and thy free awe -Pays homage to us,--thou mayst not coldly set -Our sovereign process; which imports at full, -By letters conjuring to that effect, -The present death of Hamlet. Do it, England; -For like the hectic in my blood he rages, -And thou must cure me: till I know 'tis done, -Howe'er my haps, my joys were ne'er begun. - -[Exit.] - - - -Scene IV. A plain in Denmark. - -[Enter Fortinbras, and Forces marching.] - -For. -Go, Captain, from me greet the Danish king: -Tell him that, by his license, Fortinbras -Craves the conveyance of a promis'd march -Over his kingdom. You know the rendezvous. -If that his majesty would aught with us, -We shall express our duty in his eye; -And let him know so. - -Capt. -I will do't, my lord. - -For. -Go softly on. - -[Exeunt all For. and Forces.] - -[Enter Hamlet, Rosencrantz, Guildenstern, &c.] - -Ham. -Good sir, whose powers are these? - -Capt. -They are of Norway, sir. - -Ham. -How purpos'd, sir, I pray you? - -Capt. -Against some part of Poland. - -Ham. -Who commands them, sir? - -Capt. -The nephew to old Norway, Fortinbras. - -Ham. -Goes it against the main of Poland, sir, -Or for some frontier? - -Capt. -Truly to speak, and with no addition, -We go to gain a little patch of ground -That hath in it no profit but the name. -To pay five ducats, five, I would not farm it; -Nor will it yield to Norway or the Pole -A ranker rate, should it be sold in fee. - -Ham. -Why, then the Polack never will defend it. - -Capt. -Yes, it is already garrison'd. - -Ham. -Two thousand souls and twenty thousand ducats -Will not debate the question of this straw: -This is the imposthume of much wealth and peace, -That inward breaks, and shows no cause without -Why the man dies.--I humbly thank you, sir. - -Capt. -God b' wi' you, sir. - -[Exit.] - -Ros. -Will't please you go, my lord? - -Ham. -I'll be with you straight. Go a little before. - -[Exeunt all but Hamlet.] - -How all occasions do inform against me -And spur my dull revenge! What is a man, -If his chief good and market of his time -Be but to sleep and feed? a beast, no more. -Sure he that made us with such large discourse, -Looking before and after, gave us not -That capability and godlike reason -To fust in us unus'd. Now, whether it be -Bestial oblivion, or some craven scruple -Of thinking too precisely on the event,-- -A thought which, quarter'd, hath but one part wisdom -And ever three parts coward,--I do not know -Why yet I live to say 'This thing's to do;' -Sith I have cause, and will, and strength, and means -To do't. Examples, gross as earth, exhort me: -Witness this army, of such mass and charge, -Led by a delicate and tender prince; -Whose spirit, with divine ambition puff'd, -Makes mouths at the invisible event; -Exposing what is mortal and unsure -To all that fortune, death, and danger dare, -Even for an egg-shell. Rightly to be great -Is not to stir without great argument, -But greatly to find quarrel in a straw -When honour's at the stake. How stand I, then, -That have a father kill'd, a mother stain'd, -Excitements of my reason and my blood, -And let all sleep? while, to my shame, I see -The imminent death of twenty thousand men -That, for a fantasy and trick of fame, -Go to their graves like beds; fight for a plot -Whereon the numbers cannot try the cause, -Which is not tomb enough and continent -To hide the slain?--O, from this time forth, -My thoughts be bloody, or be nothing worth! - -[Exit.] - - - -Scene V. Elsinore. A room in the Castle. - -[Enter Queen and Horatio.] - -Queen. -I will not speak with her. - -Gent. -She is importunate; indeed distract: -Her mood will needs be pitied. - -Queen. -What would she have? - -Gent. -She speaks much of her father; says she hears -There's tricks i' the world, and hems, and beats her heart; -Spurns enviously at straws; speaks things in doubt, -That carry but half sense: her speech is nothing, -Yet the unshaped use of it doth move -The hearers to collection; they aim at it, -And botch the words up fit to their own thoughts; -Which, as her winks, and nods, and gestures yield them, -Indeed would make one think there might be thought, -Though nothing sure, yet much unhappily. -'Twere good she were spoken with; for she may strew -Dangerous conjectures in ill-breeding minds. - -Queen. -Let her come in. - -[Exit Horatio.] - -To my sick soul, as sin's true nature is, -Each toy seems Prologue to some great amiss: -So full of artless jealousy is guilt, -It spills itself in fearing to be spilt. - -[Re-enter Horatio with Ophelia.] - -Oph. -Where is the beauteous majesty of Denmark? - -Queen. -How now, Ophelia? - -Oph. [Sings.] - How should I your true love know - From another one? - By his cockle bat and' staff - And his sandal shoon. - -Queen. -Alas, sweet lady, what imports this song? - -Oph. -Say you? nay, pray you, mark. -[Sings.] - He is dead and gone, lady, - He is dead and gone; - At his head a grass green turf, - At his heels a stone. - -Queen. -Nay, but Ophelia-- - -Oph. -Pray you, mark. -[Sings.] - White his shroud as the mountain snow, - -[Enter King.] - -Queen. -Alas, look here, my lord! - -Oph. -[Sings.] - Larded all with sweet flowers; - Which bewept to the grave did go - With true-love showers. - -King. -How do you, pretty lady? - -Oph. -Well, God dild you! They say the owl was a baker's daughter. -Lord, we know what we are, but know not what we may be. God be at -your table! - -King. -Conceit upon her father. - -Oph. -Pray you, let's have no words of this; but when they ask you what -it means, say you this: -[Sings.] - To-morrow is Saint Valentine's day - All in the morning bedtime, - And I a maid at your window, - To be your Valentine. - - Then up he rose and donn'd his clothes, - And dupp'd the chamber door, - Let in the maid, that out a maid - Never departed more. - -King. -Pretty Ophelia! - -Oph. -Indeed, la, without an oath, I'll make an end on't: -[Sings.] - By Gis and by Saint Charity, - Alack, and fie for shame! - Young men will do't if they come to't; - By cock, they are to blame. - - Quoth she, before you tumbled me, - You promis'd me to wed. - So would I ha' done, by yonder sun, - An thou hadst not come to my bed. - -King. -How long hath she been thus? - -Oph. -I hope all will be well. We must be patient: but I cannot -choose but weep, to think they would lay him i' the cold ground. -My brother shall know of it: and so I thank you for your good -counsel.--Come, my coach!--Good night, ladies; good night, sweet -ladies; good night, good night. - -[Exit.] - -King. -Follow her close; give her good watch, I pray you. - -[Exit Horatio.] - -O, this is the poison of deep grief; it springs -All from her father's death. O Gertrude, Gertrude, -When sorrows come, they come not single spies, -But in battalions! First, her father slain: -Next, your son gone; and he most violent author -Of his own just remove: the people muddied, -Thick and and unwholesome in their thoughts and whispers -For good Polonius' death; and we have done but greenly -In hugger-mugger to inter him: poor Ophelia -Divided from herself and her fair judgment, -Without the which we are pictures or mere beasts: -Last, and as much containing as all these, -Her brother is in secret come from France; -Feeds on his wonder, keeps himself in clouds, -And wants not buzzers to infect his ear -With pestilent speeches of his father's death; -Wherein necessity, of matter beggar'd, -Will nothing stick our person to arraign -In ear and ear. O my dear Gertrude, this, -Like to a murdering piece, in many places -Give, me superfluous death. - -[A noise within.] - -Queen. -Alack, what noise is this? - -King. -Where are my Switzers? let them guard the door. - -[Enter a Gentleman.] - -What is the matter? - -Gent. -Save yourself, my lord: -The ocean, overpeering of his list, -Eats not the flats with more impetuous haste -Than young Laertes, in a riotous head, -O'erbears your offices. The rabble call him lord; -And, as the world were now but to begin, -Antiquity forgot, custom not known, -The ratifiers and props of every word, -They cry 'Choose we! Laertes shall be king!' -Caps, hands, and tongues applaud it to the clouds, -'Laertes shall be king! Laertes king!' - -Queen. -How cheerfully on the false trail they cry! -O, this is counter, you false Danish dogs! - -[A noise within.] - -King. -The doors are broke. - -[Enter Laertes, armed; Danes following.] - -Laer. -Where is this king?--Sirs, stand you all without. - -Danes. -No, let's come in. - -Laer. -I pray you, give me leave. - -Danes. -We will, we will. - -[They retire without the door.] - -Laer. -I thank you:--keep the door.--O thou vile king, -Give me my father! - -Queen. -Calmly, good Laertes. - -Laer. -That drop of blood that's calm proclaims me bastard; -Cries cuckold to my father; brands the harlot -Even here, between the chaste unsmirched brow -Of my true mother. - -King. -What is the cause, Laertes, -That thy rebellion looks so giant-like?-- -Let him go, Gertrude; do not fear our person: -There's such divinity doth hedge a king, -That treason can but peep to what it would, -Acts little of his will.--Tell me, Laertes, -Why thou art thus incens'd.--Let him go, Gertrude:-- -Speak, man. - -Laer. -Where is my father? - -King. -Dead. - -Queen. -But not by him. - -King. -Let him demand his fill. - -Laer. -How came he dead? I'll not be juggled with: -To hell, allegiance! vows, to the blackest devil! -Conscience and grace, to the profoundest pit! -I dare damnation:--to this point I stand,-- -That both the worlds, I give to negligence, -Let come what comes; only I'll be reveng'd -Most throughly for my father. - -King. -Who shall stay you? - -Laer. -My will, not all the world: -And for my means, I'll husband them so well, -They shall go far with little. - -King. -Good Laertes, -If you desire to know the certainty -Of your dear father's death, is't writ in your revenge -That, sweepstake, you will draw both friend and foe, -Winner and loser? - -Laer. -None but his enemies. - -King. -Will you know them then? - -Laer. -To his good friends thus wide I'll ope my arms; -And, like the kind life-rendering pelican, -Repast them with my blood. - -King. -Why, now you speak -Like a good child and a true gentleman. -That I am guiltless of your father's death, -And am most sensibly in grief for it, -It shall as level to your judgment pierce -As day does to your eye. - -Danes. -[Within] Let her come in. - -Laer. -How now! What noise is that? - -[Re-enter Ophelia, fantastically dressed with straws and -flowers.] - -O heat, dry up my brains! tears seven times salt, -Burn out the sense and virtue of mine eye!-- -By heaven, thy madness shall be paid by weight, -Till our scale turn the beam. O rose of May! -Dear maid, kind sister, sweet Ophelia!-- -O heavens! is't possible a young maid's wits -Should be as mortal as an old man's life? -Nature is fine in love; and where 'tis fine, -It sends some precious instance of itself -After the thing it loves. - -Oph. -[Sings.] - They bore him barefac'd on the bier - Hey no nonny, nonny, hey nonny - And on his grave rain'd many a tear.-- - -Fare you well, my dove! - -Laer. -Hadst thou thy wits, and didst persuade revenge, -It could not move thus. - -Oph. -You must sing 'Down a-down, an you call him a-down-a.' O, -how the wheel becomes it! It is the false steward, that stole his -master's daughter. - -Laer. -This nothing's more than matter. - -Oph. -There's rosemary, that's for remembrance; pray, love, -remember: and there is pansies, that's for thoughts. - -Laer. -A document in madness,--thoughts and remembrance fitted. - -Oph. -There's fennel for you, and columbines:--there's rue for you; -and here's some for me:--we may call it herb of grace o' -Sundays:--O, you must wear your rue with a difference.--There's a -daisy:--I would give you some violets, but they wither'd all when -my father died:--they say he made a good end,-- -[Sings.] - For bonny sweet Robin is all my joy,-- - -Laer. -Thought and affliction, passion, hell itself, -She turns to favour and to prettiness. - -Oph. -[Sings.] - And will he not come again? - And will he not come again? - No, no, he is dead, - Go to thy death-bed, - He never will come again. - - His beard was as white as snow, - All flaxen was his poll: - He is gone, he is gone, - And we cast away moan: - God ha' mercy on his soul! - -And of all Christian souls, I pray God.--God b' wi' ye. - -[Exit.] - -Laer. -Do you see this, O God? - -King. -Laertes, I must commune with your grief, -Or you deny me right. Go but apart, -Make choice of whom your wisest friends you will, -And they shall hear and judge 'twixt you and me. -If by direct or by collateral hand -They find us touch'd, we will our kingdom give, -Our crown, our life, and all that we call ours, -To you in satisfaction; but if not, -Be you content to lend your patience to us, -And we shall jointly labour with your soul -To give it due content. - -Laer. -Let this be so; -His means of death, his obscure burial,-- -No trophy, sword, nor hatchment o'er his bones, -No noble rite nor formal ostentation,-- -Cry to be heard, as 'twere from heaven to earth, -That I must call't in question. - -King. -So you shall; -And where the offence is let the great axe fall. -I pray you go with me. - -[Exeunt.] - - - -Scene VI. Another room in the Castle. - -[Enter Horatio and a Servant.] - -Hor. -What are they that would speak with me? - -Servant. -Sailors, sir: they say they have letters for you. - -Hor. -Let them come in. - -[Exit Servant.] - -I do not know from what part of the world -I should be greeted, if not from Lord Hamlet. - -[Enter Sailors.] - -I Sailor. -God bless you, sir. - -Hor. -Let him bless thee too. - -Sailor. -He shall, sir, an't please him. There's a letter for you, -sir,--it comes from the ambassador that was bound for England; if -your name be Horatio, as I am let to know it is. - -Hor. -[Reads.] 'Horatio, when thou shalt have overlooked -this, give these fellows some means to the king: they have -letters for him. Ere we were two days old at sea, a pirate of -very warlike appointment gave us chase. Finding ourselves too -slow of sail, we put on a compelled valour, and in the grapple I -boarded them: on the instant they got clear of our ship; so I -alone became their prisoner. They have dealt with me like thieves -of mercy: but they knew what they did; I am to do a good turn for -them. Let the king have the letters I have sent; and repair thou -to me with as much haste as thou wouldst fly death. I have words -to speak in thine ear will make thee dumb; yet are they much too -light for the bore of the matter. These good fellows will bring -thee where I am. Rosencrantz and Guildenstern hold their course -for England: of them I have much to tell thee. Farewell. -He that thou knowest thine, HAMLET.' - -Come, I will give you way for these your letters; -And do't the speedier, that you may direct me -To him from whom you brought them. - -[Exeunt.] - - - -Scene VII. Another room in the Castle. - -[Enter King and Laertes.] - -King. -Now must your conscience my acquittance seal, -And you must put me in your heart for friend, -Sith you have heard, and with a knowing ear, -That he which hath your noble father slain -Pursu'd my life. - -Laer. -It well appears:--but tell me -Why you proceeded not against these feats, -So crimeful and so capital in nature, -As by your safety, wisdom, all things else, -You mainly were stirr'd up. - -King. -O, for two special reasons; -Which may to you, perhaps, seem much unsinew'd, -But yet to me they are strong. The queen his mother -Lives almost by his looks; and for myself,-- -My virtue or my plague, be it either which,-- -She's so conjunctive to my life and soul, -That, as the star moves not but in his sphere, -I could not but by her. The other motive, -Why to a public count I might not go, -Is the great love the general gender bear him; -Who, dipping all his faults in their affection, -Would, like the spring that turneth wood to stone, -Convert his gyves to graces; so that my arrows, -Too slightly timber'd for so loud a wind, -Would have reverted to my bow again, -And not where I had aim'd them. - -Laer. -And so have I a noble father lost; -A sister driven into desperate terms,-- -Whose worth, if praises may go back again, -Stood challenger on mount of all the age -For her perfections:--but my revenge will come. - -King. -Break not your sleeps for that:--you must not think -That we are made of stuff so flat and dull -That we can let our beard be shook with danger, -And think it pastime. You shortly shall hear more: -I lov'd your father, and we love ourself; -And that, I hope, will teach you to imagine,-- - -[Enter a Messenger.] - -How now! What news? - -Mess. -Letters, my lord, from Hamlet: -This to your majesty; this to the queen. - -King. -From Hamlet! Who brought them? - -Mess. -Sailors, my lord, they say; I saw them not: -They were given me by Claudio:--he receiv'd them -Of him that brought them. - -King. -Laertes, you shall hear them. -Leave us. - -[Exit Messenger.] - -[Reads]'High and mighty,--You shall know I am set naked on your -kingdom. To-morrow shall I beg leave to see your kingly eyes: -when I shall, first asking your pardon thereunto, recount the -occasions of my sudden and more strange return. HAMLET.' - -What should this mean? Are all the rest come back? -Or is it some abuse, and no such thing? - -Laer. -Know you the hand? - -King. -'Tis Hamlet's character:--'Naked!'-- -And in a postscript here, he says 'alone.' -Can you advise me? - -Laer. -I am lost in it, my lord. But let him come; -It warms the very sickness in my heart -That I shall live and tell him to his teeth, -'Thus didest thou.' - -King. -If it be so, Laertes,-- -As how should it be so? how otherwise?-- -Will you be rul'd by me? - -Laer. -Ay, my lord; -So you will not o'errule me to a peace. - -King. -To thine own peace. If he be now return'd-- -As checking at his voyage, and that he means -No more to undertake it,--I will work him -To exploit, now ripe in my device, -Under the which he shall not choose but fall: -And for his death no wind shall breathe; -But even his mother shall uncharge the practice -And call it accident. - -Laer. -My lord, I will be rul'd; -The rather if you could devise it so -That I might be the organ. - -King. -It falls right. -You have been talk'd of since your travel much, -And that in Hamlet's hearing, for a quality -Wherein they say you shine: your sum of parts -Did not together pluck such envy from him -As did that one; and that, in my regard, -Of the unworthiest siege. - -Laer. -What part is that, my lord? - -King. -A very riband in the cap of youth, -Yet needful too; for youth no less becomes -The light and careless livery that it wears -Than settled age his sables and his weeds, -Importing health and graveness.--Two months since, -Here was a gentleman of Normandy,-- -I've seen myself, and serv'd against, the French, -And they can well on horseback: but this gallant -Had witchcraft in't: he grew unto his seat; -And to such wondrous doing brought his horse, -As had he been incorps'd and demi-natur'd -With the brave beast: so far he topp'd my thought -That I, in forgery of shapes and tricks, -Come short of what he did. - -Laer. -A Norman was't? - -King. -A Norman. - -Laer. -Upon my life, Lamond. - -King. -The very same. - -Laer. -I know him well: he is the brooch indeed -And gem of all the nation. - -King. -He made confession of you; -And gave you such a masterly report -For art and exercise in your defence, -And for your rapier most especially, -That he cried out, 'twould be a sight indeed -If one could match you: the scrimers of their nation -He swore, had neither motion, guard, nor eye, -If you oppos'd them. Sir, this report of his -Did Hamlet so envenom with his envy -That he could nothing do but wish and beg -Your sudden coming o'er, to play with him. -Now, out of this,-- - -Laer. -What out of this, my lord? - -King. -Laertes, was your father dear to you? -Or are you like the painting of a sorrow, -A face without a heart? - -Laer. -Why ask you this? - -King. -Not that I think you did not love your father; -But that I know love is begun by time, -And that I see, in passages of proof, -Time qualifies the spark and fire of it. -There lives within the very flame of love -A kind of wick or snuff that will abate it; -And nothing is at a like goodness still; -For goodness, growing to a plurisy, -Dies in his own too much: that we would do, -We should do when we would; for this 'would' changes, -And hath abatements and delays as many -As there are tongues, are hands, are accidents; -And then this 'should' is like a spendthrift sigh, -That hurts by easing. But to the quick o' the ulcer:-- -Hamlet comes back: what would you undertake -To show yourself your father's son in deed -More than in words? - -Laer. -To cut his throat i' the church. - -King. -No place, indeed, should murder sanctuarize; -Revenge should have no bounds. But, good Laertes, -Will you do this, keep close within your chamber. -Hamlet return'd shall know you are come home: -We'll put on those shall praise your excellence -And set a double varnish on the fame -The Frenchman gave you; bring you in fine together -And wager on your heads: he, being remiss, -Most generous, and free from all contriving, -Will not peruse the foils; so that with ease, -Or with a little shuffling, you may choose -A sword unbated, and, in a pass of practice, -Requite him for your father. - -Laer. -I will do't: -And for that purpose I'll anoint my sword. -I bought an unction of a mountebank, -So mortal that, but dip a knife in it, -Where it draws blood no cataplasm so rare, -Collected from all simples that have virtue -Under the moon, can save the thing from death -This is but scratch'd withal: I'll touch my point -With this contagion, that, if I gall him slightly, -It may be death. - -King. -Let's further think of this; -Weigh what convenience both of time and means -May fit us to our shape: if this should fail, -And that our drift look through our bad performance. -'Twere better not assay'd: therefore this project -Should have a back or second, that might hold -If this did blast in proof. Soft! let me see:-- -We'll make a solemn wager on your cunnings,-- -I ha't: -When in your motion you are hot and dry,-- -As make your bouts more violent to that end,-- -And that he calls for drink, I'll have prepar'd him -A chalice for the nonce; whereon but sipping, -If he by chance escape your venom'd stuck, -Our purpose may hold there. - -[Enter Queen.] - -How now, sweet queen! - -Queen. -One woe doth tread upon another's heel, -So fast they follow:--your sister's drown'd, Laertes. - -Laer. -Drown'd! O, where? - -Queen. -There is a willow grows aslant a brook, -That shows his hoar leaves in the glassy stream; -There with fantastic garlands did she come -Of crowflowers, nettles, daisies, and long purples, -That liberal shepherds give a grosser name, -But our cold maids do dead men's fingers call them. -There, on the pendant boughs her coronet weeds -Clamb'ring to hang, an envious sliver broke; -When down her weedy trophies and herself -Fell in the weeping brook. Her clothes spread wide; -And, mermaid-like, awhile they bore her up; -Which time she chaunted snatches of old tunes; -As one incapable of her own distress, -Or like a creature native and indu'd -Unto that element: but long it could not be -Till that her garments, heavy with their drink, -Pull'd the poor wretch from her melodious lay -To muddy death. - -Laer. -Alas, then she is drown'd? - -Queen. -Drown'd, drown'd. - -Laer. -Too much of water hast thou, poor Ophelia, -And therefore I forbid my tears: but yet -It is our trick; nature her custom holds, -Let shame say what it will: when these are gone, -The woman will be out.--Adieu, my lord: -I have a speech of fire, that fain would blaze, -But that this folly douts it. - -[Exit.] - -King. -Let's follow, Gertrude; -How much I had to do to calm his rage! -Now fear I this will give it start again; -Therefore let's follow. - -[Exeunt.] - - - -ACT V. - -Scene I. A churchyard. - -[Enter two Clowns, with spades, &c.] - -1 Clown. -Is she to be buried in Christian burial when she wilfully -seeks her own salvation? - -2 Clown. -I tell thee she is; and therefore make her grave straight: the -crowner hath sat on her, and finds it Christian burial. - -1 Clown. -How can that be, unless she drowned herself in her own defence? - -2 Clown. -Why, 'tis found so. - -1 Clown. -It must be se offendendo; it cannot be else. For here lies -the point: if I drown myself wittingly, it argues an act: and an -act hath three branches; it is to act, to do, and to perform: -argal, she drowned herself wittingly. - -2 Clown. -Nay, but hear you, goodman delver,-- - -1 Clown. -Give me leave. Here lies the water; good: here stands the -man; good: if the man go to this water and drown himself, it is, -will he, nill he, he goes,--mark you that: but if the water come -to him and drown him, he drowns not himself; argal, he that is -not guilty of his own death shortens not his own life. - -2 Clown. -But is this law? - -1 Clown. -Ay, marry, is't--crowner's quest law. - -2 Clown. -Will you ha' the truth on't? If this had not been a -gentlewoman, she should have been buried out o' Christian burial. - -1 Clown. -Why, there thou say'st: and the more pity that great folk -should have countenance in this world to drown or hang themselves -more than their even Christian.--Come, my spade. There is no -ancient gentlemen but gardeners, ditchers, and grave-makers: they -hold up Adam's profession. - -2 Clown. -Was he a gentleman? - -1 Clown. -He was the first that ever bore arms. - -2 Clown. -Why, he had none. - -1 Clown. -What, art a heathen? How dost thou understand the Scripture? -The Scripture says Adam digg'd: could he dig without arms? I'll -put another question to thee: if thou answerest me not to the -purpose, confess thyself,-- - -2 Clown. -Go to. - -1 Clown. -What is he that builds stronger than either the mason, the -shipwright, or the carpenter? - -2 Clown. -The gallows-maker; for that frame outlives a thousand tenants. - -1 Clown. -I like thy wit well, in good faith: the gallows does well; -but how does it well? it does well to those that do ill: now, -thou dost ill to say the gallows is built stronger than the -church; argal, the gallows may do well to thee. To't again, come. - -2 Clown. -Who builds stronger than a mason, a shipwright, or a carpenter? - -1 Clown. -Ay, tell me that, and unyoke. - -2 Clown. -Marry, now I can tell. - -1 Clown. -To't. - -2 Clown. -Mass, I cannot tell. - -[Enter Hamlet and Horatio, at a distance.] - -1 Clown. -Cudgel thy brains no more about it, for your dull ass will -not mend his pace with beating; and when you are asked this -question next, say 'a grave-maker;' the houses he makes last -till doomsday. Go, get thee to Yaughan; fetch me a stoup of -liquor. - -[Exit Second Clown.] - -[Digs and sings.] - - In youth when I did love, did love, - Methought it was very sweet; - To contract, O, the time for, ah, my behove, - O, methought there was nothing meet. - -Ham. -Has this fellow no feeling of his business, that he sings at -grave-making? - -Hor. -Custom hath made it in him a property of easiness. - -Ham. -'Tis e'en so: the hand of little employment hath the daintier -sense. - -1 Clown. -[Sings.] - But age, with his stealing steps, - Hath claw'd me in his clutch, - And hath shipp'd me intil the land, - As if I had never been such. - -[Throws up a skull.] - -Ham. -That skull had a tongue in it, and could sing once: how the -knave jowls it to the ground,as if 'twere Cain's jawbone, that -did the first murder! This might be the pate of a politician, -which this ass now o'erreaches; one that would circumvent God, -might it not? - -Hor. -It might, my lord. - -Ham. -Or of a courtier, which could say 'Good morrow, sweet lord! -How dost thou, good lord?' This might be my lord such-a-one, that -praised my lord such-a-one's horse when he meant to beg -it,--might it not? - -Hor. -Ay, my lord. - -Ham. -Why, e'en so: and now my Lady Worm's; chapless, and knocked -about the mazard with a sexton's spade: here's fine revolution, -an we had the trick to see't. Did these bones cost no more the -breeding but to play at loggets with 'em? mine ache to think -on't. - -1 Clown. -[Sings.] - A pickaxe and a spade, a spade, - For and a shrouding sheet; - O, a pit of clay for to be made - For such a guest is meet. - -[Throws up another skull]. - -Ham. -There's another: why may not that be the skull of a lawyer? -Where be his quiddits now, his quillets, his cases, his tenures, -and his tricks? why does he suffer this rude knave now to knock -him about the sconce with a dirty shovel, and will not tell him -of his action of battery? Hum! This fellow might be in's time a -great buyer of land, with his statutes, his recognizances, his -fines, his double vouchers, his recoveries: is this the fine of -his fines, and the recovery of his recoveries, to have his fine -pate full of fine dirt? will his vouchers vouch him no more of -his purchases, and double ones too, than the length and breadth -of a pair of indentures? The very conveyances of his lands will -scarcely lie in this box; and must the inheritor himself have no -more, ha? - -Hor. -Not a jot more, my lord. - -Ham. -Is not parchment made of sheep-skins? - -Hor. -Ay, my lord, And of calf-skins too. - -Ham. -They are sheep and calves which seek out assurance in that. I -will speak to this fellow.--Whose grave's this, sir? - -1 Clown. -Mine, sir. -[Sings.] - O, a pit of clay for to be made - For such a guest is meet. - -Ham. -I think it be thine indeed, for thou liest in't. - -1 Clown. -You lie out on't, sir, and therefore 'tis not yours: for my part, -I do not lie in't, yet it is mine. - -Ham. -Thou dost lie in't, to be in't and say it is thine: 'tis for -the dead, not for the quick; therefore thou liest. - -1 Clown. -'Tis a quick lie, sir; 't will away again from me to you. - -Ham. -What man dost thou dig it for? - -1 Clown. -For no man, sir. - -Ham. -What woman then? - -1 Clown. -For none neither. - -Ham. -Who is to be buried in't? - -1 Clown. -One that was a woman, sir; but, rest her soul, she's dead. - -Ham. -How absolute the knave is! We must speak by the card, or -equivocation will undo us. By the Lord, Horatio, these three -years I have taken note of it, the age is grown so picked that -the toe of the peasant comes so near the heel of the courtier he -galls his kibe.--How long hast thou been a grave-maker? - -1 Clown. -Of all the days i' the year, I came to't that day that our -last King Hamlet overcame Fortinbras. - -Ham. -How long is that since? - -1 Clown. -Cannot you tell that? every fool can tell that: it was the -very day that young Hamlet was born,--he that is mad, and sent -into England. - -Ham. -Ay, marry, why was be sent into England? - -1 Clown. -Why, because he was mad: he shall recover his wits there; -or, if he do not, it's no great matter there. - -Ham. -Why? - -1 Clown. -'Twill not he seen in him there; there the men are as mad as he. - -Ham. -How came he mad? - -1 Clown. -Very strangely, they say. - -Ham. -How strangely? - -1 Clown. -Faith, e'en with losing his wits. - -Ham. -Upon what ground? - -1 Clown. -Why, here in Denmark: I have been sexton here, man and boy, -thirty years. - -Ham. -How long will a man lie i' the earth ere he rot? - -1 Clown. -Faith, if he be not rotten before he die,--as we have many -pocky corses now-a-days that will scarce hold the laying in,--he -will last you some eight year or nine year: a tanner will last -you nine year. - -Ham. -Why he more than another? - -1 Clown. -Why, sir, his hide is so tann'd with his trade that he will -keep out water a great while; and your water is a sore decayer of -your whoreson dead body. Here's a skull now; this skull hath lain -in the earth three-and-twenty years. - -Ham. -Whose was it? - -1 Clown. -A whoreson, mad fellow's it was: whose do you think it was? - -Ham. -Nay, I know not. - -1 Clown. -A pestilence on him for a mad rogue! 'a pour'd a flagon of -Rhenish on my head once. This same skull, sir, was Yorick's -skull, the king's jester. - -Ham. -This? - -1 Clown. -E'en that. - -Ham. -Let me see. [Takes the skull.] Alas, poor Yorick!--I knew him, -Horatio; a fellow of infinite jest, of most excellent fancy: he -hath borne me on his back a thousand times; and now, how abhorred -in my imagination it is! my gorge rises at it. Here hung those -lips that I have kiss'd I know not how oft. Where be your gibes -now? your gambols? your songs? your flashes of merriment, that -were wont to set the table on a roar? Not one now, to mock your -own grinning? quite chap-fallen? Now, get you to my lady's -chamber, and tell her, let her paint an inch thick, to this -favour she must come; make her laugh at that.--Pr'ythee, Horatio, -tell me one thing. - -Hor. -What's that, my lord? - -Ham. -Dost thou think Alexander looked o' this fashion i' the earth? - -Hor. -E'en so. - -Ham. -And smelt so? Pah! - -[Throws down the skull.] - -Hor. -E'en so, my lord. - -Ham. -To what base uses we may return, Horatio! Why may not -imagination trace the noble dust of Alexander till he find it -stopping a bung-hole? - -Hor. -'Twere to consider too curiously to consider so. - -Ham. -No, faith, not a jot; but to follow him thither with modesty -enough, and likelihood to lead it: as thus: Alexander died, -Alexander was buried, Alexander returneth into dust; the dust is -earth; of earth we make loam; and why of that loam whereto he -was converted might they not stop a beer-barrel? - Imperious Caesar, dead and turn'd to clay, - Might stop a hole to keep the wind away. - O, that that earth which kept the world in awe - Should patch a wall to expel the winter's flaw! -But soft! but soft! aside!--Here comes the king. - -[Enter priests, &c, in procession; the corpse of Ophelia, -Laertes, and Mourners following; King, Queen, their Trains, &c.] - -The queen, the courtiers: who is that they follow? -And with such maimed rites? This doth betoken -The corse they follow did with desperate hand -Fordo it own life: 'twas of some estate. -Couch we awhile and mark. - -[Retiring with Horatio.] - -Laer. -What ceremony else? - -Ham. -That is Laertes, -A very noble youth: mark. - -Laer. -What ceremony else? - -1 Priest. -Her obsequies have been as far enlarg'd -As we have warranties: her death was doubtful; -And, but that great command o'ersways the order, -She should in ground unsanctified have lodg'd -Till the last trumpet; for charitable prayers, -Shards, flints, and pebbles should be thrown on her, -Yet here she is allowed her virgin rites, -Her maiden strewments, and the bringing home -Of bell and burial. - -Laer. -Must there no more be done? - -1 Priest. -No more be done; -We should profane the service of the dead -To sing a requiem and such rest to her -As to peace-parted souls. - -Laer. -Lay her i' the earth;-- -And from her fair and unpolluted flesh -May violets spring!--I tell thee, churlish priest, -A ministering angel shall my sister be -When thou liest howling. - -Ham. -What, the fair Ophelia? - -Queen. -Sweets to the sweet: farewell. -[Scattering flowers.] -I hop'd thou shouldst have been my Hamlet's wife; -I thought thy bride-bed to have deck'd, sweet maid, -And not have strew'd thy grave. - -Laer. -O, treble woe -Fall ten times treble on that cursed head -Whose wicked deed thy most ingenious sense -Depriv'd thee of!--Hold off the earth awhile, -Till I have caught her once more in mine arms: -[Leaps into the grave.] -Now pile your dust upon the quick and dead, -Till of this flat a mountain you have made, -To o'ertop old Pelion or the skyish head -Of blue Olympus. - -Ham. -[Advancing.] -What is he whose grief -Bears such an emphasis? whose phrase of sorrow -Conjures the wandering stars, and makes them stand -Like wonder-wounded hearers? this is I, -Hamlet the Dane. -[Leaps into the grave.] - -Laer. -The devil take thy soul! -[Grappling with him.] - -Ham. -Thou pray'st not well. -I pr'ythee, take thy fingers from my throat; -For, though I am not splenetive and rash, -Yet have I in me something dangerous, -Which let thy wiseness fear: away thy hand! - -King. -Pluck them asunder. - -Queen. -Hamlet! Hamlet! - -All. -Gentlemen!-- - -Hor. -Good my lord, be quiet. - -[The Attendants part them, and they come out of the grave.] - -Ham. -Why, I will fight with him upon this theme -Until my eyelids will no longer wag. - -Queen. -O my son, what theme? - -Ham. -I lov'd Ophelia; forty thousand brothers -Could not, with all their quantity of love, -Make up my sum.--What wilt thou do for her? - -King. -O, he is mad, Laertes. - -Queen. -For love of God, forbear him! - -Ham. -'Swounds, show me what thou'lt do: -Woul't weep? woul't fight? woul't fast? woul't tear thyself? -Woul't drink up eisel? eat a crocodile? -I'll do't.--Dost thou come here to whine? -To outface me with leaping in her grave? -Be buried quick with her, and so will I: -And, if thou prate of mountains, let them throw -Millions of acres on us, till our ground, -Singeing his pate against the burning zone, -Make Ossa like a wart! Nay, an thou'lt mouth, -I'll rant as well as thou. - -Queen. -This is mere madness: -And thus a while the fit will work on him; -Anon, as patient as the female dove, -When that her golden couplets are disclos'd, -His silence will sit drooping. - -Ham. -Hear you, sir; -What is the reason that you use me thus? -I lov'd you ever: but it is no matter; -Let Hercules himself do what he may, -The cat will mew, and dog will have his day. - -[Exit.] - -King. -I pray thee, good Horatio, wait upon him.-- - -[Exit Horatio.] -[To Laertes] -Strengthen your patience in our last night's speech; -We'll put the matter to the present push.-- -Good Gertrude, set some watch over your son.-- -This grave shall have a living monument: -An hour of quiet shortly shall we see; -Till then in patience our proceeding be. - -[Exeunt.] - - - -Scene II. A hall in the Castle. - -[Enter Hamlet and Horatio.] - -Ham. -So much for this, sir: now let me see the other; -You do remember all the circumstance? - -Hor. -Remember it, my lord! - -Ham. -Sir, in my heart there was a kind of fighting -That would not let me sleep: methought I lay -Worse than the mutinies in the bilboes. Rashly, -And prais'd be rashness for it,--let us know, -Our indiscretion sometime serves us well, -When our deep plots do fail; and that should teach us -There's a divinity that shapes our ends, -Rough-hew them how we will. - -Hor. -That is most certain. - -Ham. -Up from my cabin, -My sea-gown scarf'd about me, in the dark -Grop'd I to find out them: had my desire; -Finger'd their packet; and, in fine, withdrew -To mine own room again: making so bold, -My fears forgetting manners, to unseal -Their grand commission; where I found, Horatio, -O royal knavery! an exact command,-- -Larded with many several sorts of reasons, -Importing Denmark's health, and England's too, -With, ho! such bugs and goblins in my life,-- -That, on the supervise, no leisure bated, -No, not to stay the grinding of the axe, -My head should be struck off. - -Hor. -Is't possible? - -Ham. -Here's the commission: read it at more leisure. -But wilt thou bear me how I did proceed? - -Hor. -I beseech you. - -Ham. -Being thus benetted round with villanies,-- -Or I could make a prologue to my brains, -They had begun the play,--I sat me down; -Devis'd a new commission; wrote it fair: -I once did hold it, as our statists do, -A baseness to write fair, and labour'd much -How to forget that learning; but, sir, now -It did me yeoman's service. Wilt thou know -The effect of what I wrote? - -Hor. -Ay, good my lord. - -Ham. -An earnest conjuration from the king,-- -As England was his faithful tributary; -As love between them like the palm might flourish; -As peace should still her wheaten garland wear -And stand a comma 'tween their amities; -And many such-like as's of great charge,-- -That, on the view and know of these contents, -Without debatement further, more or less, -He should the bearers put to sudden death, -Not shriving-time allow'd. - -Hor. -How was this seal'd? - -Ham. -Why, even in that was heaven ordinant. -I had my father's signet in my purse, -Which was the model of that Danish seal: -Folded the writ up in the form of the other; -Subscrib'd it: gave't the impression; plac'd it safely, -The changeling never known. Now, the next day -Was our sea-fight; and what to this was sequent -Thou know'st already. - -Hor. -So Guildenstern and Rosencrantz go to't. - -Ham. -Why, man, they did make love to this employment; -They are not near my conscience; their defeat -Does by their own insinuation grow: -'Tis dangerous when the baser nature comes -Between the pass and fell incensed points -Of mighty opposites. - -Hor. -Why, what a king is this! - -Ham. -Does it not, thinks't thee, stand me now upon,-- -He that hath kill'd my king, and whor'd my mother; -Popp'd in between the election and my hopes; -Thrown out his angle for my proper life, -And with such cozenage--is't not perfect conscience -To quit him with this arm? and is't not to be damn'd -To let this canker of our nature come -In further evil? - -Hor. -It must be shortly known to him from England -What is the issue of the business there. - -Ham. -It will be short: the interim is mine; -And a man's life is no more than to say One. -But I am very sorry, good Horatio, -That to Laertes I forgot myself; -For by the image of my cause I see -The portraiture of his: I'll court his favours: -But, sure, the bravery of his grief did put me -Into a towering passion. - -Hor. -Peace; who comes here? - -[Enter Osric.] - -Osr. -Your lordship is right welcome back to Denmark. - -Ham. -I humbly thank you, sir. Dost know this water-fly? - -Hor. -No, my good lord. - -Ham. -Thy state is the more gracious; for 'tis a vice to know him. He -hath much land, and fertile: let a beast be lord of beasts, and -his crib shall stand at the king's mess; 'tis a chough; but, as I -say, spacious in the possession of dirt. - -Osr. -Sweet lord, if your lordship were at leisure, I should -impart a thing to you from his majesty. - -Ham. -I will receive it with all diligence of spirit. Put your -bonnet to his right use; 'tis for the head. - -Osr. -I thank your lordship, t'is very hot. - -Ham. -No, believe me, 'tis very cold; the wind is northerly. - -Osr. -It is indifferent cold, my lord, indeed. - -Ham. -Methinks it is very sultry and hot for my complexion. - -Osr. -Exceedingly, my lord; it is very sultry,--as 'twere--I cannot -tell how. But, my lord, his majesty bade me signify to you that -he has laid a great wager on your head. Sir, this is the -matter,-- - -Ham. -I beseech you, remember,-- -[Hamlet moves him to put on his hat.] - -Osr. -Nay, in good faith; for mine ease, in good faith. Sir, here -is newly come to court Laertes; believe me, an absolute -gentleman, full of most excellent differences, of very soft -society and great showing: indeed, to speak feelingly of him, he -is the card or calendar of gentry; for you shall find in him the -continent of what part a gentleman would see. - -Ham. -Sir, his definement suffers no perdition in you;--though, I -know, to divide him inventorially would dizzy the arithmetic of -memory, and yet but yaw neither, in respect of his quick sail. -But, in the verity of extolment, I take him to be a soul of great -article, and his infusion of such dearth and rareness as, to make -true diction of him, his semblable is his mirror, and who else -would trace him, his umbrage, nothing more. - -Osr. -Your lordship speaks most infallibly of him. - -Ham. -The concernancy, sir? why do we wrap the gentleman in our more -rawer breath? - -Osr. -Sir? - -Hor. -Is't not possible to understand in another tongue? You will do't, -sir, really. - -Ham. -What imports the nomination of this gentleman? - -Osr. -Of Laertes? - -Hor. -His purse is empty already; all's golden words are spent. - -Ham. -Of him, sir. - -Osr. -I know, you are not ignorant,-- - -Ham. -I would you did, sir; yet, in faith, if you did, it would not -much approve me.--Well, sir. - -Osr. -You are not ignorant of what excellence Laertes is,-- - -Ham. -I dare not confess that, lest I should compare with him in -excellence; but to know a man well were to know himself. - -Osr. -I mean, sir, for his weapon; but in the imputation laid on -him by them, in his meed he's unfellowed. - -Ham. -What's his weapon? - -Osr. -Rapier and dagger. - -Ham. -That's two of his weapons:--but well. - -Osr. -The king, sir, hath wager'd with him six Barbary horses: -against the which he has imponed, as I take it, six French -rapiers and poniards, with their assigns, as girdle, hangers, and -so: three of the carriages, in faith, are very dear to fancy, -very responsive to the hilts, most delicate carriages, and of -very liberal conceit. - -Ham. -What call you the carriages? - -Hor. -I knew you must be edified by the margent ere you had done. - -Osr. -The carriages, sir, are the hangers. - -Ham. -The phrase would be more german to the matter if we could -carry cannon by our sides. I would it might be hangers till then. -But, on: six Barbary horses against six French swords, their -assigns, and three liberal conceited carriages: that's the French -bet against the Danish: why is this all imponed, as you call it? - -Osr. -The king, sir, hath laid that, in a dozen passes between -your and him, he shall not exceed you three hits: he hath -laid on twelve for nine; and it would come to immediate trial -if your lordship would vouchsafe the answer. - -Ham. -How if I answer no? - -Osr. -I mean, my lord, the opposition of your person in trial. - -Ham. -Sir, I will walk here in the hall: if it please his majesty, -it is the breathing time of day with me: let the foils be -brought, the gentleman willing, and the king hold his purpose, -I will win for him if I can; if not, I will gain nothing but my -shame and the odd hits. - -Osr. -Shall I re-deliver you e'en so? - -Ham. -To this effect, sir; after what flourish your nature will. - -Osr. -I commend my duty to your lordship. - -Ham. -Yours, yours. - -[Exit Osric.] - -He does well to commend it himself; there are no tongues else -for's turn. - -Hor. -This lapwing runs away with the shell on his head. - -Ham. -He did comply with his dug before he suck'd it. Thus has he,--and -many more of the same bevy that I know the drossy age dotes on,-- -only got the tune of the time and outward habit of encounter; -a kind of yesty collection, which carries them through and -through the most fanned and winnowed opinions; and do but blow -them to their trial, the bubbles are out, - -[Enter a Lord.] - -Lord. -My lord, his majesty commended him to you by young Osric, -who brings back to him that you attend him in the hall: he sends -to know if your pleasure hold to play with Laertes, or that you -will take longer time. - -Ham. -I am constant to my purposes; they follow the king's pleasure: -if his fitness speaks, mine is ready; now or whensoever, provided -I be so able as now. - -Lord. -The King and Queen and all are coming down. - -Ham. -In happy time. - -Lord. -The queen desires you to use some gentle entertainment to -Laertes before you fall to play. - -Ham. -She well instructs me. - -[Exit Lord.] - -Hor. -You will lose this wager, my lord. - -Ham. -I do not think so; since he went into France I have been in -continual practice: I shall win at the odds. But thou wouldst not -think how ill all's here about my heart: but it is no matter. - -Hor. -Nay, good my lord,-- - -Ham. -It is but foolery; but it is such a kind of gain-giving as -would perhaps trouble a woman. - -Hor. -If your mind dislike anything, obey it: I will forestall their -repair hither, and say you are not fit. - -Ham. -Not a whit, we defy augury: there's a special providence in -the fall of a sparrow. If it be now, 'tis not to come; if it be -not to come, it will be now; if it be not now, yet it will come: -the readiness is all: since no man has aught of what he leaves, -what is't to leave betimes? - -[Enter King, Queen, Laertes, Lords, Osric, and Attendants with -foils &c.] - -King. -Come, Hamlet, come, and take this hand from me. - -[The King puts Laertes' hand into Hamlet's.] - -Ham. -Give me your pardon, sir: I have done you wrong: -But pardon't, as you are a gentleman. -This presence knows, and you must needs have heard, -How I am punish'd with sore distraction. -What I have done -That might your nature, honour, and exception -Roughly awake, I here proclaim was madness. -Was't Hamlet wrong'd Laertes? Never Hamlet: -If Hamlet from himself be ta'en away, -And when he's not himself does wrong Laertes, -Then Hamlet does it not, Hamlet denies it. -Who does it, then? His madness: if't be so, -Hamlet is of the faction that is wrong'd; -His madness is poor Hamlet's enemy. -Sir, in this audience, -Let my disclaiming from a purpos'd evil -Free me so far in your most generous thoughts -That I have shot my arrow o'er the house -And hurt my brother. - -Laer. -I am satisfied in nature, -Whose motive, in this case, should stir me most -To my revenge. But in my terms of honour -I stand aloof; and will no reconcilement -Till by some elder masters of known honour -I have a voice and precedent of peace -To keep my name ungor'd. But till that time -I do receive your offer'd love like love, -And will not wrong it. - -Ham. -I embrace it freely; -And will this brother's wager frankly play.-- -Give us the foils; come on. - -Laer. -Come, one for me. - -Ham. -I'll be your foil, Laertes; in mine ignorance -Your skill shall, like a star in the darkest night, -Stick fiery off indeed. - -Laer. -You mock me, sir. - -Ham. -No, by this hand. - -King. -Give them the foils, young Osric. Cousin Hamlet, -You know the wager? - -Ham. -Very well, my lord; -Your grace has laid the odds o' the weaker side. - -King. -I do not fear it; I have seen you both; -But since he's better'd, we have therefore odds. - -Laer. -This is too heavy, let me see another. - -Ham. -This likes me well. These foils have all a length? - -[They prepare to play.] - -Osr. -Ay, my good lord. - -King. -Set me the stoups of wine upon that table,-- -If Hamlet give the first or second hit, -Or quit in answer of the third exchange, -Let all the battlements their ordnance fire; -The king shall drink to Hamlet's better breath; -And in the cup an union shall he throw, -Richer than that which four successive kings -In Denmark's crown have worn. Give me the cups; -And let the kettle to the trumpet speak, -The trumpet to the cannoneer without, -The cannons to the heavens, the heavens to earth, -'Now the king drinks to Hamlet.'--Come, begin:-- -And you, the judges, bear a wary eye. - -Ham. -Come on, sir. - -Laer. -Come, my lord. - -[They play.] - -Ham. -One. - -Laer. -No. - -Ham. -Judgment! - -Osr. -A hit, a very palpable hit. - -Laer. -Well;--again. - -King. -Stay, give me drink.--Hamlet, this pearl is thine; -Here's to thy health.-- - -[Trumpets sound, and cannon shot off within.] - -Give him the cup. - -Ham. -I'll play this bout first; set it by awhile.-- -Come.--Another hit; what say you? - -[They play.] - -Laer. -A touch, a touch, I do confess. - -King. -Our son shall win. - -Queen. -He's fat, and scant of breath.-- -Here, Hamlet, take my napkin, rub thy brows: -The queen carouses to thy fortune, Hamlet. - -Ham. -Good madam! - -King. -Gertrude, do not drink. - -Queen. -I will, my lord; I pray you pardon me. - -King. -[Aside.] It is the poison'd cup; it is too late. - -Ham. -I dare not drink yet, madam; by-and-by. - -Queen. -Come, let me wipe thy face. - -Laer. -My lord, I'll hit him now. - -King. -I do not think't. - -Laer. -[Aside.] And yet 'tis almost 'gainst my conscience. - -Ham. -Come, for the third, Laertes: you but dally; -I pray you pass with your best violence: -I am afeard you make a wanton of me. - -Laer. -Say you so? come on. - -[They play.] - -Osr. -Nothing, neither way. - -Laer. -Have at you now! - -[Laertes wounds Hamlet; then, in scuffling, they -change rapiers, and Hamlet wounds Laertes.] - -King. -Part them; they are incens'd. - -Ham. -Nay, come again! - -[The Queen falls.] - -Osr. -Look to the queen there, ho! - -Hor. -They bleed on both sides.--How is it, my lord? - -Osr. -How is't, Laertes? - -Laer. -Why, as a woodcock to my own springe, Osric; -I am justly kill'd with mine own treachery. - -Ham. -How does the Queen? - -King. -She swoons to see them bleed. - -Queen. -No, no! the drink, the drink!--O my dear Hamlet!-- -The drink, the drink!--I am poison'd. - -[Dies.] - -Ham. -O villany!--Ho! let the door be lock'd: -Treachery! seek it out. - -[Laertes falls.] - -Laer. -It is here, Hamlet: Hamlet, thou art slain; -No medicine in the world can do thee good; -In thee there is not half an hour of life; -The treacherous instrument is in thy hand, -Unbated and envenom'd: the foul practice -Hath turn'd itself on me; lo, here I lie, -Never to rise again: thy mother's poison'd: -I can no more:--the king, the king's to blame. - -Ham. -The point envenom'd too!-- -Then, venom, to thy work. - -[Stabs the King.] - -Osric and Lords. -Treason! treason! - -King. -O, yet defend me, friends! I am but hurt. - -Ham. -Here, thou incestuous, murderous, damned Dane, -Drink off this potion.--Is thy union here? -Follow my mother. - -[King dies.] - -Laer. -He is justly serv'd; -It is a poison temper'd by himself.-- -Exchange forgiveness with me, noble Hamlet: -Mine and my father's death come not upon thee, -Nor thine on me! - -[Dies.] - -Ham. -Heaven make thee free of it! I follow thee.-- -I am dead, Horatio.--Wretched queen, adieu!-- -You that look pale and tremble at this chance, -That are but mutes or audience to this act, -Had I but time,--as this fell sergeant, death, -Is strict in his arrest,--O, I could tell you,-- -But let it be.--Horatio, I am dead; -Thou liv'st; report me and my cause aright -To the unsatisfied. - -Hor. -Never believe it: -I am more an antique Roman than a Dane.-- -Here's yet some liquor left. - -Ham. -As thou'rt a man, -Give me the cup; let go; by heaven, I'll have't.-- -O good Horatio, what a wounded name, -Things standing thus unknown, shall live behind me! -If thou didst ever hold me in thy heart, -Absent thee from felicity awhile, -And in this harsh world draw thy breath in pain, -To tell my story.-- - -[March afar off, and shot within.] - -What warlike noise is this? - -Osr. -Young Fortinbras, with conquest come from Poland, -To the ambassadors of England gives -This warlike volley. - -Ham. -O, I die, Horatio; -The potent poison quite o'er-crows my spirit: -I cannot live to hear the news from England; -But I do prophesy the election lights -On Fortinbras: he has my dying voice; -So tell him, with the occurrents, more and less, -Which have solicited.--the rest is silence. - -[Dies.] - -Hor. -Now cracks a noble heart.--Good night, sweet prince, -And flights of angels sing thee to thy rest! -Why does the drum come hither? - -[March within.] - -[Enter Fortinbras, the English Ambassadors, and others.] - -Fort. -Where is this sight? - -Hor. -What is it you will see? -If aught of woe or wonder, cease your search. - -Fort. -This quarry cries on havoc.--O proud death, -What feast is toward in thine eternal cell, -That thou so many princes at a shot -So bloodily hast struck? - -1 Ambassador. -The sight is dismal; -And our affairs from England come too late: -The ears are senseless that should give us hearing, -To tell him his commandment is fulfill'd -That Rosencrantz and Guildenstern are dead: -Where should we have our thanks? - -Hor. -Not from his mouth, -Had it the ability of life to thank you: -He never gave commandment for their death. -But since, so jump upon this bloody question, -You from the Polack wars, and you from England, -Are here arriv'd, give order that these bodies -High on a stage be placed to the view; -And let me speak to the yet unknowing world -How these things came about: so shall you hear -Of carnal, bloody and unnatural acts; -Of accidental judgments, casual slaughters; -Of deaths put on by cunning and forc'd cause; -And, in this upshot, purposes mistook -Fall'n on the inventors' heads: all this can I -Truly deliver. - -Fort. -Let us haste to hear it, -And call the noblest to the audience. -For me, with sorrow I embrace my fortune: -I have some rights of memory in this kingdom, -Which now, to claim my vantage doth invite me. - -Hor. -Of that I shall have also cause to speak, -And from his mouth whose voice will draw on more: -But let this same be presently perform'd, -Even while men's minds are wild: lest more mischance -On plots and errors happen. - -Fort. -Let four captains -Bear Hamlet like a soldier to the stage; -For he was likely, had he been put on, -To have prov'd most royally: and, for his passage, -The soldiers' music and the rites of war -Speak loudly for him.-- -Take up the bodies.--Such a sight as this -Becomes the field, but here shows much amiss. -Go, bid the soldiers shoot. - -[A dead march.] - -[Exeunt, bearing off the dead bodies; after the which a peal of -ordnance is shot off.] - - diff --git a/mode/examples/Topics/Animation/AnimatedSprite/AnimatedSprite.pde b/mode/examples/Topics/Animation/AnimatedSprite/AnimatedSprite.pde deleted file mode 100644 index 1c13f0199..000000000 --- a/mode/examples/Topics/Animation/AnimatedSprite/AnimatedSprite.pde +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Animated Sprite (Shifty + Teddy) - * by James Patterson. - * - * Press the mouse button to change animations. - * Demonstrates loading, displaying, and animating GIF images. - * It would be easy to write a program to display - * animated GIFs, but would not allow as much control over - * the display sequence and rate of display. - */ - -Animation animation1, animation2; -float xpos, ypos; -float drag = 30.0; - -void setup() { - size(200, 200); - background(255, 204, 0); - frameRate(24); - animation1 = new Animation("PT_Shifty_", 38); - animation2 = new Animation("PT_Teddy_", 60); -} - -void draw() { - float difx = mouseX - xpos; - if (abs(difx) > 1.0) { - xpos = xpos + difx/drag; - xpos = constrain(xpos, 0, width); - } - - // Display the sprite at the position xpos, ypos - if (mousePressed) { - background(153, 153, 0); - animation1.display(xpos-animation1.getWidth()/2, ypos); - } else { - background(255, 204, 0); - animation2.display(xpos-animation1.getWidth()/2, ypos); - } -} diff --git a/mode/examples/Topics/Animation/AnimatedSprite/Animation.pde b/mode/examples/Topics/Animation/AnimatedSprite/Animation.pde deleted file mode 100644 index 6c98ef20b..000000000 --- a/mode/examples/Topics/Animation/AnimatedSprite/Animation.pde +++ /dev/null @@ -1,27 +0,0 @@ -// Class for animating a sequence of GIFs - -class Animation { - PImage[] images; - int imageCount; - int frame; - - Animation(String imagePrefix, int count) { - imageCount = count; - images = new PImage[imageCount]; - - for (int i = 0; i < imageCount; i++) { - // Use nf() to number format 'i' into four digits - String filename = imagePrefix + nf(i, 4) + ".gif"; - images[i] = loadImage(filename); - } - } - - void display(float xpos, float ypos) { - frame = (frame+1) % imageCount; - image(images[frame], xpos, ypos); - } - - int getWidth() { - return images[0].width; - } -} diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0000.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0000.gif deleted file mode 100644 index 1a9893ad2..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0000.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0001.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0001.gif deleted file mode 100644 index 1a9893ad2..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0001.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0002.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0002.gif deleted file mode 100644 index c53edb943..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0002.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0003.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0003.gif deleted file mode 100644 index b9c4fc675..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0003.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0004.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0004.gif deleted file mode 100644 index b43d0b308..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0004.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0005.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0005.gif deleted file mode 100644 index 36f373249..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0005.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0006.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0006.gif deleted file mode 100644 index b4c6ab5e6..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0006.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0007.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0007.gif deleted file mode 100644 index a53c6abc7..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0007.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0008.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0008.gif deleted file mode 100644 index 1ce59b9a6..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0008.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0009.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0009.gif deleted file mode 100644 index 557bedf8e..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0009.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0010.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0010.gif deleted file mode 100644 index 31fd776e4..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0010.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0011.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0011.gif deleted file mode 100644 index a69083697..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0011.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0012.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0012.gif deleted file mode 100644 index fe81e42ac..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0012.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0013.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0013.gif deleted file mode 100644 index c8ede5df6..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0013.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0014.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0014.gif deleted file mode 100644 index 1f1413761..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0014.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0015.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0015.gif deleted file mode 100644 index de472dfe7..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0015.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0016.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0016.gif deleted file mode 100644 index 5bc583f0a..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0016.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0017.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0017.gif deleted file mode 100644 index 8ff438690..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0017.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0018.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0018.gif deleted file mode 100644 index 0b99e3727..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0018.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0019.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0019.gif deleted file mode 100644 index 7a9217ad3..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0019.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0020.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0020.gif deleted file mode 100644 index fe8fdae31..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0020.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0021.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0021.gif deleted file mode 100644 index ab36afe0d..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0021.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0022.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0022.gif deleted file mode 100644 index 98dc00b57..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0022.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0023.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0023.gif deleted file mode 100644 index a3dd7f38c..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0023.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0024.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0024.gif deleted file mode 100644 index f8287855a..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0024.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0025.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0025.gif deleted file mode 100644 index 0107f470c..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0025.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0026.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0026.gif deleted file mode 100644 index e05a13944..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0026.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0027.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0027.gif deleted file mode 100644 index decdebe59..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0027.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0028.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0028.gif deleted file mode 100644 index ec2bae766..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0028.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0029.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0029.gif deleted file mode 100644 index 67d14b168..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0029.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0030.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0030.gif deleted file mode 100644 index 619c30c94..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0030.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0031.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0031.gif deleted file mode 100644 index aae6bfbf3..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0031.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0032.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0032.gif deleted file mode 100644 index 7cdd3561b..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0032.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0033.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0033.gif deleted file mode 100644 index 97fc08480..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0033.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0034.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0034.gif deleted file mode 100644 index 85e71dd53..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0034.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0035.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0035.gif deleted file mode 100644 index 752393673..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0035.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0036.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0036.gif deleted file mode 100644 index 92bf1c3da..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0036.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0037.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0037.gif deleted file mode 100644 index 397590e38..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Shifty_0037.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0000.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0000.gif deleted file mode 100644 index 2f824d4ae..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0000.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0001.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0001.gif deleted file mode 100644 index 08badda94..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0001.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0002.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0002.gif deleted file mode 100644 index 06624ab2c..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0002.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0003.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0003.gif deleted file mode 100644 index ea92ccc97..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0003.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0004.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0004.gif deleted file mode 100644 index 4bd11209c..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0004.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0005.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0005.gif deleted file mode 100644 index 35dd95adf..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0005.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0006.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0006.gif deleted file mode 100644 index e03110292..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0006.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0007.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0007.gif deleted file mode 100644 index c64d4f836..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0007.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0008.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0008.gif deleted file mode 100644 index 3ceb22ee7..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0008.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0009.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0009.gif deleted file mode 100644 index e641c42d8..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0009.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0010.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0010.gif deleted file mode 100644 index fcf8234bd..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0010.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0011.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0011.gif deleted file mode 100644 index 0a66343cc..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0011.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0012.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0012.gif deleted file mode 100644 index d99ab85ab..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0012.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0013.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0013.gif deleted file mode 100644 index bf83cace6..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0013.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0014.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0014.gif deleted file mode 100644 index 5cf39974a..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0014.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0015.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0015.gif deleted file mode 100644 index 2389da333..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0015.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0016.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0016.gif deleted file mode 100644 index 837b6e533..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0016.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0017.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0017.gif deleted file mode 100644 index be36c20b1..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0017.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0018.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0018.gif deleted file mode 100644 index e2da21d31..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0018.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0019.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0019.gif deleted file mode 100644 index c7125f6f2..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0019.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0020.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0020.gif deleted file mode 100644 index 21084a485..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0020.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0021.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0021.gif deleted file mode 100644 index 5a7d2b462..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0021.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0022.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0022.gif deleted file mode 100644 index aa4d8b34a..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0022.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0023.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0023.gif deleted file mode 100644 index 81952946e..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0023.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0024.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0024.gif deleted file mode 100644 index f0cfcd142..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0024.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0025.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0025.gif deleted file mode 100644 index d3e55f403..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0025.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0026.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0026.gif deleted file mode 100644 index 19aa7b6c3..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0026.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0027.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0027.gif deleted file mode 100644 index 0291b3f57..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0027.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0028.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0028.gif deleted file mode 100644 index 84d403c32..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0028.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0029.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0029.gif deleted file mode 100644 index a15ef905f..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0029.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0030.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0030.gif deleted file mode 100644 index 945a0053d..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0030.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0031.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0031.gif deleted file mode 100644 index f922e5651..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0031.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0032.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0032.gif deleted file mode 100644 index 0aff66645..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0032.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0033.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0033.gif deleted file mode 100644 index 7fedb4832..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0033.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0034.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0034.gif deleted file mode 100644 index 19a4d20ff..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0034.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0035.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0035.gif deleted file mode 100644 index 3dd6abcb7..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0035.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0036.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0036.gif deleted file mode 100644 index 93277ef54..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0036.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0037.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0037.gif deleted file mode 100644 index c9c0a0903..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0037.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0038.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0038.gif deleted file mode 100644 index f0a00a1be..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0038.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0039.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0039.gif deleted file mode 100644 index 4a8b14e27..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0039.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0040.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0040.gif deleted file mode 100644 index 88e8eb147..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0040.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0041.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0041.gif deleted file mode 100644 index 0353138a5..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0041.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0042.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0042.gif deleted file mode 100644 index 4ef947509..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0042.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0043.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0043.gif deleted file mode 100644 index aebe10476..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0043.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0044.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0044.gif deleted file mode 100644 index 96464a3cb..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0044.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0045.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0045.gif deleted file mode 100644 index 35e40b8c4..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0045.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0046.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0046.gif deleted file mode 100644 index 8476318e9..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0046.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0047.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0047.gif deleted file mode 100644 index 512c6eebc..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0047.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0048.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0048.gif deleted file mode 100644 index 9fdecf6f1..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0048.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0049.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0049.gif deleted file mode 100644 index 5988e0ff9..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0049.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0050.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0050.gif deleted file mode 100644 index 2dde61ea0..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0050.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0051.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0051.gif deleted file mode 100644 index 24ef0346d..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0051.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0052.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0052.gif deleted file mode 100644 index 132a9ad32..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0052.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0053.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0053.gif deleted file mode 100644 index d5ffebc03..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0053.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0054.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0054.gif deleted file mode 100644 index e09375aa0..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0054.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0055.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0055.gif deleted file mode 100644 index e09375aa0..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0055.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0056.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0056.gif deleted file mode 100644 index 80ee11d98..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0056.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0057.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0057.gif deleted file mode 100644 index 9af1fbacc..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0057.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0058.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0058.gif deleted file mode 100644 index 7265b9fee..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0058.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0059.gif b/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0059.gif deleted file mode 100644 index c4f730ef2..000000000 Binary files a/mode/examples/Topics/Animation/AnimatedSprite/data/PT_Teddy_0059.gif and /dev/null differ diff --git a/mode/examples/Topics/Animation/Sequential/Sequential.pde b/mode/examples/Topics/Animation/Sequential/Sequential.pde deleted file mode 100644 index a98b6d75b..000000000 --- a/mode/examples/Topics/Animation/Sequential/Sequential.pde +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Sequential - * by James Patterson. - * - * Displaying a sequence of images creates the illusion of motion. - * Twelve images are loaded and each is displayed individually in a loop. - */ - -int numFrames = 12; // The number of frames in the animation -int frame = 0; -PImage[] images = new PImage[numFrames]; - -void setup() -{ - size(200, 200); - frameRate(30); - - images[0] = loadImage("PT_anim0000.gif"); - images[1] = loadImage("PT_anim0001.gif"); - images[2] = loadImage("PT_anim0002.gif"); - images[3] = loadImage("PT_anim0003.gif"); - images[4] = loadImage("PT_anim0004.gif"); - images[5] = loadImage("PT_anim0005.gif"); - images[6] = loadImage("PT_anim0006.gif"); - images[7] = loadImage("PT_anim0007.gif"); - images[8] = loadImage("PT_anim0008.gif"); - images[9] = loadImage("PT_anim0009.gif"); - images[10] = loadImage("PT_anim0010.gif"); - images[11] = loadImage("PT_anim0011.gif"); - - // If you don't want to load each image separately - // and you know how many frames you have, you - // can create the filenames as the program runs. - // The nf() command does number formatting, which will - // ensure that the number is (in this case) 4 digits. - //for(int i=0; i 3) && world[x][y][0] == 1) - { - world[x][y][1] = -1; - } - } - } -} - -// Count the number of adjacent cells 'on' -int neighbors(int x, int y) -{ - return world[(x + 1) % sx][y][0] + - world[x][(y + 1) % sy][0] + - world[(x + sx - 1) % sx][y][0] + - world[x][(y + sy - 1) % sy][0] + - world[(x + 1) % sx][(y + 1) % sy][0] + - world[(x + sx - 1) % sx][(y + 1) % sy][0] + - world[(x + sx - 1) % sx][(y + sy - 1) % sy][0] + - world[(x + 1) % sx][(y + sy - 1) % sy][0]; -} diff --git a/mode/examples/Topics/Cellular Automata/Spore1/Spore1.pde b/mode/examples/Topics/Cellular Automata/Spore1/Spore1.pde deleted file mode 100644 index 46ec059b1..000000000 --- a/mode/examples/Topics/Cellular Automata/Spore1/Spore1.pde +++ /dev/null @@ -1,133 +0,0 @@ -/** - * Spore 1 - * by Mike Davis. - * - * A short program for alife experiments. Click in the window to restart. - * Each cell is represented by a pixel on the display as well as an entry in - * the array 'cells'. Each cell has a run() method, which performs actions - * based on the cell's surroundings. Cells run one at a time (to avoid conflicts - * like wanting to move to the same space) and in random order. - */ - -World w; -int numcells = 0; -int maxcells = 6700; -Cell[] cells = new Cell[maxcells]; -color spore_color; -// set lower for smoother animation, higher for faster simulation -int runs_per_loop = 10000; -color black = color(0, 0, 0); - -void setup() -{ - size(640, 200, P2D); - frameRate(24); - clearscr(); - w = new World(); - spore_color = color(172, 255, 128); - seed(); -} - -void seed() -{ - // Add cells at random places - for (int i = 0; i < maxcells; i++) - { - int cX = (int)random(width); - int cY = (int)random(height); - if (w.getpix(cX, cY) == black) - { - w.setpix(cX, cY, spore_color); - cells[numcells] = new Cell(cX, cY); - numcells++; - } - } -} - -void draw() -{ - // Run cells in random order - for (int i = 0; i < runs_per_loop; i++) { - int selected = min((int)random(numcells), numcells - 1); - cells[selected].run(); - } -} - -void clearscr() -{ - background(0); -} - -class Cell -{ - int x, y; - Cell(int xin, int yin) - { - x = xin; - y = yin; - } - - // Perform action based on surroundings - void run() - { - // Fix cell coordinates - while(x < 0) { - x+=width; - } - while(x > width - 1) { - x-=width; - } - while(y < 0) { - y+=height; - } - while(y > height - 1) { - y-=height; - } - - // Cell instructions - if (w.getpix(x + 1, y) == black) { - move(0, 1); - } else if (w.getpix(x, y - 1) != black && w.getpix(x, y + 1) != black) { - move((int)random(9) - 4, (int)random(9) - 4); - } - } - - // Will move the cell (dx, dy) units if that space is empty - void move(int dx, int dy) { - if (w.getpix(x + dx, y + dy) == black) { - w.setpix(x + dx, y + dy, w.getpix(x, y)); - w.setpix(x, y, color(0)); - x += dx; - y += dy; - } - } -} - -// The World class simply provides two functions, get and set, which access the -// display in the same way as getPixel and setPixel. The only difference is that -// the World class's get and set do screen wraparound ("toroidal coordinates"). -class World -{ - void setpix(int x, int y, int c) { - while(x < 0) x+=width; - while(x > width - 1) x-=width; - while(y < 0) y+=height; - while(y > height - 1) y-=height; - set(x, y, c); - } - - color getpix(int x, int y) { - while(x < 0) x+=width; - while(x > width - 1) x-=width; - while(y < 0) y+=height; - while(y > height - 1) y-=height; - return get(x, y); - } -} - -void mousePressed() -{ - numcells = 0; - setup(); -} - diff --git a/mode/examples/Topics/Cellular Automata/Spore2/Spore2.pde b/mode/examples/Topics/Cellular Automata/Spore2/Spore2.pde deleted file mode 100644 index ab4cc8397..000000000 --- a/mode/examples/Topics/Cellular Automata/Spore2/Spore2.pde +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Spore 2 - * by Mike Davis. - * - * A short program for alife experiments. Click in the window to restart. - * Each cell is represented by a pixel on the display as well as an entry in - * the array 'cells'. Each cell has a run() method, which performs actions - * based on the cell's surroundings. Cells run one at a time (to avoid conflicts - * like wanting to move to the same space) and in random order. - */ - -World w; -int maxcells = 8000; -int numcells; -Cell[] cells = new Cell[maxcells]; -color spore1, spore2, spore3, spore4; -color black = color(0, 0, 0); -// set lower for smoother animation, higher for faster simulation -int runs_per_loop = 10000; - -void setup() -{ - size(640, 200, P2D); - frameRate(24); - clearscr(); - w = new World(); - spore1 = color(128, 172, 255); - spore2 = color(64, 128, 255); - spore3 = color(255, 128, 172); - spore4 = color(255, 64, 128); - numcells = 0; - seed(); -} - -void seed() -{ - // Add cells at random places - for (int i = 0; i < maxcells; i++) - { - int cX = int(random(width)); - int cY = int(random(height)); - int c; - float r = random(1); - if (r < 0.25) c = spore1; - else if (r < 0.5) c = spore2; - else if (r < 0.75) c = spore3; - else c = spore4; - if (w.getpix(cX, cY) == black) - { - w.setpix(cX, cY, c); - cells[numcells] = new Cell(cX, cY); - numcells++; - } - } -} - -void draw() -{ - // Run cells in random order - for (int i = 0; i < runs_per_loop; i++) { - int selected = min((int)random(numcells), numcells - 1); - cells[selected].run(); - } -} - -void clearscr() -{ - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - set(x, y, color(0)); - } - } -} - -class Cell -{ - int x, y; - Cell(int xin, int yin) - { - x = xin; - y = yin; - } - // Perform action based on surroundings - void run() - { - // Fix cell coordinates - while(x < 0) { - x+=width; - } - while(x > width - 1) { - x-=width; - } - while(y < 0) { - y+=height; - } - while(y > height - 1) { - y-=height; - } - - // Cell instructions - int myColor = w.getpix(x, y); - if (myColor == spore1) { - if (w.getpix(x - 1, y + 1) == black && w.getpix(x + 1, y + 1) == black && w.getpix(x, y + 1) == black) move(0, 1); - else if (w.getpix(x - 1, y) == spore2 && w.getpix(x - 1, y - 1) != black) move(0, -1); - else if (w.getpix(x - 1, y) == spore2 && w.getpix(x - 1, y - 1) == black) move(-1, -1); - else if (w.getpix(x + 1, y) == spore1 && w.getpix(x + 1, y - 1) != black) move(0, -1); - else if (w.getpix(x + 1, y) == spore1 && w.getpix(x + 1, y - 1) == black) move(1, -1); - else move((int)random(3) - 1, 0); - } else if (myColor == spore2) { - if (w.getpix(x - 1, y + 1) == black && w.getpix(x + 1, y + 1) == black && w.getpix(x, y + 1) == black) move(0, 1); - else if (w.getpix(x + 1, y) == spore1 && w.getpix(x + 1, y - 1) != black) move(0, -1); - else if (w.getpix(x + 1, y) == spore1 && w.getpix(x + 1, y - 1) == black) move(1, -1); - else if (w.getpix(x - 1, y) == spore2 && w.getpix(x - 1, y - 1) != black) move(0, -1); - else if (w.getpix(x - 1, y) == spore2 && w.getpix(x - 1, y - 1) == black) move(-1, -1); - else move((int)random(3) - 1, 0); - } - else if (myColor == spore3) - { - if (w.getpix(x - 1, y - 1) == black && w.getpix(x + 1, y - 1) == black && w.getpix(x, y - 1) == black) move(0, -1); - else if (w.getpix(x - 1, y) == spore4 && w.getpix(x - 1, y + 1) != black) move(0, 1); - else if (w.getpix(x - 1, y) == spore4 && w.getpix(x - 1, y + 1) == black) move(-1, 1); - else if (w.getpix(x + 1, y) == spore3 && w.getpix(x + 1, y + 1) != black) move(0, 1); - else if (w.getpix(x + 1, y) == spore3 && w.getpix(x + 1, y + 1) == black) move(1, 1); - else move((int)random(3) - 1, 0); - } - else if (myColor == spore4) - { - if (w.getpix(x - 1, y - 1) == black && w.getpix(x + 1, y - 1) == black && w.getpix(x, y - 1) == black) move(0, -1); - else if (w.getpix(x + 1, y) == spore3 && w.getpix(x + 1, y + 1) != black) move(0, 1); - else if (w.getpix(x + 1, y) == spore3 && w.getpix(x + 1, y + 1) == black) move(1, 1); - else if (w.getpix(x - 1, y) == spore4 && w.getpix(x - 1, y + 1) != black) move(0, 1); - else if (w.getpix(x - 1, y) == spore4 && w.getpix(x - 1, y + 1) == black) move(-1, 1); - else move((int)random(3) - 1, 0); - } - } - - // Will move the cell (dx, dy) units if that space is empty - void move(int dx, int dy) { - if (w.getpix(x + dx, y + dy) == black) { - w.setpix(x + dx, y + dy, w.getpix(x, y)); - w.setpix(x, y, color(0)); - x += dx; - y += dy; - } - } -} - -// The World class simply provides two functions, get and set, which access the -// display in the same way as getPixel and setPixel. The only difference is that -// the World class's get and set do screen wraparound ("toroidal coordinates"). -class World -{ - void setpix(int x, int y, int c) { - while(x < 0) x+=width; - while(x > width - 1) x-=width; - while(y < 0) y+=height; - while(y > height - 1) y-=height; - set(x, y, c); - } - - color getpix(int x, int y) { - while(x < 0) x+=width; - while(x > width - 1) x-=width; - while(y < 0) y+=height; - while(y > height - 1) y-=height; - return get(x, y); - } -} - -void mousePressed() -{ - setup(); -} - diff --git a/mode/examples/Topics/Cellular Automata/Wolfram/CA.pde b/mode/examples/Topics/Cellular Automata/Wolfram/CA.pde deleted file mode 100644 index 30d02a378..000000000 --- a/mode/examples/Topics/Cellular Automata/Wolfram/CA.pde +++ /dev/null @@ -1,94 +0,0 @@ -class CA { - - int[] cells; // An array of 0s and 1s - int generation; // How many generations? - int scl; // How many pixels wide/high is each cell? - - int[] rules; // An array to store the ruleset, for example {0,1,1,0,1,1,0,1} - - CA(int[] r) { - rules = r; - scl = 1; - cells = new int[width/scl]; - restart(); - } - - CA() { - scl = 1; - cells = new int[width/scl]; - randomize(); - restart(); - } - - // Set the rules of the CA - void setRules(int[] r) { - rules = r; - } - - // Make a random ruleset - void randomize() { - for (int i = 0; i < 8; i++) { - rules[i] = int(random(2)); - } - } - - // Reset to generation 0 - void restart() { - for (int i = 0; i < cells.length; i++) { - cells[i] = 0; - } - cells[cells.length/2] = 1; // We arbitrarily start with just the middle cell having a state of "1" - generation = 0; - } - - // The process of creating the new generation - void generate() { - // First we create an empty array for the new values - int[] nextgen = new int[cells.length]; - // For every spot, determine new state by examing current state, and neighbor states - // Ignore edges that only have one neighor - for (int i = 1; i < cells.length-1; i++) { - int left = cells[i-1]; // Left neighbor state - int me = cells[i]; // Current state - int right = cells[i+1]; // Right neighbor state - nextgen[i] = rules(left,me,right); // Compute next generation state based on ruleset - } - // Copy the array into current value - cells = (int[]) nextgen.clone(); - generation++; - } - - // This is the easy part, just draw the cells, fill 255 for '1', fill 0 for '0' - void render() { - for (int i = 0; i < cells.length; i++) { - if (cells[i] == 1) fill(255); - else fill(0); - noStroke(); - rect(i*scl,generation*scl, scl,scl); - } - } - - // Implementing the Wolfram rules - // Could be improved and made more concise, but here we can explicitly see what is going on for each case - int rules (int a, int b, int c) { - if (a == 1 && b == 1 && c == 1) return rules[0]; - if (a == 1 && b == 1 && c == 0) return rules[1]; - if (a == 1 && b == 0 && c == 1) return rules[2]; - if (a == 1 && b == 0 && c == 0) return rules[3]; - if (a == 0 && b == 1 && c == 1) return rules[4]; - if (a == 0 && b == 1 && c == 0) return rules[5]; - if (a == 0 && b == 0 && c == 1) return rules[6]; - if (a == 0 && b == 0 && c == 0) return rules[7]; - return 0; - } - - // The CA is done if it reaches the bottom of the screen - boolean finished() { - if (generation > height/scl) { - return true; - } else { - return false; - } - } -} - diff --git a/mode/examples/Topics/Cellular Automata/Wolfram/Wolfram.pde b/mode/examples/Topics/Cellular Automata/Wolfram/Wolfram.pde deleted file mode 100644 index 328e6b9b9..000000000 --- a/mode/examples/Topics/Cellular Automata/Wolfram/Wolfram.pde +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Wolfram Cellular Automata - * by Daniel Shiffman. - * - * Simple demonstration of a Wolfram 1-dimensional cellular automata - * When the system reaches bottom of the window, it restarts with a new ruleset - * Mouse click restarts as well. - */ - -CA ca; // An instance object to describe the Wolfram basic Cellular Automata - -void setup() { - size(640, 360, P2D); - frameRate(30); - background(0); - int[] ruleset = {0,1,0,1,1,0,1,0}; // An initial rule system - ca = new CA(ruleset); // Initialize CA -} - -void draw() { - ca.render(); // Draw the CA - ca.generate(); // Generate the next level - - if (ca.finished()) { // If we're done, clear the screen, pick a new ruleset and restart - background(0); - ca.randomize(); - ca.restart(); - } -} - -void mousePressed() { - background(0); - ca.randomize(); - ca.restart(); -} - - - diff --git a/mode/examples/Topics/Create Shapes/BeginEndContour/BeginEndContour.pde b/mode/examples/Topics/Create Shapes/BeginEndContour/BeginEndContour.pde deleted file mode 100644 index 2769397e1..000000000 --- a/mode/examples/Topics/Create Shapes/BeginEndContour/BeginEndContour.pde +++ /dev/null @@ -1,45 +0,0 @@ -/** - * BeginEndContour - * - * How to cut a shape out of another using beginContour() and endContour() - */ - -PShape s; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - smooth(); - // Make a shape - s = createShape(); - s.beginShape(); - s.fill(0); - s.stroke(255); - s.strokeWeight(2); - // Exterior part of shape - s.vertex(-100,-100); - s.vertex(100,-100); - s.vertex(100,100); - s.vertex(-100,100); - - // Interior part of shape - s.beginContour(); - s.vertex(-10,-10); - s.vertex(10,-10); - s.vertex(10,10); - s.vertex(-10,10); - s.endContour(); - - // Finishing off shape - s.endShape(CLOSE); -} - -void draw() { - background(52); - // Display shape - translate(width/2, height/2); - // Shapes can be rotated - s.rotate(0.01); - shape(s); -} - diff --git a/mode/examples/Topics/Create Shapes/GroupPShape/GroupPShape.pde b/mode/examples/Topics/Create Shapes/GroupPShape/GroupPShape.pde deleted file mode 100644 index 79007fc69..000000000 --- a/mode/examples/Topics/Create Shapes/GroupPShape/GroupPShape.pde +++ /dev/null @@ -1,68 +0,0 @@ -/** - * GroupPShape - * - * How to group multiple PShapes into one PShape - */ - - -// A PShape that will group PShapes -PShape group; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - smooth(); - // Create the shape as a group - group = createShape(GROUP); - - // Make a polygon PShape - PShape star = createShape(); - star.beginShape(); - star.noFill(); - star.stroke(255); - star.vertex(0, -50); - star.vertex(14, -20); - star.vertex(47, -15); - star.vertex(23, 7); - star.vertex(29, 40); - star.vertex(0, 25); - star.vertex(-29, 40); - star.vertex(-23, 7); - star.vertex(-47, -15); - star.vertex(-14, -20); - star.endShape(CLOSE); - - // Make a path PShape - PShape path = createShape(); - path.beginShape(); - path.noFill(); - path.stroke(255); - for (float a = -PI; a < 0; a += 0.1) { - float r = random(60, 70); - path.vertex(r*cos(a), r*sin(a)); - } - path.endShape(); - - // Make a primitive (Rectangle) PShape - PShape rectangle = createShape(RECT,-10,-10,20,20); - rectangle.setFill(false); - rectangle.setStroke(color(255)); - - // Add them all to the group - group.addChild(star); - group.addChild(path); - group.addChild(rectangle); -} - -void draw() { - // We can access them individually via the group PShape - PShape rectangle = group.getChild(2); - // Shapes can be rotated - rectangle.rotate(0.1); - - background(52); - // Display the group PShape - translate(mouseX, mouseY); - shape(group); -} - diff --git a/mode/examples/Topics/Create Shapes/ParticleSystemPShape/Particle.pde b/mode/examples/Topics/Create Shapes/ParticleSystemPShape/Particle.pde deleted file mode 100644 index ccccb6509..000000000 --- a/mode/examples/Topics/Create Shapes/ParticleSystemPShape/Particle.pde +++ /dev/null @@ -1,82 +0,0 @@ -// An individual Particle - -class Particle { - - // Velocity - PVector center; - PVector velocity; - // Lifespane is tied to alpha - float lifespan; - - // The particle PShape - PShape part; - // The particle size - float partSize; - - // A single force - PVector gravity = new PVector(0, 0.1); - - Particle() { - partSize = random(10, 60); - // The particle is a textured quad - part = createShape(); - part.beginShape(QUAD); - part.noStroke(); - part.texture(sprite); - part.normal(0, 0, 1); - part.vertex(-partSize/2, -partSize/2, 0, 0); - part.vertex(+partSize/2, -partSize/2, sprite.width, 0); - part.vertex(+partSize/2, +partSize/2, sprite.width, sprite.height); - part.vertex(-partSize/2, +partSize/2, 0, sprite.height); - part.endShape(); - - // Initialize center vector - center = new PVector(); - - // Set the particle starting location - rebirth(width/2, height/2); - } - - PShape getShape() { - return part; - } - - void rebirth(float x, float y) { - float a = random(TWO_PI); - float speed = random(0.5, 4); - // A velocity with random angle and magnitude - velocity = PVector.fromAngle(a); - velocity.mult(speed); - // Set lifespan - lifespan = 255; - // Set location using translate - part.resetMatrix(); - part.translate(x, y); - - // Update center vector - center.set(x, y, 0); - } - - // Is it off the screen, or its lifespan is over? - boolean isDead() { - if (center.x > width || center.x < 0 || - center.y > height || center.y < 0 || lifespan < 0) { - return true; - } - else { - return false; - } - } - - void update() { - // Decrease life - lifespan = lifespan - 1; - // Apply gravity - velocity.add(gravity); - part.setTint(color(255, lifespan)); - // Move the particle according to its velocity - part.translate(velocity.x, velocity.y); - // and also update the center - center.add(velocity); - } -} diff --git a/mode/examples/Topics/Create Shapes/ParticleSystemPShape/ParticleSystem.pde b/mode/examples/Topics/Create Shapes/ParticleSystemPShape/ParticleSystem.pde deleted file mode 100644 index e2215046e..000000000 --- a/mode/examples/Topics/Create Shapes/ParticleSystemPShape/ParticleSystem.pde +++ /dev/null @@ -1,43 +0,0 @@ -// The Particle System - -class ParticleSystem { - // It's just an ArrayList of particle objects - ArrayList particles; - - // The PShape to group all the particle PShapes - PShape particleShape; - - ParticleSystem(int n) { - particles = new ArrayList(); - // The PShape is a group - particleShape = createShape(GROUP); - - // Make all the Particles - for (int i = 0; i < n; i++) { - Particle p = new Particle(); - particles.add(p); - // Each particle's PShape gets added to the System PShape - particleShape.addChild(p.getShape()); - } - } - - void update() { - for (Particle p : particles) { - p.update(); - } - } - - void setEmitter(float x, float y) { - for (Particle p : particles) { - // Each particle gets reborn at the emitter location - if (p.isDead()) { - p.rebirth(x, y); - } - } - } - - void display() { - shape(particleShape); - } -} - diff --git a/mode/examples/Topics/Create Shapes/ParticleSystemPShape/ParticleSystemPShape.pde b/mode/examples/Topics/Create Shapes/ParticleSystemPShape/ParticleSystemPShape.pde deleted file mode 100644 index a9a30d0f5..000000000 --- a/mode/examples/Topics/Create Shapes/ParticleSystemPShape/ParticleSystemPShape.pde +++ /dev/null @@ -1,42 +0,0 @@ -/** - * ParticleSystemPShape - * - * A particle system optimized for drawing using PShape - */ - -// Particle System object -ParticleSystem ps; -// A PImage for particle's texture -PImage sprite; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - // Load the image - sprite = loadImage("sprite.png"); - // A new particle system with 1,000 particles - ps = new ParticleSystem(1000); - - // Writing to the depth buffer is disabled to avoid rendering - // artifacts due to the fact that the particles are semi-transparent - // but not z-sorted. - hint(DISABLE_DEPTH_MASK); - -} - -void draw () { - background(0); - // Update and display system - ps.update(); - ps.display(); - - // Set the particle system's emitter location to the mouse - ps.setEmitter(mouseX,mouseY); - - // Display frame rate - fill(255); - textSize(16); - text("Frame rate: " + int(frameRate),10,20); - -} - diff --git a/mode/examples/Topics/Create Shapes/ParticleSystemPShape/data/sprite.png b/mode/examples/Topics/Create Shapes/ParticleSystemPShape/data/sprite.png deleted file mode 100644 index cc0f45cba..000000000 Binary files a/mode/examples/Topics/Create Shapes/ParticleSystemPShape/data/sprite.png and /dev/null differ diff --git a/mode/examples/Topics/Create Shapes/PathPShape/PathPShape.pde b/mode/examples/Topics/Create Shapes/PathPShape/PathPShape.pde deleted file mode 100644 index 7d650624e..000000000 --- a/mode/examples/Topics/Create Shapes/PathPShape/PathPShape.pde +++ /dev/null @@ -1,38 +0,0 @@ -/** - * PathPShape - * - * A simple path using PShape - */ - -// A PShape object -PShape path; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - // Create the shape - path = createShape(); - path.beginShape(); - // Set fill and stroke - path.noFill(); - path.stroke(255); - path.strokeWeight(2); - - float x = 0; - // Calculate the path as a sine wave - for (float a = 0; a < TWO_PI; a+=0.1) { - path.vertex(x,sin(a)*100); - x+= 5; - } - // The path is complete - path.endShape(); - -} - -void draw() { - background(51); - // Draw the path at the mouse location - translate(mouseX, mouseY); - shape(path); -} - diff --git a/mode/examples/Topics/Create Shapes/PolygonPShape/PolygonPShape.pde b/mode/examples/Topics/Create Shapes/PolygonPShape/PolygonPShape.pde deleted file mode 100644 index cb0b0aba2..000000000 --- a/mode/examples/Topics/Create Shapes/PolygonPShape/PolygonPShape.pde +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * PrimitivePShape. - * - * Using a PShape to display a custom polygon. - */ - -// The PShape object -PShape star; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - // First create the shape - star = createShape(); - star.beginShape(); - // You can set fill and stroke - star.fill(102); - star.stroke(255); - star.strokeWeight(2); - // Here, we are hardcoding a series of vertices - star.vertex(0, -50); - star.vertex(14, -20); - star.vertex(47, -15); - star.vertex(23, 7); - star.vertex(29, 40); - star.vertex(0, 25); - star.vertex(-29, 40); - star.vertex(-23, 7); - star.vertex(-47, -15); - star.vertex(-14, -20); - star.endShape(CLOSE); -} - -void draw() { - background(51); - // We can use translate to move the PShape - translate(mouseX, mouseY); - // Display the shape - shape(star); -} - diff --git a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP/PolygonPShapeOOP.pde b/mode/examples/Topics/Create Shapes/PolygonPShapeOOP/PolygonPShapeOOP.pde deleted file mode 100644 index 4f040adc2..000000000 --- a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP/PolygonPShapeOOP.pde +++ /dev/null @@ -1,30 +0,0 @@ -/** - * PolygonPShapeOOP. - * - * Wrapping a PShape inside a custom class - */ - - -// A Star object -Star s1, s2; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - // Make a new Star - s1 = new Star(); - s2 = new Star(); - -} - -void draw() { - background(51); - - s1.display(); // Display the first star - s1.move(); // Move the first star - - s2.display(); // Display the second star - s2.move(); // Move the second star - -} - diff --git a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP/Star.pde b/mode/examples/Topics/Create Shapes/PolygonPShapeOOP/Star.pde deleted file mode 100644 index d75d445eb..000000000 --- a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP/Star.pde +++ /dev/null @@ -1,52 +0,0 @@ -// A class to describe a Star shape - -class Star { - - // The PShape object - PShape s; - // The location where we will draw the shape - float x, y; - float speed; - - Star() { - x = random(100, width-100); - y = random(100, height-100); - speed = random(0.5, 3); - // First create the shape - s = createShape(); - s.beginShape(); - // You can set fill and stroke - s.fill(255, 204); - s.noStroke(); - // Here, we are hardcoding a series of vertices - s.vertex(0, -50); - s.vertex(14, -20); - s.vertex(47, -15); - s.vertex(23, 7); - s.vertex(29, 40); - s.vertex(0, 25); - s.vertex(-29, 40); - s.vertex(-23, 7); - s.vertex(-47, -15); - s.vertex(-14, -20); - // The shape is complete - s.endShape(CLOSE); - } - - void move() { - // Demonstrating some simple motion - x += speed; - if (x > width+100) { - x = -100; - } - } - - void display() { - // Locating and drawing the shape - pushMatrix(); - translate(x, y); - shape(s); - popMatrix(); - } -} - diff --git a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP2/Polygon.pde b/mode/examples/Topics/Create Shapes/PolygonPShapeOOP2/Polygon.pde deleted file mode 100644 index e775fb436..000000000 --- a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP2/Polygon.pde +++ /dev/null @@ -1,34 +0,0 @@ -// A class to describe a Polygon (with a PShape) - -class Polygon { - // The PShape object - PShape s; - // The location where we will draw the shape - float x, y; - // Variable for simple motion - float speed; - - Polygon(PShape s_) { - x = random(width); - y = random(-500, -100); - s = s_; - speed = random(2, 6); - } - - // Simple motion - void move() { - y+=speed; - if (y > height+100) { - y = -100; - } - } - - // Draw the object - void display() { - pushMatrix(); - translate(x, y); - shape(s); - popMatrix(); - } -} - diff --git a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP2/PolygonPShapeOOP2.pde b/mode/examples/Topics/Create Shapes/PolygonPShapeOOP2/PolygonPShapeOOP2.pde deleted file mode 100644 index b5223310f..000000000 --- a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP2/PolygonPShapeOOP2.pde +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PolygonPShapeOOP. - * - * Wrapping a PShape inside a custom class - * and demonstrating how we can have a multiple objects each - * using the same PShape. - */ - - -// A list of objects -ArrayList polygons; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - // Make a PShape - PShape star = createShape(); - star.beginShape(); - star.noStroke(); - star.fill(0, 127); - star.vertex(0, -50); - star.vertex(14, -20); - star.vertex(47, -15); - star.vertex(23, 7); - star.vertex(29, 40); - star.vertex(0, 25); - star.vertex(-29, 40); - star.vertex(-23, 7); - star.vertex(-47, -15); - star.vertex(-14, -20); - star.endShape(CLOSE); - - // Make an ArrayList - polygons = new ArrayList(); - - // Add a bunch of objects to the ArrayList - // Pass in reference to the PShape - // We coud make polygons with different PShapes - for (int i = 0; i < 25; i++) { - polygons.add(new Polygon(star)); - } -} - -void draw() { - background(255); - - // Display and move them all - for (Polygon poly : polygons) { - poly.display(); - poly.move(); - } -} - diff --git a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP3/Polygon.pde b/mode/examples/Topics/Create Shapes/PolygonPShapeOOP3/Polygon.pde deleted file mode 100644 index e775fb436..000000000 --- a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP3/Polygon.pde +++ /dev/null @@ -1,34 +0,0 @@ -// A class to describe a Polygon (with a PShape) - -class Polygon { - // The PShape object - PShape s; - // The location where we will draw the shape - float x, y; - // Variable for simple motion - float speed; - - Polygon(PShape s_) { - x = random(width); - y = random(-500, -100); - s = s_; - speed = random(2, 6); - } - - // Simple motion - void move() { - y+=speed; - if (y > height+100) { - y = -100; - } - } - - // Draw the object - void display() { - pushMatrix(); - translate(x, y); - shape(s); - popMatrix(); - } -} - diff --git a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP3/PolygonPShapeOOP3.pde b/mode/examples/Topics/Create Shapes/PolygonPShapeOOP3/PolygonPShapeOOP3.pde deleted file mode 100644 index 5ea6acec1..000000000 --- a/mode/examples/Topics/Create Shapes/PolygonPShapeOOP3/PolygonPShapeOOP3.pde +++ /dev/null @@ -1,63 +0,0 @@ -/** - * PolygonPShapeOOP. - * - * Wrapping a PShape inside a custom class - * and demonstrating how we can have a multiple objects each - * using the same PShape. - */ - - -// A list of objects -ArrayList polygons; - -// Three possible shapes -PShape[] shapes = new PShape[3]; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - - shapes[0] = createShape(ELLIPSE,0,0,100,100); - shapes[0].setFill(color(255, 127)); - shapes[0].setStroke(false); - shapes[1] = createShape(RECT,0,0,100,100); - shapes[1].setFill(color(255, 127)); - shapes[1].setStroke(false); - shapes[2] = createShape(); - shapes[2].beginShape(); - shapes[2].fill(0, 127); - shapes[2].noStroke(); - shapes[2].vertex(0, -50); - shapes[2].vertex(14, -20); - shapes[2].vertex(47, -15); - shapes[2].vertex(23, 7); - shapes[2].vertex(29, 40); - shapes[2].vertex(0, 25); - shapes[2].vertex(-29, 40); - shapes[2].vertex(-23, 7); - shapes[2].vertex(-47, -15); - shapes[2].vertex(-14, -20); - shapes[2].endShape(CLOSE); - - // Make an ArrayList - polygons = new ArrayList(); - - polygons = new ArrayList(); - - for (int i = 0; i < 25; i++) { - int selection = int(random(shapes.length)); // Pick a random index - Polygon p = new Polygon(shapes[selection]); // Use corresponding PShape to create Polygon - polygons.add(p); - } -} - -void draw() { - background(51); - - // Display and move them all - for (Polygon poly : polygons) { - poly.display(); - poly.move(); - } -} - diff --git a/mode/examples/Topics/Create Shapes/PrimitivePShape/PrimitivePShape.pde b/mode/examples/Topics/Create Shapes/PrimitivePShape/PrimitivePShape.pde deleted file mode 100644 index 0aa9f9610..000000000 --- a/mode/examples/Topics/Create Shapes/PrimitivePShape/PrimitivePShape.pde +++ /dev/null @@ -1,29 +0,0 @@ -/** - * PrimitivePShape. - * - * Using a PShape to display a primitive shape (in this case, ellipse). - */ - - -// The PShape object -PShape circle; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - // Creating the PShape as an ellipse - // The corner is -50,-50 so that the center is at 0,0 - circle = createShape(ELLIPSE, -50, -25, 100, 50); -} - -void draw() { - background(51); - // We can dynamically set the stroke and fill of the shape - circle.setStroke(color(255)); - circle.setStrokeWeight(4); - circle.setFill(color(map(mouseX, 0, width, 0, 255))); - // We can use translate to move the PShape - translate(mouseX, mouseY); - // Drawing the PShape - shape(circle); -} diff --git a/mode/examples/Topics/Create Shapes/WigglePShape/WigglePShape.pde b/mode/examples/Topics/Create Shapes/WigglePShape/WigglePShape.pde deleted file mode 100644 index 7a2cc9f47..000000000 --- a/mode/examples/Topics/Create Shapes/WigglePShape/WigglePShape.pde +++ /dev/null @@ -1,23 +0,0 @@ -/** - * WigglePShape. - * - * How to move the individual vertices of a PShape - */ - - -// A "Wiggler" object -Wiggler w; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - w = new Wiggler(); -} - -void draw() { - background(255); - w.display(); - w.wiggle(); -} - - diff --git a/mode/examples/Topics/Create Shapes/WigglePShape/Wiggler.pde b/mode/examples/Topics/Create Shapes/WigglePShape/Wiggler.pde deleted file mode 100644 index be4d7981f..000000000 --- a/mode/examples/Topics/Create Shapes/WigglePShape/Wiggler.pde +++ /dev/null @@ -1,67 +0,0 @@ -// An object that wraps the PShape - -class Wiggler { - - // The PShape to be "wiggled" - PShape s; - // Its location - float x, y; - - // For 2D Perlin noise - float yoff = 0; - - // We are using an ArrayList to keep a duplicate copy - // of vertices original locations. - ArrayList original; - - Wiggler() { - x = width/2; - y = height/2; - - // The "original" locations of the vertices make up a circle - original = new ArrayList(); - for (float a = 0; a < TWO_PI; a+=0.2) { - PVector v = PVector.fromAngle(a); - v.mult(100); - original.add(v); - } - - // Now make the PShape with those vertices - s = createShape(); - s.beginShape(); - s.fill(127); - s.stroke(0); - s.strokeWeight(2); - for (PVector v : original) { - s.vertex(v.x, v.y); - } - s.endShape(CLOSE); - } - - void wiggle() { - float xoff = 0; - // Apply an offset to each vertex - for (int i = 0; i < s.getVertexCount(); i++) { - // Calculate a new vertex location based on noise around "original" location - PVector pos = original.get(i); - float a = TWO_PI*noise(xoff,yoff); - PVector r = PVector.fromAngle(a); - r.mult(4); - r.add(pos); - // Set the location of each vertex to the new one - s.setVertex(i, r.x, r.y); - // increment perlin noise x value - xoff+= 0.5; - } - // Increment perlin noise y value - yoff += 0.02; - } - - void display() { - pushMatrix(); - translate(x, y); - shape(s); - popMatrix(); - } -} - diff --git a/mode/examples/Topics/Drawing/Animator/Animator.pde b/mode/examples/Topics/Drawing/Animator/Animator.pde deleted file mode 100644 index 883602eea..000000000 --- a/mode/examples/Topics/Drawing/Animator/Animator.pde +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Animator. - * - * Click and drag to draw and start the program. - * - * A simple animation tool that displays a continuous cycle of - * twenty-four images. Each image is displayed for 30 milliseconds - * to create animation. While each image is displayed, it’s possible - * to draw directly into it by pressing the mouse and moving the cursor. - * - */ - -int currentFrame = 0; -PImage[] frames = new PImage[24]; -int lastTime = 0; - -void setup() -{ - size(640, 200); - strokeWeight(12); - smooth(); - background(204); - for (int i = 0; i < frames.length; i++) { - frames[i] = get(); // Create a blank frame - } -} - -void draw() -{ - int currentTime = millis(); - if (currentTime > lastTime+30) { - nextFrame(); - lastTime = currentTime; - } - if (mousePressed == true) { - line(pmouseX, pmouseY, mouseX, mouseY); - } -} - -void nextFrame() -{ - frames[currentFrame] = get(); // Get the display window - currentFrame++; // Increment to next frame - if (currentFrame >= frames.length) { - currentFrame = 0; - } - image(frames[currentFrame], 0, 0); -} - diff --git a/mode/examples/Topics/Drawing/ContinuousLines/ContinuousLines.pde b/mode/examples/Topics/Drawing/ContinuousLines/ContinuousLines.pde deleted file mode 100644 index 9687331ba..000000000 --- a/mode/examples/Topics/Drawing/ContinuousLines/ContinuousLines.pde +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Continuous Lines. - * - * Click and drag the mouse to draw a line. - */ - -void setup() { - size(640, 200); - background(102); -} - -void draw() { - stroke(255); - if(mousePressed) { - line(mouseX, mouseY, pmouseX, pmouseY); - } -} diff --git a/mode/examples/Topics/Drawing/CustomTool/CustomTool.pde b/mode/examples/Topics/Drawing/CustomTool/CustomTool.pde deleted file mode 100644 index 96c3ec67c..000000000 --- a/mode/examples/Topics/Drawing/CustomTool/CustomTool.pde +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Custom Tool. - * - * Move the cursor across the screen to draw. - * In addition to creating software tools to simulate pens and pencils, - * it is possible to create unique tools to draw with. - */ - -int dots = 1000; -float[] dX = new float[dots]; -float[] dY = new float[dots]; - -float l_0 = 0.0; -float h_0 = 0.0; - -float legX = 0.0; -float legY = 0.0; -float thighX = 0.0; -float thighY = 0.0; - -float l = 60.0; // Length of the 'leg' -float h = 90.0; // Height of the 'leg' - -float nmx, nmy = 0.0; -float mx, my = 0.0; - -int currentValue = 0; -int valdir = 1; - -void setup() -{ - size(640, 360); - noStroke(); - smooth(); - background(102); -} - -void draw() -{ - // Smooth the mouse - nmx = mouseX; - nmy = mouseY; - if((abs(mx - nmx) > 1.0) || (abs(my - nmy) > 1.0)) { - mx = mx - (mx-nmx)/20.0; - my = my - (my-nmy)/20.0; - - // Set the drawing value - currentValue += 1* valdir; - if(currentValue > 255 || currentValue <= 0) { - valdir *= -1; - } - } - - iKinematics(); - kinematics(); - - pushMatrix(); - translate(width/2, height/2); - stroke(currentValue); - line(thighX, thighY, legX, legY); - popMatrix(); - - stroke(255); - point(legX + width/2, legY + height/2); -} - -void kinematics() -{ - thighX = h*cos(h_0); - thighY = h*sin(h_0); - legX = thighX + l*cos(h_0 - l_0); - legY = thighY + l*sin(h_0 - l_0); -} - -void iKinematics() -{ - float tx = mx - width/2.0; - float ty = my - height/2.0; - float c2 = (tx*tx + ty*ty - h*h - l*l)/(2*h*l); //in degrees - float s2 = sqrt(abs(1 - c2*c2)); // the sign here determines the bend in the joint - l_0 = -atan2(s2, c2); - h_0 = atan2(ty, tx) - atan2(l*s2, h+l*c2); -} - diff --git a/mode/examples/Topics/Drawing/CustomTool/data/milan.jpg b/mode/examples/Topics/Drawing/CustomTool/data/milan.jpg deleted file mode 100644 index 41aa2713d..000000000 Binary files a/mode/examples/Topics/Drawing/CustomTool/data/milan.jpg and /dev/null differ diff --git a/mode/examples/Topics/Drawing/CustomTool/data/paris.jpg b/mode/examples/Topics/Drawing/CustomTool/data/paris.jpg deleted file mode 100644 index a6d85ed57..000000000 Binary files a/mode/examples/Topics/Drawing/CustomTool/data/paris.jpg and /dev/null differ diff --git a/mode/examples/Topics/Drawing/Pattern/Pattern.pde b/mode/examples/Topics/Drawing/Pattern/Pattern.pde deleted file mode 100644 index 882b19d74..000000000 --- a/mode/examples/Topics/Drawing/Pattern/Pattern.pde +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Patterns. - * - * Move the cursor over the image to draw with a software tool - * which responds to the speed of the mouse. - */ - -void setup() -{ - size(640, 360); - background(102); - smooth(); -} - -void draw() -{ - // Call the variableEllipse() method and send it the - // parameters for the current mouse position - // and the previous mouse position - variableEllipse(mouseX, mouseY, pmouseX, pmouseY); -} - - -// The simple method variableEllipse() was created specifically -// for this program. It calculates the speed of the mouse -// and draws a small ellipse if the mouse is moving slowly -// and draws a large ellipse if the mouse is moving quickly - -void variableEllipse(int x, int y, int px, int py) -{ - float speed = abs(x-px) + abs(y-py); - stroke(speed); - ellipse(x, y, speed, speed); -} diff --git a/mode/examples/Topics/Drawing/Pulses/Pulses.pde b/mode/examples/Topics/Drawing/Pulses/Pulses.pde deleted file mode 100644 index c8b07ec52..000000000 --- a/mode/examples/Topics/Drawing/Pulses/Pulses.pde +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Pulses. - * - * Software drawing instruments can follow a rhythm or abide by rules independent - * of drawn gestures. This is a form of collaborative drawing in which the draftsperson - * controls some aspects of the image and the software controls others. - */ - -int angle = 0; - -void setup() { - size(640, 360); - background(102); - smooth(); - noStroke(); - fill(0, 102); -} - -void draw() { - // Draw only when mouse is pressed - if (mousePressed == true) { - angle += 10; - float val = cos(radians(angle)) * 6.0; - for (int a = 0; a < 360; a += 75) { - float xoff = cos(radians(a)) * val; - float yoff = sin(radians(a)) * val; - fill(0); - ellipse(mouseX + xoff, mouseY + yoff, val, val); - } - fill(255); - ellipse(mouseX, mouseY, 2, 2); - } -} diff --git a/mode/examples/Topics/Drawing/ScribblePlotter/ScribblePlotter.pde b/mode/examples/Topics/Drawing/ScribblePlotter/ScribblePlotter.pde deleted file mode 100644 index f5dcbf6ef..000000000 --- a/mode/examples/Topics/Drawing/ScribblePlotter/ScribblePlotter.pde +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Scribble Plotter - * by Ira Greenberg. - * - * Using 2-dimensional arrays, record end points - * and replot scribbles between points. - */ - -int SCRIBBLE = 0; -int HATCHING = 1; - -void setup(){ - size(640, 360); - background(0); - - // Create arrays to hold x, y coords - float[]x = new float[4]; - float[]y = new float[4]; - // create a convenient 2-dimensional - // array to hold x, y arrays - float[][]xy = {x, y}; - - // Record points - // X positions - xy[0][0] = 125; - xy[0][1] = 475; - xy[0][2] = 475; - xy[0][3] = 125; - - // Y positions - xy[1][0] = 100; - xy[1][1] = 100; - xy[1][2] = 260; - xy[1][3] = 260; - - // Call plotting function - makeRect(xy); -} - -void makeRect(float[][]pts){ - stroke(255); - smooth(); - - // Scribble variables, that get passed as arguments to the scribble function - int steps = 100; - float scribVal = 3.0; - for (int i = 0; i < pts[0].length; i++){ - // Plots vertices - strokeWeight(5); - point(pts[0][i], pts[1][i]); - - // Call scribble function - strokeWeight(.5); - if (i > 0){ - scribble(pts[0][i], pts[1][i], pts[0][i-1], pts[1][i-1], steps, scribVal, SCRIBBLE); - } - if (i == pts[0].length-1){ - // Show some hatching between last 2 points - scribble(pts[0][i], pts[1][i], pts[0][0], pts[1][0], steps, scribVal*2, HATCHING); - } - } -} - -/* - Scribble function plots lines between end points, - determined by steps and scribVal arguments. - two styles are available: SCRIBBLE and HATCHING, which - are interestingly only dependent on parentheses - placement in the line() function calls. -*/ - -void scribble(float x1, float y1, float x2, float y2, int steps, float scribVal, int style){ - - float xStep = (x2-x1)/steps; - float yStep = (y2-y1)/steps; - for (int i = 0; i < steps; i++){ - if(style == SCRIBBLE){ - if (i < steps-1){ - line(x1, y1, x1+=xStep+random(-scribVal, scribVal), y1+=yStep+random(-scribVal, scribVal)); - } - else { - // extra line needed to attach line back to point- not necessary in HATCHING style - line(x1, y1, x2, y2); - } - } - else if (style == HATCHING){ - line(x1, y1, (x1+=xStep)+random(-scribVal, scribVal), (y1+=yStep)+random(-scribVal, scribVal)); - } - } -} - diff --git a/mode/examples/Topics/Effects/FireCube/FireCube.pde b/mode/examples/Topics/Effects/FireCube/FireCube.pde deleted file mode 100644 index 2565eb3bc..000000000 --- a/mode/examples/Topics/Effects/FireCube/FireCube.pde +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Fire Cube demo effect - * by luis2048. - * - * A rotating wireframe cube with flames rising up the screen. - * The fire effect has been used quite often for oldskool demos. - * First you create a palette of 256 colors ranging from red to - * yellow (including black). For every frame, calculate each row - * of pixels based on the two rows below it: The value of each pixel, - * becomes the sum of the 3 pixels below it (one directly below, one - * to the left, and one to the right), and one pixel directly two - * rows below it. Then divide the sum so that the fire dies out as - * it rises. - */ - -// This will contain the pixels used to calculate the fire effect -int[][] fire; - -// Flame colors -color[] palette; -float angle; -int[] calc1,calc2,calc3,calc4,calc5; - -PGraphics pg; - -void setup(){ - size(640, 360, P2D); - - // Create buffered image for 3d cube - pg = createGraphics(width, height, P3D); - pg.loadPixels(); - - calc1 = new int[width]; - calc3 = new int[width]; - calc4 = new int[width]; - calc2 = new int[height]; - calc5 = new int[height]; - - colorMode(HSB); - - fire = new int[width][height]; - palette = new color[255]; - - // Generate the palette - for(int x = 0; x < palette.length; x++) { - //Hue goes from 0 to 85: red to yellow - //Saturation is always the maximum: 255 - //Lightness is 0..255 for x=0..128, and 255 for x=128..255 - palette[x] = color(x/3, 255, constrain(x*3, 0, 255)); - } - - // Precalculate which pixel values to add during animation loop - // this speeds up the effect by 10fps - for (int x = 0; x < width; x++) { - calc1[x] = x % width; - calc3[x] = (x - 1 + width) % width; - calc4[x] = (x + 1) % width; - } - - for(int y = 0; y < height; y++) { - calc2[y] = (y + 1) % height; - calc5[y] = (y + 2) % height; - } -} - -void draw() { - angle = angle + 0.05; - - // Rotating wireframe cube - pg.beginDraw(); - pg.translate(width >> 1, height >> 1); - pg.rotateX(sin(angle/2)); - pg.rotateY(cos(angle/2)); - pg.background(0); - pg.stroke(128); - pg.scale(25); - pg.noFill(); - pg.box(4); - pg.endDraw(); - - // Randomize the bottom row of the fire buffer - for(int x = 0; x < width; x++) - { - fire[x][height-1] = int(random(0,190)) ; - } - - loadPixels(); - - int counter = 0; - // Do the fire calculations for every pixel, from top to bottom - for (int y = 0; y < height; y++) { - for(int x = 0; x < width; x++) { - // Add pixel values around current pixel - - fire[x][y] = - ((fire[calc3[x]][calc2[y]] - + fire[calc1[x]][calc2[y]] - + fire[calc4[x]][calc2[y]] - + fire[calc1[x]][calc5[y]]) << 5) / 129; - - // Output everything to screen using our palette colors - pixels[counter] = palette[fire[x][y]]; - - // Extract the red value using right shift and bit mask - // equivalent of red(pg.pixels[x+y*w]) - if ((pg.pixels[counter++] >> 16 & 0xFF) == 128) { - // Only map 3D cube 'lit' pixels onto fire array needed for next frame - fire[x][y] = 128; - } - } - } - updatePixels(); -} diff --git a/mode/examples/Topics/Effects/Lens/Lens.pde b/mode/examples/Topics/Effects/Lens/Lens.pde deleted file mode 100644 index b9b63287b..000000000 --- a/mode/examples/Topics/Effects/Lens/Lens.pde +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Lens Demo Effect - * by luis2048. - * - * A picture is shown and it looks like a magnifying glass - * is drawn over the picture. One of the most famous demos - * that has a lens effect is 2nd reality by future crew. - * The trick is to precalculate the entire effect. Just make - * an array that for each pixel in the destination picture - * tells which pixel to take from the source picture. This - * array is called the transformation array. The tricky part - * is to calculate the transformation array to make the - * destination look like a lens is beeing held over the source - * picture. Based on lens formula by on Abe Racadabra. - */ - -int lensD = 256; // Lens diameter -int[] lensArray = new int[lensD*lensD]; // Height and width of lens - -PGraphics lensEffect; -PImage lensImage; -PImage lensImage2; - -int xx = 0; -int yy = 0; -int dx = 1; -int dy = 1; - -void setup() { - - size(640, 360, P2D); - - // Create buffered image for lens effect - lensEffect = createGraphics(width, height, P2D); - - // Load background image - lensEffect.beginDraw(); - lensEffect.image(loadImage("red_smoke.jpg"), 0, 0, - lensEffect.width, lensEffect.height); - lensEffect.endDraw(); - - // Create buffered image for image to warp - lensImage = createGraphics(lensD, lensD, P2D); - lensImage2 = createGraphics(lensD, lensD, P2D); - - // Lens algorithm (transformation array) - int magFactor = 40; // Magnification factor - int m, a, b; - - int r = lensD / 2; - float s = sqrt(r*r - magFactor*magFactor); - - for (int y = -r; y < r; y++) { - for (int x = -r ;x < r; x++) { - if(x*x + y*y >= s*s) { - a = x; - b = y; - } - else { - float z = sqrt(r*r - x*x - y*y); - a = int(x * magFactor / z + 0.5); - b = int(y * magFactor / z + 0.5); - } - lensArray[(y + r)*lensD + (x + r)] = (b + r) * lensD + (a + r); - } - } -} - -void draw() { - - // Bounce lens around the screen - if((xx+dx+lensD > lensEffect.width) || (xx+dx < 0)) { - dx =- dx; - } - if((yy+dy+lensD > lensEffect.height) || (yy+dy < 0)) { - dy =- dy; - } - xx += dx; - yy += dy; - - // save the backgrounlensD of lensHeight*lensWilensDth pixels rectangle at the coorlensDinates - // where the lens effect will be applielensD. - lensImage2.copy(lensEffect, xx, yy, lensD, lensD, 0, 0, lensD, lensD); - - // output into a bufferelensD image for reuse - lensImage.loadPixels(); - lensImage2.loadPixels(); - - // For each pixel in the destination rectangle, apply the color - // from the appropriate pixel in the saved background. The lensArray - // array tells the offset into the saved background. - for (int i = 0; i < lensImage.pixels.length; i++) { - lensImage.pixels[i] = lensImage2.pixels[lensArray[i]]; - } - lensImage.updatePixels(); - - // Restore the original picture - image(lensEffect, 0, 0, width, height); - - // Overlay the lens square - image(lensImage, xx, yy, lensD, lensD); - -} - diff --git a/mode/examples/Topics/Effects/Lens/data/red_smoke.jpg b/mode/examples/Topics/Effects/Lens/data/red_smoke.jpg deleted file mode 100644 index 9897b595a..000000000 Binary files a/mode/examples/Topics/Effects/Lens/data/red_smoke.jpg and /dev/null differ diff --git a/mode/examples/Topics/Effects/Metaball/Metaball.pde b/mode/examples/Topics/Effects/Metaball/Metaball.pde deleted file mode 100644 index bf21121f1..000000000 --- a/mode/examples/Topics/Effects/Metaball/Metaball.pde +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Metaball Demo Effect - * by luis2048. - * - * Organic-looking n-dimensional objects. The technique for rendering - * metaballs was invented by Jim Blinn in the early 1980s. Each metaball - * is defined as a function in n-dimensions. - */ - -int numBlobs = 3; - -int[] blogPx = { 0, 90, 90 }; -int[] blogPy = { 0, 120, 45 }; - -// Movement vector for each blob -int[] blogDx = { 1, 1, 1 }; -int[] blogDy = { 1, 1, 1 }; - -PGraphics pg; -int[][] vy,vx; - -void setup() { - size(640, 360, P2D); - pg = createGraphics(160, 90, P2D); - vy = new int[numBlobs][pg.height]; - vx = new int[numBlobs][pg.width]; -} - -void draw() { - for (int i=0; i pg.width) { - blogDx[i] = -1; - } - if (blogPy[i] < 0) { - blogDy[i] = 1; - } - if (blogPy[i] > pg.height) { - blogDy[i]=-1; - } - - for (int x = 0; x < pg.width; x++) { - vx[i][x] = int(sq(blogPx[i]-x)); - } - - for (int y = 0; y < pg.height; y++) { - vy[i][y] = int(sq(blogPy[i]-y)); - } - } - - // Output into a buffered image for reuse - pg.beginDraw(); - pg.loadPixels(); - for (int y = 0; y < pg.height; y++) { - for (int x = 0; x < pg.width; x++) { - int m = 1; - for (int i = 0; i < numBlobs; i++) { - // Increase this number to make your blobs bigger - m += 60000/(vy[i][y] + vx[i][x]+1); - } - pg.pixels[x+y*pg.width] = color(0, m+x, (x+m+y)/2); - } - } - pg.updatePixels(); - pg.endDraw(); - - // Display the results - image(pg, 0, 0, width, height); -} - diff --git a/mode/examples/Topics/Effects/Plasma/Plasma.pde b/mode/examples/Topics/Effects/Plasma/Plasma.pde deleted file mode 100644 index 17162ba8c..000000000 --- a/mode/examples/Topics/Effects/Plasma/Plasma.pde +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Plasma Demo Effect - * by luis2048. - * - * Cycles of changing colours warped to give an illusion - * of liquid, organic movement.Colors are the sum of sine - * functions and various formulas. Based on formula by Robert Klep. - */ - -int pixelSize=2; -PGraphics pg; - -void setup(){ - size(640, 360, P2D); - // Create buffered image for plasma effect - pg = createGraphics(160, 90, P2D); - colorMode(HSB); - noSmooth(); -} - -void draw() -{ - float xc = 25; - - // Enable this to control the speed of animation regardless of CPU power - // int timeDisplacement = millis()/30; - - // This runs plasma as fast as your computer can handle - int timeDisplacement = frameCount; - - // No need to do this math for every pixel - float calculation1 = sin( radians(timeDisplacement * 0.61655617)); - float calculation2 = sin( radians(timeDisplacement * -3.6352262)); - - // Output into a buffered image for reuse - pg.beginDraw(); - pg.loadPixels(); - - // Plasma algorithm - for (int x = 0; x < pg.width; x++, xc += pixelSize) - { - float yc = 25; - float s1 = 128 + 128 * sin(radians(xc) * calculation1 ); - - for (int y = 0; y < pg.height; y++, yc += pixelSize) - { - float s2 = 128 + 128 * sin(radians(yc) * calculation2 ); - float s3 = 128 + 128 * sin(radians((xc + yc + timeDisplacement * 5) / 2)); - float s = (s1+ s2 + s3) / 3; - pg.pixels[x+y*pg.width] = color(s, 255 - s / 2.0, 255); - } - } - pg.updatePixels(); - pg.endDraw(); - - // display the results - image(pg,0,0,width,height); - -} - diff --git a/mode/examples/Topics/Effects/Tunnel/Tunnel.pde b/mode/examples/Topics/Effects/Tunnel/Tunnel.pde deleted file mode 100644 index c80eda08f..000000000 --- a/mode/examples/Topics/Effects/Tunnel/Tunnel.pde +++ /dev/null @@ -1,114 +0,0 @@ -/** - * Tunnel Demo Effect - * by luis2048. - * - * This effect shows a tunnel in which you fly while the tunnel - * rotates, seemingly in 3D. The animation of the tunnel actually - * isn't calculated on the fly while the animation runs, but is - * precalculated. These calculations are stored in two tables: - * one for the angle and one for the distance. For every frame, - * go through every pixel (x,y) and use the angle and distance - * tables to get which pixel of the texture it should draw at the - * current pixel. To look like its rotating and zooming, the values - * of the angle and distance tables are shifted. - */ - -int x, y, radius, l; -PGraphics tunnelEffect; -PImage textureImg; - -// build lookup table -int[][] distanceTable; -int[][] angleTable; -int[][] shadeTable; -int w, h; - -void setup() { - size(640, 360, P2D); - - // Load texture 512 x 512 - textureImg = loadImage("red_smoke.jpg"); - textureImg.loadPixels(); - - // Create buffer screen - tunnelEffect = createGraphics(320, 200, P2D); - w = tunnelEffect.width; - h = tunnelEffect.height; - - float ratio = 32.0; - int angle; - int depth; - int shade = 0; - - // Make the tables twice as big as the screen. - // The center of the buffers is now the position (w,h). - distanceTable= new int[2 * w][2 * h]; - angleTable= new int[2 * w][2 * h]; - - for (int x = 0; x < w*2; x++) - { - for (int y = 0; y < h*2; y++) - { - depth = int(ratio * textureImg.height - / sqrt(float((x - w) * (x - w) + (y - h) * (y - h)))) ; - angle = int(0.5 * textureImg.width * atan2(float(y - h), - float(x - w)) / PI) ; - - // The distance table contains for every pixel of the - // screen, the inverse of the distance to the center of - // the screen this pixel has. - distanceTable[x][y] = depth ; - - // The angle table contains the angle of every pixel of the screen, - // where the center of the screen represents the origin. - angleTable[x][y] = angle ; - } - } -} - - -void draw() { - - tunnelEffect.beginDraw(); - tunnelEffect.loadPixels(); - - float timeDisplacement = millis() / 1000.0; - - // Calculate the shift values out of the time value - int shiftX = int(textureImg.width * .2 * timeDisplacement+300); // speed of zoom - int shiftY = int(textureImg.height * .15 * timeDisplacement+300); //speed of spin - - // Calculate the look values out of the time value - // by using sine functions, it'll alternate between - // looking left/right and up/down - int shiftLookX = w / 2 + int(w / 4 * sin(timeDisplacement)); - int shiftLookY = h / 2 + int(h / 4 * sin(timeDisplacement * 1.5)); - - for (int y = 0; y < h; y++) { - for (int x = 0; x < w; x++) { - - // Make sure that x + shiftLookX never goes outside - // the dimensions of the table - int texture_x = constrain((distanceTable[x + shiftLookX][y + shiftLookY] - + shiftX) % textureImg.width ,0, textureImg.width); - - int texture_y = (angleTable[x + shiftLookX][y + shiftLookY] - + shiftY) % textureImg.height; - - tunnelEffect.pixels[x+y*w] = textureImg.pixels[texture_y - * textureImg.width + texture_x]; - - // Test lookuptables - // tunnelEffect.pixels[x+y*w] = color( 0,texture_x,texture_y); - } - } - - tunnelEffect.updatePixels(); - tunnelEffect.endDraw(); - - // Display the results - image(tunnelEffect, 0, 0, width, height); - -} - - diff --git a/mode/examples/Topics/Effects/Tunnel/data/red_smoke.jpg b/mode/examples/Topics/Effects/Tunnel/data/red_smoke.jpg deleted file mode 100644 index 9897b595a..000000000 Binary files a/mode/examples/Topics/Effects/Tunnel/data/red_smoke.jpg and /dev/null differ diff --git a/mode/examples/Topics/Effects/UnlimitedSprites/UnlimitedSprites.pde b/mode/examples/Topics/Effects/UnlimitedSprites/UnlimitedSprites.pde deleted file mode 100644 index e027e1e99..000000000 --- a/mode/examples/Topics/Effects/UnlimitedSprites/UnlimitedSprites.pde +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Unlimited Sprites Demo Effect - * by luis2048. - * - * An infinate number of sprites drawn to screen. It's basically - * a flick-book effect; you draw the same sprite in different - * positions on different bufffer 'screens' and flip between them. - * When you've drawn on all frames, you loop back to the beginning - * and repeat. - */ - -PGraphics[] spriteFrames = new PGraphics[6]; -PImage sprite; - -float x, y; -float xang = 0.0; -float yang = 0.0; -int surf = 0; - -void setup() { - size(640, 360); - noSmooth(); - background(0); - - // Create sprite - sprite=loadImage("Aqua-Ball-48x48.png"); - - // Create blank surfaces to draw on - for (int i = 0; i < spriteFrames.length; i++) { - spriteFrames[i] = createGraphics(width, height); - } -} - -void draw() -{ - background(0); - - // Get X, Y positions - x = (width/2)*sin((radians(xang))*0.95); - y = (height/2)*cos((radians(yang))*0.97); - - // Inc the angle of the sine - xang += 1.17; - yang += 1.39; - - // Blit our 'bob' on the 'active' surface - spriteFrames[surf].beginDraw(); - spriteFrames[surf].image(sprite, x+(width/2)-32, y+(height/2)-32); - spriteFrames[surf].endDraw(); - - // Blit the active surface to the screen - image(spriteFrames[surf], 0, 0, width, height); - - // Inc the active surface number - surf = (surf+1) % spriteFrames.length; - - // Display the results - //image(spriteEffect, 0, 0, width, height); -} - diff --git a/mode/examples/Topics/Effects/UnlimitedSprites/data/Aqua-Ball-48x48.png b/mode/examples/Topics/Effects/UnlimitedSprites/data/Aqua-Ball-48x48.png deleted file mode 100644 index f5c6a44d6..000000000 Binary files a/mode/examples/Topics/Effects/UnlimitedSprites/data/Aqua-Ball-48x48.png and /dev/null differ diff --git a/mode/examples/Topics/Effects/Wormhole/Wormhole.pde b/mode/examples/Topics/Effects/Wormhole/Wormhole.pde deleted file mode 100644 index 9f2f8fed8..000000000 --- a/mode/examples/Topics/Effects/Wormhole/Wormhole.pde +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Wormhole Demo Effect - * by luis2048. - * - * A funnel-shaped hole sucking its texture to the middle. - * The effect is accomplished like the tunnel effect but with - * a 15 x 15 texture and static lookup table. The texture is shifted - * and mapped to the static lookup table. - */ - -PImage wormImg, wormTexture; -int[] reg = new int[15]; - -void setup() { - size(640, 360, P2D); - noSmooth(); - - // Reference image used to transpose texture - wormImg = loadImage("wormhole.png"); - wormImg.resize(width, height); - wormImg.loadPixels(); - - // Texture image array - wormTexture = loadImage("texture.gif"); - wormTexture.loadPixels(); -} - -// Moves the bottom row of pixels to the top and shifting remaining pixels 1 over -void shiftup() { - for (int k = 0; k < 15; k++) { - reg[k] = wormTexture.pixels[k]; - } - - for (int k = 15; k < 225; k++) { - wormTexture.pixels[k-15] = wormTexture.pixels[k]; - } - for (int k = 0; k < 15; k++) { - wormTexture.pixels[k+210] = reg[k]; - } -} - -// Moves left column of pixels to the right and shifting remaining pixels 1 over -void shiftright() { - for(int k = 0; k < 15; k++) { - reg[k] = wormTexture.pixels[15*k+14]; - for(int i = 14;i > 0; i--) { - wormTexture.pixels[15*k+i] = wormTexture.pixels[15*k+(i-1)]; - } - wormTexture.pixels[15*k] = reg[k]; - } -} - -void draw() { - // Load pixel data array - loadPixels(); - - // Loop through all pixels - for (int i = 0; i < pixels.length; i++){ - // Map texture to wormhole in a bit shift blue - pixels[i] = wormTexture.pixels[constrain(wormImg.pixels[i] & 0xFF, 0, 224)]; - } - - updatePixels(); - - shiftright(); - shiftup(); -} - - - diff --git a/mode/examples/Topics/Effects/Wormhole/data/texture.gif b/mode/examples/Topics/Effects/Wormhole/data/texture.gif deleted file mode 100644 index 37b7eb033..000000000 Binary files a/mode/examples/Topics/Effects/Wormhole/data/texture.gif and /dev/null differ diff --git a/mode/examples/Topics/Effects/Wormhole/data/wormhole.png b/mode/examples/Topics/Effects/Wormhole/data/wormhole.png deleted file mode 100644 index e9f78ac3a..000000000 Binary files a/mode/examples/Topics/Effects/Wormhole/data/wormhole.png and /dev/null differ diff --git a/mode/examples/Topics/File IO/LoadFile1/LoadFile1.pde b/mode/examples/Topics/File IO/LoadFile1/LoadFile1.pde deleted file mode 100644 index ac42a81c6..000000000 --- a/mode/examples/Topics/File IO/LoadFile1/LoadFile1.pde +++ /dev/null @@ -1,30 +0,0 @@ -/** - * LoadFile 1 - * - * Loads a text file that contains two numbers separated by a tab ('\t'). - * A new pair of numbers is loaded each frame and used to draw a point on the screen. - */ - -String[] lines; -int index = 0; - -void setup() { - size(200, 200); - background(0); - stroke(255); - frameRate(12); - lines = loadStrings("positions.txt"); -} - -void draw() { - if (index < lines.length) { - String[] pieces = split(lines[index], '\t'); - if (pieces.length == 2) { - int x = int(pieces[0]) * 2; - int y = int(pieces[1]) * 2; - point(x, y); - } - // Go to the next line for the next run through draw() - index = index + 1; - } -} diff --git a/mode/examples/Topics/File IO/LoadFile1/data/positions.txt b/mode/examples/Topics/File IO/LoadFile1/data/positions.txt deleted file mode 100644 index 3b8ff2e23..000000000 --- a/mode/examples/Topics/File IO/LoadFile1/data/positions.txt +++ /dev/null @@ -1,206 +0,0 @@ -70 35 -69 35 -68 39 -67 42 -66 47 -64 51 -64 54 -63 57 -60 60 -58 64 -51 69 -48 72 -44 73 -39 75 -35 75 -30 75 -25 75 -21 75 -17 73 -13 69 -12 66 -11 61 -11 57 -10 49 -10 45 -10 38 -12 32 -13 29 -16 23 -20 19 -24 16 -27 15 -31 13 -33 13 -37 13 -40 15 -42 16 -45 19 -46 21 -47 24 -48 26 -48 29 -48 33 -47 39 -43 45 -42 47 -38 50 -35 51 -32 51 -30 51 -27 50 -27 50 -26 46 -26 41 -29 36 -30 34 -31 33 -31 33 -32 33 -33 33 -34 33 -34 33 -35 33 -37 33 -39 33 -42 32 -44 31 -46 29 -48 29 -49 27 -52 24 -53 23 -57 19 -61 16 -63 14 -67 13 -69 12 -69 12 -77 11 -77 11 -80 11 -86 16 -90 21 -93 25 -95 29 -95 32 -95 33 -95 37 -94 41 -93 44 -92 46 -91 49 -89 51 -87 55 -85 59 -82 62 -80 64 -79 67 -77 69 -74 71 -68 72 -65 73 -63 73 -62 73 -60 72 -58 69 -57 67 -57 66 -56 60 -56 56 -56 54 -58 49 -60 47 -62 47 -63 47 -67 48 -70 52 -73 55 -74 57 -74 58 -74 60 -74 62 -73 65 -70 68 -67 69 -65 70 -63 70 -62 70 -60 68 -57 65 -55 64 -50 62 -46 61 -40 60 -38 60 -36 60 -32 61 -30 62 -27 64 -26 68 -25 71 -25 77 -25 81 -26 84 -28 86 -31 87 -33 88 -36 88 -39 86 -41 85 -43 83 -44 81 -45 76 -45 74 -45 71 -40 67 -37 65 -34 63 -33 61 -33 61 -32 60 -33 49 -37 45 -41 41 -45 39 -47 38 -51 37 -54 37 -58 38 -61 41 -63 44 -65 46 -66 49 -66 51 -67 55 -67 58 -67 60 -66 62 -64 65 -63 66 -61 67 -60 68 -58 68 -55 69 -54 69 -51 69 -48 69 -46 68 -45 66 -44 65 -44 63 -44 61 -44 59 -44 56 -44 55 -45 53 -47 52 -49 50 -50 48 -51 47 -52 46 -54 46 -55 45 -55 45 -56 44 -57 44 diff --git a/mode/examples/Topics/File IO/LoadFile2/LoadFile2.pde b/mode/examples/Topics/File IO/LoadFile2/LoadFile2.pde deleted file mode 100644 index 356d8354f..000000000 --- a/mode/examples/Topics/File IO/LoadFile2/LoadFile2.pde +++ /dev/null @@ -1,55 +0,0 @@ -/** - * LoadFile 2 - * - * This example loads a data file about cars. Each element is separated - * with a tab and corresponds to a different aspect of each car. The file stores - * the miles per gallon, cylinders, displacement, etc., for more than 400 different - * makes and models. Press a mouse button to advance to the next group of entries. - */ - -Record[] records; -String[] lines; -int recordCount; -PFont body; -int num = 9; // Display this many entries on each screen. -int startingEntry = 0; // Display from this entry number - -void setup() { - size(200, 200); - fill(255); - noLoop(); - - body = loadFont("TheSans-Plain-12.vlw"); - textFont(body); - - lines = loadStrings("cars2.tsv"); - records = new Record[lines.length]; - for (int i = 0; i < lines.length; i++) { - String[] pieces = split(lines[i], TAB); // Load data into array - if (pieces.length == 9) { - records[recordCount] = new Record(pieces); - recordCount++; - } - } - if (recordCount != records.length) { - records = (Record[]) subset(records, 0, recordCount); - } -} - -void draw() { - background(0); - for (int i = 0; i < num; i++) { - int thisEntry = startingEntry + i; - if (thisEntry < recordCount) { - text(thisEntry + " > " + records[thisEntry].name, 20, 20 + i*20); - } - } -} - -void mousePressed() { - startingEntry += num; - if (startingEntry > records.length) { - startingEntry = 0; // go back to the beginning - } - redraw(); -} diff --git a/mode/examples/Topics/File IO/LoadFile2/Record.pde b/mode/examples/Topics/File IO/LoadFile2/Record.pde deleted file mode 100644 index 2cc836abc..000000000 --- a/mode/examples/Topics/File IO/LoadFile2/Record.pde +++ /dev/null @@ -1,23 +0,0 @@ -class Record { - String name; - float mpg; - int cylinders; - float displacement; - float horsepower; - float weight; - float acceleration; - int year; - float origin; - - public Record(String[] pieces) { - name = pieces[0]; - mpg = float(pieces[1]); - cylinders = int(pieces[2]); - displacement = float(pieces[3]); - horsepower = float(pieces[4]); - weight = float(pieces[5]); - acceleration = float(pieces[6]); - year = int(pieces[7]); - origin = float(pieces[8]); - } -} diff --git a/mode/examples/Topics/File IO/LoadFile2/data/TheSans-Plain-12.vlw b/mode/examples/Topics/File IO/LoadFile2/data/TheSans-Plain-12.vlw deleted file mode 100644 index 4fcefba6b..000000000 Binary files a/mode/examples/Topics/File IO/LoadFile2/data/TheSans-Plain-12.vlw and /dev/null differ diff --git a/mode/examples/Topics/File IO/LoadFile2/data/cars2.tsv b/mode/examples/Topics/File IO/LoadFile2/data/cars2.tsv deleted file mode 100644 index 7f658bf20..000000000 --- a/mode/examples/Topics/File IO/LoadFile2/data/cars2.tsv +++ /dev/null @@ -1,406 +0,0 @@ -chevrolet chevelle malibu 18 8 307 130 3504 12 70 1 -buick skylark 320 15 8 350 165 3693 11.5 70 1 -plymouth satellite 18 8 318 150 3436 11 70 1 -amc rebel sst 16 8 304 150 3433 12 70 1 -ford torino 17 8 302 140 3449 10.5 70 1 -ford galaxie 500 15 8 429 198 4341 10 70 1 -chevrolet impala 14 8 454 220 4354 9 70 1 -plymouth fury iii 14 8 440 215 4312 8.5 70 1 -pontiac catalina 14 8 455 225 4425 10 70 1 -amc ambassador dpl 15 8 390 190 3850 8.5 70 1 -citroen ds-21 pallas NA 4 133 115 3090 17.5 70 2 -chevrolet chevelle concours (sw) NA 8 350 165 4142 11.5 70 1 -ford torino (sw) NA 8 351 153 4034 11 70 1 -plymouth satellite (sw) NA 8 383 175 4166 10.5 70 1 -amc rebel sst (sw) NA 8 360 175 3850 11 70 1 -dodge challenger se 15 8 383 170 3563 10 70 1 -plymouth 'cuda 340 14 8 340 160 3609 8 70 1 -ford mustang boss 302 NA 8 302 140 3353 8 70 1 -chevrolet monte carlo 15 8 400 150 3761 9.5 70 1 -buick estate wagon (sw) 14 8 455 225 3086 10 70 1 -toyota corona mark ii 24 4 113 95 2372 15 70 3 -plymouth duster 22 6 198 95 2833 15.5 70 1 -amc hornet 18 6 199 97 2774 15.5 70 1 -ford maverick 21 6 200 85 2587 16 70 1 -datsun pl510 27 4 97 88 2130 14.5 70 3 -volkswagen 1131 deluxe sedan 26 4 97 46 1835 20.5 70 2 -peugeot 504 25 4 110 87 2672 17.5 70 2 -audi 100 ls 24 4 107 90 2430 14.5 70 2 -saab 99e 25 4 104 95 2375 17.5 70 2 -bmw 2002 26 4 121 113 2234 12.5 70 2 -amc gremlin 21 6 199 90 2648 15 70 1 -ford f250 10 8 360 215 4615 14 70 1 -chevy c20 10 8 307 200 4376 15 70 1 -dodge d200 11 8 318 210 4382 13.5 70 1 -hi 1200d 9 8 304 193 4732 18.5 70 1 -datsun pl510 27 4 97 88 2130 14.5 71 3 -chevrolet vega 2300 28 4 140 90 2264 15.5 71 1 -toyota corona 25 4 113 95 2228 14 71 3 -ford pinto 25 4 98 NA 2046 19 71 1 -volkswagen super beetle 117 NA 4 97 48 1978 20 71 2 -amc gremlin 19 6 232 100 2634 13 71 1 -plymouth satellite custom 16 6 225 105 3439 15.5 71 1 -chevrolet chevelle malibu 17 6 250 100 3329 15.5 71 1 -ford torino 500 19 6 250 88 3302 15.5 71 1 -amc matador 18 6 232 100 3288 15.5 71 1 -chevrolet impala 14 8 350 165 4209 12 71 1 -pontiac catalina brougham 14 8 400 175 4464 11.5 71 1 -ford galaxie 500 14 8 351 153 4154 13.5 71 1 -plymouth fury iii 14 8 318 150 4096 13 71 1 -dodge monaco (sw) 12 8 383 180 4955 11.5 71 1 -ford country squire (sw) 13 8 400 170 4746 12 71 1 -pontiac safari (sw) 13 8 400 175 5140 12 71 1 -amc hornet sportabout (sw) 18 6 258 110 2962 13.5 71 1 -chevrolet vega (sw) 22 4 140 72 2408 19 71 1 -pontiac firebird 19 6 250 100 3282 15 71 1 -ford mustang 18 6 250 88 3139 14.5 71 1 -mercury capri 2000 23 4 122 86 2220 14 71 1 -opel 1900 28 4 116 90 2123 14 71 2 -peugeot 304 30 4 79 70 2074 19.5 71 2 -fiat 124b 30 4 88 76 2065 14.5 71 2 -toyota corolla 1200 31 4 71 65 1773 19 71 3 -datsun 1200 35 4 72 69 1613 18 71 3 -volkswagen model 111 27 4 97 60 1834 19 71 2 -plymouth cricket 26 4 91 70 1955 20.5 71 1 -toyota corona hardtop 24 4 113 95 2278 15.5 72 3 -dodge colt hardtop 25 4 97.5 80 2126 17 72 1 -volkswagen type 3 23 4 97 54 2254 23.5 72 2 -chevrolet vega 20 4 140 90 2408 19.5 72 1 -ford pinto runabout 21 4 122 86 2226 16.5 72 1 -chevrolet impala 13 8 350 165 4274 12 72 1 -pontiac catalina 14 8 400 175 4385 12 72 1 -plymouth fury iii 15 8 318 150 4135 13.5 72 1 -ford galaxie 500 14 8 351 153 4129 13 72 1 -amc ambassador sst 17 8 304 150 3672 11.5 72 1 -mercury marquis 11 8 429 208 4633 11 72 1 -buick lesabre custom 13 8 350 155 4502 13.5 72 1 -oldsmobile delta 88 royale 12 8 350 160 4456 13.5 72 1 -chrysler newport royal 13 8 400 190 4422 12.5 72 1 -mazda rx2 coupe 19 3 70 97 2330 13.5 72 3 -amc matador (sw) 15 8 304 150 3892 12.5 72 1 -chevrolet chevelle concours (sw) 13 8 307 130 4098 14 72 1 -ford gran torino (sw) 13 8 302 140 4294 16 72 1 -plymouth satellite custom (sw) 14 8 318 150 4077 14 72 1 -volvo 145e (sw) 18 4 121 112 2933 14.5 72 2 -volkswagen 411 (sw) 22 4 121 76 2511 18 72 2 -peugeot 504 (sw) 21 4 120 87 2979 19.5 72 2 -renault 12 (sw) 26 4 96 69 2189 18 72 2 -ford pinto (sw) 22 4 122 86 2395 16 72 1 -datsun 510 (sw) 28 4 97 92 2288 17 72 3 -toyouta corona mark ii (sw) 23 4 120 97 2506 14.5 72 3 -dodge colt (sw) 28 4 98 80 2164 15 72 1 -toyota corolla 1600 (sw) 27 4 97 88 2100 16.5 72 3 -buick century 350 13 8 350 175 4100 13 73 1 -amc matador 14 8 304 150 3672 11.5 73 1 -chevrolet malibu 13 8 350 145 3988 13 73 1 -ford gran torino 14 8 302 137 4042 14.5 73 1 -dodge coronet custom 15 8 318 150 3777 12.5 73 1 -mercury marquis brougham 12 8 429 198 4952 11.5 73 1 -chevrolet caprice classic 13 8 400 150 4464 12 73 1 -ford ltd 13 8 351 158 4363 13 73 1 -plymouth fury gran sedan 14 8 318 150 4237 14.5 73 1 -chrysler new yorker brougham 13 8 440 215 4735 11 73 1 -buick electra 225 custom 12 8 455 225 4951 11 73 1 -amc ambassador brougham 13 8 360 175 3821 11 73 1 -plymouth valiant 18 6 225 105 3121 16.5 73 1 -chevrolet nova custom 16 6 250 100 3278 18 73 1 -amc hornet 18 6 232 100 2945 16 73 1 -ford maverick 18 6 250 88 3021 16.5 73 1 -plymouth duster 23 6 198 95 2904 16 73 1 -volkswagen super beetle 26 4 97 46 1950 21 73 2 -chevrolet impala 11 8 400 150 4997 14 73 1 -ford country 12 8 400 167 4906 12.5 73 1 -plymouth custom suburb 13 8 360 170 4654 13 73 1 -oldsmobile vista cruiser 12 8 350 180 4499 12.5 73 1 -amc gremlin 18 6 232 100 2789 15 73 1 -toyota carina 20 4 97 88 2279 19 73 3 -chevrolet vega 21 4 140 72 2401 19.5 73 1 -datsun 610 22 4 108 94 2379 16.5 73 3 -maxda rx3 18 3 70 90 2124 13.5 73 3 -ford pinto 19 4 122 85 2310 18.5 73 1 -mercury capri v6 21 6 155 107 2472 14 73 1 -fiat 124 sport coupe 26 4 98 90 2265 15.5 73 2 -chevrolet monte carlo s 15 8 350 145 4082 13 73 1 -pontiac grand prix 16 8 400 230 4278 9.5 73 1 -fiat 128 29 4 68 49 1867 19.5 73 2 -opel manta 24 4 116 75 2158 15.5 73 2 -audi 100ls 20 4 114 91 2582 14 73 2 -volvo 144ea 19 4 121 112 2868 15.5 73 2 -dodge dart custom 15 8 318 150 3399 11 73 1 -saab 99le 24 4 121 110 2660 14 73 2 -toyota mark ii 20 6 156 122 2807 13.5 73 3 -oldsmobile omega 11 8 350 180 3664 11 73 1 -plymouth duster 20 6 198 95 3102 16.5 74 1 -ford maverick 21 6 200 NA 2875 17 74 1 -amc hornet 19 6 232 100 2901 16 74 1 -chevrolet nova 15 6 250 100 3336 17 74 1 -datsun b210 31 4 79 67 1950 19 74 3 -ford pinto 26 4 122 80 2451 16.5 74 1 -toyota corolla 1200 32 4 71 65 1836 21 74 3 -chevrolet vega 25 4 140 75 2542 17 74 1 -chevrolet chevelle malibu classic 16 6 250 100 3781 17 74 1 -amc matador 16 6 258 110 3632 18 74 1 -plymouth satellite sebring 18 6 225 105 3613 16.5 74 1 -ford gran torino 16 8 302 140 4141 14 74 1 -buick century luxus (sw) 13 8 350 150 4699 14.5 74 1 -dodge coronet custom (sw) 14 8 318 150 4457 13.5 74 1 -ford gran torino (sw) 14 8 302 140 4638 16 74 1 -amc matador (sw) 14 8 304 150 4257 15.5 74 1 -audi fox 29 4 98 83 2219 16.5 74 2 -volkswagen dasher 26 4 79 67 1963 15.5 74 2 -opel manta 26 4 97 78 2300 14.5 74 2 -toyota corona 31 4 76 52 1649 16.5 74 3 -datsun 710 32 4 83 61 2003 19 74 3 -dodge colt 28 4 90 75 2125 14.5 74 1 -fiat 128 24 4 90 75 2108 15.5 74 2 -fiat 124 tc 26 4 116 75 2246 14 74 2 -honda civic 24 4 120 97 2489 15 74 3 -subaru 26 4 108 93 2391 15.5 74 3 -fiat x1.9 31 4 79 67 2000 16 74 2 -plymouth valiant custom 19 6 225 95 3264 16 75 1 -chevrolet nova 18 6 250 105 3459 16 75 1 -mercury monarch 15 6 250 72 3432 21 75 1 -ford maverick 15 6 250 72 3158 19.5 75 1 -pontiac catalina 16 8 400 170 4668 11.5 75 1 -chevrolet bel air 15 8 350 145 4440 14 75 1 -plymouth grand fury 16 8 318 150 4498 14.5 75 1 -ford ltd 14 8 351 148 4657 13.5 75 1 -buick century 17 6 231 110 3907 21 75 1 -chevroelt chevelle malibu 16 6 250 105 3897 18.5 75 1 -amc matador 15 6 258 110 3730 19 75 1 -plymouth fury 18 6 225 95 3785 19 75 1 -buick skyhawk 21 6 231 110 3039 15 75 1 -chevrolet monza 2+2 20 8 262 110 3221 13.5 75 1 -ford mustang ii 13 8 302 129 3169 12 75 1 -toyota corolla 29 4 97 75 2171 16 75 3 -ford pinto 23 4 140 83 2639 17 75 1 -amc gremlin 20 6 232 100 2914 16 75 1 -pontiac astro 23 4 140 78 2592 18.5 75 1 -toyota corona 24 4 134 96 2702 13.5 75 3 -volkswagen dasher 25 4 90 71 2223 16.5 75 2 -datsun 710 24 4 119 97 2545 17 75 3 -ford pinto 18 6 171 97 2984 14.5 75 1 -volkswagen rabbit 29 4 90 70 1937 14 75 2 -amc pacer 19 6 232 90 3211 17 75 1 -audi 100ls 23 4 115 95 2694 15 75 2 -peugeot 504 23 4 120 88 2957 17 75 2 -volvo 244dl 22 4 121 98 2945 14.5 75 2 -saab 99le 25 4 121 115 2671 13.5 75 2 -honda civic cvcc 33 4 91 53 1795 17.5 75 3 -fiat 131 28 4 107 86 2464 15.5 76 2 -opel 1900 25 4 116 81 2220 16.9 76 2 -capri ii 25 4 140 92 2572 14.9 76 1 -dodge colt 26 4 98 79 2255 17.7 76 1 -renault 12tl 27 4 101 83 2202 15.3 76 2 -chevrolet chevelle malibu classic 17.5 8 305 140 4215 13 76 1 -dodge coronet brougham 16 8 318 150 4190 13 76 1 -amc matador 15.5 8 304 120 3962 13.9 76 1 -ford gran torino 14.5 8 351 152 4215 12.8 76 1 -plymouth valiant 22 6 225 100 3233 15.4 76 1 -chevrolet nova 22 6 250 105 3353 14.5 76 1 -ford maverick 24 6 200 81 3012 17.6 76 1 -amc hornet 22.5 6 232 90 3085 17.6 76 1 -chevrolet chevette 29 4 85 52 2035 22.2 76 1 -chevrolet woody 24.5 4 98 60 2164 22.1 76 1 -vw rabbit 29 4 90 70 1937 14.2 76 2 -honda civic 33 4 91 53 1795 17.4 76 3 -dodge aspen se 20 6 225 100 3651 17.7 76 1 -ford granada ghia 18 6 250 78 3574 21 76 1 -pontiac ventura sj 18.5 6 250 110 3645 16.2 76 1 -amc pacer d/l 17.5 6 258 95 3193 17.8 76 1 -volkswagen rabbit 29.5 4 97 71 1825 12.2 76 2 -datsun b-210 32 4 85 70 1990 17 76 3 -toyota corolla 28 4 97 75 2155 16.4 76 3 -ford pinto 26.5 4 140 72 2565 13.6 76 1 -volvo 245 20 4 130 102 3150 15.7 76 2 -plymouth volare premier v8 13 8 318 150 3940 13.2 76 1 -peugeot 504 19 4 120 88 3270 21.9 76 2 -toyota mark ii 19 6 156 108 2930 15.5 76 3 -mercedes-benz 280s 16.5 6 168 120 3820 16.7 76 2 -cadillac seville 16.5 8 350 180 4380 12.1 76 1 -chevy c10 13 8 350 145 4055 12 76 1 -ford f108 13 8 302 130 3870 15 76 1 -dodge d100 13 8 318 150 3755 14 76 1 -honda accord cvcc 31.5 4 98 68 2045 18.5 77 3 -buick opel isuzu deluxe 30 4 111 80 2155 14.8 77 1 -renault 5 gtl 36 4 79 58 1825 18.6 77 2 -plymouth arrow gs 25.5 4 122 96 2300 15.5 77 1 -datsun f-10 hatchback 33.5 4 85 70 1945 16.8 77 3 -chevrolet caprice classic 17.5 8 305 145 3880 12.5 77 1 -oldsmobile cutlass supreme 17 8 260 110 4060 19 77 1 -dodge monaco brougham 15.5 8 318 145 4140 13.7 77 1 -mercury cougar brougham 15 8 302 130 4295 14.9 77 1 -chevrolet concours 17.5 6 250 110 3520 16.4 77 1 -buick skylark 20.5 6 231 105 3425 16.9 77 1 -plymouth volare custom 19 6 225 100 3630 17.7 77 1 -ford granada 18.5 6 250 98 3525 19 77 1 -pontiac grand prix lj 16 8 400 180 4220 11.1 77 1 -chevrolet monte carlo landau 15.5 8 350 170 4165 11.4 77 1 -chrysler cordoba 15.5 8 400 190 4325 12.2 77 1 -ford thunderbird 16 8 351 149 4335 14.5 77 1 -volkswagen rabbit custom 29 4 97 78 1940 14.5 77 2 -pontiac sunbird coupe 24.5 4 151 88 2740 16 77 1 -toyota corolla liftback 26 4 97 75 2265 18.2 77 3 -ford mustang ii 2+2 25.5 4 140 89 2755 15.8 77 1 -chevrolet chevette 30.5 4 98 63 2051 17 77 1 -dodge colt m/m 33.5 4 98 83 2075 15.9 77 1 -subaru dl 30 4 97 67 1985 16.4 77 3 -volkswagen dasher 30.5 4 97 78 2190 14.1 77 2 -datsun 810 22 6 146 97 2815 14.5 77 3 -bmw 320i 21.5 4 121 110 2600 12.8 77 2 -mazda rx-4 21.5 3 80 110 2720 13.5 77 3 -volkswagen rabbit custom diesel 43.1 4 90 48 1985 21.5 78 2 -ford fiesta 36.1 4 98 66 1800 14.4 78 1 -mazda glc deluxe 32.8 4 78 52 1985 19.4 78 3 -datsun b210 gx 39.4 4 85 70 2070 18.6 78 3 -honda civic cvcc 36.1 4 91 60 1800 16.4 78 3 -oldsmobile cutlass salon brougham 19.9 8 260 110 3365 15.5 78 1 -dodge diplomat 19.4 8 318 140 3735 13.2 78 1 -mercury monarch ghia 20.2 8 302 139 3570 12.8 78 1 -pontiac phoenix lj 19.2 6 231 105 3535 19.2 78 1 -chevrolet malibu 20.5 6 200 95 3155 18.2 78 1 -ford fairmont (auto) 20.2 6 200 85 2965 15.8 78 1 -ford fairmont (man) 25.1 4 140 88 2720 15.4 78 1 -plymouth volare 20.5 6 225 100 3430 17.2 78 1 -amc concord 19.4 6 232 90 3210 17.2 78 1 -buick century special 20.6 6 231 105 3380 15.8 78 1 -mercury zephyr 20.8 6 200 85 3070 16.7 78 1 -dodge aspen 18.6 6 225 110 3620 18.7 78 1 -amc concord d/l 18.1 6 258 120 3410 15.1 78 1 -chevrolet monte carlo landau 19.2 8 305 145 3425 13.2 78 1 -buick regal sport coupe (turbo) 17.7 6 231 165 3445 13.4 78 1 -ford futura 18.1 8 302 139 3205 11.2 78 1 -dodge magnum xe 17.5 8 318 140 4080 13.7 78 1 -chevrolet chevette 30 4 98 68 2155 16.5 78 1 -toyota corona 27.5 4 134 95 2560 14.2 78 3 -datsun 510 27.2 4 119 97 2300 14.7 78 3 -dodge omni 30.9 4 105 75 2230 14.5 78 1 -toyota celica gt liftback 21.1 4 134 95 2515 14.8 78 3 -plymouth sapporo 23.2 4 156 105 2745 16.7 78 1 -oldsmobile starfire sx 23.8 4 151 85 2855 17.6 78 1 -datsun 200-sx 23.9 4 119 97 2405 14.9 78 3 -audi 5000 20.3 5 131 103 2830 15.9 78 2 -volvo 264gl 17 6 163 125 3140 13.6 78 2 -saab 99gle 21.6 4 121 115 2795 15.7 78 2 -peugeot 604sl 16.2 6 163 133 3410 15.8 78 2 -volkswagen scirocco 31.5 4 89 71 1990 14.9 78 2 -honda accord lx 29.5 4 98 68 2135 16.6 78 3 -pontiac lemans v6 21.5 6 231 115 3245 15.4 79 1 -mercury zephyr 6 19.8 6 200 85 2990 18.2 79 1 -ford fairmont 4 22.3 4 140 88 2890 17.3 79 1 -amc concord dl 6 20.2 6 232 90 3265 18.2 79 1 -dodge aspen 6 20.6 6 225 110 3360 16.6 79 1 -chevrolet caprice classic 17 8 305 130 3840 15.4 79 1 -ford ltd landau 17.6 8 302 129 3725 13.4 79 1 -mercury grand marquis 16.5 8 351 138 3955 13.2 79 1 -dodge st. regis 18.2 8 318 135 3830 15.2 79 1 -buick estate wagon (sw) 16.9 8 350 155 4360 14.9 79 1 -ford country squire (sw) 15.5 8 351 142 4054 14.3 79 1 -chevrolet malibu classic (sw) 19.2 8 267 125 3605 15 79 1 -chrysler lebaron town @ country (sw) 18.5 8 360 150 3940 13 79 1 -vw rabbit custom 31.9 4 89 71 1925 14 79 2 -maxda glc deluxe 34.1 4 86 65 1975 15.2 79 3 -dodge colt hatchback custom 35.7 4 98 80 1915 14.4 79 1 -amc spirit dl 27.4 4 121 80 2670 15 79 1 -mercedes benz 300d 25.4 5 183 77 3530 20.1 79 2 -cadillac eldorado 23 8 350 125 3900 17.4 79 1 -peugeot 504 27.2 4 141 71 3190 24.8 79 2 -oldsmobile cutlass salon brougham 23.9 8 260 90 3420 22.2 79 1 -plymouth horizon 34.2 4 105 70 2200 13.2 79 1 -plymouth horizon tc3 34.5 4 105 70 2150 14.9 79 1 -datsun 210 31.8 4 85 65 2020 19.2 79 3 -fiat strada custom 37.3 4 91 69 2130 14.7 79 2 -buick skylark limited 28.4 4 151 90 2670 16 79 1 -chevrolet citation 28.8 6 173 115 2595 11.3 79 1 -oldsmobile omega brougham 26.8 6 173 115 2700 12.9 79 1 -pontiac phoenix 33.5 4 151 90 2556 13.2 79 1 -vw rabbit 41.5 4 98 76 2144 14.7 80 2 -toyota corolla tercel 38.1 4 89 60 1968 18.8 80 3 -chevrolet chevette 32.1 4 98 70 2120 15.5 80 1 -datsun 310 37.2 4 86 65 2019 16.4 80 3 -chevrolet citation 28 4 151 90 2678 16.5 80 1 -ford fairmont 26.4 4 140 88 2870 18.1 80 1 -amc concord 24.3 4 151 90 3003 20.1 80 1 -dodge aspen 19.1 6 225 90 3381 18.7 80 1 -audi 4000 34.3 4 97 78 2188 15.8 80 2 -toyota corona liftback 29.8 4 134 90 2711 15.5 80 3 -mazda 626 31.3 4 120 75 2542 17.5 80 3 -datsun 510 hatchback 37 4 119 92 2434 15 80 3 -toyota corolla 32.2 4 108 75 2265 15.2 80 3 -mazda glc 46.6 4 86 65 2110 17.9 80 3 -dodge colt 27.9 4 156 105 2800 14.4 80 1 -datsun 210 40.8 4 85 65 2110 19.2 80 3 -vw rabbit c (diesel) 44.3 4 90 48 2085 21.7 80 2 -vw dasher (diesel) 43.4 4 90 48 2335 23.7 80 2 -audi 5000s (diesel) 36.4 5 121 67 2950 19.9 80 2 -mercedes-benz 240d 30 4 146 67 3250 21.8 80 2 -honda civic 1500 gl 44.6 4 91 67 1850 13.8 80 3 -renault lecar deluxe 40.9 4 85 NA 1835 17.3 80 2 -subaru dl 33.8 4 97 67 2145 18 80 3 -vokswagen rabbit 29.8 4 89 62 1845 15.3 80 2 -datsun 280-zx 32.7 6 168 132 2910 11.4 80 3 -mazda rx-7 gs 23.7 3 70 100 2420 12.5 80 3 -triumph tr7 coupe 35 4 122 88 2500 15.1 80 2 -ford mustang cobra 23.6 4 140 NA 2905 14.3 80 1 -honda accord 32.4 4 107 72 2290 17 80 3 -plymouth reliant 27.2 4 135 84 2490 15.7 81 1 -buick skylark 26.6 4 151 84 2635 16.4 81 1 -dodge aries wagon (sw) 25.8 4 156 92 2620 14.4 81 1 -chevrolet citation 23.5 6 173 110 2725 12.6 81 1 -plymouth reliant 30 4 135 84 2385 12.9 81 1 -toyota starlet 39.1 4 79 58 1755 16.9 81 3 -plymouth champ 39 4 86 64 1875 16.4 81 1 -honda civic 1300 35.1 4 81 60 1760 16.1 81 3 -subaru 32.3 4 97 67 2065 17.8 81 3 -datsun 210 mpg 37 4 85 65 1975 19.4 81 3 -toyota tercel 37.7 4 89 62 2050 17.3 81 3 -mazda glc 4 34.1 4 91 68 1985 16 81 3 -plymouth horizon 4 34.7 4 105 63 2215 14.9 81 1 -ford escort 4w 34.4 4 98 65 2045 16.2 81 1 -ford escort 2h 29.9 4 98 65 2380 20.7 81 1 -volkswagen jetta 33 4 105 74 2190 14.2 81 2 -renault 18i 34.5 4 100 NA 2320 15.8 81 2 -honda prelude 33.7 4 107 75 2210 14.4 81 3 -toyota corolla 32.4 4 108 75 2350 16.8 81 3 -datsun 200sx 32.9 4 119 100 2615 14.8 81 3 -mazda 626 31.6 4 120 74 2635 18.3 81 3 -peugeot 505s turbo diesel 28.1 4 141 80 3230 20.4 81 2 -saab 900s NA 4 121 110 2800 15.4 81 2 -volvo diesel 30.7 6 145 76 3160 19.6 81 2 -toyota cressida 25.4 6 168 116 2900 12.6 81 3 -datsun 810 maxima 24.2 6 146 120 2930 13.8 81 3 -buick century 22.4 6 231 110 3415 15.8 81 1 -oldsmobile cutlass ls 26.6 8 350 105 3725 19 81 1 -ford granada gl 20.2 6 200 88 3060 17.1 81 1 -chrysler lebaron salon 17.6 6 225 85 3465 16.6 81 1 -chevrolet cavalier 28 4 112 88 2605 19.6 82 1 -chevrolet cavalier wagon 27 4 112 88 2640 18.6 82 1 -chevrolet cavalier 2-door 34 4 112 88 2395 18 82 1 -pontiac j2000 se hatchback 31 4 112 85 2575 16.2 82 1 -dodge aries se 29 4 135 84 2525 16 82 1 -pontiac phoenix 27 4 151 90 2735 18 82 1 -ford fairmont futura 24 4 140 92 2865 16.4 82 1 -amc concord dl 23 4 151 NA 3035 20.5 82 1 -volkswagen rabbit l 36 4 105 74 1980 15.3 82 2 -mazda glc custom l 37 4 91 68 2025 18.2 82 3 -mazda glc custom 31 4 91 68 1970 17.6 82 3 -plymouth horizon miser 38 4 105 63 2125 14.7 82 1 -mercury lynx l 36 4 98 70 2125 17.3 82 1 -nissan stanza xe 36 4 120 88 2160 14.5 82 3 -honda accord 36 4 107 75 2205 14.5 82 3 -toyota corolla 34 4 108 70 2245 16.9 82 3 -honda civic 38 4 91 67 1965 15 82 3 -honda civic (auto) 32 4 91 67 1965 15.7 82 3 -datsun 310 gx 38 4 91 67 1995 16.2 82 3 -buick century limited 25 6 181 110 2945 16.4 82 1 -oldsmobile cutlass ciera (diesel) 38 6 262 85 3015 17 82 1 -chrysler lebaron medallion 26 4 156 92 2585 14.5 82 1 -ford granada l 22 6 232 112 2835 14.7 82 1 -toyota celica gt 32 4 144 96 2665 13.9 82 3 -dodge charger 2.2 36 4 135 84 2370 13 82 1 -chevrolet camaro 27 4 151 90 2950 17.3 82 1 -ford mustang gl 27 4 140 86 2790 15.6 82 1 -vw pickup 44 4 97 52 2130 24.6 82 2 -dodge rampage 32 4 135 84 2295 11.6 82 1 -ford ranger 28 4 120 79 2625 18.6 82 1 -chevy s-10 31 4 119 82 2720 19.4 82 1 \ No newline at end of file diff --git a/mode/examples/Topics/File IO/SaveFile1/SaveFile1.pde b/mode/examples/Topics/File IO/SaveFile1/SaveFile1.pde deleted file mode 100644 index 9bcdbec18..000000000 --- a/mode/examples/Topics/File IO/SaveFile1/SaveFile1.pde +++ /dev/null @@ -1,49 +0,0 @@ -/** - * SaveFile 1 - * - * Saving files is a useful way to store data so it can be viewed after a - * program has stopped running. The saveStrings() function writes an array - * of strings to a file, with each string written to a new line. This file - * is saved to the sketch's folder. This example won't work in a web browser - * because of Java security restrictions. - */ - -int[] x = new int[0]; -int[] y = new int[0]; - -void setup() -{ - size(200, 200); -} - -void draw() -{ - background(204); - stroke(0); - noFill(); - beginShape(); - for (int i = 0; i < x.length; i++) { - vertex(x[i], y[i]); - } - endShape(); - // Show the next segment to be added - if (x.length >= 1) { - stroke(255); - line(mouseX, mouseY, x[x.length-1], y[x.length-1]); - } -} - -void mousePressed() { // Click to add a line segment - x = append(x, mouseX); - y = append(y, mouseY); -} - -void keyPressed() { // Press a key to save the data - String[] lines = new String[x.length]; - for (int i = 0; i < x.length; i++) { - lines[i] = x[i] + "\t" + y[i]; - } - saveStrings("lines.txt", lines); - exit(); // Stop the program -} - diff --git a/mode/examples/Topics/File IO/SaveFile2/SaveFile2.pde b/mode/examples/Topics/File IO/SaveFile2/SaveFile2.pde deleted file mode 100644 index f47265063..000000000 --- a/mode/examples/Topics/File IO/SaveFile2/SaveFile2.pde +++ /dev/null @@ -1,34 +0,0 @@ -/** - * SaveFile 2 - * - * This file a PrintWriter object to write data continuously to a file - * while the mouse is pressed. When a key is pressed, the file closes - * itself and the program is stopped. This example won't work in a web browser - * because of Java security restrictions. - */ - -PrintWriter output; - -void setup() -{ - size(200, 200); - // Create a new file in the sketch directory - output = createWriter("positions.txt"); - frameRate(12); -} - -void draw() -{ - if (mousePressed) { - point(mouseX, mouseY); - // Write the coordinate to a file with a - // "\t" (TAB character) between each entry - output.println(mouseX + "\t" + mouseY); - } -} - -void keyPressed() { // Press a key to save the data - output.flush(); // Write the remaining data - output.close(); // Finish the file - exit(); // Stop the program -} diff --git a/mode/examples/Topics/File IO/SaveManyImages/SaveManyImages.pde b/mode/examples/Topics/File IO/SaveManyImages/SaveManyImages.pde deleted file mode 100644 index 4a030ec71..000000000 --- a/mode/examples/Topics/File IO/SaveManyImages/SaveManyImages.pde +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Save Many Images. - * - * The saveFrame() function allows you to save images from - * a program while it is running. This example saves the first - * 50 frames of a program. These images can be imported into - * animation software or QuickTime and then saved as a movie. - */ - -float x = 33; -float numFrames = 50; - -void setup() -{ - size(200, 200); - smooth(); - noStroke(); -} - -void draw() -{ - background(0); - x += random(-2, 2); - ellipse(x, 100, 80, 80); - if (frameCount <= numFrames) { - saveFrame("circles-####.tif"); - } -} diff --git a/mode/examples/Topics/File IO/SaveOneImage/SaveOneImage.pde b/mode/examples/Topics/File IO/SaveOneImage/SaveOneImage.pde deleted file mode 100644 index 81f5aa8e9..000000000 --- a/mode/examples/Topics/File IO/SaveOneImage/SaveOneImage.pde +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Save One Image - * - * The save() function allows you to save an image from the - * display window. In this example, save() is run when a mouse - * button is pressed. The image "line.tif" is saved to the - * same folder as the sketch's program file. - */ - -void setup() -{ - size(200, 200); -} - -void draw() -{ - background(204); - line(0, 0, mouseX, height); - line(width, 0, 0, mouseY); -} - -void mousePressed() -{ - save("line.tif"); -} diff --git a/mode/examples/Topics/File IO/TileImages/TileImages.pde b/mode/examples/Topics/File IO/TileImages/TileImages.pde deleted file mode 100644 index d577e275e..000000000 --- a/mode/examples/Topics/File IO/TileImages/TileImages.pde +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Tile Images - * - * Draws an image larger than the screen, and saves the image as six tiles. - * The scaleValue variable sets amount of scaling: 1 is 100%, 2 is 200%, etc. - */ - -int scaleValue = 3; // Multiplication factor -int xoffset = 0; // x-axis offset -int yoffset = 0; // y-axis offset - -void setup() { - size(600, 600); - stroke(0, 100); -} - -void draw() { - background(204); - scale(scaleValue); - translate(xoffset * (-width / scaleValue), yoffset * (-height / scaleValue)); - line(10, 150, 500, 50); - line(0, 600, 600, 0); - save("lines-" + yoffset + "-" + xoffset + ".png"); - setOffset(); -} - -void setOffset() { - xoffset++; - if (xoffset == scaleValue) { - xoffset = 0; - yoffset++; - if (yoffset == scaleValue) { - println("Tiles saved."); - exit(); - } - } -} \ No newline at end of file diff --git a/mode/examples/Topics/Fractals and L-Systems/Koch/Koch.pde b/mode/examples/Topics/Fractals and L-Systems/Koch/Koch.pde deleted file mode 100644 index 3dbc49bfc..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/Koch/Koch.pde +++ /dev/null @@ -1,176 +0,0 @@ -/** - * Koch Curve - * by Daniel Shiffman. - * - * Renders a simple fractal, the Koch snowflake. - * Each recursive level is drawn in sequence. - */ - - -KochFractal k; - -void setup() { - size(640, 360); - background(0); - frameRate(1); // Animate slowly - k = new KochFractal(); - smooth(); -} - -void draw() { - background(0); - // Draws the snowflake! - k.render(); - // Iterate - k.nextLevel(); - // Let's not do it more than 5 times. . . - if (k.getCount() > 5) { - k.restart(); - } - -} - - -// A class to manage the list of line segments in the snowflake pattern - -class KochFractal { - Point start; // A point for the start - Point end; // A point for the end - ArrayList lines; // A list to keep track of all the lines - int count; - - public KochFractal() - { - start = new Point(0,height/2 + height/4); - end = new Point(width,height/2 + height/4); - lines = new ArrayList(); - restart(); - } - - void nextLevel() - { - // For every line that is in the arraylist - // create 4 more lines in a new arraylist - lines = iterate(lines); - count++; - } - - void restart() - { - count = 0; // Reset count - lines.clear(); // Empty the array list - lines.add(new KochLine(start,end)); // Add the initial line (from one end point to the other) - } - - int getCount() { - return count; - } - - // This is easy, just draw all the lines - void render() - { - for(int i = 0; i < lines.size(); i++) { - KochLine l = (KochLine)lines.get(i); - l.render(); - } - } - - // This is where the **MAGIC** happens - // Step 1: Create an empty arraylist - // Step 2: For every line currently in the arraylist - // - calculate 4 line segments based on Koch algorithm - // - add all 4 line segments into the new arraylist - // Step 3: Return the new arraylist and it becomes the list of line segments for the structure - - // As we do this over and over again, each line gets broken into 4 lines, which gets broken into 4 lines, and so on. . . - ArrayList iterate(ArrayList before) - { - ArrayList now = new ArrayList(); //Create emtpy list - for(int i = 0; i < before.size(); i++) - { - KochLine l = (KochLine)lines.get(i); // A line segment inside the list - // Calculate 5 koch points (done for us by the line object) - Point a = l.start(); - Point b = l.kochleft(); - Point c = l.kochmiddle(); - Point d = l.kochright(); - Point e = l.end(); - // Make line segments between all the points and add them - now.add(new KochLine(a,b)); - now.add(new KochLine(b,c)); - now.add(new KochLine(c,d)); - now.add(new KochLine(d,e)); - } - return now; - } - -} - - -// A class to describe one line segment in the fractal -// Includes methods to calculate midpoints along the line according to the Koch algorithm - -class KochLine { - - // Two points, - // a is the "left" point and - // b is the "right point - Point a,b; - - KochLine(Point a_, Point b_) { - a = a_.copy(); - b = b_.copy(); - } - - void render() { - stroke(255); - line(a.x,a.y,b.x,b.y); - } - - Point start() { - return a.copy(); - } - - Point end() { - return b.copy(); - } - - // This is easy, just 1/3 of the way - Point kochleft() - { - float x = a.x + (b.x - a.x) / 3f; - float y = a.y + (b.y - a.y) / 3f; - return new Point(x,y); - } - - // More complicated, have to use a little trig to figure out where this point is! - Point kochmiddle() - { - float x = a.x + 0.5f * (b.x - a.x) + (sin(radians(60))*(b.y-a.y)) / 3; - float y = a.y + 0.5f * (b.y - a.y) - (sin(radians(60))*(b.x-a.x)) / 3; - return new Point(x,y); - } - - // Easy, just 2/3 of the way - Point kochright() - { - float x = a.x + 2*(b.x - a.x) / 3f; - float y = a.y + 2*(b.y - a.y) / 3f; - return new Point(x,y); - } - -} - -class Point { - float x,y; - - Point(float x_, float y_) { - x = x_; - y = y_; - } - - Point copy() { - return new Point(x,y); - } -} - diff --git a/mode/examples/Topics/Fractals and L-Systems/Mandelbrot/Mandelbrot.pde b/mode/examples/Topics/Fractals and L-Systems/Mandelbrot/Mandelbrot.pde deleted file mode 100644 index 2f31de8fb..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/Mandelbrot/Mandelbrot.pde +++ /dev/null @@ -1,75 +0,0 @@ -/** - * The Mandelbrot Set - * by Daniel Shiffman. - * - * Simple rendering of the Mandelbrot set. - */ - -// Establish a range of values on the complex plane -// A different range will allow us to "zoom" in or out on the fractal -// float xmin = -1.5; float ymin = -.1; float wh = 0.15; -float xmin = -2.5; -float ymin = -2; -float wh = 4; - -void setup() { - size(200, 200, P2D); - noLoop(); - background(255); - // Make sure we can write to the pixels[] array. - // Only need to do this once since we don't do any other drawing. - loadPixels(); -} - -void draw() { - // Maximum number of iterations for each point on the complex plane - int maxiterations = 200; - - // x goes from xmin to xmax - float xmax = xmin + wh; - // y goes from ymin to ymax - float ymax = ymin + wh; - - // Calculate amount we increment x,y for each pixel - float dx = (xmax - xmin) / (width); - float dy = (ymax - ymin) / (height); - - // Start y - float y = ymin; - for (int j = 0; j < height; j++) { - // Start x - float x = xmin; - for (int i = 0; i < width; i++) { - - // Now we test, as we iterate z = z^2 + cm does z tend towards infinity? - float a = x; - float b = y; - int n = 0; - while (n < maxiterations) { - float aa = a * a; - float bb = b * b; - float twoab = 2.0 * a * b; - a = aa - bb + x; - b = twoab + y; - // Infinty in our finite world is simple, let's just consider it 16 - if(aa + bb > 16.0) { - break; // Bail - } - n++; - } - - // We color each pixel based on how long it takes to get to infinity - // If we never got there, let's pick the color black - if (n == maxiterations) { - pixels[i+j*width] = 0; - } else { - // Gosh, we could make fancy colors here if we wanted - pixels[i+j*width] = color(n*16 % 255); - } - x += dx; - } - y += dy; - } - updatePixels(); -} - diff --git a/mode/examples/Topics/Fractals and L-Systems/PenroseSnowflake/LSystem.pde b/mode/examples/Topics/Fractals and L-Systems/PenroseSnowflake/LSystem.pde deleted file mode 100644 index 10e694d12..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/PenroseSnowflake/LSystem.pde +++ /dev/null @@ -1,76 +0,0 @@ -class LSystem -{ - int steps = 0; - - String axiom; - String rule; - String production; - - float startLength; - float drawLength; - float theta; - - int generations; - - LSystem() { - axiom = "F"; - rule = "F+F-F"; - startLength = 90.0; - theta = radians(120.0); - reset(); - } - - void reset() { - production = axiom; - drawLength = startLength; - generations = 0; - } - - int getAge() { - return generations; - } - - void render() { - translate(width/2, height/2); - steps += 5; - if (steps > production.length()) { - steps = production.length(); - } - for (int i = 0; i < steps; i++) { - char step = production.charAt(i); - if (step == 'F') { - rect(0, 0, -drawLength, -drawLength); - noFill(); - translate(0, -drawLength); - } - else if (step == '+') { - rotate(theta); - } - else if (step == '-') { - rotate(-theta); - } - else if (step == '[') { - pushMatrix(); - } - else if (step == ']') { - popMatrix(); - } - } - } - - void simulate(int gen) { - while (getAge() < gen) { - production = iterate(production, rule); - } - } - - String iterate(String prod_, String rule_) { - drawLength = drawLength * 0.6; - generations++; - String newProduction = prod_; - newProduction = newProduction.replaceAll("F", rule_); - return newProduction; - } -} - - diff --git a/mode/examples/Topics/Fractals and L-Systems/PenroseSnowflake/PenroseSnowflake.pde b/mode/examples/Topics/Fractals and L-Systems/PenroseSnowflake/PenroseSnowflake.pde deleted file mode 100644 index 8fe1c9393..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/PenroseSnowflake/PenroseSnowflake.pde +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Penrose Snowflake L-System - * by Geraldine Sarmiento (NYU ITP). - * - * This code was based on Patrick Dwyer's L-System class. - */ - -PenroseSnowflakeLSystem ps; - -void setup() { - size(640, 360); - stroke(255); - noFill(); - smooth(); - ps = new PenroseSnowflakeLSystem(); - ps.simulate(4); -} - -void draw() { - background(0); - ps.render(); -} - - diff --git a/mode/examples/Topics/Fractals and L-Systems/PenroseSnowflake/PenroseSnowflakeLSystem.pde b/mode/examples/Topics/Fractals and L-Systems/PenroseSnowflake/PenroseSnowflakeLSystem.pde deleted file mode 100644 index df1f775b0..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/PenroseSnowflake/PenroseSnowflakeLSystem.pde +++ /dev/null @@ -1,100 +0,0 @@ -class PenroseSnowflakeLSystem extends LSystem { - - String ruleF; - - PenroseSnowflakeLSystem() { - axiom = "F3-F3-F3-F3-F"; - ruleF = "F3-F3-F45-F++F3-F"; - startLength = 450.0; - theta = radians(18); - reset(); - } - - void useRule(String r_) { - rule = r_; - } - - void useAxiom(String a_) { - axiom = a_; - } - - void useLength(float l_) { - startLength = l_; - } - - void useTheta(float t_) { - theta = radians(t_); - } - - void reset() { - production = axiom; - drawLength = startLength; - generations = 0; - } - - int getAge() { - return generations; - } - - void render() { - translate(width, height); - int repeats = 1; - - steps += 3; - if (steps > production.length()) { - steps = production.length(); - } - - for (int i = 0; i < steps; i++) { - char step = production.charAt(i); - if (step == 'F') { - for (int j = 0; j < repeats; j++) { - line(0,0,0, -drawLength); - translate(0, -drawLength); - } - repeats = 1; - } - else if (step == '+') { - for (int j = 0; j < repeats; j++) { - rotate(theta); - } - repeats = 1; - } - else if (step == '-') { - for (int j =0; j < repeats; j++) { - rotate(-theta); - } - repeats = 1; - } - else if (step == '[') { - pushMatrix(); - } - else if (step == ']') { - popMatrix(); - } - else if ( (step >= 48) && (step <= 57) ) { - repeats += step - 48; - } - } - } - - - String iterate(String prod_, String rule_) { - String newProduction = ""; - for (int i = 0; i < prod_.length(); i++) { - char step = production.charAt(i); - if (step == 'F') { - newProduction = newProduction + ruleF; - } - else { - if (step != 'F') { - newProduction = newProduction + step; - } - } - } - drawLength = drawLength * 0.4; - generations++; - return newProduction; - } - -} diff --git a/mode/examples/Topics/Fractals and L-Systems/PenroseTile/LSystem.pde b/mode/examples/Topics/Fractals and L-Systems/PenroseTile/LSystem.pde deleted file mode 100644 index 8f00ddaf5..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/PenroseTile/LSystem.pde +++ /dev/null @@ -1,74 +0,0 @@ -class LSystem -{ - int steps = 0; - - String axiom; - String rule; - String production; - - float startLength; - float drawLength; - float theta; - - int generations; - - LSystem() { - axiom = "F"; - rule = "F+F-F"; - startLength = 190.0; - theta = radians(120.0); - reset(); - } - - void reset() { - production = axiom; - drawLength = startLength; - generations = 0; - } - - int getAge() { - return generations; - } - - void render() { - translate(width/2, height/2); - steps += 5; - if (steps > production.length()) { - steps = production.length(); - } - for (int i = 0; i < steps; i++) { - char step = production.charAt(i); - if (step == 'F') { - rect(0, 0, -drawLength, -drawLength); - noFill(); - translate(0, -drawLength); - } - else if (step == '+') { - rotate(theta); - } - else if (step == '-') { - rotate(-theta); - } - else if (step == '[') { - pushMatrix(); - } - else if (step == ']') { - popMatrix(); - } - } - } - - void simulate(int gen) { - while (getAge() < gen) { - production = iterate(production, rule); - } - } - - String iterate(String prod_, String rule_) { - drawLength = drawLength * 0.6; - generations++; - String newProduction = prod_; - newProduction = newProduction.replaceAll("F", rule_); - return newProduction; - } -} diff --git a/mode/examples/Topics/Fractals and L-Systems/PenroseTile/PenroseLSystem.pde b/mode/examples/Topics/Fractals and L-Systems/PenroseTile/PenroseLSystem.pde deleted file mode 100644 index 16a7f1c43..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/PenroseTile/PenroseLSystem.pde +++ /dev/null @@ -1,128 +0,0 @@ -class PenroseLSystem extends LSystem { - - int steps = 0; - float somestep = 0.1; - String ruleW; - String ruleX; - String ruleY; - String ruleZ; - - PenroseLSystem() { - axiom = "[X]++[X]++[X]++[X]++[X]"; - ruleW = "YF++ZF4-XF[-YF4-WF]++"; - ruleX = "+YF--ZF[3-WF--XF]+"; - ruleY = "-WF++XF[+++YF++ZF]-"; - ruleZ = "--YF++++WF[+ZF++++XF]--XF"; - startLength = 460.0; - theta = radians(36); - reset(); - } - - void useRule(String r_) { - rule = r_; - } - - void useAxiom(String a_) { - axiom = a_; - } - - void useLength(float l_) { - startLength = l_; - } - - void useTheta(float t_) { - theta = radians(t_); - } - - void reset() { - production = axiom; - drawLength = startLength; - generations = 0; - } - - int getAge() { - return generations; - } - - void render() { - translate(width/2, height/2); - int pushes = 0; - int repeats = 1; - steps += 12; - if (steps > production.length()) { - steps = production.length(); - } - - for (int i = 0; i < steps; i++) { - char step = production.charAt(i); - if (step == 'F') { - stroke(255, 60); - for (int j = 0; j < repeats; j++) { - line(0, 0, 0, -drawLength); - noFill(); - translate(0, -drawLength); - } - repeats = 1; - } - else if (step == '+') { - for (int j = 0; j < repeats; j++) { - rotate(theta); - } - repeats = 1; - } - else if (step == '-') { - for (int j =0; j < repeats; j++) { - rotate(-theta); - } - repeats = 1; - } - else if (step == '[') { - pushes++; - pushMatrix(); - } - else if (step == ']') { - popMatrix(); - pushes--; - } - else if ( (step >= 48) && (step <= 57) ) { - repeats = (int)step - 48; - } - } - - // Unpush if we need too - while (pushes > 0) { - popMatrix(); - pushes--; - } - } - - String iterate(String prod_, String rule_) { - String newProduction = ""; - for (int i = 0; i < prod_.length(); i++) { - char step = production.charAt(i); - if (step == 'W') { - newProduction = newProduction + ruleW; - } - else if (step == 'X') { - newProduction = newProduction + ruleX; - } - else if (step == 'Y') { - newProduction = newProduction + ruleY; - } - else if (step == 'Z') { - newProduction = newProduction + ruleZ; - } - else { - if (step != 'F') { - newProduction = newProduction + step; - } - } - } - - drawLength = drawLength * 0.5; - generations++; - return newProduction; - } - -} - diff --git a/mode/examples/Topics/Fractals and L-Systems/PenroseTile/PenroseTile.pde b/mode/examples/Topics/Fractals and L-Systems/PenroseTile/PenroseTile.pde deleted file mode 100644 index 1cbeb439c..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/PenroseTile/PenroseTile.pde +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Penrose Tile L-System - * by Geraldine Sarmiento (NYU ITP). - * - * This code was based on Patrick Dwyer's L-System class. - */ - -PenroseLSystem ds; - -void setup() -{ - size(640, 360); - smooth(); - ds = new PenroseLSystem(); - ds.simulate(4); -} - -void draw() -{ - background(0); - ds.render(); -} - - - - - - diff --git a/mode/examples/Topics/Fractals and L-Systems/Pentigree/LSystem.pde b/mode/examples/Topics/Fractals and L-Systems/Pentigree/LSystem.pde deleted file mode 100644 index 2adcabcd5..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/Pentigree/LSystem.pde +++ /dev/null @@ -1,76 +0,0 @@ -class LSystem { - - int steps = 0; - - String axiom; - String rule; - String production; - - float startLength; - float drawLength; - float theta; - - int generations; - - LSystem() { - - axiom = "F"; - rule = "F+F-F"; - startLength = 90.0; - theta = radians(120.0); - reset(); - } - - void reset() { - production = axiom; - drawLength = startLength; - generations = 0; - } - - int getAge() { - return generations; - } - - void render() { - translate(width/2, height/2); - steps += 5; - if (steps > production.length()) { - steps = production.length(); - } - for (int i = 0; i < steps; i++) { - char step = production.charAt(i); - if (step == 'F') { - rect(0, 0, -drawLength, -drawLength); - noFill(); - translate(0, -drawLength); - } - else if (step == '+') { - rotate(theta); - } - else if (step == '-') { - rotate(-theta); - } - else if (step == '[') { - pushMatrix(); - } - else if (step == ']') { - popMatrix(); - } - } - } - - void simulate(int gen) { - while (getAge() < gen) { - production = iterate(production, rule); - } - } - - String iterate(String prod_, String rule_) { - drawLength = drawLength * 0.6; - generations++; - String newProduction = prod_; - newProduction = newProduction.replaceAll("F", rule_); - return newProduction; - } -} - diff --git a/mode/examples/Topics/Fractals and L-Systems/Pentigree/Pentigree.pde b/mode/examples/Topics/Fractals and L-Systems/Pentigree/Pentigree.pde deleted file mode 100644 index be0d3fb77..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/Pentigree/Pentigree.pde +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Pentigree L-System - * by Geraldine Sarmiento (NYU ITP). - * - * This code was based on Patrick Dwyer's L-System class. - */ - - -PentigreeLSystem ps; - -void setup() { - size(640, 360); - smooth(); - ps = new PentigreeLSystem(); - ps.simulate(3); -} - -void draw() { - background(0); - ps.render(); -} - - diff --git a/mode/examples/Topics/Fractals and L-Systems/Pentigree/PentigreeLSystem.pde b/mode/examples/Topics/Fractals and L-Systems/Pentigree/PentigreeLSystem.pde deleted file mode 100644 index a377c016d..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/Pentigree/PentigreeLSystem.pde +++ /dev/null @@ -1,71 +0,0 @@ -class PentigreeLSystem extends LSystem { - - int steps = 0; - float somestep = 0.1; - float xoff = 0.01; - - PentigreeLSystem() { - axiom = "F-F-F-F-F"; - rule = "F-F++F+F-F-F"; - startLength = 60.0; - theta = radians(72); - reset(); - } - - void useRule(String r_) { - rule = r_; - } - - void useAxiom(String a_) { - axiom = a_; - } - - void useLength(float l_) { - startLength = l_; - } - - void useTheta(float t_) { - theta = radians(t_); - } - - void reset() { - production = axiom; - drawLength = startLength; - generations = 0; - } - - int getAge() { - return generations; - } - - void render() { - translate(width/4, height/2); - steps += 3; - if (steps > production.length()) { - steps = production.length(); - } - - for (int i = 0; i < steps; i++) { - char step = production.charAt(i); - if (step == 'F') { - noFill(); - stroke(255); - line(0, 0, 0, -drawLength); - translate(0, -drawLength); - } - else if (step == '+') { - rotate(theta); - } - else if (step == '-') { - rotate(-theta); - } - else if (step == '[') { - pushMatrix(); - } - else if (step == ']') { - popMatrix(); - } - } - } - -} diff --git a/mode/examples/Topics/Fractals and L-Systems/Tree/Tree.pde b/mode/examples/Topics/Fractals and L-Systems/Tree/Tree.pde deleted file mode 100644 index e6d4d646a..000000000 --- a/mode/examples/Topics/Fractals and L-Systems/Tree/Tree.pde +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Recursive Tree - * by Daniel Shiffman. - * - * Renders a simple tree-like structure via recursion. - * The branching angle is calculated as a function of - * the horizontal mouse location. Move the mouse left - * and right to change the angle. - */ - -float theta; - -void setup() { - size(640, 360); - smooth(); -} - -void draw() { - background(0); - frameRate(30); - stroke(255); - // Let's pick an angle 0 to 90 degrees based on the mouse position - float a = (mouseX / (float) width) * 90f; - // Convert it to radians - theta = radians(a); - // Start the tree from the bottom of the screen - translate(width/2,height); - // Draw a line 120 pixels - line(0,0,0,-120); - // Move to the end of that line - translate(0,-120); - // Start the recursive branching! - branch(120); - -} - -void branch(float h) { - // Each branch will be 2/3rds the size of the previous one - h *= 0.66; - - // All recursive functions must have an exit condition!!!! - // Here, ours is when the length of the branch is 2 pixels or less - if (h > 2) { - pushMatrix(); // Save the current state of transformation (i.e. where are we now) - rotate(theta); // Rotate by theta - line(0, 0, 0, -h); // Draw the branch - translate(0, -h); // Move to the end of the branch - branch(h); // Ok, now call myself to draw two new branches!! - popMatrix(); // Whenever we get back here, we "pop" in order to restore the previous matrix state - - // Repeat the same thing, only branch off to the "left" this time! - pushMatrix(); - rotate(-theta); - line(0, 0, 0, -h); - translate(0, -h); - branch(h); - popMatrix(); - } -} - - diff --git a/mode/examples/Topics/GUI/Button/Button.pde b/mode/examples/Topics/GUI/Button/Button.pde deleted file mode 100644 index fe477b83f..000000000 --- a/mode/examples/Topics/GUI/Button/Button.pde +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Button. - * - * Click on one of the colored squares in the - * center of the image to change the color of - * the background. - */ - -int rectX, rectY; // Position of square button -int circleX, circleY; // Position of circle button -int rectSize = 50; // Diameter of rect -int circleSize = 53; // Diameter of circle -color rectColor, circleColor, baseColor; -color rectHighlight, circleHighlight; -color currentColor; -boolean rectOver = false; -boolean circleOver = false; - -void setup() -{ - size(200, 200); - smooth(); - rectColor = color(0); - rectHighlight = color(51); - circleColor = color(255); - circleHighlight = color(204); - baseColor = color(102); - currentColor = baseColor; - circleX = width/2+circleSize/2+10; - circleY = height/2; - rectX = width/2-rectSize-10; - rectY = height/2-rectSize/2; - ellipseMode(CENTER); -} - -void draw() -{ - update(mouseX, mouseY); - background(currentColor); - - if(rectOver) { - fill(rectHighlight); - } else { - fill(rectColor); - } - stroke(255); - rect(rectX, rectY, rectSize, rectSize); - - if(circleOver) { - fill(circleHighlight); - } else { - fill(circleColor); - } - stroke(0); - ellipse(circleX, circleY, circleSize, circleSize); -} - -void update(int x, int y) -{ - if( overCircle(circleX, circleY, circleSize) ) { - circleOver = true; - rectOver = false; - } else if ( overRect(rectX, rectY, rectSize, rectSize) ) { - rectOver = true; - circleOver = false; - } else { - circleOver = rectOver = false; - } -} - -void mousePressed() -{ - if(circleOver) { - currentColor = circleColor; - } - if(rectOver) { - currentColor = rectColor; - } -} - -boolean overRect(int x, int y, int width, int height) -{ - if (mouseX >= x && mouseX <= x+width && - mouseY >= y && mouseY <= y+height) { - return true; - } else { - return false; - } -} - -boolean overCircle(int x, int y, int diameter) -{ - float disX = x - mouseX; - float disY = y - mouseY; - if(sqrt(sq(disX) + sq(disY)) < diameter/2 ) { - return true; - } else { - return false; - } -} diff --git a/mode/examples/Topics/GUI/Buttons/Buttons.pde b/mode/examples/Topics/GUI/Buttons/Buttons.pde deleted file mode 100644 index 11f8b0031..000000000 --- a/mode/examples/Topics/GUI/Buttons/Buttons.pde +++ /dev/null @@ -1,220 +0,0 @@ -/** - * Buttons. - * - * Click on one of the shapes to change - * the background color. This example - * demonstates a class for buttons. - */ - -color currentcolor; - -CircleButton circle1, circle2, circle3; -RectButton rect1, rect2; - -boolean locked = false; - -void setup() -{ - size(200, 200); - smooth(); - - color baseColor = color(102); - currentcolor = baseColor; - - // Define and create circle button - color buttoncolor = color(204); - color highlight = color(153); - ellipseMode(CENTER); - circle1 = new CircleButton(30, 100, 100, buttoncolor, highlight); - - // Define and create circle button - buttoncolor = color(204); - highlight = color(153); - circle2 = new CircleButton(130, 110, 24, buttoncolor, highlight); - - // Define and create circle button - buttoncolor = color(153); - highlight = color(102); - circle3 = new CircleButton(130, 140, 24, buttoncolor, highlight); - - // Define and create rectangle button - buttoncolor = color(102); - highlight = color(51); - rect1 = new RectButton(150, 20, 100, buttoncolor, highlight); - - // Define and create rectangle button - buttoncolor = color(51); - highlight = color(0); - rect2 = new RectButton(90, 20, 50, buttoncolor, highlight); -} - -void draw() -{ - background(currentcolor); - stroke(255); - update(mouseX, mouseY); - circle1.display(); - circle2.display(); - circle3.display(); - rect1.display(); - rect2.display(); -} - -void update(int x, int y) -{ - if(locked == false) { - circle1.update(); - circle2.update(); - circle3.update(); - rect1.update(); - rect2.update(); - } - else { - locked = false; - } - - if(mousePressed) { - if(circle1.pressed()) { - currentcolor = circle1.basecolor; - } - else if(circle2.pressed()) { - currentcolor = circle2.basecolor; - } - else if(circle3.pressed()) { - currentcolor = circle3.basecolor; - } - else if(rect1.pressed()) { - currentcolor = rect1.basecolor; - } - else if(rect2.pressed()) { - currentcolor = rect2.basecolor; - } - } -} - - -class Button -{ - int x, y; - int size; - color basecolor, highlightcolor; - color currentcolor; - boolean over = false; - boolean pressed = false; - - void update() - { - if(over()) { - currentcolor = highlightcolor; - } - else { - currentcolor = basecolor; - } - } - - boolean pressed() - { - if(over) { - locked = true; - return true; - } - else { - locked = false; - return false; - } - } - - boolean over() - { - return true; - } - - boolean overRect(int x, int y, int width, int height) - { - if (mouseX >= x && mouseX <= x+width && - mouseY >= y && mouseY <= y+height) { - return true; - } - else { - return false; - } - } - - boolean overCircle(int x, int y, int diameter) - { - float disX = x - mouseX; - float disY = y - mouseY; - if(sqrt(sq(disX) + sq(disY)) < diameter/2 ) { - return true; - } - else { - return false; - } - } - -} - -class CircleButton extends Button -{ - CircleButton(int ix, int iy, int isize, color icolor, color ihighlight) - { - x = ix; - y = iy; - size = isize; - basecolor = icolor; - highlightcolor = ihighlight; - currentcolor = basecolor; - } - - boolean over() - { - if( overCircle(x, y, size) ) { - over = true; - return true; - } - else { - over = false; - return false; - } - } - - void display() - { - stroke(255); - fill(currentcolor); - ellipse(x, y, size, size); - } -} - -class RectButton extends Button -{ - RectButton(int ix, int iy, int isize, color icolor, color ihighlight) - { - x = ix; - y = iy; - size = isize; - basecolor = icolor; - highlightcolor = ihighlight; - currentcolor = basecolor; - } - - boolean over() - { - if( overRect(x, y, size, size) ) { - over = true; - return true; - } - else { - over = false; - return false; - } - } - - void display() - { - stroke(255); - fill(currentcolor); - rect(x, y, size, size); - } -} - diff --git a/mode/examples/Topics/GUI/Handles/Handles.pde b/mode/examples/Topics/GUI/Handles/Handles.pde deleted file mode 100644 index 7036f362a..000000000 --- a/mode/examples/Topics/GUI/Handles/Handles.pde +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Handles. - * - * Click and drag the white boxes to change their position. - */ - -Handle[] handles; -int num; - -void setup() -{ - size(200, 200); - num = height/15; - handles = new Handle[num]; - int hsize = 10; - for(int i=0; i= x && mouseX <= x+width && - mouseY >= y && mouseY <= y+height) { - return true; - } else { - return false; - } -} - -int lock(int val, int minv, int maxv) -{ - return min(max(val, minv), maxv); -} diff --git a/mode/examples/Topics/GUI/ImageButton/ImageButton.pde b/mode/examples/Topics/GUI/ImageButton/ImageButton.pde deleted file mode 100644 index 338cb3d1e..000000000 --- a/mode/examples/Topics/GUI/ImageButton/ImageButton.pde +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Image button. - * - * Loading images and using them to create a button. - */ - - -ImageButtons button; - -void setup() -{ - size(200, 200); - background(102, 102, 102); - - // Define and create image button - PImage b = loadImage("base.gif"); - PImage r = loadImage("roll.gif"); - PImage d = loadImage("down.gif"); - int x = width/2 - b.width/2; - int y = height/2 - b.height/2; - int w = b.width; - int h = b.height; - button = new ImageButtons(x, y, w, h, b, r, d); -} - -void draw() -{ - button.update(); - button.display(); -} - -class Button -{ - int x, y; - int w, h; - color basecolor, highlightcolor; - color currentcolor; - boolean over = false; - boolean pressed = false; - - void pressed() { - if(over && mousePressed) { - pressed = true; - } else { - pressed = false; - } - } - - boolean overRect(int x, int y, int width, int height) { - if (mouseX >= x && mouseX <= x+width && - mouseY >= y && mouseY <= y+height) { - return true; - } else { - return false; - } -} -} - -class ImageButtons extends Button -{ - PImage base; - PImage roll; - PImage down; - PImage currentimage; - - ImageButtons(int ix, int iy, int iw, int ih, PImage ibase, PImage iroll, PImage idown) - { - x = ix; - y = iy; - w = iw; - h = ih; - base = ibase; - roll = iroll; - down = idown; - currentimage = base; - } - - void update() - { - over(); - pressed(); - if(pressed) { - currentimage = down; - } else if (over){ - currentimage = roll; - } else { - currentimage = base; - } - } - - void over() - { - if( overRect(x, y, w, h) ) { - over = true; - } else { - over = false; - } - } - - void display() - { - image(currentimage, x, y); - } -} - - - - diff --git a/mode/examples/Topics/GUI/ImageButton/data/base.gif b/mode/examples/Topics/GUI/ImageButton/data/base.gif deleted file mode 100644 index 8d7603a01..000000000 Binary files a/mode/examples/Topics/GUI/ImageButton/data/base.gif and /dev/null differ diff --git a/mode/examples/Topics/GUI/ImageButton/data/down.gif b/mode/examples/Topics/GUI/ImageButton/data/down.gif deleted file mode 100644 index 7e4f44155..000000000 Binary files a/mode/examples/Topics/GUI/ImageButton/data/down.gif and /dev/null differ diff --git a/mode/examples/Topics/GUI/ImageButton/data/roll.gif b/mode/examples/Topics/GUI/ImageButton/data/roll.gif deleted file mode 100644 index 7e2a1bc2e..000000000 Binary files a/mode/examples/Topics/GUI/ImageButton/data/roll.gif and /dev/null differ diff --git a/mode/examples/Topics/GUI/Rollover/Rollover.pde b/mode/examples/Topics/GUI/Rollover/Rollover.pde deleted file mode 100644 index 4785ec9ac..000000000 --- a/mode/examples/Topics/GUI/Rollover/Rollover.pde +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Rollover. - * - * Roll over the colored squares in the center of the image - * to change the color of the outside rectangle. - */ - - -int rectX, rectY; // Position of square button -int circleX, circleY; // Position of circle button -int rectSize = 50; // Diameter of rect -int circleSize = 53; // Diameter of circle - -color rectColor; -color circleColor; -color baseColor; - -boolean rectOver = false; -boolean circleOver = false; - -void setup() -{ - size(200, 200); - smooth(); - rectColor = color(0); - circleColor = color(255); - baseColor = color(102); - circleX = width/2+circleSize/2+10; - circleY = height/2; - rectX = width/2-rectSize-10; - rectY = height/2-rectSize/2; - ellipseMode(CENTER); -} - -void draw() -{ - update(mouseX, mouseY); - - noStroke(); - if (rectOver) { - background(rectColor); - } else if (circleOver) { - background(circleColor); - } else { - background(baseColor); - } - - stroke(255); - fill(rectColor); - rect(rectX, rectY, rectSize, rectSize); - stroke(0); - fill(circleColor); - ellipse(circleX, circleY, circleSize, circleSize); -} - -void update(int x, int y) -{ - if( overCircle(circleX, circleY, circleSize) ) { - circleOver = true; - rectOver = false; - } else if ( overRect(rectX, rectY, rectSize, rectSize) ) { - rectOver = true; - circleOver = false; - } else { - circleOver = rectOver = false; - } -} - -boolean overRect(int x, int y, int width, int height) -{ - if (mouseX >= x && mouseX <= x+width && - mouseY >= y && mouseY <= y+height) { - return true; - } else { - return false; - } -} - -boolean overCircle(int x, int y, int diameter) -{ - float disX = x - mouseX; - float disY = y - mouseY; - if(sqrt(sq(disX) + sq(disY)) < diameter/2 ) { - return true; - } else { - return false; - } -} diff --git a/mode/examples/Topics/GUI/Scrollbar/Scrollbar.pde b/mode/examples/Topics/GUI/Scrollbar/Scrollbar.pde deleted file mode 100644 index 4647b6095..000000000 --- a/mode/examples/Topics/GUI/Scrollbar/Scrollbar.pde +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Scrollbar. - * - * Move the scrollbars left and right to change the positions of the images. - */ - -HScrollbar hs1, hs2; - -PImage top, bottom; // Two image to load -int topWidth, bottomWidth; // The width of the top and bottom images - - -void setup() -{ - size(200, 200); - noStroke(); - hs1 = new HScrollbar(0, 20, width, 10, 3*5+1); - hs2 = new HScrollbar(0, height-20, width, 10, 3*5+1); - top = loadImage("seedTop.jpg"); - topWidth = top.width; - bottom = loadImage("seedBottom.jpg"); - bottomWidth = bottom.width; -} - -void draw() -{ - background(255); - - // Get the position of the top scrollbar - // and convert to a value to display the top image - float topPos = hs1.getPos()-width/2; - fill(255); - image(top, width/2-topWidth/2 + topPos*2, 0); - - // Get the position of the bottom scrollbar - // and convert to a value to display the bottom image - float bottomPos = hs2.getPos()-width/2; - fill(255); - image(bottom, width/2-bottomWidth/2 + bottomPos*2, height/2); - - hs1.update(); - hs2.update(); - hs1.display(); - hs2.display(); -} - - -class HScrollbar -{ - int swidth, sheight; // width and height of bar - int xpos, ypos; // x and y position of bar - float spos, newspos; // x position of slider - int sposMin, sposMax; // max and min values of slider - int loose; // how loose/heavy - boolean over; // is the mouse over the slider? - boolean locked; - float ratio; - - HScrollbar (int xp, int yp, int sw, int sh, int l) { - swidth = sw; - sheight = sh; - int widthtoheight = sw - sh; - ratio = (float)sw / (float)widthtoheight; - xpos = xp; - ypos = yp-sheight/2; - spos = xpos + swidth/2 - sheight/2; - newspos = spos; - sposMin = xpos; - sposMax = xpos + swidth - sheight; - loose = l; - } - - void update() { - if(over()) { - over = true; - } else { - over = false; - } - if(mousePressed && over) { - locked = true; - } - if(!mousePressed) { - locked = false; - } - if(locked) { - newspos = constrain(mouseX-sheight/2, sposMin, sposMax); - } - if(abs(newspos - spos) > 1) { - spos = spos + (newspos-spos)/loose; - } - } - - int constrain(int val, int minv, int maxv) { - return min(max(val, minv), maxv); - } - - boolean over() { - if(mouseX > xpos && mouseX < xpos+swidth && - mouseY > ypos && mouseY < ypos+sheight) { - return true; - } else { - return false; - } - } - - void display() { - fill(255); - rect(xpos, ypos, swidth, sheight); - if(over || locked) { - fill(153, 102, 0); - } else { - fill(102, 102, 102); - } - rect(spos, ypos, sheight, sheight); - } - - float getPos() { - // Convert spos to be values between - // 0 and the total width of the scrollbar - return spos * ratio; - } -} diff --git a/mode/examples/Topics/GUI/Scrollbar/data/seedBottom.jpg b/mode/examples/Topics/GUI/Scrollbar/data/seedBottom.jpg deleted file mode 100644 index dd98337c9..000000000 Binary files a/mode/examples/Topics/GUI/Scrollbar/data/seedBottom.jpg and /dev/null differ diff --git a/mode/examples/Topics/GUI/Scrollbar/data/seedTop.jpg b/mode/examples/Topics/GUI/Scrollbar/data/seedTop.jpg deleted file mode 100644 index 62af546c3..000000000 Binary files a/mode/examples/Topics/GUI/Scrollbar/data/seedTop.jpg and /dev/null differ diff --git a/mode/examples/Topics/Geometry/Icosahedra/Dimension3D.pde b/mode/examples/Topics/Geometry/Icosahedra/Dimension3D.pde deleted file mode 100644 index 90c949967..000000000 --- a/mode/examples/Topics/Geometry/Icosahedra/Dimension3D.pde +++ /dev/null @@ -1,10 +0,0 @@ -class Dimension3D{ - float w, h, d; - - Dimension3D(float w, float h, float d){ - this.w=w; - this.h=h; - this.d=d; - } -} - diff --git a/mode/examples/Topics/Geometry/Icosahedra/Icosahedra.pde b/mode/examples/Topics/Geometry/Icosahedra/Icosahedra.pde deleted file mode 100644 index 8d318c7ce..000000000 --- a/mode/examples/Topics/Geometry/Icosahedra/Icosahedra.pde +++ /dev/null @@ -1,53 +0,0 @@ -/** - * I Like Icosahedra - * by Ira Greenberg. - * - * This example plots icosahedra. The Icosahdron is a regular - * polyhedron composed of twenty equalateral triangles. - */ - -Icosahedron ico1; -Icosahedron ico2; -Icosahedron ico3; - -void setup(){ - size(640, 360, P3D); - orientation(LANDSCAPE); - ico1 = new Icosahedron(75); - ico2 = new Icosahedron(75); - ico3 = new Icosahedron(75); -} - -void draw(){ - background(0); - lights(); - translate(width/2, height/2); - - pushMatrix(); - translate(-width/3.5, 0); - rotateX(frameCount*PI/185); - rotateY(frameCount*PI/-200); - stroke(170, 0, 0); - noFill(); - ico1.create(); - popMatrix(); - - pushMatrix(); - rotateX(frameCount*PI/200); - rotateY(frameCount*PI/300); - stroke(150, 0, 180); - fill(170, 170, 0); - ico2.create(); - popMatrix(); - - pushMatrix(); - translate(width/3.5, 0); - rotateX(frameCount*PI/-200); - rotateY(frameCount*PI/200); - noStroke(); - fill(0, 0, 185); - ico3.create(); - popMatrix(); -} - - diff --git a/mode/examples/Topics/Geometry/Icosahedra/Icosahedron.pde b/mode/examples/Topics/Geometry/Icosahedra/Icosahedron.pde deleted file mode 100644 index 3a7f89453..000000000 --- a/mode/examples/Topics/Geometry/Icosahedra/Icosahedron.pde +++ /dev/null @@ -1,159 +0,0 @@ -class Icosahedron extends Shape3D{ - - // icosahedron - PVector topPoint; - PVector[] topPent = new PVector[5]; - PVector bottomPoint; - PVector[] bottomPent = new PVector[5]; - float angle = 0, radius = 150; - float triDist; - float triHt; - float a, b, c; - - // constructor - Icosahedron(float radius){ - this.radius = radius; - init(); - } - - Icosahedron(PVector v, float radius){ - super(v); - this.radius = radius; - init(); - } - - // calculate geometry - void init(){ - c = dist(cos(0)*radius, sin(0)*radius, cos(radians(72))*radius, sin(radians(72))*radius); - b = radius; - a = (float)(Math.sqrt(((c*c)-(b*b)))); - - triHt = (float)(Math.sqrt((c*c)-((c/2)*(c/2)))); - - for (int i=0; i 0.01) { xmag -= diff/4.0; } - - diff = ymag-newYmag; - if (abs(diff) > 0.01) { ymag -= diff/4.0; } - - rotateX(-ymag); - rotateY(-xmag); - - scale(90); - beginShape(QUADS); - - fill(0, 1, 1); vertex(-1, 1, 1); - fill(1, 1, 1); vertex( 1, 1, 1); - fill(1, 0, 1); vertex( 1, -1, 1); - fill(0, 0, 1); vertex(-1, -1, 1); - - fill(1, 1, 1); vertex( 1, 1, 1); - fill(1, 1, 0); vertex( 1, 1, -1); - fill(1, 0, 0); vertex( 1, -1, -1); - fill(1, 0, 1); vertex( 1, -1, 1); - - fill(1, 1, 0); vertex( 1, 1, -1); - fill(0, 1, 0); vertex(-1, 1, -1); - fill(0, 0, 0); vertex(-1, -1, -1); - fill(1, 0, 0); vertex( 1, -1, -1); - - fill(0, 1, 0); vertex(-1, 1, -1); - fill(0, 1, 1); vertex(-1, 1, 1); - fill(0, 0, 1); vertex(-1, -1, 1); - fill(0, 0, 0); vertex(-1, -1, -1); - - fill(0, 1, 0); vertex(-1, 1, -1); - fill(1, 1, 0); vertex( 1, 1, -1); - fill(1, 1, 1); vertex( 1, 1, 1); - fill(0, 1, 1); vertex(-1, 1, 1); - - fill(0, 0, 0); vertex(-1, -1, -1); - fill(1, 0, 0); vertex( 1, -1, -1); - fill(1, 0, 1); vertex( 1, -1, 1); - fill(0, 0, 1); vertex(-1, -1, 1); - - endShape(); - - popMatrix(); -} diff --git a/mode/examples/Topics/Geometry/ShapeTransform/ShapeTransform.pde b/mode/examples/Topics/Geometry/ShapeTransform/ShapeTransform.pde deleted file mode 100644 index 5e17a543d..000000000 --- a/mode/examples/Topics/Geometry/ShapeTransform/ShapeTransform.pde +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Shape Transform - * by Ira Greenberg. - * - * Illustrates the geometric relationship - * between Cube, Pyramid, Cone and - * Cylinder 3D primitives. - * - * Instructions:
    - * tap rigth side of screen - increases points
    - * tap left side of screen - decreases points
    - * tap screen center toggles between cube/pyramid
    - */ - -int pts = 4; -float angle = 0; -float radius = 99; -float cylinderLength = 95; - -//vertices -PVector vertices[][]; -boolean isPyramid = false; - -float angleInc; - -void setup(){ - size(displayWidth, displayHeight, P3D); - orientation(LANDSCAPE); - noStroke(); - angleInc = PI/300.0; -} - -void draw(){ - background(170, 95, 95); - lights(); - fill(255, 200, 200); - translate(width/2, height/2); - rotateX(frameCount * angleInc); - rotateY(frameCount * angleInc); - rotateZ(frameCount * angleInc); - - // initialize vertex arrays - vertices = new PVector[2][pts+1]; - - // fill arrays - for (int i = 0; i < 2; i++){ - angle = 0; - for(int j = 0; j <= pts; j++){ - vertices[i][j] = new PVector(); - if (isPyramid){ - if (i==1){ - vertices[i][j].x = 0; - vertices[i][j].y = 0; - } - else { - vertices[i][j].x = cos(radians(angle)) * radius; - vertices[i][j].y = sin(radians(angle)) * radius; - } - } - else { - vertices[i][j].x = cos(radians(angle)) * radius; - vertices[i][j].y = sin(radians(angle)) * radius; - } - vertices[i][j].z = cylinderLength; - // the .0 after the 360 is critical - angle += 360.0/pts; - } - cylinderLength *= -1; - } - - // draw cylinder tube - beginShape(QUAD_STRIP); - for(int j = 0; j <= pts; j++){ - vertex(vertices[0][j].x, vertices[0][j].y, vertices[0][j].z); - vertex(vertices[1][j].x, vertices[1][j].y, vertices[1][j].z); - } - endShape(); - - //draw cylinder ends - for (int i = 0; i < 2; i++){ - beginShape(); - for(int j = 0; j < pts; j++){ - vertex(vertices[i][j].x, vertices[i][j].y, vertices[i][j].z); - } - endShape(CLOSE); - } -} - - -/* - tapping controls polygon detail. - */ -void mousePressed(){ - if (abs(mouseX - width/2) < 50 && - abs(mouseY - height/2) < 50) { - if (isPyramid){ - isPyramid = false; - } - else { - isPyramid = true; - } - } else if (mouseX < width/2) { - if (pts > 4){ - pts--; - } - } else if (mouseX > width/2) { - if (pts < 90){ - pts++; - } - } -} - diff --git a/mode/examples/Topics/Geometry/SpaceJunk/Cube.pde b/mode/examples/Topics/Geometry/SpaceJunk/Cube.pde deleted file mode 100644 index 121b33f9b..000000000 --- a/mode/examples/Topics/Geometry/SpaceJunk/Cube.pde +++ /dev/null @@ -1,67 +0,0 @@ - -class Cube { - - // Properties - int w, h, d; - int shiftX, shiftY, shiftZ; - - // Constructor - Cube(int w, int h, int d, int shiftX, int shiftY, int shiftZ){ - this.w = w; - this.h = h; - this.d = d; - this.shiftX = shiftX; - this.shiftY = shiftY; - this.shiftZ = shiftZ; - } - - // Main cube drawing method, which looks - // more confusing than it really is. It's - // just a bunch of rectangles drawn for - // each cube face - void drawCube(){ - beginShape(QUADS); - // Front face - vertex(-w/2 + shiftX, -h/2 + shiftY, -d/2 + shiftZ); - vertex(w + shiftX, -h/2 + shiftY, -d/2 + shiftZ); - vertex(w + shiftX, h + shiftY, -d/2 + shiftZ); - vertex(-w/2 + shiftX, h + shiftY, -d/2 + shiftZ); - - // Back face - vertex(-w/2 + shiftX, -h/2 + shiftY, d + shiftZ); - vertex(w + shiftX, -h/2 + shiftY, d + shiftZ); - vertex(w + shiftX, h + shiftY, d + shiftZ); - vertex(-w/2 + shiftX, h + shiftY, d + shiftZ); - - // Left face - vertex(-w/2 + shiftX, -h/2 + shiftY, -d/2 + shiftZ); - vertex(-w/2 + shiftX, -h/2 + shiftY, d + shiftZ); - vertex(-w/2 + shiftX, h + shiftY, d + shiftZ); - vertex(-w/2 + shiftX, h + shiftY, -d/2 + shiftZ); - - // Right face - vertex(w + shiftX, -h/2 + shiftY, -d/2 + shiftZ); - vertex(w + shiftX, -h/2 + shiftY, d + shiftZ); - vertex(w + shiftX, h + shiftY, d + shiftZ); - vertex(w + shiftX, h + shiftY, -d/2 + shiftZ); - - // Top face - vertex(-w/2 + shiftX, -h/2 + shiftY, -d/2 + shiftZ); - vertex(w + shiftX, -h/2 + shiftY, -d/2 + shiftZ); - vertex(w + shiftX, -h/2 + shiftY, d + shiftZ); - vertex(-w/2 + shiftX, -h/2 + shiftY, d + shiftZ); - - // Bottom face - vertex(-w/2 + shiftX, h + shiftY, -d/2 + shiftZ); - vertex(w + shiftX, h + shiftY, -d/2 + shiftZ); - vertex(w + shiftX, h + shiftY, d + shiftZ); - vertex(-w/2 + shiftX, h + shiftY, d + shiftZ); - - endShape(); - - // Add some rotation to each box for pizazz. - rotateY(radians(1)); - rotateX(radians(1)); - rotateZ(radians(1)); - } -} diff --git a/mode/examples/Topics/Geometry/SpaceJunk/SpaceJunk.pde b/mode/examples/Topics/Geometry/SpaceJunk/SpaceJunk.pde deleted file mode 100644 index 6d8bd944d..000000000 --- a/mode/examples/Topics/Geometry/SpaceJunk/SpaceJunk.pde +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Space Junk - * by Ira Greenberg (zoom suggestion by Danny Greenberg). - * - * Rotating cubes in space using a custom Cube class. - * Color controlled by light sources. Move the mouse left - * and right to zoom. - */ - -// Used for oveall rotation -float ang; - -// Cube count-lower/raise to test performance -int limit = 100; - -// Array for all cubes -Cube[]cubes = new Cube[limit]; - -void setup() { - size(displayWidth, displayHeight, P3D); - background(0); - noStroke(); - - // Instantiate cubes, passing in random vals for size and postion - for (int i = 0; i< cubes.length; i++){ - cubes[i] = new Cube(int(random(-10, 10)), int(random(-10, 10)), - int(random(-10, 10)), int(random(-140, 140)), - int(random(-140, 140)), int(random(-140, 140))); - } -} - -void draw(){ - background(0); - fill(200); - - // Set up some different colored lights - pointLight(51, 102, 255, 65, 60, 100); - pointLight(200, 40, 60, -65, -60, -150); - - // Raise overall light in scene - ambientLight(70, 70, 10); - - // Center geometry in display windwow. - // you can change 3rd argument ('0') - // to move block group closer(+)/further(-) - translate(width/2, height/2, -200 + mouseX * 0.65); - - // Rotate around y and x axes - rotateY(radians(ang)); - rotateX(radians(ang)); - - // Draw cubes - for (int i = 0; i < cubes.length; i++){ - cubes[i].drawCube(); - } - - // Used in rotate function calls above - ang += 0.2; -} - - diff --git a/mode/examples/Topics/Geometry/Toroid/Toroid.pde b/mode/examples/Topics/Geometry/Toroid/Toroid.pde deleted file mode 100644 index a085e8159..000000000 --- a/mode/examples/Topics/Geometry/Toroid/Toroid.pde +++ /dev/null @@ -1,183 +0,0 @@ -/** - * Interactive Toroid - * by Ira Greenberg. - * - * Illustrates the geometric relationship between Toroid, Sphere, and Helix - * 3D primitives, as well as lathing principal. - * - * Instructions:
    - * UP arrow key pts++
    - * DOWN arrow key pts--
    - * LEFT arrow key segments--
    - * RIGHT arrow key segments++
    - * 'a' key toroid radius--
    - * 's' key toroid radius++
    - * 'z' key initial polygon radius--
    - * 'x' key initial polygon radius++
    - * 'w' key toggle wireframe/solid shading
    - * 'h' key toggle sphere/helix
    - */ - -int pts = 40; -float angle = 0; -float radius = 60.0; - -// lathe segments -int segments = 60; -float latheAngle = 0; -float latheRadius = 100.0; - -//vertices -PVector vertices[], vertices2[]; - -// for shaded or wireframe rendering -boolean isWireFrame = false; - -// for optional helix -boolean isHelix = false; -float helixOffset = 5.0; - -void setup(){ - size(640, 360, P3D); - orientation(LANDSCAPE); -} - -void draw(){ - background(50, 64, 42); - // basic lighting setup - lights(); - // 2 rendering styles - // wireframe or solid - if (isWireFrame){ - stroke(255, 255, 150); - noFill(); - } - else { - noStroke(); - fill(150, 195, 125); - } - //center and spin toroid - translate(width/2, height/2, -100); - - rotateX(frameCount*PI/150); - rotateY(frameCount*PI/170); - rotateZ(frameCount*PI/90); - - // initialize point arrays - vertices = new PVector[pts+1]; - vertices2 = new PVector[pts+1]; - - // fill arrays - for(int i=0; i<=pts; i++){ - vertices[i] = new PVector(); - vertices2[i] = new PVector(); - vertices[i].x = latheRadius + sin(radians(angle))*radius; - if (isHelix){ - vertices[i].z = cos(radians(angle))*radius-(helixOffset* - segments)/2; - } - else{ - vertices[i].z = cos(radians(angle))*radius; - } - angle+=360.0/pts; - } - - // draw toroid - latheAngle = 0; - for(int i=0; i<=segments; i++){ - beginShape(QUAD_STRIP); - for(int j=0; j<=pts; j++){ - if (i>0){ - vertex(vertices2[j].x, vertices2[j].y, vertices2[j].z); - } - vertices2[j].x = cos(radians(latheAngle))*vertices[j].x; - vertices2[j].y = sin(radians(latheAngle))*vertices[j].x; - vertices2[j].z = vertices[j].z; - // optional helix offset - if (isHelix){ - vertices[j].z+=helixOffset; - } - vertex(vertices2[j].x, vertices2[j].y, vertices2[j].z); - } - // create extra rotation for helix - if (isHelix){ - latheAngle+=720.0/segments; - } - else { - latheAngle+=360.0/segments; - } - endShape(); - } -} - -/* - left/right arrow keys control ellipse detail - up/down arrow keys control segment detail. - 'a','s' keys control lathe radius - 'z','x' keys control ellipse radius - 'w' key toggles between wireframe and solid - 'h' key toggles between toroid and helix - */ -void keyPressed(){ - if(key == CODED) { - // pts - if (keyCode == UP) { - if (pts<40){ - pts++; - } - } - else if (keyCode == DOWN) { - if (pts>3){ - pts--; - } - } - // extrusion length - if (keyCode == LEFT) { - if (segments>3){ - segments--; - } - } - else if (keyCode == RIGHT) { - if (segments<80){ - segments++; - } - } - } - // lathe radius - if (key =='a'){ - if (latheRadius>0){ - latheRadius--; - } - } - else if (key == 's'){ - latheRadius++; - } - // ellipse radius - if (key =='z'){ - if (radius>10){ - radius--; - } - } - else if (key == 'x'){ - radius++; - } - // wireframe - if (key =='w'){ - if (isWireFrame){ - isWireFrame=false; - } - else { - isWireFrame=true; - } - } - // helix - if (key =='h'){ - if (isHelix){ - isHelix=false; - } - else { - isHelix=true; - } - } -} - diff --git a/mode/examples/Topics/Geometry/Vertices/Vertices.pde b/mode/examples/Topics/Geometry/Vertices/Vertices.pde deleted file mode 100644 index 4aae8eb51..000000000 --- a/mode/examples/Topics/Geometry/Vertices/Vertices.pde +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Vertices - * by Simon Greenwold. - * - * Draw a cylinder centered on the y-axis, going down - * from y=0 to y=height. The radius at the top can be - * different from the radius at the bottom, and the - * number of sides drawn is variable. - */ - -void setup() { - size(640, 360, P3D); - orientation(LANDSCAPE); -} - -void draw() { - background(0); - lights(); - translate(width / 2, height / 2); - rotateY(map(mouseX, 0, width, 0, PI)); - rotateZ(map(mouseY, 0, height, 0, -PI)); - noStroke(); - fill(255, 255, 255); - translate(0, -40, 0); - drawCylinder(10, 180, 200, 16); // Draw a mix between a cylinder and a cone - //drawCylinder(70, 70, 120, 64); // Draw a cylinder - //drawCylinder(0, 180, 200, 4); // Draw a pyramid -} - -void drawCylinder(float topRadius, float bottomRadius, float tall, int sides) { - float angle = 0; - float angleIncrement = TWO_PI / sides; - beginShape(QUAD_STRIP); - for (int i = 0; i < sides + 1; ++i) { - vertex(topRadius*cos(angle), 0, topRadius*sin(angle)); - vertex(bottomRadius*cos(angle), tall, bottomRadius*sin(angle)); - angle += angleIncrement; - } - endShape(); - - // If it is not a cone, draw the circular top cap - if (topRadius != 0) { - angle = 0; - beginShape(TRIANGLE_FAN); - - // Center point - vertex(0, 0, 0); - for (int i = 0; i < sides + 1; i++) { - vertex(topRadius * cos(angle), 0, topRadius * sin(angle)); - angle += angleIncrement; - } - endShape(); - } - - // If it is not a cone, draw the circular bottom cap - if (bottomRadius != 0) { - angle = 0; - beginShape(TRIANGLE_FAN); - - // Center point - vertex(0, tall, 0); - for (int i = 0; i < sides + 1; i++) { - vertex(bottomRadius * cos(angle), tall, bottomRadius * sin(angle)); - angle += angleIncrement; - } - endShape(); - } -} diff --git a/mode/examples/Topics/Image Processing/Blur/Blur.pde b/mode/examples/Topics/Image Processing/Blur/Blur.pde deleted file mode 100644 index 3eb7103d2..000000000 --- a/mode/examples/Topics/Image Processing/Blur/Blur.pde +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Blur. - * - * Bluring half of an image by processing it through a - * low-pass filter. - */ - -float v = 1.0/9.0; -float[][] kernel = { { v, v, v }, - { v, v, v }, - { v, v, v } }; - -size(200, 200); - -PImage img = loadImage("trees.jpg"); // Load the original image -image(img, 0, 0); // Displays the image from point (0,0) -img.loadPixels(); - -// Create an opaque image of the same size as the original -PImage edgeImg = createImage(img.width, img.height, RGB); -edgeImg.loadPixels(); - -// Loop through every pixel in the image. -for (int y = 1; y < img.height-1; y++) { // Skip top and bottom edges - for (int x = 1; x < img.width-1; x++) { // Skip left and right edges - float sum = 0; // Kernel sum for this pixel - for (int ky = -1; ky <= 1; ky++) { - for (int kx = -1; kx <= 1; kx++) { - // Calculate the adjacent pixel for this kernel point - int pos = (y + ky)*img.width + (x + kx); - // Image is grayscale, red/green/blue are identical - float val = red(img.pixels[pos]); - // Multiply adjacent pixels based on the kernel values - sum += kernel[ky+1][kx+1] * val; - } - } - // For this pixel in the new image, set the gray value - // based on the sum from the kernel - edgeImg.pixels[y*img.width + x] = color(sum); - } -} -// State that there are changes to edgeImg.pixels[] -edgeImg.updatePixels(); -image(edgeImg, 100, 0); // Draw the new image diff --git a/mode/examples/Topics/Image Processing/Blur/data/trees.jpg b/mode/examples/Topics/Image Processing/Blur/data/trees.jpg deleted file mode 100644 index afdcf5045..000000000 Binary files a/mode/examples/Topics/Image Processing/Blur/data/trees.jpg and /dev/null differ diff --git a/mode/examples/Topics/Image Processing/Brightness/Brightness.pde b/mode/examples/Topics/Image Processing/Brightness/Brightness.pde deleted file mode 100644 index 62cb644ff..000000000 --- a/mode/examples/Topics/Image Processing/Brightness/Brightness.pde +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Brightness - * by Daniel Shiffman. - * - * Adjusts the brightness of part of the image - * Pixels closer to the mouse will appear brighter. - */ - -PImage img; - -void setup() { - size(200, 200); - frameRate(30); - img = loadImage("wires.jpg"); - img.loadPixels(); - // Only need to load the pixels[] array once, because we're only - // manipulating pixels[] inside draw(), not drawing shapes. - loadPixels(); -} - -void draw() { - for (int x = 0; x < img.width; x++) { - for (int y = 0; y < img.height; y++ ) { - // Calculate the 1D location from a 2D grid - int loc = x + y*img.width; - // Get the R,G,B values from image - float r,g,b; - r = red (img.pixels[loc]); - //g = green (img.pixels[loc]); - //b = blue (img.pixels[loc]); - // Calculate an amount to change brightness based on proximity to the mouse - float maxdist = 50;//dist(0,0,width,height); - float d = dist(x,y,mouseX,mouseY); - float adjustbrightness = 255*(maxdist-d)/maxdist; - r += adjustbrightness; - //g += adjustbrightness; - //b += adjustbrightness; - // Constrain RGB to make sure they are within 0-255 color range - r = constrain(r,0,255); - //g = constrain(g,0,255); - //b = constrain(b,0,255); - // Make a new color and set pixel in the window - //color c = color(r,g,b); - color c = color(r); - pixels[y*width + x] = c; - } - } - updatePixels(); -} diff --git a/mode/examples/Topics/Image Processing/Brightness/data/wires.jpg b/mode/examples/Topics/Image Processing/Brightness/data/wires.jpg deleted file mode 100644 index a0a6e24dd..000000000 Binary files a/mode/examples/Topics/Image Processing/Brightness/data/wires.jpg and /dev/null differ diff --git a/mode/examples/Topics/Image Processing/Convolution/Convolution.pde b/mode/examples/Topics/Image Processing/Convolution/Convolution.pde deleted file mode 100644 index 5640c89b1..000000000 --- a/mode/examples/Topics/Image Processing/Convolution/Convolution.pde +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Convolution - * by Daniel Shiffman. - * - * Applies a convolution matrix to a portion of the index. - * Move mouse to apply filter to different parts of the image. - */ - -PImage img; -int w = 80; - -// It's possible to convolve the image with -// many different matrices - - float[][] matrix = { { -1, -1, -1 }, - { -1, 9, -1 }, - { -1, -1, -1 } }; - -void setup() { - size(200, 200); - frameRate(30); - img = loadImage("end.jpg"); - img.loadPixels(); -} - -void draw() { - // We're only going to process a portion of the image - // so let's set the whole image as the background first - image(img,0,0); - // Where is the small rectangle we will process - int xstart = constrain(mouseX-w/2,0,img.width); - int ystart = constrain(mouseY-w/2,0,img.height); - int xend = constrain(mouseX+w/2,0,img.width); - int yend = constrain(mouseY+w/2,0,img.height); - int matrixsize = 3; - loadPixels(); - // Begin our loop for every pixel - for (int x = xstart; x < xend; x++) { - for (int y = ystart; y < yend; y++ ) { - color c = convolution(x,y,matrix,matrixsize,img); - int loc = x + y*img.width; - pixels[loc] = c; - } - } - updatePixels(); -} - -color convolution(int x, int y, float[][] matrix,int matrixsize, PImage img) -{ - float rtotal = 0.0; - float gtotal = 0.0; - float btotal = 0.0; - int offset = matrixsize / 2; - for (int i = 0; i < matrixsize; i++){ - for (int j= 0; j < matrixsize; j++){ - // What pixel are we testing - int xloc = x+i-offset; - int yloc = y+j-offset; - int loc = xloc + img.width*yloc; - // Make sure we haven't walked off our image, we could do better here - loc = constrain(loc,0,img.pixels.length-1); - // Calculate the convolution - rtotal += (red(img.pixels[loc]) * matrix[i][j]); - gtotal += (green(img.pixels[loc]) * matrix[i][j]); - btotal += (blue(img.pixels[loc]) * matrix[i][j]); - } - } - // Make sure RGB is within range - rtotal = constrain(rtotal,0,255); - gtotal = constrain(gtotal,0,255); - btotal = constrain(btotal,0,255); - // Return the resulting color - return color(rtotal,gtotal,btotal); -} - diff --git a/mode/examples/Topics/Image Processing/Convolution/data/end.jpg b/mode/examples/Topics/Image Processing/Convolution/data/end.jpg deleted file mode 100644 index 32935763a..000000000 Binary files a/mode/examples/Topics/Image Processing/Convolution/data/end.jpg and /dev/null differ diff --git a/mode/examples/Topics/Image Processing/Convolution/data/sunflower.jpg b/mode/examples/Topics/Image Processing/Convolution/data/sunflower.jpg deleted file mode 100644 index 88398d188..000000000 Binary files a/mode/examples/Topics/Image Processing/Convolution/data/sunflower.jpg and /dev/null differ diff --git a/mode/examples/Topics/Image Processing/EdgeDetection/EdgeDetection.pde b/mode/examples/Topics/Image Processing/EdgeDetection/EdgeDetection.pde deleted file mode 100644 index 1f1f24a43..000000000 --- a/mode/examples/Topics/Image Processing/EdgeDetection/EdgeDetection.pde +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Edge Detection. - * - * Exposing areas of contrast within an image - * by processing it through a high-pass filter. - */ - -float[][] kernel = { { -1, -1, -1 }, - { -1, 9, -1 }, - { -1, -1, -1 } }; - -size(200, 200); -PImage img = loadImage("house.jpg"); // Load the original image -image(img, 0, 0); // Displays the image from point (0,0) -img.loadPixels(); -// Create an opaque image of the same size as the original -PImage edgeImg = createImage(img.width, img.height, RGB); -// Loop through every pixel in the image. -for (int y = 1; y < img.height-1; y++) { // Skip top and bottom edges - for (int x = 1; x < img.width-1; x++) { // Skip left and right edges - float sum = 0; // Kernel sum for this pixel - for (int ky = -1; ky <= 1; ky++) { - for (int kx = -1; kx <= 1; kx++) { - // Calculate the adjacent pixel for this kernel point - int pos = (y + ky)*img.width + (x + kx); - // Image is grayscale, red/green/blue are identical - float val = red(img.pixels[pos]); - // Multiply adjacent pixels based on the kernel values - sum += kernel[ky+1][kx+1] * val; - } - } - // For this pixel in the new image, set the gray value - // based on the sum from the kernel - edgeImg.pixels[y*img.width + x] = color(sum); - } -} -// State that there are changes to edgeImg.pixels[] -edgeImg.updatePixels(); -image(edgeImg, 100, 0); // Draw the new image diff --git a/mode/examples/Topics/Image Processing/EdgeDetection/data/house.jpg b/mode/examples/Topics/Image Processing/EdgeDetection/data/house.jpg deleted file mode 100644 index c6d311fd1..000000000 Binary files a/mode/examples/Topics/Image Processing/EdgeDetection/data/house.jpg and /dev/null differ diff --git a/mode/examples/Topics/Image Processing/Histogram/Histogram.pde b/mode/examples/Topics/Image Processing/Histogram/Histogram.pde deleted file mode 100644 index f5f7d49eb..000000000 --- a/mode/examples/Topics/Image Processing/Histogram/Histogram.pde +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Histogram. - * - * Calculates the histogram of an image. - * A histogram is the frequency distribution - * of the gray levels with the number of pure black values - * displayed on the left and number of pure white values on the right. - * - * Updated 28 February, 2010. - * Note that this sketch will behave differently on Android, - * since most images will no longer be full 24-bit color. - */ - -size(200, 200); - -// Load an image from the data directory -// Load a different image by modifying the comments -PImage img = loadImage("cdi01_g.jpg"); -image(img, 0, 0); -int[] hist = new int[256]; - -// Calculate the histogram -for (int i = 0; i < img.width; i++) { - for (int j = 0; j < img.height; j++) { - int bright = int(brightness(get(i, j))); - hist[bright]++; - } -} - -// Find the largest value in the histogram -int histMax = max(hist); - -stroke(255); -// Draw half of the histogram (skip every second value) -for (int i = 0; i < img.width; i += 2) { - // Map i (from 0..img.width-1) to a location in the histogram (0..255) - int which = int(map(i, 0, img.width, 0, 255)); - // Convert the histogram value to a location between - // the bottom and the top of the picture - int y = int(map(hist[which], 0, histMax, img.height, 0)); - line(i, img.height, i, y); -} diff --git a/mode/examples/Topics/Image Processing/Histogram/data/cdi01_g.jpg b/mode/examples/Topics/Image Processing/Histogram/data/cdi01_g.jpg deleted file mode 100644 index 78ce58f4c..000000000 Binary files a/mode/examples/Topics/Image Processing/Histogram/data/cdi01_g.jpg and /dev/null differ diff --git a/mode/examples/Topics/Image Processing/Histogram/data/ystone08.jpg b/mode/examples/Topics/Image Processing/Histogram/data/ystone08.jpg deleted file mode 100644 index 5428ada88..000000000 Binary files a/mode/examples/Topics/Image Processing/Histogram/data/ystone08.jpg and /dev/null differ diff --git a/mode/examples/Topics/Image Processing/LinearImage/LinearImage.pde b/mode/examples/Topics/Image Processing/LinearImage/LinearImage.pde deleted file mode 100644 index b7c52de5e..000000000 --- a/mode/examples/Topics/Image Processing/LinearImage/LinearImage.pde +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Linear Image. - * - * Click and drag mouse up and down to control the signal. - * Press and hold any key to watch the scanning. - * - * Updated 28 February 2010. - */ - -PImage img; -int direction = 1; - -float signal; - -void setup() { - size(200, 200); - stroke(255); - img = loadImage("florence03.jpg"); - img.loadPixels(); - loadPixels(); -} - -void draw() { - if (signal > img.height-1 || signal < 0) { - direction = direction * -1; - } - if (mousePressed) { - signal = abs(mouseY % img.height); - } else { - signal += (0.3*direction); - } - - if (keyPressed) { - set(0, 0, img); - line(0, signal, img.width, signal); - } else { - int signalOffset = int(signal)*img.width; - for (int y = 0; y < img.height; y++) { - arrayCopy(img.pixels, signalOffset, pixels, y*width, img.width); - } - updatePixels(); - } -} diff --git a/mode/examples/Topics/Image Processing/LinearImage/data/florence03.jpg b/mode/examples/Topics/Image Processing/LinearImage/data/florence03.jpg deleted file mode 100644 index ec33b266a..000000000 Binary files a/mode/examples/Topics/Image Processing/LinearImage/data/florence03.jpg and /dev/null differ diff --git a/mode/examples/Topics/Image Processing/PixelArray/PixelArray.pde b/mode/examples/Topics/Image Processing/PixelArray/PixelArray.pde deleted file mode 100644 index cd133102a..000000000 --- a/mode/examples/Topics/Image Processing/PixelArray/PixelArray.pde +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Pixel Array. - * - * Click and drag the mouse up and down to control the signal and - * press and hold any key to see the current pixel being read. - * This program sequentially reads the color of every pixel of an image - * and displays this color to fill the window. - * - * Updated 28 February 2010. - */ - -PImage img; -int direction = 1; -float signal; - -void setup() { - size(200, 200); - noFill(); - stroke(255); - frameRate(30); - img = loadImage("ystone08.jpg"); -} - -void draw() { - if (signal > img.width*img.height-1 || signal < 0) { - direction = direction * -1; - } - - if (mousePressed) { - int mx = constrain(mouseX, 0, img.width-1); - int my = constrain(mouseY, 0, img.height-1); - signal = my*img.width + mx; - } else { - signal += 0.33*direction; - } - - int sx = int(signal) % img.width; - int sy = int(signal) / img.width; - - if (keyPressed) { - set(0, 0, img); // fast way to draw an image - point(sx, sy); - rect(sx - 5, sy - 5, 10, 10); - } else { - color c = img.get(sx, sy); - background(c); - } -} diff --git a/mode/examples/Topics/Image Processing/PixelArray/data/ystone08.jpg b/mode/examples/Topics/Image Processing/PixelArray/data/ystone08.jpg deleted file mode 100644 index 5428ada88..000000000 Binary files a/mode/examples/Topics/Image Processing/PixelArray/data/ystone08.jpg and /dev/null differ diff --git a/mode/examples/Topics/Interaction/Follow1/Follow1.pde b/mode/examples/Topics/Interaction/Follow1/Follow1.pde deleted file mode 100644 index f817d0f64..000000000 --- a/mode/examples/Topics/Interaction/Follow1/Follow1.pde +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Follow 1. - * Based on code from Keith Peters (www.bit-101.com). - * - * A line segment is pushed and pulled by the cursor. - */ - -float x = 100; -float y = 100; -float angle1 = 0.0; -float segLength = 50; - -void setup() { - size(200, 200); - smooth(); - strokeWeight(20.0); - stroke(0, 100); -} - -void draw() { - background(226); - - float dx = mouseX - x; - float dy = mouseY - y; - angle1 = atan2(dy, dx); - x = mouseX - (cos(angle1) * segLength); - y = mouseY - (sin(angle1) * segLength); - - segment(x, y, angle1); - ellipse(x, y, 20, 20); -} - -void segment(float x, float y, float a) { - pushMatrix(); - translate(x, y); - rotate(a); - line(0, 0, segLength, 0); - popMatrix(); -} diff --git a/mode/examples/Topics/Interaction/Follow2/Follow2.pde b/mode/examples/Topics/Interaction/Follow2/Follow2.pde deleted file mode 100644 index a0a6f8516..000000000 --- a/mode/examples/Topics/Interaction/Follow2/Follow2.pde +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Follow 2. - * Based on code from Keith Peters (www.bit-101.com). - * - * A two-segmented arm follows the cursor position. The relative - * angle between the segments is calculated with atan2() and the - * position calculated with sin() and cos(). - */ - -float[] x = new float[2]; -float[] y = new float[2]; -float segLength = 50; - -void setup() { - size(200, 200); - smooth(); - strokeWeight(20.0); - stroke(0, 100); -} - -void draw() { - background(226); - dragSegment(0, mouseX, mouseY); - dragSegment(1, x[0], y[0]); -} - -void dragSegment(int i, float xin, float yin) { - float dx = xin - x[i]; - float dy = yin - y[i]; - float angle = atan2(dy, dx); - x[i] = xin - cos(angle) * segLength; - y[i] = yin - sin(angle) * segLength; - segment(x[i], y[i], angle); -} - -void segment(float x, float y, float a) { - pushMatrix(); - translate(x, y); - rotate(a); - line(0, 0, segLength, 0); - popMatrix(); -} diff --git a/mode/examples/Topics/Interaction/Follow3/Follow3.pde b/mode/examples/Topics/Interaction/Follow3/Follow3.pde deleted file mode 100644 index 1a004ccc3..000000000 --- a/mode/examples/Topics/Interaction/Follow3/Follow3.pde +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Follow 3. - * Based on code from Keith Peters (www.bit-101.com). - * - * A segmented line follows the mouse. The relative angle from - * each segment to the next is calculated with atan2() and the - * position of the next is calculated with sin() and cos(). - */ - -float[] x = new float[20]; -float[] y = new float[20]; -float segLength = 9; - -void setup() { - size(200, 200); - smooth(); - strokeWeight(5); - stroke(0, 100); -} - -void draw() { - background(226); - dragSegment(0, mouseX, mouseY); - for(int i=0; i=1; i--) { - positionSegment(i, i-1); - } - for(int i=0; i width-25 || ballX < 25) { - ballXDirection *= -1; - } - if(ballY > height-25 || ballY < 25) { - ballYDirection *= -1; - } - ellipse(ballX, ballY, 30, 30); - - reachSegment(0, ballX, ballY); - for(int i=1; i=1; i--) { - positionSegment(i, i-1); - } - for(int i=0; i width-size || xpos < 0) { - xdirection *= -1; - } - if (ypos > height-size || ypos < 0) { - ydirection *= -1; - } - - // Draw the shape - ellipse(xpos+size/2, ypos+size/2, size, size); -} diff --git a/mode/examples/Topics/Motion/BouncyBubbles/BouncyBubbles.pde b/mode/examples/Topics/Motion/BouncyBubbles/BouncyBubbles.pde deleted file mode 100644 index e9dc24f28..000000000 --- a/mode/examples/Topics/Motion/BouncyBubbles/BouncyBubbles.pde +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Bouncy Bubbles. - * Based on code from Keith Peters (www.bit-101.com). - * - * Multiple-object collision. - */ - - -int numBalls = 12; -float spring = 0.05; -float gravity = 0.03; -float friction = -0.9; -Ball[] balls = new Ball[numBalls]; - -void setup() -{ - size(640, 200); - noStroke(); - smooth(); - for (int i = 0; i < numBalls; i++) { - balls[i] = new Ball(random(width), random(height), random(20, 40), i, balls); - } -} - -void draw() -{ - background(0); - for (int i = 0; i < numBalls; i++) { - balls[i].collide(); - balls[i].move(); - balls[i].display(); - } -} - -class Ball { - float x, y; - float diameter; - float vx = 0; - float vy = 0; - int id; - Ball[] others; - - Ball(float xin, float yin, float din, int idin, Ball[] oin) { - x = xin; - y = yin; - diameter = din; - id = idin; - others = oin; - } - - void collide() { - for (int i = id + 1; i < numBalls; i++) { - float dx = others[i].x - x; - float dy = others[i].y - y; - float distance = sqrt(dx*dx + dy*dy); - float minDist = others[i].diameter/2 + diameter/2; - if (distance < minDist) { - float angle = atan2(dy, dx); - float targetX = x + cos(angle) * minDist; - float targetY = y + sin(angle) * minDist; - float ax = (targetX - others[i].x) * spring; - float ay = (targetY - others[i].y) * spring; - vx -= ax; - vy -= ay; - others[i].vx += ax; - others[i].vy += ay; - } - } - } - - void move() { - vy += gravity; - x += vx; - y += vy; - if (x + diameter/2 > width) { - x = width - diameter/2; - vx *= friction; - } - else if (x - diameter/2 < 0) { - x = diameter/2; - vx *= friction; - } - if (y + diameter/2 > height) { - y = height - diameter/2; - vy *= friction; - } - else if (y - diameter/2 < 0) { - y = diameter/2; - vy *= friction; - } - } - - void display() { - fill(255, 204); - ellipse(x, y, diameter, diameter); - } -} diff --git a/mode/examples/Topics/Motion/Brownian/Brownian.pde b/mode/examples/Topics/Motion/Brownian/Brownian.pde deleted file mode 100644 index 7f8daf978..000000000 --- a/mode/examples/Topics/Motion/Brownian/Brownian.pde +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Brownian motion. - * - * Recording random movement as a continuous line. - */ - -int num = 2000; -int range = 6; - -float[] ax = new float[num]; -float[] ay = new float[num]; - - -void setup() -{ - size(640, 360); - for(int i = 0; i < num; i++) { - ax[i] = width/2; - ay[i] = height/2; - } - frameRate(30); -} - -void draw() -{ - background(51); - - // Shift all elements 1 place to the left - for(int i = 1; i < num; i++) { - ax[i-1] = ax[i]; - ay[i-1] = ay[i]; - } - - // Put a new value at the end of the array - ax[num-1] += random(-range, range); - ay[num-1] += random(-range, range); - - // Constrain all points to the screen - ax[num-1] = constrain(ax[num-1], 0, width); - ay[num-1] = constrain(ay[num-1], 0, height); - - // Draw a line connecting the points - for(int i=1; i width-ball.r) { - ball.x = width-ball.r; - vel.x *= -1; - } - else if (ball.x < ball.r) { - ball.x = ball.r; - vel.x *= -1; - } - else if (ball.y > height-ball.r) { - ball.y = height-ball.r; - vel.y *= -1; - } - else if (ball.y < ball.r) { - ball.y = ball.r; - vel.y *= -1; - } -} - diff --git a/mode/examples/Topics/Motion/Collision/Collision.pde b/mode/examples/Topics/Motion/Collision/Collision.pde deleted file mode 100644 index 7d5b88c2b..000000000 --- a/mode/examples/Topics/Motion/Collision/Collision.pde +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Collision (Pong). - * - * Move the mouse up and down to move the paddle. - */ - -// Global variables for the ball -float ball_x; -float ball_y; -float ball_dir = 1; -float ball_size = 15; // Radius -float dy = 0; // Direction - -// Global variables for the paddle -int paddle_width = 10; -int paddle_height = 60; - -int dist_wall = 15; - -void setup() -{ - size(640, 360); - rectMode(RADIUS); - ellipseMode(RADIUS); - noStroke(); - smooth(); - ball_y = height/2; - ball_x = 1; -} - -void draw() -{ - background(51); - - ball_x += ball_dir * 1.0; - ball_y += dy; - if(ball_x > width+ball_size) { - ball_x = -width/2 - ball_size; - ball_y = random(0, height); - dy = 0; - } - - // Constrain paddle to screen - float paddle_y = constrain(mouseY, paddle_height, height-paddle_height); - - // Test to see if the ball is touching the paddle - float py = width-dist_wall-paddle_width-ball_size; - if(ball_x == py - && ball_y > paddle_y - paddle_height - ball_size - && ball_y < paddle_y + paddle_height + ball_size) { - ball_dir *= -1; - if(mouseY != pmouseY) { - dy = (mouseY-pmouseY)/2.0; - if(dy > 5) { dy = 5; } - if(dy < -5) { dy = -5; } - } - } - - // If ball hits paddle or back wall, reverse direction - if(ball_x < ball_size && ball_dir == -1) { - ball_dir *= -1; - } - - // If the ball is touching top or bottom edge, reverse direction - if(ball_y > height-ball_size) { - dy = dy * -1; - } - if(ball_y < ball_size) { - dy = dy * -1; - } - - // Draw ball - fill(255); - ellipse(ball_x, ball_y, ball_size, ball_size); - - // Draw the paddle - fill(153); - rect(width-dist_wall, paddle_y, paddle_width, paddle_height); -} - - - - - - diff --git a/mode/examples/Topics/Motion/Linear/Linear.pde b/mode/examples/Topics/Motion/Linear/Linear.pde deleted file mode 100644 index 246b9b05e..000000000 --- a/mode/examples/Topics/Motion/Linear/Linear.pde +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Linear Motion. - * - * Changing a variable to create a moving line. - * When the line moves off the edge of the window, - * the variable is set to 0, which places the line - * back at the bottom of the screen. - */ - -float a = 100; - -void setup() -{ - size(640, 200); - stroke(255); -} - -void draw() -{ - background(51); - a = a - 0.5; - if (a < 0) { - a = height; - } - line(0, a, width, a); -} diff --git a/mode/examples/Topics/Motion/MovingOnCurves/MovingOnCurves.pde b/mode/examples/Topics/Motion/MovingOnCurves/MovingOnCurves.pde deleted file mode 100644 index 051d6ba48..000000000 --- a/mode/examples/Topics/Motion/MovingOnCurves/MovingOnCurves.pde +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Moving On Curves. - * - * In this example, the circles moves along the curve y = x^4. - * Click the mouse to have it move to a new position. - */ - -float beginX = 20.0; // Initial x-coordinate -float beginY = 10.0; // Initial y-coordinate -float endX = 570.0; // Final x-coordinate -float endY = 320.0; // Final y-coordinate -float distX; // X-axis distance to move -float distY; // Y-axis distance to move -float exponent = 4; // Determines the curve -float x = 0.0; // Current x-coordinate -float y = 0.0; // Current y-coordinate -float step = 0.01; // Size of each step along the path -float pct = 0.0; // Percentage traveled (0.0 to 1.0) - -void setup() -{ - size(640, 360); - noStroke(); - smooth(); - distX = endX - beginX; - distY = endY - beginY; -} - -void draw() -{ - fill(0, 2); - rect(0, 0, width, height); - pct += step; - if (pct < 1.0) { - x = beginX + (pct * distX); - y = beginY + (pow(pct, exponent) * distY); - } - fill(255); - ellipse(x, y, 20, 20); -} - -void mousePressed() { - pct = 0.0; - beginX = x; - beginY = y; - endX = mouseX; - endY = mouseY; - distX = endX - beginX; - distY = endY - beginY; -} diff --git a/mode/examples/Topics/Motion/Puff/Puff.pde b/mode/examples/Topics/Motion/Puff/Puff.pde deleted file mode 100644 index 49256b8a6..000000000 --- a/mode/examples/Topics/Motion/Puff/Puff.pde +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Puff - * by Ira Greenberg. - * - * Series of ellipses simulating a multi-segmented - * organism, utilizing a follow the leader algorithm. - * Collision detection occurs on the organism's head, - * controlling overall direction, and on the individual - * body segments, controlling body shape and jitter. - */ - -// For puff head -float headX; -float headY; -float speedX = .7; -float speedY = .9; - -// For puff body -int cells = 1000; -float[]px= new float[cells]; -float[]py= new float[cells]; -float[]radiiX = new float[cells]; -float[]radiiY = new float[cells]; -float[]angle = new float[cells]; -float[]frequency = new float[cells]; -float[]cellRadius = new float[cells]; - -void setup(){ - - size(640, 360); - - // Begin in the center - headX = width/2; - headY = height/2; - - // Fill body arrays - for (int i=0; i< cells; i++){ - radiiX[i] = random(-7, 7); - radiiY[i] = random(-4, 4); - frequency[i]= random(-9, 9); - cellRadius[i] = random(16, 30); - } - frameRate(30); -} - -void draw(){ - background(0); - noStroke(); - fill(255, 255, 255, 5); - - // Follow the leader - for (int i =0; i< cells; i++){ - if (i==0){ - px[i] = headX+sin(radians(angle[i]))*radiiX[i]; - py[i] = headY+cos(radians(angle[i]))*radiiY[i]; - } - else{ - px[i] = px[i-1]+cos(radians(angle[i]))*radiiX[i]; - py[i] = py[i-1]+sin(radians(angle[i]))*radiiY[i]; - - // Check collision of body - if (px[i] >= width-cellRadius[i]/2 || px[i] <= cellRadius[i]/2){ - radiiX[i]*=-1; - cellRadius[i] = random(1, 40); - frequency[i]= random(-13, 13); - } - if (py[i] >= height-cellRadius[i]/2 || py[i] <= cellRadius[i]/2){ - radiiY[i]*=-1; - cellRadius[i] = random(1, 40); - frequency[i]= random(-9, 9); - } - } - // Draw puff - ellipse(px[i], py[i], cellRadius[i], cellRadius[i]); - // Set speed of body - angle[i]+=frequency[i]; - } - - // Set velocity of head - headX+=speedX; - headY+=speedY; - - // Check boundary collision of head - if (headX >= width-cellRadius[0]/2 || headX <=cellRadius[0]/2){ - speedX*=-1; - } - if (headY >= height-cellRadius[0]/2 || headY <= cellRadius[0]/2){ - speedY*=-1; - } -} - diff --git a/mode/examples/Topics/Motion/Reflection1/Reflection1.pde b/mode/examples/Topics/Motion/Reflection1/Reflection1.pde deleted file mode 100644 index 9f8434c93..000000000 --- a/mode/examples/Topics/Motion/Reflection1/Reflection1.pde +++ /dev/null @@ -1,129 +0,0 @@ - /** - * Non-orthogonal Reflection - * by Ira Greenberg. - * - * Based on the equation (R = 2N(N*L)-L) where R is the - * reflection vector, N is the normal, and L is the incident - * vector. - */ - -float baseX1, baseY1, baseX2, baseY2; -float baseLength; -float[] xCoords, yCoords; -float ellipseX, ellipseY, ellipseRadius = 6; -float directionX, directionY; -float ellipseSpeed = 3.5; -float velocityX, velocityY; - -void setup(){ - size(640, 240); - frameRate(30); - fill(128); - smooth(); - baseX1 = 0; - baseY1 = height-150; - baseX2 = width; - baseY2 = height; - - // start ellipse at middle top of screen - ellipseX = width/2; - - // calculate initial random direction - directionX = random(0.1, 0.99); - directionY = random(0.1, 0.99); - - // normalize direction vector - float directionVectLength = sqrt(directionX*directionX + - directionY*directionY); - directionX /= directionVectLength; - directionY /= directionVectLength; -} - -void draw(){ - // draw background - fill(0, 12); - noStroke(); - rect(0, 0, width, height); - - // calculate length of base top - baseLength = dist(baseX1, baseY1, baseX2, baseY2); - xCoords = new float[ceil(baseLength)]; - yCoords = new float[ceil(baseLength)]; - - // fill base top coordinate array - for (int i=0; i width-ellipseRadius){ - ellipseX = width-ellipseRadius; - directionX *= -1; - } - // left - if (ellipseX < ellipseRadius){ - ellipseX = ellipseRadius; - directionX *= -1; - } - // top - if (ellipseY < ellipseRadius){ - ellipseY = ellipseRadius; - directionY *= -1; - // randomize base top - baseY1 = random(height-100, height); - baseY2 = random(height-100, height); - } -} - diff --git a/mode/examples/Topics/Motion/Reflection2/Ground.pde b/mode/examples/Topics/Motion/Reflection2/Ground.pde deleted file mode 100644 index 55d8497e2..000000000 --- a/mode/examples/Topics/Motion/Reflection2/Ground.pde +++ /dev/null @@ -1,20 +0,0 @@ -class Ground { - float x1, y1, x2, y2; - float x, y, len, rot; - - // Default constructor - Ground(){ - } - - // Constructor - Ground(float x1, float y1, float x2, float y2) { - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; - x = (x1+x2)/2; - y = (y1+y2)/2; - len = dist(x1, y1, x2, y2); - rot = atan2((y2-y1), (x2-x1)); - } -} diff --git a/mode/examples/Topics/Motion/Reflection2/Orb.pde b/mode/examples/Topics/Motion/Reflection2/Orb.pde deleted file mode 100644 index 7af7ed91b..000000000 --- a/mode/examples/Topics/Motion/Reflection2/Orb.pde +++ /dev/null @@ -1,14 +0,0 @@ -class Orb{ - float x, y, r; - - // Default constructor - Orb() { - } - - Orb(float x, float y, float r) { - this.x = x; - this.y = y; - this.r = r; - } -} - diff --git a/mode/examples/Topics/Motion/Reflection2/Reflection2.pde b/mode/examples/Topics/Motion/Reflection2/Reflection2.pde deleted file mode 100644 index 05f135b7f..000000000 --- a/mode/examples/Topics/Motion/Reflection2/Reflection2.pde +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Non-orthogonal Collision with Multiple Ground Segments - * by Ira Greenberg. - * - * Based on Keith Peter's Solution in - * Foundation Actionscript Animation: Making Things Move! - */ - -Orb orb; -PVector velocity; -float gravity = .05, damping = 0.8; -int segments = 40; -Ground[] ground = new Ground[segments]; -float[] peakHeights = new float[segments+1]; - -void setup(){ - size(640, 200); - smooth(); - orb = new Orb(50, 50, 3); - velocity = new PVector(.5, 0); - - // Calculate ground peak heights - for (int i=0; i width-orb.r){ - orb.x = width-orb.r; - velocity.x *= -1; - velocity.x *= damping; - } - else if (orb.x < orb.r){ - orb.x = orb.r; - velocity.x *= -1; - velocity.x *= damping; - } -} - - -void checkGroundCollision(Ground groundSegment) { - - // Get difference between orb and ground - float deltaX = orb.x - groundSegment.x; - float deltaY = orb.y - groundSegment.y; - - // Precalculate trig values - float cosine = cos(groundSegment.rot); - float sine = sin(groundSegment.rot); - - /* Rotate ground and velocity to allow - orthogonal collision calculations */ - float groundXTemp = cosine * deltaX + sine * deltaY; - float groundYTemp = cosine * deltaY - sine * deltaX; - float velocityXTemp = cosine * velocity.x + sine * velocity.y; - float velocityYTemp = cosine * velocity.y - sine * velocity.x; - - /* Ground collision - check for surface - collision and also that orb is within - left/rights bounds of ground segment */ - if (groundYTemp > -orb.r && - orb.x > groundSegment.x1 && - orb.x < groundSegment.x2 ){ - // keep orb from going into ground - groundYTemp = -orb.r; - // bounce and slow down orb - velocityYTemp *= -1.0; - velocityYTemp *= damping; - } - - // Reset ground, velocity and orb - deltaX = cosine * groundXTemp - sine * groundYTemp; - deltaY = cosine * groundYTemp + sine * groundXTemp; - velocity.x = cosine * velocityXTemp - sine * velocityYTemp; - velocity.y = cosine * velocityYTemp + sine * velocityXTemp; - orb.x = groundSegment.x + deltaX; - orb.y = groundSegment.y + deltaY; -} - - - - diff --git a/mode/examples/Topics/Shaders/BlurFilter/BlurFilter.pde b/mode/examples/Topics/Shaders/BlurFilter/BlurFilter.pde deleted file mode 100644 index 67b2e6ca0..000000000 --- a/mode/examples/Topics/Shaders/BlurFilter/BlurFilter.pde +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Blur Filter - * - * Change the default shader to apply a simple, custom blur filter. - * - * Press the mouse to switch between the custom and default shader. - */ - -PShader blur; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - blur = loadShader("blur.glsl"); - stroke(255, 0, 0); - rectMode(CENTER); -} - -void draw() { - filter(blur); - rect(mouseX, mouseY, 150, 150); - ellipse(mouseX, mouseY, 100, 100); -} - - - diff --git a/mode/examples/Topics/Shaders/BlurFilter/data/blur.glsl b/mode/examples/Topics/Shaders/BlurFilter/data/blur.glsl deleted file mode 100644 index 2aa9d6079..000000000 --- a/mode/examples/Topics/Shaders/BlurFilter/data/blur.glsl +++ /dev/null @@ -1,42 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -#define PROCESSING_TEXTURE_SHADER - -uniform sampler2D texture; -uniform vec2 texOffset; - -varying vec4 vertColor; -varying vec4 vertTexCoord; - -void main(void) { - // Grouping texcoord variables in order to make it work in the GMA 950. See post #13 - // in this thread: - // http://www.idevgames.com/forums/thread-3467.html - vec2 tc0 = vertTexCoord.st + vec2(-texOffset.s, -texOffset.t); - vec2 tc1 = vertTexCoord.st + vec2( 0.0, -texOffset.t); - vec2 tc2 = vertTexCoord.st + vec2(+texOffset.s, -texOffset.t); - vec2 tc3 = vertTexCoord.st + vec2(-texOffset.s, 0.0); - vec2 tc4 = vertTexCoord.st + vec2( 0.0, 0.0); - vec2 tc5 = vertTexCoord.st + vec2(+texOffset.s, 0.0); - vec2 tc6 = vertTexCoord.st + vec2(-texOffset.s, +texOffset.t); - vec2 tc7 = vertTexCoord.st + vec2( 0.0, +texOffset.t); - vec2 tc8 = vertTexCoord.st + vec2(+texOffset.s, +texOffset.t); - - vec4 col0 = texture2D(texture, tc0); - vec4 col1 = texture2D(texture, tc1); - vec4 col2 = texture2D(texture, tc2); - vec4 col3 = texture2D(texture, tc3); - vec4 col4 = texture2D(texture, tc4); - vec4 col5 = texture2D(texture, tc5); - vec4 col6 = texture2D(texture, tc6); - vec4 col7 = texture2D(texture, tc7); - vec4 col8 = texture2D(texture, tc8); - - vec4 sum = (1.0 * col0 + 2.0 * col1 + 1.0 * col2 + - 2.0 * col3 + 4.0 * col4 + 2.0 * col4 + - 1.0 * col5 + 2.0 * col6 + 1.0 * col7) / 16.0; - gl_FragColor = vec4(sum.rgb, 1.0) * vertColor; -} diff --git a/mode/examples/Topics/Shaders/EdgeDetect/EdgeDetect.pde b/mode/examples/Topics/Shaders/EdgeDetect/EdgeDetect.pde deleted file mode 100644 index aa3bd2695..000000000 --- a/mode/examples/Topics/Shaders/EdgeDetect/EdgeDetect.pde +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Edge Detection - * - * Change the default shader to apply a simple, custom edge detection filter. - * - * Press the mouse to switch between the custom and default shader. - */ - -PShader edges; -PImage img; -boolean enabled = true; - -void setup() { - size(640, 360, P2D); - orientation(LANDSCAPE); - img = loadImage("leaves.jpg"); - edges = loadShader("edges.glsl"); -} - -void draw() { - if (enabled == true) { - shader(edges); - } - image(img, 0, 0); -} - -void mousePressed() { - enabled = !enabled; - if (!enabled == true) { - resetShader(); - } -} diff --git a/mode/examples/Topics/Shaders/EdgeDetect/data/edges.glsl b/mode/examples/Topics/Shaders/EdgeDetect/data/edges.glsl deleted file mode 100644 index 62109e3e3..000000000 --- a/mode/examples/Topics/Shaders/EdgeDetect/data/edges.glsl +++ /dev/null @@ -1,40 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -#define PROCESSING_TEXTURE_SHADER - -uniform sampler2D texture; -uniform vec2 texOffset; - -varying vec4 vertColor; -varying vec4 vertTexCoord; - -void main(void) { - // Grouping texcoord variables in order to make it work in the GMA 950. See post #13 - // in this thread: - // http://www.idevgames.com/forums/thread-3467.html - vec2 tc0 = vertTexCoord.st + vec2(-texOffset.s, -texOffset.t); - vec2 tc1 = vertTexCoord.st + vec2( 0.0, -texOffset.t); - vec2 tc2 = vertTexCoord.st + vec2(+texOffset.s, -texOffset.t); - vec2 tc3 = vertTexCoord.st + vec2(-texOffset.s, 0.0); - vec2 tc4 = vertTexCoord.st + vec2( 0.0, 0.0); - vec2 tc5 = vertTexCoord.st + vec2(+texOffset.s, 0.0); - vec2 tc6 = vertTexCoord.st + vec2(-texOffset.s, +texOffset.t); - vec2 tc7 = vertTexCoord.st + vec2( 0.0, +texOffset.t); - vec2 tc8 = vertTexCoord.st + vec2(+texOffset.s, +texOffset.t); - - vec4 col0 = texture2D(texture, tc0); - vec4 col1 = texture2D(texture, tc1); - vec4 col2 = texture2D(texture, tc2); - vec4 col3 = texture2D(texture, tc3); - vec4 col4 = texture2D(texture, tc4); - vec4 col5 = texture2D(texture, tc5); - vec4 col6 = texture2D(texture, tc6); - vec4 col7 = texture2D(texture, tc7); - vec4 col8 = texture2D(texture, tc8); - - vec4 sum = 8.0 * col4 - (col0 + col1 + col2 + col3 + col5 + col6 + col7 + col8); - gl_FragColor = vec4(sum.rgb, 1.0) * vertColor; -} diff --git a/mode/examples/Topics/Shaders/EdgeDetect/data/leaves.jpg b/mode/examples/Topics/Shaders/EdgeDetect/data/leaves.jpg deleted file mode 100644 index 72c86a092..000000000 Binary files a/mode/examples/Topics/Shaders/EdgeDetect/data/leaves.jpg and /dev/null differ diff --git a/mode/examples/Topics/Shaders/EdgeFilter/EdgeFilter.pde b/mode/examples/Topics/Shaders/EdgeFilter/EdgeFilter.pde deleted file mode 100644 index c740f003d..000000000 --- a/mode/examples/Topics/Shaders/EdgeFilter/EdgeFilter.pde +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Edge Filter - * - * Apply a custom shader to the filter() function to affect the geometry drawn to the screen. - * - * Press the mouse to turn the filter on and off. - */ - -PShader edges; -boolean applyFilter = true; - -void setup() { - size(640, 360, P3D); - orientation(LANDSCAPE); - edges = loadShader("edges.glsl"); - noStroke(); -} - -void draw() { - background(0); - lights(); - - translate(width/2, height/2); - pushMatrix(); - rotateX(frameCount * 0.01); - rotateY(frameCount * 0.01); - box(120); - popMatrix(); - - if (applyFilter == true) { - filter(edges); - } - - // The sphere doesn't have the edge detection applied - // on it because it is drawn after filter() is called. - rotateY(frameCount * 0.02); - translate(150, 0); - sphere(40); -} - -void mousePressed() { - applyFilter = !applyFilter; -} diff --git a/mode/examples/Topics/Shaders/EdgeFilter/data/edges.glsl b/mode/examples/Topics/Shaders/EdgeFilter/data/edges.glsl deleted file mode 100644 index 62109e3e3..000000000 --- a/mode/examples/Topics/Shaders/EdgeFilter/data/edges.glsl +++ /dev/null @@ -1,40 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -#define PROCESSING_TEXTURE_SHADER - -uniform sampler2D texture; -uniform vec2 texOffset; - -varying vec4 vertColor; -varying vec4 vertTexCoord; - -void main(void) { - // Grouping texcoord variables in order to make it work in the GMA 950. See post #13 - // in this thread: - // http://www.idevgames.com/forums/thread-3467.html - vec2 tc0 = vertTexCoord.st + vec2(-texOffset.s, -texOffset.t); - vec2 tc1 = vertTexCoord.st + vec2( 0.0, -texOffset.t); - vec2 tc2 = vertTexCoord.st + vec2(+texOffset.s, -texOffset.t); - vec2 tc3 = vertTexCoord.st + vec2(-texOffset.s, 0.0); - vec2 tc4 = vertTexCoord.st + vec2( 0.0, 0.0); - vec2 tc5 = vertTexCoord.st + vec2(+texOffset.s, 0.0); - vec2 tc6 = vertTexCoord.st + vec2(-texOffset.s, +texOffset.t); - vec2 tc7 = vertTexCoord.st + vec2( 0.0, +texOffset.t); - vec2 tc8 = vertTexCoord.st + vec2(+texOffset.s, +texOffset.t); - - vec4 col0 = texture2D(texture, tc0); - vec4 col1 = texture2D(texture, tc1); - vec4 col2 = texture2D(texture, tc2); - vec4 col3 = texture2D(texture, tc3); - vec4 col4 = texture2D(texture, tc4); - vec4 col5 = texture2D(texture, tc5); - vec4 col6 = texture2D(texture, tc6); - vec4 col7 = texture2D(texture, tc7); - vec4 col8 = texture2D(texture, tc8); - - vec4 sum = 8.0 * col4 - (col0 + col1 + col2 + col3 + col5 + col6 + col7 + col8); - gl_FragColor = vec4(sum.rgb, 1.0) * vertColor; -} diff --git a/mode/examples/Topics/Shaders/LowLevelGL/LowLevelGL.pde b/mode/examples/Topics/Shaders/LowLevelGL/LowLevelGL.pde deleted file mode 100644 index 5d10bbc13..000000000 --- a/mode/examples/Topics/Shaders/LowLevelGL/LowLevelGL.pde +++ /dev/null @@ -1,104 +0,0 @@ -// Draws a triangle using low-level OpenGL calls. -import java.nio.*; - -PGL pgl; -PShader flatShader; - -int vertLoc; -int colorLoc; - -float[] vertices; -float[] colors; - -FloatBuffer vertData; -FloatBuffer colorData; - -void setup() { - size(640, 360, P3D); - orientation(LANDSCAPE); - - // Loads a shader to render geometry w/out - // textures and lights. - flatShader = loadShader("frag.glsl", "vert.glsl"); - - vertices = new float[12]; - vertData = allocateDirectFloatBuffer(12); - - colors = new float[12]; - colorData = allocateDirectFloatBuffer(12); -} - -void draw() { - background(0); - - // The geometric transformations will be automatically passed - // to the shader. - rotate(frameCount * 0.01, width, height, 0); - - updateGeometry(); - - pgl = beginPGL(); - flatShader.bind(); - - vertLoc = pgl.getAttribLocation(flatShader.glProgram, "vertex"); - colorLoc = pgl.getAttribLocation(flatShader.glProgram, "color"); - - pgl.enableVertexAttribArray(vertLoc); - pgl.enableVertexAttribArray(colorLoc); - - pgl.vertexAttribPointer(vertLoc, 4, PGL.FLOAT, false, 0, vertData); - pgl.vertexAttribPointer(colorLoc, 4, PGL.FLOAT, false, 0, colorData); - - pgl.drawArrays(PGL.TRIANGLES, 0, 3); - - pgl.disableVertexAttribArray(vertLoc); - pgl.disableVertexAttribArray(colorLoc); - - flatShader.unbind(); - - endPGL(); -} - -void updateGeometry() { - // Vertex 1 - vertices[0] = 0; - vertices[1] = 0; - vertices[2] = 0; - vertices[3] = 1; - colors[0] = 1; - colors[1] = 0; - colors[2] = 0; - colors[3] = 1; - - // Corner 2 - vertices[4] = width/2; - vertices[5] = height; - vertices[6] = 0; - vertices[7] = 1; - colors[4] = 0; - colors[5] = 1; - colors[6] = 0; - colors[7] = 1; - - // Corner 3 - vertices[8] = width; - vertices[9] = 0; - vertices[10] = 0; - vertices[11] = 1; - colors[8] = 0; - colors[9] = 0; - colors[10] = 1; - colors[11] = 1; - - vertData.rewind(); - vertData.put(vertices); - vertData.position(0); - - colorData.rewind(); - colorData.put(colors); - colorData.position(0); -} - -FloatBuffer allocateDirectFloatBuffer(int n) { - return ByteBuffer.allocateDirect(n * Float.SIZE/8).order(ByteOrder.nativeOrder()).asFloatBuffer(); -} diff --git a/mode/examples/Topics/Shaders/LowLevelGL/data/frag.glsl b/mode/examples/Topics/Shaders/LowLevelGL/data/frag.glsl deleted file mode 100644 index 16742d2bd..000000000 --- a/mode/examples/Topics/Shaders/LowLevelGL/data/frag.glsl +++ /dev/null @@ -1,30 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2011-12 Ben Fry and Casey Reas - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - */ - -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -varying vec4 vertColor; - -void main() { - gl_FragColor = vertColor; -} \ No newline at end of file diff --git a/mode/examples/Topics/Shaders/LowLevelGL/data/vert.glsl b/mode/examples/Topics/Shaders/LowLevelGL/data/vert.glsl deleted file mode 100644 index 1a0177008..000000000 --- a/mode/examples/Topics/Shaders/LowLevelGL/data/vert.glsl +++ /dev/null @@ -1,33 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2011-12 Ben Fry and Casey Reas - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - */ - -#define PROCESSING_COLOR_SHADER - -uniform mat4 transform; - -attribute vec4 vertex; -attribute vec4 color; - -varying vec4 vertColor; - -void main() { - gl_Position = transform * vertex; - vertColor = color; -} \ No newline at end of file diff --git a/mode/examples/Topics/Shaders/ToonShading/ToonShading.pde b/mode/examples/Topics/Shaders/ToonShading/ToonShading.pde deleted file mode 100644 index fd18d24b8..000000000 --- a/mode/examples/Topics/Shaders/ToonShading/ToonShading.pde +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Toon Shading. - * - * Example showing the use of a custom lighting shader in order - * to apply a "toon" effect on the scene. Based on the glsl tutorial - * from lighthouse 3D: - * http://www.lighthouse3d.com/tutorials/glsl-tutorial/toon-shader-version-ii/ - */ - -PShader toon; -boolean shaderEnabled = true; - -void setup() { - size(640, 360, P3D); - orientation(LANDSCAPE); - noStroke(); - fill(204); - toon = loadShader("ToonFrag.glsl", "ToonVert.glsl"); -} - -void draw() { - if (shaderEnabled == true) { - shader(toon); - } - - noStroke(); - background(0); - float dirY = (mouseY / float(height) - 0.5) * 2; - float dirX = (mouseX / float(width) - 0.5) * 2; - directionalLight(204, 204, 204, -dirX, -dirY, -1); - translate(width/2, height/2); - sphere(120); -} - -void mousePressed() { - if (shaderEnabled) { - shaderEnabled = false; - resetShader(); - } - else { - shaderEnabled = true; - } -} - diff --git a/mode/examples/Topics/Shaders/ToonShading/data/ToonFrag.glsl b/mode/examples/Topics/Shaders/ToonShading/data/ToonFrag.glsl deleted file mode 100644 index 054bb0dfb..000000000 --- a/mode/examples/Topics/Shaders/ToonShading/data/ToonFrag.glsl +++ /dev/null @@ -1,25 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -varying vec3 vertNormal; -varying vec3 vertLightDir; - -void main() { - float intensity; - vec4 color; - intensity = max(0.0, dot(vertLightDir, vertNormal)); - - if (intensity > 0.95) { - color = vec4(1.0, 0.5, 0.5, 1.0); - } else if (intensity > 0.5) { - color = vec4(0.6, 0.3, 0.3, 1.0); - } else if (intensity > 0.25) { - color = vec4(0.4, 0.2, 0.2, 1.0); - } else { - color = vec4(0.2, 0.1, 0.1, 1.0); - } - - gl_FragColor = color; -} \ No newline at end of file diff --git a/mode/examples/Topics/Shaders/ToonShading/data/ToonVert.glsl b/mode/examples/Topics/Shaders/ToonShading/data/ToonVert.glsl deleted file mode 100644 index 01b77b2c9..000000000 --- a/mode/examples/Topics/Shaders/ToonShading/data/ToonVert.glsl +++ /dev/null @@ -1,31 +0,0 @@ -// Toon shader using per-pixel lighting. Based on the glsl -// tutorial from lighthouse 3D: -// http://www.lighthouse3d.com/tutorials/glsl-tutorial/toon-shader-version-ii/ - -#define PROCESSING_LIGHT_SHADER - -uniform mat4 modelview; -uniform mat4 transform; -uniform mat3 normalMatrix; - -uniform vec3 lightNormal[8]; - -attribute vec4 vertex; -attribute vec3 normal; - -varying vec3 vertNormal; -varying vec3 vertLightDir; - -void main() { - // Vertex in clip coordinates - gl_Position = transform * vertex; - - // Normal vector in eye coordinates is passed - // to the fragment shader - vertNormal = normalize(normalMatrix * normal); - - // Assuming that there is only one directional light. - // Its normal vector is passed to the fragment shader - // in order to perform per-pixel lighting calculation. - vertLightDir = -lightNormal[0]; -} \ No newline at end of file diff --git a/mode/examples/Topics/Simulate/Chain/Chain.pde b/mode/examples/Topics/Simulate/Chain/Chain.pde deleted file mode 100644 index f2a53006f..000000000 --- a/mode/examples/Topics/Simulate/Chain/Chain.pde +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Chain. - * - * One mass is attached to the mouse position and the other - * is attached the position of the other mass. The gravity - * in the environment pulls down on both. - */ - - -Spring2D s1, s2; - -float gravity = 6.0; -float mass = 2.0; - -void setup() -{ - size(200, 200); - smooth(); - fill(0); - // Inputs: x, y, mass, gravity - s1 = new Spring2D(0.0, width/2, mass, gravity); - s2 = new Spring2D(0.0, width/2, mass, gravity); -} - -void draw() -{ - background(204); - s1.update(mouseX, mouseY); - s1.display(mouseX, mouseY); - s2.update(s1.x, s1.y); - s2.display(s1.x, s1.y); -} - -class Spring2D { - float vx, vy; // The x- and y-axis velocities - float x, y; // The x- and y-coordinates - float gravity; - float mass; - float radius = 20; - float stiffness = 0.2; - float damping = 0.7; - - Spring2D(float xpos, float ypos, float m, float g) { - x = xpos; - y = ypos; - mass = m; - gravity = g; - } - - void update(float targetX, float targetY) { - float forceX = (targetX - x) * stiffness; - float ax = forceX / mass; - vx = damping * (vx + ax); - x += vx; - float forceY = (targetY - y) * stiffness; - forceY += gravity; - float ay = forceY / mass; - vy = damping * (vy + ay); - y += vy; - } - - void display(float nx, float ny) { - noStroke(); - ellipse(x, y, radius*2, radius*2); - stroke(255); - line(x, y, nx, ny); - } -} diff --git a/mode/examples/Topics/Simulate/Flocking/Boid.pde b/mode/examples/Topics/Simulate/Flocking/Boid.pde deleted file mode 100644 index b2bc127b6..000000000 --- a/mode/examples/Topics/Simulate/Flocking/Boid.pde +++ /dev/null @@ -1,196 +0,0 @@ -// The Boid class - -class Boid { - - PVector loc; - PVector vel; - PVector acc; - float r; - float maxforce; // Maximum steering force - float maxspeed; // Maximum speed - - Boid(PVector l, float ms, float mf) { - acc = new PVector(0,0); - vel = new PVector(random(-1,1),random(-1,1)); - loc = l.get(); - r = 2.0; - maxspeed = ms; - maxforce = mf; - } - - void run(ArrayList boids) { - flock(boids); - update(); - borders(); - render(); - } - - // We accumulate a new acceleration each time based on three rules - void flock(ArrayList boids) { - PVector sep = separate(boids); // Separation - PVector ali = align(boids); // Alignment - PVector coh = cohesion(boids); // Cohesion - // Arbitrarily weight these forces - sep.mult(1.5); - ali.mult(1.0); - coh.mult(1.0); - // Add the force vectors to acceleration - acc.add(sep); - acc.add(ali); - acc.add(coh); - } - - // Method to update location - void update() { - // Update velocity - vel.add(acc); - // Limit speed - vel.limit(maxspeed); - loc.add(vel); - // Reset accelertion to 0 each cycle - acc.mult(0); - } - - void seek(PVector target) { - acc.add(steer(target,false)); - } - - void arrive(PVector target) { - acc.add(steer(target,true)); - } - - // A method that calculates a steering vector towards a target - // Takes a second argument, if true, it slows down as it approaches the target - PVector steer(PVector target, boolean slowdown) { - PVector steer; // The steering vector - PVector desired = target.sub(target,loc); // A vector pointing from the location to the target - float d = desired.mag(); // Distance from the target is the magnitude of the vector - // If the distance is greater than 0, calc steering (otherwise return zero vector) - if (d > 0) { - // Normalize desired - desired.normalize(); - // Two options for desired vector magnitude (1 -- based on distance, 2 -- maxspeed) - if ((slowdown) && (d < 100.0)) desired.mult(maxspeed*(d/100.0)); // This damping is somewhat arbitrary - else desired.mult(maxspeed); - // Steering = Desired minus Velocity - steer = target.sub(desired,vel); - steer.limit(maxforce); // Limit to maximum steering force - } - else { - steer = new PVector(0,0); - } - return steer; - } - - void render() { - // Draw a triangle rotated in the direction of velocity - float theta = vel.heading() + PI/2; - fill(200,100); - stroke(255); - pushMatrix(); - translate(loc.x,loc.y); - rotate(theta); - beginShape(TRIANGLES); - vertex(0, -r*2); - vertex(-r, r*2); - vertex(r, r*2); - endShape(); - popMatrix(); - } - - // Wraparound - void borders() { - if (loc.x < -r) loc.x = width+r; - if (loc.y < -r) loc.y = height+r; - if (loc.x > width+r) loc.x = -r; - if (loc.y > height+r) loc.y = -r; - } - - // Separation - // Method checks for nearby boids and steers away - PVector separate (ArrayList boids) { - float desiredseparation = 20.0; - PVector steer = new PVector(0,0,0); - int count = 0; - // For every boid in the system, check if it's too close - for (int i = 0 ; i < boids.size(); i++) { - Boid other = (Boid) boids.get(i); - float d = PVector.dist(loc,other.loc); - // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself) - if ((d > 0) && (d < desiredseparation)) { - // Calculate vector pointing away from neighbor - PVector diff = PVector.sub(loc,other.loc); - diff.normalize(); - diff.div(d); // Weight by distance - steer.add(diff); - count++; // Keep track of how many - } - } - // Average -- divide by how many - if (count > 0) { - steer.div((float)count); - } - - // As long as the vector is greater than 0 - if (steer.mag() > 0) { - // Implement Reynolds: Steering = Desired - Velocity - steer.normalize(); - steer.mult(maxspeed); - steer.sub(vel); - steer.limit(maxforce); - } - return steer; - } - - // Alignment - // For every nearby boid in the system, calculate the average velocity - PVector align (ArrayList boids) { - float neighbordist = 25.0; - PVector steer = new PVector(0,0,0); - int count = 0; - for (int i = 0 ; i < boids.size(); i++) { - Boid other = (Boid) boids.get(i); - float d = PVector.dist(loc,other.loc); - if ((d > 0) && (d < neighbordist)) { - steer.add(other.vel); - count++; - } - } - if (count > 0) { - steer.div((float)count); - } - - // As long as the vector is greater than 0 - if (steer.mag() > 0) { - // Implement Reynolds: Steering = Desired - Velocity - steer.normalize(); - steer.mult(maxspeed); - steer.sub(vel); - steer.limit(maxforce); - } - return steer; - } - - // Cohesion - // For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location - PVector cohesion (ArrayList boids) { - float neighbordist = 25.0; - PVector sum = new PVector(0,0); // Start with empty vector to accumulate all locations - int count = 0; - for (int i = 0 ; i < boids.size(); i++) { - Boid other = (Boid) boids.get(i); - float d = loc.dist(other.loc); - if ((d > 0) && (d < neighbordist)) { - sum.add(other.loc); // Add location - count++; - } - } - if (count > 0) { - sum.div((float)count); - return steer(sum,false); // Steer towards the location - } - return sum; - } -} - - diff --git a/mode/examples/Topics/Simulate/Flocking/Flock.pde b/mode/examples/Topics/Simulate/Flocking/Flock.pde deleted file mode 100644 index 9ec1001c7..000000000 --- a/mode/examples/Topics/Simulate/Flocking/Flock.pde +++ /dev/null @@ -1,22 +0,0 @@ -// The Flock (a list of Boid objects) - -class Flock { - ArrayList boids; // An arraylist for all the boids - - Flock() { - boids = new ArrayList(); // Initialize the arraylist - } - - void run() { - for (int i = 0; i < boids.size(); i++) { - Boid b = (Boid) boids.get(i); - b.run(boids); // Passing the entire list of boids to each boid individually - } - } - - void addBoid(Boid b) { - boids.add(b); - } - -} - diff --git a/mode/examples/Topics/Simulate/Flocking/Flocking.pde b/mode/examples/Topics/Simulate/Flocking/Flocking.pde deleted file mode 100644 index ed0e7e60c..000000000 --- a/mode/examples/Topics/Simulate/Flocking/Flocking.pde +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Flocking - * by Daniel Shiffman. - * - * An implementation of Craig Reynold's Boids program to simulate - * the flocking behavior of birds. Each boid steers itself based on - * rules of avoidance, alignment, and coherence. - * - * Click the mouse to add a new boid. - */ - -Flock flock; - -void setup() { - size(640, 360); - flock = new Flock(); - // Add an initial set of boids into the system - for (int i = 0; i < 150; i++) { - flock.addBoid(new Boid(new PVector(width/2,height/2), 3.0, 0.05)); - } - smooth(); -} - -void draw() { - background(50); - flock.run(); -} - -// Add a new boid into the System -void mousePressed() { - flock.addBoid(new Boid(new PVector(mouseX,mouseY),2.0f,0.05f)); -} diff --git a/mode/examples/Topics/Simulate/ForcesWithVectors/ForcesWithVectors.pde b/mode/examples/Topics/Simulate/ForcesWithVectors/ForcesWithVectors.pde deleted file mode 100644 index fccdc5658..000000000 --- a/mode/examples/Topics/Simulate/ForcesWithVectors/ForcesWithVectors.pde +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Forces (Gravity and Fluid Resistence) with Vectors - * by Daniel Shiffman. - * - * Demonstration of multiple force acting on bodies (Mover class) - * Bodies experience gravity continuously - * Bodies experience fluid resistance when in "water" - * - * For the basics of working with PVector, see - * http://processing.org/learning/pvector/ - * as well as examples in Topics/Vectors/ - * - */ - -// Five moving bodies -Mover[] movers = new Mover[10]; - -// Liquid -Liquid liquid; - -void setup() { - size(640, 360); - smooth(); - reset(); - // Create liquid object - liquid = new Liquid(0, height/2, width, height/2, 0.1); -} - -void draw() { - background(0); - - // Draw water - liquid.display(); - - for (int i = 0; i < movers.length; i++) { - - // Is the Mover in the liquid? - if (liquid.contains(movers[i])) { - // Calculate drag force - PVector drag = liquid.drag(movers[i]); - // Apply drag force to Mover - movers[i].applyForce(drag); - } - - // Gravity is scaled by mass here! - PVector gravity = new PVector(0, 0.1*movers[i].mass); - // Apply gravity - movers[i].applyForce(gravity); - - // Update and display - movers[i].update(); - movers[i].display(); - movers[i].checkEdges(); - } - - fill(255); - text("click mouse to reset",10,30); - -} - -void mousePressed() { - reset(); -} - -// Restart all the Mover objects randomly -void reset() { - for (int i = 0; i < movers.length; i++) { - movers[i] = new Mover(random(0.5, 3), 40+i*70, 0); - } -} - - - - - - - diff --git a/mode/examples/Topics/Simulate/ForcesWithVectors/Liquid.pde b/mode/examples/Topics/Simulate/ForcesWithVectors/Liquid.pde deleted file mode 100644 index 98ccfe34d..000000000 --- a/mode/examples/Topics/Simulate/ForcesWithVectors/Liquid.pde +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Forces (Gravity and Fluid Resistence) with Vectors - * by Daniel Shiffman. - * - * Demonstration of multiple force acting on bodies (Mover class) - * Bodies experience gravity continuously - * Bodies experience fluid resistance when in "water" - */ - - // Liquid class - class Liquid { - - - // Liquid is a rectangle - float x,y,w,h; - // Coefficient of drag - float c; - - Liquid(float x_, float y_, float w_, float h_, float c_) { - x = x_; - y = y_; - w = w_; - h = h_; - c = c_; - } - - // Is the Mover in the Liquid? - boolean contains(Mover m) { - PVector l = m.location; - if (l.x > x && l.x < x + w && l.y > y && l.y < y + h) { - return true; - } - else { - return false; - } - } - - // Calculate drag force - PVector drag(Mover m) { - // Magnitude is coefficient * speed squared - float speed = m.velocity.mag(); - float dragMagnitude = c * speed * speed; - - // Direction is inverse of velocity - PVector drag = m.velocity.get(); - drag.mult(-1); - - // Scale according to magnitude - drag.setMag(dragMagnitude); - return drag; - } - - void display() { - noStroke(); - fill(127); - rect(x,y,w,h); - } - -} - diff --git a/mode/examples/Topics/Simulate/ForcesWithVectors/Mover.pde b/mode/examples/Topics/Simulate/ForcesWithVectors/Mover.pde deleted file mode 100644 index b14754b71..000000000 --- a/mode/examples/Topics/Simulate/ForcesWithVectors/Mover.pde +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Forces (Gravity and Fluid Resistence) with Vectors - * by Daniel Shiffman. - * - * Demonstration of multiple force acting on bodies (Mover class) - * Bodies experience gravity continuously - * Bodies experience fluid resistance when in "water" - */ - - -class Mover { - - // location, velocity, and acceleration - PVector location; - PVector velocity; - PVector acceleration; - - // Mass is tied to size - float mass; - - Mover(float m, float x, float y) { - mass = m; - location = new PVector(x, y); - velocity = new PVector(0, 0); - acceleration = new PVector(0, 0); - } - - // Newton's 2nd law: F = M * A - // or A = F / M - void applyForce(PVector force) { - // Divide by mass - PVector f = PVector.div(force, mass); - // Accumulate all forces in acceleration - acceleration.add(f); - } - - void update() { - - // Velocity changes according to acceleration - velocity.add(acceleration); - // Location changes by velocity - location.add(velocity); - // We must clear acceleration each frame - acceleration.mult(0); - } - - // Draw Mover - void display() { - stroke(255); - strokeWeight(2); - fill(255, 200); - ellipse(location.x, location.y, mass*16, mass*16); - } - - // Bounce off bottom of window - void checkEdges() { - if (location.y > height) { - velocity.y *= -0.9; // A little dampening when hitting the bottom - location.y = height; - } - } -} - - diff --git a/mode/examples/Topics/Simulate/GravitationalAttraction3D/GravitationalAttraction3D.pde b/mode/examples/Topics/Simulate/GravitationalAttraction3D/GravitationalAttraction3D.pde deleted file mode 100644 index 87a7ed9ef..000000000 --- a/mode/examples/Topics/Simulate/GravitationalAttraction3D/GravitationalAttraction3D.pde +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Gravitational Attraction (3D) - * by Daniel Shiffman. - * - * Simulating gravitational attraction - * G ---> universal gravitational constant - * m1 --> mass of object #1 - * m2 --> mass of object #2 - * d ---> distance between objects - * F = (G*m1*m2)/(d*d) - * - * For the basics of working with PVector, see - * http://processing.org/learning/pvector/ - * as well as examples in Topics/Vectors/ - * - */ - -// A bunch of planets -Planet[] planets = new Planet[10]; -// One sun (note sun is not attracted to planets (violation of Newton's 3rd Law) -Sun s; - -// An angle to rotate around the scene -float angle = 0; - -void setup() { - size(displayWidth, displayHeight, P3D); - orientation(LANDSCAPE); - // Some random planets - for (int i = 0; i < planets.length; i++) { - planets[i] = new Planet(random(0.1, 2), random(-width/2, width/2), random(-height/2, height/2), random(-100, 100)); - } - // A single sun - s = new Sun(); -} - -void draw() { - background(0); - // Setup the scene - sphereDetail(8); - lights(); - translate(width/2, height/2); - rotateY(angle); - - - // Display the Sun - s.display(); - - // All the Planets - for (int i = 0; i < planets.length; i++) { - // Sun attracts Planets - PVector force = s.attract(planets[i]); - planets[i].applyForce(force); - // Update and draw Planets - planets[i].update(); - planets[i].display(); - } - - // Rotate around the scene - angle += 0.003; -} - - - - - - - - - - diff --git a/mode/examples/Topics/Simulate/GravitationalAttraction3D/Planet.pde b/mode/examples/Topics/Simulate/GravitationalAttraction3D/Planet.pde deleted file mode 100644 index ae8be2537..000000000 --- a/mode/examples/Topics/Simulate/GravitationalAttraction3D/Planet.pde +++ /dev/null @@ -1,45 +0,0 @@ -// Gravitational Attraction (3D) -// Daniel Shiffman - -// A class for an orbiting Planet - -class Planet { - - // Basic physics model (location, velocity, acceleration, mass) - PVector location; - PVector velocity; - PVector acceleration; - float mass; - - Planet(float m, float x, float y, float z) { - mass = m; - location = new PVector(x,y,z); - velocity = new PVector(1,0); // Arbitrary starting velocity - acceleration = new PVector(0,0); - } - - // Newton's 2nd Law (F = M*A) applied - void applyForce(PVector force) { - PVector f = PVector.div(force,mass); - acceleration.add(f); - } - - // Our motion algorithm (aka Euler Integration) - void update() { - velocity.add(acceleration); // Velocity changes according to acceleration - location.add(velocity); // Location changes according to velocity - acceleration.mult(0); - } - - // Draw the Planet - void display() { - noStroke(); - fill(255); - pushMatrix(); - translate(location.x,location.y,location.z); - sphere(mass*8); - popMatrix(); - } -} - - diff --git a/mode/examples/Topics/Simulate/GravitationalAttraction3D/Sun.pde b/mode/examples/Topics/Simulate/GravitationalAttraction3D/Sun.pde deleted file mode 100644 index 3253bc02f..000000000 --- a/mode/examples/Topics/Simulate/GravitationalAttraction3D/Sun.pde +++ /dev/null @@ -1,39 +0,0 @@ -// Gravitational Attraction (3D) -// Daniel Shiffman - -// A class for an attractive body in our world - -class Sun { - float mass; // Mass, tied to size - PVector location; // Location - float G; // Universal gravitational constant (arbitrary value) - - Sun() { - location = new PVector(0,0); - mass = 20; - G = 0.4; - } - - - PVector attract(Planet m) { - PVector force = PVector.sub(location,m.location); // Calculate direction of force - float d = force.mag(); // Distance between objects - d = constrain(d,5.0,25.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects - force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction) - float strength = (G * mass * m.mass) / (d * d); // Calculate gravitional force magnitude - force.mult(strength); // Get force vector --> magnitude * direction - return force; - } - - // Draw Sun - void display() { - stroke(255); - noFill(); - pushMatrix(); - translate(location.x,location.y,location.z); - sphere(mass*2); - popMatrix(); - } -} - - diff --git a/mode/examples/Topics/Simulate/MultipleParticleSystems/CrazyParticle.pde b/mode/examples/Topics/Simulate/MultipleParticleSystems/CrazyParticle.pde deleted file mode 100644 index 02b2dfa97..000000000 --- a/mode/examples/Topics/Simulate/MultipleParticleSystems/CrazyParticle.pde +++ /dev/null @@ -1,47 +0,0 @@ -// A subclass of Particle - -class CrazyParticle extends Particle { - - // Just adding one new variable to a CrazyParticle - // It inherits all other fields from "Particle", and we don't have to retype them! - float theta; - - // The CrazyParticle constructor can call the parent class (super class) constructor - CrazyParticle(PVector l) { - // "super" means do everything from the constructor in Particle - super(l); - // One more line of code to deal with the new variable, theta - theta = 0.0; - - } - - // Notice we don't have the method run() here; it is inherited from Particle - - // This update() method overrides the parent class update() method - void update() { - super.update(); - // Increment rotation based on horizontal velocity - float theta_vel = (vel.x * vel.mag()) / 10.0f; - theta += theta_vel; - } - - // Override timer - void timer() { - timer -= 0.5; - } - - // Method to display - void render() { - // Render the ellipse just like in a regular particle - super.render(); - - // Then add a rotating line - pushMatrix(); - translate(loc.x,loc.y); - rotate(theta); - stroke(255,timer); - line(0,0,25,0); - popMatrix(); - } -} - diff --git a/mode/examples/Topics/Simulate/MultipleParticleSystems/MultipleParticleSystems.pde b/mode/examples/Topics/Simulate/MultipleParticleSystems/MultipleParticleSystems.pde deleted file mode 100644 index 960f7c03b..000000000 --- a/mode/examples/Topics/Simulate/MultipleParticleSystems/MultipleParticleSystems.pde +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Multiple Particle Systems - * by Daniel Shiffman. - * - * Click the mouse to generate a burst of particles - * at mouse location. - * - * Each burst is one instance of a particle system - * with Particles and CrazyParticles (a subclass of Particle) - * Note use of Inheritance and Polymorphism here. - */ - -ArrayList psystems; - -void setup() { - size(640, 360); - colorMode(RGB, 255, 255, 255, 100); - psystems = new ArrayList(); - smooth(); -} - -void draw() { - background(0); - - // Cycle through all particle systems, run them and delete old ones - for (int i = psystems.size()-1; i >= 0; i--) { - ParticleSystem psys = (ParticleSystem) psystems.get(i); - psys.run(); - if (psys.dead()) { - psystems.remove(i); - } - } - -} - -// When the mouse is pressed, add a new particle system -void mousePressed() { - psystems.add(new ParticleSystem(int(random(5,25)),new PVector(mouseX,mouseY))); -} - - - - - - - - - - - diff --git a/mode/examples/Topics/Simulate/MultipleParticleSystems/Particle.pde b/mode/examples/Topics/Simulate/MultipleParticleSystems/Particle.pde deleted file mode 100644 index f06feae24..000000000 --- a/mode/examples/Topics/Simulate/MultipleParticleSystems/Particle.pde +++ /dev/null @@ -1,57 +0,0 @@ -// A simple Particle class - -class Particle { - PVector loc; - PVector vel; - PVector acc; - float r; - float timer; - - // One constructor - Particle(PVector a, PVector v, PVector l, float r_) { - acc = a.get(); - vel = v.get(); - loc = l.get(); - r = r_; - timer = 100.0; - } - - // Another constructor (the one we are using here) - Particle(PVector l) { - acc = new PVector(0,0.05,0); - vel = new PVector(random(-1,1),random(-2,0),0); - loc = l.get(); - r = 10.0; - timer = 100.0; - } - - - void run() { - update(); - render(); - } - - // Method to update location - void update() { - vel.add(acc); - loc.add(vel); - timer -= 1.0; - } - - // Method to display - void render() { - ellipseMode(CENTER); - stroke(255,timer); - fill(100,timer); - ellipse(loc.x,loc.y,r,r); - } - - // Is the particle still useful? - boolean dead() { - if (timer <= 0.0) { - return true; - } else { - return false; - } - } -} diff --git a/mode/examples/Topics/Simulate/MultipleParticleSystems/ParticleSystem.pde b/mode/examples/Topics/Simulate/MultipleParticleSystems/ParticleSystem.pde deleted file mode 100644 index 9322a70af..000000000 --- a/mode/examples/Topics/Simulate/MultipleParticleSystems/ParticleSystem.pde +++ /dev/null @@ -1,51 +0,0 @@ -// An ArrayList is used to manage the list of Particles - -class ParticleSystem { - - ArrayList particles; // An arraylist for all the particles - PVector origin; // An origin point for where particles are birthed - - ParticleSystem(int num, PVector v) { - particles = new ArrayList(); // Initialize the arraylist - origin = v.get(); // Store the origin point - for (int i = 0; i < num; i++) { - // We have a 50% chance of adding each kind of particle - if (random(1) < 0.5) { - particles.add(new CrazyParticle(origin)); - } else { - particles.add(new Particle(origin)); - } - } - } - - void run() { - // Cycle through the ArrayList backwards b/c we are deleting - for (int i = particles.size()-1; i >= 0; i--) { - Particle p = (Particle) particles.get(i); - p.run(); - if (p.dead()) { - particles.remove(i); - } - } - } - - void addParticle() { - particles.add(new Particle(origin)); - } - - void addParticle(Particle p) { - particles.add(p); - } - - // A method to test if the particle system still has particles - boolean dead() { - if (particles.isEmpty()) { - return true; - } - else { - return false; - } - } - -} - diff --git a/mode/examples/Topics/Simulate/SimpleParticleSystem/Particle.pde b/mode/examples/Topics/Simulate/SimpleParticleSystem/Particle.pde deleted file mode 100644 index ec638a61a..000000000 --- a/mode/examples/Topics/Simulate/SimpleParticleSystem/Particle.pde +++ /dev/null @@ -1,67 +0,0 @@ -// A simple Particle class - -class Particle { - PVector loc; - PVector vel; - PVector acc; - float r; - float timer; - - // Another constructor (the one we are using here) - Particle(PVector l) { - acc = new PVector(0,0.05,0); - vel = new PVector(random(-1,1),random(-2,0),0); - loc = l.get(); - r = 10.0; - timer = 100.0; - } - - void run() { - update(); - render(); - } - - // Method to update location - void update() { - vel.add(acc); - loc.add(vel); - timer -= 1.0; - } - - // Method to display - void render() { - ellipseMode(CENTER); - stroke(255,timer); - fill(100,timer); - ellipse(loc.x,loc.y,r,r); - displayVector(vel,loc.x,loc.y,10); - } - - // Is the particle still useful? - boolean dead() { - if (timer <= 0.0) { - return true; - } else { - return false; - } - } - - void displayVector(PVector v, float x, float y, float scayl) { - pushMatrix(); - float arrowsize = 4; - // Translate to location to render vector - translate(x,y); - stroke(255); - // Call vector heading function to get direction (note that pointing up is a heading of 0) and rotate - rotate(v.heading()); - // Calculate length of vector & scale it to be bigger or smaller if necessary - float len = v.mag()*scayl; - // Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction) - line(0,0,len,0); - line(len,0,len-arrowsize,+arrowsize/2); - line(len,0,len-arrowsize,-arrowsize/2); - popMatrix(); - } - -} - diff --git a/mode/examples/Topics/Simulate/SimpleParticleSystem/ParticleSystem.pde b/mode/examples/Topics/Simulate/SimpleParticleSystem/ParticleSystem.pde deleted file mode 100644 index 3d6829d83..000000000 --- a/mode/examples/Topics/Simulate/SimpleParticleSystem/ParticleSystem.pde +++ /dev/null @@ -1,50 +0,0 @@ -// A class to describe a group of Particles -// An ArrayList is used to manage the list of Particles - -class ParticleSystem { - - ArrayList particles; // An arraylist for all the particles - PVector origin; // An origin point for where particles are born - - ParticleSystem(int num, PVector v) { - particles = new ArrayList(); // Initialize the arraylist - origin = v.get(); // Store the origin point - for (int i = 0; i < num; i++) { - particles.add(new Particle(origin)); // Add "num" amount of particles to the arraylist - } - } - - void run() { - // Cycle through the ArrayList backwards b/c we are deleting - for (int i = particles.size()-1; i >= 0; i--) { - Particle p = (Particle) particles.get(i); - p.run(); - if (p.dead()) { - particles.remove(i); - } - } - } - - void addParticle() { - particles.add(new Particle(origin)); - } - - void addParticle(float x, float y) { - particles.add(new Particle(new PVector(x,y))); - } - - void addParticle(Particle p) { - particles.add(p); - } - - // A method to test if the particle system still has particles - boolean dead() { - if (particles.isEmpty()) { - return true; - } else { - return false; - } - } - -} - diff --git a/mode/examples/Topics/Simulate/SimpleParticleSystem/SimpleParticleSystem.pde b/mode/examples/Topics/Simulate/SimpleParticleSystem/SimpleParticleSystem.pde deleted file mode 100644 index 2e01b424d..000000000 --- a/mode/examples/Topics/Simulate/SimpleParticleSystem/SimpleParticleSystem.pde +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Simple Particle System - * by Daniel Shiffman. - * - * Particles are generated each cycle through draw(), - * fall with gravity and fade out over time - * A ParticleSystem object manages a variable size (ArrayList) - * list of particles. - */ - -ParticleSystem ps; - -void setup() { - size(640, 360); - colorMode(RGB, 255, 255, 255, 100); - ps = new ParticleSystem(1, new PVector(width/2,height/2,0)); - smooth(); -} - -void draw() { - background(0); - ps.run(); - ps.addParticle(mouseX,mouseY); -} - - - diff --git a/mode/examples/Topics/Simulate/SmokeParticleSystem/Particle.pde b/mode/examples/Topics/Simulate/SmokeParticleSystem/Particle.pde deleted file mode 100644 index 5ef219f68..000000000 --- a/mode/examples/Topics/Simulate/SmokeParticleSystem/Particle.pde +++ /dev/null @@ -1,59 +0,0 @@ - -// A simple Particle class, renders the particle as an image - -class Particle { - PVector loc; - PVector vel; - PVector acc; - float lifespan; - PImage img; - - Particle(PVector l,PImage img_) { - acc = new PVector(0,0); - float vx = randomGaussian()*0.3; - float vy = randomGaussian()*0.3 - 1.0; - vel = new PVector(vx,vy); - loc = l.get(); - lifespan = 100.0; - img = img_; - } - - void run() { - update(); - render(); - } - - // Method to apply a force vector to the Particle object - // Note we are ignoring "mass" here - void applyForce(PVector f) { - acc.add(f); - } - - // Method to update location - void update() { - vel.add(acc); - loc.add(vel); - lifespan -= 2.5; - acc.mult(0); // clear Acceleration - } - - // Method to display - void render() { - imageMode(CENTER); - tint(255,lifespan); - image(img,loc.x,loc.y); - // Drawing a circle instead - // fill(255,lifespan); - // noStroke(); - // ellipse(loc.x,loc.y,img.width,img.height); - } - - // Is the particle still useful? - boolean isDead() { - if (lifespan <= 0.0) { - return true; - } else { - return false; - } - } -} diff --git a/mode/examples/Topics/Simulate/SmokeParticleSystem/ParticleSystem.pde b/mode/examples/Topics/Simulate/SmokeParticleSystem/ParticleSystem.pde deleted file mode 100644 index a101200bb..000000000 --- a/mode/examples/Topics/Simulate/SmokeParticleSystem/ParticleSystem.pde +++ /dev/null @@ -1,42 +0,0 @@ -// A class to describe a group of Particles -// An ArrayList is used to manage the list of Particles - -class ParticleSystem { - - ArrayList particles; // An arraylist for all the particles - PVector origin; // An origin point for where particles are birthed - PImage img; - - ParticleSystem(int num, PVector v, PImage img_) { - particles = new ArrayList(); // Initialize the arraylist - origin = v.get(); // Store the origin point - img = img_; - for (int i = 0; i < num; i++) { - particles.add(new Particle(origin, img)); // Add "num" amount of particles to the arraylist - } - } - - void run() { - for (int i = particles.size()-1; i >= 0; i--) { - Particle p = particles.get(i); - p.run(); - if (p.isDead()) { - particles.remove(i); - } - } - } - - // Method to add a force vector to all particles currently in the system - void applyForce(PVector dir) { - // Enhanced loop!!! - for (Particle p : particles) { - p.applyForce(dir); - } - - } - - void addParticle() { - particles.add(new Particle(origin,img)); - } - -} diff --git a/mode/examples/Topics/Simulate/SmokeParticleSystem/SmokeParticleSystem.pde b/mode/examples/Topics/Simulate/SmokeParticleSystem/SmokeParticleSystem.pde deleted file mode 100644 index 32683de91..000000000 --- a/mode/examples/Topics/Simulate/SmokeParticleSystem/SmokeParticleSystem.pde +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Smoke Particle System - * by Daniel Shiffman. - * - * A basic smoke effect using a particle system. Each particle - * is rendered as an alpha masked image. - */ - -ParticleSystem ps; - -void setup() { - size(640,360); - PImage img = loadImage("texture.png"); - ps = new ParticleSystem(0,new PVector(width/2,height-60),img); -} - -void draw() { - background(0); - - // Calculate a "wind" force based on mouse horizontal position - float dx = map(mouseX,0,width,-0.2,0.2); - PVector wind = new PVector(dx,0); - ps.applyForce(wind); - ps.run(); - for (int i = 0; i < 2; i++) { - ps.addParticle(); - } - - // Draw an arrow representing the wind force - drawVector(wind, new PVector(width/2,50,0),500); - -} - -// Renders a vector object 'v' as an arrow and a location 'loc' -void drawVector(PVector v, PVector loc, float scayl) { - pushMatrix(); - float arrowsize = 4; - // Translate to location to render vector - translate(loc.x,loc.y); - stroke(255); - // Call vector heading function to get direction (note that pointing up is a heading of 0) and rotate - rotate(v.heading()); - // Calculate length of vector & scale it to be bigger or smaller if necessary - float len = v.mag()*scayl; - // Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction) - line(0,0,len,0); - line(len,0,len-arrowsize,+arrowsize/2); - line(len,0,len-arrowsize,-arrowsize/2); - popMatrix(); -} diff --git a/mode/examples/Topics/Simulate/SmokeParticleSystem/data/texture.gif b/mode/examples/Topics/Simulate/SmokeParticleSystem/data/texture.gif deleted file mode 100644 index 17e84e806..000000000 Binary files a/mode/examples/Topics/Simulate/SmokeParticleSystem/data/texture.gif and /dev/null differ diff --git a/mode/examples/Topics/Simulate/SmokeParticleSystem/data/texture.png b/mode/examples/Topics/Simulate/SmokeParticleSystem/data/texture.png deleted file mode 100644 index 0852c88e1..000000000 Binary files a/mode/examples/Topics/Simulate/SmokeParticleSystem/data/texture.png and /dev/null differ diff --git a/mode/examples/Topics/Simulate/SoftBody/SoftBody.pde b/mode/examples/Topics/Simulate/SoftBody/SoftBody.pde deleted file mode 100644 index 9372af389..000000000 --- a/mode/examples/Topics/Simulate/SoftBody/SoftBody.pde +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Soft Body - * by Ira Greenberg. - * - * Softbody dynamics simulation using curveVertex() and curveTightness(). - */ - -// center point -float centerX = 0, centerY = 0; - -float radius = 45, rotAngle = -90; -float accelX, accelY; -float springing = .0009, damping = .98; - -//corner nodes -int nodes = 5; -float nodeStartX[] = new float[nodes]; -float nodeStartY[] = new float[nodes]; -float[]nodeX = new float[nodes]; -float[]nodeY = new float[nodes]; -float[]angle = new float[nodes]; -float[]frequency = new float[nodes]; - -// soft-body dynamics -float organicConstant = 1; - -void setup() { - size(640, 360); - //center shape in window - centerX = width/2; - centerY = height/2; - // iniitalize frequencies for corner nodes - for (int i=0; i left && mouseX < right && mouseY > ps && mouseY < ps + s_height) { - over = true; - } else { - over = false; - } - - // Set and constrain the position of top bar - if(move) { - ps = mouseY - s_height/2; - if (ps < min) { ps = min; } - if (ps > max) { ps = max; } - } -} - -void mousePressed() { - if(over) { - move = true; - } -} - -void mouseReleased() -{ - move = false; -} diff --git a/mode/examples/Topics/Simulate/Springs/Springs.pde b/mode/examples/Topics/Simulate/Springs/Springs.pde deleted file mode 100644 index c615d4819..000000000 --- a/mode/examples/Topics/Simulate/Springs/Springs.pde +++ /dev/null @@ -1,162 +0,0 @@ -/** - * Springs. - * - * Move the mouse over one of the circles and click to re-position. - * When you release the mouse, it will snap back into position. - * Each circle has a slightly different behavior. - */ - - -int num = 3; -Spring[] springs = new Spring[num]; - -void setup() -{ - size(200, 200); - noStroke(); - smooth(); - springs[0] = new Spring( 70, 160, 20, 0.98, 8.0, 0.1, springs, 0); - springs[1] = new Spring(150, 110, 60, 0.95, 9.0, 0.1, springs, 1); - springs[2] = new Spring( 40, 70, 120, 0.90, 9.9, 0.1, springs, 2); -} - -void draw() -{ - background(51); - - for (int i = 0; i < num; i++) { - springs[i].update(); - springs[i].display(); - } -} - -void mousePressed() -{ - for (int i = 0; i < num; i++) { - springs[i].pressed(); - } -} - -void mouseReleased() -{ - for (int i=0; i width) || (location.x < 0)) { - velocity.x = velocity.x * -1; - } - if (location.y > height) { - // We're reducing velocity ever so slightly - // when it hits the bottom of the window - velocity.y = velocity.y * -0.95; - location.y = height; - } - - // Display circle at location vector - stroke(255); - strokeWeight(2); - fill(127); - ellipse(location.x,location.y,48,48); -} - - diff --git a/mode/examples/Topics/Vectors/Normalize/Normalize.pde b/mode/examples/Topics/Vectors/Normalize/Normalize.pde deleted file mode 100644 index 95bd8525a..000000000 --- a/mode/examples/Topics/Vectors/Normalize/Normalize.pde +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Normalize - * by Daniel Shiffman. - * - * Demonstration of normalizing a vector. - * Normalizing a vector sets its length to 1. - */ - -void setup() { - size(640,360); - smooth(); -} - -void draw() { - background(0); - - // A vector that points to the mouse location - PVector mouse = new PVector(mouseX,mouseY); - // A vector that points to the center of the window - PVector center = new PVector(width/2,height/2); - // Subtract center from mouse which results in a vector that points from center to mouse - mouse.sub(center); - - // Normalize the vector - mouse.normalize(); - - // Multiply its length by 50 - mouse.mult(150); - - translate(width/2,height/2); - // Draw the resulting vector - stroke(255); - line(0,0,mouse.x,mouse.y); - -} - - diff --git a/mode/examples/Topics/Vectors/VectorMath/VectorMath.pde b/mode/examples/Topics/Vectors/VectorMath/VectorMath.pde deleted file mode 100644 index fcc609234..000000000 --- a/mode/examples/Topics/Vectors/VectorMath/VectorMath.pde +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Vector - * by Daniel Shiffman. - * - * Demonstration some basic vector math: subtraction, normalization, scaling - * Normalizing a vector sets its length to 1. - */ - -void setup() { - size(640,360); - smooth(); -} - -void draw() { - background(0); - - // A vector that points to the mouse location - PVector mouse = new PVector(mouseX,mouseY); - // A vector that points to the center of the window - PVector center = new PVector(width/2,height/2); - // Subtract center from mouse which results in a vector that points from center to mouse - mouse.sub(center); - - // Normalize the vector - mouse.normalize(); - - // Multiply its length by 150 (Scaling its length) - mouse.mult(150); - - translate(width/2,height/2); - // Draw the resulting vector - stroke(255); - line(0,0,mouse.x,mouse.y); - -} - - diff --git a/mode/examples/Topics/Wallpapers/Circles/Circles.pde b/mode/examples/Topics/Wallpapers/Circles/Circles.pde deleted file mode 100644 index 4a66fb071..000000000 --- a/mode/examples/Topics/Wallpapers/Circles/Circles.pde +++ /dev/null @@ -1,17 +0,0 @@ -void setup() { - fullScreen(P2D); - noStroke(); - background(255); -} - -void draw() { - if (mousePressed) { - background(255); - } - float x = random(width); - float y = random(height); - color c = color(random(255), random(255), random(255)); - float r = random(10, 30); - fill(c); - ellipse(x, y, r, r); -} \ No newline at end of file diff --git a/mode/examples/Topics/Wallpapers/Circles/code/sketch.properties b/mode/examples/Topics/Wallpapers/Circles/code/sketch.properties deleted file mode 100644 index 181123ebe..000000000 --- a/mode/examples/Topics/Wallpapers/Circles/code/sketch.properties +++ /dev/null @@ -1 +0,0 @@ -component=wallpaper diff --git a/mode/examples/Topics/Watchfaces/WatchFace/WatchFace.pde b/mode/examples/Topics/Watchfaces/WatchFace/WatchFace.pde deleted file mode 100644 index 78285839d..000000000 --- a/mode/examples/Topics/Watchfaces/WatchFace/WatchFace.pde +++ /dev/null @@ -1,28 +0,0 @@ -float angle = 0; - -void setup() { - fullScreen(P2D); - frameRate(15); -} - -void draw() { - translate(0, +wearInsets().bottom/2); - - if (wearAmbient()) { - background(0); - stroke(255); - noFill(); - } else { - background(157); - stroke(0); - fill(255); - } - - line(0, 0, width, height); - line(width, 0, 0, height); - - translate(width/2, height/2); - rotate(angle); - rect(-50, -50, 100, 100); - angle += 0.01; -} \ No newline at end of file diff --git a/mode/examples/Topics/Watchfaces/WatchFace/code/sketch.properties b/mode/examples/Topics/Watchfaces/WatchFace/code/sketch.properties deleted file mode 100644 index a70fa2ba6..000000000 --- a/mode/examples/Topics/Watchfaces/WatchFace/code/sketch.properties +++ /dev/null @@ -1 +0,0 @@ -component=watchface diff --git a/mode/icons/launcher_144.png b/mode/icons/launcher_144.png deleted file mode 100644 index 78fed6592..000000000 Binary files a/mode/icons/launcher_144.png and /dev/null differ diff --git a/mode/icons/launcher_192.png b/mode/icons/launcher_192.png deleted file mode 100644 index 48d3a34fe..000000000 Binary files a/mode/icons/launcher_192.png and /dev/null differ diff --git a/mode/icons/launcher_36.png b/mode/icons/launcher_36.png deleted file mode 100644 index e276bbd6f..000000000 Binary files a/mode/icons/launcher_36.png and /dev/null differ diff --git a/mode/icons/launcher_48.png b/mode/icons/launcher_48.png deleted file mode 100644 index 9dde1a58f..000000000 Binary files a/mode/icons/launcher_48.png and /dev/null differ diff --git a/mode/icons/launcher_72.png b/mode/icons/launcher_72.png deleted file mode 100644 index ff769c587..000000000 Binary files a/mode/icons/launcher_72.png and /dev/null differ diff --git a/mode/icons/launcher_96.png b/mode/icons/launcher_96.png deleted file mode 100644 index d9b25dba2..000000000 Binary files a/mode/icons/launcher_96.png and /dev/null differ diff --git a/mode/icons/preview_circular.png b/mode/icons/preview_circular.png deleted file mode 100644 index 40a11bf0d..000000000 Binary files a/mode/icons/preview_circular.png and /dev/null differ diff --git a/mode/icons/preview_rectangular.png b/mode/icons/preview_rectangular.png deleted file mode 100644 index 9c9d9ed41..000000000 Binary files a/mode/icons/preview_rectangular.png and /dev/null differ diff --git a/mode/keywords.txt b/mode/keywords.txt deleted file mode 100644 index b16ac21d4..000000000 --- a/mode/keywords.txt +++ /dev/null @@ -1,50 +0,0 @@ -# Android-specific keywords - -# For an explanation of these tags, see Token.java -# processing/app/src/processing/app/syntax/Token.java - -VR LITERAL2 -AR LITERAL2 -STEREO LITERAL2 -MONO LITERAL2 -PORTRAIT LITERAL2 -LANDSCAPE LITERAL2 -displayDensity KEYWORD4 - -orientation FUNCTION1 -hasPermission FUNCTION1 -requestPermission FUNCTION1 -touches KEYWORD4 -touchEnded FUNCTION4 -touchMoved FUNCTION4 -touchStarted FUNCTION4 -closeKeyboard FUNCTION1 -openKeyboard FUNCTION1 -wallpaperHomeCount FUNCTION1 -wallpaperOffset FUNCTION1 -wallpaperPreview FUNCTION1 -wearAmbient FUNCTION1 -wearBurnIn FUNCTION1 -wearInsets FUNCTION1 -wearInteractive FUNCTION1 -wearLowBit FUNCTION1 -wearRound FUNCTION1 -wearSquare FUNCTION1 -cameraUp FUNCTION1 -eye FUNCTION1 -getEyeMatrix FUNCTION1 -getObjectMatrix FUNCTION1 -getRayFromScreen FUNCTION1 -intersectsSphere FUNCTION1 -intersectsBox FUNCTION1 -intersectsPlane FUNCTION1 -calculate FUNCTION1 -push FUNCTION1 -pop FUNCTION1 -circle FUNCTION1 -square FUNCTION1 - -VRCamera KEYWORD5 -ARTracker KEYWORD5 -ARTrackable KEYWORD5 -ARAnchor KEYWORD5 diff --git a/mode/languages/mode.properties b/mode/languages/mode.properties deleted file mode 100644 index 35500f539..000000000 --- a/mode/languages/mode.properties +++ /dev/null @@ -1,328 +0,0 @@ - - -# --------------------------------------- -# Language: English (en) (default) -# --------------------------------------- - - -# --------------------------------------- -# Menu - -# | File | Edit | Sketch | Android | Tools | Help | -# | File | - -menu.sketch.stop = Stop -menu.file.new = New -menu.file.open = Open -menu.file.save = Save - -menu.file.export_signed_package = Export Signed Package -menu.file.export_signed_bundle = Export Signed Bundle -menu.file.export_android_project = Export Android Project - - -# | File | Edit | Sketch | Android | Tools | Help | -# | Sketch | - -menu.sketch.run_on_device = Run on Device -menu.sketch.run_in_emulator = Run in Emulator - -# | File | Edit | Sketch | Android | Tools | Help | -# | Android | - -menu.android = Android -menu.android.sketch_permissions = Sketch Permissions -menu.android.app = App -menu.android.wallpaper = Wallpaper -menu.android.watch_face = Watch Face -menu.android.vr = VR -menu.android.ar = AR -menu.android.devices = Devices -menu.android.devices.no_connected_devices = No connected devices -menu.android.sdk_updater = SDK Updater -menu.android.reset_adb = Reset ADB - -# | File | Edit | Sketch | Android | Tools | Help | -# | Help | - -menu.help.processing_for_android_site = Processing for Android Site -menu.help.android_developer_site = Android Developer Site - -# --------------------------------------- -# Android Build - -android_build.error.build_folder = Build folder: %s -android_build.error.export_file_does_not_exist = "%s" is mentioned in export.txt, but it's a big fat lie and does not exist. -android_build.error.cannot_create_build_folder = Cannot create temp dir "%s" to build android sketch -android_build.error.zip_files_not_allowed = .zip files are not allowed in Android libraries.\nPlease rename "%s to be a .jar file. -android_build.error.cannot_copy_icons = Problem while copying icons. -android_build.error.cannot_create_icon_folder = Could not create "%s" folder -android_build.warn.cannot_find_zipalign.title = Cannot find zipaling... -android_build.warn.cannot_find_zipalign.body = The zipalign build tool needed to prepare the export bundle is missing.\nMake sure that your Android SDK was downloaded correctly. - -# --------------------------------------- -# Android Debugger - -android_debugger.info.attaching_debugger = Attaching debugger... -android_debugger.info.debugger_attached = Debugger attached -android_debugger.error.debugger_exception = Debugger error: %s - -# --------------------------------------- -# Android Editor - -android_editor.status.exporting_project = Exporting an Android project of the sketch... -android_editor.status.project_export_completed = Done with project export. -android_editor.status.project_export_failed = Error with project export. -android_editor.status.exporting_package = Exporting signed package... -android_editor.status.package_export_completed = Done with package export. -android_editor.status.package_export_failed = Error with package export. -android_editor.status.exporting_bundle = Exporting signed bundle... -android_editor.status.bundle_export_completed = Done with bundle export. -android_editor.status.bundle_export_failed = Error with bundle export. - -android_editor.error.cannot_create_sketch_properties = Error While creating sketch properties file "%s": %s - -# --------------------------------------- -# Android Keystore - -android_keystore.warn.cannot_create_folders.title = Folders, folders, folders -android_keystore.warn.cannot_create_folders.body = Could not create the necessary folders to build.\nPerhaps you have some file permissions to sort out? -android_keystore.warn.cannot_find_keystore.title = Well, this is unexpected... -android_keystore.warn.cannot_find_keystore.body = The keystore was succesfully created but cannot be found.\nPerhaps was it deleted accidentally? -android_keystore.error.cannot_create_keystore = The keystore could not be created, due to the following error: - -# --------------------------------------- -# Android Mode - -android_mode.dialog.watchface_debug_title = Is the watch connected to the computer? -android_mode.dialog.watchface_debug_body = Processing will install watch faces on a smartwatch either over Wi-Fi or via Bluetooth, in which case the watch needs to be paired with a phone.

    Read this guide on debugging an Android Wear App for more details. -android_mode.dialog.wallpaper_installed_title = Wallpaper installed! -android_mode.dialog.wallpaper_installed_body = Processing just built and installed your sketch as a live wallpaper on the selected device.

    You need to open the wallpaper picker in the device in order to select it as the new background. -android_mode.dialog.watchface_installed_title = Watch face installed! -android_mode.dialog.watchface_installed_body = Processing just built and installed your sketch as a watch face on the selected device.

    You need to add it as a favourite watch face on the device and then select it from the watch face picker in order to run it. -android_mode.dialog.cannot_export_package_title = Cannot complete export... -android_mode.dialog.cannot_export_package_body = The sketch still has the default package name. Not good, since this name will uniquely identify your app on the Play store... for ever! Come up with a different package name and write in the AndroidManifest.xml file in the sketch folder, after the "package=" attribute inside the manifest tag, which also contains version code and name. Once you have done that, try exporting the sketch again.

    For more info on distributing apps from Processing,
    check this online tutorial. -android_mode.dialog.cannot_use_default_icons_title = Cannot complete export... -android_mode.dialog.cannot_use_default_icons_body = The sketch does not include all required app icons. Processing could use its default set of Android icons, which are okay to test the app on your device, but a bad idea to distribute it on the Play store. Create a full set of unique icons for your app, and copy them into the sketch folder. Once you have done that, try exporting the sketch again.

    For more info on distributing apps from Processing,
    check this online tutorial. -android_mode.warn.cannot_load_sdk_title = Bad news... -android_mode.warn.cannot_load_sdk_body = The Android SDK could not be loaded.\nThe Android Mode will be disabled. -android_mode.info.cannot_open_sdk_path = "Android SDK path couldn't be opened."; -android_mode.error.cannot_create_avd = "Could not create a virtual device for the emulator."; -android_mode.error.emulator_installation_failed = "Encountered Issues with the emulator installation. Result Code is non-zero"; -android_mode.dialog.no_devices_found_title = No devices found! -android_mode.dialog.no_devices_found_body = Processing did not find any device where to run\nyour sketch on. Make sure that your handheld or\nwearable is properly connected to the computer\nand that USB or Bluetooth debugging is enabled. -android_mode.status.no_devices_found = No devices found. -android_mode.status.starting_project_build = Starting build... -android_mode.status.building_project = Building Android project... -android_mode.status.project_build_failed = Build failed. -android_mode.status.downloading_emulator = Downloading Emulator... -android_mode.status.downloading_emulator_successful = Emulator installation was successful. - -# --------------------------------------- -# Android Preprocessor - -android_preprocessor.error.cannot_parse_size = More about the size() command on Android can be\nfound here: http://wiki.processing.org/w/Android -android_preprocessor.error.cannot_parse_size_exception = Could not parse the size() command. -android_preprocessor.error.cannot_parse_smooth = More about the smooth() command on Android can be\nfound here: http://wiki.processing.org/w/Android -android_preprocessor.error.cannot_parse_smooth_exception = Could not parse the smooth() command. -android_preprocessor.warn.cannot_find_smooth_level_title = Could not find smooth level -android_preprocessor.warn.cannot_find_smooth_level_body = The smooth level of this applet could not automatically\nbe determined from your code. Use only a numeric\nvalue (not variables) for the smooth() command.\nSee the smooth() reference for an explanation. - -# --------------------------------------- -# Android Runner - -android_runner.status.waiting_for_device = Waiting for %s to become available... -android_runner.status.lost_connection_with_device = Lost connection with %s while launching. Try again. -android_runner.status.cannot_install_sketch = Could not install the sketch. -android_runner.warn.non_watch_device_title = Selected device is not a watch... -android_runner.warn.non_watch_device_body = You are trying to install a watch face on a non-watch device.\n" + "Select the correct device, or use the emulator. -android_runner.warn.watch_device_title = Selected device is a watch... -android_runner.warn.watch_device_body = You are trying to install a non-watch app on a watch. Select the correct device, or use the emulator. -android_runner.status.installing_sketch = Installing sketch on %s -android_runner.status.lost_connection = Lost connection with %s while installing. Try again. -android_runner.status.sketch_installed = Sketch installed -android_runner.status.cannot_install_sketch = Could not install the sketch. -android_runner.status.launching_sketch = Starting sketch on %s -android_runner.status.sketch_launched= Sketch installed -android_runner.status.cannot_launch_sketch = Could not start the sketch. -android_runner.status.in_emulator = in the emulator -android_runner.status.on_device = on the device -android_runner.status.cancel_waiting_for_device = No, on second thought, I'm giving up on waiting for that device to show up. -android_runner.error.cannot_parse_stacktrace = Can't parse this exception line: -android_runner.status.unknwon_exception = Unknown exception - -# --------------------------------------- -# Android SDK - -android_sdk.dialog.found_installed_sdk_title = Found an Android SDK! -android_sdk.dialog.found_installed_sdk_body = Processing found a valid Android SDK that seems to be in use already. Processing could use this SDK too, or download a new one.

    Sharing the same SDK across different development tools, like Processing and Android Studio, will save space (the SDK may use up to several GBs), but when one tool updates the SDK, it can create problems in the other. If Processing downloads a new SDK, it will keep it separate from the one it just found.

    What do you want to do? -android_sdk.option.use_existing_sdk = Use existing SDK -android_sdk.option.download_new_sdk = Download new SDK -android_sdk.dialog.cannot_find_sdk_title = Cannot find an Android SDK... -android_sdk.dialog.cannot_find_sdk_body = Processing did not find an Android SDK on this computer. If there is one, and you know where it is, click "Locate SDK path" to select it, or "Download SDK" to let Processing download the SDK automatically.

    If you want to download the SDK manually, you can get the command line tools from here. Make sure to install the SDK platform for API %s. -android_sdk.dialog.invalid_sdk_title = Android SDK is not valid... -android_sdk.dialog.invalid_sdk_body = Processing found an Android SDK, but is not valid. It could be missing some files, or might not be including the required platform for API %s.

    If a valid SDK is available in a different location, click "Locate SDK path" to select it, or "Download SDK" to let Processing download the SDK automatically.

    If you want to download the SDK manually, you can get the command line tools from here. Make sure to install the SDK platform for API %s. -android_sdk.option.download_sdk = Download SDK automatically -android_sdk.option.locate_sdk = Locate SDK path manually -android_sdk.dialog.download_phone_image_title = Download phone system image? -android_sdk.dialog.download_phone_image_body = The system image needed by the emulator does not appear to be installed. Do you want Processing to download and install it now? -android_sdk.dialog.download_watch_image_title = Download watch system image? -android_sdk.dialog.download_watch_image_body = The system image needed by the emulator does not appear to be installed. Do you want Processing to download and install it now? -android_sdk.dialog.select_sdk_folder = Choose the location of the Android SDK -android_sdk.error.sdk_selection_canceled = User canceled attempt to find SDK -android_sdk.error.sdk_download_canceled = User canceled SDK download -android_sdk.error.sdk_download_failed = SDK could not be downloaded -android_sdk.dialog.sdk_installed_title = SDK installed! -android_sdk.dialog.sdk_installed_body = Processing just downloaded and installed the Android SDK successfully. The Android mode is now ready to use!

    For documentation, examples, and tutorials, visit the Processing for Android website, and if you updated from version 3 of the mode, check the what's new page. -android_sdk.dialog.install_usb_driver =

    If you are planning to use Google Nexus devices, then you need the Google USB Driver to connect them to Processing. You will have to install the driver manually following these instructions.

    The installation files are available in this folder:
    %s -android_sdk.dialog.sdk_license_rejected_title = SDK license not accepted -android_sdk.dialog.sdk_license_rejected_body = The Android SDK was installed, but will not be usable. You can accept the license at a later time by opening a terminal, changing to the SDK folder, and then running the following command:

    tools/bin/sdkmanager --licenses -android_sdk.dialog.32bit_system_title = System is 32 bit... -android_sdk.dialog.32bit_system_body = The Android SDK no longer includes 32 bit platform tools (adb, etc.), and so they will not work.

    This thread provides some possible workarounds. -android_sdk.error.emulator_download_canceled = User canceled emulator download -android_sdk.error.emulator_download_failed = Emulator could not be downloaded -android_sdk.dialog.using_existing_sdk_title = SDK configured! -android_sdk.dialog.using_existing_sdk_body = Processing will use the existing Android SDK. The Android mode is now ready to use!

    For documentation, examples, and tutorials, visit the Processing for Android website, and if you updated from version 3 of the mode, check the what's new page. -android_sdk.dialog.accept_sdk_license_title = Accept SDK license? -android_sdk.dialog.accept_sdk_license_body = You need to accept the terms of the Android SDK license from Google in order to use the SDK. Read the license from here. -android_sdk.warn.cannot_run_adb_title = Trouble with adb! -android_sdk.warn.cannot_run_adb_body = Could not run the adb tool from the Android SDK.\nOne possibility is that its executable permission\nis not properly set. You can try setting this\npermission manually, or re-installing the SDK.\n\nThe mode will be disabled until this problem is fixed.\n -android_sdk.error.missing_sdk_folder = %s does not exist -android_sdk.error.missing_cmdtools_folder_found_sdktools = There is no cmdline-tools/latest folder in %s and SDK Tools(sdk/tools) got deprecated.\nInstall cmdline-tools in the existing SDK specifically or Create New SDK. -android_sdk.error.missing_cmdtools_folder = There is no `cmdline-tools/latest` folder in %s \nInstall cmdline-tools in the existing SDK specifically or Create New SDK. -android_sdk.error.missing_platform_tools_folder = There is no platform-tools folder in %s -android_sdk.error.missing_build_tools_folder = There is no build-tools folder in %s -android_sdk.error.missing_platforms_folder = There is no platforms folder in %s -android_sdk.error.missing_target_platform = There is no Android %s in %s -android_sdk.error.missing_android_jar = android.jar for plaform %s is missing from %s -android_sdk.error.missing_emulator = The emulator files are missing -android_debugger.info.removing_expired_keystore = Removing expired debug.keystore file. -android_debugger.error.cannot_remove_expired_keystore = Could not remove the expired debug.keystore file. -android_debugger.error.request_removing_keystore = Please remove the file %s -android_debugger.error.invalid_keystore_timestamp = The date '%s' could not be parsed. -android_debugger.error.request_bug_report = Please report this as a bug so we can fix it. - -# --------------------------------------- -# AVD - -android_avd.error.cannot_create_avd_title = Could not create the AVD -android_avd.error.cannot_create_avd_body = The default Android emulator could not be set up. Make sure
    that the Android SDK is installed properly, and that the
    system images are installed for level %s.
    (Between you and me, occasionally, this error is a red herring,
    and your sketch may be launching shortly.) - -android_avd.error.cannot_load_avd_title = Could not load the AVD -android_avd.error.cannot_load_avd_body = This could mean that the Android tools need to be updated,
    or that the Processing AVD should be deleted (it will
    automatically re-created the next time you run Processing).

    You can use the avdmanager command line tool to create AVDs manually and list the current AVDs. - - -android_avd.error.sdk_wrong_install_title = The SDK is not properly installed -android_avd.error.sdk_wrong_install_body = Please re-read the installation instructions for Processing
    found in this online tutorial. - -# --------------------------------------- -# Devices - -android_devices.error.cannot_get_device_list = Received unfamiliar output from \u201Cadb devices\u201D.\nThe device list may have errors. - -android_devices.error.no_permissions_title = Found devices with no permissions! - -android_devices.error.no_permissions_body = Make sure that the device has USB debugging enabled, and that the required USB drivers are installed on Windows, and that permissions are properly configured on Linux. Also, on Linux, don't set the USB configuration to "charging" while debugging.

    Read this guide on running apps on hardware device for more details. - - private static final String DEVICE_PERMISSIONS_URL = - "https://developer.android.com/studio/run/device.html"; - - private static final String DEVICE_PERMISSIONS_TITLE = - ""; - - private static final String DEVICE_PERMISSIONS_MESSAGE = - -# --------------------------------------- -# Keystore manager - -keystore_manager.top_label = Please enter the information below so we can generate a private key for you.
    Fields marked bold are required, though you may consider to fill some of optional fields below those to avoid potential problems.
    More about private keys can be found here. -keystore_manager.reset_password = Reset password -keystore_manager.dialog.reset_keyboard_title = Reset password -keystore_manager.dialog.reset_keyboard_body_part1 = Are you sure you want to reset the password? -keystore_manager.dialog.reset_keyboard_body_part2 = We will have to reset the keystore to do this, which means \nyou won't be able to upload an update for your app signed with\nthe new keystore to Google Play.\n\nWe will make a backup for the old keystore. -keystore_manager.warn.cannot_remove_keystore_title = Android keystore -keystore_manager.warn.cannot_remove_keystore_body = Failed to remove keystore -keystore_manager.warn.password_missmatch_title = Passwords -keystore_manager.warn.password_missmatch_body = Keystore passwords do not match -keystore_manager.warn.short_password_title = Passwords -keystore_manager.warn.short_password_body = Keystore password should be at least 6 characters long -keystore_manager.password_label = Keystore password: -keystore_manager.repeat_password_label = Repeat keystore password: -keystore_manager.issuer_credentials_header = Keystore issuer credentials -keystore_manager.common_name_label = First and last name: -keystore_manager.organizational_unitl_label = Organizational unit: -keystore_manager.organization_name_label = Organization name: -keystore_manager.city_name_label = City or locality: -keystore_manager.state_name_label = State name: -keystore_manager.country_code_label = Country code (XX): - -# --------------------------------------- -# Manifest - -manifest.warn.cannot_handle_file_title = Error handling %s -manifest.warn.cannot_handle_file_body = Errors occurred while reading or writing %s\nwhich means lots of things are likely to stop working properly.\nTo prevent losing any data, it's recommended that you use “Save As”\n"to save a separate copy of your sketch, and then restart Processing."; - -# --------------------------------------- -# Permissions - -permissions.dialog.label = Android applications must specifically ask for permission\nto do things like connect to the internet, write a file,\nor make phone calls. When installing your application,\nusers will be asked whether they want to allow such access. -permissions.dialog.url = More about permissions can be found here. - -# --------------------------------------- -# SDK Downloader - -sdk_downloader.error_cannot_find_platform_files = Cannot find the platform files -sdk_downloader.error_cannot_find_platform_tools = Cannot find the platform-tools -sdk_downloader.error_cannot_find_build_tools = Cannot find the build-tools -sdk_downloader.error_cannot_find_tools = Cannot find the tools -sdk_downloader.error_cannot_find_emulator = Cannot find the emulator -sdk_downloader.error.cannot_unpack_platform = Error unpacking platform to "%s" -sdk_downloader.download_title = SDK download -sdk_downloader.download_sdk_label = Downloading Android SDK... - -# --------------------------------------- -# System image downloader - -sys_image_downloader.dialog.select_image_title = Choose system image type to download... -sys_image_downloader.dialog.select_image_body = The Android emulator requires a system image to run. There are two types of system images available:

    1) ARM image - slow but compatible with all computers, no extra configuration needed.

    2) x86 image - fast but compatible only with Intel CPUs, extra configuration may be needed, see this guide for more details. -sys_image_downloader.dialog.accel_images_title = Some words of caution... -sys_image_downloader.dialog.haxm_install_body = Processing will install x86 images in the emulator. These images are fast, but also need the Intel Hardware Accelerated Execution Manager (Intel HAXM).

    Processing will try to run the HAXM installer now, which may ask for your administrator password or additional permissions. -sys_image_downloader.dialog.kvm_config_body = You chose to run x86 images in the emulator. This is great but you need to configure VM acceleration on Linux using the KVM package.

    Follow these instructions to configure KVM. -sys_image_downloader.dialog.ia32libs_title = Additional setup may be required... -sys_image_downloader.dialog.ia32libs_body = Looks like you are running a 64-bit version of Linux. In order
    to create the SD card in the emulator, Processing needs the
    ia32-libs compatibility package. On Ubuntu Linux, you can
    install it by runing the following command:

    sudo apt-get install lib32stdc++6 -sys_image_downloader.option.x86_image = Use x86 image -sys_image_downloader.option.arm_image = Use ARM image -sys_image_downloader.download_title = System image download -sys_image_downloader.download_watch_label = Downloading watch system image... -sys_image_downloader.download_phone_label = Downloading phone system image... - -# --------------------------------------- -# Download strings - -download_property.change_event_total = total -download_property.change_event_downloaded = downloaded -download_prompt.cancel = Cancel download - -# --------------------------------------- -# SDK Updater tool - -sdk_updater.name_column = Package name -sdk_updater.version_column = Installed version -sdk_updater.available_column = Available update - -sdk_updater.query_message = Querying packages... - -sdk_updater.no_updates_message = No updates available -sdk_updater.one_updates_message = 1 update found! -sdk_updater.many_updates_message = "%d" updates found! - -sdk_updater.warning_failed_finding_package = Failed to find package "%s" -sdk_updater.warning_failed_computing_dependency_list = Unable to compute a complete list of dependencies. - -sdk_updater.refresh_package_message = Refreshing packages... -sdk_updater.download_package_message = Downloading available updates... -sdk_updater.download_canceled_message = Download canceled - -sdk_updater.update_button_label = Update -sdk_updater.cancel_button_label = Cancel -sdk_updater.close_button_label = Close diff --git a/mode/languages/mode_ko.properties b/mode/languages/mode_ko.properties deleted file mode 100644 index 2890bf447..000000000 --- a/mode/languages/mode_ko.properties +++ /dev/null @@ -1,31 +0,0 @@ - - -# --------------------------------------- -# KOREAN (ko) -# --------------------------------------- - - -# --------------------------------------- -# Menu - -# | File | Edit | Sketch | Android | Tools | Help | -# | File | - -menu.file.export_signed_package = 서명 된 패키지 내보내기 -menu.file.export_signed_bundle = 안드로이드 번들 내보내기 -menu.file.export_android_project = 안드로이드 프로젝트 내보내기 - -# | File | Edit | Sketch | Android | Tools | Help | -# | Android | - -menu.android = 안드로이드 -menu.android.sketch_permissions = 권한 스케치 -menu.android.app = 앱 -menu.android.wallpaper = 벽지 -menu.android.watch_face = 시계 얼굴 -menu.android.vr = VR -menu.android.ar = AR -menu.android.devices = 장치들 -menu.android.devices.no_connected_devices = 연결된 기기 없음 -menu.android.sdk_updater = SDK 업데이터 -menu.android.reset_adb = ADB 재설정 diff --git a/mode/libraries/ar/README.md b/mode/libraries/ar/README.md deleted file mode 100644 index 8dddfce92..000000000 --- a/mode/libraries/ar/README.md +++ /dev/null @@ -1,21 +0,0 @@ -![Image](imgs/bg_1.png) - -# AR library for Processing-Android - -![Android](https://img.shields.io/badge/platform-Android-green.svg?longCache=true&style=for-the-badge) ![ARCore](https://img.shields.io/badge/ARCore-v1.2.0-blue.svg?longCache=true&style=for-the-badge) ![In Progress](https://img.shields.io/badge/in--progress-true-green.svg?longCache=true&style=for-the-badge)
    -This library includes ARCore renderer to create AR apps using Processing. - -## Steps to build: -* Make sure you have both [Processing](https://github.com/processing/processing) and [Processing-Android](https://github.com/processing/processing-android) built before you proceed.
    -* For Building [Processing-Android](https://github.com/processing/processing-android) refer [Wiki](https://github.com/processing/processing-android/wiki/Building-Processing-for-Android).
    -* Once built, clone [processing-ar](https://github.com/SyamSundarKirubakaran/processing-ar) into the `Libraries` Directory right next to `vr` Directory.
    -NOTE: Rename the cloned directory as `ar` and the name of the module to be `processing-ar`.
    -* Make sure to import `processing-ar` as a module in your IDE.
    -* Build it using the `ant` command through terminal and on Successful build, you'll see `ar.jar` file appear under `libraries/ar/library`.
    -* Once built, hit Run. You'll see `AR` appear under `Sketch -> Import Library... -> AR`.
    -* On clicking it, you'll get an import to the AR Library as `import processing.ar.*;`.
    - -## Working: -

    - -

    \ No newline at end of file diff --git a/mode/libraries/ar/build.gradle b/mode/libraries/ar/build.gradle deleted file mode 100644 index bbc2c2a72..000000000 --- a/mode/libraries/ar/build.gradle +++ /dev/null @@ -1,97 +0,0 @@ -import java.nio.file.Files -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; - -plugins { - id 'aar' -} - -dependencies { - compileOnly name: "android" - compileOnly "org.p5android:processing-core:${modeVersion}" - implementationAar "com.google.ar:core:${garVersion}" -} - -task sourceJar(type: Jar) { - from sourceSets.main.allJava - archiveClassifier = "sources" -} - -sourceSets { - main { - java { - srcDirs = ["src/"] - } - resources { - srcDirs = ["src/"] - } - } -} - -// Does not work because of Processing-specific tags in source code, such as @webref -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = "javadoc" - from javadoc.destinationDir -} - -artifacts { -// archives javadocJar - archives sourceJar -} - -jar.doLast { task -> - ant.checksum file: task.archivePath -} - -clean.doFirst { - delete "dist" - delete "library/ar.jar" -} - -compileJava.doFirst { - String[] deps = ["core.jar"] - File libFolder = file("library") - libFolder.mkdirs() - for (String fn : deps) { - Files.copy(file("${rootDir}/build/libs/" + fn).toPath(), - file("library/" + fn).toPath(), REPLACE_EXISTING); - } -} - -build.doLast { - // Copying ar jar to library folder - File arJar = file("library/ar.jar") - arJar.mkdirs(); - - // Need to check the existance of the files before using as the files - // will get generated only if Task ':mode:libraries:ar:jar' is not being skipped - // Task ':mode:libraries:ar:jar' will be skipped if source files are unchanged or jar task is UP-TO-DATE - - if (file("$buildDir/libs/ar.jar").exists()) { - Files.copy(file("$buildDir/libs/ar.jar").toPath(), - arJar.toPath(), REPLACE_EXISTING); - } - // Renaming artifacts for maven publishing - if (file("$buildDir/libs/ar.jar").exists()) { - Files.move(file("$buildDir/libs/ar.jar").toPath(), - file("$buildDir/libs/processing-ar-${arLibVersion}.jar").toPath(), REPLACE_EXISTING); - } - if (file("$buildDir/libs/ar-sources.jar").exists()) { - Files.move(file("$buildDir/libs/ar-sources.jar").toPath(), - file("$buildDir/libs/processing-ar-${arLibVersion}-sources.jar").toPath(), REPLACE_EXISTING); - } - if (file("$buildDir/libs/ar.jar.MD5").exists()) { - Files.move(file("$buildDir/libs/ar.jar.MD5").toPath(), - file("$buildDir/libs/processing-ar-${arLibVersion}.jar.md5").toPath(), REPLACE_EXISTING); - } -} - -ext { - libName = 'processing-ar' - libVersion = arLibVersion - libJar = "${buildDir}/libs/${libName}-${libVersion}.jar" - libSrc = "${buildDir}/libs/${libName}-${libVersion}-sources.jar" - libMd5 = "${buildDir}/libs/${libName}-${libVersion}-sources.jar.md5" - libDependencies = [[group: 'org.p5android', name: 'processing-core', version: modeVersion], - [group: 'com.google.ar', name: 'core', version: garVersion]] -} -apply from: "${rootProject.projectDir}/scripts/publish-module.gradle" diff --git a/mode/libraries/ar/examples/Cubes/Cubes.pde b/mode/libraries/ar/examples/Cubes/Cubes.pde deleted file mode 100644 index d5a61a518..000000000 --- a/mode/libraries/ar/examples/Cubes/Cubes.pde +++ /dev/null @@ -1,93 +0,0 @@ -import processing.ar.*; - -ARTracker tracker; -ARAnchor touchAnchor; -ArrayList trackAnchors; -float angle; - -void setup() { - fullScreen(AR); - tracker = new ARTracker(this); - tracker.start(); - trackAnchors = new ArrayList(); -} - -void draw() { - // The AR Core session, frame and camera can be accessed through Processing's surface object - // to obtain the full information about the AR scene: -// ARSurface surface = (ARSurface) getSurface(); -// surface.camera.getPose(); -// surface.frame.getLightEstimate(); - - lights(); - - if (mousePressed) { - // Create new anchor at the current touch point - if (touchAnchor != null) touchAnchor.dispose(); - ARTrackable hit = tracker.get(mouseX, mouseY); - if (hit != null) touchAnchor = new ARAnchor(hit); - else touchAnchor = null; - } - - // Draw objects attached to each anchor - for (ARAnchor anchor : trackAnchors) { - if (anchor.isTracking()) drawBox(anchor, 255, 255, 255); - - // It is very important to dispose anchors once they are no longer tracked. - if (anchor.isStopped()) anchor.dispose(); - } - if (touchAnchor != null) drawBox(touchAnchor, 255, 0, 0); - - // Conveniency function in the tracker object to remove disposed anchors from a list - tracker.clearAnchors(trackAnchors); - - // Draw trackable planes - for (int i = 0; i < tracker.count(); i++) { - ARTrackable trackable = tracker.get(i); - if (!trackable.isTracking()) continue; - - pushMatrix(); - trackable.transform(); - if (mousePressed && trackable.isSelected(mouseX, mouseY)) { - fill(255, 0, 0, 100); - } else { - fill(255, 100); - } - beginShape(); - float[] points = trackable.getPolygon(); - for (int n = 0; n < points.length / 2; n++) { - float x = points[2 * n]; - float z = points[2 * n + 1]; - vertex(x, 0, z); - } - endShape(); - popMatrix(); - } - - angle += 0.1; -} - -void drawBox(ARAnchor anchor, int r, int g, int b) { - anchor.attach(); - fill(r, g, b); - rotateY(angle); - box(0.15f); - anchor.detach(); -} - -void trackableEvent(ARTrackable t) { - if (trackAnchors.size() < 10) { - float x0 = 0, y0 = 0; - if (t.isWallPlane()) { - // The new trackable is a wall, so adding the anchor 0.3 meters to its side - x0 = 0.3; - } else if (t.isFloorPlane()) { - // The new trackable is a floor plane, so adding the anchor 0.3 meters above it - y0 = 0.3; - } else { - // The new trackable is a floor plane, so adding the anchor 0.3 meters below it - y0 = -0.3; - } - trackAnchors.add(new ARAnchor(t, x0, y0, 0)); - } -} \ No newline at end of file diff --git a/mode/libraries/ar/examples/Cubes/code/sketch.properties b/mode/libraries/ar/examples/Cubes/code/sketch.properties deleted file mode 100644 index db8eaa0b5..000000000 --- a/mode/libraries/ar/examples/Cubes/code/sketch.properties +++ /dev/null @@ -1 +0,0 @@ -component=ar diff --git a/mode/libraries/ar/examples/ImportObj/ImportObj.pde b/mode/libraries/ar/examples/ImportObj/ImportObj.pde deleted file mode 100644 index f0412165e..000000000 --- a/mode/libraries/ar/examples/ImportObj/ImportObj.pde +++ /dev/null @@ -1,31 +0,0 @@ -import processing.ar.*; - -ARTracker tracker; -ARAnchor anchor; -PShape arObj; - -void setup() { - fullScreen(AR); - arObj = loadShape("model.obj"); - - tracker = new ARTracker(this); - tracker.start(); -} - -void draw() { - lights(); - - if (mousePressed) { - // Create new anchor at the current touch point - if (anchor != null) anchor.dispose(); - ARTrackable hit = tracker.get(mouseX, mouseY); - if (hit != null) anchor = new ARAnchor(hit); - else anchor = null; - } - - if (anchor != null) { - anchor.attach(); - shape(arObj); - anchor.detach(); - } -} diff --git a/mode/libraries/ar/examples/ImportObj/code/sketch.properties b/mode/libraries/ar/examples/ImportObj/code/sketch.properties deleted file mode 100644 index db8eaa0b5..000000000 --- a/mode/libraries/ar/examples/ImportObj/code/sketch.properties +++ /dev/null @@ -1 +0,0 @@ -component=ar diff --git a/mode/libraries/ar/examples/ImportObj/data/grey.png b/mode/libraries/ar/examples/ImportObj/data/grey.png deleted file mode 100644 index b6d6f05e4..000000000 Binary files a/mode/libraries/ar/examples/ImportObj/data/grey.png and /dev/null differ diff --git a/mode/libraries/ar/examples/ImportObj/data/materials.mtl b/mode/libraries/ar/examples/ImportObj/data/materials.mtl deleted file mode 100755 index d0bf7bc00..000000000 --- a/mode/libraries/ar/examples/ImportObj/data/materials.mtl +++ /dev/null @@ -1,12 +0,0 @@ -newmtl mat10 - Kd 0.30 0.69 0.31 - -newmtl mat9 - Kd 0.55 0.76 0.29 - -newmtl mat20 - Kd 0.47 0.33 0.28 - -newmtl mat21 - Kd 1.00 1.00 1.00 - diff --git a/mode/libraries/ar/examples/ImportObj/data/model.obj b/mode/libraries/ar/examples/ImportObj/data/model.obj deleted file mode 100755 index b30f38dcd..000000000 --- a/mode/libraries/ar/examples/ImportObj/data/model.obj +++ /dev/null @@ -1,949 +0,0 @@ -mtllib materials.mtl -v 0.03500453 0.019117 0.02433401 -v -0.006614864 0.0148387 -0.01981938 -v 0.03608745 0.01436758 0.02320725 -v 0.008281738 -0.0277046 0.0253039 -v -0.002996296 0.01700664 -0.01070774 -v -0.02605835 0.00233531 0.005670011 -v -0.01863462 0.2030077 0.1667039 -v -0.01543677 0.0811317 0.09948444 -v 0.03643253 0.02604151 0.01268643 -v 0.01329854 0.01135957 -0.04139006 -v 0.01430747 0.006541491 -0.04051358 -v 0.03744149 0.02122343 0.01356286 -v -0.02249089 0.01276231 0.007519543 -v -0.02148193 0.007944226 0.008396029 -v 0.02063528 0.2003068 -0.1131554 -v 0.03034195 0.1211638 -0.04571742 -v 0.001753241 0.03735411 -0.02767992 -v 0.01017797 0.08989894 -0.05778307 -v 0.02250633 0.09819317 -0.04077369 -v 0.01443794 0.165741 -0.09460694 -v 0.01391521 0.04973161 0.003262162 -v 0.002539635 0.02941597 0.01170969 -v -0.01658016 0.02541399 0.0003730655 -v -0.06505209 0.1163319 -0.004948497 -v 0.01759383 -0.009375334 -0.01819491 -v 0.01072627 0.02040827 0.01247698 -v -0.03959695 0.07464659 -0.01419669 -v -0.0185844 -0.01070535 0.005561471 -v -0.05041924 0.06390738 0.001349032 -v 0.006013215 0.03756678 -0.005902886 -v 0.006297797 0.0006850958 -0.02858913 -v 0.00980702 -0.001161218 -0.02554345 -v 0.009522438 0.03572035 -0.002857208 -v -0.02055576 0.005186796 0.005080104 -v -0.01704657 0.003340483 0.008125842 -v -0.01841947 0.04425907 -0.06405324 -v -0.03397268 0.08564556 -0.1005961 -v -0.02476519 0.05102789 -0.0618062 -v 0.02960703 0.004537225 0.03208822 -v 0.01192492 -0.002894044 -0.007959068 -v 0.02648646 0.0009000301 0.03351396 -v -0.0108943 0.03334081 0.01692253 -v -0.01401487 0.02970362 0.01834822 -v 0.0001596808 0.05255258 0.02025765 -v 0.051799 0.1298349 0.04909253 -v 0.0005793571 0.01908755 0.01888919 -v 0.0499264 -0.01731193 -0.0006120801 -v 0.04912642 -0.0203712 0.00326097 -v 0.003881067 0.01530802 0.02209854 -v -0.006612957 -0.02721441 -0.02011198 -v -0.00741291 -0.03027368 -0.01623887 -v -0.002917379 -0.02342451 0.03035516 -v -0.1224723 0.1188886 -0.0985955 -v -0.1014801 0.09994781 -0.08556575 -v -0.1030209 0.1053934 0.1052268 -v -0.0212988 -0.01117647 -0.03490889 -v 0.0158276 0.02291071 -0.001223564 -v -0.07115999 0.05342448 0.04761094 -v -0.01541749 -0.022282 0.02439606 -v -0.07139879 0.05052888 0.06651038 -v -0.01759699 0.02451885 0.00341332 -v -0.005952865 0.01053989 -0.003992498 -v -0.02672911 -0.009570718 0.01931787 -v -0.02047238 -0.006453276 -0.02330488 -v -0.1268312 0.07678592 0.002777576 -v -0.1150678 0.0672816 0.009178877 -v -0.07114238 0.03764832 -0.006659627 -v -0.02572748 -0.02377486 -0.007589579 -v -0.01347169 0.01270366 0.01641744 -v 0.04988497 0.003462791 -0.04212153 -v -0.02844059 -0.002164483 -0.06671989 -v -0.02802613 -0.007144094 -0.06690043 -v 0.05029941 -0.0015167 -0.04230213 -v -0.07574981 -0.008532882 0.0003093481 -v -0.07533535 -0.01351237 0.000128746 -v -0.02666298 -0.00684154 0.06633401 -v -0.02624851 -0.01182103 0.06615347 -v 0.05098358 0.0005722046 0.04011029 -v 0.05139804 -0.004407287 0.03992969 -v -0.02176204 -0.04356194 -0.07239652 -v 0.05649534 -0.03909731 -0.04734689 -v -0.0695408 -0.04930222 -0.005644143 -v -0.02081233 -0.04838526 0.06066066 -v 0.0570823 -0.04207826 0.03488696 -v 0.07041439 0.01539612 -0.05716801 -v -0.03705421 0.007957578 -0.08661979 -v -0.03663483 0.002982736 -0.08689362 -v 0.07083377 0.01042128 -0.05744183 -v -0.04998913 0.00577414 -0.06675935 -v -0.0977459 -0.002287507 0.006567121 -v -0.09732652 -0.007262349 0.006293297 -v -0.08314592 -0.002056479 0.02473265 -v -0.04424265 -0.001441121 0.07313687 -v -0.02778679 -0.001180768 0.0936116 -v -0.02736741 -0.006155729 0.09333777 -v 0.07614198 0.00974834 0.05422109 -v 0.07656136 0.004773378 0.05394727 -v 0.0750888 0.01078677 0.03373891 -v 0.07135528 0.01446831 -0.03887033 -v -0.02881977 0.0001393557 0.0680449 -v 0.05481839 0.008709669 0.04043132 -v -0.03199118 -0.08194315 -0.09419835 -v -0.08995503 -0.08119118 0.001257837 -v -0.01710126 -0.08282828 0.0858857 -v 0.08588874 -0.0845921 0.04273254 -v 0.07668623 -0.08404505 -0.06856555 -v 0.04908967 0.01287305 -0.04398769 -v -0.03213352 0.007053494 -0.06265551 -v -0.07307526 -0.0002579689 0.00748086 -v -0.03908038 -0.01706243 -0.0657807 -v 0.04292423 -0.0108943 -0.05105788 -v 0.05283928 -0.01613939 0.03291172 -v -0.02927521 -0.02569211 0.06449127 -v -0.07646161 -0.02560854 0.006180525 -v 0.01355043 -0.02314949 0.04385048 -v 0.01901108 -0.008549571 -0.01473302 -v 0.01652125 -0.01269674 -0.0159986 -v 0.0110606 -0.02729666 0.0425849 -v -0.0290007 0.01061189 0.01693255 -v -0.03149053 0.00646472 0.01566696 -v -0.02181986 0.003832459 0.008502007 -v 0.1225296 0.1186905 0.01693249 -vn 0.6759462 0.3124644 -0.66743 -vn 0.3036638 -0.1538349 0.9402782 -vn -0.1288713 -0.6415519 -0.7561768 -vn 0.6317405 -0.4490114 -0.6318961 -vn 0.5168009 0.6132385 -0.5973738 -vn 0.6353032 -0.3483134 0.6892516 -vn -0.9574758 -0.1581962 0.2412763 -vn -0.7149026 -0.4934512 0.495399 -vn 0.513531 -0.404038 0.7569936 -vn -0.6899258 0.4684089 -0.5519016 -vn 0.2377314 0.9194574 -0.3131804 -vn -0.9323441 0.05290945 0.3576803 -vn 0.902027 0.1131086 -0.4165979 -vn -0.7814992 -0.2662952 -0.5642216 -vn -0.1205278 0.1531868 0.9808195 -vn -0.7951764 -0.1880778 -0.5764732 -vn 0.2017912 -0.9636137 0.1752966 -vn 0.9226931 -0.1570926 -0.3520787 -vn -0.1877113 0.5051754 0.8423552 -vn -0.828216 0.3726066 0.4185961 -vn 0.6965678 0.2683296 0.6654266 -vn -0.8662611 0.1966525 -0.4592596 -vn 0.9343936 -0.1576237 -0.3194739 -vn -0.3524163 -0.3926582 -0.8494835 -vn -0.4714933 0.5698856 0.6729968 -vn 0.9370085 -0.3383273 -0.08688932 -vn 0.8010244 -0.4923694 -0.3404884 -vn -0.5066848 0.5572503 0.6578318 -vn -0.730508 -0.2646336 -0.6295453 -vn 0.4703085 -0.6906323 -0.5493971 -vn 0.5243899 -0.5602476 -0.6412004 -vn -0.6460397 0.4476092 0.618287 -vn 0.7643175 0.5396877 -0.352925 -vn -0.5135508 -0.3115103 -0.7995167 -vn -0.2271142 -0.002504592 0.9738649 -vn -0.6906796 -0.2732151 -0.6695635 -vn 0.4608619 -0.5828981 0.6692057 -vn -0.6596208 -0.3198385 -0.6801499 -vn 0.3868736 0.2156837 0.8965542 -vn 0.7782366 0.5445973 -0.3126687 -vn 0.7123011 0.3717107 -0.595364 -vn -0.350459 -0.9234875 -0.156043 -vn -0.3618422 0.5517769 0.751407 -vn -0.6169685 -0.6768168 -0.4015832 -vn 0.7018433 -0.3692735 0.6091413 -vn 0.9352891 0.190618 -0.2981597 -vn -0.5437235 0.6330461 0.551015 -vn -0.7395383 -0.5798131 -0.3419064 -vn -0.7387139 -0.5767542 -0.3487927 -vn -0.7117295 -0.5995156 -0.3660905 -vn -0.2450886 -0.6918193 -0.6792037 -vn 0.7083459 -0.6808023 -0.1864253 -vn -0.577066 0.183116 -0.7959042 -vn -0.05425279 0.4044118 0.9129664 -vn -0.3655506 0.3593813 -0.858614 -vn -0.6241442 -0.7272121 0.285669 -vn 0.9166214 -0.1101973 -0.3842678 -vn -0.2199824 -0.04261146 0.9745728 -vn -0.4381971 -0.04221215 0.8978872 -vn 0.5168417 0.3057183 -0.7996317 -vn -0.4323599 -0.04563689 0.9005456 -vn -0.1379253 0.4258103 -0.8942384 -vn 0.6460316 0.5284206 0.5508313 -vn 0.3233464 -0.7739131 -0.5445234 -vn 0.9823619 -0.1736944 -0.0692488 -vn 0.3515399 -0.2111629 -0.9120472 -vn -0.1599931 -0.6118627 0.7746137 -vn 0.5969911 0.7998882 0.06148641 -vn -0.8055354 -0.5835604 0.1028103 -vn -0.5761724 0.2658848 0.7728718 -vn 0.3974828 0.776682 0.4886436 -vn -0.7156691 -0.6781162 0.1672608 -vn -0.07940822 0.7431037 -0.6644482 -vn -0.8092278 -0.5867478 -0.02962401 -vn 0.6566163 -0.02666638 0.7537534 -vn -0.8871716 -0.4543079 -0.08081483 -vn 0.7527174 -0.6295595 -0.1925396 -vn -0.8154821 -0.5704756 -0.09770723 -vn -0.4086105 -0.6716307 0.6180208 -vn -0.6949745 0.2989345 -0.6539487 -vn 0.6619559 0.163908 0.7314018 -vn 0.266736 0.6152108 -0.7418677 -vn -0.6199426 -0.7842435 -0.02516915 -vn 0.2866544 0.5899032 -0.7548798 -vn 0.8534204 -0.4676813 -0.2301036 -vn 0.3394441 0.6475117 -0.6822803 -vn -0.000973773 0.1296944 0.9915536 -vn 0.2884114 0.6099449 -0.7380963 -vn 0.3598991 0.7445212 0.5622818 -vn 0.3754486 0.790543 0.4838181 -vn 0.6365256 -0.4595098 -0.6194239 -vn 0.3754486 0.790543 0.4838181 -vn -0.639107 -0.6897317 0.3403125 -vn 0.8143744 -0.5001561 0.2943436 -vn -0.5803067 -0.4435949 -0.6829845 -vn 0.2952288 0.05915305 -0.9535937 -vn -0.8140077 -0.04675739 -0.5789691 -vn -0.7983131 -0.08805058 0.5957711 -vn 0.3206232 -0.007661377 0.9471759 -vn 0.9964691 0.08331603 -0.01038414 -vn -0.08289231 0.9959039 0.03611439 -vn 0.286491 0.1822246 -0.9405941 -vn -0.8123397 -0.04491663 -0.5814524 -vn -0.7837809 -0.2125169 0.5835445 -vn 0.3226649 -0.08544654 0.9426486 -vn 0.9876623 0.1565333 -0.004534003 -vn 0.06860351 -0.9969714 -0.03662946 -vn 0.2587442 0.07481664 -0.9630441 -vn -0.835243 -0.04022668 -0.5484077 -vn -0.7749525 -0.09967847 0.6241096 -vn 0.356296 -0.02137723 0.9341286 -vn 0.9951558 0.08646443 -0.04678641 -vn -0.08387454 0.9949704 0.05476191 -vn 0.2568304 0.09675303 -0.9616013 -vn -0.8347547 -0.04585963 -0.548709 -vn -0.7680125 -0.1630291 0.6193371 -vn 0.3605577 -0.07899904 0.9293854 -vn 0.9929608 0.1093502 -0.04551313 -vn -0.0185397 -0.9998224 -0.00338177 -vn 0.2300202 0.127853 -0.9647509 -vn 0.9940968 0.07122472 -0.08184498 -vn -0.8547598 -0.002095141 -0.5190196 -vn -0.7535963 -0.1191722 0.6464446 -vn 0.3856194 -0.03796748 0.9218765 -vn -0.08387487 0.9949704 0.05476191 -vn -0.08387746 0.9949701 0.05476293 -vn -0.08387492 0.9949704 0.054762 -vn -0.0838771 0.9949703 0.05476097 -vn 0.8370441 -0.3003807 0.4573058 -vn -0.2022253 -0.2306736 0.951785 -vn -0.9958286 0.05799839 0.07043803 -vn -0.3230657 0.1345664 -0.9367606 -vn 0.8053956 0.06682255 -0.588959 -vn 0.8852978 -0.1409901 0.4431361 -vn 0.7753266 -0.07137989 -0.6275139 -vn -0.1704701 -0.0781832 0.9822562 -vn -0.9686102 0.2132797 0.1276949 -vn -0.3726705 0.2958405 -0.8795426 -vn -0.08772954 0.9935086 0.07241636 -vn 0.8625041 -0.5040262 -0.04521547 -vn -0.3532428 0.4605826 -0.8142992 -vn -0.5092613 0.04344368 0.8595148 -vn 0.2014092 -0.6723981 0.7122606 -vn -0.4979688 -0.8294312 -0.2531227 -vn 0.7829186 -0.6168609 -0.08075375 -vn -0.2661578 0.3731634 0.8887683 -vn -0.3811645 0.5344062 -0.7544028 -vn -0.3251337 0.4688944 -0.8212346 -vt -0.1140787 0.03138284 -vt -0.1158554 0.02556534 -vt -0.1136141 0.03119799 -vt 0.09894149 0.1048713 -vt 0.1021685 0.109191 -vt 0.1016744 0.1091149 -vt -0.1066763 0.1035016 -vt -0.1121509 0.1055655 -vt -0.1115286 0.1024404 -vt -0.08475467 0.1383537 -vt -0.0901614 0.1356119 -vt -0.08420303 0.1333365 -vt -0.06537322 -0.03387522 -vt -0.06724139 -0.02905086 -vt -0.09099902 -0.03133029 -vt 0.07564665 0.128677 -vt 0.07249503 0.124302 -vt 0.09948863 0.1275901 -vt -0.005117498 0.1487897 -vt 0.006192557 0.1439615 -vt -0.01494416 0.1586518 -vt 0.08523902 -0.0517007 -vt 0.09608601 -0.04590664 -vt 0.08278457 -0.0473825 -vt 0.0740456 0.113275 -vt 0.08742387 0.1136336 -vt 0.1010457 0.1165095 -vt -0.08119667 0.1337613 -vt -0.0558333 0.1293723 -vt -0.05547386 0.1325383 -vt 0.006262578 0.003618848 -vt 0.01038755 0.0004965129 -vt 0.01137706 0.0003261221 -vt 0.0510156 0.1469026 -vt 0.05004591 0.1471631 -vt 0.04608426 0.1428577 -vt -0.0688381 0.1264659 -vt -0.07417805 0.1235963 -vt -0.07394136 0.1231558 -vt -0.06860141 0.1260255 -vt -0.1078465 0.1188627 -vt -0.1100746 0.1132248 -vt -0.1096096 0.1130411 -vt -0.1073815 0.1186789 -vt 0.1179777 0.102659 -vt 0.1160989 0.1084227 -vt 0.1156235 0.1082677 -vt 0.1175023 0.1025041 -vt -0.1057023 0.1199926 -vt -0.103169 0.1255001 -vt -0.1183577 0.1388551 -vt -0.01354274 0.07674651 -vt -0.01952282 0.07575219 -vt -0.01567168 0.07107045 -vt -0.05110518 0.1516622 -vt -0.04528297 0.1533509 -vt -0.05128602 0.162781 -vt 0.1083808 0.1214489 -vt 0.1108377 0.1159069 -vt 0.118157 0.1268701 -vt 0.06290381 0.1529554 -vt 0.06604792 0.1581991 -vt 0.06413454 0.1593991 -vt 0.1264942 0.130957 -vt 0.1174081 0.1225252 -vt 0.1132593 0.1180342 -vt 0.1123433 0.113189 -vt -0.06912652 0.1435414 -vt -0.06841803 0.1484213 -vt -0.07191654 0.1539707 -vt -0.07323746 0.1560659 -vt -0.04413793 0.1652177 -vt -0.05065675 0.1733763 -vt -0.04452227 0.154104 -vt -0.124141 0.1168212 -vt -0.1340527 0.124265 -vt -0.1310707 0.1216421 -vt 0.09981892 0.1402302 -vt 0.09372418 0.1338609 -vt 0.1062645 0.1424113 -vt -0.007361628 0.1738323 -vt -0.007709313 0.17138 -vt -0.005147806 0.1628786 -vt -0.0538327 0.161586 -vt -0.05581391 0.1605016 -vt -0.04927731 0.1539648 -vt 0.09250034 0.1317357 -vt 0.1043252 0.1442625 -vt 0.09186566 0.135595 -vt 0.09088932 0.1333186 -vt -0.1226757 0.1284759 -vt -0.1122508 0.114762 -vt -0.1163737 0.1228593 -vt -0.08792244 0.137607 -vt -0.08221005 0.1305407 -vt -0.08053256 0.1320529 -vt -0.08900896 0.1344408 -vt -0.08996293 0.1367266 -vt -0.09593607 0.1432101 -vt 0.09943064 0.1496814 -vt 0.1019548 0.1527476 -vt 0.0930742 0.1472529 -vt -0.01989863 -0.1092991 -vt -0.01381554 -0.09547608 -vt -0.01781833 -0.09712763 -vt -0.1225598 0.1129164 -vt -0.1139305 0.1103271 -vt -0.1124988 0.1144137 -vt 0.1284472 0.09043346 -vt 0.1162811 0.0925452 -vt 0.115033 0.08839886 -vt -0.1183999 0.1133674 -vt -0.1187976 0.1155082 -vt -0.1237072 0.1147289 -vt 0.05978798 0.1068567 -vt 0.05546509 0.1071068 -vt 0.05740996 0.103238 -vt -0.1209545 0.1119765 -vt -0.1204887 0.1098495 -vt -0.1123944 0.1091671 -vt 0.1132004 0.1118751 -vt 0.1213011 0.1124761 -vt 0.1266491 0.1136676 -vt 0.01676467 -0.1112485 -vt 0.01793306 -0.1064167 -vt 0.0187613 -0.09627871 -vt -0.11463 0.006658147 -vt -0.1112072 0.004005964 -vt -0.1109009 0.0044012 -vt -0.1143238 0.00705338 -vt -0.08027916 0.03211533 -vt -0.07883324 0.02803375 -vt -0.07836194 0.02820071 -vt -0.07980787 0.03228229 -vt 0.10148 0.1225743 -vt 0.1026396 0.1267463 -vt 0.1021579 0.1268802 -vt 0.1009982 0.1227082 -vt -0.113922 0.0599463 -vt -0.1136528 0.06426805 -vt -0.1196823 0.06541675 -vt 0.06852727 0.1349547 -vt 0.06428875 0.1340687 -vt 0.06717528 0.130841 -vt -0.031122 0.136667 -vt -0.02851421 0.1401238 -vt -0.03805421 0.1462688 -vt 0.08087214 0.137729 -vt 0.08012602 0.1334637 -vt 0.09210182 0.1393621 -vt -0.1228887 0.06915759 -vt -0.1220789 0.06966314 -vt -0.1272685 0.0721065 -vt -0.1220974 0.07083166 -vt -0.1229096 0.07033004 -vt -0.1171047 0.06465271 -vt -0.1166995 0.0635231 -vt -0.1226809 0.06901416 -vt -0.1271384 0.07184418 -vt -0.1225632 0.1000327 -vt -0.1170617 0.09840968 -vt -0.1109856 0.09754105 -vt -0.03230288 0.1458602 -vt -0.03669528 0.1452095 -vt -0.03228601 0.1453605 -vt -0.08946843 0.1235516 -vt -0.09427954 0.1223765 -vt -0.09411226 0.1219053 -vt 0.1168864 0.1136613 -vt 0.1120057 0.1154441 -vt 0.1118342 0.1149745 -vt 0.1167149 0.1131916 -vt -0.08923022 0.102894 -vt -0.08441637 0.1040579 -vt -0.09072792 0.1045616 -vt -0.02206336 -0.06198291 -vt -0.026459 -0.06236074 -vt -0.02417939 -0.06672869 -vt -0.05463599 0.1456433 -vt -0.0503474 0.1467942 -vt -0.04910248 0.1595716 -vt 0.1189074 0.08985645 -vt 0.1159428 0.08829741 -vt 0.1177477 0.08793834 -vt 0.1171631 0.08354659 -vt 0.1199852 0.08535087 -vt 0.123382 0.09447052 -vt -0.1099102 0.04050694 -vt -0.1141292 0.03747376 -vt -0.1123682 0.03800825 -vt 0.1142366 0.08509803 -vt 0.1171581 0.08316149 -vt 0.1234379 0.09405048 -vt -0.09879679 0.08813052 -vt -0.09228849 0.0808953 -vt -0.08597927 0.08036333 -vt 0.1120607 0.09141384 -vt 0.1117586 0.09101542 -vt 0.1165892 0.08735266 -vt -0.0806265 0.1231025 -vt -0.084486 0.1184276 -vt -0.08410042 0.1181093 -vt -0.08024094 0.1227841 -vt 0.003482211 0.1583301 -vt 0.008283757 0.1566894 -vt 0.009117588 0.1606198 -vt 0.003706832 0.1578865 -vt -0.1132746 0.1046951 -vt -0.110367 0.1100145 -vt -0.1334541 0.1032534 -vt 0.07486738 0.03010331 -vt 0.07010847 0.03385869 -vt 0.06923567 0.02785967 -vt 0.08733691 -0.001883278 -vt 0.107071 -0.006697561 -vt 0.08547853 0.003908656 -vt -0.1046513 -0.0164464 -vt -0.1242836 -0.02133137 -vt -0.1016751 -0.02055635 -vt 0.1212808 0.1178688 -vt 0.1042064 0.12052 -vt 0.1016979 0.117381 -vt 0.1256555 0.0683793 -vt 0.1226187 0.0690648 -vt 0.1030349 0.06861331 -vt -0.06885661 -0.05426354 -vt -0.08479238 -0.06094307 -vt -0.0872846 -0.06280877 -vt -0.06427599 0.0429099 -vt -0.04557212 0.04992529 -vt -0.05010713 0.05394819 -vt -0.1186936 0.00875746 -vt -0.1111613 0.01484358 -vt -0.1148017 0.01969101 -vt 0.1133721 0.1177334 -vt 0.09872365 0.1281269 -vt 0.09655823 0.1224647 -vt -0.1210305 0.057626 -vt -0.121323 0.05951564 -vt -0.1272598 0.05359038 -vt -0.03441339 0.1511454 -vt -0.03898577 0.147165 -vt -0.03325248 0.1451954 -vt -0.1214571 0.02656759 -vt -0.1206144 0.02485112 -vt -0.1133698 0.03189421 -vt 0.05701512 -0.0197142 -vt 0.0656883 -0.0248974 -vt 0.07260296 -0.02759513 -vt -0.0905035 0.1244898 -vt -0.08244815 0.1268278 -vt -0.07161251 0.1309845 -vt 0.1098242 0.1199025 -vt 0.1079822 0.1205848 -vt 0.1073509 0.1169247 -vt -0.07463787 0.01149246 -vt -0.07068079 0.01041753 -vt -0.07288663 0.01238216 -vt -0.09607417 -0.01917072 -vt -0.09462651 -0.01839539 -vt -0.0896282 -0.007019095 -vt -0.08036827 0.006541973 -vt -0.07875977 0.01191062 -vt -0.08519926 0.00165505 -vt -0.03451624 0.1565128 -vt -0.03692249 0.1547995 -vt -0.03572354 0.1527238 -vt -0.06357461 -0.005884686 -vt -0.06871022 -0.01052367 -vt -0.07308383 -0.01582387 -vt 0.1154477 0.1019501 -vt 0.1264731 0.09787957 -vt 0.1167904 0.1041863 -vt -0.07543775 0.008823099 -vt -0.07690215 0.003413375 -vt -0.07148749 0.007723369 -vt 0.1106047 0.07933239 -vt 0.1089076 0.0787183 -vt 0.1182114 0.07186498 -vt 0.1143609 0.06150217 -vt 0.1159351 0.06103433 -vt 0.1070294 0.0692399 -vt -0.0856042 0.133481 -vt -0.08607899 0.1360457 -vt -0.08776338 0.1366938 -vt 0.1143609 0.06150217 -vt 0.1159351 0.06103433 -vt 0.1070294 0.0692399 -vt -0.00711296 -0.08452687 -vt -0.006638455 -0.07278366 -vt -0.009549673 -0.07189343 -vt 0.02740077 0.1438553 -vt 0.03042767 0.1435304 -vt 0.02961959 0.1471556 -vt -0.1268686 0.09593622 -vt -0.1149407 0.1007597 -vt -0.1164133 0.1026511 -vt -0.1132122 0.08596116 -vt -0.116635 0.07847779 -vt -0.1161803 0.07826982 -vt -0.1127575 0.08575319 -vt -0.09220141 0.1340483 -vt -0.0955446 0.1265291 -vt -0.09508772 0.1263259 -vt -0.09174453 0.1338452 -vt 0.1076475 0.09159471 -vt 0.1012101 0.09672074 -vt 0.1008986 0.0963296 -vt 0.107336 0.09120356 -vt 0.1088697 0.1063079 -vt 0.1060496 0.1140386 -vt 0.1055798 0.1138672 -vt 0.1083999 0.1061365 -vt 0.04792935 0.1433837 -vt 0.04180641 0.1488816 -vt 0.04147236 0.1485095 -vt 0.04759529 0.1430117 -vt 0.03883927 0.07155949 -vt 0.03899961 0.06333206 -vt 0.04687391 0.06094213 -vt 0.05158016 0.0676925 -vt 0.04661448 0.07425439 -vt -0.1090102 0.0720264 -vt -0.1118069 0.06428732 -vt -0.1082356 0.06319106 -vt -0.1053391 0.07089337 -vt -0.091727 0.1338432 -vt -0.09507115 0.1263244 -vt -0.09153756 0.1253288 -vt -0.0881338 0.1328208 -vt 0.1156497 0.06152174 -vt 0.1103468 0.06781421 -vt 0.1076163 0.06526272 -vt 0.1129695 0.059013 -vt 0.1053661 0.1045086 -vt 0.1025635 0.1122455 -vt 0.09884425 0.1112788 -vt 0.1017466 0.1035787 -vt 0.05987245 0.1339858 -vt 0.05440415 0.1401351 -vt 0.05130423 0.1378654 -vt 0.05677184 0.1317156 -vt -0.04742923 0.07296612 -vt -0.052449 0.06644552 -vt -0.04779873 0.05965646 -vt -0.03990494 0.06198118 -vt -0.03967657 0.07020701 -vt -0.1126079 0.08761457 -vt -0.1170812 0.07738168 -vt -0.116623 0.07718141 -vt -0.1121497 0.0874143 -vt -0.09040387 0.137115 -vt -0.09136991 0.1349397 -vt -0.09493659 0.1269083 -vt -0.09447964 0.1267054 -vt -0.08994691 0.1369121 -vt 0.1126091 0.0847635 -vt 0.1108731 0.08631867 -vt 0.1062476 0.09046261 -vt 0.104291 0.09221547 -vt 0.1039573 0.09184305 -vt 0.1122754 0.08439109 -vt 0.1087505 0.1067333 -vt 0.1050009 0.1172529 -vt 0.1045299 0.1170851 -vt 0.1082795 0.1065654 -vt 0.04346379 0.1439831 -vt 0.04188982 0.1453021 -vt 0.03631011 0.1499778 -vt 0.03490401 0.1511562 -vt 0.03458287 0.1507729 -vt 0.04314264 0.1435999 -vt 0.03859253 0.07477754 -vt 0.03847141 0.06361028 -vt 0.04096083 0.06277146 -vt 0.04090803 0.06440245 -vt 0.04062173 0.07324729 -vt 0.04055234 0.07539091 -vt -0.1115371 0.08516809 -vt -0.1158737 0.07487652 -vt -0.1081331 0.0712769 -vt -0.09044557 0.1366012 -vt -0.09494228 0.1263786 -vt -0.08806984 0.1235113 -vt 0.116101 0.07012583 -vt 0.1085203 0.07832673 -vt 0.1028228 0.07304142 -vt 0.1059965 0.1057554 -vt 0.1022465 0.1162749 -vt 0.09359471 0.1136038 -vt 0.04671876 0.1411094 -vt 0.03839004 0.1485495 -vt 0.04023906 0.1347846 -vt -0.0485208 0.06271283 -vt -0.05463352 0.05336634 -vt -0.04763341 0.04466456 -vt -0.03719438 0.04863306 -vt -0.03774281 0.05978751 -vt -0.1063763 0.06940357 -vt -0.1014021 0.07940255 -vt -0.1101423 0.08320101 -vt 0.02503191 0.1526401 -vt 0.01901537 0.1452495 -vt 0.02837731 0.1391605 -vt -0.08299437 0.1268454 -vt -0.07715007 0.1363621 -vt -0.08486463 0.140017 -vt 0.101952 0.07948565 -vt 0.1099468 0.07168785 -vt 0.1152929 0.07687157 -vt 0.09472505 0.1153084 -vt 0.09966098 0.1052905 -vt 0.1071245 0.1074564 -vt 0.05429678 0.06709726 -vt 0.0557166 0.06900758 -vt 0.04925064 0.07811327 -vt 0.04749985 0.07756533 -vt 0.04874702 0.07564453 -vt 0.05329662 0.06863762 -vt 0.04096082 0.06277189 -vt 0.04684603 0.06078886 -vt 0.04811948 0.0623384 -vt 0.04090803 0.06440288 -vt 0.04874703 0.07564454 -vt 0.04749986 0.07756533 -vt 0.04055234 0.07539096 -vt 0.04062172 0.07324734 -vt 0.04684583 0.06078869 -vt 0.04905448 0.06004447 -vt 0.05429659 0.06709749 -vt 0.05329644 0.06863783 -vt 0.04811928 0.06233824 -vt 0.06042005 0.1400615 -vt 0.05567345 0.1466915 -vt 0.05380367 0.1449886 -vt 0.1090244 0.06430319 -vt 0.1065122 0.07227091 -vt 0.1045174 0.07067419 -vt -0.01340094 0.1599647 -vt -0.02074384 0.1557398 -vt -0.01893001 0.1538718 -vt -0.1014335 0.1117869 -vt -0.1043637 0.1034366 -vt -0.1019694 0.1024032 -vt -0.09895404 0.1022399 -vt -0.1050736 0.09790201 -vt -0.09772499 0.09993985 -vt 0.06604317 0.1456356 -vt 0.07035102 0.1387124 -vt 0.07234798 0.1403156 -vt -0.1009395 0.1124417 -vt -0.09987329 0.1101134 -vt -0.09348343 0.1140423 -vt 0.1101286 0.08789753 -vt 0.1132709 0.08015662 -vt 0.1151113 0.08189123 -vt 0.002846764 0.1586051 -vt 0.01075032 0.1616549 -vt 0.009274639 0.1637408 -vt -0.09130703 0.1005571 -vt -0.08848813 0.1089456 -vt -0.09089162 0.1099469 -vt 0.05002477 0.06340988 -vt 0.05546781 0.06948122 -vt 0.05122348 0.07667714 -vt 0.04300268 0.07463127 -vt 0.04290868 0.0657823 -vt -0.006475641 0.1533231 -vt -0.0114986 0.1567173 -vt -0.01177854 0.156303 -vt -0.006755578 0.1529089 -vt -0.0747896 0.09971711 -vt -0.07908086 0.09543516 -vt -0.07872769 0.09508123 -vt -0.07443643 0.09936318 -vt 0.1166597 0.09208065 -vt 0.1108894 0.09393932 -vt 0.1107361 0.0934634 -vt 0.1165064 0.09160472 -vt 0.05920173 0.06907564 -vt 0.05513092 0.07356769 -vt 0.05805777 0.06968994 -vt -0.09210218 0.03360453 -vt -0.09663808 0.03762642 -vt -0.0978532 0.03168727 -vt -0.02150865 0.1506603 -vt -0.01634552 0.1474835 -vt -0.01356576 0.1653571 -vt 0.1074875 0.1151102 -vt 0.1133728 0.1136564 -vt 0.1132144 0.1322682 -vt -0.06883705 0.09612168 -vt -0.07584256 0.1132075 -vt -0.06999642 0.09553699 -vt -0.08491834 0.1101264 -vt -0.07818113 0.09293307 -vt -0.07504927 0.09664721 -o group2002521463 -g mesh2002521463 -usemtl mat10 -f 3/3/1 2/2/1 1/1/1 -f 3/6/2 1/5/2 4/4/2 -f 6/9/3 5/8/3 4/7/3 -f 4/12/4 2/11/4 3/10/4 -f 7/15/5 1/14/5 5/13/5 -f 7/18/6 4/17/6 1/16/6 -f 7/21/7 6/20/7 8/19/7 -f 4/24/8 8/23/8 6/22/8 -f 7/27/9 8/26/9 4/25/9 -f 5/30/10 6/29/10 7/28/10 -f 2/33/11 5/32/11 1/31/11 -f 4/36/12 5/35/12 2/34/12 -o group1119943561 -g mesh1119943561 -usemtl mat10 -f 12/40/13 11/39/13 10/38/13 9/37/13 -f 11/44/14 14/43/14 13/42/14 10/41/14 -f 14/48/15 12/47/15 9/46/15 13/45/15 -f 15/51/16 10/50/16 13/49/16 -f 14/54/17 11/53/17 12/52/17 -f 16/57/18 9/56/18 10/55/18 -f 16/60/19 13/59/19 9/58/19 -f 19/63/20 18/62/20 17/61/20 -f 13/67/21 17/66/21 18/65/21 15/64/21 -f 16/71/22 19/70/22 17/69/22 13/68/22 -f 10/74/23 15/73/23 16/72/23 -f 20/77/24 15/76/24 18/75/24 -f 20/80/25 21/79/25 16/78/25 -f 22/83/26 19/82/26 16/81/26 -f 22/86/27 18/85/27 19/84/27 -f 22/90/28 21/89/28 20/88/28 23/87/28 -f 18/93/29 23/92/29 20/91/29 -f 22/96/30 23/95/30 18/94/30 -f 16/99/31 21/98/31 22/97/31 -f 16/102/32 15/101/32 20/100/32 -o group634111619 -g mesh634111619 -usemtl mat10 -f 26/105/33 25/104/33 24/103/33 -f 25/108/34 28/107/34 27/106/34 -f 28/111/35 26/110/35 24/109/35 -f 24/114/36 27/113/36 29/112/36 -f 28/117/37 25/116/37 26/115/37 -f 28/120/38 29/119/38 27/118/38 -f 24/123/39 29/122/39 28/121/39 -f 25/126/40 27/125/40 24/124/40 -o group1265393450 -g mesh1265393450 -usemtl mat9 -f 33/130/41 32/129/41 31/128/41 30/127/41 -f 32/134/42 35/133/42 34/132/42 31/131/42 -f 35/138/43 33/137/43 30/136/43 34/135/43 -f 36/141/44 31/140/44 34/139/44 -f 35/144/45 32/143/45 33/142/45 -f 37/147/46 30/146/46 31/145/46 -f 37/150/47 34/149/47 30/148/47 -f 37/153/48 36/152/48 38/151/48 -f 34/156/49 38/155/49 36/154/49 -f 37/159/50 38/158/50 34/157/50 -f 31/162/51 36/161/51 37/160/51 -o group792360013 -g mesh792360013 -usemtl mat9 -f 41/165/52 40/164/52 39/163/52 -f 43/168/53 42/167/53 40/166/53 -f 43/172/54 41/171/54 39/170/54 42/169/54 -f 44/175/55 40/174/55 42/173/55 -f 43/178/56 40/177/56 41/176/56 -f 45/181/57 39/180/57 40/179/57 -f 42/184/58 46/183/58 44/182/58 -f 45/187/59 44/186/59 46/185/59 -f 46/190/60 42/189/60 39/188/60 -f 45/193/61 46/192/61 39/191/61 -f 40/196/62 44/195/62 45/194/62 -o group481990970 -g mesh481990970 -usemtl mat10 -f 49/199/63 48/198/63 47/197/63 -f 48/203/64 51/202/64 50/201/64 47/200/64 -f 51/207/65 49/206/65 52/205/65 50/204/65 -f 53/210/66 47/209/66 50/208/66 -f 51/213/67 48/212/67 49/211/67 -f 47/216/68 53/215/68 49/214/68 -f 52/219/69 53/218/69 50/217/69 -f 52/222/70 49/221/70 54/220/70 -f 52/225/71 54/224/71 53/223/71 -f 53/228/72 54/227/72 49/226/72 -o group1935184771 -g mesh1935184771 -usemtl mat9 -f 57/231/73 56/230/73 55/229/73 -f 56/234/74 59/233/74 58/232/74 -f 59/237/75 57/236/75 55/235/75 -f 55/240/76 58/239/76 60/238/76 -f 59/243/77 56/242/77 57/241/77 -f 59/246/78 60/245/78 58/244/78 -f 55/249/79 60/248/79 59/247/79 -f 56/252/80 58/251/80 55/250/80 -o group2043820846 -g mesh2043820846 -usemtl mat10 -f 63/255/81 62/254/81 61/253/81 -f 62/258/82 64/257/82 61/256/82 -f 64/261/83 66/260/83 65/259/83 -f 65/264/84 61/263/84 67/262/84 -f 68/267/85 64/266/85 62/265/85 -f 65/270/86 67/269/86 64/268/86 -f 69/273/87 66/272/87 63/271/87 -f 64/276/88 67/275/88 61/274/88 -f 66/279/89 69/278/89 61/277/89 -f 61/282/90 65/281/90 66/280/90 -f 61/285/91 69/284/91 63/283/91 -f 61/288/92 65/287/92 66/286/92 -f 68/291/93 63/290/93 66/289/93 -f 62/294/94 63/293/94 68/292/94 -f 64/297/95 68/296/95 66/295/95 -o group971385351 -g mesh971385351 -usemtl mat20 -f 73/301/96 72/300/96 71/299/96 70/298/96 -f 72/305/97 75/304/97 74/303/97 71/302/97 -f 75/309/98 77/308/98 76/307/98 74/306/98 -f 77/313/99 79/312/99 78/311/99 76/310/99 -f 79/317/100 73/316/100 70/315/100 78/314/100 -f 70/322/101 71/321/101 74/320/101 76/319/101 78/318/101 -f 81/326/102 80/325/102 72/324/102 73/323/102 -f 80/330/103 82/329/103 75/328/103 72/327/103 -f 82/334/104 83/333/104 77/332/104 75/331/104 -f 83/338/105 84/337/105 79/336/105 77/335/105 -f 84/342/106 81/341/106 73/340/106 79/339/106 -f 84/347/107 83/346/107 82/345/107 80/344/107 81/343/107 -o group7854860 -g mesh7854860 -usemtl mat21 -f 88/351/108 87/350/108 86/349/108 85/348/108 -f 87/356/109 91/355/109 90/354/109 89/353/109 86/352/109 -f 91/362/110 95/361/110 94/360/110 93/359/110 92/358/110 90/357/110 -f 95/366/111 97/365/111 96/364/111 94/363/111 -f 97/372/112 88/371/112 85/370/112 99/369/112 98/368/112 96/367/112 -f 98/378/113 101/377/113 100/376/113 93/375/113 94/374/113 96/373/113 -f 102/381/114 87/380/114 88/379/114 -f 103/384/115 91/383/115 87/382/115 -f 104/387/116 95/386/116 91/385/116 -f 105/390/117 97/389/117 95/388/117 -f 105/393/118 88/392/118 97/391/118 -f 105/398/119 104/397/119 103/396/119 102/395/119 106/394/119 -f 88/401/120 106/400/120 102/399/120 -f 105/404/121 106/403/121 88/402/121 -f 87/407/122 102/406/122 103/405/122 -f 91/410/123 103/409/123 104/408/123 -f 95/413/124 104/412/124 105/411/124 -f 108/419/125 107/418/125 99/417/125 85/416/125 86/415/125 89/414/125 -f 100/423/126 109/422/126 92/421/126 93/420/126 -f 101/427/127 98/426/127 99/425/127 107/424/127 -f 109/432/128 108/431/128 89/430/128 90/429/128 92/428/128 -f 110/435/129 108/434/129 109/433/129 -f 111/438/130 107/437/130 108/436/130 -f 112/441/131 101/440/131 107/439/131 -f 113/444/132 100/443/132 101/442/132 -f 113/447/133 109/446/133 100/445/133 -f 109/450/134 114/449/134 110/448/134 -f 113/453/135 114/452/135 109/451/135 -f 108/456/136 110/455/136 111/454/136 -f 107/459/137 111/458/137 112/457/137 -f 101/462/138 112/461/138 113/460/138 -f 113/467/139 112/466/139 111/465/139 110/464/139 114/463/139 -o group1104563999 -g mesh1104563999 -usemtl mat10 -f 118/471/140 117/470/140 116/469/140 115/468/140 -f 117/475/141 120/474/141 119/473/141 116/472/141 -f 120/479/142 118/478/142 115/477/142 119/476/142 -f 121/482/143 116/481/143 119/480/143 -f 120/485/144 117/484/144 118/483/144 -f 122/488/145 115/487/145 116/486/145 -f 122/491/146 119/490/146 115/489/146 -f 119/494/147 122/493/147 121/492/147 -f 116/497/148 121/496/148 122/495/148 diff --git a/mode/libraries/ar/examples/Spheres/Spheres.pde b/mode/libraries/ar/examples/Spheres/Spheres.pde deleted file mode 100644 index f04b91f0e..000000000 --- a/mode/libraries/ar/examples/Spheres/Spheres.pde +++ /dev/null @@ -1,62 +0,0 @@ -import processing.ar.*; - -ARTracker tracker; -ARAnchor anchor; -PShape arObj; -float angle; - -void setup() { - fullScreen(AR); - - noStroke(); - - tracker = new ARTracker(this); - tracker.start(); -} - -void draw() { - lights(); - - if (mousePressed) { - // Create new anchor at the current touch point - if (anchor != null) anchor.dispose(); - ARTrackable hit = tracker.get(mouseX, mouseY); - if (hit != null) anchor = new ARAnchor(hit); - else anchor = null; - } - - if (anchor != null) { - anchor.attach(); - fill(217, 121, 255); - sphere(0.1); - rotateY(angle); - translate(0, 0, 0.3); - sphere(0.05); - angle += 0.1; - anchor.detach(); - } - - // Draw trackable planes - for (int i = 0; i < tracker.count(); i++) { - ARTrackable trackable = tracker.get(i); - if (!trackable.isTracking()) continue; - - pushMatrix(); - trackable.transform(); - if (mousePressed && trackable.isSelected(mouseX, mouseY)) { - fill(255, 0, 0, 100); - } else { - fill(255, 100); - } - - beginShape(QUADS); - float lx = trackable.lengthX(); - float lz = trackable.lengthZ(); - vertex(-lx/2, 0, -lz/2); - vertex(-lx/2, 0, +lz/2); - vertex(+lx/2, 0, +lz/2); - vertex(+lx/2, 0, -lz/2); - endShape(); - popMatrix(); - } -} diff --git a/mode/libraries/ar/examples/Spheres/code/sketch.properties b/mode/libraries/ar/examples/Spheres/code/sketch.properties deleted file mode 100644 index 7bae3ea6c..000000000 --- a/mode/libraries/ar/examples/Spheres/code/sketch.properties +++ /dev/null @@ -1,3 +0,0 @@ -mode=Android -component=ar -mode.id=processing.mode.android.AndroidMode diff --git a/mode/libraries/ar/library.properties b/mode/libraries/ar/library.properties deleted file mode 100644 index c9e600b01..000000000 --- a/mode/libraries/ar/library.properties +++ /dev/null @@ -1,10 +0,0 @@ -name = AR -authorList = The Processing Foundation, Syam Sundar K -url = http://android.processing.org -category = 3D -sentence = Renderer to develop AR apps -paragraph = -version = 13 -prettyVersion = 4.2.1 -minRevision = 249 -maxRevision = 1269 \ No newline at end of file diff --git a/mode/libraries/ar/src/assets/shaders/ARLightFrag.glsl b/mode/libraries/ar/src/assets/shaders/ARLightFrag.glsl deleted file mode 100644 index 6ab64485c..000000000 --- a/mode/libraries/ar/src/assets/shaders/ARLightFrag.glsl +++ /dev/null @@ -1,49 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform vec4 colorCorrection; - -varying vec4 vertColor; -varying vec4 backVertColor; - -// Approximate sRGB gamma parameters -const float kGamma = 0.4545454; -const float kMiddleGrayGamma = 0.466; - -void main() { - vec3 colorShift = colorCorrection.rgb; - float averagePixelIntensity = colorCorrection.a; - - vec4 color = gl_FrontFacing ? vertColor : backVertColor; - - // Apply SRGB gamma before writing the fragment color. - color.rgb = pow(color.rgb, vec3(kGamma)); - - // Apply average pixel intensity and color shift - color.rgb *= colorShift * (averagePixelIntensity / kMiddleGrayGamma); - gl_FragColor = color; -} \ No newline at end of file diff --git a/mode/libraries/ar/src/assets/shaders/ARLightVert.glsl b/mode/libraries/ar/src/assets/shaders/ARLightVert.glsl deleted file mode 100644 index b9596af48..000000000 --- a/mode/libraries/ar/src/assets/shaders/ARLightVert.glsl +++ /dev/null @@ -1,156 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -uniform mat4 modelviewMatrix; -uniform mat4 transformMatrix; -uniform mat3 normalMatrix; - -uniform int lightCount; -uniform vec4 lightPosition[8]; -uniform vec3 lightNormal[8]; -uniform vec3 lightAmbient[8]; -uniform vec3 lightDiffuse[8]; -uniform vec3 lightSpecular[8]; -uniform vec3 lightFalloff[8]; -uniform vec2 lightSpot[8]; - -attribute vec4 position; -attribute vec4 color; -attribute vec3 normal; - -attribute vec4 ambient; -attribute vec4 specular; -attribute vec4 emissive; -attribute float shininess; - -varying vec4 vertColor; -varying vec4 backVertColor; - -const float zero_float = 0.0; -const float one_float = 1.0; -const vec3 zero_vec3 = vec3(0); - -const float kInverseGamma = 2.2; - -float falloffFactor(vec3 lightPos, vec3 vertPos, vec3 coeff) { - vec3 lpv = lightPos - vertPos; - vec3 dist = vec3(one_float); - dist.z = dot(lpv, lpv); - dist.y = sqrt(dist.z); - return one_float / dot(dist, coeff); -} - -float spotFactor(vec3 lightPos, vec3 vertPos, vec3 lightNorm, float minCos, float spotExp) { - vec3 lpv = normalize(lightPos - vertPos); - vec3 nln = -one_float * lightNorm; - float spotCos = dot(nln, lpv); - return spotCos <= minCos ? zero_float : pow(spotCos, spotExp); -} - -float lambertFactor(vec3 lightDir, vec3 vecNormal) { - return max(zero_float, dot(lightDir, vecNormal)); -} - -float blinnPhongFactor(vec3 lightDir, vec3 vertPos, vec3 vecNormal, float shine) { - vec3 np = normalize(vertPos); - vec3 ldp = normalize(lightDir - np); - return pow(max(zero_float, dot(ldp, vecNormal)), shine); -} - -void main() { - // Vertex in clip coordinates - gl_Position = transformMatrix * position; - - // Vertex in eye coordinates - vec3 ecVertex = vec3(modelviewMatrix * position); - - // Normal vector in eye coordinates - vec3 ecNormal = normalize(normalMatrix * normal); - vec3 ecNormalInv = ecNormal * -one_float; - - // Light calculations - vec3 totalAmbient = vec3(0, 0, 0); - - vec3 totalFrontDiffuse = vec3(0, 0, 0); - vec3 totalFrontSpecular = vec3(0, 0, 0); - - vec3 totalBackDiffuse = vec3(0, 0, 0); - vec3 totalBackSpecular = vec3(0, 0, 0); - - for (int i = 0; i < 8; i++) { - if (lightCount == i) break; - - vec3 lightPos = lightPosition[i].xyz; - bool isDir = lightPosition[i].w < one_float; - float spotCos = lightSpot[i].x; - float spotExp = lightSpot[i].y; - - vec3 lightDir; - float falloff; - float spotf; - - if (isDir) { - falloff = one_float; - lightDir = -one_float * lightNormal[i]; - } else { - falloff = falloffFactor(lightPos, ecVertex, lightFalloff[i]); - lightDir = normalize(lightPos - ecVertex); - } - - spotf = spotExp > zero_float ? spotFactor(lightPos, ecVertex, lightNormal[i], - spotCos, spotExp) - : one_float; - - if (any(greaterThan(lightAmbient[i], zero_vec3))) { - totalAmbient += lightAmbient[i] * falloff; - } - - if (any(greaterThan(lightDiffuse[i], zero_vec3))) { - totalFrontDiffuse += lightDiffuse[i] * falloff * spotf * - lambertFactor(lightDir, ecNormal); - totalBackDiffuse += lightDiffuse[i] * falloff * spotf * - lambertFactor(lightDir, ecNormalInv); - } - - if (any(greaterThan(lightSpecular[i], zero_vec3))) { - totalFrontSpecular += lightSpecular[i] * falloff * spotf * - blinnPhongFactor(lightDir, ecVertex, ecNormal, shininess); - totalBackSpecular += lightSpecular[i] * falloff * spotf * - blinnPhongFactor(lightDir, ecVertex, ecNormalInv, shininess); - } - } - - vec4 gcolor = vec4(pow(color.rgb, vec3(kInverseGamma)), color.a); - vec4 gambient = vec4(pow(ambient.rgb, vec3(kInverseGamma)), ambient.a); - - // Calculating final color as result of all lights (plus emissive term). - // Transparency is determined exclusively by the diffuse component. - vertColor = vec4(totalAmbient, 0) * gambient + - vec4(totalFrontDiffuse, 1) * gcolor + - vec4(totalFrontSpecular, 0) * specular + - vec4(emissive.rgb, 0); - - backVertColor = vec4(totalAmbient, 0) * gambient + - vec4(totalBackDiffuse, 1) * gcolor + - vec4(totalBackSpecular, 0) * specular + - vec4(emissive.rgb, 0); -} \ No newline at end of file diff --git a/mode/libraries/ar/src/assets/shaders/ARTexLightFrag.glsl b/mode/libraries/ar/src/assets/shaders/ARTexLightFrag.glsl deleted file mode 100644 index f06fb2160..000000000 --- a/mode/libraries/ar/src/assets/shaders/ARTexLightFrag.glsl +++ /dev/null @@ -1,56 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D texture; -uniform vec2 texOffset; -uniform vec4 colorCorrection; - -varying vec4 vertColor; -varying vec4 backVertColor; -varying vec4 vertTexCoord; - -// Approximate sRGB gamma parameters -const float kGamma = 0.4545454; -const float kInverseGamma = 2.2; -const float kMiddleGrayGamma = 0.466; - -void main() { - vec3 colorShift = colorCorrection.rgb; - float averagePixelIntensity = colorCorrection.a; - - vec4 tex = texture2D(texture, vertTexCoord.st); - vec4 gtex = vec4(pow(tex.rgb, vec3(kInverseGamma)), tex.a); - - vec4 color = gtex * (gl_FrontFacing ? vertColor : backVertColor); - - // Apply SRGB gamma before writing the fragment color. - color.rgb = pow(color.rgb, vec3(kGamma)); - - // Apply average pixel intensity and color shift - color.rgb *= colorShift * (averagePixelIntensity / kMiddleGrayGamma); - gl_FragColor = color; -} \ No newline at end of file diff --git a/mode/libraries/ar/src/assets/shaders/ARTexLightVert.glsl b/mode/libraries/ar/src/assets/shaders/ARTexLightVert.glsl deleted file mode 100644 index 5269a550e..000000000 --- a/mode/libraries/ar/src/assets/shaders/ARTexLightVert.glsl +++ /dev/null @@ -1,162 +0,0 @@ -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-16 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -uniform mat4 modelviewMatrix; -uniform mat4 transformMatrix; -uniform mat3 normalMatrix; -uniform mat4 texMatrix; - -uniform int lightCount; -uniform vec4 lightPosition[8]; -uniform vec3 lightNormal[8]; -uniform vec3 lightAmbient[8]; -uniform vec3 lightDiffuse[8]; -uniform vec3 lightSpecular[8]; -uniform vec3 lightFalloff[8]; -uniform vec2 lightSpot[8]; - -attribute vec4 position; -attribute vec4 color; -attribute vec3 normal; -attribute vec2 texCoord; - -attribute vec4 ambient; -attribute vec4 specular; -attribute vec4 emissive; -attribute float shininess; - -varying vec4 vertColor; -varying vec4 backVertColor; -varying vec4 vertTexCoord; - -const float zero_float = 0.0; -const float one_float = 1.0; -const vec3 zero_vec3 = vec3(0); - -const float kInverseGamma = 2.2; - -float falloffFactor(vec3 lightPos, vec3 vertPos, vec3 coeff) { - vec3 lpv = lightPos - vertPos; - vec3 dist = vec3(one_float); - dist.z = dot(lpv, lpv); - dist.y = sqrt(dist.z); - return one_float / dot(dist, coeff); -} - -float spotFactor(vec3 lightPos, vec3 vertPos, vec3 lightNorm, float minCos, float spotExp) { - vec3 lpv = normalize(lightPos - vertPos); - vec3 nln = -one_float * lightNorm; - float spotCos = dot(nln, lpv); - return spotCos <= minCos ? zero_float : pow(spotCos, spotExp); -} - -float lambertFactor(vec3 lightDir, vec3 vecNormal) { - return max(zero_float, dot(lightDir, vecNormal)); -} - -float blinnPhongFactor(vec3 lightDir, vec3 vertPos, vec3 vecNormal, float shine) { - vec3 np = normalize(vertPos); - vec3 ldp = normalize(lightDir - np); - return pow(max(zero_float, dot(ldp, vecNormal)), shine); -} - -void main() { - // Vertex in clip coordinates - gl_Position = transformMatrix * position; - - // Vertex in eye coordinates - vec3 ecVertex = vec3(modelviewMatrix * position); - - // Normal vector in eye coordinates - vec3 ecNormal = normalize(normalMatrix * normal); - vec3 ecNormalInv = ecNormal * -one_float; - - // Light calculations - vec3 totalAmbient = vec3(0, 0, 0); - - vec3 totalFrontDiffuse = vec3(0, 0, 0); - vec3 totalFrontSpecular = vec3(0, 0, 0); - - vec3 totalBackDiffuse = vec3(0, 0, 0); - vec3 totalBackSpecular = vec3(0, 0, 0); - - for (int i = 0; i < 8; i++) { - if (lightCount == i) break; - - vec3 lightPos = lightPosition[i].xyz; - bool isDir = lightPosition[i].w < one_float; - float spotCos = lightSpot[i].x; - float spotExp = lightSpot[i].y; - - vec3 lightDir; - float falloff; - float spotf; - - if (isDir) { - falloff = one_float; - lightDir = -one_float * lightNormal[i]; - } else { - falloff = falloffFactor(lightPos, ecVertex, lightFalloff[i]); - lightDir = normalize(lightPos - ecVertex); - } - - spotf = spotExp > zero_float ? spotFactor(lightPos, ecVertex, lightNormal[i], - spotCos, spotExp) - : one_float; - - if (any(greaterThan(lightAmbient[i], zero_vec3))) { - totalAmbient += lightAmbient[i] * falloff; - } - - if (any(greaterThan(lightDiffuse[i], zero_vec3))) { - totalFrontDiffuse += lightDiffuse[i] * falloff * spotf * - lambertFactor(lightDir, ecNormal); - totalBackDiffuse += lightDiffuse[i] * falloff * spotf * - lambertFactor(lightDir, ecNormalInv); - } - - if (any(greaterThan(lightSpecular[i], zero_vec3))) { - totalFrontSpecular += lightSpecular[i] * falloff * spotf * - blinnPhongFactor(lightDir, ecVertex, ecNormal, shininess); - totalBackSpecular += lightSpecular[i] * falloff * spotf * - blinnPhongFactor(lightDir, ecVertex, ecNormalInv, shininess); - } - } - - vec4 gcolor = vec4(pow(color.rgb, vec3(kInverseGamma)), color.a); - vec4 gambient = vec4(pow(ambient.rgb, vec3(kInverseGamma)), ambient.a); - - // Calculating final color as result of all lights (plus emissive term). - // Transparency is determined exclusively by the diffuse component. - vertColor = vec4(totalAmbient, 0) * gambient + - vec4(totalFrontDiffuse, 1) * gcolor + - vec4(totalFrontSpecular, 0) * specular + - vec4(emissive.rgb, 0); - - backVertColor = vec4(totalAmbient, 0) * gambient + - vec4(totalBackDiffuse, 1) * gcolor + - vec4(totalBackSpecular, 0) * specular + - vec4(emissive.rgb, 0); - - // Calculating texture coordinates, with r and q set both to one - vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); -} diff --git a/mode/libraries/ar/src/assets/shaders/BackgroundFrag.glsl b/mode/libraries/ar/src/assets/shaders/BackgroundFrag.glsl deleted file mode 100644 index d2fc66d60..000000000 --- a/mode/libraries/ar/src/assets/shaders/BackgroundFrag.glsl +++ /dev/null @@ -1,9 +0,0 @@ -#extension GL_OES_EGL_image_external : require - -precision mediump float; -varying vec2 v_TexCoord; -uniform samplerExternalOES sTexture; - -void main() { - gl_FragColor = texture2D(sTexture, v_TexCoord); -} diff --git a/mode/libraries/ar/src/assets/shaders/BackgroundVert.glsl b/mode/libraries/ar/src/assets/shaders/BackgroundVert.glsl deleted file mode 100644 index 25a4da170..000000000 --- a/mode/libraries/ar/src/assets/shaders/BackgroundVert.glsl +++ /dev/null @@ -1,9 +0,0 @@ -attribute vec4 a_Position; -attribute vec2 a_TexCoord; - -varying vec2 v_TexCoord; - -void main() { - gl_Position = a_Position; - v_TexCoord = a_TexCoord; -} diff --git a/mode/libraries/ar/src/processing/ar/ARAnchor.java b/mode/libraries/ar/src/processing/ar/ARAnchor.java deleted file mode 100644 index c3cd930c4..000000000 --- a/mode/libraries/ar/src/processing/ar/ARAnchor.java +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2019 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.ar; - -import processing.core.PMatrix3D; - -public class ARAnchor { - protected ARGraphics g; - private boolean disposed = false; - - private int id; - private PMatrix3D m; - - public ARAnchor(ARTrackable trackable, float x, float y, float z) { - this.g = trackable.g; - - int idx = g.trackableIndex(Integer.parseInt(trackable.id())); - id = g.createAnchor(idx, x, y, z); - } - - public ARAnchor(ARTrackable trackable) { - this.g = trackable.g; - id = g.createAnchor(trackable.hit); - trackable.hit = null; - } - - public void dispose() { - if (!disposed) { - g.deleteAnchor(id); - disposed = true; - } - } - - public String id() { - return String.valueOf(id); - } - - public PMatrix3D matrix() { - m = g.getTrackableMatrix(id, m); - return m; - } - - public void attach() { - g.pushMatrix(); - g.anchor(id); - } - - public void detach() { - g.popMatrix(); - } - - public boolean isTracking() { - return g.anchorStatus(id) == ARGraphics.TRACKING; - } - - public boolean isPaused() { - return g.anchorStatus(id) == ARGraphics.PAUSED; - } - - public boolean isStopped() { - return g.anchorStatus(id) == ARGraphics.STOPPED; - } - - public boolean isDisposed() { - return disposed; - } -} diff --git a/mode/libraries/ar/src/processing/ar/ARGraphics.java b/mode/libraries/ar/src/processing/ar/ARGraphics.java deleted file mode 100644 index fc31e12ae..000000000 --- a/mode/libraries/ar/src/processing/ar/ARGraphics.java +++ /dev/null @@ -1,538 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2019 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.ar; - -import android.view.SurfaceHolder; - -import com.google.ar.core.Anchor; -import com.google.ar.core.HitResult; -import com.google.ar.core.Plane; -import com.google.ar.core.Pose; -import com.google.ar.core.Trackable; -import com.google.ar.core.TrackingState; - -import java.net.URL; -import java.nio.FloatBuffer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; - -import processing.android.AppComponent; -import processing.core.PGraphics; -import processing.core.PMatrix3D; -import processing.core.PSurface; -import processing.opengl.PGL; -import processing.opengl.PGLES; -import processing.opengl.PGraphics3D; -import processing.opengl.PGraphicsOpenGL; -import processing.opengl.PShader; - -public class ARGraphics extends PGraphics3D { - static protected final int UNKNOWN = -1; - - static protected final int PLANE_FLOOR = 0; - static protected final int PLANE_CEILING = 1; - static protected final int PLANE_WALL = 2; - static protected final int POINT = 3; - - static protected final int TRACKING = 0; - static protected final int PAUSED = 1; - static protected final int STOPPED = 2; - - // Convenience reference to the AR surface. It is the same object one gets from PApplet.getSurface(). - protected ARSurface surfar; - - protected BackgroundRenderer backgroundRenderer; - - protected float[] projMatrix = new float[16]; - protected float[] viewMatrix = new float[16]; - protected float[] anchorMatrix = new float[16]; - protected float[] colorCorrection = new float[4]; - - protected ArrayList trackers = new ArrayList(); - protected ArrayList trackPlanes = new ArrayList(); - protected HashMap trackMatrices = new HashMap(); - protected HashMap trackIds = new HashMap(); - protected HashMap trackIdx = new HashMap(); - - protected ArrayList newPlanes = new ArrayList(); - protected ArrayList delAnchors = new ArrayList(); - - protected HashMap anchors = new HashMap(); - - protected float[] pointIn = new float[3]; - protected float[] pointOut = new float[3]; - - protected int lastTrackableId = 0; - protected int lastAnchorId = 0; - - static protected URL arLightShaderVertURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/ARLightVert.glsl"); - static protected URL arTexlightShaderVertURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/ARTexLightVert.glsl"); - static protected URL arLightShaderFragURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/ARLightFrag.glsl"); - static protected URL arTexlightShaderFragURL = - PGraphicsOpenGL.class.getResource("/assets/shaders/ARTexLightFrag.glsl"); - - protected PShader arLightShader; - protected PShader arTexlightShader; - - public ARGraphics() { - } - - - static ARTrackable[] getTrackables() { - return null; - } - - @Override - public PSurface createSurface(AppComponent appComponent, SurfaceHolder surfaceHolder, boolean reset) { - if (reset) pgl.resetFBOLayer(); - surfar = new ARSurface(this, appComponent, surfaceHolder); - return surfar; - } - - - @Override - protected PGL createPGL(PGraphicsOpenGL pGraphicsOpenGL) { - return new PGLES(pGraphicsOpenGL); - } - - - @Override - public void beginDraw() { - super.beginDraw(); - updateView(); - - // Always clear the screen and draw the background - background(0); - backgroundRenderer.draw(surfar.frame); - } - - public void endDraw() { - cleanup(); - super.endDraw(); - } - - - @Override - public void camera(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - PGraphics.showWarning("The camera cannot be set in AR"); - } - - - @Override - public void perspective(float fov, float aspect, float zNear, float zFar) { - PGraphics.showWarning("Perspective cannot be set in AR"); - } - - - @Override - protected void defaultCamera() { - // do nothing - } - - - @Override - protected void defaultPerspective() { - // do nothing - } - - - @Override - protected void saveState() { - } - - - @Override - protected void restoreState() { - } - - - @Override - protected void restoreSurface() { - } - - - protected void updateView() { - if (projMatrix != null && viewMatrix != null) { - - // Fist, set all matrices to identity - resetProjection(); - resetMatrix(); - - // Apply the projection matrix - applyProjection(projMatrix[0], projMatrix[4], projMatrix[8], projMatrix[12], - projMatrix[1], projMatrix[5], projMatrix[9], projMatrix[13], - projMatrix[2], projMatrix[6], projMatrix[10], projMatrix[14], - projMatrix[3], projMatrix[7], projMatrix[11], projMatrix[15]); - - // make modelview = view - applyMatrix(viewMatrix[0], viewMatrix[4], viewMatrix[8], viewMatrix[12], - viewMatrix[1], viewMatrix[5], viewMatrix[9], viewMatrix[13], - viewMatrix[2], viewMatrix[6], viewMatrix[10], viewMatrix[14], - viewMatrix[3], viewMatrix[7], viewMatrix[11], viewMatrix[15]); - } - } - - - public void addTracker(ARTracker tracker) { - trackers.add(tracker); - } - - - public void removeTracker(ARTracker tracker) { - trackers.remove(tracker); - } - - - public int trackableCount() { - return trackPlanes.size(); - } - - - - public int trackableId(int i) { - return trackIds.get(trackPlanes.get(i)); - } - - - public int trackableIndex(int id) { - return trackIdx.get(id); - } - - public int trackableType(int i) { - Plane plane = trackPlanes.get(i); - if (plane.getType() == Plane.Type.HORIZONTAL_UPWARD_FACING) { - return PLANE_FLOOR; - } else if (plane.getType() == Plane.Type.HORIZONTAL_DOWNWARD_FACING) { - return PLANE_CEILING; - } else if (plane.getType() == Plane.Type.VERTICAL) { - return PLANE_WALL; - } - return UNKNOWN; - } - - public int trackableStatus(int i) { - Plane plane = trackPlanes.get(i); - if (plane.getTrackingState() == TrackingState.PAUSED) { - return PAUSED; - } else if (plane.getTrackingState() == TrackingState.TRACKING) { - return TRACKING; - } else if (plane.getTrackingState() == TrackingState.STOPPED) { - return STOPPED; - } - return UNKNOWN; - } - - public boolean trackableNew(int i) { - Plane plane = trackPlanes.get(i); - return newPlanes.contains(plane); - } - - public boolean trackableSelected(int i, int mx, int my) { - Plane planei = trackPlanes.get(i); - for (HitResult hit : surfar.frame.hitTest(mx, my)) { - Trackable trackable = hit.getTrackable(); - if (trackable instanceof Plane) { - Plane plane = (Plane)trackable; - if (planei.equals(plane) && plane.isPoseInPolygon(hit.getHitPose())) { - return true; - } - } - } - return false; - } - - - protected HitResult getHitResult(int mx, int my) { - for (HitResult hit : surfar.frame.hitTest(mx, my)) { - Trackable trackable = hit.getTrackable(); - if (trackable instanceof Plane) { - Plane plane = (Plane)trackable; - if (trackPlanes.contains(plane) && plane.isPoseInPolygon(hit.getHitPose())) { - return hit; - } - } - } - return null; - } - - protected int getTrackable(HitResult hit) { - Plane plane = (Plane) hit.getTrackable(); - return trackPlanes.indexOf(plane); - } - - public float[] getTrackablePolygon(int i) { - return getTrackablePolygon(i, null); - } - - - public float[] getTrackablePolygon(int i, float[] points) { - Plane plane = trackPlanes.get(i); - FloatBuffer buffer = plane.getPolygon(); - buffer.rewind(); - if (points == null || points.length < buffer.capacity()) { - points = new float[buffer.capacity()]; - } - buffer.get(points, 0, buffer.capacity()); - return points; - } - - - public float getTrackableExtentX(int i) { - Plane plane = trackPlanes.get(i); - return plane.getExtentX(); - } - - - public float getTrackableExtentZ(int i) { - Plane plane = trackPlanes.get(i); - return plane.getExtentZ(); - } - - public PMatrix3D getTrackableMatrix(int i) { - return getTrackableMatrix(i, null); - } - - - public PMatrix3D getTrackableMatrix(int i, PMatrix3D target) { - if (target == null) { - target = new PMatrix3D(); - } - - Plane plane = trackPlanes.get(i); - float[] mat = trackMatrices.get(plane); - target.set(mat[0], mat[4], mat[8], mat[12], - mat[1], mat[5], mat[9], mat[13], - mat[2], mat[6], mat[10], mat[14], - mat[3], mat[7], mat[11], mat[15]); - - return target; - } - - - public int createAnchor(int i, float x, float y, float z) { - Plane plane = trackPlanes.get(i); - Pose planePose = plane.getCenterPose(); - pointIn[0] = x; - pointIn[1] = y; - pointIn[2] = z; - planePose.transformPoint(pointIn, 0, pointOut, 0); - Pose anchorPose = Pose.makeTranslation(pointOut); - Anchor anchor = plane.createAnchor(anchorPose); - anchors.put(++lastAnchorId, anchor); - return lastAnchorId; - } - - - public int createAnchor(int mx, int my) { - for (HitResult hit : surfar.frame.hitTest(mx, my)) { - Trackable trackable = hit.getTrackable(); - if (trackable instanceof Plane) { - Plane plane = (Plane)trackable; - if (trackPlanes.contains(plane) && plane.isPoseInPolygon(hit.getHitPose())) { - return createAnchor(hit); - } - } - } - return 0; - } - - - protected int createAnchor(HitResult hit) { - Anchor anchor = hit.createAnchor(); - anchors.put(++lastAnchorId, anchor); - return lastAnchorId; - } - - - public void deleteAnchor(int id) { - delAnchors.add(id); - } - - - public int anchorCount() { - return anchors.size(); - } - - - public int anchorStatus(int id) { - Anchor anchor = anchors.get(id); - if (anchor.getTrackingState() == TrackingState.PAUSED) { - return PAUSED; - } else if (anchor.getTrackingState() == TrackingState.TRACKING) { - return TRACKING; - } else if (anchor.getTrackingState() == TrackingState.STOPPED) { - return STOPPED; - } - return UNKNOWN; - } - - - public PMatrix3D getAnchorMatrix(int id) { - return getAnchorMatrix(id, null); - } - - - public PMatrix3D getAnchorMatrix(int id, PMatrix3D target) { - if (target == null) { - target = new PMatrix3D(); - } - Anchor anchor = anchors.get(id); - anchor.getPose().toMatrix(anchorMatrix, 0); - target.set(anchorMatrix[0], anchorMatrix[4], anchorMatrix[8], anchorMatrix[12], - anchorMatrix[1], anchorMatrix[5], anchorMatrix[9], anchorMatrix[13], - anchorMatrix[2], anchorMatrix[6], anchorMatrix[10], anchorMatrix[14], - anchorMatrix[3], anchorMatrix[7], anchorMatrix[11], anchorMatrix[15]); - return target; - } - - - public void anchor(int id) { - Anchor anchor = anchors.get(id); - anchor.getPose().toMatrix(anchorMatrix, 0); - - // now, modelview = view * anchor - applyMatrix(anchorMatrix[0], anchorMatrix[4], anchorMatrix[8], anchorMatrix[12], - anchorMatrix[1], anchorMatrix[5], anchorMatrix[9], anchorMatrix[13], - anchorMatrix[2], anchorMatrix[6], anchorMatrix[10], anchorMatrix[14], - anchorMatrix[3], anchorMatrix[7], anchorMatrix[11], anchorMatrix[15]); - } - - - protected void createBackgroundRenderer() { - backgroundRenderer = new BackgroundRenderer(surfar.getActivity()); - } - - protected void setCameraTexture() { - surfar.session.setCameraTextureName(backgroundRenderer.getTextureId()); - } - - protected void updateMatrices() { - surfar.camera.getProjectionMatrix(projMatrix, 0, 0.1f, 100.0f); - surfar.camera.getViewMatrix(viewMatrix, 0); - surfar.frame.getLightEstimate().getColorCorrection(colorCorrection, 0); - } - - - protected void updateTrackables() { - Collection planes = surfar.frame.getUpdatedTrackables(Plane.class); - for (Plane plane: planes) { - if (plane.getSubsumedBy() != null) continue; - float[] mat; - if (trackMatrices.containsKey(plane)) { - mat = trackMatrices.get(plane); - } else { - mat = new float[16]; - trackMatrices.put(plane, mat); - trackPlanes.add(plane); - trackIds.put(plane, ++lastTrackableId); - newPlanes.add(plane); - } - Pose pose = plane.getCenterPose(); - pose.toMatrix(mat, 0); - } - - // Remove stopped and subsummed trackables - for (int i = trackPlanes.size() - 1; i >= 0; i--) { - Plane plane = trackPlanes.get(i); - if (plane.getTrackingState() == TrackingState.STOPPED || plane.getSubsumedBy() != null) { - trackPlanes.remove(i); - trackMatrices.remove(plane); - int pid = trackIds.remove(plane); - trackIdx.remove(pid); - for (ARTracker t: trackers) t.remove(pid); - } - } - - // Update indices - for (int i = 0; i < trackPlanes.size(); i++) { - Plane plane = trackPlanes.get(i); - int pid = trackIds.get(plane); - trackIdx.put(pid, i); - if (newPlanes.contains(plane)) { - for (ARTracker t: trackers) t.create(i); - } - } - } - - - protected void cleanup() { - newPlanes.clear(); - - for (int id: delAnchors) { - Anchor anchor = anchors.remove(id); - anchor.detach(); - } - delAnchors.clear(); - } - - - @Override - protected PShader getPolyShader(boolean lit, boolean tex) { - if (getPrimaryPG() != this) { - // An offscreen surface will use the default shaders from the parent OpenGL renderer - return super.getPolyShader(lit, tex); - } - - PShader shader; - boolean useDefault = polyShader == null; - if (lit) { - if (tex) { - if (useDefault || !isPolyShaderTexLight(polyShader)) { - if (arTexlightShader == null) { - arTexlightShader = loadShaderFromURL(arTexlightShaderFragURL, arTexlightShaderVertURL); - } - shader = arTexlightShader; - } else { - shader = polyShader; - } - } else { - if (useDefault || !isPolyShaderLight(polyShader)) { - if (arLightShader == null) { - arLightShader = loadShaderFromURL(arLightShaderFragURL, arLightShaderVertURL); - } - shader = arLightShader; - } else { - shader = polyShader; - } - } - updateShader(shader); - return shader; - } else { - // Non-lit shaders use the default shaders from the parent OpenGL renderer - return super.getPolyShader(lit, tex); - } - } - - - @Override - protected void updateShader(PShader shader) { - super.updateShader(shader); - shader.set("colorCorrection", colorCorrection, 4); - } -} diff --git a/mode/libraries/ar/src/processing/ar/ARSurface.java b/mode/libraries/ar/src/processing/ar/ARSurface.java deleted file mode 100644 index e1a4ba08f..000000000 --- a/mode/libraries/ar/src/processing/ar/ARSurface.java +++ /dev/null @@ -1,332 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2019 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.ar; - -import android.app.Activity; -import android.app.ActivityManager; -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.ConfigurationInfo; -import android.content.res.AssetManager; -import android.opengl.GLES20; -import android.opengl.GLSurfaceView; -import android.view.*; - -import com.google.ar.core.*; -import com.google.ar.core.exceptions.*; - -import processing.android.AppComponent; -import processing.core.PGraphics; -import processing.opengl.PGLES; -import processing.opengl.PGraphicsOpenGL; -import processing.opengl.PSurfaceGLES; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -import java.io.File; -import java.io.InputStream; - -public class ARSurface extends PSurfaceGLES { - private static String T_ALERT_MESSAGE = "ALERT"; - private static String C_NOT_SUPPORTED = "ARCore SDK required to run this app type"; - private static String T_PROMPT_MESSAGE = "PROMPT"; - private static String C_SUPPORTED = "ARCore SDK is installed"; - private static String C_EXCEPT_INSTALL = "Please install ARCore"; - private static String C_EXCEPT_UPDATE_SDK = "Please update ARCore"; - private static String C_EXCEPT_UPDATE_APP = "Please update this app"; - private static String C_DEVICE = "This device does not support AR"; - - // Made these public so they can be accessed from the sketch - public Session session; - public Frame frame; - public Camera camera; - - protected GLSurfaceView surfaceView; - protected AndroidARRenderer renderer; - protected ARGraphics par; - - protected RotationHandler displayRotationHelper; - - public ARSurface(PGraphics graphics, AppComponent appComponent, SurfaceHolder surfaceHolder) { - super(graphics, appComponent, surfaceHolder); - this.sketch = graphics.parent; - this.graphics = graphics; - this.component = appComponent; - this.pgl = (PGLES) ((PGraphicsOpenGL) graphics).pgl; - - par = (ARGraphics) graphics; - - displayRotationHelper = new RotationHandler(activity); - surfaceView = new SurfaceViewAR(activity); - } - - @Override - public Context getContext() { - return activity; - } - - @Override - public void finish() { - sketch.getActivity().finish(); - } - - @Override - public AssetManager getAssets() { - return sketch.getContext().getAssets(); - } - - @Override - public void startActivity(Intent intent) { - sketch.getContext().startActivity(intent); - } - - @Override - public void initView(int sketchWidth, int sketchHeight) { - Window window = sketch.getActivity().getWindow(); - - window.getDecorView() - .setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); - window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - - window.setContentView(surfaceView); - } - - @Override - public String getName() { - return sketch.getActivity().getComponentName().getPackageName(); - } - - @Override - public void setOrientation(int which) { - } - - @Override - public File getFilesDir() { - return sketch.getActivity().getFilesDir(); - } - - @Override - public InputStream openFileInput(String filename) { - return null; - } - - @Override - public File getFileStreamPath(String path) { - return sketch.getActivity().getFileStreamPath(path); - } - - @Override - public void dispose() { - } - - - public class SurfaceViewAR extends GLSurfaceView { - public SurfaceViewAR(Context context) { - super(context); - - final ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo(); - final boolean supportsGLES2 = configurationInfo.reqGlEsVersion >= 0x20000; - - if (!supportsGLES2) { - throw new RuntimeException("OpenGL ES 2.0 is not supported by this device."); - } - - setFocusable(true); - setFocusableInTouchMode(true); - requestFocus(); - - setPreserveEGLContextOnPause(true); - setEGLContextClientVersion(2); - setEGLConfigChooser(8, 8, 8, 8, 16, 0); - setRenderer(getARRenderer()); - setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); - } - - - @Override - public boolean onTouchEvent(MotionEvent event) { - return sketch.surfaceTouchEvent(event); - } - - - @Override - public boolean onKeyDown(int code, android.view.KeyEvent event) { - sketch.surfaceKeyDown(code, event); - return super.onKeyDown(code, event); - } - - - @Override - public boolean onKeyUp(int code, android.view.KeyEvent event) { - sketch.surfaceKeyUp(code, event); - return super.onKeyUp(code, event); - } - } - - public AndroidARRenderer getARRenderer() { - renderer = new AndroidARRenderer(); - return renderer; - } - - protected class AndroidARRenderer implements GLSurfaceView.Renderer { - public AndroidARRenderer() { - } - - @Override - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - pgl.getGL(null); - par.createBackgroundRenderer(); - } - - @Override - public void onSurfaceChanged(GL10 gl, int width, int height) { - displayRotationHelper.onSurfaceChanged(width, height); - GLES20.glViewport(0, 0, width, height); - - sketch.surfaceChanged(); - graphics.surfaceChanged(); - - sketch.setSize(width, height); - graphics.setSize(sketch.sketchWidth(), sketch.sketchHeight()); - } - - @Override - public void onDrawFrame(GL10 gl) { - if (session == null) return; - - displayRotationHelper.updateSessionIfNeeded(session); - try { - - par.setCameraTexture(); - frame = session.update(); - camera = frame.getCamera(); - - if (camera.getTrackingState() == TrackingState.TRACKING) par.updateTrackables(); - par.updateMatrices(); - - sketch.calculate(); - sketch.handleDraw(); - - - } catch (Throwable tr) { - PGraphics.showWarning("An error occurred in ARCORE: " + tr.getMessage()); - } - } - } - - - @Override - public void startThread() { - } - - @Override - public void pauseThread() { - if (session != null) { - displayRotationHelper.onPause(); - surfaceView.onPause(); - session.pause(); - } - } - - @Override - public void resumeThread() { - if (!sketch.hasPermission("android.permission.CAMERA")) return; - - if (session == null) { - String message = null; - String exception = null; - try { - // Perhaps this should be done in the MainActivity? - // https://github.com/google-ar/arcore-android-sdk/blob/master/samples/hello_ar_java/app/src/main/java/com/google/ar/core/examples/java/helloar/HelloArActivity.java - switch (ArCoreApk.getInstance().requestInstall(sketch.getActivity(), true)) { - case INSTALL_REQUESTED: - message(T_ALERT_MESSAGE, C_NOT_SUPPORTED); - return; - case INSTALLED: - break; - } - - session = new Session(activity); - } catch (UnavailableArcoreNotInstalledException - | UnavailableUserDeclinedInstallationException e) { - message = C_EXCEPT_INSTALL; - exception = e.toString(); - } catch (UnavailableApkTooOldException e) { - message = C_EXCEPT_UPDATE_SDK; - exception = e.toString(); - } catch (UnavailableSdkTooOldException e) { - message = C_EXCEPT_UPDATE_APP; - exception = e.toString(); - } catch (Exception e) { - e.printStackTrace(); - System.out.println("That's that"); - } - - if (message != null) { - message(T_ALERT_MESSAGE, message + " -- " + exception); - } - - Config config = new Config(session); - if (!session.isSupported(config)) { - message(T_PROMPT_MESSAGE, C_DEVICE); - } - session.configure(config); - } - try { - session.resume(); - } catch (CameraNotAvailableException e) { - } - surfaceView.onResume(); - displayRotationHelper.onResume(); - } - - public void message(String _title, String _message) { - final Activity parent = activity; - final String message = _message; - final String title = _title; - - parent.runOnUiThread(new Runnable() { - public void run() { - new AlertDialog.Builder(parent) - .setTitle(title) - .setMessage(message) - .setPositiveButton("OK", - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - } - }).show(); - } - }); - } -} diff --git a/mode/libraries/ar/src/processing/ar/ARTrackable.java b/mode/libraries/ar/src/processing/ar/ARTrackable.java deleted file mode 100644 index cddf64147..000000000 --- a/mode/libraries/ar/src/processing/ar/ARTrackable.java +++ /dev/null @@ -1,127 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2019 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.ar; - -import processing.core.PMatrix3D; - -import com.google.ar.core.HitResult; - -public class ARTrackable { - protected ARGraphics g; - protected HitResult hit; - - private int id; - private PMatrix3D m; - private float[] points; - - public ARTrackable(ARGraphics g, int id) { - this.g = g; - this.id = id; - } - - public String id() { - return String.valueOf(id); - } - - public PMatrix3D matrix() { - int idx = g.trackableIndex(id); - m = g.getTrackableMatrix(idx, m); - return m; - } - - public void transform() { - g.applyMatrix(matrix()); - } - - public float[] getPolygon() { - int idx = g.trackableIndex(id); - points = g.getTrackablePolygon(idx, points); - return points; - } - - - public float lengthX() { - int idx = g.trackableIndex(id); - return g.getTrackableExtentX(idx); - } - - - public float lengthY() { - return 0; - } - - - public float lengthZ() { - int idx = g.trackableIndex(id); - return g.getTrackableExtentZ(idx); - } - - - public boolean isSelected(int mx, int my) { - int idx = g.trackableIndex(id); - return g.trackableSelected(idx, mx, my); - } - - public boolean isNew() { - int idx = g.trackableIndex(id); - return g.trackableNew(idx); - } - - public boolean isTracking() { - int idx = g.trackableIndex(id); - return g.trackableStatus(idx) == ARGraphics.TRACKING; - } - - public boolean isPaused() { - int idx = g.trackableIndex(id); - return g.trackableStatus(idx) == ARGraphics.PAUSED; - } - - public boolean isStopped() { - int idx = g.trackableIndex(id); - return g.trackableStatus(idx) == ARGraphics.STOPPED; - } - - public boolean isPlane() { - return true; - } - - public boolean isPointCloud() { - return false; - } - - public boolean isFloorPlane() { - int idx = g.trackableIndex(id); - return g.trackableType(idx) == ARGraphics.PLANE_FLOOR; - } - - public boolean isCeilingPlane() { - int idx = g.trackableIndex(id); - return g.trackableType(idx) == ARGraphics.PLANE_CEILING; - } - - public boolean isWallPlane() { - int idx = g.trackableIndex(id); - return g.trackableType(idx) == ARGraphics.PLANE_WALL; - } -} diff --git a/mode/libraries/ar/src/processing/ar/ARTracker.java b/mode/libraries/ar/src/processing/ar/ARTracker.java deleted file mode 100644 index 9a27fdfda..000000000 --- a/mode/libraries/ar/src/processing/ar/ARTracker.java +++ /dev/null @@ -1,149 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2019 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.ar; - -import com.google.ar.core.HitResult; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Set; - -import processing.core.PApplet; - -public class ARTracker { - protected PApplet p; - protected ARGraphics g; - - private HashMap trackables = new HashMap(); - private ArrayList toRemove = new ArrayList(); - private Method trackableEventMethod; - - public ARTracker(PApplet parent) { - this.p = parent; - this.g = (ARGraphics) p.g; - setEventHandler(); - } - - public void start() { - cleanup(); - g.addTracker(this); - } - - public void stop() { - g.removeTracker(this); - } - - public int count() { - return g.trackableCount(); - } - - public ARTrackable get(int idx) { - int id = g.trackableId(idx); - String sid = String.valueOf(id); - if (!trackables.containsKey(sid)) { - ARTrackable t = new ARTrackable(g, id); - trackables.put(sid, t); - } - return get(sid); - } - - public ARTrackable get(String id) { - return trackables.get(id); - } - - public ARTrackable get(int mx, int my) { - HitResult hit = g.getHitResult(mx, my); - if (hit != null) { - int idx = g.getTrackable(hit); - ARTrackable t = get(idx); - t.hit = hit; - return t; - } else { - return null; - } - } - - protected void create(int idx) { - if (trackableEventMethod != null) { - try { - ARTrackable t = get(idx); - trackableEventMethod.invoke(p, t); - } catch (Exception e) { - System.err.println("error, disabling trackableEventMethod() for AR tracker"); - e.printStackTrace(); - trackableEventMethod = null; - } - } - } - - public void clearAnchors(Collection anchors) { - for (ARAnchor anchor : anchors) { - if (anchor.isStopped() || anchor.isDisposed()) { - anchor.dispose(); - toRemove.add(anchor); - } - } - anchors.removeAll(toRemove); - toRemove.clear(); - } - - protected void cleanup() { - // Remove any inactive trackables left over in the tracker. - Set ids = trackables.keySet(); - for (String id: ids) { - ARTrackable t = trackables.get(id); - if (t.isStopped()) trackables.remove(id); - } - } - - protected void remove(int idx) { - int id = g.trackableId(idx); - String sid = String.valueOf(id); - remove(sid); - } - - protected void remove(String id) { - trackables.remove(id); - } - - - protected void setEventHandler() { - try { - trackableEventMethod = p.getClass().getMethod("trackableEvent", ARTrackable.class); - return; - } catch (Exception e) { - // no such method, or an error... which is fine, just ignore - } - - // trackableEvent can alternatively be defined as receiving an Object, to allow - // Processing mode implementors to support the video library without linking - // to it at build-time. - try { - trackableEventMethod = p.getClass().getMethod("trackableEvent", Object.class); - } catch (Exception e) { - // no such method, or an error... which is fine, just ignore - } - } -} diff --git a/mode/libraries/ar/src/processing/ar/BackgroundRenderer.java b/mode/libraries/ar/src/processing/ar/BackgroundRenderer.java deleted file mode 100644 index f00464866..000000000 --- a/mode/libraries/ar/src/processing/ar/BackgroundRenderer.java +++ /dev/null @@ -1,152 +0,0 @@ -package processing.ar; - -import android.content.Context; -import android.opengl.GLES11Ext; -import android.opengl.GLES20; - -import com.google.ar.core.Frame; - -import java.net.URL; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; - -public class BackgroundRenderer { - - private static final int COORDS_PER_VERTEX = 3; - private static final int TEXCOORDS_PER_VERTEX = 2; - private static final int FLOAT_SIZE = 4; - - private FloatBuffer quadVertices; - private FloatBuffer quadTexCoord; - private FloatBuffer quadTexCoordTransformed; - - private int quadProgram; - - private int quadPositionParam; - private int quadTexCoordParam; - private int textureId = -1; - - static private URL screenquad_vertex = - BackgroundRenderer.class.getResource("/assets/shaders/BackgroundVert.glsl"); - static private URL screenquad_fragment = - BackgroundRenderer.class.getResource("/assets/shaders/BackgroundFrag.glsl"); - - private String VERTICES_ERROR = "Unexpected number of vertices in BackgroundRenderer"; - private String ERROR_TAG = "Error"; - private String CREATION_ERROR = "Program creation"; - private String PARAMETERS_ERROR = "Program parameters"; - private String DRAW_ERROR = "Draw"; - - public BackgroundRenderer(Context context) { - int[] textures = new int[1]; - GLES20.glGenTextures(1, textures, 0); - textureId = textures[0]; - int textureTarget = GLES11Ext.GL_TEXTURE_EXTERNAL_OES; - GLES20.glBindTexture(textureTarget, textureId); - GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); - GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); - - int numVertices = 4; - if (numVertices != QUAD_COORDS.length / COORDS_PER_VERTEX) { - throw new RuntimeException(VERTICES_ERROR); - } - - ByteBuffer bbVertices = ByteBuffer.allocateDirect(QUAD_COORDS.length * FLOAT_SIZE); - bbVertices.order(ByteOrder.nativeOrder()); - quadVertices = bbVertices.asFloatBuffer(); - quadVertices.put(QUAD_COORDS); - quadVertices.position(0); - - ByteBuffer bbTexCoords = - ByteBuffer.allocateDirect(numVertices * TEXCOORDS_PER_VERTEX * FLOAT_SIZE); - bbTexCoords.order(ByteOrder.nativeOrder()); - quadTexCoord = bbTexCoords.asFloatBuffer(); - quadTexCoord.put(QUAD_TEXCOORDS); - quadTexCoord.position(0); - - ByteBuffer bbTexCoordsTransformed = - ByteBuffer.allocateDirect(numVertices * TEXCOORDS_PER_VERTEX * FLOAT_SIZE); - bbTexCoordsTransformed.order(ByteOrder.nativeOrder()); - quadTexCoordTransformed = bbTexCoordsTransformed.asFloatBuffer(); - - int vertexShader = - ShaderUtils.loadGLShader(ERROR_TAG, context, GLES20.GL_VERTEX_SHADER, screenquad_vertex); - int fragmentShader = - ShaderUtils.loadGLShader( - ERROR_TAG, context, GLES20.GL_FRAGMENT_SHADER, screenquad_fragment); - - quadProgram = GLES20.glCreateProgram(); - GLES20.glAttachShader(quadProgram, vertexShader); - GLES20.glAttachShader(quadProgram, fragmentShader); - GLES20.glLinkProgram(quadProgram); - GLES20.glUseProgram(quadProgram); - - ShaderUtils.checkGLError(ERROR_TAG, CREATION_ERROR); - - quadPositionParam = GLES20.glGetAttribLocation(quadProgram, "a_Position"); - quadTexCoordParam = GLES20.glGetAttribLocation(quadProgram, "a_TexCoord"); - - ShaderUtils.checkGLError(ERROR_TAG, PARAMETERS_ERROR); - } - - public int getTextureId() { - return textureId; - } - - public void draw(Frame frame) { - - if (frame.hasDisplayGeometryChanged()) { - frame.transformDisplayUvCoords(quadTexCoord, quadTexCoordTransformed); - } - - GLES20.glDisable(GLES20.GL_DEPTH_TEST); - GLES20.glDepthMask(false); - - GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId); - - GLES20.glUseProgram(quadProgram); - - GLES20.glVertexAttribPointer( - quadPositionParam, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, quadVertices); - - GLES20.glVertexAttribPointer( - quadTexCoordParam, - TEXCOORDS_PER_VERTEX, - GLES20.GL_FLOAT, - false, - 0, - quadTexCoordTransformed); - - GLES20.glEnableVertexAttribArray(quadPositionParam); - GLES20.glEnableVertexAttribArray(quadTexCoordParam); - - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); - - GLES20.glDisableVertexAttribArray(quadPositionParam); - GLES20.glDisableVertexAttribArray(quadTexCoordParam); - - GLES20.glDepthMask(true); - GLES20.glEnable(GLES20.GL_DEPTH_TEST); - - ShaderUtils.checkGLError(ERROR_TAG, DRAW_ERROR); - } - - private static final float[] QUAD_COORDS = - new float[]{ - -1.0f, -1.0f, 0.0f, - -1.0f, +1.0f, 0.0f, - +1.0f, -1.0f, 0.0f, - +1.0f, +1.0f, 0.0f, - }; - - private static final float[] QUAD_TEXCOORDS = - new float[]{ - 0.0f, 1.0f, - 0.0f, 0.0f, - 1.0f, 1.0f, - 1.0f, 0.0f, - }; -} diff --git a/mode/libraries/ar/src/processing/ar/RotationHandler.java b/mode/libraries/ar/src/processing/ar/RotationHandler.java deleted file mode 100644 index cece970cc..000000000 --- a/mode/libraries/ar/src/processing/ar/RotationHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -package processing.ar; - - -import android.content.Context; -import android.hardware.display.DisplayManager; -import android.view.Display; -import android.view.WindowManager; - -import com.google.ar.core.Session; - - -public class RotationHandler implements DisplayManager.DisplayListener { - private boolean viewportChanged; - private int viewportWidth; - private int viewportHeight; - private final Context context; - private final Display display; - - public RotationHandler(Context context) { - this.context = context; - display = context.getSystemService(WindowManager.class).getDefaultDisplay(); - } - - public void onResume() { - context.getSystemService(DisplayManager.class).registerDisplayListener(this, null); - } - - public void onPause() { - context.getSystemService(DisplayManager.class).unregisterDisplayListener(this); - } - - public void onSurfaceChanged(int width, int height) { - viewportWidth = width; - viewportHeight = height; - viewportChanged = true; - } - - public void updateSessionIfNeeded(Session session) { - if (viewportChanged) { - int displayRotation = display.getRotation(); - session.setDisplayGeometry(displayRotation, viewportWidth, viewportHeight); - viewportChanged = false; - } - } - - public int getRotation() { - return display.getRotation(); - } - - @Override - public void onDisplayAdded(int displayId) { - } - - @Override - public void onDisplayRemoved(int displayId) { - } - - @Override - public void onDisplayChanged(int displayId) { - viewportChanged = true; - } -} diff --git a/mode/libraries/ar/src/processing/ar/ShaderUtils.java b/mode/libraries/ar/src/processing/ar/ShaderUtils.java deleted file mode 100644 index 97209d51b..000000000 --- a/mode/libraries/ar/src/processing/ar/ShaderUtils.java +++ /dev/null @@ -1,60 +0,0 @@ -package processing.ar; - -import android.content.Context; -import android.opengl.GLES20; - -import processing.core.PApplet; -import processing.core.PGraphics; - -import java.io.IOException; -import java.net.URL; - -public class ShaderUtils { - public static int loadGLShader(String tag, Context context, int type, URL resUrl) { - String code = readRawTextFile(resUrl); - int shader = GLES20.glCreateShader(type); - GLES20.glShaderSource(shader, code); - GLES20.glCompileShader(shader); - - final int[] compileStatus = new int[1]; - GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0); - - if (compileStatus[0] == 0) { - PGraphics.showWarning("Error compiling shader: " + GLES20.glGetShaderInfoLog(shader)); - GLES20.glDeleteShader(shader); - shader = 0; - } - - if (shader == 0) { - throw new RuntimeException("Error creating shader."); - } - - return shader; - } - - public static void checkGLError(String tag, String label) { - int lastError = GLES20.GL_NO_ERROR; - int error; - while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { - PGraphics.showWarning(label + ": glError " + error); - lastError = error; - } - if (lastError != GLES20.GL_NO_ERROR) { - throw new RuntimeException(label + ": glError " + lastError); - } - } - - private static String readRawTextFile(URL url) { - try { - String[] sample = PApplet.loadStrings(url.openStream()); - StringBuilder stringBuilder = new StringBuilder(); - for (String sam : sample) { - stringBuilder.append(sam).append("\n"); - } - return stringBuilder.toString(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } -} diff --git a/mode/libraries/vr/README.md b/mode/libraries/vr/README.md deleted file mode 100644 index e14303c16..000000000 --- a/mode/libraries/vr/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# VR library for Processing-Android - -This library includes a stereo renderer to create VR apps. - diff --git a/mode/libraries/vr/build.gradle b/mode/libraries/vr/build.gradle deleted file mode 100644 index 55a20e0ae..000000000 --- a/mode/libraries/vr/build.gradle +++ /dev/null @@ -1,103 +0,0 @@ -import java.nio.file.Files -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING - -plugins { - id 'aar' -} - -dependencies { - compileOnly name: "android" - compileOnly "org.p5android:processing-core:${modeVersion}" - -// commenting due to issue #718 -// implementationAar "com.google.vr:sdk-audio:${gvrVersion}" -// implementationAar "com.google.vr:sdk-base:${gvrVersion}" - -// fix for Issue #718 - implementationAar fileTree(dir: "libs", include: ["*.aar"]) -} - -task sourceJar(type: Jar, dependsOn: classes) { - classifier = "sources" - from sourceSets.main.allSource -} - -sourceSets { - main { - java { - srcDirs = ["src/"] - } - } -} - -// Does not work because of Processing-specific tags in source code, such as @webref -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = "javadoc" - from javadoc.destinationDir -} - -artifacts { -// archives javadocJar - archives sourceJar -} - -jar.doLast { task -> - ant.checksum file: task.archivePath -} - -clean.doFirst { - delete "dist" - delete "library/vr.jar" -} - -compileJava.doFirst { - String[] deps = ["sdk-audio.jar", - "sdk-base.jar", - "sdk-common.jar"] - File libFolder = file("library") - libFolder.mkdirs() - for (String fn : deps) { - Files.copy(file("${rootDir}/build/libs/" + fn).toPath(), - file("library/" + fn).toPath(), REPLACE_EXISTING); - } -} - -build.doLast { - // Copying vr jar to library folder - File vrJar = file("library/vr.jar") - vrJar.mkdirs(); - - // Need to check the existance of the files before using as the files - // will get generated only if Task ':mode:libraries:vr:jar' is not being skipped - // Task ':mode:libraries:vr:jar' will be skipped if source files are unchanged or jar task is UP-TO-DATE - - if (file("$buildDir/libs/vr.jar").exists()) { - Files.copy(file("$buildDir/libs/vr.jar").toPath(), - vrJar.toPath(), REPLACE_EXISTING); - } - // Renaming artifacts for maven publishing - if (file("$buildDir/libs/vr.jar").exists()) { - Files.move(file("$buildDir/libs/vr.jar").toPath(), - file("$buildDir/libs/processing-vr-${vrLibVersion}.jar").toPath(), REPLACE_EXISTING); - } - if (file("$buildDir/libs/vr-sources.jar").exists()) { - Files.move(file("$buildDir/libs/vr-sources.jar").toPath(), - file("$buildDir/libs/processing-vr-${vrLibVersion}-sources.jar").toPath(), REPLACE_EXISTING); - } - if (file("$buildDir/libs/vr.jar.MD5").exists()) { - Files.move(file("$buildDir/libs/vr.jar.MD5").toPath(), - file("$buildDir/libs/processing-vr-${vrLibVersion}.jar.md5").toPath(), REPLACE_EXISTING); - } -} - -ext { - libName = 'processing-vr' - libVersion = vrLibVersion - libJar = "${buildDir}/libs/${libName}-${libVersion}.jar" - libSrc = "${buildDir}/libs/${libName}-${libVersion}-sources.jar" - libMd5 = "${buildDir}/libs/${libName}-${libVersion}-sources.jar.md5" - libDependencies = [[group: 'org.p5android', name: 'processing-core', version: modeVersion], - [group: 'com.google.vr', name: 'sdk-base', version: gvrVersion], - [group: 'com.google.vr', name: 'sdk-audio', version: gvrVersion]] -} -apply from: "${rootProject.projectDir}/scripts/publish-module.gradle" diff --git a/mode/libraries/vr/examples/Cube/Cube.pde b/mode/libraries/vr/examples/Cube/Cube.pde deleted file mode 100644 index 7ecd2cb78..000000000 --- a/mode/libraries/vr/examples/Cube/Cube.pde +++ /dev/null @@ -1,14 +0,0 @@ -import processing.vr.*; - -void setup() { - fullScreen(VR); -} - -void draw() { - background(157); - lights(); - translate(width/2, height/2); - rotateX(frameCount * 0.01); - rotateY(frameCount * 0.01); - box(350); -} diff --git a/mode/libraries/vr/examples/Cube/code/sketch.properties b/mode/libraries/vr/examples/Cube/code/sketch.properties deleted file mode 100644 index 8b38b89c7..000000000 --- a/mode/libraries/vr/examples/Cube/code/sketch.properties +++ /dev/null @@ -1,3 +0,0 @@ -mode=Android -component=vr -mode.id=processing.mode.android.AndroidMode \ No newline at end of file diff --git a/mode/libraries/vr/examples/GenerateRay/GenerateRay.pde b/mode/libraries/vr/examples/GenerateRay/GenerateRay.pde deleted file mode 100644 index e9fcac44d..000000000 --- a/mode/libraries/vr/examples/GenerateRay/GenerateRay.pde +++ /dev/null @@ -1,59 +0,0 @@ -import processing.vr.*; - -PVector origin, direction; -float[] randomx = new float[5]; -float[] randomy = new float[5]; -float[] randomz = new float[5]; -VRCamera cam; - -void setup() { - fullScreen(VR); - cameraUp(); - cam = new VRCamera(this); - - for (int i = 0; i < 5; ++i) { - randomx[i] = random(-500, 500); - randomy[i] = random(-500, 500); - randomz[i] = random(-100, 100); - } - noStroke(); - - origin = new PVector(randomx[0], randomy[0], randomz[0]); - direction = new PVector(); -} - -void draw() { - background(200, 0, 150); - lights(); - - cam.setPosition(0, 0, 400); - push(); - translate(randomx[0], randomy[0], randomz[0]); - fill(0, 255, 0); - sphere(30); - - int r = floor(random(1, 5)); - float rx = randomx[r] - randomx[0]; - float ry = randomy[r] - randomy[0]; - float rz = randomz[r] - randomz[0]; - stroke(0); - strokeWeight(1 * displayDensity); - line(0, 0, 0, rx, ry, rz); - noStroke(); - - direction.set(rx, ry, rz); - direction.normalize(); - - pop(); - - for (int i = 1; i < 5; ++i) { - push(); - translate(randomx[i], randomy[i], randomz[i]); - fill(255, 0, 0); - if (intersectsSphere(70, origin, direction)) { - fill(0, 0, 255); - } - sphere(70); - pop(); - } -} \ No newline at end of file diff --git a/mode/libraries/vr/examples/GenerateRay/code/sketch.properties b/mode/libraries/vr/examples/GenerateRay/code/sketch.properties deleted file mode 100644 index 0828c1ecf..000000000 --- a/mode/libraries/vr/examples/GenerateRay/code/sketch.properties +++ /dev/null @@ -1,3 +0,0 @@ -mode=Android -component=vr -mode.id=processing.mode.android.AndroidMode diff --git a/mode/libraries/vr/examples/IntersectsBox/IntersectsBox.pde b/mode/libraries/vr/examples/IntersectsBox/IntersectsBox.pde deleted file mode 100644 index 566cb7a72..000000000 --- a/mode/libraries/vr/examples/IntersectsBox/IntersectsBox.pde +++ /dev/null @@ -1,27 +0,0 @@ -import processing.vr.*; - -VRCamera cam; -float rotSpeed = 0.3; -float rotAngle = 0; - -void setup() { - fullScreen(VR); - cameraUp(); - cam = new VRCamera(this); -} - -void draw() { - background(200, 0, 150); - - cam.setPosition(0, 0, 200); - push(); - rotateZ(radians(rotAngle)); - translate(100, 0, 0); - fill(255, 0, 0); - if (intersectsBox(50, 0, 0)) { - rotAngle += rotSpeed; - fill(0, 0, 255); - } - box(50); - pop(); -} \ No newline at end of file diff --git a/mode/libraries/vr/examples/IntersectsBox/code/sketch.properties b/mode/libraries/vr/examples/IntersectsBox/code/sketch.properties deleted file mode 100644 index 0828c1ecf..000000000 --- a/mode/libraries/vr/examples/IntersectsBox/code/sketch.properties +++ /dev/null @@ -1,3 +0,0 @@ -mode=Android -component=vr -mode.id=processing.mode.android.AndroidMode diff --git a/mode/libraries/vr/examples/IntersectsPlane/IntersectsPlane.pde b/mode/libraries/vr/examples/IntersectsPlane/IntersectsPlane.pde deleted file mode 100644 index a1a6f2701..000000000 --- a/mode/libraries/vr/examples/IntersectsPlane/IntersectsPlane.pde +++ /dev/null @@ -1,39 +0,0 @@ -import processing.vr.*; - -VRCamera cam; -float x, y; - -void setup() { - fullScreen(VR); - cameraUp(); - cam = new VRCamera(this); -} - -void draw() { - background(200, 0, 150); - - cam.setPosition(0, 0, 400); - fill(255, 170, 238); - plane(400, 400); - fill(255, 0, 0); - translate(x, y, 0); - PVector offset; - if (intersectsBox(60, 0, 0)) { - translate(-x, -y, 0); - fill(0, 0, 255); - offset = intersectsPlane(0, 0); - x = offset.x; - y = offset.y; - } - translate(x, y, 0); - box(60); -} - -void plane(float w, float d) { - beginShape(QUADS); - vertex(-w/2, -d/2); - vertex(+w/2, -d/2); - vertex(+w/2, +d/2); - vertex(-w/2, +d/2); - endShape(); -} \ No newline at end of file diff --git a/mode/libraries/vr/examples/IntersectsPlane/code/sketch.properties b/mode/libraries/vr/examples/IntersectsPlane/code/sketch.properties deleted file mode 100644 index 0828c1ecf..000000000 --- a/mode/libraries/vr/examples/IntersectsPlane/code/sketch.properties +++ /dev/null @@ -1,3 +0,0 @@ -mode=Android -component=vr -mode.id=processing.mode.android.AndroidMode diff --git a/mode/libraries/vr/examples/IntersectsSphere/IntersectsSphere.pde b/mode/libraries/vr/examples/IntersectsSphere/IntersectsSphere.pde deleted file mode 100644 index 041b91ed4..000000000 --- a/mode/libraries/vr/examples/IntersectsSphere/IntersectsSphere.pde +++ /dev/null @@ -1,42 +0,0 @@ -import processing.vr.*; - -float[] randomx = new float[5]; -float[] randomy = new float[5]; -VRCamera cam; - -void setup() { - fullScreen(VR); - cameraUp(); - cam = new VRCamera(this); - - for (int i = 0; i < 5; ++i) { - randomx[i] = random(-500, 500); - randomy[i] = random(-500, 500); - } -} - -void draw() { - background(200, 0, 150); - - lights(); - noStroke(); - cam.setPosition(0, 0, 400); - for (int i = 0; i < 5; ++i) { - push(); - translate(randomx[i], randomy[i]); - fill(255, 0, 0); - if (intersectsSphere(70, 0, 0)) { - fill(0, 0, 255); - } - sphere(70); - pop(); - } - - cam.sticky(); - strokeWeight(5 * displayDensity); - stroke(0, 0, 255); - noFill(); - translate(0, 0, 200); - circle(0, 0, 50); - cam.noSticky(); -} \ No newline at end of file diff --git a/mode/libraries/vr/examples/IntersectsSphere/code/sketch.properties b/mode/libraries/vr/examples/IntersectsSphere/code/sketch.properties deleted file mode 100644 index 0828c1ecf..000000000 --- a/mode/libraries/vr/examples/IntersectsSphere/code/sketch.properties +++ /dev/null @@ -1,3 +0,0 @@ -mode=Android -component=vr -mode.id=processing.mode.android.AndroidMode diff --git a/mode/libraries/vr/examples/Mono/Mono.pde b/mode/libraries/vr/examples/Mono/Mono.pde deleted file mode 100644 index df4714544..000000000 --- a/mode/libraries/vr/examples/Mono/Mono.pde +++ /dev/null @@ -1,14 +0,0 @@ -import processing.vr.*; - -void setup() { - fullScreen(MONO); -} - -void draw() { - background(157); - lights(); - translate(width/2, height/2); - rotateX(frameCount * 0.01f); - rotateY(frameCount * 0.01f); - box(500); -} \ No newline at end of file diff --git a/mode/libraries/vr/examples/Mono/code/sketch.properties b/mode/libraries/vr/examples/Mono/code/sketch.properties deleted file mode 100644 index 8b38b89c7..000000000 --- a/mode/libraries/vr/examples/Mono/code/sketch.properties +++ /dev/null @@ -1,3 +0,0 @@ -mode=Android -component=vr -mode.id=processing.mode.android.AndroidMode \ No newline at end of file diff --git a/mode/libraries/vr/examples/Stereoscopy/Stereoscopy.pde b/mode/libraries/vr/examples/Stereoscopy/Stereoscopy.pde deleted file mode 100644 index 8b3f12511..000000000 --- a/mode/libraries/vr/examples/Stereoscopy/Stereoscopy.pde +++ /dev/null @@ -1,88 +0,0 @@ -// Stereoscopy in VR: -// https://github.com/processing/processing-android/issues/593 -// By Javier Marco Rubio (https://github.com/jmarco2000) - -import processing.vr.*; - -int eyedist = 50; - -VRCamera cam; - -float angulo=0; - -float cx, cz; -float px, pz; -float ang; -float orbita = 400; -float vorbita = 0.01; - -// eye matrix -PMatrix3D eyeMat = new PMatrix3D(); - -boolean ciclo = false; //test witch eye is beign draw -float orientacion; - -void setup() { - fullScreen(VR); - cameraUp(); - rectMode(CENTER); - cam = new VRCamera(this); - cam.setNear(10); - cam.setFar(2500); - - //posicion planeta - //centro - cx=width/2; - cz=-200; - ang=0; -} - -void draw() { - ciclo = !ciclo; - - background(0); - lights(); - if (!ciclo) { - getEyeMatrix(eyeMat); - orientacion = acos(eyeMat.m00); - if (eyeMat.m02 < 0) orientacion =- orientacion; - println(degrees(orientacion)); - } - if (ciclo) { - cam.setPosition(+(eyedist/2) * cos(orientacion), 100, 500 + (eyedist/2) * sin(orientacion)); - } else { - cam.setPosition(-(eyedist/2) * cos(orientacion), 100, 500 - (eyedist/2) * sin(orientacion)); - } - - pushMatrix(); - px = cx + cos(ang) * orbita; - pz = cz + sin(ang) * orbita; - translate(px, 100, pz); - ang = ang + vorbita; - rotateY(1.25); - rotateX(-0.4); - rotateZ(angulo); //angulo=angulo+0.01; - noStroke(); - fill(251, 100, 10); - box(100); - popMatrix(); - - pushMatrix(); - translate(width/2, 100, cz); - rotateY(1.25); - rotateX(-0.4); - rotateZ(angulo); //angulo=angulo+0.01; - noStroke(); - fill(0, 200, 10); - sphere(70); - popMatrix(); -} - -void mousePressed() { - vorbita = 0; -} - -void mouseReleased() { - vorbita = 0.01; -} - diff --git a/mode/libraries/vr/examples/Stereoscopy/code/sketch.properties b/mode/libraries/vr/examples/Stereoscopy/code/sketch.properties deleted file mode 100644 index 8b38b89c7..000000000 --- a/mode/libraries/vr/examples/Stereoscopy/code/sketch.properties +++ /dev/null @@ -1,3 +0,0 @@ -mode=Android -component=vr -mode.id=processing.mode.android.AndroidMode \ No newline at end of file diff --git a/mode/libraries/vr/examples/drawAim/code/sketch.properties b/mode/libraries/vr/examples/drawAim/code/sketch.properties deleted file mode 100644 index 0828c1ecf..000000000 --- a/mode/libraries/vr/examples/drawAim/code/sketch.properties +++ /dev/null @@ -1,3 +0,0 @@ -mode=Android -component=vr -mode.id=processing.mode.android.AndroidMode diff --git a/mode/libraries/vr/examples/drawAim/drawAim.pde b/mode/libraries/vr/examples/drawAim/drawAim.pde deleted file mode 100644 index eaae4e797..000000000 --- a/mode/libraries/vr/examples/drawAim/drawAim.pde +++ /dev/null @@ -1,68 +0,0 @@ -import processing.vr.*; - -VRCamera cam; - -void setup() { - fullScreen(VR); - cam = new VRCamera(this); -} - -void calculate() { - println("in calculate function"); -} - -void draw() { - background(150); - translate(width/2, height/2); - noStroke(); - - // Some lights - pointLight(255, 255, 255, 0, 0, 500); - - // Floor - beginShape(QUADS); - fill(255, 0, 0); - normal(0, 0, -1); - vertex(-width/2, +500, -width/2); - fill(0, 0, 255); - vertex(-width/2, +500, +width/2); - vertex(+width/2, +500, +width/2); - fill(255, 0, 0); - vertex(+width/2, +500, -width/2); - endShape(); - - // Large box at the center - pushMatrix(); - rotateY(millis()/1000.0); - fill(220); - box(200); - popMatrix(); - - // Red box, X axis - pushMatrix(); - translate(200, 0, 0); - fill(255, 0, 0); - box(100); - popMatrix(); - - // Green box, Y axis - pushMatrix(); - translate(0, 200, 0); - fill(0, 255, 0); - box(100); - popMatrix(); - - // Blue box, Z axis - pushMatrix(); - translate(0, 0, 200); - fill(0, 0, 255); - box(100); - popMatrix(); - - // Use eye coordinates at 100 units from the camera position:; - cam.sticky(); - stroke(255, 200); - strokeWeight(50); - point(0, 0, 100); - cam.noSticky(); -} \ No newline at end of file diff --git a/mode/libraries/vr/library.properties b/mode/libraries/vr/library.properties deleted file mode 100644 index 2b6aecb22..000000000 --- a/mode/libraries/vr/library.properties +++ /dev/null @@ -1,10 +0,0 @@ -name = VR -authorList = Processing Foundation -url = http://android.processing.org -category = 3D -sentence = Renderer to develop VR apps -paragraph = -version = 13 -prettyVersion = 4.2.1 -minRevision = 249 -maxRevision = 1269 \ No newline at end of file diff --git a/mode/libraries/vr/libs/sdk-audio-1.180.0.aar b/mode/libraries/vr/libs/sdk-audio-1.180.0.aar deleted file mode 100644 index 007485cf4..000000000 Binary files a/mode/libraries/vr/libs/sdk-audio-1.180.0.aar and /dev/null differ diff --git a/mode/libraries/vr/libs/sdk-base-1.180.0.aar b/mode/libraries/vr/libs/sdk-base-1.180.0.aar deleted file mode 100644 index e9047d226..000000000 Binary files a/mode/libraries/vr/libs/sdk-base-1.180.0.aar and /dev/null differ diff --git a/mode/libraries/vr/libs/sdk-common-1.180.0.aar b/mode/libraries/vr/libs/sdk-common-1.180.0.aar deleted file mode 100644 index 7ba5cff92..000000000 Binary files a/mode/libraries/vr/libs/sdk-common-1.180.0.aar and /dev/null differ diff --git a/mode/libraries/vr/src/processing/vr/VRActivity.java b/mode/libraries/vr/src/processing/vr/VRActivity.java deleted file mode 100644 index d3433bfba..000000000 --- a/mode/libraries/vr/src/processing/vr/VRActivity.java +++ /dev/null @@ -1,195 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-19 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.vr; - -import com.google.vr.sdk.base.GvrActivity; - -import android.content.Intent; -import android.util.DisplayMetrics; -import processing.android.AppComponent; -import processing.android.ServiceEngine; -import processing.core.PApplet; - -public class VRActivity extends GvrActivity implements AppComponent { - static public final int GVR = 3; - - private DisplayMetrics metrics; - private PApplet sketch; - - - public VRActivity() { - - } - - - static public VRGraphics getRenderer(PApplet p) { - return (VRGraphics) p.g; - } - - - public VRActivity(PApplet sketch) { - this.sketch = sketch; - } - - - public void initDimensions() { - metrics = getResources().getDisplayMetrics(); - } - - - public int getDisplayWidth() { - return metrics.widthPixels; - } - - - public int getDisplayHeight() { - return metrics.heightPixels; - } - - - public float getDisplayDensity() { - return metrics.density; - } - - - public int getKind() { - return GVR; - } - - - public void dispose() { - } - - - public void setSketch(PApplet sketch) { - this.sketch = sketch; - if (sketch != null) { - sketch.initSurface(VRActivity.this, null); - // Required to read the paired viewer's distortion parameters. - sketch.requestPermission("android.permission.READ_EXTERNAL_STORAGE"); - } - } - - - public PApplet getSketch() { - return sketch; - } - - - public boolean isService() { - return false; - } - - - public ServiceEngine getEngine() { - return null; - } - - - @Override - public void onResume() { - super.onResume(); - if (sketch != null) { - sketch.onResume(); - } - } - - - @Override - public void onPause() { - super.onPause(); - if (sketch != null) { - sketch.onPause(); - } - } - - - @Override - public void onDestroy() { - super.onDestroy(); - if (sketch != null) { - sketch.onDestroy(); - } - } - - - @Override - public void onStart() { - super.onStart(); - if (sketch != null) { - sketch.onStart(); - } - } - - - @Override - public void onStop() { - super.onStop(); - if (sketch != null) { - sketch.onStop(); - } - } - - - public void requestDraw() { - } - - - public boolean canDraw() { - return true; - } - - - @Override - public void onRequestPermissionsResult(int requestCode, - String permissions[], - int[] grantResults) { - if (sketch != null) { - sketch.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - } - - - @Override - public void onNewIntent(Intent intent) { - if (sketch != null) { - sketch.onNewIntent(intent); - } - } - - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (sketch != null) { - sketch.onActivityResult(requestCode, resultCode, data); - } - } - - - @Override - public void onBackPressed() { - if (sketch != null) { - sketch.onBackPressed(); - } - } -} diff --git a/mode/libraries/vr/src/processing/vr/VRCamera.java b/mode/libraries/vr/src/processing/vr/VRCamera.java deleted file mode 100644 index c7e150297..000000000 --- a/mode/libraries/vr/src/processing/vr/VRCamera.java +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2019 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.vr; - -import processing.core.PApplet; -import processing.core.PMatrix3D; -import processing.core.PVector; - -public class VRCamera { - protected PApplet parent; - protected VRGraphics graphics; - protected PMatrix3D eyeMat; - - public VRCamera(PApplet parent) { - if (parent.g instanceof VRGraphics) { - this.parent = parent; - this.graphics = (VRGraphics)(parent.g); - } else { - System.err.println("The VR camera can only be created when the VR renderer is in use"); - } - } - - public void sticky() { - parent.pushMatrix(); - parent.eye(); - } - - public void noSticky() { - parent.popMatrix(); - } - - public void setPosition(float x, float y, float z) { - eyeMat = graphics.getEyeMatrix(eyeMat); - float x0 = eyeMat.m03; - float y0 = eyeMat.m13; - float z0 = eyeMat.m23; - graphics.translate(x0 - x, y0 - y, z0 - z); - } - - public void setNear(float near) { - graphics.defCameraNear = near; - } - - public void setFar(float far) { - graphics.defCameraFar = far; - } -} diff --git a/mode/libraries/vr/src/processing/vr/VRGraphics.java b/mode/libraries/vr/src/processing/vr/VRGraphics.java deleted file mode 100644 index f39560457..000000000 --- a/mode/libraries/vr/src/processing/vr/VRGraphics.java +++ /dev/null @@ -1,264 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-19 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.vr; - -import com.google.vr.sdk.base.Eye; -import com.google.vr.sdk.base.FieldOfView; -import com.google.vr.sdk.base.HeadTransform; -import com.google.vr.sdk.base.Viewport; - -import processing.core.PApplet; -import processing.core.PGraphics; -import processing.core.PMatrix3D; -import processing.core.PVector; -import processing.opengl.PGL; -import processing.opengl.PGLES; -import processing.opengl.PGraphics3D; -import processing.opengl.PGraphicsOpenGL; - -public class VRGraphics extends PGraphics3D { - static public final int LEFT = Eye.Type.LEFT; - static public final int RIGHT = Eye.Type.RIGHT; - static public final int MONOCULAR = Eye.Type.MONOCULAR; - - private boolean initialized = false; - - public HeadTransform headTransform; - public Eye eye; - public int eyeType; - - protected float[] forwardVector; - protected float[] rightVector; - protected float[] upVector; - - private Viewport eyeViewport; - private float[] eyeView; - private float[] eyePerspective; - - - @Override - protected PGL createPGL(PGraphicsOpenGL pg) { - return new PGLES(pg); - } - - - @Override - public void beginDraw() { - super.beginDraw(); - updateView(); - } - - - @Override - public void camera(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - PGraphics.showWarning("The camera cannot be set in VR"); - } - - - @Override - public void perspective(float fov, float aspect, float zNear, float zFar) { - PGraphics.showWarning("Perspective cannot be set in VR"); - } - - - @Override - protected void defaultCamera() { - // do nothing - } - - - @Override - protected void defaultPerspective() { - // do nothing - } - - - @Override - protected void saveState() { - } - - - @Override - protected void restoreState() { - } - - - @Override - protected void restoreSurface() { - } - - - protected void updateView() { - setVRViewport(); - setVRCamera(); - setVRProjection(); - } - - - protected void eyeTransform(Eye e) { - eye = e; - eyeType = eye.getType(); - eyeViewport = eye.getViewport(); - eyePerspective = eye.getPerspective(defCameraNear, defCameraFar); - eyeView = eye.getEyeView(); - - // Adjust the camera Z position to it fits the (width,height) rect at Z = 0, given - // the fov settings. - FieldOfView fov = eye.getFov(); - defCameraFOV = fov.getTop()* DEG_TO_RAD; - defCameraZ = (float) (height / (2 * Math.tan(defCameraFOV))); - cameraAspect = (float)width / height; - if (cameraUp) { - defCameraX = 0; - defCameraY = 0; - } else { - defCameraX = +width / 2.0f; - defCameraY = +height / 2.0f; - } - } - - - protected void headTransform(HeadTransform ht) { - initVR(); - - headTransform = ht; - - // Forward, right, and up vectors are given in the original system with Y - // pointing up. Need to invert y coords in the non-gl case: - float yf = cameraUp ? +1 : -1; - - headTransform.getForwardVector(forwardVector, 0); - headTransform.getRightVector(rightVector, 0); - headTransform.getUpVector(upVector, 0); - - forwardX = forwardVector[0]; - forwardY = yf * forwardVector[1]; - forwardZ = forwardVector[2]; - - rightX = rightVector[0]; - rightY = yf * rightVector[1]; - rightZ = rightVector[2]; - - upX = upVector[0]; - upY = yf * upVector[1]; - upZ = upVector[2]; - } - - - protected void initVR() { - if (!initialized) { - forwardVector = new float[3]; - rightVector = new float[3]; - upVector = new float[3]; - initialized = true; - } - } - - - protected void setVRViewport() { - pgl.viewport(eyeViewport.x, eyeViewport.y, eyeViewport.width, eyeViewport.height); - } - - - protected void setVRCamera() { - cameraX = defCameraX; - cameraY = defCameraY; - cameraZ = defCameraZ; - - // Calculating Z vector - float z0 = 0; - float z1 = 0; - float z2 = defCameraZ; - eyeDist = PApplet.abs(z2); - if (nonZero(eyeDist)) { - z0 /= eyeDist; - z1 /= eyeDist; - z2 /= eyeDist; - } - - // Calculating Y vector - float y0 = 0; - float y1 = cameraUp ? + 1: -1; - float y2 = 0; - - // Computing X vector as Y cross Z - float x0 = y1 * z2 - y2 * z1; - float x1 = -y0 * z2 + y2 * z0; - float x2 = y0 * z1 - y1 * z0; - if (!cameraUp) { - // Inverting X axis - x0 *= -1; - x1 *= -1; - x2 *= -1; - } - - // Cross product gives area of parallelogram, which is < 1.0 for - // non-perpendicular unit-length vectors; so normalize x, y here: - float xmag = PApplet.sqrt(x0 * x0 + x1 * x1 + x2 * x2); - if (nonZero(xmag)) { - x0 /= xmag; - x1 /= xmag; - x2 /= xmag; - } - - float ymag = PApplet.sqrt(y0 * y0 + y1 * y1 + y2 * y2); - if (nonZero(ymag)) { - y0 /= ymag; - y1 /= ymag; - y2 /= ymag; - } - - // Pre-apply the eye view matrix: - // https://developers.google.com/vr/android/reference/com/google/vr/sdk/base/Eye.html#getEyeView() - modelview.set(eyeView[0], eyeView[4], eyeView[8], eyeView[12], - eyeView[1], eyeView[5], eyeView[9], eyeView[13], - eyeView[2], eyeView[6], eyeView[10], eyeView[14], - eyeView[3], eyeView[7], eyeView[11], eyeView[15]); - modelview.apply(x0, x1, x2, 0, - y0, y1, y2, 0, - z0, z1, z2, 0, - 0, 0, 0, 1); - float tx = -defCameraX; - float ty = -defCameraY; - float tz = -defCameraZ; - modelview.translate(tx, ty, tz); - - modelviewInv.set(modelview); - modelviewInv.invert(); - - camera.set(modelview); - cameraInv.set(modelviewInv); - } - - - protected void setVRProjection() { - // Matrices in Processing are row-major, and GVR API is column-major - projection.set(eyePerspective[0], eyePerspective[4], eyePerspective[8], eyePerspective[12], - eyePerspective[1], eyePerspective[5], eyePerspective[9], eyePerspective[13], - eyePerspective[2], eyePerspective[6], eyePerspective[10], eyePerspective[14], - eyePerspective[3], eyePerspective[7], eyePerspective[11], eyePerspective[15]); - updateProjmodelview(); - } -} diff --git a/mode/libraries/vr/src/processing/vr/VRGraphicsMono.java b/mode/libraries/vr/src/processing/vr/VRGraphicsMono.java deleted file mode 100644 index 6a31a2b57..000000000 --- a/mode/libraries/vr/src/processing/vr/VRGraphicsMono.java +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-19 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.vr; - -import android.view.SurfaceHolder; -import processing.android.AppComponent; -import processing.core.PSurface; - -public class VRGraphicsMono extends VRGraphics { - @Override - public PSurface createSurface(AppComponent component, SurfaceHolder holder, boolean reset) { // ignore - if (reset) pgl.resetFBOLayer(); - return new VRSurface(this, component, holder, false); - } -} \ No newline at end of file diff --git a/mode/libraries/vr/src/processing/vr/VRGraphicsStereo.java b/mode/libraries/vr/src/processing/vr/VRGraphicsStereo.java deleted file mode 100644 index 681de9e1b..000000000 --- a/mode/libraries/vr/src/processing/vr/VRGraphicsStereo.java +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-19 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.vr; - -import android.view.SurfaceHolder; -import processing.android.AppComponent; -import processing.core.PSurface; - -public class VRGraphicsStereo extends VRGraphics { - @Override - public PSurface createSurface(AppComponent component, SurfaceHolder holder, boolean reset) { // ignore - if (reset) pgl.resetFBOLayer(); - return new VRSurface(this, component, holder, true); - } -} diff --git a/mode/libraries/vr/src/processing/vr/VRSurface.java b/mode/libraries/vr/src/processing/vr/VRSurface.java deleted file mode 100644 index dac07ee27..000000000 --- a/mode/libraries/vr/src/processing/vr/VRSurface.java +++ /dev/null @@ -1,338 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-19 The Processing Foundation - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.vr; - -import java.io.File; -import java.io.InputStream; - -import javax.microedition.khronos.egl.EGLConfig; - -import com.google.vr.sdk.base.GvrActivity; -import com.google.vr.sdk.base.GvrView; -import com.google.vr.sdk.base.AndroidCompat; -import com.google.vr.sdk.base.Eye; -import com.google.vr.sdk.base.HeadTransform; -import com.google.vr.sdk.base.Viewport; - -import android.app.Activity; -import android.app.ActivityManager; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ConfigurationInfo; -import android.content.res.AssetManager; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import processing.android.AppComponent; -import processing.core.PGraphics; -import processing.opengl.PGLES; -import processing.opengl.PGraphicsOpenGL; -import processing.opengl.PSurfaceGLES; -import android.view.Window; -import android.view.WindowManager; - -public class VRSurface extends PSurfaceGLES { - protected SurfaceViewVR vrView; - protected VRGraphics pvr; - - protected GvrActivity vrActivity; - protected AndroidVRStereoRenderer renderer; - - private boolean needCalculate; - - public VRSurface(PGraphics graphics, AppComponent component, SurfaceHolder holder, boolean vr) { - this.sketch = graphics.parent; - this.graphics = graphics; - this.component = component; - this.pgl = (PGLES)((PGraphicsOpenGL)graphics).pgl; - - vrActivity = (GvrActivity)component; - this.activity = vrActivity; - pvr = (VRGraphics)graphics; - - vrView = new SurfaceViewVR(vrActivity); - - // Enables/disables the transition view used to prompt the user to place - // their phone into a GVR viewer. - vrView.setTransitionViewEnabled(true); - - // Enables Cardboard-trigger feedback with Daydream headsets. This is a simple way of supporting - // Daydream controller input for basic interactions using the existing Cardboard trigger API. - vrView.enableCardboardTriggerEmulation(); - - vrView.setStereoModeEnabled(vr); - if (vr) { - vrView.setDistortionCorrectionEnabled(true); - vrView.setNeckModelEnabled(true); - } - - if (vrView.setAsyncReprojectionEnabled(true)) { - // Async reprojection decouples the app framerate from the display framerate, - // allowing immersive interaction even at the throttled clockrates set by - // sustained performance mode. - AndroidCompat.setSustainedPerformanceMode(vrActivity, true); - } - vrActivity.setGvrView(vrView); - - surfaceView = null; - - // The glview is ready right after creation, does not need to wait for a - // surfaceCreate() event. - surfaceReady = true; - } - - @Override - public Context getContext() { - return vrActivity; - } - - @Override - public Activity getActivity() { - return vrActivity; - } - - @Override - public void finish() { - vrActivity.finish(); - } - - @Override - public AssetManager getAssets() { - return vrActivity.getAssets(); - } - - @Override - public void startActivity(Intent intent) { - vrActivity.startActivity(intent); - } - - @Override - public void initView(int sketchWidth, int sketchHeight) { - Window window = vrActivity.getWindow(); - - // Take up as much area as possible - //requestWindowFeature(Window.FEATURE_NO_TITLE); // may need to set in theme properties - // the above line does not seem to be needed when using VR - // android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" > - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); - - // This does the actual full screen work - window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - - window.setContentView(vrView); - } - - @Override - public String getName() { - return vrActivity.getComponentName().getPackageName(); - } - - @Override - public void setOrientation(int which) { - PGraphics.showWarning("Orientation in VR apps cannot be changed"); - } - - @Override - public File getFilesDir() { - return vrActivity.getFilesDir(); - } - - @Override - public InputStream openFileInput(String filename) { - return null; - } - - @Override - public File getFileStreamPath(String path) { - return vrActivity.getFileStreamPath(path); - } - - @Override - public void dispose() { -// surface.onDestroy(); - } - - - /////////////////////////////////////////////////////////// - - // Thread handling - - private boolean running = false; - - @Override - public void startThread() { - vrView.onResume(); - running = true; - } - - @Override - public void pauseThread() { - vrView.onPause(); - running = false; - } - - @Override - public void resumeThread() { - vrView.onResume(); - running = true; - } - - @Override - public boolean stopThread() { - running = false; - return true; - } - - @Override - public boolean isStopped() { - return !running; - } - - /////////////////////////////////////////////////////////// - - public class SurfaceViewVR extends GvrView { - public SurfaceViewVR(Context context) { - super(context); - - // Check if the system supports OpenGL ES 2.0. - final ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo(); - final boolean supportsGLES2 = configurationInfo.reqGlEsVersion >= 0x20000; - - if (!supportsGLES2) { - throw new RuntimeException("OpenGL ES 2.0 is not supported by this device."); - } - - setFocusable(true); - setFocusableInTouchMode(true); - requestFocus(); - - - int samples = sketch.sketchSmooth(); - if (1 < samples) { - setMultisampling(samples); - } else { - // use default EGL config chooser for now -// setEGLConfigChooser(8, 8, 8, 8, 16, 8); - } - - // The renderer can be set only once. - setRenderer(getVRStereoRenderer()); - } - - - @Override - public boolean onTouchEvent(MotionEvent event) { - return sketch.surfaceTouchEvent(event); - } - - - @Override - public boolean onKeyDown(int code, android.view.KeyEvent event) { - sketch.surfaceKeyDown(code, event); - return super.onKeyDown(code, event); - } - - - @Override - public boolean onKeyUp(int code, android.view.KeyEvent event) { - sketch.surfaceKeyUp(code, event); - return super.onKeyUp(code, event); - } - } - - /////////////////////////////////////////////////////////// - - // Android specific classes (Renderer, ConfigChooser) - - - public AndroidVRStereoRenderer getVRStereoRenderer() { - renderer = new AndroidVRStereoRenderer(); - return renderer; - } - - - protected class AndroidVRStereoRenderer implements GvrView.StereoRenderer { - public AndroidVRStereoRenderer() { - - } - - @Override - public void onNewFrame(HeadTransform transform) { - hadnleGVREnumError(); - pgl.getGL(null); - pvr.headTransform(transform); - needCalculate = true; - } - - @Override - public void onDrawEye(Eye eye) { - pvr.eyeTransform(eye); - if (needCalculate) { - // Call calculate() right after we have the first eye transform. - // This allows to update the modelview and projection matrices, so - // geometry-related calculations can also be conducted in calculate(). - pvr.updateView(); - sketch.calculate(); - needCalculate = false; - } - sketch.handleDraw(); - } - - @Override - public void onFinishFrame(Viewport arg0) { - } - - @Override - public void onRendererShutdown() { - } - - @Override - public void onSurfaceChanged(int iwidth, int iheight) { - sketch.surfaceChanged(); - graphics.surfaceChanged(); - - sketch.setSize(iwidth, iheight); - graphics.setSize(sketch.sketchWidth(), sketch.sketchHeight()); - } - - @Override - public void onSurfaceCreated(EGLConfig arg0) { - } - - // Don't print the invalid enum error: - // https://github.com/processing/processing-android/issues/281 - // seems harmless as it happens in the first frame only - // TODO: need to find the reason for the error (gl config?) - private void hadnleGVREnumError() { - int err = pgl.getError(); - if (err != 0 && err != 1280) { - String where = "top onNewFrame"; - String errString = pgl.errorString(err); - String msg = "OpenGL error " + err + " at " + where + ": " + errString; - PGraphics.showWarning(msg); - } - } - } -} diff --git a/mode/mode.properties b/mode/mode.properties deleted file mode 100644 index c91327d3b..000000000 --- a/mode/mode.properties +++ /dev/null @@ -1,11 +0,0 @@ -name = Android Mode for Processing 4 -authorList = [The Processing Foundation](https://processingfoundation.org/) -url = http://android.processing.org -sentence = This mode lets you use Processing to create Android apps -paragraph = -imports=processing.mode.java.JavaMode -version = 409 -prettyVersion = 4.5.0b5 -minRevision = 1283 -maxRevision = 0 - diff --git a/mode/mode/JavaMode.jar b/mode/mode/JavaMode.jar deleted file mode 100644 index 04c55cc15..000000000 Binary files a/mode/mode/JavaMode.jar and /dev/null differ diff --git a/mode/mode/core.jar b/mode/mode/core.jar deleted file mode 100644 index e7b82a144..000000000 Binary files a/mode/mode/core.jar and /dev/null differ diff --git a/mode/mode/gradlew.zip b/mode/mode/gradlew.zip deleted file mode 100644 index e782e5b17..000000000 Binary files a/mode/mode/gradlew.zip and /dev/null differ diff --git a/mode/mode/istack-commons-runtime.jar b/mode/mode/istack-commons-runtime.jar deleted file mode 100644 index b91ea56ba..000000000 Binary files a/mode/mode/istack-commons-runtime.jar and /dev/null differ diff --git a/mode/mode/javax.activation-api.jar b/mode/mode/javax.activation-api.jar deleted file mode 100644 index 986c36509..000000000 Binary files a/mode/mode/javax.activation-api.jar and /dev/null differ diff --git a/mode/mode/jaxb-api.jar b/mode/mode/jaxb-api.jar deleted file mode 100644 index 456586547..000000000 Binary files a/mode/mode/jaxb-api.jar and /dev/null differ diff --git a/mode/mode/jaxb-jxc.jar b/mode/mode/jaxb-jxc.jar deleted file mode 100644 index 039e6cb2d..000000000 Binary files a/mode/mode/jaxb-jxc.jar and /dev/null differ diff --git a/mode/mode/jaxb-runtime.jar b/mode/mode/jaxb-runtime.jar deleted file mode 100644 index 0b9ef67c4..000000000 Binary files a/mode/mode/jaxb-runtime.jar and /dev/null differ diff --git a/mode/mode/jaxb-xjc.jar b/mode/mode/jaxb-xjc.jar deleted file mode 100644 index aab6be555..000000000 Binary files a/mode/mode/jaxb-xjc.jar and /dev/null differ diff --git a/mode/mode/jdi.jar b/mode/mode/jdi.jar deleted file mode 100644 index 397e9e4da..000000000 Binary files a/mode/mode/jdi.jar and /dev/null differ diff --git a/mode/mode/jdimodel.jar b/mode/mode/jdimodel.jar deleted file mode 100644 index 3e272ce72..000000000 Binary files a/mode/mode/jdimodel.jar and /dev/null differ diff --git a/mode/mode/org.eclipse.core.contenttype.jar b/mode/mode/org.eclipse.core.contenttype.jar deleted file mode 100644 index 2d8f772d1..000000000 Binary files a/mode/mode/org.eclipse.core.contenttype.jar and /dev/null differ diff --git a/mode/mode/org.eclipse.core.jobs.jar b/mode/mode/org.eclipse.core.jobs.jar deleted file mode 100644 index 579555f49..000000000 Binary files a/mode/mode/org.eclipse.core.jobs.jar and /dev/null differ diff --git a/mode/mode/org.eclipse.core.resources.jar b/mode/mode/org.eclipse.core.resources.jar deleted file mode 100644 index dd04e3eef..000000000 Binary files a/mode/mode/org.eclipse.core.resources.jar and /dev/null differ diff --git a/mode/mode/org.eclipse.core.runtime.jar b/mode/mode/org.eclipse.core.runtime.jar deleted file mode 100644 index 4b46a1262..000000000 Binary files a/mode/mode/org.eclipse.core.runtime.jar and /dev/null differ diff --git a/mode/mode/org.eclipse.equinox.common.jar b/mode/mode/org.eclipse.equinox.common.jar deleted file mode 100644 index c2a745e12..000000000 Binary files a/mode/mode/org.eclipse.equinox.common.jar and /dev/null differ diff --git a/mode/mode/org.eclipse.equinox.preferences.jar b/mode/mode/org.eclipse.equinox.preferences.jar deleted file mode 100644 index d6cb801c6..000000000 Binary files a/mode/mode/org.eclipse.equinox.preferences.jar and /dev/null differ diff --git a/mode/mode/org.eclipse.jdt.core.jar b/mode/mode/org.eclipse.jdt.core.jar deleted file mode 100644 index 2b675bc84..000000000 Binary files a/mode/mode/org.eclipse.jdt.core.jar and /dev/null differ diff --git a/mode/mode/org.eclipse.osgi.jar b/mode/mode/org.eclipse.osgi.jar deleted file mode 100644 index 91f36da60..000000000 Binary files a/mode/mode/org.eclipse.osgi.jar and /dev/null differ diff --git a/mode/mode/org.eclipse.text.jar b/mode/mode/org.eclipse.text.jar deleted file mode 100644 index e1263c239..000000000 Binary files a/mode/mode/org.eclipse.text.jar and /dev/null differ diff --git a/mode/mode/pde.jar b/mode/mode/pde.jar deleted file mode 100644 index 0eba179a6..000000000 Binary files a/mode/mode/pde.jar and /dev/null differ diff --git a/mode/resources/device-art-resources/device-art.xml b/mode/resources/device-art-resources/device-art.xml deleted file mode 100644 index b67fa2033..000000000 --- a/mode/resources/device-art-resources/device-art.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mode/resources/device-art-resources/pixel_3/layout b/mode/resources/device-art-resources/pixel_3/layout deleted file mode 100644 index 4615fb58d..000000000 --- a/mode/resources/device-art-resources/pixel_3/layout +++ /dev/null @@ -1,38 +0,0 @@ -parts { - device { - display { - width 1080 - height 2160 - x 0 - y 0 - } - } - portrait { - background { - image port_back.webp - } - foreground { - mask round_corners.webp - } - onion { - image port_fore.webp - } - } -} -layouts { - portrait { - width 1194 - height 2532 - event EV_SW:0:1 - part1 { - name portrait - x 0 - y 0 - } - part2 { - name device - x 54 - y 196 - } - } -} diff --git a/mode/resources/device-art-resources/pixel_3/port_back.webp b/mode/resources/device-art-resources/pixel_3/port_back.webp deleted file mode 100644 index 6037b7963..000000000 Binary files a/mode/resources/device-art-resources/pixel_3/port_back.webp and /dev/null differ diff --git a/mode/resources/device-art-resources/pixel_3/round_corners.webp b/mode/resources/device-art-resources/pixel_3/round_corners.webp deleted file mode 100644 index 9dad9033a..000000000 Binary files a/mode/resources/device-art-resources/pixel_3/round_corners.webp and /dev/null differ diff --git a/mode/resources/device-art-resources/pixel_6/back.webp b/mode/resources/device-art-resources/pixel_6/back.webp deleted file mode 100644 index a41256802..000000000 Binary files a/mode/resources/device-art-resources/pixel_6/back.webp and /dev/null differ diff --git a/mode/resources/device-art-resources/pixel_6/layout b/mode/resources/device-art-resources/pixel_6/layout deleted file mode 100644 index ae638d344..000000000 --- a/mode/resources/device-art-resources/pixel_6/layout +++ /dev/null @@ -1,36 +0,0 @@ -parts { - device { - display { - width 1080 - height 2400 - x 0 - y 0 - } - } - portrait { - background { - image back.webp - } - foreground { - mask mask.webp - cutout hole - } - } -} -layouts { - portrait { - width 1209 - height 2553 - event EV_SW:0:1 - part1 { - name portrait - x 0 - y 0 - } - part2 { - name device - x 60 - y 69 - } - } -} diff --git a/mode/resources/device-art-resources/pixel_6/mask.webp b/mode/resources/device-art-resources/pixel_6/mask.webp deleted file mode 100644 index c658b192d..000000000 Binary files a/mode/resources/device-art-resources/pixel_6/mask.webp and /dev/null differ diff --git a/mode/resources/device-art-resources/pixel_c/land_back.webp b/mode/resources/device-art-resources/pixel_c/land_back.webp deleted file mode 100644 index 4cec52875..000000000 Binary files a/mode/resources/device-art-resources/pixel_c/land_back.webp and /dev/null differ diff --git a/mode/resources/device-art-resources/pixel_c/land_fore.webp b/mode/resources/device-art-resources/pixel_c/land_fore.webp deleted file mode 100644 index 66a0b9df0..000000000 Binary files a/mode/resources/device-art-resources/pixel_c/land_fore.webp and /dev/null differ diff --git a/mode/resources/device-art-resources/pixel_c/land_shadow.webp b/mode/resources/device-art-resources/pixel_c/land_shadow.webp deleted file mode 100644 index 15acd8679..000000000 Binary files a/mode/resources/device-art-resources/pixel_c/land_shadow.webp and /dev/null differ diff --git a/mode/resources/device-art-resources/pixel_c/layout b/mode/resources/device-art-resources/pixel_c/layout deleted file mode 100644 index 7378ba8c5..000000000 --- a/mode/resources/device-art-resources/pixel_c/layout +++ /dev/null @@ -1,59 +0,0 @@ -parts { - device { - display { - width 1800 - height 2560 - x 0 - y 0 - } - } - portrait { - background { - image port_back.webp - } - onion { - image port_fore.webp - } - } - landscape { - background { - image land_back.webp - } - onion { - image land_fore.webp - } - } -} -layouts { - portrait { - width 2307 - height 2971 - event EV_SW:0:1 - part1 { - name portrait - x 0 - y 0 - } - part2 { - name device - x 259 - y 181 - } - } - landscape { - width 3096 - height 2215 - event EV_SW:0:0 - part1 { - name landscape - x 0 - y 0 - } - part2 { - name device - x 269 - y 1988 - rotation 3 - } - } -} diff --git a/mode/resources/device-art-resources/pixel_c/port_back.webp b/mode/resources/device-art-resources/pixel_c/port_back.webp deleted file mode 100644 index ee9e3eaea..000000000 Binary files a/mode/resources/device-art-resources/pixel_c/port_back.webp and /dev/null differ diff --git a/mode/resources/device-art-resources/pixel_c/port_fore.webp b/mode/resources/device-art-resources/pixel_c/port_fore.webp deleted file mode 100644 index f2e6b7ca5..000000000 Binary files a/mode/resources/device-art-resources/pixel_c/port_fore.webp and /dev/null differ diff --git a/mode/resources/device-art-resources/pixel_c/port_shadow.webp b/mode/resources/device-art-resources/pixel_c/port_shadow.webp deleted file mode 100644 index e7c1e74bf..000000000 Binary files a/mode/resources/device-art-resources/pixel_c/port_shadow.webp and /dev/null differ diff --git a/mode/resources/device-art-resources/wearos_small_round/device_bezel.png b/mode/resources/device-art-resources/wearos_small_round/device_bezel.png deleted file mode 100644 index 5eccf08ce..000000000 Binary files a/mode/resources/device-art-resources/wearos_small_round/device_bezel.png and /dev/null differ diff --git a/mode/resources/device-art-resources/wearos_small_round/hardware.ini b/mode/resources/device-art-resources/wearos_small_round/hardware.ini deleted file mode 100644 index 3f8ab78b8..000000000 --- a/mode/resources/device-art-resources/wearos_small_round/hardware.ini +++ /dev/null @@ -1,3 +0,0 @@ -# skin-specific hardware values -hw.rotaryInput=yes -hw.sensors.heart_rate=yes diff --git a/mode/resources/device-art-resources/wearos_small_round/layout b/mode/resources/device-art-resources/wearos_small_round/layout deleted file mode 100644 index 6c45bac29..000000000 --- a/mode/resources/device-art-resources/wearos_small_round/layout +++ /dev/null @@ -1,46 +0,0 @@ -parts { - portrait { - background { - image device_bezel.png - } - } - - device { - display { - width 384 - height 384 - x 0 - y 0 - } - } -} - -layouts { - portrait { - width 456 - height 456 - color 0x1f1f1f - event EV_SW:0:1 - - part1 { - name portrait - x 0 - y 0 - } - - part2 { - name device - x 36 - y 36 - } - } -} - -keyboard { - charmap qwerty2 -} - -network { - speed full - delay none -} diff --git a/mode/resources/device-art-resources/wearos_square/device_bezel.png b/mode/resources/device-art-resources/wearos_square/device_bezel.png deleted file mode 100644 index 01c5cc146..000000000 Binary files a/mode/resources/device-art-resources/wearos_square/device_bezel.png and /dev/null differ diff --git a/mode/resources/device-art-resources/wearos_square/hardware.ini b/mode/resources/device-art-resources/wearos_square/hardware.ini deleted file mode 100644 index 3f8ab78b8..000000000 --- a/mode/resources/device-art-resources/wearos_square/hardware.ini +++ /dev/null @@ -1,3 +0,0 @@ -# skin-specific hardware values -hw.rotaryInput=yes -hw.sensors.heart_rate=yes diff --git a/mode/resources/device-art-resources/wearos_square/layout b/mode/resources/device-art-resources/wearos_square/layout deleted file mode 100644 index d1f9278d1..000000000 --- a/mode/resources/device-art-resources/wearos_square/layout +++ /dev/null @@ -1,46 +0,0 @@ -parts { - portrait { - background { - image device_bezel.png - } - } - - device { - display { - width 360 - height 360 - x 0 - y 0 - } - } -} - -layouts { - portrait { - width 432 - height 432 - color 0x1f1f1f - event EV_SW:0:1 - - part1 { - name portrait - x 18 - y 18 - } - - part2 { - name device - x 36 - y 36 - } - } -} - -keyboard { - charmap qwerty2 -} - -network { - speed full - delay none -} diff --git a/mode/scripts/permissions.py b/mode/scripts/permissions.py deleted file mode 100644 index 4e8053864..000000000 --- a/mode/scripts/permissions.py +++ /dev/null @@ -1,84 +0,0 @@ -import sys, re - -from urllib.request import urlopen -from bs4 import BeautifulSoup - -def get_soup(url): - page = urlopen(url) - soup = BeautifulSoup(page, features="lxml") - return soup - -def parse_all(soup): - print('Parsing all permissions...') - table = soup.find('table', { 'id': 'constants', 'class' : 'responsive constants' }) - entries = table.find_all('tr') - str_list = '' - for entry in entries: - if not entry or not entry.attrs: continue - info = entry.find('td', {'width':'100%'}) - if info: - name = info.find('code').find('a').contents[0] - pieces = [] - deprecated = False - for piece in info.find('p').contents: - piece_str = re.sub('\s+', ' ', str(piece)).strip() - if '' in piece_str: - piece_str = piece.find('a').contents[0].strip() - if '' in piece_str and 'This constant was deprecated' in piece_str: - deprecated = True - pieces += [piece_str] - if name and pieces and not deprecated: - desc = ' '.join(pieces).strip().replace('"', '\\"') - str_list += (',' if str_list else '') + '\n "' + name + '", "' + desc + '"' - str_list = 'static final String[] listing = {' + str_list + '\n };\n' - return str_list - -def replace_all(source, str_list): - print('Replacing old permissions...') - idx0 = source.find('static final String[] listing = {') - idx1 = source[idx0:].find(' };') - return source[:idx0] + str_list + source[idx0+idx1+5:] - -def parse_danger(soup): - print('Parsing dangerous permissions...') - entries = soup.find_all(lambda tag:tag.name == "div" and - len(tag.attrs) == 1 and - "data-version-added" in tag.attrs) - str_list = '' - for entry in entries: - name = entry.find('h3').contents[0] - items = entry.find_all('p') - for item in items: - text = item.getText().strip() - if 'Protection level:' in text and 'dangerous' in text: - str_list += (',' if str_list else '') + '\n "' + name + '"' - str_list = 'static final String[] dangerous = {' + str_list + '\n };\n' - return str_list - -def replace_danger(source, str_list): - print('Replacing dangerous permissions...') - idx0 = source.find('static final String[] dangerous = {') - idx1 = source[idx0:].find(' };') - return source[:idx0] + str_list + source[idx0+idx1+5:] - -java_file = '../src/processing/mode/android/Permissions.java' -ref_url = 'https://developer.android.com/reference/android/Manifest.permission.html' - -print('Reading Android reference...') -soup = get_soup(ref_url) - -print('Reading Permissions.java...') -with open(java_file, 'r') as f: - source = f.read() - -all_list = parse_all(soup) -source = replace_all(source, all_list) - -danger_list = parse_danger(soup) -source = replace_danger(source, danger_list) - -print('Writing Permissions.java...') -with open(java_file, 'w') as f: - f.write(source) - -print('Done.') \ No newline at end of file diff --git a/mode/scripts/requirements.txt b/mode/scripts/requirements.txt deleted file mode 100644 index c1f5f713c..000000000 --- a/mode/scripts/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -beautifulsoup4 diff --git a/mode/src/processing/mode/android/AVD.java b/mode/src/processing/mode/android/AVD.java deleted file mode 100644 index 47bf632f4..000000000 --- a/mode/src/processing/mode/android/AVD.java +++ /dev/null @@ -1,484 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import processing.app.Base; -import processing.app.Platform; -import processing.app.Preferences; -import processing.app.exec.StreamPump; -import processing.core.PApplet; - -import java.awt.Frame; -import java.io.*; -import java.util.ArrayList; -import java.util.Map; - - -public class AVD { - final static private int PHONE = 0; - final static private int WEAR = 1; - - final static public String DEFAULT_ABI = "x86"; - - public static final String TARGET_SDK_ARM = "24"; - - public final static String DEFAULT_PHONE_PORT = "5566"; - public final static String DEFAULT_WEAR_PORT = "5576"; - - private static final String GETTING_START_TUT_URL = - "http://android.processing.org/tutorials/getting_started/index.html"; - - static final String DEVICE_DEFINITION = "pixel_6"; - static final String DEVICE_SKIN = "pixel_6"; - - static final String DEVICE_WEAR_DEFINITION = "wearos_square"; - static final String DEVICE_WEAR_SKIN = "wearos_square"; - - /** Name of this avd. */ - protected String name; - - protected String device; - protected String skin; - protected int type; - - static ArrayList avdList; - static ArrayList badList; - - /** "system-images;android-25;google_apis;x86" */ - static ArrayList wearImages; - static ArrayList phoneImages; - - private static Process process; - - /** Default virtual device used by Processing. */ - static public final AVD phoneAVD = - new AVD("processing-phone", - DEVICE_DEFINITION, DEVICE_SKIN, PHONE); - - /** Default virtual wear device used by Processing. */ - static public final AVD watchAVD = - new AVD("processing-watch", - DEVICE_WEAR_DEFINITION, DEVICE_WEAR_SKIN, WEAR); - - - public AVD(final String name, final String device, final String skin, int type) { - this.name = name; - this.device = device; - this.skin = skin; - this.type = type; - } - - - static public String getName(boolean wear) { - if (wear) { - return AVD.watchAVD.name; - } else { - return AVD.phoneAVD.name; - } - } - - - static public String getPreferredPlatform(boolean wear, String abi) { - if (wear) { - return AndroidBuild.TARGET_PLATFORM; - } else if (abi.equals("arm")) { - // The ARM images using Google APIs are too slow, so use the - // older Android (AOSP) images. - // TODO check if we can move to the regular ARM images... - return "android-" + TARGET_SDK_ARM; - } else if (abi.equals("arm64-v8a")) { - return AndroidBuild.TARGET_PLATFORM; - } else { - return AndroidBuild.TARGET_PLATFORM; - } - } - - static public String getPreferredPort(boolean wear) { - String port = ""; - if (wear) { - port = Preferences.get("android.emulator.port.wear"); - if (port == null) { - port = DEFAULT_WEAR_PORT; - Preferences.set("android.emulator.port.wear", port); - } - } else { - port = Preferences.get("android.emulator.port.phone"); - if (port == null) { - port = DEFAULT_PHONE_PORT; - Preferences.set("android.emulator.port.phone", port); - } - } - return port; - } - - - static protected String getPreferredTag(boolean wear, String abi) { - if (wear) { - return "android-wear"; -// } else if (abi.contains("arm")) { -// // The ARM images are located in the default folder. No, apparently ARM images are in google_apis too -// return "default"; - } else { - return "google_apis"; - } - } - - - static protected String getPreferredABI() { - String abi = Preferences.get("android.emulator.image.abi"); - if (abi == null) { - abi = DEFAULT_ABI; - Preferences.set("android.emulator.image.abi", abi); - } - return abi; - } - - - static protected void list(final AndroidSDK sdk) throws IOException { - String prefABI = getPreferredABI(); - - try { - avdList = new ArrayList(); - badList = new ArrayList(); - File avdManager = sdk.getAVDManagerTool(); - ProcessBuilder pb = new ProcessBuilder(avdManager.getCanonicalPath(), "list", "avd"); - Map env = pb.environment(); - env.clear(); - env.put("JAVA_HOME", Platform.getJavaHome().getCanonicalPath()); - pb.redirectErrorStream(true); - - process = pb.start(); - - StringWriter outWriter = new StringWriter(); - new StreamPump(process.getInputStream(), "out: ").addTarget(outWriter).start(); - process.waitFor(); - - String[] lines = PApplet.split(outWriter.toString(), '\n'); - - if (process.exitValue() == 0) { - String name = ""; - String abi = ""; - boolean badness = false; - for (String line : lines) { - String[] m = PApplet.match(line, "\\s+Name\\:\\s+(\\S+)"); - String[] t = PApplet.match(line, "\\s+Tag/ABI\\:\\s+(\\S+)"); - - if (m != null) { - name = m[1]; - } - if (t != null) { - abi = t[1]; - if (-1 < abi.indexOf("/" + prefABI)) { - if (!badness) { -// System.out.println("good: " + m[1]); - avdList.add(name); - } else { -// System.out.println("bad: " + m[1]); - badList.add(name); - } -// } else { -// System.out.println("nope: " + line); - } - } - - - // "The following Android Virtual Devices could not be loaded:" - if (line.contains("could not be loaded:")) { -// System.out.println("starting the bad list"); -// System.err.println("Could not list AVDs:"); -// System.err.println(listResult); - badness = true; -// break; - } - } - } else { - System.err.println("Unhappy inside exists()"); - System.err.println(outWriter.toString()); - } - } catch (final InterruptedException ie) { } - finally { - process.destroy(); - } - } - - - protected boolean exists(final AndroidSDK sdk) throws IOException { - if (avdList == null) { - list(sdk); - } - for (String avd : avdList) { - if (Base.DEBUG) { - System.out.println("AVD.exists() checking for " + name + " against " + avd); - } - if (avd.equals(name)) { - return true; - } - } - return false; - } - - - /** - * Return true if a member of the renowned and prestigious - * "The following Android Virtual Devices could not be loaded:" club. - * (Prestigious may also not be the right word.) - */ - protected boolean badness() { - for (String avd : badList) { - if (avd.equals(name)) { - return true; - } - } - return false; - } - - - protected boolean hasImages(final AndroidSDK sdk) throws IOException { - String abi = getPreferredABI(); - if (type == PHONE) { - if (phoneImages == null) { - phoneImages = new ArrayList(); - getImages(phoneImages, sdk, abi); - } - return !phoneImages.isEmpty(); - } else { - if (wearImages == null) { - wearImages = new ArrayList(); - getImages(wearImages, sdk, abi); - } - return !wearImages.isEmpty(); - } - } - - - protected void refreshImages(final AndroidSDK sdk) throws IOException { - String abi = getPreferredABI(); - - if (type == PHONE) { - phoneImages = new ArrayList(); - getImages(phoneImages, sdk, abi); - } else { - wearImages = new ArrayList(); - getImages(wearImages, sdk, abi); - } - } - - - protected void getImages(final ArrayList images, final AndroidSDK sdk, - final String imageAbi) throws IOException { - final boolean wear = type == WEAR; - final String imagePlatform = getPreferredPlatform(wear, imageAbi); - final String imageTag = getPreferredTag(wear, imageAbi); - - final File avdManager = sdk.getAVDManagerTool(); - final String[] cmd = new String[] { - avdManager.getCanonicalPath(), - "create", "avd", - "-n", "dummy", - "-k", "dummy" - }; - - // Dummy avdmanager creation command to get the list of installed images, - // so far this is the only method available get that list. - ProcessBuilder pb = new ProcessBuilder(cmd); - - if (Base.DEBUG) { - System.out.println(processing.core.PApplet.join(cmd, " ")); - } - - Map env = pb.environment(); - env.clear(); - env.put("JAVA_HOME", Platform.getJavaHome().getCanonicalPath()); - pb.redirectErrorStream(true); - - try { - process = pb.start(); - StringWriter outWriter = new StringWriter(); - new StreamPump(process.getInputStream(), "out: ").addTarget(outWriter).start(); - process.waitFor(); - - String[] lines = PApplet.split(outWriter.toString(), '\n'); - for (String line : lines) { - if (images != null && - line.contains(";" + imagePlatform) && - line.contains(";" + imageTag) && - line.contains(";" + imageAbi)) { -// System.out.println(" added image!"); - images.add(line); - } - } - - } catch (final InterruptedException ie) { - ie.printStackTrace(); - } finally { - process.destroy(); - } - } - - - protected String getSdkId() throws IOException { - String abi = getPreferredABI(); - - if (type == PHONE) { - for (String image : phoneImages) { - if (image.contains(";" + abi)) return image; - } - } else { - for (String image : wearImages) { - if (image.contains(";" + abi)) return image; - } - } - - // Could not find any suitable package - return "null"; - } - - protected void copyDeviceSkins(final AndroidSDK sdk, final AndroidMode mode) { - File skinsFolder = new File(sdk.getFolder(), "skins"); - if (!skinsFolder.exists()) { - // The skins in this folder come from Android Studio, on Mac they are in the folder: - // /Applications/Android Studio.app/Contents/plugins/android/resources/device-art-resources - // Apparently the skins are not available as a SDK download. - File artFolder = new File(mode.getResourcesFolder(), "device-art-resources"); - AndroidUtil.copyDir(artFolder, skinsFolder); - } - } - - protected boolean create(final AndroidSDK sdk) throws IOException { - File sketchbookFolder = processing.app.Base.getSketchbookFolder(); - File androidFolder = new File(sketchbookFolder, "android"); - if (!androidFolder.exists()) androidFolder.mkdir(); - File avdPath = new File(androidFolder, "avd/" + name); - - File avdManager = sdk.getAVDManagerTool(); - final String[] cmd = new String[] { - avdManager.getCanonicalPath(), - "create", "avd", - "-n", name, - "-k", getSdkId(), - "-p", avdPath.getAbsolutePath(), - "-d", device, - "--skin", skin, - "--force" - }; - - ProcessBuilder pb = new ProcessBuilder(cmd); - - if (Base.DEBUG) { - System.out.println(processing.core.PApplet.join(cmd, " ")); - } - - // avdmanager create avd -n "Wear-Processing-0254" -k "system-images;android-25;google_apis;x86" -c 64M - // Set the list to null so that exists() will check again -// avdList = null; - - Map env = pb.environment(); - env.clear(); - env.put("JAVA_HOME", Platform.getJavaHome().getCanonicalPath()); - pb.redirectErrorStream(true); - - try { - process = pb.start(); - - // Passes 'no' to "Do you wish to create a custom hardware profile [no]" -// OutputStream os = process.getOutputStream(); -// PrintWriter pw = new PrintWriter(new OutputStreamWriter(os)); -// pw.println("no"); -// pw.flush(); -// pw.close(); -// os.flush(); -// os.close(); - - StringWriter outWriter = new StringWriter(); - new StreamPump(process.getInputStream(), "out: ").addTarget(outWriter).start(); - - process.waitFor(); - - if (process.exitValue() == 0) { - // Add skin to AVD's config file -// File configFile = new File(avdPath, "config.ini"); -// if (configFile.exists()) { -// try (PrintWriter output = new PrintWriter(new FileWriter(configFile.getAbsolutePath(), true))) { -// output.printf("%s\r\n", "skin.name=" + skin); -// } -// catch (Exception e) {} -// } - return true; - } - - if (outWriter.toString().contains("Package path is not valid")) { - // They didn't install the Google APIs - AndroidUtil.showMessage(AndroidMode.getTextString("android_avd.error.sdk_wrong_install_title"), - AndroidMode.getTextString("android_avd.error.sdk_wrong_install_body", GETTING_START_TUT_URL)); - } else { - // Just generally not working - AndroidUtil.showMessage(AndroidMode.getTextString("android_avd.error.cannot_create_avd_title"), - AndroidMode.getTextString("android_avd.error.cannot_create_avd_body", AndroidBuild.TARGET_SDK)); - } - System.err.println(outWriter.toString()); - } catch (final InterruptedException ie) { - ie.printStackTrace(); - } finally { - process.destroy(); - } - - return false; - } - - - static public boolean ensureProperAVD(final Frame window, final AndroidMode mode, - final AndroidSDK sdk, boolean wear) { - try { - AVD avd = wear ? watchAVD : phoneAVD; - if (avd.exists(sdk)) { - return true; - } - if (avd.badness()) { - AndroidUtil.showMessage(AndroidMode.getTextString("android_avd.error.cannot_load_avd_title"), - AndroidMode.getTextString("android_avd.error.cannot_load_avd_body")); - return false; - } - if (!avd.hasImages(sdk)) { - // Check that the AVD for the other kind of device has been already - // downloaded, and if so, the downloader should not ask for an - // ABI again. - AVD other = wear ? phoneAVD : watchAVD; - boolean ask = !other.hasImages(sdk); - boolean res = AndroidSDK.requestSysImage(window, mode, wear, ask); - if (!res) { - return false; - } else { - avd.refreshImages(sdk); - } - } - avd.copyDeviceSkins(sdk, mode); - if (avd.create(sdk)) { - return true; - } - } catch (final Exception e) { - e.printStackTrace(); - AndroidUtil.showMessage(AndroidMode.getTextString("android_avd.error.cannot_create_avd_title"), - AndroidMode.getTextString("android_avd.error.cannot_create_avd_body", AndroidBuild.TARGET_SDK)); - } - return false; - } -} diff --git a/mode/src/processing/mode/android/AndroidBuild.java b/mode/src/processing/mode/android/AndroidBuild.java deleted file mode 100644 index f1ae72ecf..000000000 --- a/mode/src/processing/mode/android/AndroidBuild.java +++ /dev/null @@ -1,1115 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2009-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import org.gradle.tooling.*; - -import processing.app.Base; -import processing.app.Library; -import processing.app.Messages; -import processing.app.Platform; -import processing.app.Preferences; -import processing.app.Sketch; -import processing.app.SketchException; -import processing.app.Util; -import processing.core.PApplet; -import processing.mode.java.JavaBuild; -import processing.mode.java.preproc.PdePreprocessor; - -import java.io.*; -import java.util.HashMap; -import java.util.Properties; - -import java.util.*; -import processing.app.SketchCode; -import processing.mode.java.preproc.PreprocessorResult; - - -/** - * Class with all the infrastructure needed to build a sketch in the Android - * mode and run it either on the device or in the emulator, using Gradle as the - * build system. It also exports the sketch as a Gradle project file to build - * from the command line or import into Android Studio, and a signed and aligned - * package ready to upload to the Play Store. - */ -class AndroidBuild extends JavaBuild { - static public final int APP = 0; - static public final int WALLPAPER = 1; - static public final int WATCHFACE = 2; - static public final int VR = 3; - static public final int AR = 4; - - // Minimum SDK's API levels required for each component: - static public String MIN_SDK_APP; - static public String MIN_SDK_WALLPAPER; - static public String MIN_SDK_VR; - static public String MIN_SDK_AR; - static public String MIN_SDK_WATCHFACE; - - // Versions of all required dependencies - static public String TARGET_SDK; - static public String TARGET_PLATFORM; - static public String GRADLE_PLUGIN_VER; - static public String APPCOMPAT_VER; - static public String V4LEGACY_VER; - static public String PLAY_SERVICES_VER; - static public String WEAR_VER; - static public String GVR_VER; - static public String GAR_VER; - - // Main activity or service - static private final String APP_ACTIVITY_TEMPLATE = "AppActivity.java.tmpl"; - static private final String WALLPAPER_SERVICE_TEMPLATE = "WallpaperService.java.tmpl"; - static private final String WATCHFACE_SERVICE_TEMPLATE = "WatchFaceService.java.tmpl"; - static private final String VR_ACTIVITY_TEMPLATE = "VRActivity.java.tmpl"; - static private final String AR_ACTIVITY_TEMPLATE = "ARActivity.java.tmpl"; - - // Additional resources - static private final String LAYOUT_ACTIVITY_TEMPLATE = "LayoutActivity.xml.tmpl"; - static private final String STYLES_FRAGMENT_TEMPLATE = "StylesFragment.xml.tmpl"; - static private final String STYLES_VR_TEMPLATE = "StylesVR.xml.tmpl"; - static private final String STYLES_AR_TEMPLATE = "StylesAR.xml.tmpl"; - static private final String XML_WALLPAPER_TEMPLATE = "XMLWallpaper.xml.tmpl"; - static private final String STRINGS_WALLPAPER_TEMPLATE = "StringsWallpaper.xml.tmpl"; - static private final String XML_WATCHFACE_TEMPLATE = "XMLWatchFace.xml.tmpl"; - - // Gradle build files - static private final String GRADLE_SETTINGS_TEMPLATE = "Settings.gradle.tmpl"; - static private final String GRADLE_PROPERTIES_TEMPLATE = "Properties.gradle.tmpl"; - static private final String EXPORTED_GRADLE_PROPERTIES_TEMPLATE = "ExpProperties.gradle.tmpl"; - static private final String LOCAL_PROPERTIES_TEMPLATE = "Properties.local.tmpl"; - static private final String TOP_GRADLE_BUILD_TEMPLATE = "TopBuild.gradle.tmpl"; - static private final String APP_GRADLE_BUILD_ECJ_TEMPLATE = "AppBuildECJ.gradle.tmpl"; - static private final String APP_GRADLE_BUILD_TEMPLATE = "AppBuild.gradle.tmpl"; - static private final String VR_GRADLE_BUILD_ECJ_TEMPLATE = "VRBuildECJ.gradle.tmpl"; - static private final String VR_GRADLE_BUILD_TEMPLATE = "VRBuild.gradle.tmpl"; - static private final String AR_GRADLE_BUILD_ECJ_TEMPLATE = "ARBuildECJ.gradle.tmpl"; - static private final String AR_GRADLE_BUILD_TEMPLATE = "ARBuild.gradle.tmpl"; - static private final String WEAR_GRADLE_BUILD_ECJ_TEMPLATE = "WearBuildECJ.gradle.tmpl"; - static private final String WEAR_GRADLE_BUILD_TEMPLATE = "WearBuild.gradle.tmpl"; - - // Launcher and watch face icon files - static final String[] SKETCH_LAUNCHER_ICONS = {"launcher_36.png", "launcher_48.png", - "launcher_72.png", "launcher_96.png", - "launcher_144.png", "launcher_192.png"}; - static final String[] SKETCH_OLD_LAUNCHER_ICONS = {"icon-36.png", "icon-48.png", - "icon-72.png", "icon-96.png", - "icon-144.png", "icon-192.png"}; - static final String[] BUILD_LAUNCHER_ICONS = {"mipmap-ldpi/ic_launcher.png", "mipmap-mdpi/ic_launcher.png", - "mipmap-hdpi/ic_launcher.png", "mipmap-xhdpi/ic_launcher.png", - "mipmap-xxhdpi/ic_launcher.png", "mipmap-xxxhdpi/ic_launcher.png"}; - static final String[] SKETCH_WATCHFACE_ICONS = {"preview_circular.png", - "preview_rectangular.png"}; - static final String[] BUILD_WATCHFACE_ICONS = {"drawable-nodpi/preview_circular.png", - "drawable-nodpi/preview_rectangular.png"}; - - private int appComponent = APP; - - private final AndroidSDK sdk; - private final File coreZipFile; - - /** whether this is a "debug" or "release" build */ - private String target; - - /** The manifest for the sketch being built */ - private Manifest manifest; - - /** temporary folder safely inside a 8.3-friendly folder */ - private File tmpFolder; - - /** Determines which gradle build template will be used */ - private boolean exportProject = false; - - /** Renderer used by the sketch */ - private String renderer = ""; - - /** Name of the Gradle module in the project, either app or wear */ - private String module = ""; - - /** - * Constructor. - * @param sketch the sketch to be built - * @param mode reference to the mode - * @param appComp component (regular handheld app, wallpaper, watch face, VR, AR) - * @param emu build to run in emulator or on device if false - */ - public AndroidBuild(Sketch sketch, AndroidMode mode, int comp) { - super(sketch); - appComponent = comp; - sdk = mode.getSDK(); - coreZipFile = mode.getCoreZipLocation(); - module = appComponent == WATCHFACE ? "wear" : "app"; - } - - - public String getPackageName() { - return manifest.getPackageName(); - } - - - public int getAppComponent() { - return appComponent; - } - - - public boolean isWear() { - return appComponent == WATCHFACE; - } - - - public void cleanup() { - tmpFolder.deleteOnExit(); - } - - - public boolean usesOpenGL() { - return renderer != null && (renderer.equals("P2D") || renderer.equals("P3D")); - } - - - public String getPathForAPK() { - String suffix = target.equals("release") ? "release" : "debug"; - String apkName = getPathToAPK() + sketch.getName().toLowerCase() + "_" + suffix + ".apk"; - final File apkFile = new File(tmpFolder, apkName); - if (!apkFile.exists()) { - return null; - } - return apkFile.getAbsolutePath(); - } - - /** - * Build into temporary folders for building bundles (needed for the Windows 8.3 bugs in the Android SDK) - * @param target "debug" or "release" - * @throws SketchException - * @throws IOException - */ - public File buildBundle(String target, String password) throws IOException, SketchException { - this.target = target; - File folder = createProject(true, password); - if (folder == null) return null; - if (!gradleBuildBundle()) return null; - return folder; - } - - - /** - * Build into temporary folders (needed for the Windows 8.3 bugs in the Android SDK). - * @param target "debug" or "release" - * @throws SketchException - * @throws IOException - */ - public File build(String target, String password) throws IOException, SketchException { - this.target = target; - File folder = createProject(true, password); - if (folder == null) return null; - if (!gradleBuildPackage()) return null; - return folder; - } - - - /** - * Create an Gradle Android project folder, and run the preprocessor on the - * sketch. Creates the top and app modules in the case of regular, VR, AR and - * wallpapers, and top, mobile and wear modules in the case of watch faces. - */ - protected File createProject(boolean external, String password) - throws IOException, SketchException { - tmpFolder = createTempBuildFolder(sketch); - System.out.println(AndroidMode.getTextString("android_build.error.build_folder", tmpFolder.getAbsolutePath())); - - // Create the 'src' folder with the preprocessed code. - srcFolder = new File(tmpFolder, module + "/src/main/java"); - binFolder = srcFolder; // Needed in the the parent JavaBuild class - if (processing.app.Base.DEBUG) { - Platform.openFolder(tmpFolder); - } - - manifest = new Manifest(sketch, appComponent, mode.getFolder(), false); - - // build the preproc and get to work - String pckgName = getPackageName(); - PdePreprocessor preprocessor = PdePreprocessor.builderFor(sketch.getName()).setDestinationPackage(pckgName).build(); - PreprocessorResult result = preprocess(srcFolder, pckgName, preprocessor, false); - if (result != null) { - sketchClassName = result.getClassName(); - if (sketchClassName != null) { - renderer = result.getSketchRenderer(); - if (renderer == null) { - renderer = "JAVA2D"; - } - writeMainClass(srcFolder, external); - createTopModule("':" + module + "'", password); - createAppModule(module); - } - } - - return tmpFolder; - } - - - protected boolean gradleBuildBundle() throws SketchException { - ProjectConnection connection = GradleConnector.newConnector() - .forProjectDirectory(tmpFolder) - .connect(); - - boolean success = false; - BuildLauncher build = connection.newBuild(); - build.setStandardOutput(System.out); - build.setStandardError(System.err); - - try { - if (target.equals("debug")) build.forTasks("bundleDebug"); - else build.forTasks("bundleRelease"); - build.run(); - renameAAB(); - success = true; - } catch (org.gradle.tooling.UnsupportedVersionException e) { - e.printStackTrace(); - success = false; - } catch (org.gradle.tooling.BuildException e) { - e.printStackTrace(); - success = false; - } catch (org.gradle.tooling.BuildCancelledException e) { - e.printStackTrace(); - success = false; - } catch (org.gradle.tooling.GradleConnectionException e) { - e.printStackTrace(); - success = false; - } catch (Exception e) { - e.printStackTrace(); - success = false; - } finally { - connection.close(); - } - - try { - removeKeyPassword(); - } catch (IOException e) { - e.printStackTrace(); - } - - return success; - } - - - protected boolean gradleBuildPackage() throws SketchException { - ProjectConnection connection = GradleConnector.newConnector() - .forProjectDirectory(tmpFolder) - .connect(); - - boolean success = false; - BuildLauncher build = connection.newBuild(); - build.setStandardOutput(System.out); - build.setStandardError(System.err); - - try { - if (target.equals("debug")) build.forTasks("assembleDebug"); - else build.forTasks("assembleRelease"); - build.run(); - renameAPK(); - success = true; - } catch (org.gradle.tooling.UnsupportedVersionException e) { - e.printStackTrace(); - success = false; - } catch (org.gradle.tooling.BuildException e) { - e.printStackTrace(); - success = false; - } catch (org.gradle.tooling.BuildCancelledException e) { - e.printStackTrace(); - success = false; - } catch (org.gradle.tooling.GradleConnectionException e) { - e.printStackTrace(); - success = false; - } catch (Exception e) { - e.printStackTrace(); - success = false; - } finally { - connection.close(); - } - - try { - removeKeyPassword(); - } catch (IOException e) { - e.printStackTrace(); - } - - return success; - } - - - // --------------------------------------------------------------------------- - // Gradle modules - - - private void createTopModule(String projectModules, String keyPassword) - throws IOException { - HashMap replaceMap = new HashMap(); - - File buildTemplate = mode.getContentFile("templates/" + TOP_GRADLE_BUILD_TEMPLATE); - File buildlFile = new File(tmpFolder, "build.gradle"); - replaceMap.put("@@gradle_plugin_version@@", GRADLE_PLUGIN_VER); - AndroidUtil.createFileFromTemplate(buildTemplate, buildlFile, replaceMap); - -// File gradlePropsTemplate = mode.getContentFile("templates/" + GRADLE_PROPERTIES_TEMPLATE); -// File gradlePropsFile = new File(tmpFolder, "gradle.properties"); -// Util.copyFile(gradlePropsTemplate, gradlePropsFile); - File gradlePropsTemplate; - if (exportProject) { - gradlePropsTemplate = mode.getContentFile("templates/" + EXPORTED_GRADLE_PROPERTIES_TEMPLATE); - } else { - gradlePropsTemplate = mode.getContentFile("templates/" + GRADLE_PROPERTIES_TEMPLATE); - } - File gradlePropsFile = new File(tmpFolder, "gradle.properties"); - String javaHome = Platform.getJavaHome().getAbsolutePath(); - replaceMap.clear(); - replaceMap.put("@@java_home@@", javaHome); - if (!keyPassword.equals("") && AndroidKeyStore.getKeyStore() != null) { - replaceMap.put("@@keystore_file@@", AndroidKeyStore.getKeyStore().getAbsolutePath().replace('\\', '/')); - replaceMap.put("@@key_alias@@", AndroidKeyStore.ALIAS_STRING); - replaceMap.put("@@key_password@@", keyPassword); - } - AndroidUtil.createFileFromTemplate(gradlePropsTemplate, gradlePropsFile, replaceMap); - - File settingsTemplate = mode.getContentFile("templates/" + GRADLE_SETTINGS_TEMPLATE); - File settingsFile = new File(tmpFolder, "settings.gradle"); - replaceMap.clear(); - replaceMap.put("@@project_modules@@", projectModules); - AndroidUtil.createFileFromTemplate(settingsTemplate, settingsFile, replaceMap); - - File localPropsTemplate = mode.getContentFile("templates/" + LOCAL_PROPERTIES_TEMPLATE); - File localPropsFile = new File(tmpFolder, "local.properties"); - replaceMap.clear(); - final String sdkPath = sdk.getFolder().getAbsolutePath(); - if (Platform.isWindows()) { - // Windows needs backslashes escaped, or it will also accept forward - // slashes in the build file. We're using the forward slashes since this - // path gets concatenated with a lot of others that use forwards anyway. - replaceMap.put("@@sdk_path@@", sdkPath.replace('\\', '/')); - } else { - replaceMap.put("@@sdk_path@@", sdkPath); - } - AndroidUtil.createFileFromTemplate(localPropsTemplate, localPropsFile, replaceMap); - } - - - private void createAppModule(String moduleName) - throws SketchException, IOException { - File moduleFolder = AndroidUtil.createPath(tmpFolder, moduleName); - - String minSdk; - String tmplFile; - if (appComponent == AR) { - minSdk = MIN_SDK_AR; - tmplFile = exportProject ? AR_GRADLE_BUILD_TEMPLATE : AR_GRADLE_BUILD_ECJ_TEMPLATE; - } else if (appComponent == VR) { - minSdk = MIN_SDK_VR; - tmplFile = exportProject ? VR_GRADLE_BUILD_TEMPLATE : VR_GRADLE_BUILD_ECJ_TEMPLATE; - } else if (appComponent == WATCHFACE) { - minSdk = MIN_SDK_WATCHFACE; - tmplFile = exportProject ? WEAR_GRADLE_BUILD_TEMPLATE : WEAR_GRADLE_BUILD_ECJ_TEMPLATE; - } else { - minSdk = MIN_SDK_APP; - tmplFile = exportProject ? APP_GRADLE_BUILD_TEMPLATE : APP_GRADLE_BUILD_ECJ_TEMPLATE; - } - - String modePath = new File(mode.getFolder(), "mode").getPath().replace('\\', '/'); - String toolPath = Base.getToolsFolder().getPath().replace('\\', '/'); - String platformPath = sdk.getTargetPlatform(TARGET_SDK).getPath().replace('\\', '/'); - - File appBuildTemplate = mode.getContentFile("templates/" + tmplFile); - File appBuildFile = new File(moduleFolder, "build.gradle"); - HashMap replaceMap = new HashMap(); - replaceMap.put("@@mode_folder@@", modePath); - replaceMap.put("@@tools_folder@@", toolPath); - replaceMap.put("@@target_platform@@", platformPath); - replaceMap.put("@@package_name@@", getPackageName()); - replaceMap.put("@@min_sdk@@", minSdk); - replaceMap.put("@@target_sdk@@", TARGET_SDK); - replaceMap.put("@@appcompat_version@@", APPCOMPAT_VER); - replaceMap.put("@@v4legacy_version@@", V4LEGACY_VER); - replaceMap.put("@@play_services_version@@", PLAY_SERVICES_VER); - replaceMap.put("@@wear_version@@", WEAR_VER); - replaceMap.put("@@gvr_version@@", GVR_VER); - replaceMap.put("@@gar_version@@", GAR_VER); - replaceMap.put("@@version_code@@", manifest.getVersionCode()); - replaceMap.put("@@version_name@@", manifest.getVersionName()); - AndroidUtil.createFileFromTemplate(appBuildTemplate, appBuildFile, replaceMap); - - AndroidUtil.writeFile(new File(moduleFolder, "proguard-rules.pro"), - new String[]{"# Add project specific ProGuard rules here."}); - - File libsFolder = AndroidUtil.createPath(moduleFolder, "libs"); - File mainFolder = new File(moduleFolder, "src/main"); - File resFolder = AndroidUtil.createPath(mainFolder, "res"); - File assetsFolder = AndroidUtil.createPath(mainFolder, "assets"); - - writeRes(resFolder); - - File tempManifest = new File(mainFolder, "AndroidManifest.xml"); - manifest.writeCopy(tempManifest, sketchClassName); - - Util.copyFile(coreZipFile, new File(libsFolder, "processing-core.jar")); - - // Copy any imported libraries (their libs and assets), - // and anything in the code folder contents to the project. - copyImportedLibs(libsFolder, mainFolder, assetsFolder); - copyCodeFolder(libsFolder); - - // Copy any system libraries needed by the project -// copyWearLib(libsFolder); -// copySupportLibs(libsFolder); -// if (getAppComponent() == APP) { -// copyAppCompatLib(libsFolder); -// } -// if (getAppComponent() == VR) { -// copyGVRLibs(libsFolder); -// } - - // Copy the data folder (if one exists) to the project's 'assets' folder - final File sketchDataFolder = sketch.getDataFolder(); - if (sketchDataFolder.exists()) { - Util.copyDir(sketchDataFolder, assetsFolder); - } - - // Do the same for the 'res' folder. The user can copy an entire res folder - // into the sketch's folder, and it will be used in the project! - final File sketchResFolder = new File(sketch.getFolder(), "res"); - if (sketchResFolder.exists()) { - Util.copyDir(sketchResFolder, resFolder); - } - } - - - // --------------------------------------------------------------------------- - // Templates - - - private void writeMainClass(final File srcDirectory, final boolean external) { - int comp = getAppComponent(); - String[] permissions = manifest.getPermissions(); - if (comp == APP) { - writeFragmentActivity(srcDirectory, permissions, external); - } else if (comp == WALLPAPER) { - writeWallpaperService(srcDirectory, permissions, external); - } else if (comp == WATCHFACE) { - if (usesOpenGL()) { - writeWatchFaceGLESService(srcDirectory, permissions, external); - } else { - writeWatchFaceCanvasService(srcDirectory, permissions, external); - } - } else if (comp == VR) { - writeVRActivity(srcDirectory, permissions, external); - } else if (comp == AR) { - writeARActivity(srcDirectory, permissions, external); - } - } - - - private void writeFragmentActivity(final File srcDirectory, - final String[] permissions, final boolean external) { - File javaTemplate = mode.getContentFile("templates/" + APP_ACTIVITY_TEMPLATE); - File javaFile = new File(new File(srcDirectory, getPackageName().replace(".", "/")), "MainActivity.java"); - - HashMap replaceMap = new HashMap(); - replaceMap.put("@@package_name@@", getPackageName()); - replaceMap.put("@@sketch_class_name@@", sketchClassName); - replaceMap.put("@@external@@", external ? "sketch.setExternal(true);" : ""); - - AndroidUtil.createFileFromTemplate(javaTemplate, javaFile, replaceMap); - } - - - private void writeWallpaperService(final File srcDirectory, - String[] permissions, final boolean external) { - File javaTemplate = mode.getContentFile("templates/" + WALLPAPER_SERVICE_TEMPLATE); - File javaFile = new File(new File(srcDirectory, getPackageName().replace(".", "/")), "MainService.java"); - - HashMap replaceMap = new HashMap(); - replaceMap.put("@@package_name@@", getPackageName()); - replaceMap.put("@@sketch_class_name@@", sketchClassName); - replaceMap.put("@@external@@", external ? "sketch.setExternal(true);" : ""); - - AndroidUtil.createFileFromTemplate(javaTemplate, javaFile, replaceMap); - } - - - private void writeWatchFaceGLESService(final File srcDirectory, - String[] permissions, final boolean external) { - File javaTemplate = mode.getContentFile("templates/" + WATCHFACE_SERVICE_TEMPLATE); - File javaFile = new File(new File(srcDirectory, getPackageName().replace(".", "/")), "MainService.java"); - - HashMap replaceMap = new HashMap(); - replaceMap.put("@@watchface_classs@@", "PWatchFaceGLES"); - replaceMap.put("@@package_name@@", getPackageName()); - replaceMap.put("@@sketch_class_name@@", sketchClassName); - replaceMap.put("@@external@@", external ? "sketch.setExternal(true);" : ""); - - AndroidUtil.createFileFromTemplate(javaTemplate, javaFile, replaceMap); - } - - - private void writeWatchFaceCanvasService(final File srcDirectory, - String[] permissions, final boolean external) { - File javaTemplate = mode.getContentFile("templates/" + WATCHFACE_SERVICE_TEMPLATE); - File javaFile = new File(new File(srcDirectory, getPackageName().replace(".", "/")), "MainService.java"); - - HashMap replaceMap = new HashMap(); - replaceMap.put("@@watchface_classs@@", "PWatchFaceCanvas"); - replaceMap.put("@@package_name@@", getPackageName()); - replaceMap.put("@@sketch_class_name@@", sketchClassName); - replaceMap.put("@@external@@", external ? "sketch.setExternal(true);" : ""); - - AndroidUtil.createFileFromTemplate(javaTemplate, javaFile, replaceMap); - } - - - private void writeVRActivity(final File srcDirectory, String[] permissions, - final boolean external) { - File javaTemplate = mode.getContentFile("templates/" + VR_ACTIVITY_TEMPLATE); - File javaFile = new File(new File(srcDirectory, getPackageName().replace(".", "/")), "MainActivity.java"); - - HashMap replaceMap = new HashMap(); - replaceMap.put("@@package_name@@", getPackageName()); - replaceMap.put("@@sketch_class_name@@", sketchClassName); - replaceMap.put("@@external@@", external ? "sketch.setExternal(true);" : ""); - - AndroidUtil.createFileFromTemplate(javaTemplate, javaFile, replaceMap); - } - - private void writeARActivity(final File srcDirectory, String[] permissions, - final boolean external) { - File javaTemplate = mode.getContentFile("templates/" + AR_ACTIVITY_TEMPLATE); - File javaFile = new File(new File(srcDirectory, getPackageName().replace(".", "/")), "MainActivity.java"); - - HashMap replaceMap = new HashMap(); - replaceMap.put("@@package_name@@", getPackageName()); - replaceMap.put("@@sketch_class_name@@", sketchClassName); - replaceMap.put("@@external@@", external ? "sketch.setExternal(true);" : ""); - - AndroidUtil.createFileFromTemplate(javaTemplate, javaFile, replaceMap); - } - - - private void writeResLayoutMainActivity(final File layoutFolder) { - File xmlTemplate = mode.getContentFile("templates/" + LAYOUT_ACTIVITY_TEMPLATE); - File xmlFile = new File(layoutFolder, "main.xml"); - - HashMap replaceMap = new HashMap(); - replaceMap.put("@@sketch_class_name@@",sketchClassName); - - AndroidUtil.createFileFromTemplate(xmlTemplate, xmlFile, replaceMap); - } - - - private void writeResStylesFragment(final File valuesFolder) { - File xmlTemplate = mode.getContentFile("templates/" + STYLES_FRAGMENT_TEMPLATE); - File xmlFile = new File(valuesFolder, "styles.xml"); - AndroidUtil.createFileFromTemplate(xmlTemplate, xmlFile); - } - - - private void writeResStylesVR(final File valuesFolder) { - File xmlTemplate = mode.getContentFile("templates/" + STYLES_VR_TEMPLATE); - File xmlFile = new File(valuesFolder, "styles.xml"); - AndroidUtil.createFileFromTemplate(xmlTemplate, xmlFile); - } - - - private void writeResStylesAR(final File valuesFolder) { - File xmlTemplate = mode.getContentFile("templates/" + STYLES_AR_TEMPLATE); - File xmlFile = new File(valuesFolder, "styles.xml"); - AndroidUtil.createFileFromTemplate(xmlTemplate, xmlFile); - } - - - private void writeResXMLWallpaper(final File xmlFolder) { - File xmlTemplate = mode.getContentFile("templates/" + XML_WALLPAPER_TEMPLATE); - File xmlFile = new File(xmlFolder, "wallpaper.xml"); - AndroidUtil.createFileFromTemplate(xmlTemplate, xmlFile); - } - - - private void writeResStringsWallpaper(final File valuesFolder) { - File xmlTemplate = mode.getContentFile("templates/" + STRINGS_WALLPAPER_TEMPLATE); - File xmlFile = new File(valuesFolder, "strings.xml"); - - HashMap replaceMap = new HashMap(); - replaceMap.put("@@sketch_class_name@@",sketchClassName); - - AndroidUtil.createFileFromTemplate(xmlTemplate, xmlFile, replaceMap); - } - - - private void writeResXMLWatchFace(final File xmlFolder) { - File xmlTemplate = mode.getContentFile("templates/" + XML_WATCHFACE_TEMPLATE); - File xmlFile = new File(xmlFolder, "watch_face.xml"); - AndroidUtil.createFileFromTemplate(xmlTemplate, xmlFile); - } - - - private void writeRes(File resFolder) throws SketchException { - File layoutFolder = AndroidUtil.createPath(resFolder, "layout"); - writeResLayoutMainActivity(layoutFolder); - - int comp = getAppComponent(); - if (comp == APP) { - File valuesFolder = AndroidUtil.createPath(resFolder, "values"); - writeResStylesFragment(valuesFolder); - } else if (comp == WALLPAPER) { - File xmlFolder = AndroidUtil.createPath(resFolder, "xml"); - writeResXMLWallpaper(xmlFolder); - File valuesFolder = AndroidUtil.createPath(resFolder, "values"); - writeResStringsWallpaper(valuesFolder); - } else if (comp == WATCHFACE) { - File xmlFolder = AndroidUtil.createPath(resFolder, "xml"); - writeResXMLWatchFace(xmlFolder); - } else if (comp == VR) { - File valuesFolder = AndroidUtil.createPath(resFolder, "values"); - writeResStylesVR(valuesFolder); - } else if (comp == AR) { - File valuesFolder = AndroidUtil.createPath(resFolder, "values"); - writeResStylesAR(valuesFolder); - } - - File sketchFolder = sketch.getFolder(); - writeLauncherIconFiles(sketchFolder, resFolder); - if (comp == WATCHFACE) { - // Need the preview icons for watch faces. - writeWatchFaceIconFiles(sketchFolder, resFolder); - } - } - - - // --------------------------------------------------------------------------- - // Icons - - - private void writeLauncherIconFiles(File sketchFolder, File resFolder) { - writeIconFiles(sketchFolder, resFolder, SKETCH_LAUNCHER_ICONS, SKETCH_OLD_LAUNCHER_ICONS, BUILD_LAUNCHER_ICONS); - } - - - private void writeWatchFaceIconFiles(File sketchFolder, File resFolder) { - writeIconFiles(sketchFolder, resFolder, SKETCH_WATCHFACE_ICONS, null, BUILD_WATCHFACE_ICONS); - } - - - private void writeIconFiles(File sketchFolder, File resFolder, - String[] sketchIconNames, String[] oldIconNames, String[] buildIconNames) { - File[] localIcons = AndroidUtil.getFileList(sketchFolder, sketchIconNames, oldIconNames); - File[] buildIcons = AndroidUtil.getFileList(resFolder, buildIconNames); - if (AndroidUtil.noFileExists(localIcons)) { - // If no icons are in the sketch folder, then copy all the defaults - File[] defaultIcons = AndroidUtil.getFileList(mode, "icons/", sketchIconNames); - try { - for (int i = 0; i < localIcons.length; i++) { - copyIcon(defaultIcons[i], buildIcons[i]); - } - } catch (IOException e) { - e.printStackTrace(); - } - } else { - // If at least one of the icons already exists, then use that across the board - try { - for (int i = 0; i < localIcons.length; i++) { - if (localIcons[i].exists()) copyIcon(localIcons[i], buildIcons[i]); - } - } catch (IOException e) { - System.err.println(AndroidMode.getTextString("android_build.error.cannot_copy_icons")); - e.printStackTrace(); - } - } - } - - - private void copyIcon(File srcFile, File destFile) throws IOException { - File parent = destFile.getParentFile(); - if (parent.exists() || parent.mkdirs()) { - Util.copyFile(srcFile, destFile); - } else { - System.err.println(AndroidMode.getTextString("android_build.error.cannot_create_icon_folder", destFile.getParentFile())); - } - } - - - // --------------------------------------------------------------------------- - // Export project - - - public File exportProject() throws IOException, SketchException { - target = "debug"; - - exportProject = true; - File projectFolder = createProject(false, ""); - exportProject = false; - - File exportFolder = createExportFolder("android"); - Util.copyDir(projectFolder, exportFolder); - installGradlew(exportFolder); - return exportFolder; - } - - - // --------------------------------------------------------------------------- - // Export bundle - - - public File exportBundle(String keyStorePassword) throws Exception { - File projectFolder = buildBundle("release", keyStorePassword); - if (projectFolder == null) return null; - - // Final export folder - File exportFolder = createExportFolder("buildBundle"); - Util.copyDir(new File(projectFolder, getPathToAAB()), exportFolder); - return exportFolder; - } - - - // --------------------------------------------------------------------------- - // Export package - - - public File exportPackage(String keyStorePassword) throws Exception { - File projectFolder = build("release", keyStorePassword); - if (projectFolder == null) return null; - - // Final export folder - File exportFolder = createExportFolder("buildPackage"); - Util.copyDir(new File(projectFolder, getPathToAPK()), exportFolder); - return exportFolder; - } - - - //--------------------------------------------------------------------------- - // Build utils - - - /** - * Tell the PDE to not complain about android.* packages and others that are - * part of the OS library set as if they're missing. - */ - protected boolean ignorableImport(String pkg) { - if (pkg.startsWith("android.")) return true; - if (pkg.startsWith("java.")) return true; - if (pkg.startsWith("javax.")) return true; - if (pkg.startsWith("org.apache.http.")) return true; - if (pkg.startsWith("org.json.")) return true; - if (pkg.startsWith("org.w3c.dom.")) return true; - if (pkg.startsWith("org.xml.sax.")) return true; - - if (pkg.startsWith("processing.core.")) return true; - if (pkg.startsWith("processing.data.")) return true; - if (pkg.startsWith("processing.event.")) return true; - if (pkg.startsWith("processing.opengl.")) return true; - - return false; - } - - - /** - * For each library, copy .jar and .zip files to the 'libs' folder, - * and copy anything else to the 'assets' folder. - */ - private void copyImportedLibs(final File libsFolder, - final File mainFolder, - final File assetsFolder) throws IOException { - for (Library library : getImportedLibraries()) { - // Add each item from the library folder / export list to the output - for (File exportFile : library.getApplicationExports("armeabi")) { - copyImportedLib(libsFolder, mainFolder, assetsFolder, exportFile); - } - for (File exportFile : library.getApplicationExports("armeabi-v7a")) { - copyImportedLib(libsFolder, mainFolder, assetsFolder, exportFile); - } - for (File exportFile : library.getApplicationExports("x86")) { - copyImportedLib(libsFolder, mainFolder, assetsFolder, exportFile); - } - for (File exportFile : library.getApplicationExports("arm64-v8a")) { - copyImportedLib(libsFolder, mainFolder, assetsFolder, exportFile); - } - for (File exportFile : library.getApplicationExports("x86_64")) { - copyImportedLib(libsFolder, mainFolder, assetsFolder, exportFile); - } - } - } - - - private void copyImportedLib(final File libsFolder, - final File mainFolder, - final File assetsFolder, - final File exportFile) throws IOException { - String exportName = exportFile.getName(); - - // Skip the GVR and ARCore jars, because gradle will resolve the dependencies - if (appComponent == VR && exportName.toLowerCase().startsWith("sdk")) return; - if (appComponent == AR && exportName.toLowerCase().startsWith("core")) return; - - if (!exportFile.exists()) { - System.err.println(AndroidMode.getTextString("android_build.error.export_file_does_not_exist", exportFile.getName())); - } else if (exportFile.isDirectory()) { - // Copy native library folders to the correct location - if (exportName.equals("armeabi") || - exportName.equals("armeabi-v7a") || - exportName.equals("x86") || - exportName.equals("arm64-v8a") || - exportName.equals("x86_64")) - { - Util.copyDir(exportFile, new File(libsFolder, exportName)); - } - // Copy jni libraries (.so files) to the correct location - else if (exportName.equals("jniLibs")) { - Util.copyDir(exportFile, new File(mainFolder, exportName)); - } - else { - // Copy any other directory to the assets folder - Util.copyDir(exportFile, new File(assetsFolder, exportName)); - } - } else if (exportName.toLowerCase().endsWith(".zip")) { - // As of r4 of the Android SDK, it looks like .zip files - // are ignored in the libs folder, so rename to .jar - System.err.println(AndroidMode.getTextString("android_build.error.zip_files_not_allowed", exportFile.getName())); - String jarName = exportName.substring(0, exportName.length() - 4) + ".jar"; - Util.copyFile(exportFile, new File(libsFolder, jarName)); - - } else if (exportName.toLowerCase().endsWith(".jar")) { - Util.copyFile(exportFile, new File(libsFolder, exportName)); - - } else { - Util.copyFile(exportFile, new File(assetsFolder, exportName)); - } - } - - - private void copyCodeFolder(final File libsFolder) throws IOException { - // Copy files from the 'code' directory into the 'libs' folder - final File codeFolder = sketch.getCodeFolder(); - if (codeFolder != null && codeFolder.exists()) { - for (final File item : codeFolder.listFiles()) { - if (!item.isDirectory()) { - final String name = item.getName(); - final String lcname = name.toLowerCase(); - if (lcname.endsWith(".jar") || lcname.endsWith(".zip")) { - String jarName = name.substring(0, name.length() - 4) + ".jar"; - Util.copyFile(item, new File(libsFolder, jarName)); - } - } - } - } - } - - private void renameAAB() { - String suffix = target.equals("release") ? "release" : "debug"; - String aabName = getPathToAAB() + module + "-" + suffix + ".aab"; - final File aabFile = new File(tmpFolder, aabName); - if (aabFile.exists()) { - String suffixNew = target.equals("release") ? "release" : "debug"; - String aabNameNew = getPathToAAB() + - sketch.getName().toLowerCase() + "_" + suffixNew + ".aab"; - final File aabFileNew = new File(tmpFolder, aabNameNew); - aabFile.renameTo(aabFileNew); - } - } - - private String getPathToAAB() { - return module + "/build/outputs/bundle/" + target + "/"; - } - - - private void renameAPK() { - String suffix = target.equals("release") ? "release" : "debug"; - String apkName = getPathToAPK() + module + "-" + suffix + ".apk"; - final File apkFile = new File(tmpFolder, apkName); - if (apkFile.exists()) { - String suffixNew = target.equals("release") ? "release" : "debug"; - String apkNameNew = getPathToAPK() + - sketch.getName().toLowerCase() + "_" + suffixNew + ".apk"; - final File apkFileNew = new File(tmpFolder, apkNameNew); - apkFile.renameTo(apkFileNew); - } - } - - - private void removeKeyPassword() throws IOException { - File gradlePropsTemplate = mode.getContentFile("templates/" + GRADLE_PROPERTIES_TEMPLATE); - File gradlePropsFile = new File(tmpFolder, "gradle.properties"); - Util.copyFile(gradlePropsTemplate, gradlePropsFile); - } - - - private String getPathToAPK() { - return module + "/build/outputs/apk/" + target + "/"; - } - - - /** - * The Android dex util pukes on paths containing spaces, which will happen - * most of the time on Windows, since Processing sketches wind up in - * "My Documents". Therefore, build android in a temp file. - * http://code.google.com/p/android/issues/detail?id=4567 - * - * @param sketch - * @return A folder in which to build the android sketch - * @throws IOException - */ - private File createTempBuildFolder(final Sketch sketch) throws IOException { - final File tmp = File.createTempFile("android", "sketch"); - if (!(tmp.delete() && tmp.mkdir())) { - throw new IOException(AndroidMode.getTextString("android_build.error.cannot_create_build_folder", tmp)); - } - return tmp; - } - - - private void installGradlew(File exportFolder) throws IOException { - File gradlewFile = mode.getContentFile("mode/gradlew.zip"); - AndroidUtil.extractFolder(gradlewFile, exportFolder, false, true); - if (Platform.isMacOS() || Platform.isLinux()) { - File execFile = new File(exportFolder, "gradlew"); - execFile.setExecutable(true); - } - } - - - private File createExportFolder(String name) throws IOException { - return AndroidUtil.createSubFolder(sketch.getFolder(), name); - } - - - static public void initVersions(File file) { - InputStream input; - try { - input = new FileInputStream(file); - Properties props = new Properties(); - props.load(input); - - MIN_SDK_APP = props.getProperty("android-min-app"); - MIN_SDK_WALLPAPER = props.getProperty("android-min-wallpaper"); - MIN_SDK_VR = props.getProperty("android-min-vr"); - MIN_SDK_AR = props.getProperty("android-min-ar"); - MIN_SDK_WATCHFACE = props.getProperty("android-min-wear"); - - // Versions strings of all dependencies are stored in a preferences file so they can be changed by the - // user without having to rebuild/reinstall the mode. - - GRADLE_PLUGIN_VER = Preferences.get("android.gradle_plugin"); - String defGradlePluginVersion = props.getProperty("android-gradle-plugin"); - if (GRADLE_PLUGIN_VER == null || PApplet.parseInt(GRADLE_PLUGIN_VER) != PApplet.parseInt(defGradlePluginVersion)) { - GRADLE_PLUGIN_VER = defGradlePluginVersion; - Preferences.set("android.gradle_plugin", GRADLE_PLUGIN_VER); - } - - TARGET_SDK = Preferences.get("android.sdk.target"); - String defTargetSDK = props.getProperty("android-platform"); - if (TARGET_SDK == null || PApplet.parseInt(TARGET_SDK) != PApplet.parseInt(defTargetSDK)) { - TARGET_SDK = defTargetSDK; - Preferences.set("android.sdk.target", TARGET_SDK); - } - TARGET_PLATFORM = "android-" + TARGET_SDK; - - APPCOMPAT_VER = Preferences.get("android.sdk.appcompat"); - String defAppCompatVer = props.getProperty("androidx.appcompat%appcompat"); - if (APPCOMPAT_VER == null || !versionCheck(APPCOMPAT_VER, defAppCompatVer)) { - APPCOMPAT_VER = defAppCompatVer; - Preferences.set("android.sdk.appcompat", APPCOMPAT_VER); - } - - V4LEGACY_VER = Preferences.get("android.sdk.v4legacy"); - String defV4LegacyVer = props.getProperty("androidx.legacy%legacy-support-v4"); - if (V4LEGACY_VER == null || !versionCheck(V4LEGACY_VER, defV4LegacyVer)) { - V4LEGACY_VER = defV4LegacyVer; - Preferences.set("android.sdk.v4legacy", V4LEGACY_VER); - } - - PLAY_SERVICES_VER = Preferences.get("android.sdk.play_services"); - String defPlayServicesVer = props.getProperty("com.google.android.gms%play-services-wearable"); - if (PLAY_SERVICES_VER == null || !versionCheck(PLAY_SERVICES_VER, defPlayServicesVer)) { - PLAY_SERVICES_VER = defPlayServicesVer; - Preferences.set("android.sdk.play_services", PLAY_SERVICES_VER); - } - - WEAR_VER = Preferences.get("android.sdk.wear"); - String defWearVer = props.getProperty("com.google.android.support%wearable"); - if (WEAR_VER == null || !versionCheck(WEAR_VER, defWearVer)) { - WEAR_VER = defWearVer; - Preferences.set("android.sdk.wear", WEAR_VER); - } - - GVR_VER = Preferences.get("android.sdk.gvr"); - String defVRVer = props.getProperty("com.google.vr"); - if (GVR_VER == null || !versionCheck(GVR_VER, defVRVer)) { - GVR_VER = defVRVer; - Preferences.set("android.sdk.gvr", GVR_VER); - } - - GAR_VER = Preferences.get("android.sdk.ar"); - String defARVer = props.getProperty("com.google.ar"); - if (GAR_VER == null || !versionCheck(GAR_VER, defARVer)) { - GAR_VER = defARVer; - Preferences.set("android.sdk.ar", GAR_VER); - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - - static private boolean versionCheck(String currentVersion, String minVersion) { - String[] currentPieces = currentVersion.split("\\."); - String[] minPieces = minVersion.split("\\."); - - if (currentPieces.length == 3 && minPieces.length == 3) { - int currentMajor = PApplet.parseInt(currentPieces[0], -1); - int currentMinor = PApplet.parseInt(currentPieces[1], -1); - int currentMicro = PApplet.parseInt(currentPieces[2], -1); - - int minMajor = PApplet.parseInt(minPieces[0], -1); - int minMinor = PApplet.parseInt(minPieces[1], -1); - int minMicro = PApplet.parseInt(minPieces[2], -1); - - if (-1 < currentMajor && -1 < currentMinor && -1 < currentMicro && - -1 < minMajor && -1 < minMinor && -1 < minMicro) { - if (currentMajor < minMajor) { - return false; - } else if (currentMajor == minMajor) { - if (currentMinor < minMinor) { - return false; - } if (currentMinor == minMinor) { - if (currentMicro < minMicro) { - return false; - } else { - return true; - } - } else { - return true; - } - } else { - return true; - } - } - } - - return false; - } -} diff --git a/mode/src/processing/mode/android/AndroidDebugger.java b/mode/src/processing/mode/android/AndroidDebugger.java deleted file mode 100644 index f68766cca..000000000 --- a/mode/src/processing/mode/android/AndroidDebugger.java +++ /dev/null @@ -1,411 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2018-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; -import com.sun.jdi.event.Event; -import com.sun.jdi.request.ClassPrepareRequest; -import com.sun.jdi.request.EventRequestManager; -import com.sun.jdi.request.StepRequest; -import processing.app.Language; -import processing.app.Messages; -import processing.mode.java.debug.*; - -import javax.swing.*; -import java.awt.*; -import java.io.IOException; - -// Developed by Manav Jain as part of GSoC 2018 -public class AndroidDebugger extends Debugger { - /// editor window, acting as main view - protected AndroidEditor editor; - protected AndroidRunner runtime; - protected AndroidMode androidMode; - - protected boolean isEnabled; - - - private String pkgName = ""; - private String sketchClassName = ""; - - public AndroidDebugger(AndroidEditor editor, AndroidMode androidMode) { - super(editor); - this.editor = editor; - this.androidMode = androidMode; - } - - public boolean isEnabled() { - return isEnabled; - } - - public void toggleDebug() { - isEnabled = !isEnabled; - inspector.setVisible(enabled); - if (isEnabled) { - debugItem.setText(Language.text("menu.debug.disable")); - } else { - debugItem.setText(Language.text("menu.debug.enable")); - } - - for (Component item : debugMenu.getMenuComponents()) { - if (item instanceof JMenuItem && item != debugItem) { - item.setEnabled(isEnabled); - } - } - - } - - @Override - public AndroidEditor getEditor() { - return editor; - } - - public synchronized void startDebug(AndroidRunner runner, Device device) { - //stopDebug(); // stop any running sessions - if (isStarted()) { - return; // do nothing - } - - inspector.reset(); - - // make the inspector instance visible on which tree nodes would be reflected - inspector.setVisible(true); - - runtime = runner; - pkgName = runner.build.getPackageName(); - sketchClassName = runner.build.getSketchClassName(); - - mainClassName = pkgName + "." + sketchClassName; - - try { - int port = 8000 + (int) (Math.random() * 1000); - device.forwardPort(port); - - // connect - System.out.println(AndroidMode.getTextString("android_debugger.info.attaching_debugger")); - VirtualMachine vm = runner.connectVirtualMachine(port); - System.out.println(AndroidMode.getTextString("android_debugger.info.debugger_attached")); - - // start receiving vm events - VMEventReader eventThread = new VMEventReader(vm.eventQueue(), vmEventListener); - eventThread.start(); - - // watch for loaded classes - addClassWatch(vm); - - // resume the vm - vm.resume(); - - } catch (IOException e) { - Messages.log(AndroidMode.getTextString("android_debugger.error.debugger_exception", e.getMessage())); - // Retry - startDebug(runner, device); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - @Override public synchronized void vmEvent(EventSet es) { - VirtualMachine vm = vm(); - if (vm != null && vm != es.virtualMachine()) { - // This is no longer VM we are interested in, - // we already cleaned up and run different VM now. - return; - } - for (Event e : es) { - // System.out.println("VM Event: " + e); - if (e instanceof VMStartEvent) { -// System.out.println("start"); - - } else if (e instanceof ClassPrepareEvent) { - vmClassPrepareEvent((ClassPrepareEvent) e); - - } else if (e instanceof BreakpointEvent) { - vmBreakPointEvent((BreakpointEvent) e); - - } else if (e instanceof StepEvent) { - vmStepEvent(((StepEvent) e)); - - } else if (e instanceof VMDisconnectEvent) { - stopDebug(); - - } else if (e instanceof VMDeathEvent) { - started = false; - editor.statusEmpty(); - } - } - } - - private void vmClassPrepareEvent(ClassPrepareEvent ce) { - ReferenceType rt = ce.referenceType(); - currentThread = ce.thread(); - paused = true; // for now we're paused - - if (rt.name().equals(mainClassName)) { - //printType(rt); - mainClass = rt; - classes.add(rt); -// log("main class load: " + rt.name()); - started = true; // now that main class is loaded, we're started - } else { - classes.add(rt); // save loaded classes -// log("class load: {0}" + rt.name()); - } - - // notify listeners - for (ClassLoadListener listener : classLoadListeners) { - if (listener != null) { - listener.classLoaded(rt); - } - } - paused = false; // resuming now - runtime.vm().resume(); - } - - private void vmBreakPointEvent(BreakpointEvent be) { - currentThread = be.thread(); // save this thread - updateVariableInspector(currentThread); // this is already on the EDT - final LineID newCurrentLine = locationToLineID(be.location()); - javax.swing.SwingUtilities.invokeLater(new Runnable() { - @Override public void run() { - editor.setCurrentLine(newCurrentLine); - editor.deactivateStep(); - editor.deactivateContinue(); - } - }); - - // hit a breakpoint during a step, need to cancel the step. - if (requestedStep != null) { - runtime.vm().eventRequestManager().deleteEventRequest(requestedStep); - requestedStep = null; - } - - // fix canvas update issue - // TODO: is this a good solution? - resumeOtherThreads(currentThread); - - paused = true; - editor.statusHalted(); - } - - private void vmStepEvent(StepEvent se) { - currentThread = se.thread(); - - //printSourceLocation(currentThread); - updateVariableInspector(currentThread); // this is already on the EDT - final LineID newCurrentLine = locationToLineID(se.location()); - javax.swing.SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - editor.setCurrentLine(newCurrentLine); - editor.deactivateStep(); - editor.deactivateContinue(); - } - }); - - // delete the steprequest that triggered this step so new ones can be placed (only one per thread) - EventRequestManager mgr = runtime.vm().eventRequestManager(); - mgr.deleteEventRequest(se.request()); - requestedStep = null; // mark that there is no step request pending - paused = true; - editor.statusHalted(); - - // disallow stepping into invisible lines - if (!locationIsVisible(se.location())) { - // TODO: this leads to stepping, should it run on the EDT? - javax.swing.SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - stepOutIntoViewOrContinue(); - } - }); - } - } - - - @Override public synchronized void continueDebug() { - editor.activateContinue(); - inspector.lock(); - //editor.clearSelection(); - //clearHighlight(); - editor.clearCurrentLine(); - if (!isStarted()) { - startDebug(); - } else if (isPaused()) { - runtime.vm().resume(); - paused = false; - editor.statusBusy(); - } - } - - - - @Override protected void step(int stepDepth) { - if (!isStarted()) { - startDebug(); - } else if (isPaused()) { - inspector.lock(); - editor.activateStep(); - - // use global to mark that there is a step request pending - requestedStep = runtime.vm().eventRequestManager().createStepRequest(currentThread, StepRequest.STEP_LINE, stepDepth); - requestedStep.addCountFilter(1); // valid for one step only - requestedStep.enable(); - paused = false; - runtime.vm().resume(); - editor.statusBusy(); - } - } - - - - @Override public synchronized void stopDebug() { - inspector.lock(); - if (runtime != null) { - - for (LineBreakpoint bp : breakpoints) { - bp.detach(); - } - - runtime.close(); - runtime = null; - //build = null; - classes.clear(); - // need to clear highlight here because, VMDisconnectedEvent seems to be unreliable. TODO: likely synchronization problem - editor.clearCurrentLine(); - } - stopTrackingLineChanges(); - started = false; - - // editor.deactivateDebug(); - editor.deactivateContinue(); - editor.deactivateStep(); - - editor.statusEmpty(); - } - - - /** - * Watch all classes ({@value sketchClassName}) variable - */ - private void addClassWatch(VirtualMachine vm) { - EventRequestManager erm = vm.eventRequestManager(); - ClassPrepareRequest classPrepareRequest = erm.createClassPrepareRequest(); - classPrepareRequest.addClassFilter(mainClassName); - classPrepareRequest.setEnabled(true); - } - - @Override - public VirtualMachine vm() { - if (runtime != null) { - return runtime.vm(); - } - return null; - } - - @Override public synchronized boolean isStarted() { - return started && runtime != null && runtime.vm() != null; - } - - /** - * Get the breakpoint on a certain line, if set. - * - * @param line the line to get the breakpoint from - * @return the breakpoint, or null if no breakpoint is set on the specified - * line. - */ - LineBreakpoint breakpointOnLine(LineID line) { - for (LineBreakpoint bp : breakpoints) { - if (bp.isOnLine(line)) { - return bp; - } - } - return null; - } - - synchronized public void toggleBreakpoint(int lineIdx) { - LineID line = editor.getLineIDInCurrentTab(lineIdx); - int index = line.lineIdx(); - if (hasBreakpoint(line)) { - removeBreakpoint(index); - } else { - // Make sure the line contains actual code before setting the break - // https://github.com/processing/processing/issues/3765 - if (editor.getLineText(index).trim().length() != 0) { - setBreakpoint(index); - } - } - } - - /** - * Set a breakpoint on a line in the current tab. - * - * @param lineIdx the line index (0-based) of the current tab to set the - * breakpoint on - */ - synchronized void setBreakpoint(int lineIdx) { - setBreakpoint(editor.getLineIDInCurrentTab(lineIdx)); - } - - synchronized public void setBreakpoint(LineID line) { - // do nothing if we are kinda busy - if (isStarted() && !isPaused()) { - return; - } - // do nothing if there already is a breakpoint on this line - if (hasBreakpoint(line)) { - return; - } - breakpoints.add(new AndroidLineBreakpoint(line, this)); - } - - /** - * Remove a breakpoint from the current line (if set). - */ - synchronized void removeBreakpoint() { - removeBreakpoint(editor.getCurrentLineID().lineIdx()); - } - - /** - * Remove a breakpoint from a line in the current tab. - * - * @param lineIdx the line index (0-based) in the current tab to remove the - * breakpoint from - */ - void removeBreakpoint(int lineIdx) { - // do nothing if we are kinda busy - if (isBusy()) { - return; - } - - LineBreakpoint bp = breakpointOnLine(editor.getLineIDInCurrentTab(lineIdx)); - if (bp != null) { - bp.remove(); - breakpoints.remove(bp); - } - } - - public String getPackageName() { - return pkgName; - } -} diff --git a/mode/src/processing/mode/android/AndroidEditor.java b/mode/src/processing/mode/android/AndroidEditor.java deleted file mode 100644 index c7c7e5dd4..000000000 --- a/mode/src/processing/mode/android/AndroidEditor.java +++ /dev/null @@ -1,828 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2009-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import processing.app.Base; -import processing.app.Mode; -import processing.app.Language; -import processing.app.Platform; -import processing.app.Settings; -import processing.app.SketchException; -import processing.app.tools.Tool; -import processing.app.ui.EditorException; -import processing.app.ui.EditorState; -import processing.app.ui.EditorToolbar; -import processing.app.ui.Toolkit; -import processing.mode.java.JavaEditor; -import processing.mode.java.debug.Debugger; -import processing.mode.java.debug.LineID; -import processing.mode.java.preproc.PdePreprocessor; - -import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.MenuEvent; -import javax.swing.event.MenuListener; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.TimerTask; - - -@SuppressWarnings("serial") -public class AndroidEditor extends JavaEditor { - // Component selected by default - static public final String DEFAULT_COMPONENT = "app"; - - private JMenu androidMenu; - - private int appComponent; - - protected JMenu debugMenu; - private AndroidDebugger debugger; - - private Settings settings; - private AndroidMode androidMode; - - private List androidTools; - - private JCheckBoxMenuItem fragmentItem; - private JCheckBoxMenuItem wallpaperItem; - private JCheckBoxMenuItem watchfaceItem; - private JCheckBoxMenuItem vrItem; - private JCheckBoxMenuItem arItem; - - protected AndroidEditor(Base base, String path, EditorState state, - Mode mode) throws EditorException { - super(base, path, state, mode); - - androidMode = (AndroidMode) mode; - androidMode.resetUserSelection(); - androidMode.checkSDK(this); - - - androidTools = loadAndroidTools(); - addToolsToMenu(); - - loadModeSettings(); - } - -// @Override -// public PdePreprocessor createPreprocessor(final String sketchName) { -// return new AndroidPreprocessor(sketchName); -// } - - - public EditorToolbar createToolbar() { - return new AndroidToolbar(this, base); - } - - - /* - // Not for now, it is unclear if the package name should be reset after save - // as, i.e.: sketch_1 -> sketch_2 ... - @Override - public boolean handleSaveAs() { - boolean saved = super.handleSaveAs(); - if (saved) { - // Reset the manifest so package name and versions are blank - androidMode.resetManifest(sketch, appComponent); - } - return saved; - } - */ - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public JMenu buildFileMenu() { - String exportPackageTitle = AndroidToolbar.getTitle(AndroidToolbar.EXPORT_PACKAGE); - JMenuItem exportPackage = Toolkit.newJMenuItemShift(exportPackageTitle,'T'); - exportPackage.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleExportPackage(); - } - }); - - - String exportBundleTitle = AndroidToolbar.getTitle(AndroidToolbar.EXPORT_BUNDLE); - JMenuItem exportBundle = Toolkit.newJMenuItem(exportBundleTitle, 'B'); - exportBundle.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleExportBundle(); - } - }); - - - String exportProjectTitle = AndroidToolbar.getTitle(AndroidToolbar.EXPORT_PROJECT); - JMenuItem exportProject = Toolkit.newJMenuItemShift(exportProjectTitle, 'X'); - exportProject.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleExportProject(); - } - }); - - return buildFileMenu(new JMenuItem[] {exportPackage, exportBundle, exportProject}); - } - - - public JMenu buildSketchMenu() { - JMenuItem runItem = Toolkit.newJMenuItem(AndroidToolbar.getTitle(AndroidToolbar.RUN_ON_DEVICE), 'D'); - runItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleRunDevice(); - } - }); - - JMenuItem presentItem = Toolkit.newJMenuItemShift(AndroidToolbar.getTitle(AndroidToolbar.RUN_IN_EMULATOR), 'E'); - presentItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleRunEmulator(); - } - }); - - JMenuItem stopItem = new JMenuItem(AndroidToolbar.getTitle(AndroidToolbar.STOP)); - stopItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleStop(); - } - }); - return buildSketchMenu(new JMenuItem[] { buildDebugMenu(), runItem, presentItem, stopItem }); -// return buildSketchMenu(new JMenuItem[] { runItem, presentItem, stopItem }); - } - - - public JMenu buildModeMenu() { - super.buildModeMenu(); - - androidMenu = new JMenu(AndroidMode.getTextString("menu.android")); - JMenuItem item; - - item = new JMenuItem(AndroidMode.getTextString("menu.android.sketch_permissions")); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - new Permissions(sketch, appComponent, androidMode.getFolder()); - } - }); - androidMenu.add(item); - - androidMenu.addSeparator(); - - fragmentItem = new JCheckBoxMenuItem(AndroidMode.getTextString("menu.android.app")); - wallpaperItem = new JCheckBoxMenuItem(AndroidMode.getTextString("menu.android.wallpaper")); - watchfaceItem = new JCheckBoxMenuItem(AndroidMode.getTextString("menu.android.watch_face")); - vrItem = new JCheckBoxMenuItem(AndroidMode.getTextString("menu.android.vr")); - arItem = new JCheckBoxMenuItem(AndroidMode.getTextString("menu.android.ar")); - - fragmentItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - fragmentItem.setState(true); - wallpaperItem.setState(false); - watchfaceItem.setSelected(false); - vrItem.setSelected(false); - arItem.setSelected(false); - setAppComponent(AndroidBuild.APP); - } - }); - wallpaperItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - fragmentItem.setState(false); - wallpaperItem.setState(true); - watchfaceItem.setSelected(false); - vrItem.setSelected(false); - arItem.setSelected(false); - setAppComponent(AndroidBuild.WALLPAPER); - } - }); - watchfaceItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - fragmentItem.setState(false); - wallpaperItem.setState(false); - watchfaceItem.setSelected(true); - vrItem.setSelected(false); - arItem.setSelected(false); - setAppComponent(AndroidBuild.WATCHFACE); - } - }); - vrItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - fragmentItem.setState(false); - wallpaperItem.setState(false); - watchfaceItem.setSelected(false); - vrItem.setSelected(true); - arItem.setSelected(false); - setAppComponent(AndroidBuild.VR); - } - }); - arItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - fragmentItem.setState(false); - wallpaperItem.setState(false); - watchfaceItem.setSelected(false); - vrItem.setSelected(false); - arItem.setSelected(true); - setAppComponent(AndroidBuild.AR); - } - }); - - fragmentItem.setState(false); - wallpaperItem.setState(false); - watchfaceItem.setSelected(false); - vrItem.setSelected(false); - arItem.setSelected(false); - - androidMenu.add(fragmentItem); - androidMenu.add(wallpaperItem); - androidMenu.add(watchfaceItem); - androidMenu.add(vrItem); - androidMenu.add(arItem); - - androidMenu.addSeparator(); - - final JMenu devicesMenu = new JMenu(AndroidMode.getTextString("menu.android.devices")); - - JMenuItem noDevicesItem = new JMenuItem(AndroidMode.getTextString("menu.android.devices.no_connected_devices")); - noDevicesItem.setEnabled(false); - devicesMenu.add(noDevicesItem); - androidMenu.add(devicesMenu); - - // Update the device list only when the Android menu is selected. - androidMenu.addMenuListener(new MenuListener() { - UpdateDeviceListTask task; - java.util.Timer timer; - - @Override - public void menuSelected(MenuEvent e) { - task = new UpdateDeviceListTask(devicesMenu); - timer = new java.util.Timer(); - timer.schedule(task, 400, 3000); - } - - @Override - public void menuDeselected(MenuEvent e) { - timer.cancel(); - } - - @Override - public void menuCanceled(MenuEvent e) { - timer.cancel(); - } - }); - - androidMenu.addSeparator(); - - return androidMenu; - } - - private JMenu buildDebugMenu() { - initDebugger(); - debugMenu = new JMenu(Language.text("menu.debug")); - debugger.populateMenu(debugMenu); - return debugMenu; - } - - - private void setAppComponent(int comp) { - if (appComponent != comp) { - appComponent = comp; - - if (appComponent == AndroidBuild.APP) { - settings.set("component", "app"); - } else if (appComponent == AndroidBuild.WALLPAPER) { - settings.set("component", "wallpaper"); - } else if (appComponent == AndroidBuild.WATCHFACE) { - settings.set("component", "watchface"); - } else if (appComponent == AndroidBuild.VR) { - settings.set("component", "vr"); - } else if (appComponent == AndroidBuild.AR) { - settings.set("component", "ar"); - } - settings.save(); - androidMode.resetManifest(sketch, appComponent); - androidMode.showSelectComponentMessage(comp); - } - } - - - /** - * Uses the main help menu, and adds a few extra options. If/when there's - * Android-specific documentation, we'll switch to that. - */ - public JMenu buildHelpMenu() { - JMenu menu = super.buildHelpMenu(); - JMenuItem item; - - menu.addSeparator(); - - item = new JMenuItem(AndroidMode.getTextString("menu.help.processing_for_android_site")); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Platform.openURL("http://android.processing.org/"); - } - }); - menu.add(item); - - - item = new JMenuItem(AndroidMode.getTextString("menu.help.android_developer_site")); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Platform.openURL("http://developer.android.com/"); - } - }); - menu.add(item); - - return menu; - } - - - /** override the standard grab reference to just show the java reference */ - public void showReference(String filename) { - File javaReferenceFolder = Platform.getContentFile("modes/java/reference"); - File file = new File(javaReferenceFolder, filename); - Platform.openURL(file.toURI().toString()); - } - - - public void statusError(String what) { - super.statusError(what); - toolbar.deactivateRun(); - } - - - public void sketchStopped() { - deactivateRun(); - statusEmpty(); - } - - - /** - * Build the sketch and run it inside an emulator with the debugger. - */ - public void handleRunEmulator() { - new Thread() { - public void run() { - toolbar.activateRun(); - startIndeterminate(); - prepareRun(); - try { - androidMode.handleRunEmulator(sketch, AndroidEditor.this, AndroidEditor.this); - } catch (SketchException e) { - statusError(e); - } catch (IOException e) { - statusError(e); - } - stopIndeterminate(); - } - }.start(); - } - - - /** - * Build the sketch and run it on a device with the debugger connected. - */ - public void handleRunDevice() { - new Thread() { - public void run() { - toolbar.activateRun(); - startIndeterminate(); - prepareRun(); - try { - androidMode.handleRunDevice(sketch, AndroidEditor.this, AndroidEditor.this); - } catch (SketchException e) { - statusError(e); - } catch (IOException e) { - statusError(e); - } - stopIndeterminate(); - } - }.start(); - } - - - public void handleStop() { - /* - if (debugger.isStarted()) { - debugger.stopDebug(); - - } else { - toolbar.activateStop(); - androidMode.handleStop(this); - toolbar.deactivateStop(); - toolbar.deactivateRun(); - - // focus the PDE again after quitting presentation mode [toxi 030903] - toFront(); - } - */ - toolbar.activateStop(); - androidMode.handleStop(this); - toolbar.deactivateStop(); - toolbar.deactivateRun(); - - // focus the PDE again after quitting presentation mode [toxi 030903] - toFront(); - } - - @Override - public AndroidDebugger getDebugger() { - return debugger; - } - - -// @Override protected void deactivateDebug() { -// super.deactivateDebug(); -// } - - @Override public void activateContinue() { - ((AndroidToolbar) toolbar).activateContinue(); - } - - @Override public void deactivateContinue() { - ((AndroidToolbar) toolbar).deactivateContinue(); - } - - @Override public void activateStep() { - ((AndroidToolbar) toolbar).activateStep(); - } - - @Override public void deactivateStep() { - ((AndroidToolbar) toolbar).deactivateStep(); - } - - - - @Override - public void toggleDebug() { - super.toggleDebug(); - // make the unused inspector invisible - super.debugger.dispose(); - debugger.toggleDebug(); - } - - @Override - public void toggleBreakpoint(int lineIndex) { - debugger.toggleBreakpoint(lineIndex); - } - - @Override - public LineID getCurrentLineID() { - return super.getCurrentLineID(); - } - - /** - * Create a release build of the sketch and have its apk files ready. - * If users want a debug build, they can do that from the command line. - */ - public void handleExportProject() { - if (handleExportCheckModified()) { - new Thread() { - public void run() { - ((AndroidToolbar) toolbar).activateExport(); - startIndeterminate(); - statusNotice(AndroidMode.getTextString("android_editor.status.exporting_project")); - AndroidBuild build = new AndroidBuild(sketch, androidMode, appComponent); - try { - File exportFolder = build.exportProject(); - if (exportFolder != null) { - Platform.openFolder(exportFolder); - statusNotice(AndroidMode.getTextString("android_editor.status.project_export_completed")); - } else { - statusError(AndroidMode.getTextString("android_editor.status.project_export_failed")); - } - } catch (IOException e) { - statusError(e); - } catch (SketchException e) { - statusError(e); - } - stopIndeterminate(); - ((AndroidToolbar)toolbar).deactivateExport(); - } - }.start(); - } - } - - /** - * Create a release package of the sketch - */ - public void handleExportPackage() { - if (androidMode.checkPackageName(sketch, appComponent) && - androidMode.checkAppIcons(sketch, appComponent) && handleExportCheckModified()) { - new KeyStoreManager(this, KeyStoreManager.PACKAGE); - } - } - - public void startExportPackage(final String keyStorePassword) { - new Thread() { - public void run() { - startIndeterminate(); - statusNotice(AndroidMode.getTextString("android_editor.status.exporting_package")); - AndroidBuild build = new AndroidBuild(sketch, androidMode, appComponent); - try { - File projectFolder = build.exportPackage(keyStorePassword); - if (projectFolder != null) { - statusNotice(AndroidMode.getTextString("android_editor.status.package_export_completed")); - Platform.openFolder(projectFolder); - } else { - statusError(AndroidMode.getTextString("android_editor.status.package_export_failed")); - } - } catch (IOException e) { - statusError(e); - } catch (SketchException e) { - statusError(e); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - stopIndeterminate(); - } - }.start(); - } - - - /** - * Create a release bundle of the sketch - */ - public void handleExportBundle() { - if (androidMode.checkPackageName(sketch, appComponent) && - androidMode.checkAppIcons(sketch, appComponent) && handleExportCheckModified()) { - new KeyStoreManager(this, KeyStoreManager.BUNDLE); - } - } - - public void startExportBundle(final String keyStorePassword) { - new Thread() { - public void run() { - startIndeterminate(); - statusNotice(AndroidMode.getTextString("android_editor.status.exporting_bundle")); - AndroidBuild build = new AndroidBuild(sketch, androidMode, appComponent); - try { - File projectFolder = build.exportBundle(keyStorePassword); - if (projectFolder != null) { - statusNotice(AndroidMode.getTextString("android_editor.status.bundle_export_completed")); - Platform.openFolder(projectFolder); - } else { - statusError(AndroidMode.getTextString("android_editor.status.bundle_export_failed")); - } - } catch (IOException e) { - statusError(e); - } catch (SketchException e) { - statusError(e); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - stopIndeterminate(); - } - }.start(); - } - - - public int getAppComponent() { - return appComponent; - } - - - private void loadModeSettings() { - File sketchProps = new File(sketch.getCodeFolder(), "sketch.properties"); - try { - settings = new Settings(sketchProps); - boolean save = false; - String component; - if (!sketchProps.exists()) { - component = DEFAULT_COMPONENT; - settings.set("component", component); - save = true; - } else { - component = settings.get("component"); - if (component == null) { - component = DEFAULT_COMPONENT; - settings.set("component", component); - save = true; - } - } - if (save) settings.save(); - - if (component.equals("app")) { - appComponent = AndroidBuild.APP; - fragmentItem.setState(true); - } else if (component.equals("wallpaper")) { - appComponent = AndroidBuild.WALLPAPER; - wallpaperItem.setState(true); - } else if (component.equals("watchface")) { - appComponent = AndroidBuild.WATCHFACE; - watchfaceItem.setState(true); - } else if (component.equals("vr")) { - appComponent = AndroidBuild.VR; - vrItem.setState(true); - } else if (component.equals("ar")) { - appComponent = AndroidBuild.AR; - arItem.setState(true); - } - - androidMode.initManifest(sketch, appComponent); - } catch (IOException e) { - System.err.println(AndroidMode.getTextString("android_editor.error.cannot_create_sketch_properties", sketchProps, e.getMessage())); - } - } - - private List loadAndroidTools() { - // This gets called before assigning mode to androidMode... - ArrayList outgoing = new ArrayList(); - - File folder = new File(androidMode.getFolder(), "tools"); - String[] list = folder.list(); - if (list == null) { - return outgoing; - } - - Arrays.sort(list, String.CASE_INSENSITIVE_ORDER); - for (String name : list) { - if (name.charAt(0) == '.') { - continue; - } - - File toolPath = new File(folder, name); - if (toolPath.isDirectory()) { - File jarPath = new File(toolPath, "tool" + File.separator + name + ".jar"); - if (jarPath.exists()) { - try { - AndroidTool tool = new AndroidTool(toolPath, androidMode); - tool.init(base); - outgoing.add(tool); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - } - - return outgoing; - } - - private void addToolsToMenu() { - JMenuItem item; - - for (final Tool tool : androidTools) { - item = new JMenuItem(AndroidMode.getTextString(tool.getMenuTitle())); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - tool.run(); - } - }); - androidMenu.add(item); - } - -// item = new JMenuItem("AVD Manager"); -// item.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// File file = androidMode.getSDK().getAndroidTool(); -// PApplet.exec(new String[] { file.getAbsolutePath(), "avd" }); -// } -// }); -// menu.add(item); - - item = new JMenuItem(AndroidMode.getTextString("menu.android.reset_adb")); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { -// editor.statusNotice("Resetting the Android Debug Bridge server."); - final Devices devices = Devices.getInstance(); - devices.killAdbServer(); - devices.startAdbServer(); - } - }); - androidMenu.add(item); - } - - private void initDebugger() { - debugger = new AndroidDebugger(this, androidMode); - // Set saved breakpoints when sketch is opened for the first time -// for (LineID lineID : stripBreakpointComments()) { -// debugger.setBreakpoint(lineID); -// } - super.debugger = debugger; - - } - - class UpdateDeviceListTask extends TimerTask { - - private JMenu deviceMenu; - - public UpdateDeviceListTask(JMenu deviceMenu) { - this.deviceMenu = deviceMenu; - } - - private Device selectFirstDevice(java.util.List deviceList) { - if (0 < deviceList.size()) return deviceList.get(0); - return null; - } - - @Override - public void run() { - if (androidMode == null || androidMode.getSDK() == null) return; - - final Devices devices = Devices.getInstance(); - - if (appComponent == AndroidBuild.WATCHFACE) { - devices.enableBluetoothDebugging(); - } - - java.util.List deviceList = devices.findMultiple(false); - Device selectedDevice = devices.getSelectedDevice(); - - if (deviceList.size() == 0) { - if (0 < deviceMenu.getItemCount()) { - deviceMenu.removeAll(); - JMenuItem noDevicesItem = new JMenuItem(AndroidMode.getTextString("menu.android.devices.no_connected_devices")); - noDevicesItem.setEnabled(false); - deviceMenu.add(noDevicesItem); - } - devices.setSelectedDevice(null); - } else { - deviceMenu.removeAll(); - - if (selectedDevice == null) { - selectedDevice = selectFirstDevice(deviceList); - devices.setSelectedDevice(selectedDevice); - } else { - // check if selected device is still connected - boolean found = false; - for (Device device : deviceList) { - if (device.equals(selectedDevice)) { - found = true; - break; - } - } - - if (!found) { - selectedDevice = selectFirstDevice(deviceList); - devices.setSelectedDevice(selectedDevice); - } - } - - for (final Device device : deviceList) { - final JCheckBoxMenuItem deviceItem = new JCheckBoxMenuItem(device.getName()); - deviceItem.setEnabled(true); - - if (device.equals(selectedDevice)) deviceItem.setState(true); - - // prevent checkboxmenuitem automatic state changing onclick - deviceItem.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - if (device.equals(devices.getSelectedDevice())) deviceItem.setState(true); - else deviceItem.setState(false); - } - }); - - deviceItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - devices.setSelectedDevice(device); - - for (int i = 0; i < deviceMenu.getItemCount(); i++) { - ((JCheckBoxMenuItem) deviceMenu.getItem(i)).setState(false); - } - - deviceItem.setState(true); - } - }); - - deviceMenu.add(deviceItem); - } - } - } - } -} diff --git a/mode/src/processing/mode/android/AndroidKeyStore.java b/mode/src/processing/mode/android/AndroidKeyStore.java deleted file mode 100644 index 711678f56..000000000 --- a/mode/src/processing/mode/android/AndroidKeyStore.java +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2014-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import processing.app.Messages; -import processing.app.exec.ProcessHelper; -import processing.app.exec.ProcessResult; -import processing.core.PApplet; -import java.io.File; - -/** - * Class handling the keystore where the users can store the credentials for - * their apps. - */ -public class AndroidKeyStore { - public static final String ALIAS_STRING = "p5android-key"; - public static final int KEY_VALIDITY_YEARS = 25; - public static final String KEYSTORE_FILE_NAME = "processing-upload-keystore.jks"; - - public static File getKeyStore() { - return getKeyStore(KEYSTORE_FILE_NAME); - } - - public static File getKeyStore(String name) { - File keyStore = getKeyStoreLocation(name); - if (!keyStore.exists()) return null; - return keyStore; - } - - public static File getKeyStoreLocation(String name) { - File sketchbookFolder = processing.app.Base.getSketchbookFolder(); - File androidFolder = new File(sketchbookFolder, "android"); - File keyStoreFolder = new File(androidFolder, "keystore"); - if (!keyStoreFolder.exists()) { - boolean result = keyStoreFolder.mkdirs(); - - if (!result) { - Messages.showWarning(AndroidMode.getTextString("android_keystore.warn.cannot_create_folders.title"), - AndroidMode.getTextString("android_keystore.warn.cannot_create_folders.body")); - return null; - } - } - - File keyStore = new File(keyStoreFolder, name); - return keyStore; - } - - public static void generateKeyStore(String password, - String commonName, String organizationalUnit, - String organizationName, String locality, - String state, String country) throws Exception { - String dnamePlaceholder = "CN=%s, OU=%s, O=%s, L=%s, S=%s, C=%s"; - String dname = String.format(dnamePlaceholder, - parseDnameField(commonName), parseDnameField(organizationalUnit), parseDnameField(organizationName), - parseDnameField(locality), parseDnameField(state), parseDnameField(country)); - - ProcessHelper ph = new ProcessHelper(new String[] { - "keytool", "-genkey", - "-keystore", getKeyStoreLocation(KEYSTORE_FILE_NAME).getAbsolutePath(), - "-alias", ALIAS_STRING, - "-keyalg", "RSA", - "-keysize", "2048", - "-validity", Integer.toString(KEY_VALIDITY_YEARS * 365), - "-keypass", password, - "-storepass", password, - "-dname", dname - }); - - try { - ProcessResult result = ph.execute(); - if (result.succeeded()) { - if (getKeyStore() == null) { - Messages.showWarning(AndroidMode.getTextString("android_keystore.warn.cannot_find_keystore.title"), - AndroidMode.getTextString("android_keystore.warn.cannot_find_keystore.body")); - } - } else { - String[] lines = PApplet.split(result.getStderr(), '\n'); - System.err.println(AndroidMode.getTextString("android_keystore.error.cannot_create_keystore")); - for (String line: lines) { - System.err.println(line); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static boolean resetKeyStore() { - File keyStore = getKeyStore(); - if (keyStore == null) return true; - - File keyStoreBackup = getKeyStoreLocation(KEYSTORE_FILE_NAME + "-" + AndroidMode.getDateStamp()); - if (!keyStore.renameTo(keyStoreBackup)) return false; - return true; - } - - private static String parseDnameField(String content) { - if (content == null || content.length() == 0) return "Unknown"; - else return content; - } -} diff --git a/mode/src/processing/mode/android/AndroidLineBreakpoint.java b/mode/src/processing/mode/android/AndroidLineBreakpoint.java deleted file mode 100644 index 3716826b1..000000000 --- a/mode/src/processing/mode/android/AndroidLineBreakpoint.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2018-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import com.sun.jdi.ReferenceType; -import processing.mode.java.debug.Debugger; -import processing.mode.java.debug.LineBreakpoint; -import processing.mode.java.debug.LineID; - -public class AndroidLineBreakpoint extends LineBreakpoint { - private boolean alreadyAdded; - - public AndroidLineBreakpoint(LineID line, Debugger dbg) { - super(line, dbg); - } - - public AndroidLineBreakpoint(int lineIdx, Debugger dbg) { - super(lineIdx, dbg); - } - - @Override public void classLoaded(ReferenceType theClass) { - if (!isAttached()) { - addPackageName(); - // try to attach - attach(theClass); - } - } - - - /** - * Add package name to the class name. Needed to match - * the logical class name to the VM (Physical) class name - */ - private void addPackageName() { - if (!alreadyAdded) { - className = ((AndroidDebugger) dbg).getPackageName() + "." + className; - alreadyAdded = !alreadyAdded; - } - } -} diff --git a/mode/src/processing/mode/android/AndroidMode.java b/mode/src/processing/mode/android/AndroidMode.java deleted file mode 100644 index 6d35f855b..000000000 --- a/mode/src/processing/mode/android/AndroidMode.java +++ /dev/null @@ -1,441 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2011-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import processing.app.Base; -import processing.app.Library; -import processing.app.Messages; -import processing.app.Platform; -import processing.app.RunnerListener; -import processing.app.Sketch; -import processing.app.SketchException; -import processing.app.ui.Editor; -import processing.app.ui.EditorException; -import processing.app.ui.EditorState; -import processing.core.PApplet; -import processing.mode.android.AndroidSDK.CancelException; -import processing.mode.java.JavaMode; - -import java.io.File; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Future; - -/** - * Programming mode to create and run Processing sketches on Android devices. - */ -public class AndroidMode extends JavaMode { - private AndroidSDK sdk; - private File coreZipLocation; - private AndroidRunner runner; - - private boolean showWatchFaceDebugMessage = true; - private boolean showWatchFaceSelectMessage = true; - private boolean showWallpaperSelectMessage = true; - - private boolean checkingSDK = false; - private boolean userCancelledSDKSearch = false; - - // Using this temporarily until support for mode translations is finalized in the Processing app - private static Map textStrings = null; - - private static final String VERSIONS_FILE = "version.properties"; - - private static final String BLUETOOTH_DEBUG_URL = - "https://developer.android.com/training/wearables/apps/debugging.html"; - - private static final String DISTRIBUTING_APPS_TUT_URL = - "http://android.processing.org/tutorials/distributing/index.html"; - - public AndroidMode(Base base, File folder) { - super(base, folder); - AndroidBuild.initVersions(getContentFile(VERSIONS_FILE)); - loadTextStrings(); - } - - - @Override - public Editor createEditor(Base base, String path, - EditorState state) throws EditorException { - return new AndroidEditor(base, path, state, this); - } - - - @Override - public String getTitle() { - return "Android"; - } - - - public File[] getKeywordFiles() { - return new File[] { - Platform.getContentFile("modes/java/keywords.txt"), - getContentFile("keywords.txt") - }; - } - - - public File[] getExampleCategoryFolders() { - return new File[] { - new File(examplesFolder, "Basics"), - new File(examplesFolder, "Topics"), - new File(examplesFolder, "Demos"), - new File(examplesFolder, "Sensors") - }; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** @return null so that it doesn't try to pass along the desktop version of core.jar */ - public Library getCoreLibrary() { - return null; - } - - - protected File getCoreZipLocation() { - if (coreZipLocation == null) { - /* - // for debugging only, check to see if this is an svn checkout - File debugFile = new File("../../../android/core.zip"); - if (!debugFile.exists() && Base.isMacOS()) { - // current path might be inside Processing.app, so need to go much higher - debugFile = new File("../../../../../../../android/core.zip"); - } - if (debugFile.exists()) { - System.out.println("Using version of core.zip from local SVN checkout."); -// return debugFile; - coreZipLocation = debugFile; - } - */ - - // otherwise do the usual - // return new File(base.getSketchbookFolder(), ANDROID_CORE_FILENAME); - coreZipLocation = getContentFile("processing-core.zip"); - } - return coreZipLocation; - } - - - public void resetUserSelection() { - userCancelledSDKSearch = false; - } - - - public void checkSDK(Editor editor) { - if (checkingSDK) { - // Some other thread has invoked SDK checking, so wait until the first one - // is done (it might involve downloading the SDK, etc). - while (checkingSDK) { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - return; - } - } - } - if (userCancelledSDKSearch) return; - checkingSDK = true; - Throwable tr = null; - if (sdk == null) { - try { - sdk = AndroidSDK.load(true, editor); - if (sdk == null) { - sdk = AndroidSDK.locate(editor, this); - } - } catch (CancelException cancel) { - userCancelledSDKSearch = true; - tr = cancel; - } catch (Exception other) { - tr = other; - } - } - if (sdk == null) { - Messages.showWarning(AndroidMode.getTextString("android_mode.warn.cannot_load_sdk_title"), - AndroidMode.getTextString("android_mode.warn.cannot_load_sdk_body"), tr); - } else { - Devices devices = Devices.getInstance(); - devices.setSDK(sdk); - } - checkingSDK = false; - } - - - public AndroidSDK getSDK() { - return sdk; - } - - - public File getResourcesFolder() { - return new File(getFolder(), "resources"); - } - - - public String getModeJar() { - String modePath = new File(getFolder(), "mode").getAbsolutePath(); - return modePath + File.separator + "AndroidMode.jar"; - } - - - @Override - public String getSearchPath() { - if (sdk == null) { - checkSDK(null); - } - - if (sdk == null) { - Messages.log(AndroidMode.getTextString("android_mode.info.cannot_open_sdk_path")); - return ""; - } - - String coreJarPath = new File(getFolder(), "processing-core.zip").getAbsolutePath(); - return sdk.getAndroidJarPath().getAbsolutePath() + File.pathSeparatorChar + coreJarPath; - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd.HHmm"); - - - static public String getDateStamp() { - return dateFormat.format(new Date()); - } - - - static public String getDateStamp(long stamp) { - return dateFormat.format(new Date(stamp)); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - public void handleRunEmulator(Sketch sketch, AndroidEditor editor, - RunnerListener listener) throws SketchException, IOException { - listener.startIndeterminate(); - listener.statusNotice(AndroidMode.getTextString("android_mode.status.starting_project_build")); - AndroidBuild build = new AndroidBuild(sketch, this, editor.getAppComponent()); - - listener.statusNotice(AndroidMode.getTextString("android_mode.status.building_project")); - build.build("debug", ""); - - if (sdk.getEmulatorTool() == null) { - // System.out.println("Try to download the emulator using the SDK Manager..."); - listener.statusNotice(AndroidMode.getTextString("android_mode.status.downloading_emulator")); - boolean emulatorInstallationSucceded = sdk.downloadEmuOnDemand(); - if (!emulatorInstallationSucceded) { - SketchException emulatorInstallationErrorException = new SketchException(AndroidMode.getTextString("android_mode.error.emulator_installation_failed")); - emulatorInstallationErrorException.hideStackTrace(); - throw emulatorInstallationErrorException; - } else { - System.out.println(AndroidMode.getTextString("android_mode.status.downloading_emulator_successful")); - } - } - - boolean avd = AVD.ensureProperAVD(editor, this, sdk, build.isWear()); - if (!avd) { - SketchException se = - new SketchException(AndroidMode.getTextString("android_mode.error.cannot_create_avd")); - se.hideStackTrace(); - throw se; - } - - int comp = build.getAppComponent(); - Future emu = Devices.getInstance().getEmulator(build.isWear()); - runner = new AndroidRunner(build, listener); - runner.launch(emu, comp, true); - } - - - public void handleRunDevice(Sketch sketch, AndroidEditor editor, - RunnerListener listener) - throws SketchException, IOException { - - final Devices devices = Devices.getInstance(); - java.util.List deviceList = devices.findMultiple(false); - if (deviceList.size() == 0) { - Messages.showWarning(AndroidMode.getTextString("android_mode.dialog.no_devices_found_title"), - AndroidMode.getTextString("android_mode.dialog.no_devices_found_body")); - listener.statusError(AndroidMode.getTextString("android_mode.status.no_devices_found")); - return; - } - - listener.startIndeterminate(); - listener.statusNotice(AndroidMode.getTextString("android_mode.status.starting_project_build")); - AndroidBuild build = new AndroidBuild(sketch, this, editor.getAppComponent()); - - listener.statusNotice(AndroidMode.getTextString("android_mode.status.building_project")); - File projectFolder = build.build("debug", ""); - if (projectFolder == null) { - listener.statusError(AndroidMode.getTextString("android_mode.status.project_build_failed")); - return; - } - - int comp = build.getAppComponent(); - Future dev = Devices.getInstance().getHardware(); - runner = new AndroidRunner(build, listener); - if (runner.launch(dev, comp, false)) { - showPostBuildMessage(comp); - } - } - - - public void showSelectComponentMessage(int appComp) { - if (showWatchFaceDebugMessage && appComp == AndroidBuild.WATCHFACE) { - AndroidUtil.showMessage(AndroidMode.getTextString("android_mode.dialog.watchface_debug_title"), - AndroidMode.getTextString("android_mode.dialog.watchface_debug_body", BLUETOOTH_DEBUG_URL)); - showWatchFaceDebugMessage = false; - } - } - - - public void showPostBuildMessage(int appComp) { - if (showWallpaperSelectMessage && appComp == AndroidBuild.WALLPAPER) { - AndroidUtil.showMessage(AndroidMode.getTextString("android_mode.dialog.wallpaper_installed_title"), - AndroidMode.getTextString("android_mode.dialog.wallpaper_installed_body")); - showWallpaperSelectMessage = false; - } - if (showWatchFaceSelectMessage && appComp == AndroidBuild.WATCHFACE) { - AndroidUtil.showMessage(AndroidMode.getTextString("android_mode.dialog.watchface_installed_title"), - AndroidMode.getTextString("android_mode.dialog.watchface_installed_body")); - showWatchFaceSelectMessage = false; - } - } - - - public void handleStop(RunnerListener listener) { - listener.statusNotice(""); - listener.stopIndeterminate(); - -// if (runtime != null) { -// runtime.close(); // kills the window -// runtime = null; // will this help? -// } - if (runner != null) { - runner.close(); - runner = null; - } - } - - - public boolean checkPackageName(Sketch sketch, int comp) { - Manifest manifest = new Manifest(sketch, comp, getFolder(), false); - String defName = Manifest.BASE_PACKAGE + "." + sketch.getName().toLowerCase(); - String name = manifest.getPackageName(); - if (name.toLowerCase().equals(defName.toLowerCase())) { - // The user did not set the package name, show error and stop - AndroidUtil.showMessage(AndroidMode.getTextString("android_mode.dialog.cannot_export_package_title"), - AndroidMode.getTextString("android_mode.dialog.cannot_export_package_body", DISTRIBUTING_APPS_TUT_URL)); - return false; - } - return true; - } - - - public boolean checkAppIcons(Sketch sketch, int comp) { - File sketchFolder = sketch.getFolder(); - - File[] launcherIcons = AndroidUtil.getFileList(sketchFolder, AndroidBuild.SKETCH_LAUNCHER_ICONS, - AndroidBuild.SKETCH_OLD_LAUNCHER_ICONS); - boolean allFilesExist = AndroidUtil.allFilesExists(launcherIcons); - - if (comp == AndroidBuild.WATCHFACE) { - // Additional preview icons are needed for watch faces - File[] watchFaceIcons = AndroidUtil.getFileList(sketchFolder, AndroidBuild.SKETCH_WATCHFACE_ICONS); - allFilesExist &= AndroidUtil.allFilesExists(watchFaceIcons); - } - - if (!allFilesExist) { - // The user did not set custom icons, show error and stop - AndroidUtil.showMessage(AndroidMode.getTextString("android_mode.dialog.cannot_use_default_icons_title"), - AndroidMode.getTextString("android_mode.dialog.cannot_use_default_icons_body", DISTRIBUTING_APPS_TUT_URL)); - return false; - } - return true; - } - - - public void initManifest(Sketch sketch, int comp) { - new Manifest(sketch, comp, getFolder(), false); - } - - - public void resetManifest(Sketch sketch, int comp) { - new Manifest(sketch, comp, getFolder(), true); - } - - private void loadTextStrings() { - String baseFilename = "languages/mode.properties"; - File modeBaseFile = new File(getFolder(), baseFilename); - if (textStrings == null) { - textStrings = new HashMap(); - String[] lines = PApplet.loadStrings(modeBaseFile); - if (lines == null) { - throw new NullPointerException("File not found:\n" + modeBaseFile.getAbsolutePath()); - } - //for (String line : lines) { - for (int i = 0; i < lines.length; i++) { - String line = lines[i]; - if ((line.length() == 0) || - (line.charAt(0) == '#')) continue; - - // this won't properly handle = signs inside in the text - int equals = line.indexOf('='); - if (equals != -1) { - String key = line.substring(0, equals).trim(); - String value = line.substring(equals + 1).trim(); - - value = value.replaceAll("\\\\n", "\n"); - value = value.replaceAll("\\\\'", "'"); - - textStrings.put(key, value); - } - } - } - } - - static public String getTextString(String key) { - if (textStrings.containsKey(key)) { - return textStrings.get(key); - } else { - return key; - } - -// return Language.text(key); - } - - static public String getTextString(String key, Object... arguments) { - String value = textStrings.get(key); - if (value == null) { - return key; - } - return String.format(value, arguments); - } -} - diff --git a/mode/src/processing/mode/android/AndroidRunner.java b/mode/src/processing/mode/android/AndroidRunner.java deleted file mode 100644 index ea22aa93d..000000000 --- a/mode/src/processing/mode/android/AndroidRunner.java +++ /dev/null @@ -1,298 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2011-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import java.io.IOException; -import java.io.PrintStream; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.sun.jdi.VirtualMachine; -import com.sun.jdi.VirtualMachineManager; -import com.sun.jdi.connect.AttachingConnector; -import com.sun.jdi.connect.Connector; -import com.sun.jdi.connect.IllegalConnectorArgumentsException; -import processing.app.ui.Editor; -import processing.app.Messages; -import processing.app.RunnerListener; -import processing.app.SketchException; -import processing.mode.java.runner.Runner; - -/** - * Launches an app on the device or in the emulator. - */ -public class AndroidRunner implements DeviceListener { - private static final String DEFAULT_PACKAGE_NAME = "processing.android"; - - AndroidBuild build; - RunnerListener listener; - - protected PrintStream sketchErr; - protected PrintStream sketchOut; - - private VirtualMachine vm; - - private boolean isDebugEnabled; - - public AndroidRunner(AndroidBuild build, RunnerListener listener) { - this.build = build; - this.listener = listener; - - if (listener instanceof AndroidEditor) { - isDebugEnabled = ((AndroidEditor) listener).isDebuggerEnabled(); - } - - if (listener instanceof Editor) { - Editor editor = (Editor) listener; - sketchErr = editor.getConsole().getErr(); - sketchOut = editor.getConsole().getOut(); - } else { - sketchErr = System.err; - sketchOut = System.out; - } - } - - - public boolean launch(Future deviceFuture, int comp, boolean emu) { - String devStr = emu ? "emulator" : "device"; - listener.statusNotice(AndroidMode.getTextString("android_runner.status.waiting_for_device", devStr)); - - final Device device = waitForDevice(deviceFuture, listener); - if (device == null || !device.isAlive()) { - listener.statusError(AndroidMode.getTextString("android_runner.status.lost_connection_with_device", devStr)); - // Reset the server, in case that's the problem. Sometimes when - // launching the emulator times out, the device list refuses to update. - final Devices devices = Devices.getInstance(); - devices.killAdbServer(); - return false; - } - - if (comp == AndroidBuild.WATCHFACE && !device.hasFeature("watch")) { - listener.statusError(AndroidMode.getTextString("android_runner.status.cannot_install_sketch")); - Messages.showWarning(AndroidMode.getTextString("android_runner.warn.non_watch_device_title"), - AndroidMode.getTextString("android_runner.warn.non_watch_device_body")); - return false; - } - - if (comp != AndroidBuild.WATCHFACE && device.hasFeature("watch")) { - listener.statusError(AndroidMode.getTextString("android_runner.status.cannot_install_sketch")); - Messages.showWarning(AndroidMode.getTextString("android_runner.warn.watch_device_title"), - AndroidMode.getTextString("android_runner.warn.watch_device_body")); - return false; - } - - device.addListener(this); - device.setPackageName(build.getPackageName()); - listener.statusNotice(AndroidMode.getTextString("android_runner.status.installing_sketch", device.getId())); - // this stopped working with Android SDK tools revision 17 - if (!device.installApp(build, listener)) { - listener.statusError(AndroidMode.getTextString("android_runner.status.lost_connection", devStr)); - final Devices devices = Devices.getInstance(); - devices.killAdbServer(); // see above - return false; - } - - boolean status = false; - if (comp == AndroidBuild.WATCHFACE || comp == AndroidBuild.WALLPAPER) { - if (startSketch(build, device)) { - listener.statusNotice(AndroidMode.getTextString("android_runner.status.sketch_installed") - + (device.isEmulator() ? " " + AndroidMode.getTextString("android_runner.status.in_emulator") : " " + - AndroidMode.getTextString("android_runner.status.on_device")) + "."); - status = true; - } else { - listener.statusError(AndroidMode.getTextString("android_runner.status.cannot_install_sketch")); - } - } else { - listener.statusNotice(AndroidMode.getTextString("android_runner.status.launching_sketch", device.getId())); - if (startSketch(build, device)) { - listener.statusNotice(AndroidMode.getTextString("android_runner.status.sketch_launched") - + (device.isEmulator() ? " " + AndroidMode.getTextString("android_runner.status.in_emulator") : " " + - AndroidMode.getTextString("android_runner.status.on_device")) + "."); - status = true; - } else { - listener.statusError(AndroidMode.getTextString("android_runner.status.cannot_launch_sketch")); - } - } - - // Start Debug if Debugger is enabled - if (isDebugEnabled) { - ((AndroidEditor) listener).getDebugger() - .startDebug(this, device); - } - - listener.stopIndeterminate(); - lastRunDevice = device; - return status; - } - - public VirtualMachine connectVirtualMachine(int port) throws IOException { - String strPort = Integer.toString(port); - AttachingConnector connector = getConnector(); - try { - vm = connect(connector, strPort); - return vm; - } catch (IllegalConnectorArgumentsException e) { - throw new IllegalStateException(e); - } - } - - private AttachingConnector getConnector() { - VirtualMachineManager vmManager = org.eclipse.jdi.Bootstrap.virtualMachineManager(); - for (Connector connector : vmManager.attachingConnectors()) { - if ("com.sun.jdi.SocketAttach".equals(connector.name())) { - return (AttachingConnector) connector; - } - } - throw new IllegalStateException(); - } - - private VirtualMachine connect( - AttachingConnector connector, String port) throws IllegalConnectorArgumentsException, IOException { - Map args = connector - .defaultArguments(); - Connector.Argument pidArgument = args.get("port"); - if (pidArgument == null) { - throw new IllegalStateException(); - } - pidArgument.setValue(port); - - return connector.attach(args); - } - - public VirtualMachine vm() { - return vm; - } - - private volatile Device lastRunDevice = null; - - - // if user asks for 480x320, 320x480, 854x480 etc, then launch like that - // though would need to query the emulator to see if it can do that - - private boolean startSketch(AndroidBuild build, final Device device) { - final String packageName = build.getPackageName(); - try { - if (device.launchApp(packageName, isDebugEnabled)) { - return true; - } - } catch (final Exception e) { - e.printStackTrace(System.err); - } - return false; - } - - - private Device waitForDevice(Future deviceFuture, RunnerListener listener) { - for (int i = 0; i < 120; i++) { - if (listener.isHalted()) { - deviceFuture.cancel(true); - return null; - } - try { - return deviceFuture.get(1, TimeUnit.SECONDS); - } catch (final InterruptedException e) { - listener.statusError("Interrupted."); - return null; - } catch (final ExecutionException e) { - listener.statusError(e); - return null; - } catch (final TimeoutException expected) { - } - } - listener.statusError(AndroidMode.getTextString("android_runner.status.cancel_waiting_for_device")); - return null; - } - - - private static final Pattern LOCATION = - Pattern.compile("\\(([^:]+):(\\d+)\\)"); - private static final Pattern EXCEPTION_PARSER = - Pattern.compile("^\\s*([a-z]+(?:\\.[a-z]+)+)(?:: .+)?$", - Pattern.CASE_INSENSITIVE); - - /** - * Currently figures out the first relevant stack trace line - * by looking for the telltale presence of "processing.android" - * in the package. If the packaging for droid sketches changes, - * this method will have to change too. - */ - public void stackTrace(final List trace) { - final Iterator frames = trace.iterator(); - final String exceptionLine = frames.next(); - - final Matcher m = EXCEPTION_PARSER.matcher(exceptionLine); - if (!m.matches()) { - System.err.println(AndroidMode.getTextString("android_runner.error.cannot_parse_stacktrace")); - System.err.println(exceptionLine); - listener.statusError(AndroidMode.getTextString("android_runner.status.unknwon_exception")); - return; - } - final String exceptionClass = m.group(1); - Runner.handleCommonErrors(exceptionClass, exceptionLine, listener, sketchErr); - - while (frames.hasNext()) { - final String line = frames.next(); - if (line.contains(DEFAULT_PACKAGE_NAME)) { - final Matcher lm = LOCATION.matcher(line); - if (lm.find()) { - final String filename = lm.group(1); - final int lineNumber = Integer.parseInt(lm.group(2)) - 1; - final SketchException rex = - build.placeException(exceptionLine, filename, lineNumber); - listener.statusError(rex == null ? new SketchException(exceptionLine, false) : rex); - return; - } - } - } - } - - - // called by AndroidMode.handleStop()... - public void close() { - if (lastRunDevice != null) { - lastRunDevice.bringLauncherToFront(); - } - - if (vm != null) { - try { - vm.exit(0); - - } catch (com.sun.jdi.VMDisconnectedException vmde) { - // if the vm has disconnected on its own, ignore message - //System.out.println("harmless disconnect " + vmde.getMessage()); - // TODO shouldn't need to do this, need to do more cleanup - } - } - } - - - // sketch stopped on the device - public void sketchStopped() { - listener.stopIndeterminate(); - listener.statusHalt(); - } -} diff --git a/mode/src/processing/mode/android/AndroidSDK.java b/mode/src/processing/mode/android/AndroidSDK.java deleted file mode 100644 index 18b988edf..000000000 --- a/mode/src/processing/mode/android/AndroidSDK.java +++ /dev/null @@ -1,883 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import processing.app.Language; -import processing.app.Messages; -import processing.app.Platform; -import processing.app.Preferences; -import processing.app.exec.ProcessHelper; -import processing.app.exec.ProcessResult; -import processing.app.ui.Toolkit; -import processing.core.PApplet; - -import javax.swing.*; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; - -import java.awt.*; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; - -import java.io.PrintWriter; - -/** - * Class holding all needed references (path, tools, etc) to the SDK used by - * the mode. - */ -class AndroidSDK { - public static boolean adbDisabled = false; - - final static private int FONT_SIZE = Toolkit.zoom(11); - final static private int TEXT_MARGIN = Toolkit.zoom(8); - final static private int TEXT_WIDTH = Toolkit.zoom(300); - - private final File folder; - private final File platforms; - private final File highestPlatform; - private final File androidJar; - private final File platformTools; - private final File buildTools; - private final File cmdlineTools; - private final File avdManager; - private final File sdkManager; - - private File emulator; - - private static final String SDK_DOWNLOAD_URL = - "https://developer.android.com/studio/index.html#downloads"; - - private static final String PROCESSING_FOR_ANDROID_URL = - "http://android.processing.org/"; - - private static final String WHATS_NEW_URL = - "http://android.processing.org/whatsnew.html"; - - private static final String DRIVER_INSTALL_URL = - "https://developer.android.com/studio/run/oem-usb.html#InstallingDriver"; - - private static final String SYSTEM_32BIT_URL = - "https://askubuntu.com/questions/710426/android-sdk-on-ubuntu-32bit"; - - private static final String SDK_LICENSE_URL = - "https://developer.android.com/studio/terms.html"; - - private static final int NO_ERROR = 0; - private static final int SKIP_ENV_SDK = 1; - private static final int MISSING_SDK = 2; - private static final int INVALID_SDK = 3; - private static int loadError = NO_ERROR; - - public AndroidSDK(File folder) throws BadSDKException, IOException { - this.folder = folder; - if (!folder.exists()) { - throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_sdk_folder", folder)); - } - - cmdlineTools = new File(folder, "cmdline-tools/latest"); - // We need only command line tools, as sdk/tools got deprecated and can't be used with java 17 - if (!cmdlineTools.exists()) { - // Let's be more specific to show the error - File sdkTools = new File(folder, "tools"); - if (sdkTools.exists()) { - throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_cmdtools_folder_found_sdktools", folder)); - } else { - throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_cmdtools_folder", folder)); - } - } - // If we reached here, that means command line tools exists - // ok to go with the command line tools - - platformTools = new File(folder, "platform-tools"); - if (!platformTools.exists()) { - throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_platform_tools_folder", folder)); - } - - buildTools = new File(folder, "build-tools"); - if (!buildTools.exists()) { - throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_build_tools_folder", folder)); - } - - platforms = new File(folder, "platforms"); - if (!platforms.exists()) { - throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_platforms_folder", folder)); - } - - // Retrieve the highest platform from the available targets - ArrayList targets = getAvailableSdkTargets(); - int highest = 1; - for (SDKTarget targ: targets) { - if (highest < targ.version) { - highest = targ.version; - } - } - - if (highest < PApplet.parseInt(AndroidBuild.TARGET_SDK)) { - throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_target_platform", - AndroidBuild.TARGET_SDK, platforms.getAbsolutePath())); - } - - highestPlatform = new File(platforms, "android-" + highest); - - androidJar = new File(highestPlatform, "android.jar"); - if (!androidJar.exists()) { - throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_android_jar", - AndroidBuild.TARGET_SDK, highestPlatform.getAbsolutePath())); - } - - avdManager = findCliTool(new File(cmdlineTools, "bin"), "avdmanager"); - sdkManager = findCliTool(new File(cmdlineTools, "bin"), "sdkmanager"); - - initEmu(); - - String path = Platform.getenv("PATH"); - - Platform.setenv("ANDROID_SDK", folder.getCanonicalPath()); - path = platformTools.getCanonicalPath() + File.pathSeparator + - cmdlineTools.getCanonicalPath() + File.pathSeparator + path; - - String javaHomeProp = System.getProperty("java.home"); - File javaHome = new File(javaHomeProp).getCanonicalFile(); - Platform.setenv("JAVA_HOME", javaHome.getCanonicalPath()); - - path = new File(javaHome, "bin").getCanonicalPath() + File.pathSeparator + path; - Platform.setenv("PATH", path); - - checkDebugCertificate(); - } - - private void initEmu() throws BadSDKException, IOException { - File emuFolder = new File(folder, "emulator"); - if (emuFolder.exists()) { - // First try the new location of the emulator inside its own folder - emulator = findCliTool(emuFolder, "emulator"); - } else { - // If not found, use old location inside tools as fallback - emuFolder = new File(cmdlineTools, "emulator"); - if (emuFolder.exists()) { - emulator = findCliTool(cmdlineTools, "emulator"); - } else { - emulator = null; - if (SDKDownloader.DOWNLOAD_EMU_WITH_SDK) { - // Only throw an exception if the downloader was supposed to download the emulator - throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_emulator", - AndroidBuild.TARGET_SDK, highestPlatform.getAbsolutePath())); - } - } - } - } - public boolean downloadEmuOnDemand() { - final String[] cmd = new String[] { - sdkManager.getAbsolutePath(), - "emulator" - }; - - ProcessBuilder pb = new ProcessBuilder(cmd); - Process process = null; - try { - process = pb.start(); - } catch (IOException e) { - e.printStackTrace(); - } - - try { - new RedirectStreamHandler(new PrintWriter(System.out, true), process.getInputStream()); - new RedirectStreamHandler(new PrintWriter(System.out, true), process.getErrorStream()); - - int emulatorDownloadResultCode = process.waitFor(); - System.out.println("Output from emulator download " + emulatorDownloadResultCode); - if (emulatorDownloadResultCode == 0) { - initEmu(); - return true; - } - } catch (IOException e) { - e.printStackTrace(); - } catch (BadSDKException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - process.destroy(); - } - - return false; - } - - - /** - * If a debug certificate exists, check its expiration date. If it's expired, - * remove it so that it doesn't cause problems during the build. - */ - protected void checkDebugCertificate() { - File dotAndroidFolder = new File(System.getProperty("user.home"), ".android"); - File keystoreFile = new File(dotAndroidFolder, "debug.keystore"); - if (keystoreFile.exists()) { - // keytool -list -v -storepass android -keystore debug.keystore - ProcessHelper ph = new ProcessHelper(new String[] { - "keytool", "-list", "-v", - "-storepass", "android", - "-keystore", keystoreFile.getAbsolutePath() - }); - try { - ProcessResult result = ph.execute(); - if (result.succeeded()) { - // Valid from: Mon Nov 02 15:38:52 EST 2009 until: Tue Nov 02 16:38:52 EDT 2010 - String[] lines = PApplet.split(result.getStdout(), '\n'); - for (String line : lines) { - String[] m = PApplet.match(line, "Valid from: .* until: (.*)"); - if (m != null) { - String timestamp = m[1].trim(); - // "Sun Jan 22 11:09:08 EST 2012" - // Hilariously, this is the format of Date.toString(), however - // it isn't the default for SimpleDateFormat or others. Yay! - DateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); - try { - Date date = df.parse(timestamp); - long expireMillis = date.getTime(); - if (expireMillis < System.currentTimeMillis()) { - System.out.println(AndroidMode.getTextString("android_debugger.info.removing_expired_keystore")); - String hidingName = "debug.keystore." + AndroidMode.getDateStamp(expireMillis); - File hidingFile = new File(keystoreFile.getParent(), hidingName); - if (!keystoreFile.renameTo(hidingFile)) { - System.err.println(AndroidMode.getTextString("android_debugger.error.cannot_remove_expired_keystore")); - System.err.println(AndroidMode.getTextString("android_debugger.error.request_removing_keystore", keystoreFile.getAbsolutePath())); - } - } - } catch (ParseException pe) { - System.err.println(AndroidMode.getTextString("android_debugger.error.invalid_keystore_timestamp", timestamp)); - System.err.println(AndroidMode.getTextString("android_debugger.error.request_bug_report")); - } - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - - public File getFolder() { - return folder; - } - - - public File getBuildToolsFolder() { - return buildTools; - } - - - public File getPlatformToolsFolder() { - return platformTools; - } - - - public File getAndroidJarPath() { - return androidJar; - } - - - public File getCommandLineToolsFolder() { - return cmdlineTools; - } - - - public File getEmulatorTool() { - return emulator; - } - - - public File getAVDManagerTool() { - return avdManager; - } - - - public File getHighestPlatform() { - return highestPlatform; - } - - - public File getTargetPlatform(String target) { - return new File(platforms, "android-" + target); - } - - - public File getZipAlignTool() { - File[] files = buildTools.listFiles(); - String name = Platform.isWindows() ? "zipalign.exe" : "zipalign"; - for (File f: files) { - File z = new File(f, name); - if (z.exists()) return z; - } - return null; - } - - - // Write to the process input, so the licenses will be accepted. In - // principle, we only need 7 'y', one for the 'yes' to the first - // 'review licenses?' question, the rest for the 6 licenses, but adding - // 10 just in case, having more does not cause any trouble. - private static final String response = "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"; - - private void acceptLicenses() { - final String[] cmd = new String[] { - sdkManager.getAbsolutePath(), - "--licenses" - }; - - ProcessBuilder pb = new ProcessBuilder(cmd); - pb.redirectErrorStream(true); - try { - Process process = pb.start(); - final OutputStream os = process.getOutputStream(); - final InputStream is = process.getInputStream(); - // Read the process output, otherwise read() will block and wait for new - // data to read - new Thread(new Runnable() { - public void run() { - byte[] b = new byte[1024]; - try { - while (is.read(b) != -1) { } - is.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - }, "AndroidSDK: reading licenses").start(); - Thread.sleep(3000); - os.write(response.getBytes()); - os.flush(); - os.close(); - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - - static public File getHAXMInstallerFolder() { - String sdkPrefsPath = Preferences.get("android.sdk.path"); - File sdkPath = new File(sdkPrefsPath); - return new File(sdkPath, "extras/intel/HAXM"); - } - - - static public File getGoogleDriverFolder() { - String sdkPrefsPath = Preferences.get("android.sdk.path"); - File sdkPath = new File(sdkPrefsPath); - return new File(sdkPath, "extras/google/usb_driver"); - } - - - /** - * Checks a path to see if there's a tools/android file inside, a rough check - * for the SDK installation. Also figures out the name of android/android.bat/android.exe - * so that it can be called explicitly. - */ - private static File findCliTool(final File tools, String name) - throws BadSDKException { - if (new File(tools, name + ".bat").exists()) { - return new File(tools, name + ".bat"); - } - if (new File(tools, name + ".exe").exists()) { - return new File(tools, name + ".exe"); - } - if (new File(tools, name).exists()) { - return new File(tools, name); - } - throw new BadSDKException("Cannot find " + name + " in " + tools); - } - - - /** - * Check for a set android.sdk.path preference. If the pref - * is set, and refers to a legitimate Android SDK, then use that. - * - * Check for the ANDROID_SDK environment variable. If the variable is set, - * and refers to a legitimate Android SDK, then use that and save the pref. - * - * Prompt the user to select an Android SDK. If the user selects a - * legitimate Android SDK, then use that, and save the preference. - * - * @return an AndroidSDK - * @throws BadSDKException - * @throws IOException - */ - public static AndroidSDK load(boolean checkEnvSDK, Frame editor) throws IOException { - loadError = NO_ERROR; - - // Give priority to preferences: - // https://github.com/processing/processing-android/issues/372 - final String sdkPrefsPath = Preferences.get("android.sdk.path"); - if (sdkPrefsPath != null && !sdkPrefsPath.equals("")) { - try { - final AndroidSDK androidSDK = new AndroidSDK(new File(sdkPrefsPath)); - Preferences.set("android.sdk.path", sdkPrefsPath); - return androidSDK; - } catch (final BadSDKException badPref) { - Preferences.unset("android.sdk.path"); - loadError = INVALID_SDK; - } - } - - final String sdkEnvPath = Platform.getenv("ANDROID_SDK"); - if (sdkEnvPath != null && !sdkEnvPath.equals("")) { - try { - final AndroidSDK androidSDK = new AndroidSDK(new File(sdkEnvPath)); - - if (checkEnvSDK && editor != null) { - // There is a valid SDK in the environment, but let's give the user - // the option to not to use it. After this, we should go straight to - // download a new SDK. - int result = showEnvSDKDialog(editor); - if (result != JOptionPane.YES_OPTION) { - loadError = SKIP_ENV_SDK; - return null; - } - } - - // Set this value in preferences.txt, in case ANDROID_SDK - // gets knocked out later. For instance, by that pesky Eclipse, - // which nukes all env variables when launching from the IDE. - Preferences.set("android.sdk.path", sdkEnvPath); - - // If we are here, it means that there was no SDK path in the preferences - // and the user wants to use the SDK found in the environment. This - // means we just installed the mode for the first time, so we show a - // welcome message with some useful info. - AndroidUtil.showMessage(AndroidMode.getTextString("android_sdk.dialog.using_existing_sdk_title"), - AndroidMode.getTextString("android_sdk.dialog.using_existing_sdk_body", - PROCESSING_FOR_ANDROID_URL, WHATS_NEW_URL)); - - return androidSDK; - } catch (final BadSDKException badEnv) { - Preferences.unset("android.sdk.path"); - loadError = INVALID_SDK; - } - } else if (loadError == NO_ERROR) { - loadError = MISSING_SDK; - } - - return null; - } - - - static public AndroidSDK locate(final Frame window, final AndroidMode androidMode) - throws BadSDKException, CancelException, IOException { - - if (loadError == SKIP_ENV_SDK) { - // The user does not want to use the environment SDK, so let's simply - // download a new one to the sketchbook folder. - return download(window, androidMode); - } - - // At this point, there is no ANDROID_SDK env variable, no SDK in the preferences, - // or either one was invalid, so we will continue by asking the user to either locate - // a valid SDK manually, or download a new one. - int result = showLocateDialog(window); - - if (result == JOptionPane.YES_OPTION) { - return download(window, androidMode); - } else if (result == JOptionPane.NO_OPTION) { - // User will manually select folder containing SDK folder - File folder = selectFolder(AndroidMode.getTextString("android_sdk.dialog.select_sdk_folder"), null, window); - if (folder == null) { - throw new CancelException(AndroidMode.getTextString("android_sdk.error.cancel_sdk_selection")); - } else { - final AndroidSDK androidSDK = new AndroidSDK(folder); - Preferences.set("android.sdk.path", folder.getAbsolutePath()); - return androidSDK; - } - } else { - throw new CancelException(AndroidMode.getTextString("android_sdk.error.sdk_selection_canceled")); - } - } - - static public boolean requestSysImage(final Frame window, - final AndroidMode androidMode, final boolean wear, final boolean ask) - throws BadSDKException, CancelException, IOException { - final int result = showDownloadSysImageDialog(window, wear); - if (result == JOptionPane.YES_OPTION) { - return downloadSysImage(window, androidMode, wear, ask); - } else if (result == JOptionPane.NO_OPTION) { - return false; - } else { - return false; - } - } - - static public AndroidSDK download(final Frame editor, final AndroidMode androidMode) - throws BadSDKException, CancelException { - final SDKDownloader downloader = new SDKDownloader(editor); - downloader.run(); // This call blocks until the SDK download complete, or user cancels. - - if (downloader.cancelled()) { - throw new CancelException(AndroidMode.getTextString("android_sdk.error.sdk_download_canceled")); - } - AndroidSDK sdk = downloader.getSDK(); - if (sdk == null) { - throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.sdk_download_failed")); - } - - final int result = showSDKLicenseDialog(editor); - if (result == JOptionPane.YES_OPTION) { - sdk.acceptLicenses(); - String msg = AndroidMode.getTextString("android_sdk.dialog.sdk_installed_body", PROCESSING_FOR_ANDROID_URL, WHATS_NEW_URL); - File driver = AndroidSDK.getGoogleDriverFolder(); - if (Platform.isWindows() && driver.exists()) { - msg += AndroidMode.getTextString("android_sdk.dialog.install_usb_driver", DRIVER_INSTALL_URL, driver.getAbsolutePath()); - } - AndroidUtil.showMessage(AndroidMode.getTextString("android_sdk.dialog.sdk_installed_title"), msg); - } else { - AndroidUtil.showMessage(AndroidMode.getTextString("android_sdk.dialog.sdk_license_rejected_title"), - AndroidMode.getTextString("android_sdk.dialog.sdk_license_rejected_body")); - } - - // if (Platform.isLinux() && Platform.getNativeBits() == 32) { - // AndroidUtil.showMessage(AndroidMode.getTextString("android_sdk.dialog.32bit_system_title"), - // AndroidMode.getTextString("android_sdk.dialog.32bit_system_body", SYSTEM_32BIT_URL)); - // } - - return sdk; - } - - static public boolean downloadSysImage(final Frame editor, - final AndroidMode androidMode, final boolean wear, final boolean ask) - throws BadSDKException, CancelException { - final SysImageDownloader downloader = new SysImageDownloader(editor, wear, ask); - downloader.run(); // This call blocks until the SDK download complete, or user cancels. - - if (downloader.cancelled()) { - throw new CancelException(AndroidMode.getTextString("android_sdk.error.emulator_download_canceled")); - } - boolean res = downloader.getResult(); - if (!res) { - throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.emulator_download_failed")); - } - return res; - } - - - static public int showEnvSDKDialog(Frame editor) { - String title = AndroidMode.getTextString("android_sdk.dialog.found_installed_sdk_title"); - String htmlString = " " + - " " + - "

    " + AndroidMode.getTextString("android_sdk.dialog.found_installed_sdk_body") + "

    "; - JEditorPane pane = new JEditorPane("text/html", htmlString); - pane.addHyperlinkListener(new HyperlinkListener() { - @Override - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { - Platform.openURL(e.getURL().toString()); - } - } - }); - pane.setEditable(false); - JLabel label = new JLabel(); - pane.setBackground(label.getBackground()); - - String[] options = new String[] { AndroidMode.getTextString("android_sdk.option.use_existing_sdk"), - AndroidMode.getTextString("android_sdk.option.download_new_sdk") }; - int result = JOptionPane.showOptionDialog(null, pane, title, - JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, - null, options, options[0]); - if (result == JOptionPane.YES_OPTION) { - return JOptionPane.YES_OPTION; - } else if (result == JOptionPane.NO_OPTION) { - return JOptionPane.NO_OPTION; - } else { - return JOptionPane.CLOSED_OPTION; - } - } - - - static public int showLocateDialog(Frame editor) { - // How to show a option dialog containing clickable links: - // http://stackoverflow.com/questions/8348063/clickable-links-in-joptionpane - String htmlString = " " + - " "; - String title = ""; - if (loadError == MISSING_SDK) { - htmlString += "

    " + AndroidMode.getTextString("android_sdk.dialog.cannot_find_sdk_body", SDK_DOWNLOAD_URL, AndroidBuild.TARGET_SDK) + "

    "; - title = AndroidMode.getTextString("android_sdk.dialog.cannot_find_sdk_title"); - } else if (loadError == INVALID_SDK) { - htmlString += "

    " + AndroidMode.getTextString("android_sdk.dialog.invalid_sdk_body", AndroidBuild.TARGET_SDK, SDK_DOWNLOAD_URL, AndroidBuild.TARGET_SDK) + "

    "; - title = AndroidMode.getTextString("android_sdk.dialog.invalid_sdk_title"); - } - JEditorPane pane = new JEditorPane("text/html", htmlString); - pane.addHyperlinkListener(new HyperlinkListener() { - @Override - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { - Platform.openURL(e.getURL().toString()); - } - } - }); - pane.setEditable(false); - JLabel label = new JLabel(); - pane.setBackground(label.getBackground()); - - String[] options = new String[] { AndroidMode.getTextString("android_sdk.option.download_sdk"), - AndroidMode.getTextString("android_sdk.option.locate_sdk") }; - int result = JOptionPane.showOptionDialog(null, pane, title, - JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, - null, options, options[0]); - if (result == JOptionPane.YES_OPTION) { - return JOptionPane.YES_OPTION; - } else if (result == JOptionPane.NO_OPTION) { - return JOptionPane.NO_OPTION; - } else { - return JOptionPane.CLOSED_OPTION; - } - } - - - static public int showDownloadSysImageDialog(Frame editor, boolean wear) { - String title = wear ? AndroidMode.getTextString("android_sdk.dialog.download_watch_image_title") : - AndroidMode.getTextString("android_sdk.dialog.download_phone_image_title"); - String msg = wear ? AndroidMode.getTextString("android_sdk.dialog.download_watch_image_body") : - AndroidMode.getTextString("android_sdk.dialog.download_phone_image_body"); - String htmlString = " " + - " " + "

    " + msg + "

    "; - JEditorPane pane = new JEditorPane("text/html", htmlString); - pane.addHyperlinkListener(new HyperlinkListener() { - @Override - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { - Platform.openURL(e.getURL().toString()); - } - } - }); - pane.setEditable(false); - JLabel label = new JLabel(); - pane.setBackground(label.getBackground()); - - String[] options = new String[] { Language.text("prompt.yes"), Language.text("prompt.no") }; - - int result = JOptionPane.showOptionDialog(null, pane, title, - JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, - null, options, options[0]); - if (result == JOptionPane.YES_OPTION) { - return JOptionPane.YES_OPTION; - } else if (result == JOptionPane.NO_OPTION) { - return JOptionPane.NO_OPTION; - } else { - return JOptionPane.CLOSED_OPTION; - } - } - - - static public int showSDKLicenseDialog(Frame editor) { - String title = AndroidMode.getTextString("android_sdk.dialog.accept_sdk_license_title"); - String msg = AndroidMode.getTextString("android_sdk.dialog.accept_sdk_license_body", SDK_LICENSE_URL); - String htmlString = " " + - " " + "

    " + msg + "

    "; - JEditorPane pane = new JEditorPane("text/html", htmlString); - pane.addHyperlinkListener(new HyperlinkListener() { - @Override - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { - Platform.openURL(e.getURL().toString()); - } - } - }); - pane.setEditable(false); - JLabel label = new JLabel(); - pane.setBackground(label.getBackground()); - - String[] options = new String[] { Language.text("prompt.yes"), Language.text("prompt.no") }; - - int result = JOptionPane.showOptionDialog(null, pane, title, - JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, - null, options, options[0]); - if (result == JOptionPane.YES_OPTION) { - return JOptionPane.YES_OPTION; - } else if (result == JOptionPane.NO_OPTION) { - return JOptionPane.NO_OPTION; - } else { - return JOptionPane.CLOSED_OPTION; - } - } - - - // this was banished from Base because it encourages bad practice. - // TODO figure out a better way to handle the above. - static public File selectFolder(String prompt, File folder, Frame frame) { - if (Platform.isMacOS()) { - if (frame == null) frame = new Frame(); //.pack(); - FileDialog fd = new FileDialog(frame, prompt, FileDialog.LOAD); - if (folder != null) { - fd.setDirectory(folder.getParent()); - //fd.setFile(folder.getName()); - } - System.setProperty("apple.awt.fileDialogForDirectories", "true"); - fd.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); - fd.setVisible(true); - System.setProperty("apple.awt.fileDialogForDirectories", "false"); - if (fd.getFile() == null) { - return null; - } - return new File(fd.getDirectory(), fd.getFile()); - - } else { - JFileChooser fc = new JFileChooser(); - fc.setDialogTitle(prompt); - if (folder != null) { - fc.setSelectedFile(folder); - } - fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - - int returned = fc.showOpenDialog(frame); - if (returned == JFileChooser.APPROVE_OPTION) { - return fc.getSelectedFile(); - } - } - return null; - } - - - private static final String ADB_DAEMON_MSG_1 = "daemon not running"; - private static final String ADB_DAEMON_MSG_2 = "daemon started successfully"; - - public ProcessResult runADB(final String... cmd) - throws InterruptedException, IOException { - - if (adbDisabled) { - throw new IOException("adb is currently disabled"); - } - - final String[] adbCmd; - if (!cmd[0].contains("adb")) { - File abdPath = Platform.isWindows() ? new File(platformTools, "adb.exe") : - new File(platformTools, "adb"); - adbCmd = PApplet.splice(cmd, abdPath.getCanonicalPath(), 0); - } else { - adbCmd = cmd; - } - // printing this here to see if anyone else is killing the adb server - if (processing.app.Base.DEBUG) { - PApplet.printArray(adbCmd); - } - try { - ProcessResult adbResult = new ProcessHelper(adbCmd).execute(); - // Ignore messages about starting up an adb daemon - String out = adbResult.getStdout(); - if (out.contains(ADB_DAEMON_MSG_1) && out.contains(ADB_DAEMON_MSG_2)) { - StringBuilder sb = new StringBuilder(); - for (String line : out.split("\n")) { - if (!out.contains(ADB_DAEMON_MSG_1) && - !out.contains(ADB_DAEMON_MSG_2)) { - sb.append(line).append("\n"); - } - } - return new ProcessResult(adbResult.getCmd(), - adbResult.getResult(), - sb.toString(), - adbResult.getStderr(), - adbResult.getTime()); - } - return adbResult; - } catch (IOException ioe) { - if (-1 < ioe.getMessage().indexOf("Permission denied")) { - Messages.showWarning(AndroidMode.getTextString("android_sdk.warn.cannot_run_adb_title"), - AndroidMode.getTextString("android_sdk.warn.cannot_run_adb_body")); - adbDisabled = true; - } - throw ioe; - } - } - - static class SDKTarget { - public int version = 0; - public String name; - } - - public ArrayList getAvailableSdkTargets() throws IOException { - ArrayList targets = new ArrayList(); - - for (File platform : platforms.listFiles()) { - File propFile = new File(platform, "build.prop"); - if (!propFile.exists()) continue; - - SDKTarget target = new SDKTarget(); - - BufferedReader br = new BufferedReader(new FileReader(propFile)); - String line; - while ((line = br.readLine()) != null) { - String[] lineData = line.split("="); - if (lineData[0].equals("ro.build.version.sdk")) { - target.version = Integer.valueOf(lineData[1]); - } - - if (lineData[0].equals("ro.build.version.release")) { - target.name = lineData[1]; - break; - } - } - br.close(); - - if (target.version != 0 && target.name != null) targets.add(target); - } - - return targets; - } - - @SuppressWarnings("serial") - static public class BadSDKException extends Exception { - public BadSDKException(final String message) { - super(message); - } - } - - @SuppressWarnings("serial") - static public class CancelException extends Exception { - public CancelException(final String message) { - super(message); - } - } -} diff --git a/mode/src/processing/mode/android/AndroidTool.java b/mode/src/processing/mode/android/AndroidTool.java deleted file mode 100644 index 3dbdb932b..000000000 --- a/mode/src/processing/mode/android/AndroidTool.java +++ /dev/null @@ -1,138 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2017-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -package processing.mode.android; - -import java.io.File; -import java.net.URL; -import java.net.URLClassLoader; - -import processing.app.Base; -import processing.app.Messages; -import processing.app.Util; -import processing.app.contrib.ContributionType; -import processing.app.contrib.IgnorableException; -import processing.app.contrib.LocalContribution; -import processing.app.tools.Tool; - -/** - * Specialized local contribution for Android tools. Cannot use ToolContribution - * from processing-app since Android tools may need SDK jars in the classpath. - */ -public class AndroidTool extends LocalContribution implements Tool, Comparable { - private Tool tool; - private AndroidMode mode; - - AndroidTool(File toolFolder, AndroidMode androidMode) throws Throwable { - super(toolFolder); - this.mode = androidMode; - - String className = initLoader(null); - if (className != null) { - Class toolClass = loader.loadClass(className); - tool = (Tool) toolClass.newInstance(); - } - } - - public void init(Base base) { - tool.init(base); - } - - - public void run() { - tool.run(); - } - - - public String getMenuTitle() { - return tool.getMenuTitle(); - } - - public String initLoader(String className) throws Exception { - File toolDir = new File(folder, "tool"); - if (toolDir.exists()) { - Messages.log("checking mode folder regarding " + className); - // If no class name specified, search the main .jar for the - // full name package and mode name. - if (className == null) { - String shortName = folder.getName(); - File mainJar = new File(toolDir, shortName + ".jar"); - if (mainJar.exists()) { - className = findClassInZipFile(shortName, mainJar); - } else { - throw new IgnorableException(mainJar.getAbsolutePath() + " does not exist."); - } - - if (className == null) { - throw new IgnorableException("Could not find " + shortName + - " class inside " + mainJar.getAbsolutePath()); - } - } - - // Add .jar and .zip files from the "tool" and the tools/lib - // folder into the classpath - File libDir = new File(folder, "lib"); - File[] toolArchives = Util.listJarFiles(toolDir); - File[] libArchives = Util.listJarFiles(libDir); - - if (toolArchives != null && toolArchives.length > 0 && - libArchives != null && libArchives.length > 0) { - URL[] urlList = new URL[toolArchives.length + libArchives.length + 1]; - - int j; - for (j = 0; j < toolArchives.length; j++) { - Messages.log("Found archive " + toolArchives[j] + " for " + getName()); - urlList[j] = toolArchives[j].toURI().toURL(); - } - for (int k = 0; k < libArchives.length; k++, j++) { - Messages.log("Found archive " + libArchives[k] + " for " + getName()); - urlList[j] = libArchives[k].toURI().toURL(); - } - urlList[urlList.length - 1] = new File(mode.getModeJar()).toURI().toURL(); - - -// String modePath = new File(dmode.getFolder(), "mode").getAbsolutePath(); -// urlList[urlList.length - 1] = new File(modePath + File.separator + "JavaMode.jar").toURI().toURL(); - - loader = new URLClassLoader(urlList); - Messages.log("loading above JARs with loader " + loader); - } - } - - // If no archives were found, just use the regular ClassLoader - if (loader == null) { - loader = Thread.currentThread().getContextClassLoader(); - } - return className; - } - - - @Override - public int compareTo(AndroidTool o) { - return getMenuTitle().compareTo(o.getMenuTitle()); - } - - - @Override - public ContributionType getType() { - return ContributionType.TOOL; - } -} diff --git a/mode/src/processing/mode/android/AndroidToolbar.java b/mode/src/processing/mode/android/AndroidToolbar.java deleted file mode 100644 index 960cd30b0..000000000 --- a/mode/src/processing/mode/android/AndroidToolbar.java +++ /dev/null @@ -1,218 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2011-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -package processing.mode.android; - -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.util.ArrayList; -import java.util.List; - -import processing.app.Base; -import processing.app.ui.Editor; -import processing.app.ui.EditorButton; -import processing.app.ui.EditorToolbar; -import processing.app.Language; - -import javax.swing.*; - - -@SuppressWarnings("serial") -public class AndroidToolbar extends EditorToolbar { - static protected final int RUN_ON_DEVICE = 0; - static protected final int RUN_IN_EMULATOR = 1; - static protected final int STOP = 2; - - static protected final int NEW = 3; - static protected final int OPEN = 4; - static protected final int SAVE = 5; - - static protected final int EXPORT_PACKAGE = 6; - static protected final int EXPORT_BUNDLE = 7; - static protected final int EXPORT_PROJECT = 8; - - - private AndroidEditor aEditor; - - EditorButton stepButton; - EditorButton continueButton; - - public AndroidToolbar(Editor editor, Base base) { - super(editor); - aEditor = (AndroidEditor) editor; - } - - - static public String getTitle(int index) { - switch (index) { - case RUN_ON_DEVICE: return AndroidMode.getTextString("menu.sketch.run_on_device"); - case RUN_IN_EMULATOR: return AndroidMode.getTextString("menu.sketch.run_in_emulator"); - case STOP: return AndroidMode.getTextString("menu.sketch.stop"); - case NEW: return AndroidMode.getTextString("menu.file.new"); - case OPEN: return AndroidMode.getTextString("menu.file.open"); - case SAVE: return AndroidMode.getTextString("menu.file.save"); - case EXPORT_PACKAGE: return AndroidMode.getTextString("menu.file.export_signed_package"); - case EXPORT_BUNDLE: return AndroidMode.getTextString("menu.file.export_signed_bundle"); - case EXPORT_PROJECT: return AndroidMode.getTextString("menu.file.export_android_project"); - } - return null; - } - - - @Override - public List createButtons() { - // aEditor not ready yet because this is called by super() - final boolean debug = ((AndroidEditor) editor).isDebuggerEnabled(); - // final boolean debug = false; - - - ArrayList toReturn = new ArrayList(); - final String runText = debug ? - Language.text("toolbar.debug") : Language.text("Run on Device"); - runButton = new EditorButton(this, - "/lib/toolbar/run", - runText, - "Run on emulator") { - @Override - public void actionPerformed(ActionEvent e) { - handleRun(e.getModifiers()); - } - }; - toReturn.add(runButton); - - if (debug) { - stepButton = new EditorButton(this, - "/lib/toolbar/step", - Language.text("menu.debug.step"), - Language.text("menu.debug.step_into"), - Language.text("menu.debug.step_out")) { - @Override - public void actionPerformed(ActionEvent e) { - final int mask = ActionEvent.SHIFT_MASK | ActionEvent.ALT_MASK; - handleStep(e.getModifiers() & mask); - } - }; - toReturn.add(stepButton); - - continueButton = new EditorButton(this, - "/lib/toolbar/continue", - Language.text("menu.debug.continue")) { - @Override - public void actionPerformed(ActionEvent e) { - aEditor.getDebugger().continueDebug(); - } - }; - toReturn.add(continueButton); - } - - stopButton = new EditorButton(this, - "/lib/toolbar/stop", - Language.text("toolbar.stop")) { - @Override - public void actionPerformed(ActionEvent e) { - handleStop(); - } - }; - toReturn.add(stopButton); - - return toReturn; - } - - private void handleStep(int modifiers) { - if (modifiers == 0) { - aEditor.getDebugger().stepOver(); - } else if ((modifiers & ActionEvent.SHIFT_MASK) != 0) { - aEditor.getDebugger().stepInto(); - } else if ((modifiers & ActionEvent.ALT_MASK) != 0) { - aEditor.getDebugger().stepOut(); - } - } - - @Override - public void addModeButtons(Box box, JLabel label) { - - EditorButton debugButton = - new EditorButton(this, "/lib/toolbar/debug", - Language.text("toolbar.debug")) { - @Override - public void actionPerformed(ActionEvent e) { - aEditor.toggleDebug(); - } - }; - - if (((AndroidEditor) editor).isDebuggerEnabled()) { - debugButton.setSelected(true); - } -// debugButton.setRolloverLabel(label); - box.add(debugButton); - addGap(box); - - } - - @Override - public void handleRun(int modifiers) { - boolean shift = (modifiers & InputEvent.SHIFT_MASK) != 0; - if (!shift) { - aEditor.handleRunDevice(); - } else { - aEditor.handleRunEmulator(); - } - } - - - @Override - public void handleStop() { - // TODO Auto-generated method stub - aEditor.handleStop(); - } - - - public void activateExport() { - // TODO added to match the new API in EditorToolbar (activateRun, etc). - } - - - public void deactivateExport() { - // TODO added to match the new API in EditorToolbar (activateRun, etc). - } - - public void activateContinue() { - continueButton.setSelected(true); - repaint(); - } - - public void deactivateContinue() { - continueButton.setSelected(false); - repaint(); - } - - public void activateStep() { - stepButton.setSelected(true); - repaint(); - } - - public void deactivateStep() { - stepButton.setSelected(false); - repaint(); - } -} diff --git a/mode/src/processing/mode/android/AndroidUtil.java b/mode/src/processing/mode/android/AndroidUtil.java deleted file mode 100644 index f73e86dbf..000000000 --- a/mode/src/processing/mode/android/AndroidUtil.java +++ /dev/null @@ -1,347 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2017-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.nio.file.Paths; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.FileVisitResult; -import java.nio.file.attribute.BasicFileAttributes; - -import javax.swing.JEditorPane; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; - -import processing.app.Base; -import processing.app.Messages; -import processing.app.Mode; -import processing.app.Platform; -import processing.app.SketchException; -import processing.app.Util; -import processing.app.exec.ProcessHelper; -import processing.app.exec.ProcessResult; -import processing.app.ui.Toolkit; -import processing.core.PApplet; - -/** - * Some utilities. - */ -public class AndroidUtil { - final static private int FONT_SIZE = Toolkit.zoom(11); - final static private int TEXT_MARGIN = Toolkit.zoom(8); - final static private int TEXT_WIDTH = Toolkit.zoom(300); - - // Creates a message dialog, where the text can contain clickable links. - static public void showMessage(String title, String text) { - if (title == null) title = "Message"; - if (Base.isCommandLine()) { - System.out.println(title + ": " + text); - } else { - String htmlString = " " + - " " + - "

    " + text + "

    "; - JEditorPane pane = new JEditorPane("text/html", htmlString); - pane.addHyperlinkListener(new HyperlinkListener() { - @Override - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { - Platform.openURL(e.getURL().toString()); - } - } - }); - pane.setEditable(false); - JLabel label = new JLabel(); - pane.setBackground(label.getBackground()); - JOptionPane.showMessageDialog(null, pane, title, - JOptionPane.INFORMATION_MESSAGE); - } - } - - static public void writeFile(final File file, String[] lines) { - final PrintWriter writer = PApplet.createWriter(file); - for (String line: lines) writer.println(line); - writer.flush(); - writer.close(); - } - - - static public File createPath(final File parent, final String name) - throws SketchException { - final File result = new File(parent, name); - if (!(result.exists() || result.mkdirs())) { - throw new SketchException("Could not create " + result); - } - return result; - } - - - static public void createFileFromTemplate(final File tmplFile, final File destFile) { - createFileFromTemplate(tmplFile, destFile, null); - } - - - static public void createFileFromTemplate(final File tmplFile, final File destFile, - final HashMap replaceMap) { - PrintWriter pw = PApplet.createWriter(destFile); - String lines[] = PApplet.loadStrings(tmplFile); - for (int i = 0; i < lines.length; i++) { - if (lines[i].indexOf("@@") != -1 && replaceMap != null) { - StringBuilder sb = new StringBuilder(lines[i]); - int index = 0; - for (String key: replaceMap.keySet()) { - String val = replaceMap.get(key); - while ((index = sb.indexOf(key)) != -1) { - sb.replace(index, index + key.length(), val); - } - } - lines[i] = sb.toString(); - } - // explicit newlines to avoid Windows CRLF - pw.print(lines[i] + "\n"); - } - pw.flush(); - pw.close(); - } - - - static public File createSubFolder(File parent, String name) throws IOException { - File newFolder = new File(parent, name); - if (newFolder.exists()) { - String stamp = AndroidMode.getDateStamp(newFolder.lastModified()); - File dest = new File(parent, name + "." + stamp); - boolean result = newFolder.renameTo(dest); - if (!result) { - ProcessHelper mv; - ProcessResult pr; - try { - System.err.println("Cannot rename existing " + name + " folder, resorting to mv/move instead."); - mv = new ProcessHelper("mv", newFolder.getAbsolutePath(), dest.getAbsolutePath()); - pr = mv.execute(); - } catch (InterruptedException e) { - e.printStackTrace(); - return null; - } - if (!pr.succeeded()) { - System.err.println(pr.getStderr()); - Messages.showWarning("Failed to rename", - "Could not rename the old \"" + name + "\" folder.\n" + - "Please delete, close, or rename the folder\n" + - newFolder.getAbsolutePath() + "\n" + - "and try again." , null); - Platform.openFolder(newFolder); - return null; - } - } - } else { - boolean result = newFolder.mkdirs(); - if (!result) { - Messages.showWarning("Folders, folders, folders", - "Could not create the necessary folders to build.\n" + - "Perhaps you have some file permissions to sort out?", null); - return null; - } - } - return newFolder; - } - - - static public void extractFolder(File file, File newPath, boolean setExec) - throws IOException { - extractFolder(file, newPath, setExec, false); - } - - static public void extractFolder(File file, File newPath, boolean setExec, - boolean remRoot) throws IOException { - int BUFFER = 2048; - - ZipFile zip = new ZipFile(file); - Enumeration zipFileEntries = zip.entries(); - - // Process each entry - while (zipFileEntries.hasMoreElements()) { - // grab a zip file entry - ZipEntry entry = zipFileEntries.nextElement(); - String currentEntry = entry.getName(); - - if (remRoot) { - // Remove root folder from path - int idx = currentEntry.indexOf("/"); - if (idx == -1) { - // Let's try the system file separator - // https://stackoverflow.com/a/16485210 - idx = currentEntry.indexOf(File.separator); - } - currentEntry = currentEntry.substring(idx + 1); - } - - File destFile = new File(newPath, currentEntry); - //destFile = new File(newPath, destFile.getName()); - File destinationParent = destFile.getParentFile(); - - // create the parent directory structure if needed - destinationParent.mkdirs(); - - String ext = PApplet.getExtension(currentEntry); - if (setExec && ext.equals("unknown")) { - // On some OS X machines the android binaries lose their executable - // attribute, rendering the mode unusable - destFile.setExecutable(true); - } - - if (!entry.isDirectory()) { - // should preserve permissions - // https://bitbucket.org/atlassian/amps/pull-requests/21/amps-904-preserve-executable-file-status/diff - BufferedInputStream is = new BufferedInputStream(zip.getInputStream(entry)); - int currentByte; - // establish buffer for writing file - byte data[] = new byte[BUFFER]; - - // write the current file to disk - FileOutputStream fos = new FileOutputStream(destFile); - BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER); - - // read and write until last byte is encountered - while ((currentByte = is.read(data, 0, BUFFER)) != -1) { - dest.write(data, 0, currentByte); - } - dest.flush(); - dest.close(); - is.close(); - } - } - zip.close(); - } - - static public void extractClassesJarFromAar(File wearFile, File explodeDir, - File jarFile) throws IOException { - extractClassesJarFromAar(wearFile, explodeDir, jarFile, true); - } - - - static public void extractClassesJarFromAar(File wearFile, File explodeDir, - File jarFile, boolean removeDir) throws IOException { - extractFolder(wearFile, explodeDir, false); - File classFile = new File(explodeDir, "classes.jar"); - Util.copyFile(classFile, jarFile); - Util.removeDir(explodeDir); - } - - - static public File[] getFileList(File folder, String[] names) { - return getFileList(folder, names, null); - } - - static public File[] getFileList(File folder, String[] names, String[] altNames) { - File[] icons = new File[names.length]; - for (int i = 0; i < names.length; i++) { - File f = new File(folder, names[i]); - if (!f.exists() && altNames != null) { - f = new File(folder, altNames[i]); - } - icons[i] = f; - } - return icons; - } - - - static public File[] getFileList(Mode mode, String prefix, String[] names) { - File[] icons = new File[names.length]; - for (int i = 0; i < names.length; i++) { - icons[i] = mode.getContentFile(prefix + names[i]); - } - return icons; - } - - static public boolean allFilesExists(File[] files) { - for (File f: files) { - if (!f.exists()) return false; - } - return true; - } - - - static public boolean noFileExists(File[] files) { - for (File f: files) { - if (f.exists()) return false; - } - return true; - } - - static public void moveDir(File from, File to) { - try { - Files.move(from.toPath(), to.toPath(), StandardCopyOption.REPLACE_EXISTING); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - - static public void copyDir(File from, File to) { - final Path source = Paths.get(from.toURI()); - final Path target = Paths.get(to.toURI()); - - SimpleFileVisitor copyVisitor = new SimpleFileVisitor() { - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - Path resolve = target.resolve(source.relativize(dir)); - if (Files.notExists(resolve)) Files.createDirectories(resolve); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Path resolve = target.resolve(source.relativize(file)); - Files.copy(file, resolve, StandardCopyOption.REPLACE_EXISTING); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) { - System.err.format("Unable to copy: %s: %s%n", file, exc); - return FileVisitResult.CONTINUE; - } - }; - - try { - Files.walkFileTree(source, copyVisitor); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/mode/src/processing/mode/android/Commander.java b/mode/src/processing/mode/android/Commander.java deleted file mode 100644 index 437dab96b..000000000 --- a/mode/src/processing/mode/android/Commander.java +++ /dev/null @@ -1,360 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2008-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; -import java.util.Arrays; - -import processing.app.Base; -import processing.app.Platform; -import processing.app.Preferences; -import processing.app.RunnerListener; -import processing.app.Sketch; -import processing.app.SketchException; -import processing.app.Util; -import processing.app.contrib.ModeContribution; - -/** - * Class to handle running Android mode of Processing from the command line. - * - * @author ostap.andrusiv - */ -public class Commander implements RunnerListener { - static final String helpArg = "--help"; - static final String buildArg = "--build"; - static final String runArg = "--run"; - static final String runArg_DEVICE = "d"; - static final String runArg_EMULATOR = "e"; - static final String targetArg = "--target"; - static final String targetArg_DEBUG = "debug"; - static final String targetArg_RELEASE = "release"; - static final String componentArg = "--component"; - static final String targetArg_FRAGMENT = "fragment"; - static final String targetArg_WALLPAPER = "wallpaper"; - static final String targetArg_WATCHFACE = "watchface"; - static final String targetArg_VR = "vr"; - static final String targetArg_AR = "ar"; - static final String sketchArg = "--sketch="; - static final String forceArg = "--force"; - static final String outputArg = "--output="; - static final String exportApplicationArg = "--export"; - - static final int HELP = -1; - static final int BUILD = 1; - static final int RUN = 2; - static final int EXPORT = 4; - - private AndroidMode androidMode = null; - - private int task = HELP; - - private Sketch sketch; - private PrintStream systemOut; - private PrintStream systemErr; - - private String sketchPath = null; - private File sketchFolder = null; - private String pdePath = null; // path to the .pde file - - private String outputPath = null; - private File outputFolder = null; - - private int appComponent = AndroidBuild.APP; - - private boolean force = false; // replace that no good output folder - private String device = runArg_DEVICE; - private String target = targetArg_DEBUG; - - static public void main(String[] args) { - // Do this early so that error messages go to the console - Base.setCommandLine(); - // init the platform so that prefs and other native code is ready to go - Platform.init(); - - // launch command line handler - Commander commander = new Commander(args); - commander.execute(); - } - - public Commander(String[] args) { - if (processing.app.Base.DEBUG) { - System.out.println(Arrays.toString(args)); - } - // Turns out the output goes as MacRoman or something else useless. - // http://code.google.com/p/processing/issues/detail?id=1418 - try { - systemOut = new PrintStream(System.out, true, "UTF-8"); - systemErr = new PrintStream(System.err, true, "UTF-8"); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - System.exit(1); - } - - parseArgs(args); - - initValues(); - } - - private void parseArgs(String[] args) { - for (String arg : args) { - if (arg.length() == 0) { - // ignore it, just the crappy shell script - } else if (arg.equals(helpArg)) { - // mode already set to HELP - } else if (arg.startsWith(targetArg)) { - target = extractValue(arg, targetArg, targetArg_DEBUG); - } else if (arg.startsWith(componentArg)) { - String compStr = extractValue(arg, targetArg, targetArg_FRAGMENT); - if (compStr.equals(targetArg_FRAGMENT)) { - appComponent = AndroidBuild.APP; - } else if (compStr.equals(targetArg_WALLPAPER)) { - appComponent = AndroidBuild.WALLPAPER; - } else if (compStr.equals(targetArg_WATCHFACE)) { - appComponent = AndroidBuild.WATCHFACE; - } else if (compStr.equals(targetArg_VR)) { - appComponent = AndroidBuild.VR; - } else if (compStr.equals(targetArg_AR)) { - appComponent = AndroidBuild.AR; - } - } else if (arg.equals(buildArg)) { - task = BUILD; - } else if (arg.startsWith(runArg)) { - task = RUN; - device = extractValue(arg, runArg, runArg_DEVICE); - } else if (arg.equals(exportApplicationArg)) { - task = EXPORT; - } else if (arg.startsWith(sketchArg)) { - sketchPath = arg.substring(sketchArg.length()); - sketchFolder = new File(sketchPath); - checkOrQuit(sketchFolder.exists(), sketchFolder + " does not exist.", false); - - File pdeFile = new File(sketchFolder, sketchFolder.getName() + ".pde"); - checkOrQuit(pdeFile.exists(), "Not a valid sketch folder. " + pdeFile + " does not exist.", true); - - pdePath = pdeFile.getAbsolutePath(); - } else if (arg.startsWith(outputArg)) { - outputPath = arg.substring(outputArg.length()); - } else if (arg.equals(forceArg)) { - force = true; - } else { - complainAndQuit("I don't know anything about " + arg + ".", true); - } - } - } - - /** - *
    -   * extractValue("--target=release", "--target", "debug") ==> "release"
    -   * extractValue("--target=",        "--target", "debug") ==> ""
    -   * extractValue("--target",         "--target", "debug") ==> "debug"
    -   * 
    - * - * @param arg - * @param template - * @param def - * @return - */ - private static String extractValue(String arg, String template, String def) { - String result = def; - String withEq = arg.substring(template.length()); - if (withEq.startsWith("=")) { - result = withEq.substring(1); - } - return result; - } - - private void initValues() { - checkOrQuit(outputPath != null, "An output path must be specified.", true); - outputFolder = new File(outputPath); - if (outputFolder.exists()) { - if (force) { - Util.removeDir(outputFolder); - } else { - complainAndQuit("The output folder already exists. " + "Use --force to remove it.", false); - } - } - - Preferences.init(); - Base.locateSketchbookFolder(); - - checkOrQuit(sketchPath != null, "No sketch path specified.", true); - checkOrQuit(!outputPath.equals(sketchPath), "The sketch path and output path cannot be identical.", false); - - androidMode = (AndroidMode) ModeContribution.load(null, Platform.getContentFile("modes/android"), - "processing.mode.android.AndroidMode").getMode(); - androidMode.checkSDK(null); - } - - private void execute() { - if (processing.app.Base.DEBUG) { - systemOut.println("Build status: "); - systemOut.println("Sketch: " + sketchPath); - systemOut.println("Output: " + outputPath); - systemOut.println("Force: " + force); - systemOut.println("Target: " + target); - systemOut.println("Component: " + appComponent); - systemOut.println("==== Task ===="); - systemOut.println("--build: " + (task == BUILD)); - systemOut.println("--run: " + (task == RUN)); - systemOut.println("--export: " + (task == EXPORT)); - systemOut.println(); - } - - if (task == HELP) { - printCommandLine(systemOut); - System.exit(0); - } - - checkOrQuit(outputFolder.mkdirs(), "Could not create the output folder.", false); - - boolean success = false; - - try { - boolean runOnEmu = runArg_EMULATOR.equals(device); - sketch = new Sketch(pdePath, androidMode); - if (task == BUILD || task == RUN) { - AndroidBuild build = new AndroidBuild(sketch, androidMode, appComponent); - build.build(target, ""); - - if (task == RUN) { - AndroidRunner runner = new AndroidRunner(build, this); - runner.launch(runOnEmu ? - Devices.getInstance().getEmulator(build.isWear()) : - Devices.getInstance().getHardware(), build.getAppComponent(), runOnEmu); - } - - success = true; - - } else if (task == EXPORT) { - AndroidBuild build = new AndroidBuild(sketch, androidMode, appComponent); - build.exportProject(); - - success = true; - } - - if (!success) { // error already printed - System.exit(1); - } - - systemOut.println("Finished."); - System.exit(0); - } catch (SketchException re) { - statusError(re); - - } catch (IOException e) { - e.printStackTrace(); - System.exit(1); - } - } - - public void statusNotice(String message) { - systemErr.println(message); - } - - public void statusError(String message) { - systemErr.println(message); - } - - public void statusError(Exception exception) { - if (exception instanceof SketchException) { - SketchException re = (SketchException) exception; - - int codeIndex = re.getCodeIndex(); - if (codeIndex != -1) { - // format the runner exception like emacs - // blah.java:2:10:2:13: Syntax Error: This is a big error message - String filename = sketch.getCode(codeIndex).getFileName(); - int line = re.getCodeLine() + 1; - int column = re.getCodeColumn() + 1; - // if (column == -1) column = 0; - // TODO if column not specified, should just select the whole line. - systemErr.println(filename + ":" + line + ":" + column + ":" + line + ":" + column + ":" + " " - + re.getMessage()); - - } else { // no line number, pass the trace along to the user - exception.printStackTrace(); - } - } else { - exception.printStackTrace(); - } - } - - private void checkOrQuit(boolean condition, String lastWords, boolean schoolEmFirst) { - if (!condition) { - complainAndQuit(lastWords, schoolEmFirst); - } - } - - void complainAndQuit(String lastWords, boolean schoolEmFirst) { - if (schoolEmFirst) { - printCommandLine(systemErr); - } - systemErr.println(lastWords); - System.exit(1); - } - - static void printCommandLine(PrintStream out) { - out.println(); - out.println("Command line edition for Processing " + Base.getVersionName() + " (Android Mode)"); - out.println(); - out.println("--help Show this help text. Congratulations."); - out.println(); - out.println("--sketch= Specify the sketch folder (required)"); - out.println("--output= Specify the output folder (required and"); - out.println(" cannot be the same as the sketch folder.)"); - out.println(); - out.println("--force The sketch will not build if the output"); - out.println(" folder already exists, because the contents"); - out.println(" will be replaced. This option erases the"); - out.println(" folder first. Use with extreme caution!"); - out.println(); - out.println("--target= \"debug\" or \"release\" target."); - out.println(" \"debug\" by default."); - out.println("--build Preprocess and compile a sketch into .apk file."); - out.println("--run= Preprocess, compile, and run a sketch on device"); - out.println(" or emulator. Device will be used by default."); - out.println(); - out.println("--export Export an application."); - out.println(); - } - - @Override - public void startIndeterminate() { - } - - @Override - public void stopIndeterminate() { - } - - @Override - public void statusHalt() { - } - - @Override - public boolean isHalted() { - return false; - } -} diff --git a/mode/src/processing/mode/android/Device.java b/mode/src/processing/mode/android/Device.java deleted file mode 100644 index 590c9167e..000000000 --- a/mode/src/processing/mode/android/Device.java +++ /dev/null @@ -1,488 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import processing.app.Base; -import processing.app.Platform; -import processing.app.RunnerListener; -import processing.app.exec.LineProcessor; -import processing.app.exec.ProcessRegistry; -import processing.app.exec.ProcessResult; -import processing.app.exec.StreamPump; -import processing.core.PApplet; -import processing.mode.android.LogEntry.Severity; - -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - -class Device { - private final Devices env; - private final String id; - private final String features; - private final Set activeProcesses = new HashSet(); - private final Set listeners = - Collections.synchronizedSet(new HashSet()); - -// public static final String APP_STARTED = "android.device.app.started"; -// public static final String APP_ENDED = "android.device.app.ended"; - - private String packageName = ""; - - // mutable state - private Process logcat; - - public Device(final Devices env, final String id) { - this.env = env; - this.id = id; - - // http://android.stackexchange.com/questions/82169/howto-get-devices-features-with-adb - String concat = ""; - try { - final ProcessResult res = adb("shell", "getprop", "ro.build.characteristics"); - for (String line : res) { - concat += "," + line.toLowerCase(); - } - } catch (final Exception e) { - } - this.features = concat; - } - - public void bringLauncherToFront() { - try { - adb("shell", "am", "start", - "-a", "android.intent.action.MAIN", - "-c", "android.intent.category.HOME"); - } catch (final Exception e) { - e.printStackTrace(System.err); - } - } - - public boolean hasFeature(String feature) { - return -1 < features.indexOf(feature); - } - - public String getName() { - String name = ""; - - try { - ProcessResult result = env.getSDK().runADB("-s", id, "shell", "getprop", "ro.product.brand"); - if (result.succeeded()) { - name += result.getStdout() + " "; - } - - result = env.getSDK().runADB("-s", id, "shell", "getprop", "ro.product.model"); - if (result.succeeded()) { - name += result.getStdout(); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - name += " [" + id + "]"; - -// if (hasFeature("watch")) { -// name += " (watch)"; -// } - - return name; - } - - // adb -s emulator-5556 install helloWorld.apk - - // : adb -s HT91MLC00031 install bin/Brightness-debug.apk - // 532 KB/s (190588 bytes in 0.349s) - // pkg: /data/local/tmp/Brightness-debug.apk - // Failure [INSTALL_FAILED_ALREADY_EXISTS] - - // : adb -s HT91MLC00031 install -r bin/Brightness-debug.apk - // 1151 KB/s (190588 bytes in 0.161s) - // pkg: /data/local/tmp/Brightness-debug.apk - // Success - - // safe to just always include the -r (reinstall) flag - public boolean installApp(final AndroidBuild build, final RunnerListener status) { - if (!isAlive()) { - return false; - } - bringLauncherToFront(); - - String apkPath = build.getPathForAPK(); - if (apkPath == null) { - status.statusError("Could not install the sketch."); - System.err.println("The APK file is missing"); - return false; - } - - try { - final ProcessResult installResult = adb("install", "-r", apkPath); - if (!installResult.succeeded()) { - status.statusError("Could not install the sketch."); - System.err.println(installResult); - return false; - } - String errorMsg = null; - for (final String line : installResult) { - if (line.startsWith("Failure")) { - errorMsg = line.substring(8); - - if (line.contains("INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES")) { - boolean removeResult = removeApp(build.getPackageName()); - if (removeResult) return installApp(build, status); - } - - System.err.println(line); - } - } - if (errorMsg == null) { - status.statusNotice("Done installing."); - return true; - } - status.statusError("Error while installing " + errorMsg); - } catch (final IOException e) { - status.statusError(e); - } catch (final InterruptedException e) { - } - return false; - } - - public boolean removeApp(String packageName) throws IOException, InterruptedException { - final ProcessResult removeResult = adb("uninstall", packageName); - - if (!removeResult.succeeded()) { - return false; - } - - return true; - } - - - // different version that actually runs through JDI: - // http://asantoso.wordpress.com/2009/09/26/using-jdb-with-adb-to-debugging-of-android-app-on-a-real-device/ - public boolean launchApp(final String packageName, boolean isDebuggerEnabled) - throws IOException, InterruptedException { - if (!isAlive()) { - return false; - } - ProcessResult pr; - if (isDebuggerEnabled) { - String[] cmd = { - "shell", "am", "start", - "-e", "debug", "true", - "-a", "android.intent.action.MAIN", - "-c", "android.intent.category.LAUNCHER", "-D", - "-n", packageName + "/.MainActivity" - }; - pr = adb(cmd); - }else { - String[] cmd = { - "shell", "am", "start", - "-e", "debug", "true", - "-a", "android.intent.action.MAIN", - "-c", "android.intent.category.LAUNCHER", - "-n", packageName + "/.MainActivity" - }; - pr = adb(cmd); - } -// PApplet.println(cmd); - - if (Base.DEBUG) { - System.out.println(pr.toString()); - } - // Sometimes this shows up on stdout, even though it returns 'success' - // Error type 2 - // android.util.AndroidException: Can't connect to activity manager; is the system running? - if (pr.getStdout().contains("android.util.AndroidException")) { - System.err.println(pr.getStdout()); - return false; - } - return pr.succeeded(); - } - - public void forwardPort(int tcpPort) throws IOException, InterruptedException { - // Start ADB Server - adb("start-server"); - final String[] jdwpcmd = generateAdbCommand("jdwp"); - Process deviceId = Runtime.getRuntime().exec(jdwpcmd); - // Get Process ID from ADB command `adb jdwp` - JDWPProcessor pIDProcessor = new JDWPProcessor(); - new StreamPump(deviceId.getInputStream(), "jdwp: ").addTarget( - pIDProcessor).start(); - new StreamPump(deviceId.getErrorStream(), "jdwperr: ").addTarget( - System.err).start(); - - Thread.sleep(1000); - // forward to tcp port - adb("forward", "tcp:" + tcpPort, "jdwp:" + pIDProcessor.getId()); - } - - private class JDWPProcessor implements LineProcessor { - private int pId; - public void processLine(final String line) { - pId = Integer.parseInt(line); - } - public int getId() { - return pId; - } - } - - public boolean isEmulator() { - return id.startsWith("emulator"); - } - - public void setPackageName(String pkgName) { - packageName = pkgName; - } - - // I/Process ( 9213): Sending signal. PID: 9213 SIG: 9 - private static final Pattern SIG = Pattern - .compile("PID:\\s+(\\d+)\\s+SIG:\\s+(\\d+)"); - - private final List stackTrace = new ArrayList(); - - private class LogLineProcessor implements LineProcessor { - public void processLine(final String line) { - final LogEntry entry = new LogEntry(line); -// System.out.println("***************************************************"); -// System.out.println(line); -// System.out.println(activeProcesses); -// System.out.println(entry.message); - - if (entry.message.startsWith("PROCESSING")) { - // Old start/stop process detection, does not seem to work anymore. - // Should be ok to remove at some point. - if (entry.message.contains("onStart")) { - startProc(entry.source, entry.pid); - } else if (entry.message.contains("onStop")) { - endProc(entry.pid); - } - } else if (packageName != null && !packageName.equals("") && - entry.message.contains("Start proc") && - entry.message.contains(packageName)) { - // Sample message string from logcat when starting process: - // "Start proc 29318:processing.test.sketch001/u0a403 for activity processing.test.sketch001/.MainActivity" - boolean pidFound = false; - - try { - int idx0 = entry.message.indexOf("Start proc") + 11; - int idx1 = entry.message.indexOf(packageName) - 1; - String pidStr = entry.message.substring(idx0, idx1); - int pid = Integer.parseInt(pidStr); - startProc(entry.source, pid); - pidFound = true; - } catch (Exception ex) { } - - if (!pidFound) { - // In some cases (old adb maybe?): - // https://github.com/processing/processing-android/issues/331 - // the process start line is slightly different: - // I/ActivityManager( 648): Start proc processing.test.sketch_170818a for activity processing.test.sketch_170818a/.MainActivity: pid=4256 uid=10175 gids={50175} - try { - int idx0 = entry.message.indexOf("pid=") + 4; - int idx1 = entry.message.indexOf("uid") - 1; - String pidStr = entry.message.substring(idx0, idx1); - int pid = Integer.parseInt(pidStr); - startProc(entry.source, pid); - pidFound = true; - } catch (Exception ex) { } - - if (!pidFound) { - System.err.println("AndroidDevice: cannot find process id, console output will be disabled."); - } - } - } else if (packageName != null && !packageName.equals("") && - entry.message.contains("Killing") && - entry.message.contains(packageName)) { - // Sample message string from logcat when stopping process: - // "Killing 31360:processing.test.test1/u0a403 (adj 900): remove task" - try { - int idx0 = entry.message.indexOf("Killing") + 8; - int idx1 = entry.message.indexOf(packageName) - 1; - String pidStr = entry.message.substring(idx0, idx1); - int pid = Integer.parseInt(pidStr); - endProc(pid); - } catch (Exception ex) { - System.err.println("AndroidDevice: cannot find process id, console output will continue. " + packageName); - } - } else if (entry.source.equals("Process")) { - handleCrash(entry); - } else if (activeProcesses.contains(entry.pid)) { - handleConsole(entry); - } - } - - private void handleCrash(final LogEntry entry) { - final Matcher m = SIG.matcher(entry.message); - if (m.find()) { - final int pid = Integer.parseInt(m.group(1)); - final int signal = Integer.parseInt(m.group(2)); - if (activeProcesses.contains(pid)) { // only report crashes of *our* sketches, por favor - /* - * A crashed sketch first gets a signal 3, which causes the - * "you've crashed" dialog to appear on the device. After - * the user dismisses the dialog, a sig 9 is sent. - * TODO: is it possible to forcibly dismiss the crash dialog? - */ - if (signal == 3) { - endProc(pid); - reportStackTrace(entry); - } - } - } - } - - private void handleConsole(final LogEntry entry) { - final boolean isStackTrace = entry.source.equals("AndroidRuntime") - && entry.severity == Severity.Error; - if (isStackTrace) { - if (!entry.message.startsWith("Uncaught handler")) { - stackTrace.add(entry.message); - System.err.println(entry.message); - } - } else if (entry.source.equals("System.out") - || entry.source.equals("System.err")) { - if (entry.severity.useErrorStream) { - System.err.println(entry.message); - } else { - System.out.println(entry.message); - } - } - } - } - - private void reportStackTrace(final LogEntry entry) { - if (stackTrace.isEmpty()) { - System.err.println("That's weird. Proc " + entry.pid - + " got signal 3, but there's no stack trace."); - } - final List stackCopy = Collections - .unmodifiableList(new ArrayList(stackTrace)); - for (final DeviceListener listener : listeners) { - listener.stackTrace(stackCopy); - } - stackTrace.clear(); - } - - void initialize() throws IOException, InterruptedException { - adb("logcat", "-c"); - final String[] cmd = generateAdbCommand("logcat", "-v", "brief"); - final String title = PApplet.join(cmd, ' '); - logcat = Runtime.getRuntime().exec(cmd); - ProcessRegistry.watch(logcat); - new StreamPump(logcat.getInputStream(), "log: " + title).addTarget( - new LogLineProcessor()).start(); - new StreamPump(logcat.getErrorStream(), "err: " + title).addTarget( - System.err).start(); - new Thread(new Runnable() { - public void run() { - try { - logcat.waitFor(); - } catch (final InterruptedException e) { - System.err - .println("AndroidDevice: logcat process monitor interrupted"); - } finally { - shutdown(); - } - } - }, "AndroidDevice: logcat process monitor").start(); - // System.err.println("Receiving log entries from " + id); - } - - synchronized void shutdown() { - if (!isAlive()) { - return; - } - // System.err.println(id + " is shutting down."); - if (logcat != null) { - logcat.destroy(); - logcat = null; - ProcessRegistry.unwatch(logcat); - } - env.deviceRemoved(this); - if (activeProcesses.size() > 0) { - for (final DeviceListener listener : listeners) { - listener.sketchStopped(); - } - } - listeners.clear(); - } - - synchronized boolean isAlive() { - return logcat != null; - } - - public String getId() { - return id; - } - - public Devices getEnv() { - return env; - } - - private void startProc(final String name, final int pid) { - // System.err.println("Process " + name + " started at pid " + pid); - activeProcesses.add(pid); - } - - private void endProc(final int pid) { - // System.err.println("Process " + pid + " stopped."); - activeProcesses.remove(pid); - for (final DeviceListener listener : listeners) { - listener.sketchStopped(); - } - } - - public void addListener(final DeviceListener listener) { - listeners.add(listener); - } - - public void removeListener(final DeviceListener listener) { - listeners.remove(listener); - } - - private ProcessResult adb(final String... cmd) throws InterruptedException, IOException { - final String[] adbCmd = generateAdbCommand(cmd); - return env.getSDK().runADB(adbCmd); - } - - private String[] generateAdbCommand(final String... cmd) throws IOException { - File toolsPath = env.getSDK().getPlatformToolsFolder(); - File abdPath = Platform.isWindows() ? new File(toolsPath, "adb.exe") : - new File(toolsPath, "adb"); - return PApplet.concat(new String[] { abdPath.getCanonicalPath(), "-s", getId() }, cmd); - } - - @Override - public String toString() { - return "[AndroidDevice " + getId() + "]"; - } - - @Override - public boolean equals(Object obj) { - return ((Device) obj).getId().equals(getId()); - } -} diff --git a/mode/src/processing/mode/android/DeviceListener.java b/mode/src/processing/mode/android/DeviceListener.java deleted file mode 100644 index f6be233be..000000000 --- a/mode/src/processing/mode/android/DeviceListener.java +++ /dev/null @@ -1,30 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import java.util.List; - -public interface DeviceListener { - void stackTrace(final List trace); - - void sketchStopped(); -} diff --git a/mode/src/processing/mode/android/Devices.java b/mode/src/processing/mode/android/Devices.java deleted file mode 100644 index c893f1de0..000000000 --- a/mode/src/processing/mode/android/Devices.java +++ /dev/null @@ -1,399 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import processing.app.exec.ProcessResult; -import processing.mode.android.EmulatorController.State; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.*; - -//import processing.app.EditorConsole; - -/** - *
     AndroidEnvironment env = AndroidEnvironment.getInstance();
    - * AndroidDevice n1 = env.getHardware();
    - * AndroidDevice emu = env.getEmulator();
    - * @author Jonathan Feinberg <jdf@pobox.com> - * - */ -class Devices { - private static final String DEVICE_PERMISSIONS_URL = - "https://developer.android.com/studio/run/device.html"; - - private static final Devices INSTANCE = new Devices(); - - private static final String BT_DEBUG_PORT = "4444"; - - private boolean showPermissionsErrorMessage = true; - - private AndroidSDK sdk; - - private Device selectedDevice; - - public static Devices getInstance() { - return INSTANCE; - } - - private final Map devices = - new ConcurrentHashMap(); - private final ExecutorService deviceLaunchThread = - Executors.newSingleThreadExecutor(); - - public void setSDK(AndroidSDK sdk) { - this.sdk = sdk; - } - - public AndroidSDK getSDK() { - return sdk; - } - - public Device getSelectedDevice() { - return selectedDevice; - } - - public void setSelectedDevice(Device selectedDevice) { - this.selectedDevice = selectedDevice; - } - - public void killAdbServer() { - System.out.print("Shutting down any existing adb server..."); - System.out.flush(); - try { - sdk.runADB("kill-server"); - System.out.println(" Done."); - } catch (final Exception e) { - System.err.println("/nDevices.killAdbServer() failed."); - e.printStackTrace(); - } - } - - public void startAdbServer() { - System.out.print("Starting a new adb server..."); - System.out.flush(); - try { - sdk.runADB("start-server"); - System.out.println(" Done."); - } catch (final Exception e) { - System.err.println("/nDevices.startAdbServer() failed."); - e.printStackTrace(); - } - } - - public void enableBluetoothDebugging() { - final Devices devices = Devices.getInstance(); - java.util.List deviceList = devices.findMultiple(false); - - if (deviceList.size() != 1) { - // There is more than one non-emulator device connected to the computer, - // but don't know which one the watch could be paired to... or the watch - // is already paired to the phone, in which case we don't need to keep - // trying to connect. - return; - } - Device device = deviceList.get(0); - try { - // Try Enable debugging over bluetooth - // http://developer.android.com/training/wearables/apps/bt-debugging.html - sdk.runADB("-s", device.getId(), "forward", "tcp:" + BT_DEBUG_PORT, - "localabstract:/adb-hub"); - sdk.runADB("connect", "127.0.0.1:" + BT_DEBUG_PORT); - } catch (final Exception e) { - e.printStackTrace(); - } - } - - - private Devices() { - if (processing.app.Base.DEBUG) { - System.out.println("Starting up Devices"); - } -// killAdbServer(); - Runtime.getRuntime().addShutdownHook( - new Thread("processing.mode.android.Devices Shutdown") { - public void run() { - //System.out.println("Shutting down Devices"); - //System.out.flush(); - for (Device device : new ArrayList(devices.values())) { - device.shutdown(); - } - // Don't do this, it'll just make Eclipse and others freak out. - //killAdbServer(); - } - }); - } - - - public Future getEmulator(final boolean wear) { - final Callable androidFinder = new Callable() { - public Device call() throws Exception { - return blockingGetEmulator( wear); - } - }; - final FutureTask task = new FutureTask(androidFinder); - deviceLaunchThread.execute(task); - return task; - } - - - private final Device blockingGetEmulator(final boolean wear) { - String port = AVD.getPreferredPort(wear); - Device emu = find(true, port); - if (emu != null) { - return emu; - } - - EmulatorController emuController = EmulatorController.getInstance(wear); - if (emuController.getState() == State.RUNNING) { - // The emulator is in running state, but did not find any emulator device, - // to the most common cause is that it was closed, so we will re-launch it. - emuController.setState(State.NOT_RUNNING); - } - - if (emuController.getState() == State.NOT_RUNNING) { - try { - emuController.launch(sdk, wear); // this blocks until emulator boots - } catch (final IOException e) { - System.err.println("Problem while launching emulator."); - e.printStackTrace(System.err); - return null; - } - } else { - return null; - } - - while (!Thread.currentThread().isInterrupted()) { - // System.err.println("AndroidEnvironment: looking for emulator in loop."); - // System.err.println("AndroidEnvironment: emulatorcontroller state is " - // + emuController.getState()); - if (emuController.getState() == State.NOT_RUNNING) { - System.err.println("Error while starting the emulator. (" + - emuController.getState() + ")"); - return null; - } - emu = find(true, port); - if (emu != null) { - // System.err.println("AndroidEnvironment: returning " + emu.getId() - // + " from loop."); - return emu; - } - try { - Thread.sleep(2000); - } catch (final InterruptedException e) { - System.err.println("Devices: interrupted in loop."); - return null; - } - } - return null; - } - - - private Device find(final boolean wantEmulator, final String port) { - refresh(); - synchronized (devices) { - for (final Device device : devices.values()) { - if (port != null && device.getName().indexOf(port) == -1) continue; - final boolean isEmulator = device.getId().contains("emulator"); - if ((isEmulator && wantEmulator) || (!isEmulator && !wantEmulator)) { - return device; - } - } - } - return null; - } - - public List findMultiple(final boolean wantEmulator) { - List deviceList = new ArrayList(); - - refresh(); - synchronized (devices) { - for (final Device device : devices.values()) { - final boolean isEmulator = device.getId().contains("emulator"); - if ((isEmulator && wantEmulator) || (!isEmulator && !wantEmulator)) { - deviceList.add(device); - } - } - } - - return deviceList; - } - - /** - * @return the first Android hardware device known to be running, or null if there are none. - */ - public Future getHardware() { - Device device = getSelectedDevice(); - if (device == null || !device.isAlive()) device = blockingGetHardware(); - return getHardware(device); - } - - public Future getHardware(final Device device) { - final Callable androidFinder = new Callable() { - public Device call() throws Exception { - return device; - } - }; - final FutureTask task = - new FutureTask(androidFinder); - deviceLaunchThread.execute(task); - return task; - } - - private final Device blockingGetHardware() { - Device hardware = find(false, null); - if (hardware != null) { - return hardware; - } - while (!Thread.currentThread().isInterrupted()) { - try { - Thread.sleep(2000); - } catch (final InterruptedException e) { - return null; - } - hardware = find(false, null); - if (hardware != null) { - return hardware; - } - } - return null; - } - - - private void refresh() { - final List activeDevices = list(); - for (final String deviceId : activeDevices) { - if (!devices.containsKey(deviceId)) { - Device device = new Device(this, deviceId); - addDevice(device); - } - } - } - - - private void addDevice(final Device device) { - // System.err.println("AndroidEnvironment: adding " + device.getId()); - try { - device.initialize(); - if (devices.put(device.getId(), device) != null) { - // TODO: Silently add existing device, this may be indicating, like in - // deviceRemoved() below, different threads trying to add the same - // device. Does not seem to have any negative effect. -// throw new IllegalStateException("Adding " + device -// + ", which already exists!"); - } - } catch (final Exception e) { - System.err.println("While initializing " + device.getId() + ": " + e); - } - } - - - void deviceRemoved(final Device device) { - String id = device.getId(); - if (devices.containsKey(id)) { - devices.remove(device.getId()); - } else { - // TODO: Device already removed, don't throw exception as this seems to - // happen quite often when removing a device, perhaps shutdown() gets - // called twice? -// throw new IllegalStateException("I didn't know about device " -// + device.getId() + "!"); - } - } - - - /** - *

    First line starts "List of devices" - * - *

    When an emulator is started with a debug port, then it shows up - * in the list of devices. - * - *

    List of devices attached - *
    HT91MLC00031 device - *
    emulator-5554 offline - * - *

    List of devices attached - *
    HT91MLC00031 device - *
    emulator-5554 device - * - * @return list of device identifiers - * @throws IOException - */ - public List list() { - if (AndroidSDK.adbDisabled) { - return Collections.emptyList(); - } - - ProcessResult result; - try { -// System.out.println("listing devices 00"); - result = sdk.runADB("devices"); -// System.out.println("listing devices 05"); - } catch (InterruptedException e) { - return Collections.emptyList(); - } catch (IOException e) { - System.err.println("Problem inside Devices.list()"); - e.printStackTrace(); -// System.err.println(e); -// System.err.println("checking devices"); -// e.printStackTrace(EditorConsole.systemErr); - return Collections.emptyList(); - } -// System.out.println("listing devices 10"); - if (!result.succeeded()) { - if (result.getStderr().contains("protocol fault (no status)")) { - System.err.println("bleh: " + result); // THIS IS WORKING - } else { - System.err.println("nope: " + result); - } - return Collections.emptyList(); - } -// System.out.println("listing devices 20"); - - // might read "List of devices attached" - final String stdout = result.getStdout(); - if (!(stdout.contains("List of devices") || stdout.trim().length() == 0)) { - System.err.println(AndroidMode.getTextString("android_devices.error.cannot_get_device_list")); - System.err.println(stdout); - return Collections.emptyList(); - } - -// System.out.println("listing devices 30"); - final List devices = new ArrayList(); - for (final String line : result) { - if (line.contains("\t")) { - final String[] fields = line.split("\t"); - if (fields[1].equals("device")) { - devices.add(fields[0]); - } else if (fields[1].contains("no permissions") && showPermissionsErrorMessage) { - AndroidUtil.showMessage(AndroidMode.getTextString("android_devices.error.no_permissions_title"), - AndroidMode.getTextString("android_devices.error.no_permissions_body", DEVICE_PERMISSIONS_URL)); - showPermissionsErrorMessage = false; - } - } - } - return devices; - } -} diff --git a/mode/src/processing/mode/android/EmulatorController.java b/mode/src/processing/mode/android/EmulatorController.java deleted file mode 100644 index 0e2288591..000000000 --- a/mode/src/processing/mode/android/EmulatorController.java +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.CountDownLatch; - -import processing.app.Base; -import processing.app.exec.*; - -import processing.core.PApplet; - - -class EmulatorController { - public static enum State { - NOT_RUNNING, WAITING_FOR_BOOT, RUNNING - } - - private volatile State state = State.NOT_RUNNING; - - - public State getState() { - return state; - } - - - public void setState(final State state) { - if (processing.app.Base.DEBUG) { - //System.out.println("Emulator state: " + state); - new Exception("setState(" + state + ") called").printStackTrace(System.out); - } - this.state = state; - } - - - /** - * Blocks until emulator is running, or some catastrophe happens. - * @throws IOException - */ - synchronized public void launch(final AndroidSDK sdk, final boolean wear) - throws IOException { - if (state != State.NOT_RUNNING) { - String illegal = "You can't launch an emulator whose state is " + state; - throw new IllegalStateException(illegal); - } - - // Emulator options: - // https://developer.android.com/studio/run/emulator-commandline.html - String avdName = AVD.getName(wear); - - final String portString = AVD.getPreferredPort(wear); - - // We let the emulator decide what's better for hardware acceleration: - // https://developer.android.com/studio/run/emulator-acceleration.html#accel-graphics - String gpuFlag = "auto"; - - final File emulator = sdk.getEmulatorTool(); - if (emulator == null || !emulator.exists()) { - System.err.println("EmulatorController: Emulator is not available."); - return; - } - - final String[] cmd = new String[] { - emulator.getCanonicalPath(), - "-avd", avdName, - "-port", portString, - "-gpu", gpuFlag - }; - - //System.err.println("EmulatorController: Launching emulator"); - if (Base.DEBUG) { - System.out.println(processing.core.PApplet.join(cmd, " ")); - } - //ProcessResult adbResult = new ProcessHelper(adbCmd).execute(); - final Process p = Runtime.getRuntime().exec(cmd); - ProcessRegistry.watch(p); -// new StreamPump(p.getInputStream(), "emulator: ").addTarget(System.out).start(); - - // if we've gotten this far, then we've at least succeeded in finding and - // beginning execution of the emulator, so we are now officially "Launched" - setState(State.WAITING_FOR_BOOT); - - final String title = PApplet.join(cmd, ' '); - - // when this shows up on stdout: - // emulator: ERROR: the cache image is used by another emulator. aborting - // need to reset adb and try again, since it's running but adb is hosed - StreamPump outie = new StreamPump(p.getInputStream(), "out: " + title); - outie.addTarget(new LineProcessor() { - public void processLine(String line) { - if (line.contains("the cache image is used by another emulator")) { - - } else { -// System.out.println(line); - System.out.println(title + ": " + line); - } - } - }); - //new StreamPump(p.getInputStream(), "out: " + title).addTarget(System.out).start(); - - // suppress this warning on OS X, otherwise we're gonna get a lot of reports: - // 2010-04-13 15:26:56.380 emulator[91699:903] Warning once: This - // application, or a library it uses, is using NSQuickDrawView, which has - // been deprecated. Apps should cease use of QuickDraw and move to Quartz. - StreamPump errie = new StreamPump(p.getErrorStream(), "err: " + title); - errie.addTarget(new LineProcessor() { - public void processLine(String line) { - if (line.contains("This application, or a library it uses, is using NSQuickDrawView")) { - // i don't really care - } else { -// System.err.println(line); - System.err.println(title + ": " + line); - } - } - }); - //new StreamPump(p.getErrorStream(), "err: " + title).addTarget(System.err).start(); - - final CountDownLatch latch = new CountDownLatch(1); - new Thread(new Runnable() { - public void run() { - try { - //System.err.println("EmulatorController: Waiting for boot."); - while (state == State.WAITING_FOR_BOOT) { - if (processing.app.Base.DEBUG) { - System.out.println("sleeping for 2 seconds " + new java.util.Date().toString()); - } - Thread.sleep(2000); - //System.out.println("done sleeping"); - ProcessResult result = sdk.runADB("-s", "emulator-" + portString, - "shell", "getprop", "dev.bootcomplete"); - if (result.getStdout().trim().equals("1")) { - setState(State.RUNNING); - return; - } - } - System.err.println("EmulatorController: Emulator never booted. " + state); - } catch (Exception e) { - System.err.println("Exception while waiting for emulator to boot:"); - e.printStackTrace(); - p.destroy(); - } finally { - latch.countDown(); - } - } - }, "EmulatorController: Wait for emulator to boot").start(); - new Thread(new Runnable() { - public void run() { - try { - final int result = p.waitFor(); - // On Windows (as of SDK tools 15), emulator.exe process will terminate - // immediately, even though the emulator itself is launching correctly. - // However on OS X and Linux the process will stay open. - if (result != 0) { - System.err.println("Emulator process exited with status " + result + "."); - setState(State.NOT_RUNNING); - } - } catch (InterruptedException e) { - System.err.println("Emulator was interrupted."); - setState(State.NOT_RUNNING); - } finally { - p.destroy(); - ProcessRegistry.unwatch(p); - } - } - }, "EmulatorController: emulator process waitFor()").start(); - try { - latch.await(); - } catch (final InterruptedException drop) { - System.err.println("Interrupted while waiting for emulator to launch."); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - // whoever called them "design patterns" certainly wasn't a f*king designer. - - public static EmulatorController getInstance(boolean wear) { - if (wear) { - return INSTANCE_WEAR; - } else { - return INSTANCE; - } - } - - private static final EmulatorController INSTANCE = new EmulatorController(); - private static final EmulatorController INSTANCE_WEAR = new EmulatorController(); -} diff --git a/mode/src/processing/mode/android/KeyStoreManager.java b/mode/src/processing/mode/android/KeyStoreManager.java deleted file mode 100644 index d968687ca..000000000 --- a/mode/src/processing/mode/android/KeyStoreManager.java +++ /dev/null @@ -1,343 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2014-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -package processing.mode.android; - -import processing.app.Language; -import processing.app.Messages; -import processing.app.Platform; -import processing.app.ui.Toolkit; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.border.MatteBorder; -import javax.swing.border.TitledBorder; - -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.util.Arrays; - - -@SuppressWarnings("serial") -public class KeyStoreManager extends JFrame { - final static protected int PACKAGE = 0; - final static protected int BUNDLE = 1; - - final static private int BOX_BORDER = Toolkit.zoom(13); - final static private int PASS_BORDER = Toolkit.zoom(15); - final static private int LABEL_WIDTH = Toolkit.zoom(400); - final static private int LABEL_HEIGHT = Toolkit.zoom(100); - final static private int GAP = Toolkit.zoom(13); - - static final String GUIDE_URL = - "https://developer.android.com/studio/publish/app-signing.html"; - - File keyStore; - AndroidEditor editor; - - JPasswordField passwordField; - JPasswordField repeatPasswordField; - - JTextField commonName; - JTextField organizationalUnit; - JTextField organizationName; - JTextField localityName; - JTextField country; - JTextField stateName; - - public KeyStoreManager(final AndroidEditor editor, final int kind) { - super("Android keystore manager"); - this.editor = editor; - - createLayout(kind); - } - - private void createLayout(int kind) { - Container outer = getContentPane(); - outer.removeAll(); - - Box vbox = Box.createVerticalBox(); - vbox.setBorder(new EmptyBorder(BOX_BORDER, BOX_BORDER, BOX_BORDER, BOX_BORDER)); - outer.add(vbox); - - keyStore = AndroidKeyStore.getKeyStore(); - if (keyStore != null) { - showKeystorePasswordLayout(vbox); - } else { - showKeystoreCredentialsLayout(vbox); - } - - vbox.add(Box.createVerticalStrut(GAP)); - - // buttons - JPanel buttons = new JPanel(); - buttons.setAlignmentX(LEFT_ALIGNMENT); - JButton okButton = new JButton(Language.text("prompt.ok")); - Dimension dim = new Dimension(Toolkit.getButtonWidth(), - okButton.getPreferredSize().height); - okButton.setPreferredSize(dim); - okButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (checkRequiredFields()) { - if (keyStore == null) { - try { - AndroidKeyStore.generateKeyStore(new String(passwordField.getPassword()), - commonName.getText(), organizationalUnit.getText(), organizationName.getText(), - localityName.getText(), stateName.getText(), country.getText()); - - setVisible(false); - if (kind == KeyStoreManager.BUNDLE) { - editor.startExportBundle(new String(passwordField.getPassword())); - } else { - editor.startExportPackage(new String(passwordField.getPassword())); - } - } catch (Exception e1) { - e1.printStackTrace(); - } - } else { - setVisible(false); - if (kind == KeyStoreManager.BUNDLE) { - editor.startExportBundle(new String(passwordField.getPassword())); - } else { - editor.startExportPackage(new String(passwordField.getPassword())); - } - } - } - } - }); - okButton.setEnabled(true); - - JButton cancelButton = new JButton(Language.text("prompt.cancel")); - cancelButton.setPreferredSize(dim); - cancelButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - setVisible(false); - } - }); - cancelButton.setEnabled(true); - - JButton resetKeystoreButton = new JButton(AndroidMode.getTextString("keystore_manager.reset_password")); - dim = new Dimension(Toolkit.getButtonWidth()*2, - resetKeystoreButton.getPreferredSize().height); - resetKeystoreButton.setPreferredSize(dim); - resetKeystoreButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - setVisible(false); - int result = Messages.showYesNoQuestion(editor, AndroidMode.getTextString("keystore_manager.dialog.reset_keyboard_title"), - AndroidMode.getTextString("keystore_manager.dialog.reset_keyboard_body_part1"), - AndroidMode.getTextString("keystore_manager.dialog.reset_keyboard_body_part2")); - - if (result == JOptionPane.NO_OPTION) { - setVisible(true); - } else { - if (!AndroidKeyStore.resetKeyStore()) { - Messages.showWarning(AndroidMode.getTextString("keystore_manager.warn.cannot_remove_keystore_title"), - AndroidMode.getTextString("keystore_manager.warn.cannot_remove_keystore_body")); - setVisible(true); - } else { - keyStore = null; - createLayout(kind); - } - } - } - }); - resetKeystoreButton.setEnabled(true); - - // think different, biznatchios! - if (Platform.isMacOS()) { - buttons.add(cancelButton); - - if (keyStore != null) buttons.add(resetKeystoreButton); -// buttons.add(Box.createHorizontalStrut(8)); - buttons.add(okButton); - } else { - buttons.add(okButton); - - if (keyStore != null) buttons.add(resetKeystoreButton); -// buttons.add(Box.createHorizontalStrut(8)); - buttons.add(cancelButton); - } -// buttons.setMaximumSize(new Dimension(300, buttons.getPreferredSize().height)); - vbox.add(buttons); - - JRootPane root = getRootPane(); - root.setDefaultButton(okButton); - ActionListener disposer = new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - setVisible(false); - } - }; - Toolkit.registerWindowCloseKeys(root, disposer); - Toolkit.setIcon(this); - - pack(); - /* - Dimension screen = Toolkit.getScreenSize(); - Dimension windowSize = getSize(); - setLocation((screen.width - windowSize.width) / 2, - (screen.height - windowSize.height) / 2); - */ - setLocationRelativeTo(null); - setVisible(true); - } - - private void showKeystorePasswordLayout(Box pain) { - passwordField = new JPasswordField(15); - JLabel passwordLabel = new JLabel("" + AndroidMode.getTextString("keystore_manager.password_label") + " "); - passwordLabel.setLabelFor(passwordField); - - JPanel textPane = new JPanel(new FlowLayout(FlowLayout.TRAILING)); - textPane.add(passwordLabel); - textPane.add(passwordField); - textPane.setAlignmentX(LEFT_ALIGNMENT); - pain.add(textPane); - } - - private boolean checkRequiredFields() { - if (passwordField.getPassword().length > 5) { - if (keyStore != null) return true; - - if (Arrays.equals(passwordField.getPassword(), repeatPasswordField.getPassword())) { - return true; - } else { - Messages.showWarning(AndroidMode.getTextString("keystore_manager.warn.password_missmatch_title"), - AndroidMode.getTextString("keystore_manager.warn.password_missmatch_body")); - return false; - } - } else { - Messages.showWarning(AndroidMode.getTextString("keystore_manager.warn.short_password_title"), - AndroidMode.getTextString("keystore_manager.warn.short_password_body")); - return false; - } - } - - private void showKeystoreCredentialsLayout(Box box) { - String labelText = AndroidMode.getTextString("keystore_manager.top_label"); - JLabel textarea = new JLabel(labelText); - textarea.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT)); - textarea.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - Platform.openURL(GUIDE_URL); - } - }); - textarea.setAlignmentX(LEFT_ALIGNMENT); - box.add(textarea); - - // password field - passwordField = new JPasswordField(15); - JLabel passwordLabel = new JLabel("" + AndroidMode.getTextString("keystore_manager.password_label") + " "); - passwordLabel.setLabelFor(passwordField); - - JPanel textPane = new JPanel(new FlowLayout(FlowLayout.TRAILING)); - textPane.add(passwordLabel); - textPane.add(passwordField); - textPane.setAlignmentX(LEFT_ALIGNMENT); - box.add(textPane); - - // repeat password field - repeatPasswordField = new JPasswordField(15); - JLabel repeatPasswordLabel = new JLabel("" + AndroidMode.getTextString("keystore_manager.repeat_password_label") + " "); - repeatPasswordLabel.setLabelFor(passwordField); - - textPane = new JPanel(new FlowLayout(FlowLayout.TRAILING)); - textPane.add(repeatPasswordLabel); - textPane.add(repeatPasswordField); - textPane.setAlignmentX(LEFT_ALIGNMENT); - textPane.setBorder(new EmptyBorder(0, 0, PASS_BORDER, 0)); - box.add(textPane); - - MatteBorder mb = new MatteBorder(1, 0, 0, 0, Color.LIGHT_GRAY); - TitledBorder tb = new TitledBorder(mb, AndroidMode.getTextString("keystore_manager.issuer_credentials_header"), TitledBorder.LEFT, TitledBorder.DEFAULT_POSITION); - JPanel separatorPanel = new JPanel(); - separatorPanel.setBorder(tb); - box.add(separatorPanel); - - // common name (CN) - commonName = new JTextField(15); - JLabel commonNameLabel = new JLabel(AndroidMode.getTextString("keystore_manager.common_name_label")); - commonNameLabel.setLabelFor(commonName); - - textPane = new JPanel(new FlowLayout(FlowLayout.TRAILING)); - textPane.add(commonNameLabel); - textPane.add(commonName); - textPane.setAlignmentX(LEFT_ALIGNMENT); - box.add(textPane); - - // organizational unit (OU) - organizationalUnit = new JTextField(15); - JLabel organizationalUnitLabel = new JLabel(AndroidMode.getTextString("keystore_manager.organizational_unitl_label")); - organizationalUnitLabel.setLabelFor(organizationalUnit); - - textPane = new JPanel(new FlowLayout(FlowLayout.TRAILING)); - textPane.add(organizationalUnitLabel); - textPane.add(organizationalUnit); - textPane.setAlignmentX(LEFT_ALIGNMENT); - box.add(textPane); - - // organization name (O) - organizationName = new JTextField(15); - JLabel organizationNameLabel = new JLabel(AndroidMode.getTextString("keystore_manager.organization_name_label")); - organizationNameLabel.setLabelFor(organizationName); - - textPane = new JPanel(new FlowLayout(FlowLayout.TRAILING)); - textPane.add(organizationNameLabel); - textPane.add(organizationName); - textPane.setAlignmentX(LEFT_ALIGNMENT); - box.add(textPane); - - // locality name (L) - localityName = new JTextField(15); - JLabel localityNameLabel = new JLabel(AndroidMode.getTextString("keystore_manager.city_name_label")); - localityNameLabel.setLabelFor(localityName); - - textPane = new JPanel(new FlowLayout(FlowLayout.TRAILING)); - textPane.add(localityNameLabel); - textPane.add(localityName); - textPane.setAlignmentX(LEFT_ALIGNMENT); - box.add(textPane); - - // state name (S) - stateName = new JTextField(15); - JLabel stateNameLabel = new JLabel(AndroidMode.getTextString("keystore_manager.state_name_label")); - stateNameLabel.setLabelFor(stateName); - - textPane = new JPanel(new FlowLayout(FlowLayout.TRAILING)); - textPane.add(stateNameLabel); - textPane.add(stateName); - textPane.setAlignmentX(LEFT_ALIGNMENT); - box.add(textPane); - - // country (C) - country = new JTextField(15); - JLabel countryLabel = new JLabel(AndroidMode.getTextString("keystore_manager.country_code_label")); - countryLabel.setLabelFor(country); - - textPane = new JPanel(new FlowLayout(FlowLayout.TRAILING)); - textPane.add(countryLabel); - textPane.add(country); - textPane.setAlignmentX(LEFT_ALIGNMENT); - box.add(textPane); - } -} diff --git a/mode/src/processing/mode/android/Keys.java b/mode/src/processing/mode/android/Keys.java deleted file mode 100644 index 02b796227..000000000 --- a/mode/src/processing/mode/android/Keys.java +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2010-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -package processing.mode.android; - -import javax.swing.*; - -import processing.app.ui.Editor; - - -@SuppressWarnings("serial") -public class Keys extends JFrame { - Editor editor; - - public Keys(Editor editor) { - this.editor = editor; - setVisible(true); - } -} diff --git a/mode/src/processing/mode/android/LogEntry.java b/mode/src/processing/mode/android/LogEntry.java deleted file mode 100644 index e4b0fd51c..000000000 --- a/mode/src/processing/mode/android/LogEntry.java +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -package processing.mode.android; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -class LogEntry { - public static enum Severity { - Verbose(false), Debug(false), Info(false), Warning(true), Error(true), Fatal( - true); - public final boolean useErrorStream; - - private Severity(final boolean useErrorStream) { - this.useErrorStream = useErrorStream; - } - - private static Severity fromChar(final char c) { - if (c == 'V') { - return Verbose; - } else if (c == 'D') { - return Debug; - } else if (c == 'I') { - return Info; - } else if (c == 'W') { - return Warning; - } else if (c == 'E') { - return Error; - } else if (c == 'F') { - return Fatal; - } else { - throw new IllegalArgumentException("I don't know how to interpret '" - + c + "' as a log severity"); - } - } - } - - public final Severity severity; - public final String source; - public final int pid; - public final String message; - - private static final Pattern PARSER = Pattern - .compile("^([VDIWEF])/([^\\(\\s]+)\\s*\\(\\s*(\\d+)\\): (.+)$"); - - public LogEntry(final String line) { - final Matcher m = PARSER.matcher(line); - if (!m.matches()) { - throw new RuntimeException("I can't understand log entry\n" + line); - } - this.severity = Severity.fromChar(m.group(1).charAt(0)); - this.source = m.group(2); - this.pid = Integer.parseInt(m.group(3)); - this.message = m.group(4); - } - - @Override - public String toString() { - return severity + "/" + source + "(" + pid + "): " + message; - } -} diff --git a/mode/src/processing/mode/android/Manifest.java b/mode/src/processing/mode/android/Manifest.java deleted file mode 100644 index 856a43c4a..000000000 --- a/mode/src/processing/mode/android/Manifest.java +++ /dev/null @@ -1,446 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2010-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package processing.mode.android; - -import org.xml.sax.SAXException; -import processing.app.Messages; -import processing.app.Sketch; -import processing.core.PApplet; -import processing.data.XML; - -import javax.xml.parsers.ParserConfigurationException; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.HashMap; - -/** - * Class encapsulating the manifest file associated with a Processing sketch - * in the Android mode. - * - */ -public class Manifest { - static final String MANIFEST_XML = "AndroidManifest.xml"; - - static final String MANIFEST_ERROR_TITLE = "Error handling " + MANIFEST_XML; - static final String MANIFEST_ERROR_MESSAGE = - "Errors occurred while reading or writing " + MANIFEST_XML + ",\n" + - "which means lots of things are likely to stop working properly.\n" + - "To prevent losing any data, it's recommended that you use “Save As”\n" + - "to save a separate copy of your sketch, and then restart Processing."; - - static private final String[] MANIFEST_TEMPLATE = { - "AppManifest.xml.tmpl", - "WallpaperManifest.xml.tmpl", - "WatchFaceManifest.xml.tmpl", - "VRManifest.xml.tmpl", - "ARManifest.xml.tmpl" - }; - - // Default base package name, user need to change when exporting package. - static final String BASE_PACKAGE = "processing.test"; - - static final String PERMISSION_PREFIX = "android.permission."; - - private Sketch sketch; - private int appComp; - private File modeFolder; - - /** the manifest data read from the file */ - private XML xml; - - - public Manifest(Sketch sketch, int appComp, File modeFolder, boolean forceNew) { - this.sketch = sketch; - this.appComp = appComp; - this.modeFolder = modeFolder; - load(forceNew); - } - - - private String defaultPackageName() { - return BASE_PACKAGE + "." + sketch.getName().toLowerCase(); - } - - - private String defaultVersionCode() { - return "1"; - } - - - private String defaultVersionName() { - return "1.0"; - } - - - // called by other classes who want an actual package name - // internally, we'll figure this out ourselves whether it's filled or not - public String getPackageName() { - String pkg = xml.getString("package"); - return pkg.length() == 0 ? defaultPackageName() : pkg; - } - - - public String getVersionCode() { - String code = xml.getString("android:versionCode"); - return code.length() == 0 ? defaultVersionCode() : code; - } - - - public String getVersionName() { - String name = xml.getString("android:versionName"); - return name.length() == 0 ? defaultVersionName() : name; - } - - - public void setPackageName(String packageName) { - xml.setString("package", packageName); - save(); - } - - - public String[] getPermissions() { - XML[] elements = xml.getChildren("uses-permission"); - int count = elements.length; - String[] names = new String[count]; - for (int i = 0; i < count; i++) { - String tmp = elements[i].getString("android:name"); - if (tmp.indexOf("android.permission") == 0) { - // Standard permission, remove perfix - int idx = tmp.lastIndexOf("."); - names[i] = tmp.substring(idx + 1); - } else { - // Non-standard permission (for example, wearables) - // Store entire name. - names[i] = tmp; - } - } - return names; - } - - - public void setPermissions(String[] names) { - boolean hasWakeLock = false; - boolean hasVibrate = false; - boolean hasReadExtStorage = false; - boolean hasCameraAccess = false; - - // Remove all the old permissions... - for (XML kid : xml.getChildren("uses-permission")) { - String name = kid.getString("android:name"); - - // ...except the ones for watch faces and VR apps. - if (appComp == AndroidBuild.WATCHFACE && name.equals(PERMISSION_PREFIX + "WAKE_LOCK")) { - hasWakeLock = true; - continue; - } - if (appComp == AndroidBuild.VR && name.equals(PERMISSION_PREFIX + "VIBRATE")) { - hasVibrate = true; - continue; - } - if (appComp == AndroidBuild.VR && name.equals(PERMISSION_PREFIX + "READ_EXTERNAL_STORAGE")) { - hasReadExtStorage = true; - continue; - } - if (appComp == AndroidBuild.AR && name.equals(PERMISSION_PREFIX + "CAMERA")) { - hasCameraAccess = true; - continue; - } - - // Don't remove non-standard permissions, such as - // com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA - // because these are set manually by the user. - if (-1 < name.indexOf("com.google.android")) continue; - xml.removeChild(kid); - } - - // ...and add the new permissions back - for (String name : names) { - - // Don't add required permissions for watch faces and VR again... - if (appComp == AndroidBuild.WATCHFACE && name.equals("WAKE_LOCK")) continue; - if (appComp == AndroidBuild.VR && name.equals("VIBRATE")) continue; - if (appComp == AndroidBuild.VR && name.equals("READ_EXTERNAL_STORAGE")) continue; - if (appComp == AndroidBuild.AR && name.equals(PERMISSION_PREFIX + "CAMERA")) continue; - - XML newbie = xml.addChild("uses-permission"); - if (-1 < name.indexOf(".")) { - // Permission string contains path - newbie.setString("android:name", name); - } else { - newbie.setString("android:name", PERMISSION_PREFIX + name); - } - } - - // ...unless they were initially missing. - if (appComp == AndroidBuild.WATCHFACE && !hasWakeLock) { - xml.addChild("uses-permission"). - setString("android:name", PERMISSION_PREFIX + "WAKE_LOCK"); - } - if (appComp == AndroidBuild.VR && !hasVibrate) { - xml.addChild("uses-permission"). - setString("android:name", PERMISSION_PREFIX + "VIBRATE"); - } - if (appComp == AndroidBuild.VR && !hasReadExtStorage) { - xml.addChild("uses-permission"). - setString("android:name", PERMISSION_PREFIX + "READ_EXTERNAL_STORAGE"); - } - if (appComp == AndroidBuild.AR && !hasCameraAccess) { - xml.addChild("uses-permission"). - setString("android:name", PERMISSION_PREFIX + "CAMERA"); - } - - save(); - } - - - private void fixPermissions(XML mf) { - boolean hasWakeLock = false; - boolean hasVibrate = false; - boolean hasReadExtStorage = false; - boolean hasCameraAccess = false; - for (XML kid : mf.getChildren("uses-permission")) { - String name = kid.getString("android:name"); - if (appComp == AndroidBuild.WATCHFACE && name.equals(PERMISSION_PREFIX + "WAKE_LOCK")) { - hasWakeLock = true; - continue; - } - if (appComp == AndroidBuild.VR && name.equals(PERMISSION_PREFIX + "VIBRATE")) { - hasVibrate = true; - continue; - } - if (appComp == AndroidBuild.VR && name.equals(PERMISSION_PREFIX + "READ_EXTERNAL_STORAGE")) { - hasReadExtStorage = true; - continue; - } - if (appComp == AndroidBuild.AR && name.equals(PERMISSION_PREFIX + "CAMERA")) { - hasCameraAccess = true; - continue; - } - - if (appComp == AndroidBuild.AR && !hasCameraAccess) { - mf.addChild("uses-permission"). - setString("android:name", PERMISSION_PREFIX + "CAMERA"); - } - } - if (appComp == AndroidBuild.WATCHFACE && !hasWakeLock) { - mf.addChild("uses-permission"). - setString("android:name", PERMISSION_PREFIX + "WAKE_LOCK"); - } - if (appComp == AndroidBuild.VR && !hasVibrate) { - mf.addChild("uses-permission"). - setString("android:name", PERMISSION_PREFIX + "VIBRATE"); - } - if (appComp == AndroidBuild.VR && !hasReadExtStorage) { - mf.addChild("uses-permission"). - setString("android:name", PERMISSION_PREFIX + "READ_EXTERNAL_STORAGE"); - } - } - - - private void writeBlankManifest(final File xmlFile, final int appComp) { - File xmlTemplate = new File(modeFolder, "templates/" + MANIFEST_TEMPLATE[appComp]); - HashMap replaceMap = new HashMap(); - AndroidUtil.createFileFromTemplate(xmlTemplate, xmlFile, replaceMap); - } - - - /** - * Save a new version of the manifest info to the build location. - * Also fill in any missing attributes that aren't yet set properly. - */ - protected void writeCopy(File file, String className) throws IOException { - // write a copy to the build location - save(file); - - // load the copy from the build location and start messing with it - XML mf = null; - try { - mf = new XML(file); - - // package name, or default - String p = mf.getString("package").trim(); - if (p.length() == 0) { - mf.setString("package", defaultPackageName()); - } - - // app name and label, or the class name - XML app = mf.getChild("application"); - String label = app.getString("android:label"); - if (label.length() == 0) { - app.setString("android:label", className); - } - - // Services need the label also in the service section - if (appComp == AndroidBuild.WALLPAPER || appComp == AndroidBuild.WATCHFACE) { - XML serv = app.getChild("service"); - label = serv.getString("android:label"); - if (label.length() == 0) { - serv.setString("android:label", className); - } - } - - // Make sure that the required permissions for watch faces, AR and VR apps are - // included. - if (appComp == AndroidBuild.WATCHFACE || appComp == AndroidBuild.VR|| appComp == AndroidBuild.AR) { - fixPermissions(mf); - } - - PrintWriter writer = PApplet.createWriter(file); - writer.print(mf.format(4)); - writer.flush(); - writer.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - - protected void load(boolean forceNew) { - File manifestFile = getManifestFile(); - if (manifestFile.exists()) { - try { - xml = new XML(manifestFile); - - boolean saveOld = false; - - XML app = xml.getChild("application"); - String icon = app.getString("android:icon"); - if (icon.equals("@drawable/icon")) { - // Manifest file generated with older version of the mode, replace icon and save - app.setString("android:icon", "@mipmap/ic_launcher"); - saveOld = true; - } - - XML activity = app.getChild("activity"); - XML service = app.getChild("service"); - if (activity != null && activity.getString("android:name").equals(".MainActivity")) { - addExportedAttrib(activity); - saveOld = true; - } - if (service != null && service.getString("android:name").equals(".MainService")) { - addExportedAttrib(service); - saveOld = true; - } - - XML usesSDK = xml.getChild("uses-sdk"); - if (usesSDK != null) { - // Manifest file generated with older version of the mode, uses-sdk is no longer needed in manifest - xml.removeChild(usesSDK); - saveOld = true; - } - - if (saveOld && !forceNew) save(); - - } catch (Exception e) { - e.printStackTrace(); - System.err.println("Problem reading AndroidManifest.xml, creating a new version"); - - // remove the old manifest file, rename it with date stamp - long lastModified = manifestFile.lastModified(); - String stamp = AndroidMode.getDateStamp(lastModified); - File dest = new File(sketch.getFolder(), MANIFEST_XML + "." + stamp); - boolean moved = manifestFile.renameTo(dest); - if (!moved) { - System.err.println("Could not move/rename " + manifestFile.getAbsolutePath()); - System.err.println("You'll have to move or remove it before continuing."); - return; - } - } - } - - String[] permissionNames = null; - String pkgName = null; - String versionCode = null; - String versionName = null; - if (xml != null && forceNew) { - permissionNames = getPermissions(); - pkgName = getPackageName(); - versionCode = getVersionCode(); - versionName = getVersionName(); - xml = null; - } - - if (xml == null) { - writeBlankManifest(manifestFile, appComp); - try { - xml = new XML(manifestFile); - if (permissionNames != null) { - setPermissions(permissionNames); - } - if (pkgName != null) { - xml.setString("package", pkgName); - } - if (versionCode != null) { - xml.setString("android:versionCode", versionCode); - } - if (versionName != null) { - xml.setString("android:versionName", versionName); - } - } catch (FileNotFoundException e) { - System.err.println("Could not read " + manifestFile.getAbsolutePath()); - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } - } - if (xml == null) { - Messages.showWarning(AndroidMode.getTextString("manifest.warn.cannot_handle_file_title", MANIFEST_XML), - AndroidMode.getTextString("manifest.warn.cannot_handle_file_body", MANIFEST_XML)); - } - } - - protected void addExportedAttrib(XML child) { - if (!child.hasAttribute("android:exported")) { - // Manifest file generated with older version of the mode, missing android:exported attributed - child.setString("android:exported", "true"); - } - } - - protected void save() { - save(getManifestFile()); - } - - - /** - * Save to the sketch folder, so that it can be copied in later. - */ - protected void save(File file) { - PrintWriter writer = PApplet.createWriter(file); -// xml.write(writer); - writer.print(xml.format(4)); - writer.flush(); - writer.close(); - } - - - private File getManifestFile() { - return new File(sketch.getFolder(), MANIFEST_XML); - } -} diff --git a/mode/src/processing/mode/android/Pair.java b/mode/src/processing/mode/android/Pair.java deleted file mode 100644 index 04ef7ea81..000000000 --- a/mode/src/processing/mode/android/Pair.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - package processing.mode.android; - -/** - * Pair of two elements. - */ -public final class Pair { - private final A mFirst; - private final B mSecond; - private Pair(A first, B second) { - mFirst = first; - mSecond = second; - } - public static Pair create(A first, B second) { - return new Pair(first, second); - } - public A getFirst() { - return mFirst; - } - public B getSecond() { - return mSecond; - } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mFirst == null) ? 0 : mFirst.hashCode()); - result = prime * result + ((mSecond == null) ? 0 : mSecond.hashCode()); - return result; - } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - @SuppressWarnings("rawtypes") - Pair other = (Pair) obj; - if (mFirst == null) { - if (other.mFirst != null) { - return false; - } - } else if (!mFirst.equals(other.mFirst)) { - return false; - } - if (mSecond == null) { - if (other.mSecond != null) { - return false; - } - } else if (!mSecond.equals(other.mSecond)) { - return false; - } - return true; - } -} \ No newline at end of file diff --git a/mode/src/processing/mode/android/Permissions.java b/mode/src/processing/mode/android/Permissions.java deleted file mode 100644 index cc1ea0a2f..000000000 --- a/mode/src/processing/mode/android/Permissions.java +++ /dev/null @@ -1,566 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012-21 The Processing Foundation - Copyright (c) 2010-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -package processing.mode.android; - -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.event.*; -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; - -import javax.swing.*; -import javax.swing.border.*; -import javax.swing.event.*; - -import processing.app.Language; -import processing.app.Platform; -import processing.app.Sketch; -import processing.app.ui.Toolkit; - - -@SuppressWarnings("serial") -public class Permissions extends JFrame { - static final String GUIDE_URL = - "https://developer.android.com/training/articles/security-tips.html#Permissions"; - - static final int BORDER_HORIZ = Toolkit.zoom(5); - static final int BORDER_VERT = Toolkit.zoom(3); - static final int CELL_HEIGHT = Toolkit.zoom(20); - static final int BORDER = Toolkit.zoom(13); - static final int TEXT_WIDTH = Toolkit.zoom(400); - static final int TEXT_HEIGHT = Toolkit.zoom(80); - static final int URL_WIDTH = Toolkit.zoom(400); - static final int URL_HEIGHT = Toolkit.zoom(30); - static final int DESC_WIDTH = Toolkit.zoom(400); - static final int DESC_HEIGHT = Toolkit.zoom(50); - static final int GAP = Toolkit.zoom(8); - - JScrollPane permissionScroller; - JList permissionList; - JLabel descriptionLabel; - Sketch sketch; - - int appComp; - - File modeFolder; - - - public Permissions(Sketch sketch, int appComp, File modeFolder) { - super("Android Permissions Selector"); - this.appComp = appComp; - this.sketch = sketch; - this.modeFolder = modeFolder; - - permissionList = new CheckBoxList(); - permissionList.addListSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent e) { - if (e.getValueIsAdjusting() == false) { - int index = permissionList.getSelectedIndex(); - if (index == -1) { - descriptionLabel.setText(""); - } else { - descriptionLabel.setText("" + description[index] + ""); - } - } - } - }); - permissionList.setFixedCellHeight(CELL_HEIGHT); - permissionList.setBorder(new EmptyBorder(BORDER_VERT, BORDER_HORIZ, - BORDER_VERT, BORDER_HORIZ)); - - DefaultListModel model = new DefaultListModel(); - permissionList.setModel(model); - for (String item : title) { - model.addElement(new JCheckBox(item)); - } - - permissionScroller = - new JScrollPane(permissionList, - ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, - ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - permissionList.setVisibleRowCount(12); - permissionList.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { - if (e.getKeyChar() == ' ') { - int index = permissionList.getSelectedIndex(); - JCheckBox checkbox = - permissionList.getModel().getElementAt(index); - checkbox.setSelected(!checkbox.isSelected()); - permissionList.repaint(); - } - } - }); - - Container outer = getContentPane(); - Box vbox = Box.createVerticalBox(); - vbox.setBorder(new EmptyBorder(BORDER, BORDER, BORDER, BORDER)); - outer.add(vbox); - - String labelText = AndroidMode.getTextString("permissions.dialog.label"); - String urlText = AndroidMode.getTextString("permissions.dialog.url", GUIDE_URL); - JLabel textarea = new JLabel(labelText); - JLabel urlarea = new JLabel(urlText); - textarea.setPreferredSize(new Dimension(TEXT_WIDTH, TEXT_HEIGHT)); - urlarea.setPreferredSize(new Dimension(URL_WIDTH, URL_HEIGHT)); - urlarea.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - Platform.openURL(GUIDE_URL); - } - }); - urlarea.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); - textarea.setAlignmentX(LEFT_ALIGNMENT); - urlarea.setAlignmentX(LEFT_ALIGNMENT); - vbox.add(textarea); - vbox.add(urlarea); - - permissionScroller.setAlignmentX(LEFT_ALIGNMENT); - vbox.add(permissionScroller); - vbox.add(Box.createVerticalStrut(GAP)); - - descriptionLabel = new JLabel(); - descriptionLabel.setPreferredSize(new Dimension(DESC_WIDTH, DESC_HEIGHT)); - descriptionLabel.setVerticalAlignment(SwingConstants.TOP); - descriptionLabel.setAlignmentX(LEFT_ALIGNMENT); - vbox.add(descriptionLabel); - vbox.add(Box.createVerticalStrut(GAP)); - - JPanel buttons = new JPanel(); - buttons.setAlignmentX(LEFT_ALIGNMENT); - JButton okButton = new JButton(Language.text("prompt.ok")); - Dimension dim = new Dimension(Toolkit.getButtonWidth(), - okButton.getPreferredSize().height); - okButton.setPreferredSize(dim); - okButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - saveSelections(); - setVisible(false); - } - }); - okButton.setEnabled(true); - - JButton cancelButton = new JButton(Language.text("prompt.cancel")); - cancelButton.setPreferredSize(dim); - cancelButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - setVisible(false); - } - }); - cancelButton.setEnabled(true); - - // think different, biznatchios! - if (Platform.isMacOS()) { - buttons.add(cancelButton); - buttons.add(okButton); - } else { - buttons.add(okButton); - buttons.add(cancelButton); - } - vbox.add(buttons); - - JRootPane root = getRootPane(); - root.setDefaultButton(okButton); - ActionListener disposer = new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - setVisible(false); - } - }; - Toolkit.registerWindowCloseKeys(root, disposer); - Toolkit.setIcon(this); - - pack(); - - Dimension screen = Toolkit.getScreenSize(); - Dimension windowSize = getSize(); - - setLocation((screen.width - windowSize.width) / 2, - (screen.height - windowSize.height) / 2); - - Manifest mf = new Manifest(sketch, appComp, modeFolder, false); - setSelections(mf.getPermissions()); - - // show the window and get to work - setVisible(true); - } - - - @SuppressWarnings("rawtypes") - protected void setSelections(String[] sel) { -// processing.core.PApplet.println("permissions are:"); -// processing.core.PApplet.println(sel); - HashMap map = new HashMap(); - for (String s : sel) { - map.put(s, new Object()); - } - DefaultListModel model = (DefaultListModel) permissionList.getModel(); - for (int i = 0; i < count; i++) { - JCheckBox box = (JCheckBox) model.get(i); -// System.out.println(map.containsKey(box.getText()) + " " + box.getText()); - box.setSelected(map.containsKey(box.getText())); - } - } - - - @SuppressWarnings("rawtypes") - protected String[] getSelections() { - ArrayList sel = new ArrayList(); - DefaultListModel model = (DefaultListModel) permissionList.getModel(); - for (int i = 0; i < count; i++) { - if (((JCheckBox) model.get(i)).isSelected()) { - sel.add(title[i]); - } - } - return sel.toArray(new String[0]); - } - - - protected void saveSelections() { - String[] sel = getSelections(); - Manifest mf = new Manifest(sketch, appComp, modeFolder, false); - mf.setPermissions(sel); - } - - - public String getMenuTitle() { - return "Android Permissions"; - } - - - // List of constants for each permission and a brief description: - // https://developer.android.com/reference/android/Manifest.permission - static final String[] listing = { - "ACCEPT_HANDOVER", "Allows a calling app to continue a call which was started in another app.", - "ACCESS_BACKGROUND_LOCATION", "Allows an app to access location in the background.", - "ACCESS_BLOBS_ACROSS_USERS", "Allows an application to access data blobs across users.", - "ACCESS_CHECKIN_PROPERTIES", "Allows read/write access to the \"properties\" table in the checkin database, to change values that get uploaded.", - "ACCESS_COARSE_LOCATION", "Allows an app to access approximate location.", - "ACCESS_FINE_LOCATION", "Allows an app to access precise location.", - "ACCESS_LOCATION_EXTRA_COMMANDS", "Allows an application to access extra location provider commands.", - "ACCESS_MEDIA_LOCATION", "Allows an application to access any geographic locations persisted in the user's shared collection.", - "ACCESS_NETWORK_STATE", "Allows applications to access information about networks.", - "ACCESS_NOTIFICATION_POLICY", "Marker permission for applications that wish to access notification policy.", - "ACCESS_WIFI_STATE", "Allows applications to access information about Wi-Fi networks.", - "ACCOUNT_MANAGER", "Allows applications to call into AccountAuthenticators.", - "ACTIVITY_RECOGNITION", "Allows an application to recognize physical activity.", - "ADD_VOICEMAIL", "Allows an application to add voicemails into the system.", - "ANSWER_PHONE_CALLS", "Allows the app to answer an incoming phone call.", - "BATTERY_STATS", "Allows an application to collect battery statistics", - "BIND_ACCESSIBILITY_SERVICE", "Must be required by an AccessibilityService , to ensure that only the system can bind to it.", - "BIND_APPWIDGET", "Allows an application to tell the AppWidget service which application can access AppWidget's data.", - "BIND_AUTOFILL_SERVICE", "Must be required by a AutofillService , to ensure that only the system can bind to it.", - "BIND_CALL_REDIRECTION_SERVICE", "Must be required by a CallRedirectionService , to ensure that only the system can bind to it.", - "BIND_CARRIER_MESSAGING_CLIENT_SERVICE", "A subclass of CarrierMessagingClientService must be protected with this permission.", - "BIND_CARRIER_SERVICES", "The system process that is allowed to bind to services in carrier apps will have this permission.", - "BIND_COMPANION_DEVICE_SERVICE", "Must be required by any CompanionDeviceService s to ensure that only the system can bind to it.", - "BIND_CONDITION_PROVIDER_SERVICE", "Must be required by a ConditionProviderService , to ensure that only the system can bind to it.", - "BIND_CONTROLS", "Allows SystemUI to request third party controls.", - "BIND_DEVICE_ADMIN", "Must be required by device administration receiver, to ensure that only the system can interact with it.", - "BIND_DREAM_SERVICE", "Must be required by an DreamService , to ensure that only the system can bind to it.", - "BIND_INCALL_SERVICE", "Must be required by a InCallService , to ensure that only the system can bind to it.", - "BIND_INPUT_METHOD", "Must be required by an InputMethodService , to ensure that only the system can bind to it.", - "BIND_MIDI_DEVICE_SERVICE", "Must be required by an MidiDeviceService , to ensure that only the system can bind to it.", - "BIND_NFC_SERVICE", "Must be required by a HostApduService or OffHostApduService to ensure that only the system can bind to it.", - "BIND_NOTIFICATION_LISTENER_SERVICE", "Must be required by an NotificationListenerService , to ensure that only the system can bind to it.", - "BIND_PRINT_SERVICE", "Must be required by a PrintService , to ensure that only the system can bind to it.", - "BIND_QUICK_ACCESS_WALLET_SERVICE", "Must be required by a QuickAccessWalletService to ensure that only the system can bind to it.", - "BIND_QUICK_SETTINGS_TILE", "Allows an application to bind to third party quick settings tiles.", - "BIND_REMOTEVIEWS", "Must be required by a RemoteViewsService , to ensure that only the system can bind to it.", - "BIND_SCREENING_SERVICE", "Must be required by a CallScreeningService , to ensure that only the system can bind to it.", - "BIND_TELECOM_CONNECTION_SERVICE", "Must be required by a ConnectionService , to ensure that only the system can bind to it.", - "BIND_TEXT_SERVICE", "Must be required by a TextService (e.g. SpellCheckerService) to ensure that only the system can bind to it.", - "BIND_TV_INPUT", "Must be required by a TvInputService to ensure that only the system can bind to it.", - "BIND_TV_INTERACTIVE_APP", "Must be required by a TvInteractiveAppService to ensure that only the system can bind to it.", - "BIND_VISUAL_VOICEMAIL_SERVICE", "Must be required by a link VisualVoicemailService to ensure that only the system can bind to it.", - "BIND_VOICE_INTERACTION", "Must be required by a VoiceInteractionService , to ensure that only the system can bind to it.", - "BIND_VPN_SERVICE", "Must be required by a VpnService , to ensure that only the system can bind to it.", - "BIND_VR_LISTENER_SERVICE", "Must be required by an VrListenerService , to ensure that only the system can bind to it.", - "BIND_WALLPAPER", "Must be required by a WallpaperService , to ensure that only the system can bind to it.", - "BLUETOOTH", "Allows applications to connect to paired bluetooth devices.", - "BLUETOOTH_ADMIN", "Allows applications to discover and pair bluetooth devices.", - "BLUETOOTH_ADVERTISE", "Required to be able to advertise to nearby Bluetooth devices.", - "BLUETOOTH_CONNECT", "Required to be able to connect to paired Bluetooth devices.", - "BLUETOOTH_PRIVILEGED", "Allows applications to pair bluetooth devices without user interaction, and to allow or disallow phonebook access or message access.", - "BLUETOOTH_SCAN", "Required to be able to discover and pair nearby Bluetooth devices.", - "BODY_SENSORS", "Allows an application to access data from sensors that the user uses to measure what is happening inside their body, such as heart rate.", - "BODY_SENSORS_BACKGROUND", "Allows an application to access data from sensors that the user uses to measure what is happening inside their body, such as heart rate.", - "BROADCAST_PACKAGE_REMOVED", "Allows an application to broadcast a notification that an application package has been removed.", - "BROADCAST_SMS", "Allows an application to broadcast an SMS receipt notification.", - "BROADCAST_STICKY", "Allows an application to broadcast sticky intents.", - "BROADCAST_WAP_PUSH", "Allows an application to broadcast a WAP PUSH receipt notification.", - "CALL_COMPANION_APP", "Allows an app which implements the InCallService API to be eligible to be enabled as a calling companion app.", - "CALL_PHONE", "Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call.", - "CALL_PRIVILEGED", "Allows an application to call any phone number, including emergency numbers, without going through the Dialer user interface for the user to confirm the call being placed.", - "CAMERA", "Required to be able to access the camera device.", - "CAPTURE_AUDIO_OUTPUT", "Allows an application to capture audio output.", - "CHANGE_COMPONENT_ENABLED_STATE", "Allows an application to change whether an application component (other than its own) is enabled or not.", - "CHANGE_CONFIGURATION", "Allows an application to modify the current configuration, such as locale.", - "CHANGE_NETWORK_STATE", "Allows applications to change network connectivity state.", - "CHANGE_WIFI_MULTICAST_STATE", "Allows applications to enter Wi-Fi Multicast mode.", - "CHANGE_WIFI_STATE", "Allows applications to change Wi-Fi connectivity state.", - "CLEAR_APP_CACHE", "Allows an application to clear the caches of all installed applications on the device.", - "CONTROL_LOCATION_UPDATES", "Allows enabling/disabling location update notifications from the radio.", - "DELETE_CACHE_FILES", "Old permission for deleting an app's cache files, no longer used, but signals for us to quietly ignore calls instead of throwing an exception.", - "DELETE_PACKAGES", "Allows an application to delete packages.", - "DELIVER_COMPANION_MESSAGES", "Allows an application to deliver companion messages to system", - "DIAGNOSTIC", "Allows applications to RW to diagnostic resources.", - "DISABLE_KEYGUARD", "Allows applications to disable the keyguard if it is not secure.", - "DUMP", "Allows an application to retrieve state dump information from system services.", - "EXPAND_STATUS_BAR", "Allows an application to expand or collapse the status bar.", - "FACTORY_TEST", "Run as a manufacturer test application, running as the root user.", - "FOREGROUND_SERVICE", "Allows a regular application to use Service.startForeground .", - "GET_ACCOUNTS", "Allows access to the list of accounts in the Accounts Service.", - "GET_ACCOUNTS_PRIVILEGED", "Allows access to the list of accounts in the Accounts Service.", - "GET_PACKAGE_SIZE", "Allows an application to find out the space used by any package.", - "GLOBAL_SEARCH", "This permission can be used on content providers to allow the global search system to access their data.", - "HIDE_OVERLAY_WINDOWS", "Allows an app to prevent non-system-overlay windows from being drawn on top of it", - "HIGH_SAMPLING_RATE_SENSORS", "Allows an app to access sensor data with a sampling rate greater than 200 Hz.", - "INSTALL_LOCATION_PROVIDER", "Allows an application to install a location provider into the Location Manager.", - "INSTALL_PACKAGES", "Allows an application to install packages.", - "INSTALL_SHORTCUT", "Allows an application to install a shortcut in Launcher.", - "INSTANT_APP_FOREGROUND_SERVICE", "Allows an instant app to create foreground services.", - "INTERACT_ACROSS_PROFILES", "Allows interaction across profiles in the same profile group.", - "INTERNET", "Allows applications to open network sockets.", - "KILL_BACKGROUND_PROCESSES", "Allows an application to call ActivityManager.killBackgroundProcesses(String) .", - "LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK", "An application needs this permission for Settings.ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY to show its Activity embedded in Settings app.", - "LOADER_USAGE_STATS", "Allows a data loader to read a package's access logs.", - "LOCATION_HARDWARE", "Allows an application to use location features in hardware, such as the geofencing api.", - "MANAGE_DOCUMENTS", "Allows an application to manage access to documents, usually as part of a document picker.", - "MANAGE_EXTERNAL_STORAGE", "Allows an application a broad access to external storage in scoped storage.", - "MANAGE_MEDIA", "Allows an application to modify and delete media files on this device or any connected storage device without user confirmation.", - "MANAGE_ONGOING_CALLS", "Allows to query ongoing call details and manage ongoing calls", - "MANAGE_OWN_CALLS", "Allows a calling application which manages its own calls through the self-managed ConnectionService APIs.", - "MANAGE_WIFI_INTERFACES", "Allows applications to get notified when a Wi-Fi interface request cannot be satisfied without tearing down one or more other interfaces, and provide a decision whether to approve the request or reject it.", - "MANAGE_WIFI_NETWORK_SELECTION", "This permission is used to let OEMs grant their trusted app access to a subset of privileged wifi APIs to improve wifi performance.", - "MASTER_CLEAR", "Not for use by third-party applications.", - "MEDIA_CONTENT_CONTROL", "Allows an application to know what content is playing and control its playback.", - "MODIFY_AUDIO_SETTINGS", "Allows an application to modify global audio settings.", - "MODIFY_PHONE_STATE", "Allows modification of the telephony state - power on, mmi, etc.", - "MOUNT_FORMAT_FILESYSTEMS", "Allows formatting file systems for removable storage.", - "MOUNT_UNMOUNT_FILESYSTEMS", "Allows mounting and unmounting file systems for removable storage.", - "NEARBY_WIFI_DEVICES", "Required to be able to advertise and connect to nearby devices via Wi-Fi.", - "NFC", "Allows applications to perform I/O operations over NFC.", - "NFC_PREFERRED_PAYMENT_INFO", "Allows applications to receive NFC preferred payment service information.", - "NFC_TRANSACTION_EVENT", "Allows applications to receive NFC transaction events.", - "OVERRIDE_WIFI_CONFIG", "Allows an application to modify any wifi configuration, even if created by another application.", - "PACKAGE_USAGE_STATS", "Allows an application to collect component usage statistics", - "POST_NOTIFICATIONS", "Allows an app to post notifications", - "QUERY_ALL_PACKAGES", "Allows query of any normal app on the device, regardless of manifest declarations.", - "READ_ASSISTANT_APP_SEARCH_DATA", "Allows an application to query over global data in AppSearch that's visible to the ASSISTANT role.", - "READ_BASIC_PHONE_STATE", "Allows read only access to phone state with a non dangerous permission, including the information like cellular network type, software version.", - "READ_CALENDAR", "Allows an application to read the user's calendar data.", - "READ_CALL_LOG", "Allows an application to read the user's call log.", - "READ_CONTACTS", "Allows an application to read the user's contacts data.", - "READ_EXTERNAL_STORAGE", "Allows an application to read from external storage.", - "READ_HOME_APP_SEARCH_DATA", "Allows an application to query over global data in AppSearch that's visible to the HOME role.", - "READ_LOGS", "Allows an application to read the low-level system log files.", - "READ_MEDIA_AUDIO", "Allows an application to read audio files from external storage.", - "READ_MEDIA_IMAGES", "Allows an application to read image files from external storage.", - "READ_MEDIA_VIDEO", "Allows an application to read video files from external storage.", - "READ_NEARBY_STREAMING_POLICY", "Allows an application to read nearby streaming policy.", - "READ_PHONE_NUMBERS", "Allows read access to the device's phone number(s).", - "READ_PHONE_STATE", "Allows read only access to phone state, including the current cellular network information, the status of any ongoing calls, and a list of any PhoneAccount s registered on the device.", - "READ_PRECISE_PHONE_STATE", "Allows read only access to precise phone state.", - "READ_SMS", "Allows an application to read SMS messages.", - "READ_SYNC_SETTINGS", "Allows applications to read the sync settings.", - "READ_SYNC_STATS", "Allows applications to read the sync stats.", - "READ_VOICEMAIL", "Allows an application to read voicemails in the system.", - "REBOOT", "Required to be able to reboot the device.", - "RECEIVE_BOOT_COMPLETED", "Allows an application to receive the Intent.ACTION_BOOT_COMPLETED that is broadcast after the system finishes booting.", - "RECEIVE_MMS", "Allows an application to monitor incoming MMS messages.", - "RECEIVE_SMS", "Allows an application to receive SMS messages.", - "RECEIVE_WAP_PUSH", "Allows an application to receive WAP push messages.", - "RECORD_AUDIO", "Allows an application to record audio.", - "REORDER_TASKS", "Allows an application to change the Z-order of tasks.", - "REQUEST_COMPANION_PROFILE_APP_STREAMING", "Allows application to request to be associated with a virtual display capable of streaming Android applications ( AssociationRequest.DEVICE_PROFILE_APP_STREAMING ) by CompanionDeviceManager .", - "REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION", "Allows application to request to be associated with a vehicle head unit capable of automotive projection ( AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION ) by CompanionDeviceManager .", - "REQUEST_COMPANION_PROFILE_COMPUTER", "Allows application to request to be associated with a computer to share functionality and/or data with other devices, such as notifications, photos and media ( AssociationRequest.DEVICE_PROFILE_COMPUTER ) by CompanionDeviceManager .", - "REQUEST_COMPANION_PROFILE_WATCH", "Allows app to request to be associated with a device via CompanionDeviceManager as a \"watch\"", - "REQUEST_COMPANION_RUN_IN_BACKGROUND", "Allows a companion app to run in the background.", - "REQUEST_COMPANION_SELF_MANAGED", "Allows an application to create a \"self-managed\" association.", - "REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND", "Allows a companion app to start a foreground service from the background.", - "REQUEST_COMPANION_USE_DATA_IN_BACKGROUND", "Allows a companion app to use data in the background.", - "REQUEST_DELETE_PACKAGES", "Allows an application to request deleting packages.", - "REQUEST_IGNORE_BATTERY_OPTIMIZATIONS", "Permission an application must hold in order to use Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS .", - "REQUEST_INSTALL_PACKAGES", "Allows an application to request installing packages.", - "REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE", "Allows an application to subscribe to notifications about the presence status change of their associated companion device", - "REQUEST_PASSWORD_COMPLEXITY", "Allows an application to request the screen lock complexity and prompt users to update the screen lock to a certain complexity level.", - "SCHEDULE_EXACT_ALARM", "Allows applications to use exact alarm APIs.", - "SEND_RESPOND_VIA_MESSAGE", "Allows an application (Phone) to send a request to other applications to handle the respond-via-message action during incoming calls.", - "SEND_SMS", "Allows an application to send SMS messages.", - "SET_ALARM", "Allows an application to broadcast an Intent to set an alarm for the user.", - "SET_ALWAYS_FINISH", "Allows an application to control whether activities are immediately finished when put in the background.", - "SET_ANIMATION_SCALE", "Modify the global animation scaling factor.", - "SET_DEBUG_APP", "Configure an application for debugging.", - "SET_PROCESS_LIMIT", "Allows an application to set the maximum number of (not needed) application processes that can be running.", - "SET_TIME", "Allows applications to set the system time directly.", - "SET_TIME_ZONE", "Allows applications to set the system time zone directly.", - "SET_WALLPAPER", "Allows applications to set the wallpaper.", - "SET_WALLPAPER_HINTS", "Allows applications to set the wallpaper hints.", - "SIGNAL_PERSISTENT_PROCESSES", "Allow an application to request that a signal be sent to all persistent processes.", - "START_FOREGROUND_SERVICES_FROM_BACKGROUND", "Allows an application to start foreground services from the background at any time.", - "START_VIEW_APP_FEATURES", "Allows the holder to start the screen with a list of app features.", - "START_VIEW_PERMISSION_USAGE", "Allows the holder to start the permission usage screen for an app.", - "STATUS_BAR", "Allows an application to open, close, or disable the status bar and its icons.", - "SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE", "Allows an application to subscribe to keyguard locked (i.e., showing) state.", - "SYSTEM_ALERT_WINDOW", "Allows an app to create windows using the type WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY , shown on top of all other apps.", - "TRANSMIT_IR", "Allows using the device's IR transmitter, if available.", - "UPDATE_DEVICE_STATS", "Allows an application to update device statistics.", - "UPDATE_PACKAGES_WITHOUT_USER_ACTION", "Allows an application to indicate via PackageInstaller.SessionParams.setRequireUserAction(int) that user action should not be required for an app update.", - "USE_BIOMETRIC", "Allows an app to use device supported biometric modalities.", - "USE_EXACT_ALARM", "Allows apps to use exact alarms just like with SCHEDULE_EXACT_ALARM but without needing to request this permission from the user.", - "USE_FULL_SCREEN_INTENT", "Required for apps targeting Build.VERSION_CODES.Q that want to use notification full screen intents .", - "USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER", "Allows to read device identifiers and use ICC based authentication like EAP-AKA.", - "USE_SIP", "Allows an application to use SIP service.", - "UWB_RANGING", "Required to be able to range to devices using ultra-wideband.", - "VIBRATE", "Allows access to the vibrator.", - "WAKE_LOCK", "Allows using PowerManager WakeLocks to keep processor from sleeping or screen from dimming.", - "WRITE_APN_SETTINGS", "Allows applications to write the apn settings and read sensitive fields of an existing apn settings like user and password.", - "WRITE_CALENDAR", "Allows an application to write the user's calendar data.", - "WRITE_CALL_LOG", "Allows an application to write (but not read) the user's call log data.", - "WRITE_CONTACTS", "Allows an application to write the user's contacts data.", - "WRITE_EXTERNAL_STORAGE", "Allows an application to write to external storage.", - "WRITE_GSERVICES", "Allows an application to modify the Google service map.", - "WRITE_SECURE_SETTINGS", "Allows an application to read or write the secure system settings.", - "WRITE_SETTINGS", "Allows an application to read or write the system settings.", - "WRITE_SYNC_SETTINGS", "Allows applications to write the sync settings.", - "WRITE_VOICEMAIL", "Allows an application to modify and remove existing voicemails in the system." - }; - - // Dangerous permissions that need runtime approval: - // https://developer.android.com/guide/topics/permissions/overview#runtime - public static final String[] dangerous = { - "ACCEPT_HANDOVER", - "ACCESS_BACKGROUND_LOCATION", - "ACCESS_COARSE_LOCATION", - "ACCESS_FINE_LOCATION", - "ACCESS_MEDIA_LOCATION", - "ACTIVITY_RECOGNITION", - "ADD_VOICEMAIL", - "ANSWER_PHONE_CALLS", - "BLUETOOTH_ADVERTISE", - "BLUETOOTH_CONNECT", - "BLUETOOTH_SCAN", - "BODY_SENSORS", - "BODY_SENSORS_BACKGROUND", - "CALL_PHONE", - "CAMERA", - "GET_ACCOUNTS", - "NEARBY_WIFI_DEVICES", - "POST_NOTIFICATIONS", - "READ_CALENDAR", - "READ_CALL_LOG", - "READ_CONTACTS", - "READ_EXTERNAL_STORAGE", - "READ_MEDIA_AUDIO", - "READ_MEDIA_IMAGES", - "READ_MEDIA_VIDEO", - "READ_PHONE_NUMBERS", - "READ_PHONE_STATE", - "READ_SMS", - "RECEIVE_MMS", - "RECEIVE_SMS", - "RECEIVE_WAP_PUSH", - "RECORD_AUDIO", - "SEND_SMS", - "USE_SIP", - "UWB_RANGING", - "WRITE_CALENDAR", - "WRITE_CALL_LOG", - "WRITE_CONTACTS", - "WRITE_EXTERNAL_STORAGE" - }; - - static String[] title; - static String[] description; - static int count; - static { - count = listing.length / 2; - title = new String[count]; - description = new String[count]; - for (int i = 0; i < count; i++) { - title[i] = listing[i*2]; - description[i] = listing[i*2+1]; - } - } -} - - -// Code for this CheckBoxList class found on the net, though I've lost the -// link. If you run across the original version, please let me know so that -// the original author can be credited properly. It was from a snippet -// collection, but it seems to have been picked up so many places with others -// placing their copyright on it that I haven't been able to determine the -// original author. [fry 20100216] -@SuppressWarnings("serial") -class CheckBoxList extends JList { - protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); - int checkboxWidth; - - public CheckBoxList() { - setCellRenderer(new CellRenderer()); - - // get the width of a checkbox so we can figure out if the mouse is inside - checkboxWidth = new JCheckBox().getPreferredSize().width; - // add the amount for the inset - checkboxWidth += Permissions.BORDER_HORIZ; - - addMouseListener(new MouseAdapter() { - public void mousePressed(MouseEvent e) { - if (isEnabled()) { -// System.out.println("cbw = " + checkboxWidth); - int index = locationToIndex(e.getPoint()); -// descriptionLabel.setText(description[index]); - if (index != -1) { - JCheckBox checkbox = getModel().getElementAt(index); - //System.out.println("mouse event in list: " + e); -// System.out.println(checkbox.getSize() + " ... " + checkbox); -// if (e.getX() < checkbox.getSize().height) { - if (e.getX() < checkboxWidth) { - checkbox.setSelected(!checkbox.isSelected()); - repaint(); - } - } - } - } - }); - setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - } - - - protected class CellRenderer implements ListCellRenderer { - public Component getListCellRendererComponent(JList list, - JCheckBox checkbox, - int index, boolean isSelected, - boolean cellHasFocus) { - checkbox.setBackground(isSelected ? getSelectionBackground() : getBackground()); - checkbox.setForeground(isSelected ? getSelectionForeground() : getForeground()); - checkbox.setEnabled(list.isEnabled()); - checkbox.setFont(getFont()); - checkbox.setFocusPainted(false); - checkbox.setBorderPainted(true); - checkbox.setBorder(isSelected ? UIManager.getBorder("List.focusCellHighlightBorder") : noFocusBorder); - return checkbox; - } - } -} diff --git a/mode/src/processing/mode/android/RedirectStreamHandler.java b/mode/src/processing/mode/android/RedirectStreamHandler.java deleted file mode 100644 index 933669106..000000000 --- a/mode/src/processing/mode/android/RedirectStreamHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -package processing.mode.android; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.PrintWriter; - - -public class RedirectStreamHandler extends Thread { - // Streams Redirection- from and to - private final InputStream input; - private final PrintWriter output; - - RedirectStreamHandler(PrintWriter output, InputStream input) { - this.input = input; - this.output = output; - start(); - } - - @Override - public void run() { - try { - BufferedReader reader = new BufferedReader(new InputStreamReader(input)); - String line; - while ((line = reader.readLine()) != null) { - // print to output line by line - output.println(line); - } - } catch (IOException ioException) { - System.out.println("I/O Redirection failure: "+ ioException.toString()); - } - } - } diff --git a/mode/src/processing/mode/android/SDKDownloader.java b/mode/src/processing/mode/android/SDKDownloader.java deleted file mode 100644 index 58397611d..000000000 --- a/mode/src/processing/mode/android/SDKDownloader.java +++ /dev/null @@ -1,689 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2014-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -package processing.mode.android; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; -import processing.app.Platform; -import processing.app.Preferences; -import processing.app.ui.Toolkit; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; - -@SuppressWarnings("serial") -public class SDKDownloader extends JDialog implements PropertyChangeListener { - final static private int BOX_BORDER = Toolkit.zoom(13); - final static private int BAR_BORDER = Toolkit.zoom(10); - final static private int BAR_WIDTH = Toolkit.zoom(300); - final static private int BAR_HEIGHT = Toolkit.zoom(30); - final static private int GAP = Toolkit.zoom(13); - - private static final int PLATFORM_TOOLS = 2; - private static final int ANDROID_REPO = 4; - private static final int GOOGLE_REPO = 5; - private static final int USB_DRIVER = 6; - - private static final String REPOSITORY_URL = "https://dl.google.com/android/repository/"; - private static final String HAXM_URL = "https://dl.google.com/android/repository/extras/intel/"; - private static final String REPOSITORY_LIST = "repository2-3.xml"; - private static final String ADDON_LIST = "addon2-3.xml"; - - public static final boolean DOWNLOAD_EMU_WITH_SDK = false; - - private JProgressBar progressBar; - private JLabel downloadedTextArea; - - private SDKDownloadTask downloadTask; - - private Frame editor; - private AndroidSDK sdk; - private boolean cancelled; - - private int totalSize = 0; - - class SDKUrlHolder { - public String platformVersion, buildToolsVersion; - public String platformToolsUrl, buildToolsUrl, platformUrl, cmdlineToolsUrl, emulatorUrl; - public String platformToolsFilename, buildToolsFilename, platformFilename, cmdlineToolsFilename, emulatorFilename; - public String usbDriverUrl; - public String usbDriverFilename; - public String haxmFilename, haxmUrl; - public int totalSize = 0; - } - - class SDKDownloadTask extends SwingWorker { - - private int downloadedSize = 0; - private int BUFFER_SIZE = 4096; - - @Override - protected Object doInBackground() throws Exception { - File sketchbookFolder = processing.app.Base.getSketchbookFolder(); - File androidFolder = new File(sketchbookFolder, "android"); - if (!androidFolder.exists()) androidFolder.mkdir(); - - File sdkFolder = AndroidUtil.createSubFolder(androidFolder, "sdk"); - - // creating sdk folders - File platformsFolder = new File(sdkFolder, "platforms"); - if (!platformsFolder.exists()) platformsFolder.mkdir(); - File buildToolsFolder = new File(sdkFolder, "build-tools"); - if (!buildToolsFolder.exists()) buildToolsFolder.mkdir(); - File extrasFolder = new File(sdkFolder, "extras"); - if (!extrasFolder.exists()) extrasFolder.mkdir(); - File googleRepoFolder = new File(extrasFolder, "google"); - if (!googleRepoFolder.exists()) googleRepoFolder.mkdir(); - File haxmFolder = new File(extrasFolder, "intel/HAXM"); - if (!haxmFolder.exists()) haxmFolder.mkdirs(); - - if (DOWNLOAD_EMU_WITH_SDK) { - File emulatorFolder = new File(sdkFolder, "emulator"); - if (!emulatorFolder.exists()) emulatorFolder.mkdir(); - } - - // creating temp folder for downloaded zip packages - File tempFolder = new File(androidFolder, "temp"); - if (!tempFolder.exists()) tempFolder.mkdir(); - - try { - SDKUrlHolder downloadUrls = new SDKUrlHolder(); - String repositoryUrl = REPOSITORY_URL + REPOSITORY_LIST; - String addonUrl = REPOSITORY_URL + ADDON_LIST; - String haxmUrl = HAXM_URL + ADDON_LIST; - - String platformName = Platform.getName(); - System.out.println("PLATFORM NAME " + platformName); - if (platformName.equals("macos")) { - platformName = "macosx"; - } - getMainDownloadUrls(downloadUrls, repositoryUrl, platformName); - getExtrasDownloadUrls(downloadUrls, addonUrl, platformName); - getHaxmDownloadUrl(downloadUrls, haxmUrl, platformName); - firePropertyChange(AndroidMode.getTextString("download_property.change_event_total"), 0, downloadUrls.totalSize); - - // Command-line tools - File downloadedCmdLineTools = new File(tempFolder, downloadUrls.cmdlineToolsFilename); - downloadAndUnpack(downloadUrls.cmdlineToolsUrl, downloadedCmdLineTools, sdkFolder, true); - File tmpFrom = new File(sdkFolder, "cmdline-tools"); - File tmpTo = new File(sdkFolder, "cmdline-tmp"); - AndroidUtil.moveDir(tmpFrom, tmpTo); - File cmdlineToolsFolder = new File(sdkFolder, "cmdline-tools/latest"); - if (!cmdlineToolsFolder.exists()) cmdlineToolsFolder.mkdirs(); - AndroidUtil.moveDir(tmpTo, cmdlineToolsFolder); - - // Platform tools - File downloadedPlatformTools = new File(tempFolder, downloadUrls.platformToolsFilename); - downloadAndUnpack(downloadUrls.platformToolsUrl, downloadedPlatformTools, sdkFolder, true); - - // Build tools - File downloadedBuildTools = new File(tempFolder, downloadUrls.buildToolsFilename); - downloadAndUnpack(downloadUrls.buildToolsUrl, downloadedBuildTools, buildToolsFolder, true); - - // Platform - File downloadedPlatform = new File(tempFolder, downloadUrls.platformFilename); - downloadAndUnpack(downloadUrls.platformUrl, downloadedPlatform, platformsFolder, false); - - // USB driver - if (Platform.isWindows()) { - File downloadedFolder = new File(tempFolder, downloadUrls.usbDriverFilename); - downloadAndUnpack(downloadUrls.usbDriverUrl, downloadedFolder, googleRepoFolder, false); - } - - // HAXM - if (!Platform.isLinux()) { - File downloadedFolder = new File(tempFolder, downloadUrls.haxmFilename); - downloadAndUnpack(downloadUrls.haxmUrl, downloadedFolder, haxmFolder, true); - } - - if (DOWNLOAD_EMU_WITH_SDK) { - // Emulator, unpacks directly to sdk folder - File downloadedEmulator = new File(tempFolder, downloadUrls.emulatorFilename); - downloadAndUnpack(downloadUrls.emulatorUrl, downloadedEmulator, sdkFolder, true); - } - - if (Platform.isLinux() || Platform.isMacOS()) { - Runtime.getRuntime().exec("chmod -R 755 " + sdkFolder.getAbsolutePath()); - } - - for (File f: tempFolder.listFiles()) f.delete(); - tempFolder.delete(); - - // Normalize built-tools and platform folders to android- - String actualName = platformsFolder.listFiles()[0].getName(); - renameFolder(platformsFolder, "android-" + AndroidBuild.TARGET_SDK, actualName); - actualName = buildToolsFolder.listFiles()[0].getName(); - renameFolder(buildToolsFolder, downloadUrls.buildToolsVersion, actualName); - - // Done, let's set the environment and load the new SDK! - Platform.setenv("ANDROID_SDK", sdkFolder.getAbsolutePath()); - Preferences.set("android.sdk.path", sdkFolder.getAbsolutePath()); - sdk = AndroidSDK.load(false, null); - } catch (ParserConfigurationException e) { - // TODO Handle exceptions here somehow (ie show error message) - // and handle at least mkdir() results (above) - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } - return null; - } - - @Override - protected void done() { - super.done(); - setVisible(false); - dispose(); - } - - private void downloadAndUnpack(String urlString, File saveTo, - File unpackTo, boolean setExec) throws IOException { - URL url = null; - try { - url = new URL(urlString); - } catch (MalformedURLException e) { - //This is expected for API level 14 and more - try { - url = new URL(REPOSITORY_URL + urlString); - } catch (MalformedURLException e1) { - //This exception is not expected. Need to return. - e1.printStackTrace(); - return; - } - } - URLConnection conn = url.openConnection(); - - InputStream inputStream = conn.getInputStream(); - FileOutputStream outputStream = new FileOutputStream(saveTo); - - byte[] b = new byte[BUFFER_SIZE]; - int count; - while ((count = inputStream.read(b)) >= 0) { - outputStream.write(b, 0, count); - downloadedSize += count; - - firePropertyChange(AndroidMode.getTextString("download_property.change_event_downloaded"), 0, downloadedSize); - } - outputStream.flush(); outputStream.close(); inputStream.close(); - - inputStream.close(); - outputStream.close(); - - AndroidUtil.extractFolder(saveTo, unpackTo, setExec); - } - - private void getMainDownloadUrls(SDKUrlHolder urlHolder, - String repositoryUrl, String requiredHostOs) - throws ParserConfigurationException, IOException, SAXException, XPathException { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - Document doc = db.parse(new URL(repositoryUrl).openStream()); - - XPathFactory xPathfactory = XPathFactory.newInstance(); - XPath xpath = xPathfactory.newXPath(); - XPathExpression expr; - NodeList remotePackages; - boolean found; - - // ----------------------------------------------------------------------- - // Platform - expr = xpath.compile("//remotePackage[starts-with(@path, \"platforms;\")" + - "and contains(@path, '" + AndroidBuild.TARGET_SDK + "')]"); // Skip latest platform; download only the targeted - remotePackages = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); - if (remotePackages != null) { - NodeList childNodes = remotePackages.item(0).getChildNodes(); - - NodeList typeDetails = ((Element) childNodes).getElementsByTagName("type-details"); - NodeList apiLevel = ((Element) typeDetails.item(0)).getElementsByTagName("api-level"); - urlHolder.platformVersion = apiLevel.item(0).getTextContent(); - - NodeList archives = ((Element) childNodes).getElementsByTagName("archive"); - NodeList archive = archives.item(0).getChildNodes(); - NodeList complete = ((Element) archive).getElementsByTagName("complete"); - - NodeList url = ((Element) complete.item(0)).getElementsByTagName("url"); - NodeList size = ((Element) complete.item(0)).getElementsByTagName("size"); - - urlHolder.platformFilename = url.item(0).getTextContent(); - urlHolder.platformUrl = REPOSITORY_URL + urlHolder.platformFilename; - urlHolder.totalSize += Integer.parseInt(size.item(0).getTextContent()); - } else { - throw new IOException(AndroidMode.getTextString("sdk_downloader.error_cannot_find_platform_files")); - } - - // Difference between platform tools, build tools, and SDK (now command-line) tools: - // http://stackoverflow.com/questions/19911762/what-is-android-sdk-build-tools-and-which-version-should-be-used - // Always get the latest! - - // ----------------------------------------------------------------------- - // Platform tools - expr = xpath.compile("//remotePackage[@path=\"platform-tools\"]"); - remotePackages = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); - if (remotePackages != null) { - parseAndSet(urlHolder, remotePackages, requiredHostOs, PLATFORM_TOOLS); - } else { - throw new IOException(AndroidMode.getTextString("sdk_downloader.error_cannot_find_platform_tools")); - } - - // ----------------------------------------------------------------------- - // Build tools - expr = xpath.compile("//remotePackage[starts-with(@path, \"build-tools;\")]"); - remotePackages = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); - found = false; - if (remotePackages != null) { - for (int buildTool = 0; buildTool < remotePackages.getLength(); buildTool++) { - NodeList childNodes = remotePackages.item(buildTool).getChildNodes(); - - NodeList channel = ((Element) childNodes).getElementsByTagName("channelRef"); - if (!channel.item(0).getAttributes().item(0).getNodeValue().equals("channel-0")) { - continue; // Stable channel only, skip others - } - - NodeList revision = ((Element) childNodes).getElementsByTagName("revision"); - String major = (((Element) revision.item(0)).getElementsByTagName("major")).item(0).getTextContent(); - String minor = (((Element) revision.item(0)).getElementsByTagName("minor")).item(0).getTextContent(); - String micro = (((Element) revision.item(0)).getElementsByTagName("micro")).item(0).getTextContent(); - if (!major.equals(AndroidBuild.TARGET_SDK)) { - continue; // Allows only the latest build tools for the target platform - } - - urlHolder.buildToolsVersion = major + "." + minor + "." + micro; - - NodeList archives = ((Element) childNodes).getElementsByTagName("archive"); - - for (int j = 0; j < archives.getLength(); ++j) { - NodeList archive = archives.item(j).getChildNodes(); - NodeList complete = ((Element) archive).getElementsByTagName("complete"); - - NodeList os = ((Element) archive).getElementsByTagName("host-os"); - NodeList url = ((Element) complete.item(0)).getElementsByTagName("url"); - NodeList size = ((Element) complete.item(0)).getElementsByTagName("size"); - - if (os.item(0).getTextContent().equals(requiredHostOs)) { - urlHolder.buildToolsFilename = url.item(0).getTextContent(); - urlHolder.buildToolsUrl = REPOSITORY_URL + urlHolder.buildToolsFilename; - urlHolder.totalSize += Integer.parseInt(size.item(0).getTextContent()); - found = true; - break; - } - } - if (found) break; - } - } - if (!found) { - throw new IOException(AndroidMode.getTextString("sdk_downloader.error_cannot_find_build_tools")); - } - - // ----------------------------------------------------------------------- - // Command-line tools - expr = xpath.compile("//remotePackage[starts-with(@path, \"cmdline-tools;\")]"); - remotePackages = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); - found = false; - if (remotePackages != null) { - for (int tool = 0; tool < remotePackages.getLength(); tool++) { - NodeList childNodes = remotePackages.item(tool).getChildNodes(); - - NodeList channel = ((Element) childNodes).getElementsByTagName("channelRef"); - if (!channel.item(0).getAttributes().item(0).getNodeValue().equals("channel-0")) { - continue; // Stable channel only, skip others - } - - NodeList archives = ((Element) childNodes).getElementsByTagName("archive"); - for (int i = 0; i < archives.getLength(); ++i) { - NodeList archive = archives.item(i).getChildNodes(); - NodeList complete = ((Element) archive).getElementsByTagName("complete"); - - NodeList os = ((Element) archive).getElementsByTagName("host-os"); - NodeList url = ((Element) complete.item(0)).getElementsByTagName("url"); - NodeList size = ((Element) complete.item(0)).getElementsByTagName("size"); - - if (os.item(0).getTextContent().equals(requiredHostOs)) { - urlHolder.cmdlineToolsFilename = url.item(0).getTextContent(); - urlHolder.cmdlineToolsUrl = REPOSITORY_URL + urlHolder.cmdlineToolsFilename; - urlHolder.totalSize += Integer.parseInt(size.item(0).getTextContent()); - found = true; - break; - } - } - if (found) break; - } - } - if (!found) { - throw new IOException(AndroidMode.getTextString("sdk_downloader.error_cannot_find_tools")); - } - - if (DOWNLOAD_EMU_WITH_SDK) { - // ----------------------------------------------------------------------- - // Emulator - expr = xpath.compile("//remotePackage[@path=\"emulator\"]"); - remotePackages = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); - found = false; - if (remotePackages != null) { - for (int i = 0; i < remotePackages.getLength(); ++i) { - NodeList childNodes = remotePackages.item(i).getChildNodes(); - - NodeList channel = ((Element) childNodes).getElementsByTagName("channelRef"); - if (!channel.item(0).getAttributes().item(0).getNodeValue().equals("channel-0")) { - continue; //Stable channel only, skip others - } - - NodeList archives = ((Element) childNodes).getElementsByTagName("archive"); - - for (int j = 0; j < archives.getLength(); ++j) { - NodeList archive = archives.item(j).getChildNodes(); - NodeList complete = ((Element) archive).getElementsByTagName("complete"); - - NodeList os = ((Element) archive).getElementsByTagName("host-os"); - NodeList url = ((Element) complete.item(0)).getElementsByTagName("url"); - NodeList size = ((Element) complete.item(0)).getElementsByTagName("size"); - - if (os.item(0).getTextContent().equals(requiredHostOs)) { - urlHolder.emulatorFilename = url.item(0).getTextContent(); - urlHolder.emulatorUrl = REPOSITORY_URL + urlHolder.emulatorFilename; - urlHolder.totalSize += Integer.parseInt(size.item(0).getTextContent()); - found = true; - break; - } - } - if (found) break; - } - } - } - if (!found) { - throw new IOException(AndroidMode.getTextString("sdk_downloader.error_cannot_find_emulator")); - } - } - } - - private void getExtrasDownloadUrls(SDKUrlHolder urlHolder, - String repositoryUrl, String requiredHostOs) - throws ParserConfigurationException, IOException, SAXException, XPathException { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - Document doc = db.parse(new URL(repositoryUrl).openStream()); - - XPathFactory xPathfactory = XPathFactory.newInstance(); - XPath xpath = xPathfactory.newXPath(); - XPathExpression expr; - NodeList remotePackages; - - // --------------------------------------------------------------------- - // Android Support repository - expr = xpath.compile("//remotePackage[@path=\"extras;android;m2repository\"]"); - remotePackages = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); - if (remotePackages != null) { - parseAndSet(urlHolder, remotePackages, requiredHostOs, ANDROID_REPO); - } - - // --------------------------------------------------------------------- - // Google repository - expr = xpath.compile("//remotePackage[@path=\"extras;google;m2repository\"]"); - remotePackages = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); - if (remotePackages != null) { - parseAndSet(urlHolder, remotePackages, requiredHostOs, GOOGLE_REPO); - } - - // --------------------------------------------------------------------- - // USB driver - expr = xpath.compile("//remotePackage[@path=\"extras;google;usb_driver\"]"); - remotePackages = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); - if (remotePackages != null && Platform.isWindows()) { - parseAndSet(urlHolder, remotePackages, requiredHostOs, USB_DRIVER); - } - } - - private void getHaxmDownloadUrl(SDKUrlHolder urlHolder, - String repositoryUrl, String requiredHostOs) - throws ParserConfigurationException, IOException, SAXException, XPathException { - if (requiredHostOs.equals("linux")) - return; - - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - Document doc = db.parse(new URL(repositoryUrl).openStream()); - - XPathFactory xPathfactory = XPathFactory.newInstance(); - XPath xpath = xPathfactory.newXPath(); - XPathExpression expr; - NodeList remotePackages; - - expr = xpath.compile("//remotePackage[@path=\"extras;intel;Hardware_Accelerated_Execution_Manager\"]"); - remotePackages = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); - if (remotePackages != null) { - for (int i = 0; i < remotePackages.getLength(); ++i) { - NodeList childNodes = remotePackages.item(i).getChildNodes(); - NodeList archives = ((Element) childNodes).getElementsByTagName("archive"); - - NodeList archive = archives.item(0).getChildNodes(); - NodeList os = ((Element) archive).getElementsByTagName("host-os"); - - if (!os.item(0).getTextContent().equals(requiredHostOs)) { - continue; - } - - NodeList complete = ((Element) archive).getElementsByTagName("complete"); - NodeList url = ((Element) complete.item(0)).getElementsByTagName("url"); - NodeList size = ((Element) complete.item(0)).getElementsByTagName("size"); - - urlHolder.haxmFilename = url.item(0).getTextContent(); - urlHolder.haxmUrl = HAXM_URL + urlHolder.haxmFilename; - urlHolder.totalSize += Integer.parseInt(size.item(0).getTextContent()); - break; - } - } - } - - private void parseAndSet(SDKUrlHolder urlHolder, NodeList remotePackages, String requiredHostOs, int packageN) { - NodeList childNodes = remotePackages.item(0).getChildNodes(); - NodeList archives = ((Element) childNodes).getElementsByTagName("archive"); - - for (int i = 0; i < archives.getLength(); ++i) { - NodeList archive = archives.item(i).getChildNodes(); - NodeList complete = ((Element) archive).getElementsByTagName("complete"); - - NodeList url = ((Element) complete.item(0)).getElementsByTagName("url"); - NodeList size = ((Element) complete.item(0)).getElementsByTagName("size"); - - switch (packageN) { - case PLATFORM_TOOLS: - NodeList os = ((Element) archive).getElementsByTagName("host-os"); - if (!os.item(0).getTextContent().equals(requiredHostOs)) { - continue; - } - urlHolder.platformToolsFilename = url.item(0).getTextContent(); - urlHolder.platformToolsUrl = REPOSITORY_URL + urlHolder.platformToolsFilename; - urlHolder.totalSize += Integer.parseInt(size.item(0).getTextContent()); - break; - case USB_DRIVER: - urlHolder.usbDriverFilename = url.item(0).getTextContent(); - urlHolder.usbDriverUrl = REPOSITORY_URL + urlHolder.usbDriverFilename; - urlHolder.totalSize += Integer.parseInt(size.item(0).getTextContent()); - break; - } - break; - } - } - - private void renameFolder(File baseFolder, String expected, String actual) - throws IOException { - File expectedPath = new File(baseFolder, expected); - File actualPath = new File(baseFolder, actual); - if (!expectedPath.exists()) { - if (actualPath.exists()) { - actualPath.renameTo(expectedPath); - } else { - throw new IOException(AndroidMode.getTextString("sdk_downloader.error.cannot_unpack_platform", actualPath.getAbsolutePath())); - } - } - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals(AndroidMode.getTextString("download_property.change_event_total"))) { - progressBar.setIndeterminate(false); - totalSize = (Integer) evt.getNewValue(); - progressBar.setMaximum(totalSize); - } else if (evt.getPropertyName().equals(AndroidMode.getTextString("download_property.change_event_downloaded"))) { - downloadedTextArea.setText(humanReadableByteCount((Integer) evt.getNewValue(), true) - + " / " + humanReadableByteCount(totalSize, true)); - progressBar.setValue((Integer) evt.getNewValue()); - } - } - - // http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java - public static String humanReadableByteCount(long bytes, boolean si) { - int unit = si ? 1000 : 1024; - if (bytes < unit) return bytes + " B"; - int exp = (int) (Math.log(bytes) / Math.log(unit)); - String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i"); - return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); - } - - public SDKDownloader(Frame editor) { - super(editor, AndroidMode.getTextString("sdk_downloader.download_title"), true); - this.editor = editor; - this.sdk = null; - createLayout(); - } - - public void run() { - cancelled = false; - downloadTask = new SDKDownloadTask(); - downloadTask.addPropertyChangeListener(this); - downloadTask.execute(); - setAlwaysOnTop(true); - setVisible(true); - } - - public boolean cancelled() { - return cancelled; - } - - public AndroidSDK getSDK() { - return sdk; - } - - private void createLayout() { - Container outer = getContentPane(); - outer.removeAll(); - - Box vbox = Box.createVerticalBox(); - vbox.setBorder(new EmptyBorder(BOX_BORDER, BOX_BORDER, BOX_BORDER, BOX_BORDER)); - outer.add(vbox); - - String labelText = AndroidMode.getTextString("sdk_downloader.download_sdk_label"); - JLabel textarea = new JLabel(labelText); - textarea.setAlignmentX(LEFT_ALIGNMENT); - vbox.add(textarea); - - // Needed to put the progressBar inside this panel so we can set its size - JPanel progressPanel = new JPanel(); - BoxLayout boxLayout = new BoxLayout(progressPanel, BoxLayout.Y_AXIS); - progressPanel.setLayout(boxLayout); - progressBar = new JProgressBar(0, 100); - progressBar.setPreferredSize(new Dimension(BAR_WIDTH, BAR_HEIGHT)); - progressBar.setValue(0); - progressBar.setStringPainted(true); - progressBar.setIndeterminate(true); - progressBar.setBorder(new EmptyBorder(BAR_BORDER, BAR_BORDER, BAR_BORDER, BAR_BORDER)); - progressPanel.add(progressBar); - vbox.add(progressPanel); - - downloadedTextArea = new JLabel("0 / 0 MB"); - downloadedTextArea.setAlignmentX(LEFT_ALIGNMENT); - vbox.add(downloadedTextArea); - - vbox.add(Box.createVerticalStrut(GAP)); - - // buttons - JPanel buttons = new JPanel(); -// buttons.setPreferredSize(new Dimension(400, 35)); -// JPanel buttons = new JPanel() { -// public Dimension getPreferredSize() { -// return new Dimension(400, 35); -// } -// public Dimension getMinimumSize() { -// return new Dimension(400, 35); -// } -// public Dimension getMaximumSize() { -// return new Dimension(400, 35); -// } -// }; - -// Box buttons = Box.createHorizontalBox(); - buttons.setAlignmentX(LEFT_ALIGNMENT); - JButton cancelButton = new JButton(AndroidMode.getTextString("download_prompt.cancel")); - Dimension dim = new Dimension(Toolkit.getButtonWidth()*2, - Toolkit.zoom(cancelButton.getPreferredSize().height)); - - cancelButton.setPreferredSize(dim); - cancelButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (downloadTask != null) { - downloadTask.cancel(true); - } - setVisible(false); - cancelled = true; - } - }); - cancelButton.setEnabled(true); - - buttons.add(cancelButton); -// buttons.setMaximumSize(new Dimension(300, buttons.getPreferredSize().height)); - vbox.add(buttons); - - JRootPane root = getRootPane(); - root.setDefaultButton(cancelButton); - ActionListener disposer = new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - setVisible(false); - } - }; - Toolkit.registerWindowCloseKeys(root, disposer); - Toolkit.setIcon(this); - - pack(); - - setResizable(false); - setLocationRelativeTo(editor); - } -} \ No newline at end of file diff --git a/mode/src/processing/mode/android/SysImageDownloader.java b/mode/src/processing/mode/android/SysImageDownloader.java deleted file mode 100644 index 0b626fcae..000000000 --- a/mode/src/processing/mode/android/SysImageDownloader.java +++ /dev/null @@ -1,568 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2016-21 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -package processing.mode.android; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -import processing.app.Platform; -import processing.app.Preferences; -import processing.app.exec.LineProcessor; -import processing.app.exec.StreamPump; -import processing.app.ui.Toolkit; -import processing.core.PApplet; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.*; - -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.*; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; - -@SuppressWarnings("serial") -public class SysImageDownloader extends JDialog implements PropertyChangeListener { - final static private int FONT_SIZE = Toolkit.zoom(11); - final static private int TEXT_MARGIN = Toolkit.zoom(8); - final static private int TEXT_WIDTH = Toolkit.zoom(300); - - private static final String SYS_IMAGES_ARM_URL = "https://dl.google.com/android/repository/sys-img/android/"; - - private static final String SYS_IMAGES_PHONE_URL = "https://dl.google.com/android/repository/sys-img/google_apis/"; - private static final String SYS_IMAGES_PHONE_LIST = "sys-img2-3.xml"; - - private static final String SYS_IMAGES_WEAR_URL = "https://dl.google.com/android/repository/sys-img/android-wear/"; - private static final String SYS_IMAGES_WEAR_LIST = "sys-img2-3.xml"; - - private static final String EMULATOR_GUIDE_URL = - "https://developer.android.com/studio/run/emulator-acceleration.html"; - - private static final String KVM_LINUX_GUIDE_URL = - "https://developer.android.com/studio/run/emulator-acceleration.html#vm-linux"; - - private JProgressBar progressBar; - private JLabel downloadedTextArea; - - private DownloadTask downloadTask; - - private Frame editor; - private boolean result; - private boolean wear; - private boolean askABI; - private String abi; - private boolean cancelled; - - private int totalSize = 0; - - class UrlHolder { - public String platformVersion; - public String sysImgUrl, sysImgTag, sysImgWearUrl, sysImgWearTag; - public String sysImgFilename, sysImgWearFilename; - public int totalSize = 0; - } - - class DownloadTask extends SwingWorker { - - private int downloadedSize = 0; - private int BUFFER_SIZE = 4096; - - @Override - protected Object doInBackground() throws Exception { - result = false; - - // The SDK should already be detected by the android mode - String sdkPrefsPath = Preferences.get("android.sdk.path"); - - File sketchbookFolder = processing.app.Base.getSketchbookFolder(); - File androidFolder = new File(sketchbookFolder, "android"); - if (!androidFolder.exists()) androidFolder.mkdir(); - - File sdkFolder = new File(sdkPrefsPath); - if (!sdkFolder.exists()) { - throw new IOException("SDK folder does not exist " + sdkFolder.getAbsolutePath()); - } - - // creating sdk folders - File sysImgFolder = new File(sdkFolder, "system-images"); - if (!sysImgFolder.exists()) sysImgFolder.mkdir(); - - // creating temp folder for downloaded zip packages - File tempFolder = new File(androidFolder, "temp"); - if (!tempFolder.exists()) tempFolder.mkdir(); - - try { - String repo; - if (wear) { - repo = SYS_IMAGES_WEAR_URL + SYS_IMAGES_WEAR_LIST; - } else if (abi.equals("arm")) { - // The ARM images using Google APIs are too slow, so use the - // older Android (AOSP) images. - repo = SYS_IMAGES_ARM_URL + SYS_IMAGES_PHONE_LIST; - } else { - repo = SYS_IMAGES_PHONE_URL + SYS_IMAGES_PHONE_LIST; - } - - UrlHolder downloadUrls = new UrlHolder(); - getDownloadUrls(downloadUrls, repo, Platform.getName()); - firePropertyChange(AndroidMode.getTextString("download_property.change_event_total"), 0, downloadUrls.totalSize); - totalSize = downloadUrls.totalSize; - - if (wear) { - // wear system images - File downloadedSysImgWear = new File(tempFolder, downloadUrls.sysImgWearFilename); - File tmp = new File(sysImgFolder, "android-" + AndroidBuild.TARGET_SDK); - if (!tmp.exists()) tmp.mkdir(); - File sysImgWearFinalFolder = new File(tmp, downloadUrls.sysImgWearTag); - if (!sysImgWearFinalFolder.exists()) sysImgWearFinalFolder.mkdir(); - downloadAndUnpack(downloadUrls.sysImgWearUrl, downloadedSysImgWear, sysImgWearFinalFolder, false); - fixSourceProperties(sysImgWearFinalFolder); - } else { - // mobile system images - File downloadedSysImg = new File(tempFolder, downloadUrls.sysImgFilename); - - String level = abi.equals("arm") ? AVD.TARGET_SDK_ARM : AndroidBuild.TARGET_SDK; - File tmp = new File(sysImgFolder, "android-" + level); - - if (!tmp.exists()) tmp.mkdir(); - File sysImgFinalFolder = new File(tmp, downloadUrls.sysImgTag); - if (!sysImgFinalFolder.exists()) sysImgFinalFolder.mkdir(); - downloadAndUnpack(downloadUrls.sysImgUrl, downloadedSysImg, sysImgFinalFolder, false); - fixSourceProperties(sysImgFinalFolder); - } - - if (Platform.isLinux() || Platform.isMacOS()) { - Runtime.getRuntime().exec("chmod -R 755 " + sysImgFolder.getAbsolutePath()); - } - - for (File f: tempFolder.listFiles()) f.delete(); - tempFolder.delete(); - - if (Platform.isLinux() && Platform.getVariant().equals("64")) { - AndroidUtil.showMessage(AndroidMode.getTextString("sys_image_downloader.dialog.ia32libs_title"), AndroidMode.getTextString("sys_image_downloader.dialog.ia32libs_body")); - } - - result = true; - } catch (ParserConfigurationException e) { - // TODO Handle exceptions here somehow (ie show error message) - // and handle at least mkdir() results (above) - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } - return null; - } - - @Override - protected void done() { - super.done(); - setVisible(false); - dispose(); - } - - private void downloadAndUnpack(String urlString, File saveTo, - File unpackTo, boolean setExec) throws IOException { - URL url = null; - try { - url = new URL(urlString); - } catch (MalformedURLException e) { - e.printStackTrace(); - return; - } - URLConnection conn = url.openConnection(); - - InputStream inputStream = conn.getInputStream(); - FileOutputStream outputStream = new FileOutputStream(saveTo); - - byte[] b = new byte[BUFFER_SIZE]; - int count; - while ((count = inputStream.read(b)) >= 0) { - outputStream.write(b, 0, count); - downloadedSize += count; - firePropertyChange(AndroidMode.getTextString("download_property.change_event_downloaded"), 0, downloadedSize); - } - outputStream.flush(); outputStream.close(); inputStream.close(); - - inputStream.close(); - outputStream.close(); - - AndroidUtil.extractFolder(saveTo, unpackTo, setExec); - } - - // For some reason the source.properties file includes Addon entries, - // and this breaks the image... - private void fixSourceProperties(File imageFolder) { - for (File d: imageFolder.listFiles()) { - // Should iterate over the installed archs (x86, etc) - if (d.isDirectory()) { - for (File f: d.listFiles()) { - if (PApplet.getExtension(f.getName()).equals("properties")) { - String[] linesIn = PApplet.loadStrings(f); - String concat = ""; - for (String l: linesIn) { - if (l.indexOf("Addon") == -1) concat += l + "\n"; - } - String[] linesOut = concat.split("\n"); - PApplet.saveStrings(f, linesOut); - } - } - } - } - } - - private void getDownloadUrls(UrlHolder urlHolder, - String repositoryUrl, String requiredHostOs) - throws ParserConfigurationException, IOException, SAXException, XPathException { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - XPathFactory xPathfactory = XPathFactory.newInstance(); - XPath xpath = xPathfactory.newXPath(); - XPathExpression expr; - NodeList remotePackages; - - if (abi.equals("arm")) { - expr = xpath.compile("//remotePackage[contains(@path, '" + AVD.TARGET_SDK_ARM + "')" + - "and contains(@path, \"armeabi-v7a\")]"); - } else if (abi.equals("arm64-v8a")) { - expr = xpath.compile("//remotePackage[contains(@path, '" + AndroidBuild.TARGET_SDK + "')" + - "and contains(@path, \"arm64-v8a\")]"); - } else { - expr = xpath.compile("//remotePackage[contains(@path, '" + AndroidBuild.TARGET_SDK + "')" + - "and contains(@path, \"x86\")]"); - } - - if (wear) { - Document docSysImgWear = db.parse(new URL(repositoryUrl).openStream()); - remotePackages = (NodeList) expr.evaluate(docSysImgWear, XPathConstants.NODESET); - NodeList childNodes = remotePackages.item(0).getChildNodes(); - - NodeList typeDetails = ((Element) childNodes).getElementsByTagName("type-details"); - NodeList tag = ((Element) typeDetails.item(0)).getElementsByTagName("tag"); - NodeList id = ((Element) tag.item(0)).getElementsByTagName("id"); - urlHolder.sysImgWearTag = id.item(0).getTextContent(); - - NodeList archives = ((Element) childNodes).getElementsByTagName("archive"); - NodeList archive = archives.item(0).getChildNodes(); - NodeList complete = ((Element) archive).getElementsByTagName("complete"); - - NodeList url = ((Element) complete.item(0)).getElementsByTagName("url"); - NodeList size = ((Element) complete.item(0)).getElementsByTagName("size"); - - urlHolder.sysImgWearFilename = url.item(0).getTextContent(); - urlHolder.sysImgWearUrl = SYS_IMAGES_WEAR_URL + urlHolder.sysImgWearFilename; - urlHolder.totalSize += Integer.parseInt(size.item(0).getTextContent()); - } else { - Document docSysImg = db.parse(new URL(repositoryUrl).openStream()); - remotePackages = (NodeList) expr.evaluate(docSysImg, XPathConstants.NODESET); - NodeList childNodes = remotePackages.item(0).getChildNodes(); // Index 1 contains x86_64 - - NodeList typeDetails = ((Element) childNodes).getElementsByTagName("type-details"); - //NodeList abi = ((Element) typeDetails.item(0)).getElementsByTagName("abi"); - //NodeList api = ((Element) typeDetails.item(0)).getElementsByTagName("api-level"); - //System.out.println(api.item(0).getTextContent()); - - NodeList tag = ((Element) typeDetails.item(0)).getElementsByTagName("tag"); - NodeList id = ((Element) tag.item(0)).getElementsByTagName("id"); - urlHolder.sysImgTag = id.item(0).getTextContent(); - - NodeList archives = ((Element) childNodes).getElementsByTagName("archive"); - NodeList archive = archives.item(0).getChildNodes(); - NodeList complete = ((Element) archive).getElementsByTagName("complete"); - - NodeList url = ((Element) complete.item(0)).getElementsByTagName("url"); - NodeList size = ((Element) complete.item(0)).getElementsByTagName("size"); - - urlHolder.sysImgFilename = url.item(0).getTextContent(); - String imgUrl = abi.equals("arm") ? SYS_IMAGES_ARM_URL : SYS_IMAGES_PHONE_URL; - urlHolder.sysImgUrl = imgUrl + urlHolder.sysImgFilename; - urlHolder.totalSize += Integer.parseInt(size.item(0).getTextContent()); - } - } - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals(AndroidMode.getTextString("download_property.change_event_total"))) { - progressBar.setIndeterminate(false); - totalSize = (Integer) evt.getNewValue(); - progressBar.setMaximum(totalSize); - } else if (evt.getPropertyName().equals(AndroidMode.getTextString("download_property.change_event_downloaded"))) { - downloadedTextArea.setText(humanReadableByteCount((Integer) evt.getNewValue(), true) - + " / " + humanReadableByteCount(totalSize, true)); - progressBar.setValue((Integer) evt.getNewValue()); - } - } - - // http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java - public static String humanReadableByteCount(long bytes, boolean si) { - int unit = si ? 1000 : 1024; - if (bytes < unit) return bytes + " B"; - int exp = (int) (Math.log(bytes) / Math.log(unit)); - String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i"); - return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); - } - - static public int showSysImageMessage() { - String htmlString = " " + - " "; - htmlString += "

    " + AndroidMode.getTextString("sys_image_downloader.dialog.select_image_body", EMULATOR_GUIDE_URL) + "

    "; - String title = AndroidMode.getTextString("sys_image_downloader.dialog.select_image_title"); - JEditorPane pane = new JEditorPane("text/html", htmlString); - pane.addHyperlinkListener(new HyperlinkListener() { - @Override - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { - Platform.openURL(e.getURL().toString()); - } - } - }); - pane.setEditable(false); - JLabel label = new JLabel(); - pane.setBackground(label.getBackground()); - - String[] options = new String[] { - AndroidMode.getTextString("sys_image_downloader.option.x86_image"), - AndroidMode.getTextString("sys_image_downloader.option.arm_image") - }; - int result = JOptionPane.showOptionDialog(null, pane, title, - JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, - null, options, options[0]); - if (result == JOptionPane.YES_OPTION) { - return JOptionPane.YES_OPTION; - } else if (result == JOptionPane.NO_OPTION) { - return JOptionPane.NO_OPTION; - } else { - return JOptionPane.CLOSED_OPTION; - } - } - - public SysImageDownloader(Frame editor, boolean wear, boolean ask) { - super(editor, AndroidMode.getTextString("sys_image_downloader.download_title"), true); - this.editor = editor; - this.wear = wear; - this.askABI = ask; - this.result = false; - createLayout(); - } - - public void run() { - cancelled = false; - - abi = Preferences.get("android.emulator.image.abi"); - if (abi == null || askABI) { - // Either there was no image architecture selected, or the default was set. - // In this case, we give the user the option to choose between ARM and x86 - - int result = 0; - boolean arm64 = false; - // PROCESSOR_IDENTIFIER is only defined on Windows. For cross-platform CPU - // info, in the future we could use OSHI: https://github.com/oshi/oshi - String procId = System.getenv("PROCESSOR_IDENTIFIER"); - if (procId != null) { - if (-1 < procId.indexOf("Intel")) { - // Intel CPU: we go for the x86 abi - result = JOptionPane.YES_OPTION; - } else { - // Another CPU, can only be AMD, so we go for ARM abi - result = JOptionPane.NO_OPTION; - } - } else if (Platform.isMacOS()) { - if (Platform.getNativeArch().equals("aarch64")) { - // Apple Silicon Mac, so we go for the arm64 abi - arm64 = true; - result = JOptionPane.NO_OPTION; - } else { - // Intel Mac, so we go for the x86 abi - result = JOptionPane.YES_OPTION; - } - } else { - result = showSysImageMessage(); - } - if (result == JOptionPane.YES_OPTION || result == JOptionPane.CLOSED_OPTION) { - abi = "x86"; - installHAXM(); - } else if (arm64) { - abi = "arm64-v8a"; - } else { - abi = "arm"; - } - Preferences.set("android.emulator.image.abi", abi); - } - - downloadTask = new DownloadTask(); - downloadTask.addPropertyChangeListener(this); - downloadTask.execute(); - setAlwaysOnTop(true); - setVisible(true); - } - - public boolean cancelled() { - return cancelled; - } - - public boolean getResult() { - return result; - } - - static public void installHAXM() { - File haxmFolder = AndroidSDK.getHAXMInstallerFolder(); - if (Platform.isLinux()) { - AndroidUtil.showMessage(AndroidMode.getTextString("sys_image_downloader.dialog.accel_images_title"), - AndroidMode.getTextString("sys_image_downloader.dialog.kvm_config_body", KVM_LINUX_GUIDE_URL)); - } else if (haxmFolder.exists()) { - AndroidUtil.showMessage(AndroidMode.getTextString("sys_image_downloader.dialog.accel_images_title"), - AndroidMode.getTextString("sys_image_downloader.dialog.haxm_install_body")); - - ProcessBuilder pb; - if (Platform.isWindows()) { - File exec = new File(haxmFolder, "silent_install.bat"); - pb = new ProcessBuilder(exec.getAbsolutePath()); - } else { - File exec = new File(haxmFolder, "HAXM installation"); - pb = new ProcessBuilder(exec.getAbsolutePath()); - } - pb.directory(haxmFolder); - pb.redirectErrorStream(true); - - Process process = null; - try { - process = pb.start(); - } catch (IOException e) { - e.printStackTrace(); - } - - if (process != null) { - try { - StreamPump output = new StreamPump(process.getInputStream(), "HAXM: "); - output.addTarget(new LineProcessor() { - @Override - public void processLine(String line) { - System.out.println("HAXM: " + line); - } - }).start(); - - process.waitFor(); - } catch (final InterruptedException ie) { - ie.printStackTrace(); - } finally { - process.destroy(); - } - } - } - } - - private void createLayout() { - Container outer = getContentPane(); - outer.removeAll(); - - Box pain = Box.createVerticalBox(); - pain.setBorder(new EmptyBorder(13, 13, 13, 13)); - outer.add(pain); - - String labelText = wear ? AndroidMode.getTextString("sys_image_downloader.download_watch_label") : - AndroidMode.getTextString("sys_image_downloader.download_phone_label"); - JLabel textarea = new JLabel(labelText); - textarea.setAlignmentX(LEFT_ALIGNMENT); - pain.add(textarea); - - progressBar = new JProgressBar(0, 100); - progressBar.setValue(0); - progressBar.setStringPainted(true); - progressBar.setIndeterminate(true); - progressBar.setBorder(new EmptyBorder(10, 10, 10, 10) ); - pain.add(progressBar); - - downloadedTextArea = new JLabel(""); - downloadedTextArea.setAlignmentX(LEFT_ALIGNMENT); - pain.add(downloadedTextArea); - - // buttons - JPanel buttons = new JPanel(); -// buttons.setPreferredSize(new Dimension(400, 35)); -// JPanel buttons = new JPanel() { -// public Dimension getPreferredSize() { -// return new Dimension(400, 35); -// } -// public Dimension getMinimumSize() { -// return new Dimension(400, 35); -// } -// public Dimension getMaximumSize() { -// return new Dimension(400, 35); -// } -// }; - -// Box buttons = Box.createHorizontalBox(); - buttons.setAlignmentX(LEFT_ALIGNMENT); - JButton cancelButton = new JButton(AndroidMode.getTextString("download_prompt.cancel")); - Dimension dim = new Dimension(Toolkit.getButtonWidth()*2, - cancelButton.getPreferredSize().height); - - cancelButton.setPreferredSize(dim); - cancelButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (downloadTask != null) { - downloadTask.cancel(true); - } - setVisible(false); - cancelled = true; - } - }); - cancelButton.setEnabled(true); - - buttons.add(cancelButton); -// buttons.setMaximumSize(new Dimension(300, buttons.getPreferredSize().height)); - pain.add(buttons); - - JRootPane root = getRootPane(); - root.setDefaultButton(cancelButton); - ActionListener disposer = new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - setVisible(false); - } - }; - Toolkit.registerWindowCloseKeys(root, disposer); - Toolkit.setIcon(this); - - pack(); - - setResizable(false); - setLocationRelativeTo(editor); - } -} diff --git a/mode/templates/ARActivity.java.tmpl b/mode/templates/ARActivity.java.tmpl deleted file mode 100644 index ade8e71a3..000000000 --- a/mode/templates/ARActivity.java.tmpl +++ /dev/null @@ -1,102 +0,0 @@ -package @@package_name@@; - -import android.Manifest; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.os.Bundle; -import android.content.Intent; -import android.provider.Settings; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.Toast; - -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - -import processing.android.PFragment; -import processing.android.CompatUtils; -import processing.core.PApplet; - -public class MainActivity extends AppCompatActivity { - private static final int CAMERA_PERMISSION_CODE = 0; - private static final String CAMERA_PERMISSION = Manifest.permission.CAMERA; - private static final String CAMERA_PERMISSION_MESSAGE = "Camera permission is needed to use AR"; - - private PApplet sketch; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - FrameLayout frame = new FrameLayout(this); - frame.setId(CompatUtils.getUniqueViewId()); - setContentView(frame, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - - sketch = new @@sketch_class_name@@(); - @@external@@ - PFragment fragment = new PFragment(sketch); - fragment.setView(frame, this); - } - - @Override - protected void onResume() { - super.onResume(); - if (!hasCameraPermission()) requestCameraPermission(); - } - - @Override - public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { - if (!hasCameraPermission()) { - Toast.makeText(this, CAMERA_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show(); - if (!shouldShowRequestPermissionRationale()) { - launchPermissionSettings(); - } - finish(); - } - if (sketch != null) { - sketch.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - } - - @Override - public void onNewIntent(Intent intent) { - if (sketch != null) { - sketch.onNewIntent(intent); - } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (sketch != null) { - sketch.onActivityResult(requestCode, resultCode, data); - } - } - - @Override - public void onBackPressed() { - if (sketch != null) { - sketch.onBackPressed(); - } - } - - private boolean hasCameraPermission() { - int res = ContextCompat.checkSelfPermission(this, CAMERA_PERMISSION); - return res == PackageManager.PERMISSION_GRANTED; - } - - private void requestCameraPermission() { - ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_CODE); - } - - private boolean shouldShowRequestPermissionRationale() { - return ActivityCompat.shouldShowRequestPermissionRationale(this, CAMERA_PERMISSION); - } - - private void launchPermissionSettings() { - Intent intent = new Intent(); - intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - intent.setData(Uri.fromParts("package", this.getPackageName(), null)); - this.startActivity(intent); - } -} diff --git a/mode/templates/ARBuild.gradle.tmpl b/mode/templates/ARBuild.gradle.tmpl deleted file mode 100644 index 2c222a9d0..000000000 --- a/mode/templates/ARBuild.gradle.tmpl +++ /dev/null @@ -1,54 +0,0 @@ -apply plugin: 'com.android.application' - -android { - sourceSets { - main.jni.srcDirs = [] - main.jniLibs.srcDirs = ['libs'] - } - compileSdkVersion @@target_sdk@@ - defaultConfig { - applicationId "@@target_sdk@@" - minSdkVersion @@min_sdk@@ - targetSdkVersion @@target_sdk@@ - versionCode @@version_code@@ - versionName "@@version_name@@" - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - signingConfigs { - release { - if (project.hasProperty('PROCESSING_UPLOAD_KEYSTORE_FILE')) { - storeFile file(PROCESSING_UPLOAD_KEYSTORE_FILE) - storePassword PROCESSING_UPLOAD_STORE_PASSWORD - keyAlias PROCESSING_UPLOAD_KEY_ALIAS - keyPassword PROCESSING_UPLOAD_KEY_PASSWORD - } - } - } - buildTypes { - debug { - debuggable true - } - release { - minifyEnabled false - signingConfig signingConfigs.release - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - lintOptions { - abortOnError false - } -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'androidx.appcompat:appcompat:@@appcompat_version@@' - implementation 'com.google.ar:core:@@gar_version@@' - implementation files('libs/processing-core.jar') - implementation files('libs/ar.jar') - androidTestImplementation 'com.android.support.test:runner:1.3.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - testImplementation 'junit:junit:4.13' -} diff --git a/mode/templates/ARBuildECJ.gradle.tmpl b/mode/templates/ARBuildECJ.gradle.tmpl deleted file mode 100644 index 45e72f569..000000000 --- a/mode/templates/ARBuildECJ.gradle.tmpl +++ /dev/null @@ -1,100 +0,0 @@ -apply plugin: 'com.android.application' - -android { - sourceSets { - main.jni.srcDirs = [] - main.jniLibs.srcDirs = ['libs'] - } - compileSdkVersion @@target_sdk@@ - defaultConfig { - applicationId "@@package_name@@" - minSdkVersion @@min_sdk@@ - targetSdkVersion @@target_sdk@@ - versionCode @@version_code@@ - versionName "@@version_name@@" - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - signingConfigs { - release { - if (project.hasProperty('PROCESSING_UPLOAD_KEYSTORE_FILE')) { - storeFile file(PROCESSING_UPLOAD_KEYSTORE_FILE) - storePassword PROCESSING_UPLOAD_STORE_PASSWORD - keyAlias PROCESSING_UPLOAD_KEY_ALIAS - keyPassword PROCESSING_UPLOAD_KEY_PASSWORD - } - } - } - buildTypes { - debug { - debuggable true - } - release { - minifyEnabled false - signingConfig signingConfigs.release - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - lintOptions { - abortOnError false - } - - // We create a variant of the compile task, where we use the Eclipse Compiler for Java - // (ECJ) instead of the JDK (which would require the user to download and install - // the Oracle JDK). Inspired by the following: - // https://github.com/bytedeco/javacpp/wiki/Gradle - // https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.JavaCompile.html - applicationVariants.all { variant -> - variant.javaCompileProvider.get().doFirst { - // The main class that runs the Eclipse batch compiler - String ecjMain = 'org.eclipse.jdt.internal.compiler.batch.Main' - - // We construct the list of arguments needed by the batch compiler - // https://help.eclipse.org/neon/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-using_batch_compiler.htm - List ecjArgs = ['-nowarn', - '-source', variant.javaCompileProvider.get().sourceCompatibility, - '-target', variant.javaCompileProvider.get().targetCompatibility, - '-d', variant.javaCompileProvider.get().destinationDir] as String[] - - // Set the debug attributes level according to the build target - if (variant.name == 'debug') { - // All debug info - ecjArgs += '-g' - } else { - // No debug info - ecjArgs += '-g:none' - } - - // Adding all the source files to the list of arguments - ecjArgs += variant.javaCompileProvider.get().source - - // Add the Android jar to the classpath inherited from the task - FileCollection ecjClasspath = files('@@target_platform@@/android.jar', - variant.javaCompileProvider.get().classpath) - - // Running the JavaExec task, which requires the main class to run, - // the classpath, and the list of arguments - // https://docs.gradle.org/3.5/dsl/org.gradle.api.tasks.JavaExec.html#org.gradle.api.tasks.JavaExec:main - javaexec { - main ecjMain - classpath ecjClasspath - args ecjArgs - } - - // We skip the rest of the compileXxxJavaWithJavac task, since we - // source is already compiled with ecj - throw new StopExecutionException("skip javac") - } - } -} - -dependencies { - compileOnly files('@@mode_folder@@/org.eclipse.jdt.core.jar') - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:@@appcompat_version@@' - implementation 'com.google.ar:core:@@gar_version@@' - implementation files('libs/processing-core.jar') - implementation files('libs/ar.jar') -} diff --git a/mode/templates/ARManifest.xml.tmpl b/mode/templates/ARManifest.xml.tmpl deleted file mode 100644 index 1b31e497b..000000000 --- a/mode/templates/ARManifest.xml.tmpl +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/mode/templates/AppActivity.java.tmpl b/mode/templates/AppActivity.java.tmpl deleted file mode 100644 index 3e24984b4..000000000 --- a/mode/templates/AppActivity.java.tmpl +++ /dev/null @@ -1,57 +0,0 @@ -package @@package_name@@; - -import android.os.Bundle; -import android.content.Intent; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import androidx.appcompat.app.AppCompatActivity; - -import processing.android.PFragment; -import processing.android.CompatUtils; -import processing.core.PApplet; - -public class MainActivity extends AppCompatActivity { - private PApplet sketch; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - FrameLayout frame = new FrameLayout(this); - frame.setId(CompatUtils.getUniqueViewId()); - setContentView(frame, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - - sketch = new @@sketch_class_name@@(); - @@external@@ - PFragment fragment = new PFragment(sketch); - fragment.setView(frame, this); - } - - @Override - public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { - if (sketch != null) { - sketch.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - } - - @Override - public void onNewIntent(Intent intent) { - if (sketch != null) { - sketch.onNewIntent(intent); - } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (sketch != null) { - sketch.onActivityResult(requestCode, resultCode, data); - } - } - - @Override - public void onBackPressed() { - if (sketch != null) { - sketch.onBackPressed(); - } - } -} diff --git a/mode/templates/AppBuild.gradle.tmpl b/mode/templates/AppBuild.gradle.tmpl deleted file mode 100644 index 7774d0368..000000000 --- a/mode/templates/AppBuild.gradle.tmpl +++ /dev/null @@ -1,59 +0,0 @@ -apply plugin: 'com.android.application' - -android { - sourceSets { - main.jni.srcDirs = [] - main.jniLibs.srcDirs = ['libs'] - } - compileSdkVersion @@target_sdk@@ - defaultConfig { - applicationId "@@package_name@@" - minSdkVersion @@min_sdk@@ - targetSdkVersion @@target_sdk@@ - versionCode @@version_code@@ - versionName "@@version_name@@" - vectorDrawables.useSupportLibrary = true - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - signingConfigs { - release { - if (project.hasProperty('PROCESSING_UPLOAD_KEYSTORE_FILE')) { - storeFile file(PROCESSING_UPLOAD_KEYSTORE_FILE) - storePassword PROCESSING_UPLOAD_STORE_PASSWORD - keyAlias PROCESSING_UPLOAD_KEY_ALIAS - keyPassword PROCESSING_UPLOAD_KEY_PASSWORD - } - } - } - buildTypes { - debug { - debuggable true - } - release { - minifyEnabled false - signingConfig signingConfigs.release - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - lintOptions { - abortOnError false - } - aaptOptions { - noCompress "tflite" - noCompress "lite" - } -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'androidx.appcompat:appcompat:@@appcompat_version@@' - implementation files('libs/processing-core.jar') - androidTestImplementation 'com.android.support.test:runner:1.3.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - testImplementation 'junit:junit:4.13' -} - diff --git a/mode/templates/AppBuildECJ.gradle.tmpl b/mode/templates/AppBuildECJ.gradle.tmpl deleted file mode 100644 index 6e2d7f055..000000000 --- a/mode/templates/AppBuildECJ.gradle.tmpl +++ /dev/null @@ -1,104 +0,0 @@ -apply plugin: 'com.android.application' - -android { - sourceSets { - main.jni.srcDirs = [] - main.jniLibs.srcDirs = ['libs'] - } - compileSdkVersion @@target_sdk@@ - defaultConfig { - applicationId "@@package_name@@" - minSdkVersion @@min_sdk@@ - targetSdkVersion @@target_sdk@@ - versionCode @@version_code@@ - versionName "@@version_name@@" - vectorDrawables.useSupportLibrary = true - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - signingConfigs { - release { - if (project.hasProperty('PROCESSING_UPLOAD_KEYSTORE_FILE')) { - storeFile file(PROCESSING_UPLOAD_KEYSTORE_FILE) - storePassword PROCESSING_UPLOAD_STORE_PASSWORD - keyAlias PROCESSING_UPLOAD_KEY_ALIAS - keyPassword PROCESSING_UPLOAD_KEY_PASSWORD - } - } - } - buildTypes { - debug { - debuggable true - } - release { - minifyEnabled false - signingConfig signingConfigs.release - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - lintOptions { - abortOnError false - } - aaptOptions { - noCompress "tflite" - noCompress "lite" - } - - // We create a variant of the compile task, where we use the Eclipse Compiler for Java - // (ECJ) instead of the JDK (which would require the user to download and install - // the Oracle JDK). Inspired by the following: - // https://github.com/bytedeco/javacpp/wiki/Gradle - // https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.JavaCompile.html - applicationVariants.all { variant -> - variant.javaCompileProvider.get().doFirst { - // The main class that runs the Eclipse batch compiler - String ecjMain = 'org.eclipse.jdt.internal.compiler.batch.Main' - - // We construct the list of arguments needed by the batch compiler - // https://help.eclipse.org/neon/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-using_batch_compiler.htm - List ecjArgs = ['-nowarn', - '-source', variant.javaCompileProvider.get().sourceCompatibility, - '-target', variant.javaCompileProvider.get().targetCompatibility, - '-d', variant.javaCompileProvider.get().destinationDir] as String[] - - // Set the debug attributes level according to the build target - if (variant.name == 'debug') { - // All debug info - ecjArgs += '-g' - } else { - // No debug info - ecjArgs += '-g:none' - } - - // Adding all the source files to the list of arguments - ecjArgs += variant.javaCompileProvider.get().source - - // Add the Android jar to the classpath inherited from the task - FileCollection ecjClasspath = files('@@target_platform@@/android.jar', - variant.javaCompileProvider.get().classpath) - - // Running the JavaExec task, which requires the main class to run, - // the classpath, and the list of arguments - // https://docs.gradle.org/4.4/dsl/org.gradle.api.tasks.JavaExec.html#org.gradle.api.tasks.JavaExec:main - javaexec { - main ecjMain - classpath ecjClasspath - args ecjArgs - } - - // We skip the rest of the compileXxxJavaWithJavac task, since we - // source is already compiled with ecj - throw new StopExecutionException("skip javac") - } - } -} - -dependencies { - compileOnly files('@@mode_folder@@/org.eclipse.jdt.core.jar') - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:@@appcompat_version@@' - implementation files('libs/processing-core.jar') -} diff --git a/mode/templates/AppManifest.xml.tmpl b/mode/templates/AppManifest.xml.tmpl deleted file mode 100644 index 4f1abe5ef..000000000 --- a/mode/templates/AppManifest.xml.tmpl +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/mode/templates/ExpProperties.gradle.tmpl b/mode/templates/ExpProperties.gradle.tmpl deleted file mode 100644 index 777b6aad8..000000000 --- a/mode/templates/ExpProperties.gradle.tmpl +++ /dev/null @@ -1,3 +0,0 @@ -org.gradle.jvmargs=-Xmx1536m -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/mode/templates/LayoutActivity.xml.tmpl b/mode/templates/LayoutActivity.xml.tmpl deleted file mode 100644 index 012ad5a34..000000000 --- a/mode/templates/LayoutActivity.xml.tmpl +++ /dev/null @@ -1,7 +0,0 @@ - \ No newline at end of file diff --git a/mode/templates/Properties.gradle.tmpl b/mode/templates/Properties.gradle.tmpl deleted file mode 100644 index 6511be76b..000000000 --- a/mode/templates/Properties.gradle.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -org.gradle.jvmargs=-Xmx1536m -android.enableJetifier=true -android.useAndroidX=true - -PROCESSING_UPLOAD_KEYSTORE_FILE=@@keystore_file@@ -PROCESSING_UPLOAD_KEY_ALIAS=@@key_alias@@ -PROCESSING_UPLOAD_STORE_PASSWORD=@@key_password@@ -PROCESSING_UPLOAD_KEY_PASSWORD=@@key_password@@ - - - - diff --git a/mode/templates/Properties.local.tmpl b/mode/templates/Properties.local.tmpl deleted file mode 100644 index ee51efb73..000000000 --- a/mode/templates/Properties.local.tmpl +++ /dev/null @@ -1 +0,0 @@ -sdk.dir=@@sdk_path@@ \ No newline at end of file diff --git a/mode/templates/Settings.gradle.tmpl b/mode/templates/Settings.gradle.tmpl deleted file mode 100644 index e6bbec22c..000000000 --- a/mode/templates/Settings.gradle.tmpl +++ /dev/null @@ -1 +0,0 @@ -include @@project_modules@@ diff --git a/mode/templates/StringsWallpaper.xml.tmpl b/mode/templates/StringsWallpaper.xml.tmpl deleted file mode 100644 index dccf2cf3c..000000000 --- a/mode/templates/StringsWallpaper.xml.tmpl +++ /dev/null @@ -1,3 +0,0 @@ - - @@sketch_class_name@@ - \ No newline at end of file diff --git a/mode/templates/StylesAR.xml.tmpl b/mode/templates/StylesAR.xml.tmpl deleted file mode 100644 index 38b270523..000000000 --- a/mode/templates/StylesAR.xml.tmpl +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/mode/templates/StylesFragment.xml.tmpl b/mode/templates/StylesFragment.xml.tmpl deleted file mode 100644 index 2ae9b9544..000000000 --- a/mode/templates/StylesFragment.xml.tmpl +++ /dev/null @@ -1,8 +0,0 @@ - - - \ No newline at end of file diff --git a/mode/templates/StylesVR.xml.tmpl b/mode/templates/StylesVR.xml.tmpl deleted file mode 100644 index 30903bcbd..000000000 --- a/mode/templates/StylesVR.xml.tmpl +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/mode/templates/TopBuild.gradle.tmpl b/mode/templates/TopBuild.gradle.tmpl deleted file mode 100644 index ef01cc08e..000000000 --- a/mode/templates/TopBuild.gradle.tmpl +++ /dev/null @@ -1,29 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:@@gradle_plugin_version@@' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - maven { url "https://maven.google.com" } - maven { url "https://jitpack.io" } - maven { url 'https://repo.gradle.org/gradle/libs-releases' } - google() - mavenCentral() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/mode/templates/VRActivity.java.tmpl b/mode/templates/VRActivity.java.tmpl deleted file mode 100644 index 304996a34..000000000 --- a/mode/templates/VRActivity.java.tmpl +++ /dev/null @@ -1,16 +0,0 @@ -package @@package_name@@; - -import android.os.Bundle; - -import processing.vr.VRActivity; -import processing.core.PApplet; - -public class MainActivity extends VRActivity { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - PApplet sketch = new @@sketch_class_name@@(); - @@external@@ - setSketch(sketch); - } -} \ No newline at end of file diff --git a/mode/templates/VRBuild.gradle.tmpl b/mode/templates/VRBuild.gradle.tmpl deleted file mode 100644 index 86883c131..000000000 --- a/mode/templates/VRBuild.gradle.tmpl +++ /dev/null @@ -1,59 +0,0 @@ -apply plugin: 'com.android.application' - -android { - sourceSets { - main.jni.srcDirs = [] - main.jniLibs.srcDirs = ['libs'] - } - compileSdkVersion @@target_sdk@@ - defaultConfig { - applicationId "@@package_name@@" - minSdkVersion @@min_sdk@@ - targetSdkVersion @@target_sdk@@ - versionCode @@version_code@@ - versionName "@@version_name@@" - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - signingConfigs { - release { - if (project.hasProperty('PROCESSING_UPLOAD_KEYSTORE_FILE')) { - storeFile file(PROCESSING_UPLOAD_KEYSTORE_FILE) - storePassword PROCESSING_UPLOAD_STORE_PASSWORD - keyAlias PROCESSING_UPLOAD_KEY_ALIAS - keyPassword PROCESSING_UPLOAD_KEY_PASSWORD - } - } - } - buildTypes { - debug { - debuggable true - } - release { - minifyEnabled false - signingConfig signingConfigs.release - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - lintOptions { - abortOnError false - } - aaptOptions { - noCompress "tflite" - noCompress "lite" - } -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'androidx.appcompat:appcompat:@@appcompat_version@@' - implementation 'com.google.vr:sdk-audio:@@gvr_version@@' - implementation 'com.google.vr:sdk-base:@@gvr_version@@' - implementation files('libs/processing-core.jar') - implementation files('libs/vr.jar') - androidTestImplementation 'com.android.support.test:runner:1.3.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - testImplementation 'junit:junit:4.13' -} diff --git a/mode/templates/VRBuildECJ.gradle.tmpl b/mode/templates/VRBuildECJ.gradle.tmpl deleted file mode 100644 index f5a0c12cc..000000000 --- a/mode/templates/VRBuildECJ.gradle.tmpl +++ /dev/null @@ -1,105 +0,0 @@ -apply plugin: 'com.android.application' - -android { - sourceSets { - main.jni.srcDirs = [] - main.jniLibs.srcDirs = ['libs'] - } - compileSdkVersion @@target_sdk@@ - defaultConfig { - applicationId "@@package_name@@" - minSdkVersion @@min_sdk@@ - targetSdkVersion @@target_sdk@@ - versionCode @@version_code@@ - versionName "@@version_name@@" - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - signingConfigs { - release { - if (project.hasProperty('PROCESSING_UPLOAD_KEYSTORE_FILE')) { - storeFile file(PROCESSING_UPLOAD_KEYSTORE_FILE) - storePassword PROCESSING_UPLOAD_STORE_PASSWORD - keyAlias PROCESSING_UPLOAD_KEY_ALIAS - keyPassword PROCESSING_UPLOAD_KEY_PASSWORD - } - } - } - buildTypes { - debug { - debuggable true - } - release { - minifyEnabled false - signingConfig signingConfigs.release - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - lintOptions { - abortOnError false - } - aaptOptions { - noCompress "tflite" - noCompress "lite" - } - - // We create a variant of the compile task, where we use the Eclipse Compiler for Java - // (ECJ) instead of the JDK (which would require the user to download and install - // the Oracle JDK). Inspired by the following: - // https://github.com/bytedeco/javacpp/wiki/Gradle - // https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.JavaCompile.html - applicationVariants.all { variant -> - variant.javaCompileProvider.get().doFirst { - // The main class that runs the Eclipse batch compiler - String ecjMain = 'org.eclipse.jdt.internal.compiler.batch.Main' - - // We construct the list of arguments needed by the batch compiler - // https://help.eclipse.org/neon/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-using_batch_compiler.htm - List ecjArgs = ['-nowarn', - '-source', variant.javaCompileProvider.get().sourceCompatibility, - '-target', variant.javaCompileProvider.get().targetCompatibility, - '-d', variant.javaCompileProvider.get().destinationDir] as String[] - - // Set the debug attributes level according to the build target - if (variant.name == 'debug') { - // All debug info - ecjArgs += '-g' - } else { - // No debug info - ecjArgs += '-g:none' - } - - // Adding all the source files to the list of arguments - ecjArgs += variant.javaCompileProvider.get().source - - // Add the Android jar to the classpath inherited from the task - FileCollection ecjClasspath = files('@@target_platform@@/android.jar', - variant.javaCompileProvider.get().classpath) - - // Running the JavaExec task, which requires the main class to run, - // the classpath, and the list of arguments - // https://docs.gradle.org/3.5/dsl/org.gradle.api.tasks.JavaExec.html#org.gradle.api.tasks.JavaExec:main - javaexec { - main ecjMain - classpath ecjClasspath - args ecjArgs - } - - // We skip the rest of the compileXxxJavaWithJavac task, since we - // source is already compiled with ecj - throw new StopExecutionException("skip javac") - } - } -} - -dependencies { - compileOnly files('@@mode_folder@@/org.eclipse.jdt.core.jar') - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:@@appcompat_version@@' - implementation 'com.google.vr:sdk-audio:@@gvr_version@@' - implementation 'com.google.vr:sdk-base:@@gvr_version@@' - implementation files('libs/processing-core.jar') - implementation files('libs/vr.jar') -} diff --git a/mode/templates/VRManifest.xml.tmpl b/mode/templates/VRManifest.xml.tmpl deleted file mode 100644 index 0c550cfa0..000000000 --- a/mode/templates/VRManifest.xml.tmpl +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mode/templates/WallpaperManifest.xml.tmpl b/mode/templates/WallpaperManifest.xml.tmpl deleted file mode 100644 index baec25eb5..000000000 --- a/mode/templates/WallpaperManifest.xml.tmpl +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - diff --git a/mode/templates/WallpaperService.java.tmpl b/mode/templates/WallpaperService.java.tmpl deleted file mode 100644 index f38471b68..000000000 --- a/mode/templates/WallpaperService.java.tmpl +++ /dev/null @@ -1,13 +0,0 @@ -package @@package_name@@; - -import processing.android.PWallpaper; -import processing.core.PApplet; - -public class MainService extends PWallpaper { - @Override - public PApplet createSketch() { - PApplet sketch = new @@sketch_class_name@@(); - @@external@@ - return sketch; - } -} \ No newline at end of file diff --git a/mode/templates/WatchFaceManifest.xml.tmpl b/mode/templates/WatchFaceManifest.xml.tmpl deleted file mode 100644 index 28d8119da..000000000 --- a/mode/templates/WatchFaceManifest.xml.tmpl +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mode/templates/WatchFaceService.java.tmpl b/mode/templates/WatchFaceService.java.tmpl deleted file mode 100644 index ab322ba86..000000000 --- a/mode/templates/WatchFaceService.java.tmpl +++ /dev/null @@ -1,13 +0,0 @@ -package @@package_name@@; - -import processing.android.@@watchface_classs@@; -import processing.core.PApplet; - -public class MainService extends @@watchface_classs@@ { - @Override - public PApplet createSketch() { - PApplet sketch = new @@sketch_class_name@@(); - @@external@@ - return sketch; - } -} \ No newline at end of file diff --git a/mode/templates/WearBuild.gradle.tmpl b/mode/templates/WearBuild.gradle.tmpl deleted file mode 100644 index 25b37049b..000000000 --- a/mode/templates/WearBuild.gradle.tmpl +++ /dev/null @@ -1,51 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion @@target_sdk@@ - defaultConfig { - applicationId "@@package_name@@" - minSdkVersion @@min_sdk@@ - targetSdkVersion @@target_sdk@@ - versionCode @@version_code@@ - versionName "@@version_name@@" - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - signingConfigs { - release { - if (project.hasProperty('PROCESSING_UPLOAD_KEYSTORE_FILE')) { - storeFile file(PROCESSING_UPLOAD_KEYSTORE_FILE) - storePassword PROCESSING_UPLOAD_STORE_PASSWORD - keyAlias PROCESSING_UPLOAD_KEY_ALIAS - keyPassword PROCESSING_UPLOAD_KEY_PASSWORD - } - } - } - buildTypes { - debug { - debuggable true - } - release { - minifyEnabled false - signingConfig signingConfigs.release - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - lintOptions { - abortOnError false - } - aaptOptions { - noCompress "tflite" - noCompress "lite" - } -} - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.google.android.gms:play-services-wearable:@@play_services_version@@' - implementation 'com.google.android.support:wearable:@@wear_version@@' - compileOnly 'com.google.android.wearable:wearable:@@wear_version@@' - implementation files('libs/processing-core.jar') -} diff --git a/mode/templates/WearBuildECJ.gradle.tmpl b/mode/templates/WearBuildECJ.gradle.tmpl deleted file mode 100644 index 518aa96d8..000000000 --- a/mode/templates/WearBuildECJ.gradle.tmpl +++ /dev/null @@ -1,104 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion @@target_sdk@@ - defaultConfig { - applicationId "@@package_name@@" - minSdkVersion @@min_sdk@@ - targetSdkVersion @@target_sdk@@ - versionCode @@version_code@@ - versionName "@@version_name@@" - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - signingConfigs { - release { - if (project.hasProperty('PROCESSING_UPLOAD_KEYSTORE_FILE')) { - storeFile file(PROCESSING_UPLOAD_KEYSTORE_FILE) - storePassword PROCESSING_UPLOAD_STORE_PASSWORD - keyAlias PROCESSING_UPLOAD_KEY_ALIAS - keyPassword PROCESSING_UPLOAD_KEY_PASSWORD - } - } - } - buildTypes { - debug { - debuggable true - } - release { - minifyEnabled false - signingConfig signingConfigs.release - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - lintOptions { - abortOnError false - } - aaptOptions { - noCompress "tflite" - noCompress "lite" - } - - // We create a variant of the compile task, where we use the Eclipse Compiler for Java - // (ECJ) instead of the JDK (which would require the user to download and install - // the Oracle JDK). Inspired by the following: - // https://github.com/bytedeco/javacpp/wiki/Gradle - // https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.JavaCompile.html - applicationVariants.all { variant -> - variant.javaCompileProvider.get().doFirst { - // The main class that runs the Eclipse batch compiler - String ecjMain = 'org.eclipse.jdt.internal.compiler.batch.Main' - - // We construct the list of arguments needed by the batch compiler - // https://help.eclipse.org/neon/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-using_batch_compiler.htm - List ecjArgs = ['-nowarn', - '-source', variant.javaCompileProvider.get().sourceCompatibility, - '-target', variant.javaCompileProvider.get().targetCompatibility, - '-d', variant.javaCompileProvider.get().destinationDir] as String[] - - // Set the debug attributes level according to the build target - if (variant.name == 'debug') { - // All debug info - ecjArgs += '-g' - } else { - // No debug info - ecjArgs += '-g:none' - } - - // Adding all the source files to the list of arguments - ecjArgs += variant.javaCompileProvider.get().source - - // Add the Android jar to the classpath inherited from the task - FileCollection ecjClasspath = files('@@target_platform@@/android.jar', - variant.javaCompileProvider.get().classpath) - - // Running the JavaExec task, which requires the main class to run, - // the classpath, and the list of arguments - // https://docs.gradle.org/3.5/dsl/org.gradle.api.tasks.JavaExec.html#org.gradle.api.tasks.JavaExec:main - javaexec { - main ecjMain - classpath ecjClasspath - args ecjArgs - } - - // We skip the rest of the compileXxxJavaWithJavac task, since we - // source is already compiled with ecj - throw new StopExecutionException("skip javac") - } - } -} - -dependencies { - compileOnly files('@@mode_folder@@/org.eclipse.jdt.core.jar') - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.google.android.gms:play-services-wearable:@@play_services_version@@' - implementation 'com.google.android.support:wearable:@@wear_version@@' - compileOnly 'com.google.android.wearable:wearable:@@wear_version@@' - implementation files('libs/processing-core.jar') -} - - - - \ No newline at end of file diff --git a/mode/templates/XMLWallpaper.xml.tmpl b/mode/templates/XMLWallpaper.xml.tmpl deleted file mode 100644 index 4c5057c56..000000000 --- a/mode/templates/XMLWallpaper.xml.tmpl +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/mode/templates/XMLWatchFace.xml.tmpl b/mode/templates/XMLWatchFace.xml.tmpl deleted file mode 100644 index 27199e957..000000000 --- a/mode/templates/XMLWatchFace.xml.tmpl +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/mode/theme/completion/class_obj-1x.png b/mode/theme/completion/class_obj-1x.png deleted file mode 100644 index 7ea06bb70..000000000 Binary files a/mode/theme/completion/class_obj-1x.png and /dev/null differ diff --git a/mode/theme/completion/class_obj-2x.png b/mode/theme/completion/class_obj-2x.png deleted file mode 100644 index 0f7b25331..000000000 Binary files a/mode/theme/completion/class_obj-2x.png and /dev/null differ diff --git a/mode/theme/completion/field_default_obj-1x.png b/mode/theme/completion/field_default_obj-1x.png deleted file mode 100644 index 10f8e61c5..000000000 Binary files a/mode/theme/completion/field_default_obj-1x.png and /dev/null differ diff --git a/mode/theme/completion/field_default_obj-2x.png b/mode/theme/completion/field_default_obj-2x.png deleted file mode 100644 index 093ae9c8a..000000000 Binary files a/mode/theme/completion/field_default_obj-2x.png and /dev/null differ diff --git a/mode/theme/completion/field_protected_obj-1x.png b/mode/theme/completion/field_protected_obj-1x.png deleted file mode 100644 index 4858d93e6..000000000 Binary files a/mode/theme/completion/field_protected_obj-1x.png and /dev/null differ diff --git a/mode/theme/completion/field_protected_obj-2x.png b/mode/theme/completion/field_protected_obj-2x.png deleted file mode 100644 index bdd9ab600..000000000 Binary files a/mode/theme/completion/field_protected_obj-2x.png and /dev/null differ diff --git a/mode/theme/completion/methpub_obj-1x.png b/mode/theme/completion/methpub_obj-1x.png deleted file mode 100644 index 7e9e3aeee..000000000 Binary files a/mode/theme/completion/methpub_obj-1x.png and /dev/null differ diff --git a/mode/theme/completion/methpub_obj-2x.png b/mode/theme/completion/methpub_obj-2x.png deleted file mode 100644 index cf64cb75b..000000000 Binary files a/mode/theme/completion/methpub_obj-2x.png and /dev/null differ diff --git a/mode/theme/debug/breakpoint-enabled-1x.png b/mode/theme/debug/breakpoint-enabled-1x.png deleted file mode 100644 index db540e8b2..000000000 Binary files a/mode/theme/debug/breakpoint-enabled-1x.png and /dev/null differ diff --git a/mode/theme/debug/breakpoint-enabled-2x.png b/mode/theme/debug/breakpoint-enabled-2x.png deleted file mode 100644 index 426ddbf75..000000000 Binary files a/mode/theme/debug/breakpoint-enabled-2x.png and /dev/null differ diff --git a/mode/theme/debug/continue-enabled-1x.png b/mode/theme/debug/continue-enabled-1x.png deleted file mode 100644 index f43171df4..000000000 Binary files a/mode/theme/debug/continue-enabled-1x.png and /dev/null differ diff --git a/mode/theme/debug/continue-enabled-2x.png b/mode/theme/debug/continue-enabled-2x.png deleted file mode 100644 index 49c3687b9..000000000 Binary files a/mode/theme/debug/continue-enabled-2x.png and /dev/null differ diff --git a/mode/theme/debug/step-enabled-1x.png b/mode/theme/debug/step-enabled-1x.png deleted file mode 100644 index 2217cd8b3..000000000 Binary files a/mode/theme/debug/step-enabled-1x.png and /dev/null differ diff --git a/mode/theme/debug/step-enabled-2x.png b/mode/theme/debug/step-enabled-2x.png deleted file mode 100644 index b4e0f329d..000000000 Binary files a/mode/theme/debug/step-enabled-2x.png and /dev/null differ diff --git a/mode/theme/variables-1x.png b/mode/theme/variables-1x.png deleted file mode 100644 index b20038b48..000000000 Binary files a/mode/theme/variables-1x.png and /dev/null differ diff --git a/mode/theme/variables-2x.png b/mode/theme/variables-2x.png deleted file mode 100644 index 134701d1e..000000000 Binary files a/mode/theme/variables-2x.png and /dev/null differ diff --git a/mode/tools/SDKUpdater/.classpath b/mode/tools/SDKUpdater/.classpath deleted file mode 100644 index e79c28a0d..000000000 --- a/mode/tools/SDKUpdater/.classpath +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/mode/tools/SDKUpdater/.gitignore b/mode/tools/SDKUpdater/.gitignore deleted file mode 100644 index de7299333..000000000 --- a/mode/tools/SDKUpdater/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -bin -build -tool/SDKUpdater.jar diff --git a/mode/tools/SDKUpdater/.project b/mode/tools/SDKUpdater/.project deleted file mode 100644 index 4dc71227b..000000000 --- a/mode/tools/SDKUpdater/.project +++ /dev/null @@ -1,34 +0,0 @@ - - - android-mode-sdkupdater - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.buildship.core.gradleprojectnature - - - - 1650246874238 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - - diff --git a/mode/tools/SDKUpdater/.settings/org.eclipse.buildship.core.prefs b/mode/tools/SDKUpdater/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index e8895216f..000000000 --- a/mode/tools/SDKUpdater/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,2 +0,0 @@ -connection.project.dir= -eclipse.preferences.version=1 diff --git a/mode/tools/SDKUpdater/.settings/org.eclipse.jdt.core.prefs b/mode/tools/SDKUpdater/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 6558ab78f..000000000 --- a/mode/tools/SDKUpdater/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,12 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=17 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=17 diff --git a/mode/tools/SDKUpdater/build.gradle b/mode/tools/SDKUpdater/build.gradle deleted file mode 100644 index a47fffbb1..000000000 --- a/mode/tools/SDKUpdater/build.gradle +++ /dev/null @@ -1,62 +0,0 @@ -import java.nio.file.Files -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; - -configurations { - implementation.extendsFrom implementationCopy -} - -dependencies { - // implementation group: "org.processing", name: "pde", version: "${processingVersion}" - // implementation group: "org.processing", name: "java-mode", version: "${processingVersion}" - implementation fileTree(include: ["AndroidMode.jar", "pde.jar", "JavaMode.jar"], dir: '../../mode') - - implementationCopy group: "com.android.tools", name: "sdklib", version: "${toolsLibVersion}" - implementationCopy group: "com.android.tools", name: "repository", version: "${toolsLibVersion}" - implementationCopy group: "com.android.tools", name: "common", version: "${toolsLibVersion}" -} - -// This task copies the gradle tooling jar into the mode folder -task copyToLib(type: Copy) { - from configurations.implementationCopy.files { - - include '**/common-*jar' - include '**/commons-compress-*jar' - include '**/guava-*jar' - include '**/httpcore-*jar' - include '**/istack-*jar' - include '**/jakarta.activation-api-*jar' - include '**/jakarta.xml.bind-api-*jar' - include '**/jaxb-runtime-*jar' - include '**/kotlin-stdlib-1*jar' - include '**/shared-*jar' - include '**/protos-*jar' - include '**/protob*jar' - include '**/sdklib-*jar' - include '**/repository-*jar' - - } - into "lib" -} -build.dependsOn(copyToLib) -compileJava.dependsOn(':mode:copyToLib') - -sourceSets { - main { - java { - srcDirs = ["src/"] - } - } -} - -clean.doFirst { - delete "tool" - delete "lib" -} - -build.doLast { - // Copy jar file to tool folder - File toolJar = file("tool/SDKUpdater.jar"); - toolJar.mkdirs(); - Files.copy(file("$buildDir/libs/SDKUpdater.jar").toPath(), - toolJar.toPath(), REPLACE_EXISTING); -} diff --git a/mode/tools/SDKUpdater/src/processing/mode/android/tools/SDKUpdater.java b/mode/tools/SDKUpdater/src/processing/mode/android/tools/SDKUpdater.java deleted file mode 100644 index 685b6716c..000000000 --- a/mode/tools/SDKUpdater/src/processing/mode/android/tools/SDKUpdater.java +++ /dev/null @@ -1,654 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2017 The Processing Foundation - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -package processing.mode.android.tools; - -import com.android.repository.api.*; -import com.android.repository.impl.meta.RepositoryPackages; -import com.android.repository.util.InstallerUtil; -import com.android.sdklib.repository.AndroidSdkHandler; -import com.android.sdklib.repository.installer.SdkInstallerUtil; -import com.android.sdklib.repository.legacy.LegacyDownloader; -import com.android.sdklib.tool.sdkmanager.SdkManagerCli; -import com.android.prefs.AndroidLocationsSingleton; - -import processing.app.Base; -import processing.app.Preferences; -import processing.app.tools.Tool; -import processing.app.ui.Toolkit; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.table.DefaultTableModel; - -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Vector; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; - -@SuppressWarnings("serial") -public class SDKUpdater extends JFrame implements PropertyChangeListener, Tool { - final static private int NUM_ROWS = 10; - final static private int COL_WIDTH = Toolkit.zoom(220); - - final static private int BORDER = Toolkit.zoom(13); - final static private int GAP = Toolkit.zoom(13); - final static private int INSET = Toolkit.zoom(1); - final static private int BUTTON_WIDTH = Toolkit.zoom(85); - final static private int BUTTON_HEIGHT = Toolkit.zoom(25); - - // private final Vector columns = new Vector<>(Arrays.asList( -// AndroidMode.getTextString("sdk_updater.name_column"), -// AndroidMode.getTextString("sdk_updater.version_column"), -// AndroidMode.getTextString("sdk_updater.available_column"))); - private final Vector columns = new Vector<>(Arrays.asList( - "Package name", "Installed version", "Available update" )); - - private static final String PROPERTY_CHANGE_QUERY = "query"; - - private File sdkFolder; - - private QueryTask queryTask; - private DownloadTask downloadTask; - private boolean downloadTaskRunning; - - private Vector> packageList; - private DefaultTableModel packageTable; - private int numUpdates; - - private JProgressBar progressBar; - private JLabel status; - private JLabel statusSecondary; - private JButton actionButton; - private JTable table; - - - @Override - public void init(Base base) { - createLayout(base.getActiveEditor() == null); - } - - - @Override - public void run() { - setVisible(true); - String path = Preferences.get("android.sdk.path"); - sdkFolder = new File(path); - queryTask = new QueryTask(); - queryTask.addPropertyChangeListener(this); - queryTask.execute(); -// status.setText(AndroidMode.getTextString("sdk_updater.query_message")); - status.setText("Querying packages..."); - statusSecondary.setText(""); - } - - - @Override - public String getMenuTitle() { -// return AndroidMode.getTextString("menu.android.sdk_updater"); - return "SDK Updater"; - } - - - @Override - public void propertyChange(PropertyChangeEvent evt) { - switch (evt.getPropertyName()) { - case PROPERTY_CHANGE_QUERY: - progressBar.setIndeterminate(false); - if (numUpdates == 0) { - actionButton.setEnabled(false); -// status.setText(AndroidMode.getTextString("sdk_updater.no_updates_message")); - status.setText("No updates available"); - statusSecondary.setText(""); - } else { - actionButton.setEnabled(true); - if (numUpdates == 1) { -// status.setText(AndroidMode.getTextString("sdk_updater.one_updates_message")); - status.setText("1 update found!"); - statusSecondary.setText(""); - } else { -// status.setText(AndroidMode.getTextString("sdk_updater.many_updates_message", numUpdates)); - status.setText(numUpdates + " updates found!"); - statusSecondary.setText(""); - } - } - break; - } - } - - class QueryTask extends SwingWorker { - ProgressIndicator progress; - - QueryTask() { - super(); - progress = new CustomProgressIndicatorToMonitor(); - } - - @Override - protected Object doInBackground() throws Exception { - numUpdates = 0; - packageList = new Vector<>(); - - /* Following code is from listPackages() of com.android.sdklib.tool.SdkManagerCli - with some changes - */ - AndroidSdkHandler mHandler = AndroidSdkHandler.getInstance(AndroidLocationsSingleton.INSTANCE, sdkFolder.toPath()); - - RepoManager mRepoManager = mHandler.getSdkManager(progress); - mRepoManager.loadSynchronously(0, progress, new LegacyDownloader(new SettingsController() { - @Override - public boolean getForceHttp() { - return false; - } - - @Override - public void setForceHttp(boolean b) { } - - @Override - public Channel getChannel() { - return null; - } - - @Override - public boolean getDisableSdkPatches() { - return false; - } - - @Override - public void setDisableSdkPatches(boolean arg0) { - } - }), null); - - RepositoryPackages packages = mRepoManager.getPackages(); - HashMap> installed = new HashMap>(); - for (LocalPackage local : packages.getLocalPackages().values()) { - String path = local.getPath(); - String name = local.getDisplayName(); - String ver = local.getVersion().toString(); - // Remove version from the display name - int rev = name.indexOf(", rev"); - if (-1 < rev) { - name = name.substring(0, rev); - } - int maj = ver.indexOf("."); - if (-1 < maj) { - String major = ver.substring(0, maj); - int pos = name.indexOf(major); - if (-1 < pos) { - name = name.substring(0, pos).trim(); - } - } - installed.put(path, Arrays.asList(name, ver)); - } - - HashMap> updated = new HashMap>(); - for (UpdatablePackage update : packages.getUpdatedPkgs()) { - String path = update.getPath(); - String loc = update.getLocal().getVersion().toString(); - String rem = update.getRemote().getVersion().toString(); - updated.put(path, Arrays.asList(loc, rem)); - } - - for (String path: installed.keySet()) { - Vector info = new Vector<>(); - List locInfo = installed.get(path); - info.add(locInfo.get(0)); - info.add(locInfo.get(1)); - if (updated.containsKey(path)) { - String upVer = updated.get(path).get(1); - info.add(upVer); - numUpdates++; - } else { - info.add(""); - } - packageList.add(info); - } - - return null; - } - - @Override - protected void done() { - super.done(); - - try { - get(); - firePropertyChange(PROPERTY_CHANGE_QUERY, "query", "SUCCESS"); - - if (packageList != null) { - packageTable.setDataVector(packageList, columns); - packageTable.fireTableDataChanged(); - } - } catch (InterruptedException | CancellationException e) { - this.cancel(false); - } catch (ExecutionException e) { - this.cancel(true); - JOptionPane.showMessageDialog(null, - e.getCause().toString(), "Error", JOptionPane.ERROR_MESSAGE); - e.printStackTrace(); - } - } - } - - class DownloadTask extends SwingWorker { - ProgressIndicator progress; - - DownloadTask() { - super(); - progress = new CustomProgressIndicatorToMonitor(); - } - - @Override - protected Object doInBackground() throws Exception { - downloadTaskRunning = true; - - /* Following code is from installPackages() of com.android.sdklib.tool.SdkManagerCli - with some changes - */ - AndroidSdkHandler mHandler = AndroidSdkHandler.getInstance(AndroidLocationsSingleton.INSTANCE, sdkFolder.toPath()); - - CustomSettings settings = new CustomSettings(); - Downloader downloader = new LegacyDownloader(settings); - - RepoManager mRepoManager = mHandler.getSdkManager(progress); - mRepoManager.loadSynchronously(0, progress, downloader, settings); - - List remotes = new ArrayList<>(); - for (String path : settings.getPaths(mRepoManager)) { - RemotePackage p = mRepoManager.getPackages().getRemotePackages().get(path); - if (p == null) { -// progress.logWarning(AndroidMode.getTextString("sdk_updater.warning_failed_finding_package", path)); - progress.logWarning("Failed to find package " + path); - throw new SdkManagerCli.CommandFailedException(); - } - remotes.add(p); - } - remotes = InstallerUtil.computeRequiredPackages( - remotes, mRepoManager.getPackages(), progress); - if (remotes != null) { - for (RemotePackage p : remotes) { - Installer installer = SdkInstallerUtil.findBestInstallerFactory(p, mHandler) - .createInstaller(p, mRepoManager, downloader); - if (!(installer.prepare(progress) && installer.complete(progress))) { - // there was an error, abort. - throw new SdkManagerCli.CommandFailedException(); - } - } - } else { -// progress.logWarning(AndroidMode.getTextString("sdk_updater.warning_failed_computing_dependency_list")); - progress.logWarning("Unable to compute a complete list of dependencies."); - throw new SdkManagerCli.CommandFailedException(); - } - - return null; - } - - @Override - protected void done() { - super.done(); - - try { - get(); - actionButton.setEnabled(false); -// status.setText(AndroidMode.getTextString("sdk_updater.refresh_package_message")); - status.setText("Refreshing packages..."); - statusSecondary.setText(""); - queryTask = new QueryTask(); - queryTask.addPropertyChangeListener(SDKUpdater.this); - queryTask.execute(); - } catch (InterruptedException | CancellationException e) { - this.cancel(true); - } catch (ExecutionException e) { - this.cancel(true); - JOptionPane.showMessageDialog(null, - e.getCause().toString(), "Error", JOptionPane.ERROR_MESSAGE); - e.printStackTrace(); - } finally { - downloadTaskRunning = false; - progressBar.setIndeterminate(false); - } - } - - class CustomSettings implements SettingsController { - /* Dummy implementation with some necessary methods from the original - implementation in com.android.sdklib.tool.SdkManagerCli - */ - @Override - public boolean getForceHttp() { - return false; - } - - @Override - public void setForceHttp(boolean b) { } - - @Override - public Channel getChannel() { - return null; - } - - public java.util.List getPaths(RepoManager mgr) { - List updates = new ArrayList<>(); - for(UpdatablePackage upd : mgr.getPackages().getUpdatedPkgs()) { - if (!upd.getRemote().obsolete()) { - updates.add(upd.getRepresentative().getPath()); - } - } - return updates; - } - - @Override - public boolean getDisableSdkPatches() { - return false; - } - - @Override - public void setDisableSdkPatches(boolean arg0) { - // TODO Auto-generated method stub - - } - } - } - - private void createLayout(final boolean standalone) { - setTitle(getMenuTitle()); - - Container outer = getContentPane(); - outer.removeAll(); - - Box verticalBox = Box.createVerticalBox(); - verticalBox.setBorder(new EmptyBorder(BORDER, BORDER, BORDER, BORDER)); - outer.add(verticalBox); - - /* Packages panel */ - JPanel packagesPanel = new JPanel(); - - BoxLayout boxLayout = new BoxLayout(packagesPanel, BoxLayout.Y_AXIS); - packagesPanel.setLayout(boxLayout); - - // Packages table - packageTable = new DefaultTableModel(NUM_ROWS, columns.size()) { - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - - @Override - public Class getColumnClass(int columnIndex) { - return String.class; - } - }; - - table = new JTable(packageTable) { - @Override - public String getColumnName(int column) { - return columns.get(column); - } - }; - table.setFillsViewportHeight(true); - table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); - table.setRowHeight(Toolkit.zoom(table.getRowHeight())); - Dimension dim = new Dimension(table.getColumnCount() * COL_WIDTH, - table.getRowHeight() * NUM_ROWS); - table.setPreferredScrollableViewportSize(dim); - - packagesPanel.add(new JScrollPane(table)); - - JPanel controlPanel = new JPanel(); - GridBagLayout gridBagLayout = new GridBagLayout(); - controlPanel.setLayout(gridBagLayout); - - GridBagConstraints gbc = new GridBagConstraints(); - gbc.insets = new Insets(INSET, INSET, INSET, INSET); - - status = new JLabel(); - status.setText("Starting up..."); - gbc.gridx = 0; - gbc.gridy = 0; - controlPanel.add(status, gbc); - - statusSecondary = new JLabel(); - statusSecondary.setText("Getting Detailed Information Here..."); - statusSecondary.setFont(new Font("Calibri", Font.PLAIN, 12)); - gbc.gridx = 0; - gbc.gridy = 1; - controlPanel.add(statusSecondary, gbc); - - // Using an indeterminate progress bar from now until we learn - // how to update the fraction of the query/download process: - // https://github.com/processing/processing-android/issues/362 - progressBar = new JProgressBar(); - gbc.gridx = 0; - gbc.gridy = 2; - gbc.weightx = 1.0; - gbc.fill = GridBagConstraints.HORIZONTAL; - controlPanel.add(progressBar, gbc); - - actionButton = new JButton("Update"); // handles Update/Cancel - actionButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (downloadTaskRunning) { // i.e button state is Cancel - cancelTasks(); - } else { // i.e button state is Update - downloadTask = new DownloadTask(); - downloadTask.execute(); - - -// status.setText(AndroidMode.getTextString("sdk_updater.download_package_message")); - status.setText("Downloading available updates..."); - statusSecondary.setText(""); -// actionButton.setText(AndroidMode.getTextString("sdk_updater.cancel_button_label")); - actionButton.setText("Cancel"); - } - } - }); - actionButton.setEnabled(false); - actionButton.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT)); - gbc.gridx = 1; - gbc.gridy = 0; - gbc.weightx = 0.0; - gbc.fill = GridBagConstraints.HORIZONTAL; - controlPanel.add(actionButton, gbc); - - ActionListener disposer = new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { - cancelTasks(); - if (standalone) { - System.exit(0); - } else { - setVisible(false); - } - } - }; - -// JButton closeButton = new JButton(AndroidMode.getTextString("sdk_updater.close_button_label")); - JButton closeButton = new JButton("Close"); - closeButton.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT)); - closeButton.addActionListener(disposer); - closeButton.setEnabled(true); - gbc.gridx = 1; - gbc.gridy = 1; - gbc.weightx = 0.0; - gbc.fill = GridBagConstraints.HORIZONTAL; - controlPanel.add(closeButton, gbc); - - verticalBox.add(packagesPanel); - verticalBox.add(Box.createVerticalStrut(GAP)); - verticalBox.add(controlPanel); - pack(); - - JRootPane root = getRootPane(); - root.setDefaultButton(closeButton); - processing.app.ui.Toolkit.registerWindowCloseKeys(root, disposer); - processing.app.ui.Toolkit.setIcon(this); - - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - cancelTasks(); - super.windowClosing(e); - } - }); - - registerWindowCloseKeys(getRootPane(), disposer); - - setLocationRelativeTo(null); - setResizable(false); - setVisible(false); - } - - public void cancelTasks() { - queryTask.cancel(true); - if (downloadTaskRunning) { - downloadTask.cancel(true); -// status.setText(AndroidMode.getTextString("sdk_updater.download_canceled_message")); - status.setText("Download canceled"); - statusSecondary.setText(""); - JOptionPane.showMessageDialog(null, -// AndroidMode.getTextString("sdk_updater.download_canceled_message"), - "Download canceled", - "Warning", JOptionPane.WARNING_MESSAGE); -// actionButton.setText(AndroidMode.getTextString("sdk_updater.update_button_label")); - actionButton.setText("Update"); - } - } - - - /** - * Registers key events for a Ctrl-W and ESC with an ActionListener - * that will take care of disposing the window. - */ - static public void registerWindowCloseKeys(JRootPane root, - ActionListener disposer) { - KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); - root.registerKeyboardAction(disposer, stroke, - JComponent.WHEN_IN_FOCUSED_WINDOW); - - int modifiers = java.awt.Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx(); - stroke = KeyStroke.getKeyStroke('W', modifiers); - root.registerKeyboardAction(disposer, stroke, - JComponent.WHEN_IN_FOCUSED_WINDOW); - } - - class CustomProgressIndicatorToMonitor implements com.android.repository.api.ProgressIndicator{ - - int percentage = 0; - String progressTextData = ""; - String progressTextDataDetailed = ""; - - @Override - public void setText(String progressText) { - progressTextData = progressText; - } - - @Override - public boolean isCanceled() { - return false; - } - - @Override - public void cancel() { - - } - - @Override - public void setCancellable(boolean cancellable) { - - } - - @Override - public boolean isCancellable() { - return false; - } - - @Override - public void setIndeterminate(boolean indeterminate) { - - } - - @Override - public boolean isIndeterminate() { - return false; - } - - @Override - public void setFraction(double progress) { - if(progress<=1 && progress>=0) { - percentage = ((int)(progress*100)); - // System.out.println("CustomProgressIndicatorToMonitor:Progress Bar Percentage:"+percentage); - progressBar.setValue(percentage); - status.setText(progressTextData+" "+percentage+" % "); - statusSecondary.setText(progressTextDataDetailed); - } - } - - @Override - public double getFraction() { - return 0; - } - - @Override - public void setSecondaryText(String s) { - progressTextDataDetailed = s; - // System.out.println("CustomProgressIndicatorToMonitor:SecondaryText:"+s); - } - - @Override - public void logWarning(String s) { - progressTextDataDetailed = s; - // System.out.println("CustomProgressIndicatorToMonitor:WarningText:"+s); - } - - @Override - public void logWarning(String s, Throwable e) { - - } - - @Override - public void logError(String s) { - progressTextDataDetailed = s; - // System.out.println("CustomProgressIndicatorToMonitor:ErrorText:"+s); - } - - @Override - public void logError(String s, Throwable e) { - - } - - @Override - public void logInfo(String s) { - progressTextDataDetailed = s; - // System.out.println("CustomProgressIndicatorToMonitor:LogInfoText:"+s); - } - } - -} diff --git a/mode/version.properties b/mode/version.properties deleted file mode 100644 index 2a5b3b5df..000000000 --- a/mode/version.properties +++ /dev/null @@ -1,27 +0,0 @@ -# Basics -android-platform = 33 -android-toolslib = 30.3.0 -android-gradle-plugin = 7.1.0 -gradle-wrapper = 7.4.2 - -# Minimum SDK versions for each type of project -android-min-app = 17 -android-min-wallpaper = 17 -android-min-vr = 19 -android-min-ar = 24 -android-min-wear = 25 - -# Dependencies. Latest versions could be found at: -# https://mvnrepository.com -# https://repo.gradle.org -# The format below is group%artifact -androidx.appcompat%appcompat = 1.6.0 -androidx.legacy%legacy-support-v4 = 1.0.0 -com.google.android.support%wearable = 2.9.0 -com.google.android.gms%play-services-wearable = 18.0.0 -com.google.vr = 1.180.0 -com.google.ar = 1.35.0 -org.processing = 4.0.0b7 -org.gradle%gradle-tooling-api = 7.2 -org.slf4j = 1.7.30 -org.eclipse.jdt = 3.19.300 diff --git a/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.jar b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.jar new file mode 100644 index 000000000..96031d83f Binary files /dev/null and b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.jar differ diff --git a/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.jar.md5 b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.jar.md5 new file mode 100644 index 000000000..1d131ce31 --- /dev/null +++ b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.jar.md5 @@ -0,0 +1 @@ +4f0da42cfc32150d346f92cb54ac44e9 \ No newline at end of file diff --git a/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.jar.sha1 b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.jar.sha1 new file mode 100644 index 000000000..8f278fa68 --- /dev/null +++ b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.jar.sha1 @@ -0,0 +1 @@ +c41590881d011eda2aff44adabe730601a435f92 \ No newline at end of file diff --git a/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.pom b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.pom new file mode 100644 index 000000000..0e9d81c19 --- /dev/null +++ b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.pom @@ -0,0 +1,9 @@ + + + 4.0.0 + org.processing.android + processing-core + 4.5.0b5 + POM was created from install:install-file + diff --git a/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.pom.md5 b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.pom.md5 new file mode 100644 index 000000000..41f4585c6 --- /dev/null +++ b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.pom.md5 @@ -0,0 +1 @@ +068628cc61db3257482a3f26f00c069d \ No newline at end of file diff --git a/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.pom.sha1 b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.pom.sha1 new file mode 100644 index 000000000..4f184b85e --- /dev/null +++ b/org/processing/android/processing-core/4.5.0b5/processing-core-4.5.0b5.pom.sha1 @@ -0,0 +1 @@ +3e184e5022e85ff550529b16013c40872d98a16e \ No newline at end of file diff --git a/org/processing/android/processing-core/4.5.1/_remote.repositories b/org/processing/android/processing-core/4.5.1/_remote.repositories new file mode 100644 index 000000000..f0f9b8468 --- /dev/null +++ b/org/processing/android/processing-core/4.5.1/_remote.repositories @@ -0,0 +1,4 @@ +#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice. +#Mon May 29 17:42:51 EDT 2023 +processing-core-4.5.1.pom>= +processing-core-4.5.1.jar>= diff --git a/org/processing/android/processing-core/4.5.1/processing-core-4.5.1.jar b/org/processing/android/processing-core/4.5.1/processing-core-4.5.1.jar new file mode 100644 index 000000000..60347a64c Binary files /dev/null and b/org/processing/android/processing-core/4.5.1/processing-core-4.5.1.jar differ diff --git a/org/processing/android/processing-core/4.5.1/processing-core-4.5.1.pom b/org/processing/android/processing-core/4.5.1/processing-core-4.5.1.pom new file mode 100644 index 000000000..6951cf540 --- /dev/null +++ b/org/processing/android/processing-core/4.5.1/processing-core-4.5.1.pom @@ -0,0 +1,9 @@ + + + 4.0.0 + org.processing.android + processing-core + 4.5.1 + POM was created from install:install-file + diff --git a/org/processing/android/processing-core/4.5/processing-core-4.5.jar b/org/processing/android/processing-core/4.5/processing-core-4.5.jar new file mode 100644 index 000000000..d480eb06e Binary files /dev/null and b/org/processing/android/processing-core/4.5/processing-core-4.5.jar differ diff --git a/org/processing/android/processing-core/4.5/processing-core-4.5.jar.md5 b/org/processing/android/processing-core/4.5/processing-core-4.5.jar.md5 new file mode 100644 index 000000000..14f69bea2 --- /dev/null +++ b/org/processing/android/processing-core/4.5/processing-core-4.5.jar.md5 @@ -0,0 +1 @@ +2abf77533a406630e8ccc61cffbe88fa \ No newline at end of file diff --git a/org/processing/android/processing-core/4.5/processing-core-4.5.jar.sha1 b/org/processing/android/processing-core/4.5/processing-core-4.5.jar.sha1 new file mode 100644 index 000000000..a86a079ec --- /dev/null +++ b/org/processing/android/processing-core/4.5/processing-core-4.5.jar.sha1 @@ -0,0 +1 @@ +5f9736dca7def4c6ad3d5df4bc40a5fd63335483 \ No newline at end of file diff --git a/org/processing/android/processing-core/4.5/processing-core-4.5.pom b/org/processing/android/processing-core/4.5/processing-core-4.5.pom new file mode 100644 index 000000000..5de7a1541 --- /dev/null +++ b/org/processing/android/processing-core/4.5/processing-core-4.5.pom @@ -0,0 +1,9 @@ + + + 4.0.0 + org.processing.android + processing-core + 4.5 + POM was created from install:install-file + diff --git a/org/processing/android/processing-core/4.5/processing-core-4.5.pom.md5 b/org/processing/android/processing-core/4.5/processing-core-4.5.pom.md5 new file mode 100644 index 000000000..d33d18db6 --- /dev/null +++ b/org/processing/android/processing-core/4.5/processing-core-4.5.pom.md5 @@ -0,0 +1 @@ +68453d54939bc7f0396e5c14c76cedd5 \ No newline at end of file diff --git a/org/processing/android/processing-core/4.5/processing-core-4.5.pom.sha1 b/org/processing/android/processing-core/4.5/processing-core-4.5.pom.sha1 new file mode 100644 index 000000000..866f51620 --- /dev/null +++ b/org/processing/android/processing-core/4.5/processing-core-4.5.pom.sha1 @@ -0,0 +1 @@ +c1cd5ed31c22c1e50c42f7a1c553418ef027dcaf \ No newline at end of file diff --git a/org/processing/android/processing-core/4.6.0/_remote.repositories b/org/processing/android/processing-core/4.6.0/_remote.repositories new file mode 100644 index 000000000..b91114c05 --- /dev/null +++ b/org/processing/android/processing-core/4.6.0/_remote.repositories @@ -0,0 +1,4 @@ +#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice. +#Sun Jun 09 23:20:45 EDT 2024 +processing-core-4.6.0.pom>= +processing-core-4.6.0.jar>= diff --git a/org/processing/android/processing-core/4.6.0/processing-core-4.6.0.jar b/org/processing/android/processing-core/4.6.0/processing-core-4.6.0.jar new file mode 100644 index 000000000..7098e7686 Binary files /dev/null and b/org/processing/android/processing-core/4.6.0/processing-core-4.6.0.jar differ diff --git a/org/processing/android/processing-core/4.6.0/processing-core-4.6.0.pom b/org/processing/android/processing-core/4.6.0/processing-core-4.6.0.pom new file mode 100644 index 000000000..7cc77552d --- /dev/null +++ b/org/processing/android/processing-core/4.6.0/processing-core-4.6.0.pom @@ -0,0 +1,9 @@ + + + 4.0.0 + org.processing.android + processing-core + 4.6.0 + POM was created from install:install-file + diff --git a/org/processing/android/processing-core/maven-metadata-local.xml b/org/processing/android/processing-core/maven-metadata-local.xml new file mode 100644 index 000000000..e52728210 --- /dev/null +++ b/org/processing/android/processing-core/maven-metadata-local.xml @@ -0,0 +1,15 @@ + + + org.processing.android + processing-core + + 4.6.0 + + 4.5.0b5 + 4.5 + 4.5.1 + 4.6.0 + + 20240610032045 + + diff --git a/org/processing/android/processing-core/maven-metadata-local.xml.md5 b/org/processing/android/processing-core/maven-metadata-local.xml.md5 new file mode 100644 index 000000000..ba8613347 --- /dev/null +++ b/org/processing/android/processing-core/maven-metadata-local.xml.md5 @@ -0,0 +1 @@ +3d56d37eb1fa310643ef1926a6288637 \ No newline at end of file diff --git a/org/processing/android/processing-core/maven-metadata-local.xml.sha1 b/org/processing/android/processing-core/maven-metadata-local.xml.sha1 new file mode 100644 index 000000000..bdf24eb06 --- /dev/null +++ b/org/processing/android/processing-core/maven-metadata-local.xml.sha1 @@ -0,0 +1 @@ +b2bef88b320e500c81ab70dcf0aa2c00640496df \ No newline at end of file diff --git a/release.sh b/release.sh new file mode 100755 index 000000000..b47d2a0b1 --- /dev/null +++ b/release.sh @@ -0,0 +1,3 @@ +ver=$1 + +mvn install:install-file -DgroupId=org.processing.android -DartifactId=processing-core -Dversion=$ver -Dpackaging=jar -DgeneratePom=true -DlocalRepositoryPath=. -DcreateChecksum=true -Dfile=../pkgs/processing-core-$ver.jar diff --git a/scripts/publish-module.gradle b/scripts/publish-module.gradle deleted file mode 100644 index 5d3fdcb89..000000000 --- a/scripts/publish-module.gradle +++ /dev/null @@ -1,55 +0,0 @@ -apply plugin: 'maven-publish' -apply plugin: 'signing' - -afterEvaluate { - publishing { - publications { - release(MavenPublication) { - artifact(libJar) - artifact(libSrc) - artifact(libMd5) - pom { - groupId = "org.p5android" - artifactId = "${libName}" - version = "${libVersion}" - packaging = "jar" - licenses { - license { - name = "GNU Lesser General Public License, version 2.1" - url = "https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt" - distribution = "repo" - } - } - scm { - connection = 'scm:git:github.com/processing/processing-android.git' - developerConnection = 'scm:git:ssh://github.com/processing/processing-android.git' - url = 'https://github.com/processing/processing-android/tree/master' - } - } - pom.withXml { - def dependenciesNode = asNode().appendNode('dependencies') - libDependencies.each { - def dependencyNode = dependenciesNode.appendNode('dependency') - if (it.name == 'android') { - dependencyNode.appendNode('artifactId', 'android') - dependencyNode.appendNode('scope', 'runtime') - } else { - dependencyNode.appendNode('groupId', it.group) - dependencyNode.appendNode('artifactId', it.name) - dependencyNode.appendNode('version', it.version) - dependencyNode.appendNode('scope', 'implementation') - } - } - } - } - } - } -} - -ext["signing.keyId"] = rootProject.ext["signing.keyId"] -ext["signing.password"] = rootProject.ext["signing.password"] -ext["signing.secretKeyRingFile"] = rootProject.ext["signing.secretKeyRingFile"] - -signing { - sign publishing.publications -} \ No newline at end of file diff --git a/scripts/publish-root.gradle b/scripts/publish-root.gradle deleted file mode 100644 index 166c3bace..000000000 --- a/scripts/publish-root.gradle +++ /dev/null @@ -1,36 +0,0 @@ -// Create variables with empty default values -ext["signing.keyId"] = '' -ext["signing.password"] = '' -ext["signing.secretKeyRingFile"] = '' -ext["ossrhUsername"] = '' -ext["ossrhPassword"] = '' -ext["sonatypeStagingProfileId"] = '' - -File secretPropsFile = project.rootProject.file('local.properties') -if (secretPropsFile.exists()) { - // Read local.properties file first if it exists - Properties p = new Properties() - new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) } - p.each { name, value -> ext[name] = value } -} else { - // Use system environment variables - ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME') - ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD') - ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID') - ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID') - ext["signing.password"] = System.getenv('SIGNING_PASSWORD') - ext["signing.secretKeyRingFile"] = System.getenv('SIGNING_SECRET_KEY_RING_FILE') -} - -// Set up Sonatype repository -nexusPublishing { - repositories { - sonatype { - stagingProfileId = sonatypeStagingProfileId - username = ossrhUsername - password = ossrhPassword - nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) - snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) - } - } -} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 9e3fad4ab..000000000 --- a/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -include ':mode', ':core', ':mode:libraries:vr', ':mode:libraries:ar', 'mode:tools:SDKUpdater' -