From 795a5ec1a8454df5279d3d42ad42d48e31fc1b5a Mon Sep 17 00:00:00 2001 From: Aleksi Sapon Date: Tue, 10 Feb 2015 22:15:05 -0500 Subject: [PATCH 1/8] Add window resizing --- .../flowpowered/caustic/api/gl/Context.java | 7 +++++- .../caustic/lwjgl/gl20/GL20Context.java | 24 +++++++++++-------- .../caustic/software/SoftwareContext.java | 5 ++++ .../caustic/software/SoftwareRenderer.java | 19 +++++++++++---- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/api/src/main/java/com/flowpowered/caustic/api/gl/Context.java b/api/src/main/java/com/flowpowered/caustic/api/gl/Context.java index e3c73cc..efa58f2 100644 --- a/api/src/main/java/com/flowpowered/caustic/api/gl/Context.java +++ b/api/src/main/java/com/flowpowered/caustic/api/gl/Context.java @@ -27,7 +27,6 @@ import com.flowpowered.math.vector.Vector2i; import com.flowpowered.math.vector.Vector4f; - import com.flowpowered.caustic.api.Camera; import com.flowpowered.caustic.api.Creatable; import com.flowpowered.caustic.api.GLVersioned; @@ -109,6 +108,12 @@ public void destroy() { */ public abstract void setWindowTitle(String title); + /** + * Sets if the window can be re-sized. + * @param resizable Whether or not the window can be re-sized + */ + public abstract void setResizable(boolean resizable); + /** * Sets the window size. * diff --git a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Context.java b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Context.java index 8343fc1..0832cc0 100644 --- a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Context.java +++ b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Context.java @@ -25,16 +25,6 @@ import java.nio.ByteBuffer; -import com.flowpowered.math.vector.Vector2i; -import com.flowpowered.math.vector.Vector4f; - -import org.lwjgl.LWJGLException; -import org.lwjgl.opengl.ContextAttribs; -import org.lwjgl.opengl.Display; -import org.lwjgl.opengl.DisplayMode; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.PixelFormat; - import com.flowpowered.caustic.api.gl.Context; import com.flowpowered.caustic.api.gl.FrameBuffer; import com.flowpowered.caustic.api.gl.Program; @@ -46,6 +36,15 @@ import com.flowpowered.caustic.api.util.CausticUtil; import com.flowpowered.caustic.api.util.Rectangle; import com.flowpowered.caustic.lwjgl.LWJGLUtil; +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector4f; + +import org.lwjgl.LWJGLException; +import org.lwjgl.opengl.ContextAttribs; +import org.lwjgl.opengl.Display; +import org.lwjgl.opengl.DisplayMode; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.PixelFormat; /** * An OpenGL 2.0 implementation of {@link com.flowpowered.caustic.api.gl.Context}. @@ -130,6 +129,11 @@ public void setWindowTitle(String title) { Display.setTitle(title); } + @Override + public void setResizable(boolean resizable) { + Display.setResizable(resizable); + } + @Override public void setWindowSize(Vector2i windowSize) { try { diff --git a/software/src/main/java/com/flowpowered/caustic/software/SoftwareContext.java b/software/src/main/java/com/flowpowered/caustic/software/SoftwareContext.java index 4bb1522..e68d470 100644 --- a/software/src/main/java/com/flowpowered/caustic/software/SoftwareContext.java +++ b/software/src/main/java/com/flowpowered/caustic/software/SoftwareContext.java @@ -96,6 +96,11 @@ public void setWindowTitle(String title) { renderer.setWindowTitle(title); } + @Override + public void setResizable(boolean resizable) { + renderer.setWindowResizable(resizable); + } + @Override public void setWindowSize(Vector2i windowSize) { renderer.setWindowSize(windowSize.getX(), windowSize.getY()); diff --git a/software/src/main/java/com/flowpowered/caustic/software/SoftwareRenderer.java b/software/src/main/java/com/flowpowered/caustic/software/SoftwareRenderer.java index 3d96949..51c4990 100644 --- a/software/src/main/java/com/flowpowered/caustic/software/SoftwareRenderer.java +++ b/software/src/main/java/com/flowpowered/caustic/software/SoftwareRenderer.java @@ -37,13 +37,13 @@ import java.awt.image.DataBufferInt; import java.util.Arrays; -import gnu.trove.map.TIntObjectMap; -import gnu.trove.map.hash.TIntObjectHashMap; - import com.flowpowered.caustic.api.gl.Context.Capability; import com.flowpowered.caustic.api.util.CausticUtil; import com.flowpowered.caustic.api.util.Rectangle; +import gnu.trove.map.TIntObjectMap; +import gnu.trove.map.hash.TIntObjectHashMap; + /** * */ @@ -81,6 +81,10 @@ int getWindowWidth() { return width; } + void setWindowResizable(boolean resizable) { + frame.setResizable(resizable); + } + void setWindowSize(int width, int height) { if (this.width != width || this.height != height) { this.width = width; @@ -171,7 +175,9 @@ private void updateImage() { pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); depths = new short[width * height]; frame.pack(); - frame.setLocationRelativeTo(null); + if (!frame.isResizable()) { + frame.setLocationRelativeTo(null); + } } void dispose() { @@ -189,6 +195,11 @@ void render() { graphics.drawImage(image, 0, 0, width * scale, height * scale, null); graphics.dispose(); bufferStrategy.show(); + if (frame.isResizable() && getWidth() != width && getHeight() != height) { + width = getWidth(); + height = getHeight(); + updateImage(); + } } void clearPixels() { From 4ab28dd11baac13f5e6085947ea45d500e575a6a Mon Sep 17 00:00:00 2001 From: Aleksi Sapon Date: Tue, 10 Feb 2015 22:15:29 -0500 Subject: [PATCH 2/8] Improve handling of indices in vertex arrays --- .../caustic/lwjgl/gl20/GL20VertexArray.java | 29 +++++++++---------- .../caustic/lwjgl/gl30/GL30VertexArray.java | 27 ++++++++--------- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20VertexArray.java b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20VertexArray.java index 603b34e..92539a2 100644 --- a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20VertexArray.java +++ b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20VertexArray.java @@ -25,6 +25,12 @@ import java.nio.ByteBuffer; +import com.flowpowered.caustic.api.data.VertexAttribute; +import com.flowpowered.caustic.api.data.VertexAttribute.DataType; +import com.flowpowered.caustic.api.data.VertexData; +import com.flowpowered.caustic.api.gl.VertexArray; +import com.flowpowered.caustic.lwjgl.LWJGLUtil; + import org.lwjgl.opengl.APPLEVertexArrayObject; import org.lwjgl.opengl.ARBVertexArrayObject; import org.lwjgl.opengl.ContextCapabilities; @@ -33,12 +39,6 @@ import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GLContext; -import com.flowpowered.caustic.api.data.VertexAttribute; -import com.flowpowered.caustic.api.data.VertexAttribute.DataType; -import com.flowpowered.caustic.api.data.VertexData; -import com.flowpowered.caustic.api.gl.VertexArray; -import com.flowpowered.caustic.lwjgl.LWJGLUtil; - /** * An OpenGL 2.0 implementation of {@link VertexArray}. *

@@ -143,12 +143,13 @@ public void setData(VertexData vertexData) { } // Unbind the indices buffer GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); - // Update the count to the new one + // Update the total indices count indicesCount = newIndicesCount; - indicesDrawCount = indicesCount; + // Ensure the count fits under the total one + indicesDrawCount = indicesDrawCount <= 0 ? indicesCount : Math.min(indicesDrawCount, indicesCount); // Ensure that the indices offset and count fits inside the valid part of the buffer - indicesOffset = Math.min(indicesOffset, indicesCount - 1); - indicesDrawCount = indicesDrawCount - indicesOffset; + indicesOffset = Math.min(indicesOffset, indicesDrawCount - 1); + indicesDrawCount -= indicesOffset; // Bind the vao if (extension.has()) { extension.glBindVertexArray(id); @@ -245,12 +246,8 @@ public void setIndicesOffset(int offset) { @Override public void setIndicesCount(int count) { - if (count < 0) { - indicesDrawCount = indicesCount; - } else { - indicesDrawCount = count; - } - indicesDrawCount = Math.min(indicesDrawCount, indicesCount - indicesOffset); + indicesDrawCount = count <= 0 ? indicesCount : count; + indicesDrawCount = Math.min(count, indicesCount - indicesOffset); } @Override diff --git a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30VertexArray.java b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30VertexArray.java index 5c6d1a4..6ad0e59 100644 --- a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30VertexArray.java +++ b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30VertexArray.java @@ -25,11 +25,6 @@ import java.nio.ByteBuffer; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL15; -import org.lwjgl.opengl.GL20; -import org.lwjgl.opengl.GL30; - import com.flowpowered.caustic.api.data.VertexAttribute; import com.flowpowered.caustic.api.data.VertexAttribute.DataType; import com.flowpowered.caustic.api.data.VertexAttribute.UploadMode; @@ -37,6 +32,11 @@ import com.flowpowered.caustic.api.gl.VertexArray; import com.flowpowered.caustic.lwjgl.LWJGLUtil; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL30; + /** * An OpenGL 3.0 implementation of {@link VertexArray}. * @@ -112,12 +112,13 @@ public void setData(VertexData vertexData) { } // Unbind the indices buffer GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); - // Update the count to the new one + // Update the total indices count indicesCount = newIndicesCount; - indicesDrawCount = indicesCount; + // Ensure the count fits under the total one + indicesDrawCount = indicesDrawCount <= 0 ? indicesCount : Math.min(indicesDrawCount, indicesCount); // Ensure that the indices offset and count fits inside the valid part of the buffer - indicesOffset = Math.min(indicesOffset, indicesCount - 1); - indicesDrawCount = indicesDrawCount - indicesOffset; + indicesOffset = Math.min(indicesOffset, indicesDrawCount - 1); + indicesDrawCount -= indicesOffset; // Bind the vao GL30.glBindVertexArray(id); // Create a new array of attribute buffers ID of the correct size @@ -203,12 +204,8 @@ public void setIndicesOffset(int offset) { @Override public void setIndicesCount(int count) { - if (count < 0) { - indicesDrawCount = indicesCount; - } else { - indicesDrawCount = count; - } - indicesDrawCount = Math.min(indicesDrawCount, indicesCount - indicesOffset); + indicesDrawCount = count <= 0 ? indicesCount : count; + indicesDrawCount = Math.min(count, indicesCount - indicesOffset); } @Override From 5bccd0824d738e00849644fbf077a2aeb0b41340 Mon Sep 17 00:00:00 2001 From: Aleksi Sapon Date: Tue, 10 Feb 2015 22:15:56 -0500 Subject: [PATCH 3/8] Don't reallocate textures when possible --- .../caustic/lwjgl/gl20/GL20Texture.java | 28 ++++++++++++------- .../caustic/lwjgl/gl30/GL30Texture.java | 21 ++++++++++---- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Texture.java b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Texture.java index 4560419..1ed7a45 100644 --- a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Texture.java +++ b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Texture.java @@ -26,6 +26,10 @@ import java.nio.ByteBuffer; import java.nio.FloatBuffer; +import com.flowpowered.caustic.api.data.VertexAttribute.DataType; +import com.flowpowered.caustic.api.gl.Texture; +import com.flowpowered.caustic.api.util.CausticUtil; +import com.flowpowered.caustic.lwjgl.LWJGLUtil; import com.flowpowered.math.vector.Vector4f; import org.lwjgl.opengl.EXTTextureFilterAnisotropic; @@ -34,11 +38,6 @@ import org.lwjgl.opengl.GL14; import org.lwjgl.util.glu.GLU; -import com.flowpowered.caustic.api.data.VertexAttribute.DataType; -import com.flowpowered.caustic.api.gl.Texture; -import com.flowpowered.caustic.api.util.CausticUtil; -import com.flowpowered.caustic.lwjgl.LWJGLUtil; - /** * An OpenGL 2.0 implementation of {@link Texture}. * @@ -199,6 +198,10 @@ public void setImageData(ByteBuffer imageData, int width, int height) { if (height <= 0) { throw new IllegalArgumentException("Height must be greater than zero"); } + // Back up the old values + int oldWidth = this.width; + int oldHeight = this.height; + // Update the texture width and height this.width = width; this.height = height; // Bind the texture @@ -210,12 +213,17 @@ public void setImageData(ByteBuffer imageData, int width, int height) { GLU.gluBuild2DMipmaps(GL11.GL_TEXTURE_2D, hasInternalFormat ? internalFormat.getGLConstant() : format.getGLConstant(), width, height, format.getGLConstant(), hasInternalFormat ? internalFormat.getComponentType().getGLConstant() : DataType.UNSIGNED_BYTE.getGLConstant(), imageData); } else { - // Else just make it a normal texture - // Use byte alignment + // Else just make it a normal texture, use byte alignment GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1); - // Upload the image - GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, hasInternalFormat ? internalFormat.getGLConstant() : format.getGLConstant(), width, height, 0, format.getGLConstant(), - hasInternalFormat ? internalFormat.getComponentType().getGLConstant() : DataType.UNSIGNED_BYTE.getGLConstant(), imageData); + // Check if we can only upload without reallocating + if (imageData != null && width == oldWidth && height == oldHeight) { + GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, width, height, format.getGLConstant(), + hasInternalFormat ? internalFormat.getComponentType().getGLConstant() : DataType.UNSIGNED_BYTE.getGLConstant(), imageData); + } else { + // Reallocate and upload the image + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, hasInternalFormat ? internalFormat.getGLConstant() : format.getGLConstant(), width, height, 0, format.getGLConstant(), + hasInternalFormat ? internalFormat.getComponentType().getGLConstant() : DataType.UNSIGNED_BYTE.getGLConstant(), imageData); + } } // Unbind the texture GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); diff --git a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30Texture.java b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30Texture.java index eca37be..d0547ee 100644 --- a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30Texture.java +++ b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30Texture.java @@ -25,13 +25,13 @@ import java.nio.ByteBuffer; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL30; - import com.flowpowered.caustic.api.data.VertexAttribute.DataType; import com.flowpowered.caustic.lwjgl.LWJGLUtil; import com.flowpowered.caustic.lwjgl.gl20.GL20Texture; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL30; + /** * An OpenGL 3.0 implementation of {@link com.flowpowered.caustic.api.gl.Texture}. * @@ -47,6 +47,10 @@ public void setImageData(ByteBuffer imageData, int width, int height) { if (height <= 0) { throw new IllegalArgumentException("Height must be greater than zero"); } + // Back up the old values + int oldWidth = this.width; + int oldHeight = this.height; + // Update the texture width and height this.width = width; this.height = height; // Bind the texture @@ -55,8 +59,15 @@ public void setImageData(ByteBuffer imageData, int width, int height) { GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1); // Upload the texture final boolean hasInternalFormat = internalFormat != null; - GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, hasInternalFormat ? internalFormat.getGLConstant() : format.getGLConstant(), width, height, 0, format.getGLConstant(), - hasInternalFormat ? internalFormat.getComponentType().getGLConstant() : DataType.UNSIGNED_BYTE.getGLConstant(), imageData); + // Check if we can only upload without reallocating + if (imageData != null && width == oldWidth && height == oldHeight) { + GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, width, height, format.getGLConstant(), + hasInternalFormat ? internalFormat.getComponentType().getGLConstant() : DataType.UNSIGNED_BYTE.getGLConstant(), imageData); + } else { + // Reallocate and upload the image + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, hasInternalFormat ? internalFormat.getGLConstant() : format.getGLConstant(), width, height, 0, format.getGLConstant(), + hasInternalFormat ? internalFormat.getComponentType().getGLConstant() : DataType.UNSIGNED_BYTE.getGLConstant(), imageData); + } // Generate mipmaps if necessary if (minFilter.needsMipMaps() && imageData != null) { GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D); From 4c89103060dbf6ad89517a1c19d4561087a87bfa Mon Sep 17 00:00:00 2001 From: Luke Spragg Date: Mon, 16 Feb 2015 17:28:22 -0500 Subject: [PATCH 4/8] Setup for deployment and minor cleanup --- .travis.yml | 2 +- android/pom.xml | 38 ---------- .../caustic/android/AndroidUtil.java | 72 ------------------- .../flowpowered/caustic/api/gl/Context.java | 1 + .../caustic/api/model/StringModel.java | 8 +-- .../caustic/api/util/ColladaFileLoader.java | 16 ++--- .../caustic/api/util/MeshGenerator.java | 12 ++-- .../caustic/api/util/ObjFileLoader.java | 4 +- bump.sh | 4 +- .../caustic/lwjgl/gl20/GL20Context.java | 14 ++-- .../caustic/lwjgl/gl20/GL20Program.java | 14 ++-- .../caustic/lwjgl/gl20/GL20Texture.java | 12 ++-- .../caustic/lwjgl/gl20/GL20VertexArray.java | 12 ++-- .../caustic/lwjgl/gl30/GL30Texture.java | 6 +- .../caustic/lwjgl/gl30/GL30VertexArray.java | 10 +-- pom.xml | 3 +- 16 files changed, 59 insertions(+), 169 deletions(-) delete mode 100644 android/pom.xml delete mode 100644 android/src/main/java/com/flowpowered/caustic/android/AndroidUtil.java diff --git a/.travis.yml b/.travis.yml index bcd7c1a..dafaa4a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ jdk: oraclejdk8 install: mvn dependency:go-offline # Compile and test source -script: mvn clean -DbuildNumber=$TRAVIS_BUILD_NUMBER -DciSystem=travis -Dcommit=${TRAVIS_COMMIT:0:7} +script: mvn clean install -DbuildNumber=$TRAVIS_BUILD_NUMBER -DciSystem=travis -Dcommit=${TRAVIS_COMMIT:0:7} # Fetch resources, run deployment goal/task, and generate Javadocs and reports after_success: diff --git a/android/pom.xml b/android/pom.xml deleted file mode 100644 index 878adf9..0000000 --- a/android/pom.xml +++ /dev/null @@ -1,38 +0,0 @@ - - 4.0.0 - - - Caustic Android - caustic-android - jar - Android implementation of the Caustic rendering library API. - - - - com.flowpowered - caustic - 1.0.0-SNAPSHOT - - - - - .. - 4.1.1.4 - - - - - - - ${project.groupId} - caustic-api - ${project.version} - - - com.google.android - android - ${android.version} - - - diff --git a/android/src/main/java/com/flowpowered/caustic/android/AndroidUtil.java b/android/src/main/java/com/flowpowered/caustic/android/AndroidUtil.java deleted file mode 100644 index d7033ea..0000000 --- a/android/src/main/java/com/flowpowered/caustic/android/AndroidUtil.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of Caustic Android, licensed under the MIT License (MIT). - * - * Copyright (c) 2013 Flow Powered - * - * 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 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. - */ -package com.flowpowered.caustic.android; - -import android.opengl.GLES20; -import android.opengl.GLU; - -public final class AndroidUtil { - //public static final GLImplementation GLES20_IMPL = new GLImplementation(GLVersion.GLES20, GLES20GLFactory.class.getName()); - private static boolean debug = true; - - private AndroidUtil() { - } - - /** - * Sets the caustic renderer in debug mode. - * - * @param enabled If debug should be enabled - */ - public static void setDebugEnabled(boolean enabled) { - debug = enabled; - } - - /** - * Throws an exception if OpenGL reports an error. - * - * @throws com.flowpowered.caustic.android.AndroidUtil.GLESException If OpenGL reports an error - */ - public static void checkForGLESError() { - if (debug) { - final int errorValue = GLES20.glGetError(); - if (errorValue != GLES20.GL_NO_ERROR) { - throw new GLESException("OPEN GL ERROR: " + GLU.gluErrorString(errorValue)); - } - } - } - - /** - * An exception throw when a GLES exception occurs on Android. - */ - public static class GLESException extends RuntimeException { - /** - * Constructs a new Android GLES exception from the message. - * - * @param message The error message - */ - public GLESException(String message) { - super(message); - } - } -} diff --git a/api/src/main/java/com/flowpowered/caustic/api/gl/Context.java b/api/src/main/java/com/flowpowered/caustic/api/gl/Context.java index efa58f2..19ca1a1 100644 --- a/api/src/main/java/com/flowpowered/caustic/api/gl/Context.java +++ b/api/src/main/java/com/flowpowered/caustic/api/gl/Context.java @@ -27,6 +27,7 @@ import com.flowpowered.math.vector.Vector2i; import com.flowpowered.math.vector.Vector4f; + import com.flowpowered.caustic.api.Camera; import com.flowpowered.caustic.api.Creatable; import com.flowpowered.caustic.api.GLVersioned; diff --git a/api/src/main/java/com/flowpowered/caustic/api/model/StringModel.java b/api/src/main/java/com/flowpowered/caustic/api/model/StringModel.java index 757490e..1b1b77e 100644 --- a/api/src/main/java/com/flowpowered/caustic/api/model/StringModel.java +++ b/api/src/main/java/com/flowpowered/caustic/api/model/StringModel.java @@ -34,10 +34,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import com.flowpowered.math.GenericMath; -import com.flowpowered.math.vector.Vector2f; -import com.flowpowered.math.vector.Vector4f; - import gnu.trove.impl.Constants; import gnu.trove.list.TFloatList; import gnu.trove.list.TIntList; @@ -49,6 +45,10 @@ import gnu.trove.map.hash.TCharIntHashMap; import gnu.trove.map.hash.TIntObjectHashMap; +import com.flowpowered.math.GenericMath; +import com.flowpowered.math.vector.Vector2f; +import com.flowpowered.math.vector.Vector4f; + import com.flowpowered.caustic.api.Material; import com.flowpowered.caustic.api.data.VertexAttribute; import com.flowpowered.caustic.api.data.VertexAttribute.DataType; diff --git a/api/src/main/java/com/flowpowered/caustic/api/util/ColladaFileLoader.java b/api/src/main/java/com/flowpowered/caustic/api/util/ColladaFileLoader.java index d6e04aa..b896841 100644 --- a/api/src/main/java/com/flowpowered/caustic/api/util/ColladaFileLoader.java +++ b/api/src/main/java/com/flowpowered/caustic/api/util/ColladaFileLoader.java @@ -23,6 +23,12 @@ */ package com.flowpowered.caustic.api.util; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -31,14 +37,6 @@ import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.flowpowered.math.vector.Vector3i; import gnu.trove.list.TFloatList; import gnu.trove.list.TIntList; @@ -52,6 +50,8 @@ import org.w3c.dom.NodeList; import org.xml.sax.SAXException; +import com.flowpowered.math.vector.Vector3i; + /** * A static loading class for the COLLADA file format (.dae). This class has the capability to load mesh data such as positions, texture coordinates, and normals. All models should be triangulated. * Apart from geometry, the COLLADA file format also allows for joint descriptions as well as animation descriptions. COLLADA also allows for physical properties to be assigned to a model which can be diff --git a/api/src/main/java/com/flowpowered/caustic/api/util/MeshGenerator.java b/api/src/main/java/com/flowpowered/caustic/api/util/MeshGenerator.java index db1ce58..ff2790e 100644 --- a/api/src/main/java/com/flowpowered/caustic/api/util/MeshGenerator.java +++ b/api/src/main/java/com/flowpowered/caustic/api/util/MeshGenerator.java @@ -29,6 +29,12 @@ import java.util.List; import java.util.Set; +import gnu.trove.list.TFloatList; +import gnu.trove.list.TIntList; +import gnu.trove.list.array.TFloatArrayList; +import gnu.trove.map.TObjectIntMap; +import gnu.trove.map.hash.TObjectIntHashMap; + import com.flowpowered.math.GenericMath; import com.flowpowered.math.TrigMath; import com.flowpowered.math.matrix.Matrix3f; @@ -37,12 +43,6 @@ import com.flowpowered.math.vector.Vector3f; import com.flowpowered.math.vector.Vector4i; -import gnu.trove.list.TFloatList; -import gnu.trove.list.TIntList; -import gnu.trove.list.array.TFloatArrayList; -import gnu.trove.map.TObjectIntMap; -import gnu.trove.map.hash.TObjectIntHashMap; - import com.flowpowered.caustic.api.data.VertexAttribute; import com.flowpowered.caustic.api.data.VertexAttribute.DataType; import com.flowpowered.caustic.api.data.VertexData; diff --git a/api/src/main/java/com/flowpowered/caustic/api/util/ObjFileLoader.java b/api/src/main/java/com/flowpowered/caustic/api/util/ObjFileLoader.java index cb39b22..16165d0 100644 --- a/api/src/main/java/com/flowpowered/caustic/api/util/ObjFileLoader.java +++ b/api/src/main/java/com/flowpowered/caustic/api/util/ObjFileLoader.java @@ -26,13 +26,13 @@ import java.io.InputStream; import java.util.Scanner; -import com.flowpowered.math.vector.Vector3i; - import gnu.trove.list.TFloatList; import gnu.trove.list.TIntList; import gnu.trove.list.array.TFloatArrayList; import gnu.trove.list.array.TIntArrayList; +import com.flowpowered.math.vector.Vector3i; + /** * A static loading class for standard .obj model files. This class will load positions, normals can texture coordinates. Missing normals are not calculated. Normals are expected to be of unit length. * Models should be triangulated. diff --git a/bump.sh b/bump.sh index e78375f..08800bc 100755 --- a/bump.sh +++ b/bump.sh @@ -10,5 +10,5 @@ read -p "New version: " NEW_VERSION || die_with "Prompt for new version failed" if ! echo $NEW_VERSION | grep -i -- '-SNAPSHOT' >/dev/null; then echo "WARNING: changing to a release version!"; fi echo "Updating the project version in build.gradle, pom.xml and README.md to $NEW_VERSION" -sed -ri "s/"`echo $CURRENT_VERSION | sed 's/\./\\\\./g'`"/$NEW_VERSION/g" build.gradle pom.xml README.md || die_with "Failed to update the project version!" -chmod 644 build.gradle pom.xml README.md +find . \( -name "pom.xml" -o -name "README.md" \) -exec sed -i "s/$CURRENT_VERSION/$NEW_VERSION/g" {} \; die_with "Failed to update the project version!" +chmod -R 644 pom.xml README.md diff --git a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Context.java b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Context.java index 0832cc0..d98308e 100644 --- a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Context.java +++ b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Context.java @@ -25,6 +25,13 @@ import java.nio.ByteBuffer; +import org.lwjgl.LWJGLException; +import org.lwjgl.opengl.ContextAttribs; +import org.lwjgl.opengl.Display; +import org.lwjgl.opengl.DisplayMode; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.PixelFormat; + import com.flowpowered.caustic.api.gl.Context; import com.flowpowered.caustic.api.gl.FrameBuffer; import com.flowpowered.caustic.api.gl.Program; @@ -39,13 +46,6 @@ import com.flowpowered.math.vector.Vector2i; import com.flowpowered.math.vector.Vector4f; -import org.lwjgl.LWJGLException; -import org.lwjgl.opengl.ContextAttribs; -import org.lwjgl.opengl.Display; -import org.lwjgl.opengl.DisplayMode; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.PixelFormat; - /** * An OpenGL 2.0 implementation of {@link com.flowpowered.caustic.api.gl.Context}. * diff --git a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Program.java b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Program.java index 98a1e3b..2e819b3 100644 --- a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Program.java +++ b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Program.java @@ -34,13 +34,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import com.flowpowered.math.matrix.Matrix2f; -import com.flowpowered.math.matrix.Matrix3f; -import com.flowpowered.math.matrix.Matrix4f; -import com.flowpowered.math.vector.Vector2f; -import com.flowpowered.math.vector.Vector3f; -import com.flowpowered.math.vector.Vector4f; - import gnu.trove.impl.Constants; import gnu.trove.iterator.TObjectIntIterator; import gnu.trove.map.TIntObjectMap; @@ -51,6 +44,13 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL20; +import com.flowpowered.math.matrix.Matrix2f; +import com.flowpowered.math.matrix.Matrix3f; +import com.flowpowered.math.matrix.Matrix4f; +import com.flowpowered.math.vector.Vector2f; +import com.flowpowered.math.vector.Vector3f; +import com.flowpowered.math.vector.Vector4f; + import com.flowpowered.caustic.api.gl.Program; import com.flowpowered.caustic.api.gl.Shader; import com.flowpowered.caustic.api.util.CausticUtil; diff --git a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Texture.java b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Texture.java index 1ed7a45..950c0c3 100644 --- a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Texture.java +++ b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20Texture.java @@ -26,18 +26,18 @@ import java.nio.ByteBuffer; import java.nio.FloatBuffer; -import com.flowpowered.caustic.api.data.VertexAttribute.DataType; -import com.flowpowered.caustic.api.gl.Texture; -import com.flowpowered.caustic.api.util.CausticUtil; -import com.flowpowered.caustic.lwjgl.LWJGLUtil; -import com.flowpowered.math.vector.Vector4f; - import org.lwjgl.opengl.EXTTextureFilterAnisotropic; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL14; import org.lwjgl.util.glu.GLU; +import com.flowpowered.caustic.api.data.VertexAttribute.DataType; +import com.flowpowered.caustic.api.gl.Texture; +import com.flowpowered.caustic.api.util.CausticUtil; +import com.flowpowered.caustic.lwjgl.LWJGLUtil; +import com.flowpowered.math.vector.Vector4f; + /** * An OpenGL 2.0 implementation of {@link Texture}. * diff --git a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20VertexArray.java b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20VertexArray.java index 92539a2..919db39 100644 --- a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20VertexArray.java +++ b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl20/GL20VertexArray.java @@ -25,12 +25,6 @@ import java.nio.ByteBuffer; -import com.flowpowered.caustic.api.data.VertexAttribute; -import com.flowpowered.caustic.api.data.VertexAttribute.DataType; -import com.flowpowered.caustic.api.data.VertexData; -import com.flowpowered.caustic.api.gl.VertexArray; -import com.flowpowered.caustic.lwjgl.LWJGLUtil; - import org.lwjgl.opengl.APPLEVertexArrayObject; import org.lwjgl.opengl.ARBVertexArrayObject; import org.lwjgl.opengl.ContextCapabilities; @@ -39,6 +33,12 @@ import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GLContext; +import com.flowpowered.caustic.api.data.VertexAttribute; +import com.flowpowered.caustic.api.data.VertexAttribute.DataType; +import com.flowpowered.caustic.api.data.VertexData; +import com.flowpowered.caustic.api.gl.VertexArray; +import com.flowpowered.caustic.lwjgl.LWJGLUtil; + /** * An OpenGL 2.0 implementation of {@link VertexArray}. *

diff --git a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30Texture.java b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30Texture.java index d0547ee..87f9e12 100644 --- a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30Texture.java +++ b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30Texture.java @@ -25,13 +25,13 @@ import java.nio.ByteBuffer; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL30; + import com.flowpowered.caustic.api.data.VertexAttribute.DataType; import com.flowpowered.caustic.lwjgl.LWJGLUtil; import com.flowpowered.caustic.lwjgl.gl20.GL20Texture; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL30; - /** * An OpenGL 3.0 implementation of {@link com.flowpowered.caustic.api.gl.Texture}. * diff --git a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30VertexArray.java b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30VertexArray.java index 6ad0e59..d868346 100644 --- a/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30VertexArray.java +++ b/lwjgl/src/main/java/com/flowpowered/caustic/lwjgl/gl30/GL30VertexArray.java @@ -25,6 +25,11 @@ import java.nio.ByteBuffer; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL30; + import com.flowpowered.caustic.api.data.VertexAttribute; import com.flowpowered.caustic.api.data.VertexAttribute.DataType; import com.flowpowered.caustic.api.data.VertexAttribute.UploadMode; @@ -32,11 +37,6 @@ import com.flowpowered.caustic.api.gl.VertexArray; import com.flowpowered.caustic.lwjgl.LWJGLUtil; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL15; -import org.lwjgl.opengl.GL20; -import org.lwjgl.opengl.GL30; - /** * An OpenGL 3.0 implementation of {@link VertexArray}. * diff --git a/pom.xml b/pom.xml index 80c6c79..aaabab3 100644 --- a/pom.xml +++ b/pom.xml @@ -23,8 +23,7 @@ api lwjgl - android - software + From dfd61063a20bbdf8aa1c1dd1233b34a2b28491d2 Mon Sep 17 00:00:00 2001 From: Luke Spragg Date: Mon, 16 Feb 2015 18:58:11 -0500 Subject: [PATCH 5/8] Update .travis.yml --- .travis.yml | 5 +---- pom.xml | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index dafaa4a..c0ac547 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,6 @@ language: java jdk: oraclejdk8 -# Pre-install Maven dependencies -install: mvn dependency:go-offline - # Compile and test source script: mvn clean install -DbuildNumber=$TRAVIS_BUILD_NUMBER -DciSystem=travis -Dcommit=${TRAVIS_COMMIT:0:7} @@ -45,4 +42,4 @@ env: - secure: "VFecbQ+pXBMbLfEDZDmT4Hsh7BP5vxQPzL3uyjKpB6ZnUw1rAkjwyTLfXT/ONdu8683gDUgbf6DawQ2TkAQBGRQjEDZL2fKp2oXw8mX0t0WKpLjL6uqC8QuRwKLOk9rWuOTiuk8IU6gNTHeD+wFatnMxKrwIc54IY+deK/Wo0PE=" - secure: "RtHTH8NllkaVBFHpX8+54Vlao8FEuRCDuTkCyYq5EN+hOXTQ64lQhhQneE+L7XwFj8hP7VYEckLLZ/whkj6hXJVZw5EtYJ+WnB9OvoRa+hI48PTzCXeNd8dafNQhu32A2iIKyVdc0UmjsM/rchrLBDovdVpVzfzfnACoCNVYOlM=" - secure: "bKD7Z1RbmfTRQHZ05c75a/X05QFnS51ejhCp+mpk7t9NIlWgV3xE9xhlKWS3x+A6xv8xYIrsQctex0zYxuKwZNjtb9rfeF5Yuf3PADAlDjaUykupo27jAp4Vi2SrTouMSlOmlnkDZ8b+RHI4v8Cb/Q01p1manZMAeouBtcms0tg=" - - secure: "Z43e9QaVLJN2v+of2K3p5NwYvn9TSG6bV4R7aLwJvMBIbDJ07LIdPGwWOJ1D2MxjhGOT/GVoyWO1ri/fO7uxAziIqes6xjoQALZOl3jlhU7VG1qEsoCtlEUZcX/CUgeKX9CK1Xg143AmrcOPLdYx7d2kXJOt/gMRToXsiUaY/x8=" + - secure: "YpuIE54CJ0s3lcGn0eBUxiMy2OJWBBCk+s+q9cMGixVZEt262+Ek2y1aZ02cx7moedYwnFlmr8oZt6X4l1LKKPO7O+woL10OWtS2iZTZk49V1MO4getIn8NRjQ/NGqgr2FOobIU6ygrp5RND662slO+07CN+hxTExVHuedfvJ9E=" diff --git a/pom.xml b/pom.xml index aaabab3..478ec40 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ 1.0.0-SNAPSHOT pom 2013 - https://flowpowered.com + https://flowpowered.com/caustic Parent Maven project for the Caustic OpenGL rendering library. From e893473c769e580e15ec46cc24786cba1d144a18 Mon Sep 17 00:00:00 2001 From: Luke Spragg Date: Mon, 16 Feb 2015 20:18:48 -0500 Subject: [PATCH 6/8] Add Gradle build support so Maven doesn't get lonely --- api/build.gradle | 11 ++ build.gradle | 223 +++++++++++++++++++++++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 50514 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 164 +++++++++++++++++ gradlew.bat | 90 +++++++++ lwjgl/build.gradle | 12 ++ settings.gradle | 1 + software/build.gradle | 10 + 9 files changed, 516 insertions(+) create mode 100644 api/build.gradle create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 lwjgl/build.gradle create mode 100644 settings.gradle create mode 100644 software/build.gradle diff --git a/api/build.gradle b/api/build.gradle new file mode 100644 index 0000000..b9d0a33 --- /dev/null +++ b/api/build.gradle @@ -0,0 +1,11 @@ +// Project information +ext.projectName = 'Caustic API' +archivesBaseName = 'caustic-api' +ext.packaging = 'jar' +ext.description = 'API for the Caustic OpenGL rendering library.' + +// Project dependencies +dependencies { + compile 'net.sf.trove4j:trove4j:3.0.3' + compile 'com.flowpowered:flow-math:1.0.0' +} diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..1f13c00 --- /dev/null +++ b/build.gradle @@ -0,0 +1,223 @@ +// Default tasks +defaultTasks 'clean', 'licenseFormat', 'build', 'install' + +// Apply plugins +apply plugin: 'cobertura' // Coveralls dependency +apply plugin: 'com.github.kt3k.coveralls' +apply plugin: 'license' + +// Project information +ext.projectName = 'Caustic' +group = 'com.flowpowered' +version = '1.0.0-SNAPSHOT' +ext.packaging = 'pom' +ext.inceptionYear = '2013' +ext.url = 'https://flowpowered.com/caustic' +ext.description = 'Parent Gradle project for the Caustic OpenGL rendering library.' + +// Organization information +ext.organization = 'Flow Powered' +ext.organizationUrl = 'https://flowpowered.com' + +// Build properties +ext.buildNumber = project.hasProperty('buildNumber') ? buildNumber : '0' +ext.ciSystem = project.hasProperty('ciSystem') ? ciSystem : 'unknown' +ext.commit = project.hasProperty('commit') ? commit : 'unknown' + +// Apply to all projects +allprojects { + // Apply plugins + apply plugin: 'java' + apply plugin: 'maven' + apply plugin: 'signing' + + // Project information + ext.projectName = 'Caustic' + group = 'com.flowpowered' + version = '1.0.0-SNAPSHOT' + ext.packaging = 'pom' + ext.inceptionYear = '2013' + ext.url = 'https://flowpowered.com/caustic' + ext.description = 'Parent Gradle project for the Caustic OpenGL rendering library.' + + // Project repositories + repositories { + mavenLocal() + mavenCentral() + maven { + name = 'sonatype-nexus' + url = 'https://oss.sonatype.org/content/groups/public/' + } + } + + // Project dependencies + dependencies { + testCompile 'junit:junit:4.12' + } + + // Filter, process, and include resources + processResources { + // Include in final JAR + from(rootProject.rootDir) { + include 'LICENSE.txt' + } + } + + // License header formatting + license { + ext.project = projectName + ext.year = inceptionYear + ext.name = organization + ext.url = organizationUrl + header rootProject.file('HEADER.txt') + ignoreFailures true + strictCheck true + useDefaultMappings false + mapping { java = 'SLASHSTAR_STYLE' } + } + + // JAR manifest configuration + jar.manifest.mainAttributes( + 'Built-By': System.properties['user.name'], + 'Created-By': System.properties['java.vm.version'] + ' (' + System.properties['java.vm.vendor'] + ')', + 'Specification-Title': projectName, + 'Specification-Version': version + '+' + ciSystem + '-b' + buildNumber + '.git-' + commit, + 'Specification-Vendor': organization + ' - ' + organizationUrl) + + // Artifact deployment + uploadArchives { + repositories.mavenDeployer { + // Javadoc JAR generation + task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from 'build/docs/javadoc' + } + + // Source JAR generation + task sourcesJar(type: Jar) { + classifier = 'sources' + from sourceSets.main.java.srcDirs + } + + // Set all artifacts + artifacts { + archives jar, javadocJar, sourcesJar + } + + // Tasks and variables based on if release or snapshot + if (version.endsWith('-SNAPSHOT')) { + // Set variable to snapshots repository URL + ext.sonatypeUrl = 'https://oss.sonatype.org/content/repositories/snapshots/' + } else { + // Set variable to releases repository URL + ext.sonatypeUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' + + // Artifact signing + signing { + // Sign JAR artifacts + sign configurations.archives + + // Sign Maven POM + beforeDeployment { + org.gradle.api.artifacts.maven.MavenDeployment deployment -> signing.signPom(deployment) + } + } + } + + // Set login credentials for repository + repository(url: sonatypeUrl) { + authentication(userName: System.getenv("sonatypeUsername"), password: System.getenv("sonatypePassword")) + } + + // Maven POM generation + pom.project { + name projectName + artifactId archivesBaseName + packaging packaging + inceptionYear inceptionYear + url url + description project.ext.description + + scm { + connection 'scm:git:git://github.com/flow/caustic.git' + developerConnection 'scm:git:ssh://git@github.com:flow/caustic.git' + url 'https://github.com/flow/caustic' + } + + licenses { + license { + name 'MIT License' + url 'https://tldrlegal.com/l/mit' + distribution 'repo' + } + } + + organization { + name organization + url organizationUrl + } + + developers { + developer { + id 'DDoS' + name 'Aleksi Sapon' + email 'qctechs@gmail.com' + } + developer { + id 'kitskub' + name 'Jack Huey' + email 'kitskub@gmail.com' + } + developer { + id 'Wolf480pl' + name 'Wolf480pl' + email 'wolf480@interia.pl' + } + developer { + id 'Wulfspider' + name 'Luke Spragg' + email 'the@wulf.im' + } + } + } + } + } +} + +// Build plugin repositories and dependencies +buildscript { + repositories { + mavenLocal() + mavenCentral() + maven { + name = 'sonatype-nexus' + url = 'https://oss.sonatype.org/content/groups/public/' + } + } + dependencies { + classpath 'net.saliman:gradle-cobertura-plugin:2.2.5' // Coveralls dependency + classpath 'nl.javadude.gradle.plugins:license-gradle-plugin:0.10.0' + classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.0.1' + } +} + +// Source compiler configuration +configure([compileJava, compileTestJava]) { + sourceCompatibility = '1.7' + targetCompatibility = '1.7' + options.compilerArgs += ['-Xlint:all', '-Xlint:-path'] + options.deprecation = true + options.encoding = 'UTF-8' +} + +// Javadoc doclint configuration +if (JavaVersion.current().isJava8Compatible()) { + allprojects { + tasks.withType(Javadoc) { + options.addStringOption('Xdoclint:none', '-quiet') + } + } +} + +// Coveralls report configuration +cobertura.coverageFormats = ['html', 'xml'] // Coveralls requires xml format diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..667288ad6c2b3b87c990ece1267e56f0bcbf3622 GIT binary patch literal 50514 zcmagFbChSz(k5EAZQHhOS9NvSwr&2(Rb94i+qSxF+w8*h%sKPjdA~XL-o1A2m48I8 z#Ey)JC!a_qSx_(-ARs6xAQ?F>QJ}vM$p8HOeW3pqd2uyidT9j-Mo=K7e+XW0&Y<)E z6;S(I(Ed+Bd0_=<32{|526>4G`Kd`cS$c+fcv*UynW@=E6{aQD-J|;{`Z4Kg`Dt2d zI$)UdFq4$SA}#7RO!AV$BBL=9%jVsq{Ueb7*4^J8{%c%df9v*6=Kt4_{!ba$f6JIV z8JgIb{(p+1{!`T5$U)an0fVi9CwR`^$R`EMcp&rQVa-R*4b4Nb_H8H{ZVot=H7 z#(J{{DW4ze_Ck|1(EbPiGfXTO}v^zl-H!Y3ls9=HV&q>SAGP=VEDW z=wk2muSF2y_lb}fJxZ}al~$+3RF^U!k9x5x zWyl(8dbQ0`AG$%Y?*M0m+cp^Qa}1udZW_Tm3>qdzZv!1x+<_Uf(p@M@ymKp>OX9|F z#L1je z9d6SUXxx2fS*7N*e<;=+3&t4*d+M`}GIPJUbTo-OSVjvF3WrfXg7*_H3ct9cxJKZ9 zLrMzth3?nx0{#c^OdHM`vr>x#A)-roI0OOn<=2h_wo|XV0&wMtLI5!@**l*_XQ2R` zrLSV49cUPRsX#(O5oQzZaIYwwq8Zs2DLXGdDKbr!Yg?7fxU|>+HHQ`48#X--yYCk5 z2_CBTW9rX2eLQC0%EyQli<87+%+Sy))FFW+RMC{*hfJ$|;#$?pAT~P0nL-F}%M*RxwBh)JT4trq7rR7dHloLmiM^IC{>usB=4fXXH9NMyWznFd(bffDK zE@*_maXO?|$?M^W>jXtsnk2}7g8b8%oLp);SNzqtjlYHDKkJ?J|K42x(kk(o{=Zub zF6?{i>=+HX3r6qB=&q|022@z-QLmMSLx%Up}FGL44Gk+C_QL5BU+!i2(vEvNf8Z)-btUdpVY9ovODm+#V7jjU7Y!AWEnY5L4 zy;^;=x#{x<{pUJOVPj)cXJ>gsJ418R ze{ZN{4Os^?bu@m)^eIMs5MU5c;IIG|=#WSfkfeyP1R(>Iv2Y(9if76Ptu~dWzdSmPFUp;6Ezs&WmP-Mn-9ah*g8e8 znAxyrWhx~~tuF4fFyFI)v-S3=C$HmPHmqv%hb3*;ljbj9zaA_}QvfU@RJCGH%&3Mc=GR}sQDh$UWT-8|{1QwhXWO-dM z3?^C@cbP^-hfFljgacs|7mE%a1FSMK5?o1{VuaVB3iP=LvFEL@C0pfwirZ4SXxMUy zrMG05M!9CU@G7-}bgjI%x$|_B9Z@Hc86jXlPhZpJfk@$BToMpqU8Y zS7rRkdp>e0{86ZjFbE^zkdwV*R|JV3EhCJcqjJlZ1HJnbe0I+>a5?HpHLs6A`4&VE zZkHUK@cLRF?y^Gi~ zzERBcPdAs0R^=N{aeUhK(Oc+@?mb~Y)__*Dt{8Wawz6H_)v6niTA_*_%)UP`0`WBL zFONOa&+T9+RMF!QsgKq(%Ib;a-!w+*&V)Y#Xz0(87=H{^VBk3UVeed$SFCL{IJMl-`1FQ@Es zq)F=J+jn(WH_*lNW;=>)d5ZFyL~O+t;)Rex`&~h0ZJ`wg7K@*lu0E7;tx>KLWPduY zB{4G}TQLJE$Fp^?*3raESC`NSpmv`$M^ zR?`+VFj;fQu`)I4O1dHwa_R-0y`qHjG*yT1*ta##G_W-;1ira)uP6}+r|OX64}vD7 zCfB#p>H^?YEyF6K(H( zcSh4u5_|{iq)=K{S8Z{@n?&h}u!l2^EP#?v?Obp5kDl`o9~up%2*s>1Ix5~kT~M3` zo9Mg;n$TcwaN!PHHbuUUw3tRqYfjpz$rm9)1|S{rtPnG|3qao}1W27Wig_4j-(rTjVi`D@Hu z`P>h7i$K>zzc1rQ!~L?29sG(`4ewg^)@Jc)II0KI)@q=D4CEaX%j&RlZ>Dhv0p=|f zDJPQ~ioTP^ju2_j2(V9haP$r!cTNIK`eUF|-}43c=4*G09&bROE80IECDekrK%+jW zBayIlJSDqrri?dj#ZGRQI45{XfBLkOiWIkGb#Tk>GU0NMA&{q`1jQe9jlfJZSTNF_ z5nD5A=Z=a%6uCagCu3np^0R1ibyV8p>-XWfFJK2Gb#o`L=pCm3Bz0F-w`5gv7zJaA z)RS8mWR&`<;DgOxA@S6FQ*5HVF=Pi6>}viGQ3jbA1*0gz7vev?ig9gVhr!>t4e76E zq5scb<;TCmT2XsDGfQ(RVj)A|h<&2OW-AJrbhweQvr{uOf)AdTJN|xO zAOSplNX(IEhc4?4!HsA&Vy7Ayn|y;{2-yn=}+S<{JboP z+O;`IR0`XIjUt&s+%;#~ImRt_GtRFatr{*eLSOp`M&L2~I&K?Jn-<|hTDADdW0!CI zT`L(i=DpZ{m#h7}m5b)AA2rK@4IrsGNhTCLuA(5#C4^ihsG8k9wtfgz{e1{i2dg)4 z+mI{R5E#Qkbkp^PpXHo%=j>nj&GC#hXN&B=ng^Nz`nHCfc3$|&N@`tY-`ccR_&0zX zWOMW?UqQVp6a|9)%p$rhzNSyZx#rwXmnhl-bz2n%^a-VY_->1Rq3M@UM*B73Rbh3KcNU|sUv}tj}yqehs%OmelPMB0M zliOnQ$*!7!%0vXViN+eRgc?|(1-`Kgq(g{Uq<|t%Bz*Q}Y@)~Dxqfxxh@oH`C}F!u zVKM>}SoSAuA}tUnZK%W}VFDOojbWmn1c%601hYWY6h!VJL@bC6^kD6@5DA{~rDbc` zz$!9AztbeXVgISB%D(uPM}Of3_Fv4&^q*DrzatANL%Y8i?%&Z*jK+mCsyf=YZKlbf z+hn1Vj7%sLh~;}k0J;qf&74dzBAF6hP=~yIQm6^14M!6?dhV;l=Kx&n;12=r;6bdu znKAcoswa2O{OPE5Gq3CJ6W7_dZ0Fg_o$rq~%z)3=pMwn1WgeoUs1j^hLuCL?_E++U zUl8cV_e>1#s5BJnSsHgKVH(k3juJJ{(latn3c<1EL^IYNxQh#yBCy;2!x%aPorztP zjJ%Y^H`Yu{q|z#bbRlXv*1|BB=p}$j7!c7C(+){=Hpz}swAa{;Mv?w7=0z0L(939t z85~w@r}dG`qJ(r7Jk^{@x!g>S2N}H{+N(b&vsMA1Z#qSh8<*eRxUKlI&Oa;*Luox`bScaqq#hN!IK3bgB zB`i9szi)5mm7=-Sfccdew3}(DLGfBO@@O!zHa3jAA@asvg`6x7z?j<@r!?HkxDGl; zA4MQQdP?iygX<&#Pt&fZ>4)tZ`4;uBW9N{x=T%*k!S#nf$>KRy}>6yQy?^(R#_fv9|9gTaH7IwKpOb=Xo?gi;akww64+&sf$z|_oI zuZahhq^LF60F>Rc%fkD!7@rigV#kVa^+@?Px~$YsNR3)QPBOZ(f96@IYTBerb(63c zz>}2iX36tDclpTaec;b}1pAap^JYHW{v(X;O)ygVC?+2IJ<4~lV|hQY9F&fz1UDoX5607wu*7FLP=u_rpZVqb zT#DD($Gu8`ZL1j?)6BP@h^#Ro?+wo>lacs#^O^h3c%lrP#Tk&f76F66$)uko$~U{i zFxE>!FOr^ZN46l7O(fh3ODY*ED*fGB+br75!b zD9RQm9(DT(;y?RI{yGj7%_y8*a2V>LYb1M$e5qJezC!U zR-eGYfjYJ!gD34F6x`2&w_<7T-E^D#yUo<&OS zc1dmXr~k)`Uat3yd(Xob>E|E8mmLrXobN;jv|@g)D0OHYJ1I8rlyDYAbYvcT+%8Sj zyDTth@@-~MGjYR*#RQ^#3j3XXL*1dUkl@#l5XF0c^E)53T$DRY=-htu!q=>j*#p?F zSCUz~s8xl*&iOy(^Ngfv-XmA*;GBW zd)}`C2W_ashy}02xm~3DH36VWBLJ10Il7Id6nt$~7hora6?Ils4LaFoFuZm?UJmAT z-3&$(^VAx-lSbLl_O;C=Q{eh>+zEMdU5!VT4k3ic1#w_+)-by@fE^>1sU&)xy_ws4 zq>WjPpOyZ&8o<pKeHD!`!)ch6}P=2?*1GiR*lYgDdHl?x-o7`hcV{KiLo}+xZ%sf#cl0pH_6K{bq zJ^!4l)|nnxEEZo|+C^#VtxL;YGSGqvxx;)O*@`@qRekwLLNq6DAOt*bI;>KPM!}** z*1Fv^$Ob1f_^3hhEllh0rml_3l0gYu~zep zi*ck$)DHOCTC>mzKw9~QfB`qEqwJY9v`tosEI@3GmTICiWK7~mMjAyp`O1}(QXfHS z>I0_glIrf2a);VQV~kDfQmL&R&8yX3mcimT!67&}8=24)t$%BU*8A&@Hs=$k7KZC# zTYN^qk95D4#q5?W`MM}sK)U$CCNE8|C%e3CXNafxch(eEGL_+Piz|4%*V5)8zAF*P8JmMUCYz%v(Y>ssFWfrj)^We?D7Hx)U#H`)OGH2IiptVS z2*zF^F)h%($!r@~7>1<19H#-i?~NUfQGG)@kw(C!+efD4E|L8jmIO9uP6su+9Vme) z_Ut*1ruchGUdny9ogKS9J#EHo68*jLp!D!uee*%?fo0~NSf8QchIDo8oULzpP`tQ3 zT}c@f(sqT>I-GJSSpkR;CSJA;>Vy5h`}yCCQ(YrT&O4d3zYfl}u(z6VCE6!F;F*76 z9j0J8{ssW#uLmNn53($aP9>wroVI83#TbxmSWb`TR@1fFW3)dyT%j-X7{NjG)mBPt z8z+G-hb{;ve{Nq7hNHIcwvmwURm%F#C{Jia_1Xs2a;#VmHY@`q_oFT2!7gKT1L$_S ze4X%%XFJ_o4wSPX)sr=BrRLuUVxO2k%NiH>WW1LwEI*K{3Gz#YW*r(J_Sjb*2iasE z!QPPy6q}ec#&eKI67nf|({Azk6jE$x>w`_s;hWgIE=e_ovbyj_2_8Fh5WIi)Q06ex zK_rmt=gfYqkR{}_CY95yTSFZsiL!^3CJvV4kYI{vBVoSPTEKg^5Yhjh6Q*qkbl3Z` zxrAGk8TrF!V-9SzKxWt&%eP$HlsQs0ga${AUpu%Lh1E=Z@$g5?rRAwX)DueM5vQtCS;kk&S~>Q(zA}iXj?uYPSN2g;`3 zr)tMR>iS6fS{Bt4(+lHMq?p7GTTP4Z-3CxC>~=?1uq|2lu9RZ)h-_brR*o4NcMfZt z>9{-CUh@iJ&~YV=FmZ$@bUu>LCHA9Bs#;S-ykkxyG&;)aSds(|=LmlnnN>@$5#y6f z52PWa7ov;Cg&4n9^e8SUIxgmgdaGopW=?jeS>5hOHimVi!ixB z&L3V_Y{(6VZK+dE@^d&Lp5biwj+@@G6Y|R6E7bpetG}Z6lodOa3o-q%rZKdO?53uHjV=~>M>LX0e}LqA0#;Wi z>Fi99*d>>vgM$sFrG?jSll(bPvE3F0SBr`E-F%7bVw3zL1%G0T0xl)LpRL!9rRcZ4 znW820$m!^d?*snLNAF9IeeeBXsy=xE{l^`V_?cqSTM64v;<2La{6~897oU{tV~NPl zGm`(o6A}0+qsbLx@tZ>YcEJtAnfK!lVXycvt&CpfQ~O{wVSh^PZ@v7R)Oo=a~+pMUfd_P;?MMbq0W zn5d_K8KCPRQ7_>a%$}tW5E}*pRTz%)226#|i#S263Qo`)>UAV&gS!BZJCB^* zD)9KKv*&q?w2V58r&^+i9tld&yUj=}t)c(aVaT2V_ry>mvCmQ%m0*}^30i0^;xDFP z#GK)q)7zR!wDLf_FI+hJNHi+CQYLx%kd$c4;YQ(OP45JYT0gFhYtmR|&A;F>cY8aj zC{lzsg>cZL@c@)hdyj$RA8y!D!n)(iTko!hyL)Wp!_&LE&D6}bxGl&Y_tbnuS`jQY z(f*_-X`iYEoxr&a*76lkZCe-a5AIOXCY># zbiVD(DT$0EI=U*Yf6Sl8f6>23pKEMNQ4Ajg^{ZHghmvEQH$3o{ms4*o6hgYvpNE+( z#AZ;x7E{DM`7Hvh|Bml=1j#gyl{K&_{-jEI@)yyKG&XZ8%52}!B`ZE?EL7#WtMBKol?Mvj2saaE<61>mL%<6)IXN}3^`@*!@} z341EQrH}dRV~Fjv>F3@mjwCOV$Y%oyGr0LwkxkuPb6X#ms0o?9o+d9{x3cbiGKmX3 z^!+;D#Al?M&g?P9kq(7|b*i(XsOwP?H!ElS*uhTDBDKArqGP#E7dcE;HWkvkaEAW? zF!3|NMZb>RCGHa5#)`X}8w)%}Ey|gW@8DUXNsDR*{esPO{W?k2a}RxGK|616o0)}e zw?Os9aROYmtw`mSga!UI{x(DS%Vyo@y>JF`^Fi2A{GhSfM8=YCUiq2tRfBwSZeFh1 z8SG=1Ot08%#iR0jnhZp?#@V2YFnQ7qP$zE3&#`>FhsO>}OG$enmf?*FVG@qB!C+bO{M}K?d?H2@pq=}!TIg&Q z<|^+Ey(ErEeOf1wvGI?LX+DEA>A4Ka7Q!%PAW&4a-t8+>1M9b(T0qACQ=f;57D`tu0g(=;a7O*h_Jc4JEypx1gs; zCDX69d|g$NsXEuD1H|$3$ZHE}u3HP4b!9=Q%rqHBgCfvK3>j?XLQkgDUg`93gF?}s zS4$rqaDE(s2IL!2Y@kw=(NL~wa24NU3sm0I71mIjZ>?9}bNl5^Al?Sk^y(`qsW$ER z@g$;Pyb*^A=G{Yrb0a>4vvBBZ5U2|)}iX;AAo6X<=K0YOtm49s4edp~uvJxx$&=o-&rGttC2~o83 zfuN5-wJBS(4plr-Qmhz$`*di+<4KB`>;9BgrbANhj6VsJNxLq5IoU%8vF$2M+Z2ek zTw84Kxg}m}jc^*zK>s;O8dE$R&kkO5>*Y75eKaR2>i5fb7o!D~D0P;E`CzLz<48 zBzH@erfNN`nS4Uy3@n#r)*^n}uKHeJxygl)GV-F`w49%s`cYMPYi5Gahg$5e??^in2I<7 zUKZDwHf#riMrllW@f~Nsm&l0q?KJzSfp9hXd2pb;UnzJj^xc9bqY2zVLk%GU)}?}} zB7(TNFqdZnN}qRsHgj1;xcwQt^<58f3wN(P=y%mH3&}An)2M$}(>TF|q1;N5^ZX`t zd&q8vtB(q@FPC>=6)%sC=t3jOE{U+j(IShmITq`TXA`_QKhoBZ7GXEN9MCEV z+~@7gbqUElkbsjU7o$HOfy49&nNHI)#@Dt#fvePViP1MzItEa|goh@hCZ273Hd#4Xdhb+D?L0E87T>DawyVvc3J#zePjBG zaZj%zUc`L}>#2=d=9E*RS9(6nm|%{&E`OI4~x8fs!0ZZ3b-$x(I3NCjCbUBu$h&4 zvkoaim?yiSh1?-2osDeuCf;fbpe3>H#44}rDb%z#W=Jf-*l&-c4uk{yAX)0;9gvX= z#)Ov%5_L%}8e9yEMI=PVh2w~CbgO6&n#>WB?TO?1h+5Yitr3i}=1JW98CC66#>33g zXG+Th=cRh7?7HQYiRy+vd{ov@)w1~xg@TuyK2?xGWXu88_2%M2@eaFd&c-wqqNP26!WU&USZ z8lIHzv`SrJIVF=z2amJL`aB8>O7!d0X?{4zEM+hWKZDaY!_ekJhvtHd^7?hm>;4d@ zeK2Evnj=*zE(YguNX`-&354G{M`WHLvobFJIa9yg@YweQb2NV_p4&_KA0#<1V4d`|3w~@!Wda7`st< zYW?_t6&a=_{Uf&^ zGZWvYxn={#fj-{6v~}bU*&E+%&Wlu@!G)AUL<|!YF&;Wt5x}BM0*{RdB?B3}`gI!y zj553FXs}D9SFRVNei9isSJcMC!3@^b=ePm!`OM}?eK*P2HgZK{1j$CJKRVD)>81IkA@&{z~;ow^HGAt9aw-uE=tusp@Din2k-hBfMQG|V1erRt^^#(kf zQgupM_mjXiJP~C9gG88#+vMpN>pP3tsvec=R=AjpK6(QH<hWIpOCT{1tvWALW6Lfn1W{#(itOApM^OhR99D@A%6#OSz-s+Q!9QsS& zCI3wh{eNMaMeOZeoL&CX&GLqpcB(FhPA>lsclT3!Lj#F_paHxBrO$>L%mD-~b67!D z1~-olI4)rvJ!SWC8`+8~*2V+>RkNnOb#`h)vdAAyqV9xtx zMECS`Ugw#qZsX6lS$js{u0TT5SH~X`jAmqAjD{K#w8ti!gI&?!boYkRVUWz&lbU;j zpI&^siQ!M0$w;Y8f6pGRQGT1+7^n_FK1n%n#=X`JhmStJDve0KY7S67DZM#qOJF9V zsDSvWX5_Ceg7D?vh5F&(%8r5@;-NmtUM&Z~CdhPHI<~GF>GNyiKPMbBbs?{JaFpUQsE*gVRbs zEv49jG95i*$&=}FTc(jg(zL{cLDWfnG7V?guH&aE6kMsRMlX`f2A_$)&f1YNJtD_G zEQRHuh&2^kQ#&G~_Tdnw#7hD^OP={T-S`-#7hL-v%-Yo+CsrqZStHFQd`|C z8@mVz18m8%DgMB0My7%LL@iHak7P4Ah^U6z1F{v&MJJvISf*T}A7KH-4c%fj=~gT- zHX0-tQ8*3d8Qlj)Rv5#D((4pQe6vFQ5#(Tu-+Z>7YHTlH?qLbF8gNPN0T2b2KiU7Y z;jIP@EeRtqcp`2R$~G6e(rg>M4-2lpPYXVK%YNrH7>6+!ClN+~>M1+G3DYy|u6FqV zRLMQ~o8_{~0L09EDk}#Drv!hg{E`E9y_4=#1q#C#0`sN{g1wMR!Sa`_E$=8l7$jsv zFf#b;9e?<9a6td}ThnPw7AURoVe|BpI*p4em5$dICdDLevr=8O`p=QEhH8?PVXfAZ zbbP^ybvo6rIsgHUB3EtV8lqYhw%UzDJtP{bt^XjXYH_o^OqFd@!kwVvTk2 zBG|Ahenv*#WTt1SAkrj_V~5HSuQ~GpT{->!jrjE-v`Zf|a?upEKsR@Z&l7eVgyDKx zIDZ1gJEvHlP8FUycaZm|AJ9DkFDoYnx0Aj8*#)$Fy;@{GLD$BQAC4M>u!Elq_c1vzSH@#&FR16q3Cxx4oLvwP=f+<@S8~wy}z=stlxT|jUJ$d z7cJ6nZF=Hr*d-9e8FDv5WjBhiytFq%g|TaZWe+eyM);j@Kh4r59@aW>%dyuZ8`c?m zc!k_0dh9+i(|LHI1a_11#?R8l8T2y#;fF1N)DLO;6%Q9a*hU$I7&Q|Ib5;cq%!c5DCI5wVr|1{4;5WVk%7rjfIP8hpujO@b~BuVlr29_JWtJ>hp z7A;x0N@bFp^2W-7ryDSO`!nIbok@UDoUw;UrUz>{_12X6idNYNT|a97;#C4{N3E`_ zl#!ihVWru$$=`n=h^UoGhbts>^OIOi!t9sJYex zcWq{GLBO_(QPq~CfvsV?m~BeoXB4J48?9t`7{IN^B2|pL#%|)|Nk;&(8 zd*p6;RXJJ*U8;8rG}ClE(=G}neQYM7w-S%n4>B$Z>5;c zaaFy_anPH*Iff?(4tOo)x{j(uWciGp(pj(CdQ#uE`^6Y1ad1*oFh&s7K9B@aLIusr zvrQ%{S7R&HqK%>e)vG1@Ygnp=g=GVM4CsRWisf_%v<(c^d6lo&1V8SaHp});3TlFk zG#e?^KSZefsKd{jB?QFNTvMNZINe?VKvNGmoo=CYRU?nvmJz#3kon4YoO}Y15~ii< zw`0%`p{>o+EQ~{}#TW!D&T8Tn7_+A-&mOYP^~>Hl#q^H!spWjs+8YbVgxO25UOsUN z(<7r#ZN-Y|o#k}~8SSyJ4jSgG2g5<;8IK%#EcoU}Wcs;K2RA|6f@+&2uZ&Na1+{y! zT;JvU`mgR--^zFT-XJi$H?~ClDYfY6LhB!_Ny7nx=U(#ANjOQ9v`?>wfw~{iF z7iy``+ne+ZHHI(z9M$i67}3t^eaKrOdU~_qpt*>I&Z?*lwH-fFVF%MF>aY0Bvhf7h zAlI1y-Ljs7H*OPTr(#w$4n^uB3aSI_pVg&-Ocy-|^KzFz4#@0e(^$H9Rh3J`ozlWFj&MQyrIxnfkda8;6m}LjSsPrxErj|osSsJ z&jo8TaWE!yAfCfv2+(<<2A-cY#~I^>HZ4vgd5Ba%XU?;u7MVy?F>|NMPNIp0#2YwiZTB<_ip#a=5n+UbTCvk^-;PCb06bq2hu{kC=ala6;aYD60)q3&7JGDnwT;z^yce=7daJ|-puuzal;!BAu=ok#ta0d{S zOY92%j^NNEC64@f_q2YOc@2K3Ht#+bkWS6Y!U$76?$E(tBS1TRu+X`T2%Hm}5 z$G}vhy#EjY|0ga-lGVSw`WuMSVgUis{O3Sa@_${0{C7C|Ke73L@!2|fe?!sUI;Ke` zG81Cx%rq0!BnNN}RAaayDqtfhT%j2wn*)>dzVn9Q#zt;0E5$3rjmJ8z%IBu%=ye9Q ziu%-+=bG-DKXos@+J71BpU-J{y9vdy@$Ie-Mo?j#JCH#6j@d_NnDSN{J$ImxhG4K1-AAJTfTm@y zkwzeV_Rk%-=W&#uk92?P(Z!F$V^pVyN|aM*!5)ghp6gLgG#}M-ClQ35`vbGLj~2om z#_4u1a$ZU2izx8ddYMF z#gRInDsFTHdYY+T9h!q^ZnfOxy2;G4E6k)B4e~PG{ge2GZ)yuUx}yanU0KWTuO9hM zAl4TT(^-N^1gg3mHB{CxW4JKcO>Cs{3~?3jBrL*J%hyH&b%TSTTfw8KEq-*gOqL&x zBZWS*BO+mH>r{hgLv@J=;?sO_9}yLN`zURJ3d(e(mL*kX^EqTO`HIkVlM}zQ(-hXO zS>mk1Rq9_~1CZH`7Tr>&0%wz*WIxwF^^1D^DWSKD)FAOaHzV})eyPyk7lnyNSfvfX zvTsJ$<&E_C92MF>*AHiq@?)`Dn%#|_Qh za(?Iz3f?M$e=pqHe@G7c-=TfhAzl1=vV{LG^mW8*weTRwsf8xSpe_(Y6;P(BTOe)e zH0_Qa1=sMjam$cIbyOuZ*XZDtWbcCGoVO~V+mU;qe0TM3;7?~O(LA7&E*(98L|$`0)graBHY!{tsoLS4* zluf$Jxt+S9_sS4?5D}yUJ0nggbdNR+!=$b!h6pOJ7%i+~+c5ZwSf+{kbP-D&0%eUX zQ~3L__Ams-qVs8?shPyVRnFEI9Fp(D@&g=u6(gt~b2;Tkb>z~ogt}P@EsP&6uY>iG zzr;6e=_=-iC&naxoa>OxsN>Eu*q=F0tZ$tHiNTJTSD&^~LgBrI>2_Q$j5HW}XAx^ym9D&~X_ zZ_d}T$`AcZkQ>;eg#ldX6`u3%Hka9#NRHaAu9V$8sxVSSb>3ZcO(KQ%An>4%cDST>@~&74Zl{1mEkXEVt7jfO7|_C#=ks<~N1E3-dd z9qn~MPSEoiE>UWqUA(KL#Q-MurE7nxH_S+FA25TbvWkZ}*8HNVj^tZ7R=h-$QaqQY zlM;O5?N+dZ=cPqE@}}AZibpMLO`nEc^Y&;^n3PLhyv)PH-4Q&p?wn>>;u;mqxC{*y zJFao4I#f74vU#W3H%_)UtuFXq$XfxSC|+6m1*M}im_6&DaXAqq@;?u8XYrceVyP}w z#Fx`%3{x|1G;_=f72Ui5ejJxJiW@F=zijT=G>-*gO?}u=Bwq`7*){XtvMy8Gg~t@p zH(XNd5Dc4usl=7Gd0#PxSl`e*Fm^EWvmS!Eo!@E;teuWOvo5$FfOC-UC&Lc7ehm1) zMDB2bI_8QRInX&{{5W8eoF?xBqj;l}gj-1jgb%adCJ{Tl&|!#Ym?<~p2G_bH6dSWr zSwDgMT2d7X>z|3<#wCMIK#uwVyE4T9*qY|K)e@~7tu5=+7U-ehaTd$0=re~GG|0;w zn(1QtNXrxoDaMvftH1JkJuxOZcjC|+%WUZpQ#facxj4d;jRVyix$Ge-PwLF*PILR$ zu|tmQV&Q(5I(`M|bt(@#lKQNQ$)DF@!D|LeSgnUd%|*-32PxWHB={GuvWjv}CbLOcpbin3wj(wkwzN9OC2jsj2K+KWXr)1Uw7lIYfp4DU}iJ|6y zWsYq>Dkcq~r+WFGO&6ZR&t0p$tqB&~%nUc3ou{)6oh1SGfeR-8W88{uGPelX-T-ke zk`7;RfYs4s#!&gfZyvhXNf;LkP)iG5@iIpnJ?xcdtgxUc&Kg_BR}ZJ3XWAinV$R) zekh20+d^x|)cdR~bO$Lwyi`YnOZOBa7# zzs9L-LwYI;h*DF2&7Ld$QSF)^U*^T6`wCZjm~2fVFHI~TnVO4YWA>)R+=Zm2?6A6%&V+igaN5`0 zQ?mRv#Ul$=hdpMH$oOb7jIGKWM3f~!?3-=X_7kpT{GtHDzk=oqAJ10Y z&yvY$`2V}@z(1s)|Ly4Usd3Uk(?I{=XCY>ej-=AApsK77rRr~}45R|pwibhcXlQhk z$~JOMk4Su2yTlDUL7g9Cm09`lbuZ!6l02mU)YRuXA%yi{Db|l zi;hHuv<0(K38!#VRt(yIZAFxQy{$!*jYdT@7p>hFX+1#9U#rJi*qt@RY^Ml!s-Aur z18QcAHkMGt^2-^xM@bI?m2rOM z;Wg#_KPzwfXjRk8K)~k^XOrE_^T?AD$z&}IRog;`Xu%~W(x6UZO)woHQPEKD`?(y+ zy(_yx7vn)Kf_d?+Y+}vop1+$Dr8U|JtR}Oh+SY~2_01TA?jSR}REUWo$^F_~ zugzs8%a_p4A^^_N8pbR~8jFsDb*Po)3YQw!)kk7w7QNWJ(A`eaVbebZcD zD$|h|OFU5+OI_a=$}~f~F%Z^*Yqfzq?Q+m6oQh7knGl%rzs~@@?7OSVttd&2ks4QJ zk&9P6W~DtmRXgyLi`xho4m%Z*P0e1JW|v!fUmQe5>Ig6{w=0k?%b!4qWOe2w!#)U%&09pluOgJ?^0+fb$YofO zg=R=-YjIBzBK4bmMU5M;4aL^>$ zDbnQ7!@GBME=7F{8t3qrCEO@#YLA95++Nj3`N{@WT#=z0oL0DRz&{lQv9cC%1NCbp z*VFAPc<~|RCkLqx7y}%~XLC@+<;B%Q>R|MDys5OPnuK)j<9lCF8d&(3Q%BW983-1X z`Hye1WchSn5>peL_Xx+2i@PnSOXOyN%|ELKhU^Ty#MjcJ)vTgVB@gzSeYlQ?zL1y~ zQK6-v$vz+liwY^@S<;0oKVVOy7d?v`QqjU>Rlh^8Mh|)u2+-u?n?(Mj>)AJw8UC1Y$A?R3sfBfV?JK#4=l@63iu=1w;Qdlhdme* zzj61I%uOB2h7+EoD2|LiKR}f@3_aX^)@FF)9)XREew@~1S8z_1Adp`vcX8D_!;{oo z!;|N|FnfxqjbJBFVR$koHiADY>B!g!9X+a)n-4@?gW&e$K)VhmVi2dEk+mzMA{a;> z_e_~37jCy9e)Q0$?@xeQC99Rp6*9lV`VlA0B@L{hs8-7r_=3Ypf7LvqIfyARp3~Fv zM-_n|NWvywevkTPQImE*(;qHbK!Ubb`9%jHOAPHvk$Vo#^HA z`nbpq)D|YG&Vyzq)9llv!bTgC#-+l%#m>lYP(QH;8|;(sFoc{zs%rCquMVlv%!JG<{Hy}VO!`K#* zge&eKsU*h6Kd=>D!xvqGT2&dL*(-uNuYktS9g5ctv!z|uz+>0m{ZmeG;~D|=k?p! z#GOwKXThlmC&U-%cr^l+fRBGOv^fK)bJl$U0Z|770pa?e>6m{h*&~y4Ffp*^9>t$q7<%)Yo}wk3F6$Az+Vv_p0n_=5Njw6W;vUtT zX&TZr?7QuHDWy9EM%Bz-zPhe_t9+!*uUaBB>ZUF8NRBn zF-pCG=L9u=m5IW6H_^zxLoB6_Dm^oNH}3fjF#%Ffc1Dtz0cmI6G%@3CZM3)e4)dm2 zS$kmXiA~a66gMkdpvl)?g}!Tl$B~1&Vm>eUw)7qlcQ&9cExr&DmngeT16>rVW#)#8 zXZ>d3`8Ju1jEjUHGJvdDiXGM1m)TF3@jt|XC?98IzUN*fuy^$j? z6A2mJ2Aun4;H^(LV(Qs*@_OLrw>7QZv?+&wg&3N~O|7KV&*@JE2vcn|0osoE8M(cQ|KEZb427Yj^-JTRpYLrd=ZtRBvVCO6=|EIB%9K-;{+q z*m%nKd9e9v^gXiq8uXpg_~-71d5QuvY5WU!24Qo%rL)$StgZju)I+YA|erFq502iPAbdAQX=C4R@p58(LWAzS zP*10IYwDH6p}ESu>g~f(sju*pRhc=%A#_@8fld=@UzTG>yV^a$x^=lwPJ1E-d8w<~ zo0#yc`BL&e%peQgSn(NpBX@SbS^XL8VSi$YvVx#fIRzSRXVgbk`!0a9lo7%_Ec1kop#JdZixt!qcH@W&xl~?IuM>}jGZpm$ zujoC~QHWVImrO01BbhtSa*SW#^VVW%cn2XVNhvF>wIyXdCuQE!%NG(D61GiBp1s2i zvsx<*yjsM0<{=L1-Qjm8Un88rBpv6v(VV%y1Y+tvw9iOMtA~u~02L74-~}}t-@afp ze0&h`;Mj=+8R6SQn$+HAx~s2jz`A-I5V8iOF}hf<5Uc9gIJfa1ThLo1w523X?%B#r zzi*CiBhkEDZt1-ZcWY&lg5U6m`hlvxEq5C@j&&P2i2~)pF1H;Z^}FfS`@ObaXN4QWsG+?$kOG2?I$+$$E*wIy#cl!03YFHAw-U&e z-Wp0ZK04v_1jTJFq3fYbW07eiXZ3FS`M&3&fWoc3(8rCHN}kN{Wl(}Hzfjb}fmfB7 zO8d}Y4rY7g*)lSXdTVt8@ceQdF}Aj|J$~mx7E7A_0Bv7Mh)y#qof^H`1`@xpJ%?%c zNQyrGX|lDJ(sQUXEx#R<4c!;7B5V=lHZN}P=-a;bI`Au{D#3*se|+X;F7CMDjbV%M zRr8{QPt5^#CwG0+?{bjvSA+g~2p*AbMOCzztwC4(VvD)v$!eA!$fbi(F9Jj%p?~h2 zr{YX(m(+Ht(z~TEQUwm1buJw6%7m(O?}0yh^3Hv>9H zzDR8*{1|7~;yd92_>0=^5;RLbf4UwEFScPHfTEANKv9f4#7)r;M~FCGNrM^7GW8-J zdtc9_OVnQWiYtEgrxcx1Vza!kT`CQeH7D%KiekbA6{1rrVdFumBc+)awo{8N&#|eK zq<&V}VewDn4euDKP7yi-(%5P=AZNrDtl6dF1A`eSRh#%SZuVma6|)TO<&lbR7|y=9 z9Bb$at4k;fn>FGtTE#JRhhT_SVV*3c^;+d(vre@$R=1u%t(no?^*1Jk9O2GM8kg~_ zO!8>`b6!=KRtk$~n7WH|q0Diu)9}V%HK|k==n_u6)v%>SqLeCr-&a|aJ z2mpNJrIB8@0<{HePvF9?sNeT+Z1y`9UM(tu^ac8~;LcUJCbi=A2d=dyMDE<87bIaW znPBv;wh`jlG9+VNM-Py5?U5}POYr(7b3gt~nB~e%Bc$}X-zt1wf4O!3qoR}kpB0_- z|7FkV_-UHJ;P}4{ELA4P6{yFh)ug25N5@9#hQ}s%l@Y1s)u6x8D>AVtG1b(waMZG} zC_1_$ASyAjFtHubP>oE=$TLtk$}`Hy4NK3Ky^oe)uKR+@2pnoWa_(o;o7kQPFp@J&h# z3Z{e1xAqgH7v&`@*+3rG%8gF+27UHl$Q`Bfa{ebWGMU+v)3*{*BZsr0{9+Wz$qe7^Mm_Hae|{Qj4R>pv@PO>C|H#c=hn z+ruwz3=cm|t>Qo76Z3!GE^Pdl$k@bH)WOc~(;!IB%HHhL+{*pajP$?d#wluc3TU6s zqpA7^T%%E%dHEt=5*}8Rg~SURV2E+0X;7`C-aI?94-+0_sx*=Xw;g&I$*22?w&GYO zE`BxKeWN03W##2$on)=6TQ%tF`T(zq{SA*(u7qwHZKyUtwb0x+(SXp&w>>&bl`US2 z19St zwk^6LTv8;knrD)kO58kB-D&v}VbWOPj;;e=5C$+R{Wb{LxfMMeR@{frJQj8iRO*N` zc0BLQe{+JT?K8#VYXob%fI{3ubvpX$8aAoXy%-OoiPy@!cj4S>cAWEA(O963>&B6Q z*pFDOclcOz()i)C?9ghA?W;mf)X38a=;CrAFN>$^YTv@s3urFVsjfkM&L%^(wm3_5JUPdb1J{D_HX9a zH2cBpe6&o6%3Wp>13XG#QZSD?l7-R4FKyDv2+%5b>sN_~o7GxCUL|Cp(ds3FonVvd z2lSxU0Q`=JiR8kG)5G#A_zE5pEMm?FP!a;VU+>h1-H54MY_YZ(NDleGJ8h>5MF$R2 zWq}o~DI$g2uu3VvV2iKy(fxsNys}EH(#St_%V{T!XGri3=bn*ZVhk_hGlnAb%BnC; zVaV6(pMZ+|g@M0z<{TF!w~Tf4+V$HE$qU&*X^Y;=(?D8=EJ>gAA%)LDESr{czCxnDg6_xQp5TzXc;ZtfX;hoW z(V?~0Uhvq*m;aM+{1r7U24-=9&uBUNy#7s*`d5(sEm{3+b-U?Lu-jRXtdl;&UZmXlftss&4#_1nV&>`e7Xi>4? zBU}5%ExXF}nj!gB8NCaeaY`$KRX5VhM5fIn5gd)vlkWBTWMcE+qS};_3ObA^k@=lN zuM`xaa1ZUe@f6os0^;KY5ox`M-J41IJ6T{xHca7Bkf+41$p<1R(lfT^>nbzY*HvtJ^EW(qWBf50$&{qp zufU%2q7SV`mkfsut!A=s@3J<%lf_&Yyf?k zh)d!U@0HG{2VaY++89*l%5jmoi!Xge7GdW4YfubC4<=WJp(||Ykwf8!?uh~ce$lv+ z;}c&KjuwL6kKMq_hWw)n?Q0Nr^Jb;d`{{@ZBCk;Jc`D z+!ApjU9NlB4x+o~__NKJxv6~oLQ1jKNUOy%9uFAI5957Soq2JxKLAVwLWGHCOAbo{ zOBV^I8y>1l%QdI^yG5>Gtoq_OldQ7rU@GBLjxtjuH!R3Vt(`cnj|F)mT zsIv+ud`|x$2oR9Jtl0l;KmE_?|BrdE^2ssTTYUcNX!L0V`QJ9(zf^@kH%s()^HwvX zb&*m=UDdTMvUozPyEHSSRCXy1|Y*Wq< zu9oDr=Fur3j8HM+?zPjjGi~8zX%e+)FVU8+y##fg86^{OJbEVHURpKC+_#Bww~_o! znA%2Kh7!=^+8~*wf}`x6@80+=t?k}A%wzV&Q*|TV|eQ-sqCjKNir%#+s^@-+7Mk75R$c} ze{0d1b+%v{XmBC(qV=d+Voo zsko{QpR#VVl9Tdka^xjxiQ(OIB54YQStIx6-gAoMqwkRKcVWK9N|uh7AIItvHptzC zfYjmd@-IU;W0OSz4wq;}Iwx&e6-~M7dIr(O?VEP&k2QYz6(~)UUhE4RNAd=5PO8%_ z{~HaRNCXAvhA>{-JKnw~d@%h9=3lq9BT|GL$xq}g`#InL2Qc`zx&FDVyV-qu(0|%! zoBh{1|Bv-OC1G3!j2S&d;f1xJp;6n8_N4csUJYt7B``dYskx@;)fE?zkRisxdScT; z(|q;Cmx@_h7K1)eYi%!k?R6dP=KcBwatnSO6?TcmXjOb&JgA%dFtC_E@Fg!mfv6Nq z3B~)5suPNPTqt;mEVnthS`M6hCXf^W>56VubTIl|LbR-T_|Ta6*H!RVe;Uo5i1;AN zZD6=h8cS>`Hr`MOY+ZW9-3hlL5_MX>?A8FCw54Tfmo9RBn&&G3oF>nIC zU-z!rvu(2%a>Dv&e>7*y56KhRDFdh93pw3?5!z3kqUPW@N0}{?4@TRrv6A>Ad~5 z>S4dR+;O#uWdJ!9+cmlrxT-#t7(X4s3U_@kOm@OuY4r3Z{;{_k_Ljcv#4W2(FK8aky{|ypVOp@IvMQ0XU-qISJ z)PJ7I)D8V3b*J%Qs;+cbn*`WYamHH_V^c}JC{_P}^Lcnj3mJ`~;-bOEqDKD$ZD z=2FPs?12^KB8gB8IN#xXq&GbI6>8P22YPrCmBh#j3*b`8H`M7VlYa4 zpIahc7sw@$L8h3o0M_^Cn&Y)2#S=fIcDJ6&+w|U5{=^zT2O?07$#kaB*R2vt#~cG_ zYsv)#brDA8Q)*IEu!cX+bRzw#m+ia!`^o1)?e0exYOTdQ9xW%b_KWTjIK9${Crm{w zs*}B_X%&s);F+{^AhhwGM5j?b@caw;1jM2LBQYte8gu1 zOIJJ48MtQ#WO*40+HJRslF};Ipi;kvf^rxZou&I%_E>c?!~sHr0ES537`joX*e@~N zKU);tR~y}vU*U=Piwv>6(QSe55E>?7fxn*W0~uUtvHRnNc6T_;Sgals(g}kDWF6PC za$V*f=B@QARf-4b*OlZ))%4Ce^ycN*ldkFKhz?o&H}m?uqv?EbCu_VWX*>}p;m*!D z)coj<3CDkzqWvtOu(MeUKXtlSA5}MrDzQ&+l9Ozm4V5Lj5Ty`Hki5Nc%d97INv0HG`G3JRjS4r!yi#jEpiRI-O?`P^ZrJrK@Q*6@!=q#iXX%A(y# zEtG_tTF>ee8e;(FQoND{m$k0Kig&axszzqS5kXekRaM}l=99ryXK)v636Msu2kI%a zTaBnr1J0GM)@{s0TMuNhy@HTzsy+)+#KHS|2CIa2gEmM)wDQ-2^GGOj49}kjP=~pm z&JZ=pN%bGa#br~k1HEXi+&i(}t=`9O8G?Pt+EIg8juvxMCAeeIh|Npz}Uw2`$03zq>JX}1}5wZj8Gw1Ymc zsG*5M(MAmylsFghwzMhuEX~FmleZt=CpL7rk%Z|Q1Yx!6 z3T$EbrvcPb(+AYS1@n2-72)b=>H_D|?b!>m#M9x=Urn7r)pm$&(UEppuA!}g1(xV> zd2yCJN&`2wSg#;R#%;2E;q;96UmN-Ngl+wBw3>)=CReDu?*2@((GYe6w5a+LQu5Mj ztee@qA!oX^bXj6XG;n7%e{sj|5uxdBa0RiGW0MHmD403aCh&j#CW5Mvc&}ho=ZUMg zqjeW~*p63m+hE}^6~}1!-4>1OJ02)r*pN4Flaj1J!F)n0P(< zN}tO#uJ3_xVs4OSQa&f>28y}gu9C5-j<1pf^S5ceC}@kbu8ldu1he+Lm`w_s)9|Ig zVVa!{Nzd(T9{E(Z<}RvVz0+~LXmj2_+vem>v&SfScc+QQS=jqqQGljl#CF54qxoc- zJ93v-l5D{W*Da>}i5a(=%X&L9=uBU6Ir>_%N5?UlA3IYkFcUA4TvRlTZFOTrK}LnJ zV|V>n$!a;OR6|^l+mYiS;z~d%_(J*PMi;pXz$DZj$-curva(41;IM`1gow5ykB@c8 zOwF(r>Ckx! z=cj}-;Qitc^`@}O{KiA}cM|rm{CpSZUS#GIu&sXP=bZol3Ch2xCV%mGvx?~c7Yox$ zJlGB@R}f-j92+Ab!c-(&Ksp9P7SWwSmY-TP4Tb07f_+52SY6)}`mdG^Oy{sC?J~KS z3ZL>i4zq8w4%dA2R~)*!d?6IO8-vl!$?tA7kPgJgWRYvW8llLN5JqXH#_zq7Wru6- zU$LWVzn)|T#RFrytNGzX3$E#K$jnPa}%LUwJQe9;h%TUrIcAw1y|ZEd_lUE zaM4}QXdlUA30Dh{{Gq>JMGVb1ZzwK35Fqe=*eJ#~1lb9Zsnn6~h~T4p;;d|sRJ9NoCh zRdniy+gzwc`p70rg`|a5P)Skbx?|Z(W6vtdET(^~%BWO;->#-Z96#odc;>(~_+2Hf-DaiG-hfG9 zQ4~aq3HFI9kM;FYWA4nnD&`Qo|Q@ybGA-&hQ9w=t$_QDfD+5+}yhYdUVLANET z!{sw(znM5$)%Uj8Ebhss7hmcyA}A2~5kT~Nj!xTucZaQH(~y$;Mf?yEj176b4oo@Y z4V6j-0||A)^93yx%e$2%k)3Mg^NW1q4)!>MkC;4a{oc$v3(!WJNZ5P5SVq}KpOI$O zX50~b0}DE%{C$>2m$i2ZDSY`jYbb4<^(9(3heJuK2L zB`An9PVp2pai1B%Ep(8G1X9B%GwENDW;(nab{wY3NV6 zWP>XMT`7z>8Z7_sf?ETNy)k&4t&Q#c8L%iK|#2v{CO2 zBV(XbOxE^Ie$gRpYKD%x47oj)hMZ3Ij>O5mswhd3m^Usf%*un*8;0jGELTSDY1CUtqr4B$fGATyOge-FL6 zVM0&kEXZ)l$2w68OyTUX@pi_)c|RlePg)jzvLkAG_NLjDktRel8&$J!(9$yD#YmWl|cMH<0N)aLF` zU=}n3nI0!+dzj|YS3%}xzoyzrn!apvU_~0Sty{B({zUj9O38?MY45{eaHt;g@F!-V z;mdq2EwdO=FXD@4XgoSXo|_;`}cKsnZT6qZ-;5I+gd*Fb>>jN&7?a#TYQ3y=VE2Ge&LUFv6ACAsi?3nzwV z9$9@;>Fvb^9}<$@&gXXPd$uhzuDBkM47m8;jd4Snq+6G6hAohtLL;g@E_+2u-GaW3 zWj_^t5~8EtqtdZ2zndpG_hZ1=rOmB~TM{Wb-w+p&Xf7%AFITrFqN=H%NHH=%>EacB zJ&sD}NF@*iS>;xqhawVG8821C=t~hg#Fha2Wg_*;6QwqA86C`=Lm&0+rVl;B1k+mc z&17PSP0cHU57pS#+=;*9?cbv3Ep2SZ0b3^WjslAez4yX zQYM(o5}t!?@zE*$I>t2w@Eij@hIoO2wP;AnlJGd@$5}W!Ny`+@CU^%JL zDELdM`I8VO?%i2VRi(=)xo)=jz23DvX4^mQUK#{|U9oh+m@wLxHDgHN*}EGene#A3 zaTc*thPi?}7zqTfYR2~wV0e&v;$4y} zB>Bj5SCrJKF2SnuUg9>YDNeDsRBSG)h%Yj!u=WxtPcfV9(XG?-i1g&G%x}*Wm+G|4 zMW14;+aG~?Shgn7RzZ*c@=HDhWS5mFsW75r|L)k}%!=nF)lwSb3YC-)u1Cq9s2JiU zDHx5fztFs+fyPq@G)v{YDcUEwPSi#{*KadWb7?88xI33-63_vC%vz%58dZZ0x3-qKm^MkhAAeUm(sx zySNMe?!5zsfXbtMY2##TD$N-Ew4&sg-o~K>S!sw1B zLY|#(MD$SZX%G}7iilPipwdxdyrl+W{6XHsxWOMBPj*BWnPadmfv_&kSkhL@<~EK&J4Om9+zsJ{!0 z8Cdt$#XYmOO>omRXvWGK)1L2Q7y1QeZ%)U89NI(_E22(LaeSbkmqU~J52UJr(-N|` z#Ks4n4lYjTZ85vgLes7hWyrh*c5m_2a}?&h-7YGK*+@q23I}stkov>x9f>l!a0@Yr z?m34nfRpMQiv^;HhF|4G6|CVLj?i*R`yR}Nb$n0O5Ig4EALAJSI+-b>i_rDRY4 z%js1Qx~?tk?*^P9n83oHf$gy7;H(obnkvq*=6Cqpo-x0in7p>fv!7KU^9_DRjXtdes@WZ8? zdP3}WFCSreoVmp{YA^PA7&t1!bDpG(_Cu{7w;L1My*M&X`@p5LqTs{^rLqh2@ux0a zP4)OivUV5u>diNKZ>+agB$Bttello-WIbQj!VJwp`=2RI1xc(m{Te-nZmH#E=(H|T z&y2?V^6}ZG&+_T{?B`mX?|&;${wo)lT_l4q{v>b#|EY-mpU)-#FDzk-vff{cSpGV# zI(K>b`ky-<(bN*u_UHy=B$h(xfv^dDPaM*r=R@Y|=9J_C`GNq25P>JKmx4$SjxQ*1 zR_=rozuFG7NBKS8-~Rl8-$FLyjFm`%%k>>!&^9>GOBsZ%~{ zCwN6RZ@-CU0L|C-l`?ItE_VxUI){UewjYLvG}oPeL9er{O;xWoD2s5CWRnF_4UTJu z372>=q6%{+3X@(uwwx>r6ts@;Ch+w6R#43yNWhP`Ao3^U9BkZ`sy$N3c46F`h-(LR zDu!<7ulVk5dLcVuK++c!!JewnPK5R9Uhk=;jQL98DebF}MPJqQfrPG~n4b5wt_QPL zFsr_Y$;W743wZ#G>Sd`rck!2CT+)RXL_@YMU(}e;_4QiM`63w*p51WMut$<4ji}^F zTFAY78P3u|Oe{z=_*)@@O_|Lf0(zdMe*`TjoBDnHKtey10DpRdZm#E`D{Kx|pk^@Q z2Ih}r(Yct>`HLJy1DCsiQKY?6d@<^^si~F4ZwS^%BW6doMici5lyu1c6kPs(27pHkS>@J|Fa@LSxtg3B0jatC8lGQ3K!@V;jVRb~;Rx8|h zytsaq^kT&QjAX}Pv^*O49m=44+|PrL!RWqY^5lunSn8=&uuREz)g20k zkrT07XY40#*-k?zxEL|nhqB5D4P~Hut&Lx8gWa9Rb8Y4;e&nmhx1o3q2(na@v+wGQ1l5etudXvwSZ^#F! zQpewnmq!GxxYX)AXY{q0X@Jz_#@R_IaJzSF4JYYpbvxdY^9x&b0NIpR9R*NO8OZ~T zMP`aDWxJ4zBTJ8@dT6BN5&+}@2yuv%+x*hwHO(XgT5!+MU}HzrX$A!gQ5l{&)ab|~GZ%YjAS zBGS-in+6zTuUl*GA2u|DSnkGJ&E>!YPUHfO6CA6%4YVhe`gvn{UM8$2G3 zf7NafSM@H|6ZxRaY{y{;70$jlWN{VUPl1C!gn+v#LpLhD+I83IcDX_zic&fRM%RoJ z0v?Zl3>=St5Zt*~V{PHrER=nP`bmNb_0bRAT2k!`iCGJ}Y5$QgL&U72ghd`3TT_ik`PVo%J6&>8X`jzHF1baJMqqSCWfdA6Tws4+(k!y2)amaGvfIWy(>-n#Cl-W7R`k6QqflR(a)9``;#-m z82pYO**a2G*fD_oPJL}DWv59?x>p}DXg_JCX+RD&&=ST(^?4oMNPZxf(m%DM(F( z)%6!{^mi^lha8?V`eA&u*6nrgij7U5>|?c*B4T~}SmCj18}Zs?N+IcXc^ zAR-QNfS2b2szPPN3JzVsY+tMV{M~Bqe zVVRm3+I0x(IeGmsr*+<;l=(FL%cPu+j^7kz?v9Zq&3{SA)9{VB4wxBBPv$0wAw}ut z@l!y=5+(k&W{%T>vud39epi>m-vkZ@|W~;z+tU8||3mK>g?Q&^Py+z_vv!p82k&rv# z0fAEhJ^QG64Y#z}I~siymzBki6Ux<^;gANdx6?{?DBhucHx)k1Xc0m}&Wt58w?R*h z(wJs-4)kA>oTYD5lE6a*sTaAGLCd|6$hAM#ziK73tN45I(O*z2N|@c&_Y-QteL^js z|ICO#8?{@TnYey_{IhfW-!|TVQ&9d&lvU^zLJygQ02lKWRP4(?>juX~bK50Vil)sc z!+sRyO=Y$Vg9n58kkO!Ec>D5BwToWHyd<_ucX6D>y?N&jaJXcw26?E}5yHgtvOTCx zk)#eg$9IQbMni%1laSJ|@d%bvY0auxLnZDagw(6D*IMM9(3a&H>oSoMyImSP%Em^H z)mHXuEKWalS-lQfSHJneyCRiCOaGKh9rQiKzTQS9l+?u8O-}Rv$->fic2OiWIL5m2 zzFT7KLF;Ilpi=B8<7gu8hYC^*S~r7M~`}AfjZyL-2kfoQH}ejPJ)v zuyKIQe9Qw37C}|zQl#sR`KdmQ>|^sh0qkZ206|l2;|f>3gCM$K&5DVTIbg^Jp|>Xh zF~*TA=$8kScI_sYDwD;9ATEyLoe^LnGs7-9dg7cvD0@s47DA;C&4mCCfLZ*dAPUVF zW|UbsZu?IA#0iq#PjuGcNCxz0w)kkoku~Vg3~^eRl4lRf()+*Zng1G7x$Y;MtiHBUQQ|8*l#v+p z2JW)=K%sCMV-YfIk=e&DkXh!-cJ65dT{{6=z_g!FhQ1GyIG1#Ia&VAnqUk<|6D@}m z{2mX7)ef6q=C1i5z!a31rer~1y{U1iP91?lRX33Y8fv(BjrLQkgYJ0X|_^gjCV*Tw6`x^ z`|*t>p_d&ktR#~QlscnD#>^Ox7c!f<{cV%kz&MAqzoxE?G_>R1n%Pz|?qKOWnqV=h zRiN)85~>iYwMB>(ePKF@4ARd&S)9laU-wjuH_07S3s(R&rFzR?Xj^Lb=bSL2F6Cwx zSWO7s9V;-nGs9H2tNF_tWj7`V&i#bR1H#!9Mweolg= zKC(mMl`PC|zs+Hsp`m*FP4$-E_zr9)u85o zs9U3efQ)?#Q2*bQ+&?DkKPfqFA46TU6hRApkAs6odC^&SSUXW7wm9ioOx%^bj8xDN ziXupD5wAOn7U|+&W5F#+0AYO~Xk@!?(FzF?O37EM$zWt*B{6Yij1)Z$r)j+fJu?q+ zb<8REfWtP{B(Jr^9zo|WpRP;aLqGq`XMo@J(Cj4Yw6Q;lSjU~<%~KNJM(SV=yEmoS zhit&~u)^g@`m^A#m1F*xjYa9SYp`GN8E>?I?=qW#CTEP>Wnf>@DMJ9M1_|LOhE_^GOoAm<{rIjbTAj!fZm^l!RtabpB+i z+UM~CXOBIqk3419FPX))pYlu?h;q{&ly$W}ND4VZk4Zam}1;w~3NvRX>?AblQ&MtaYeJvJ{?^7W{ z0&uqQxafpS2jpOF5-7m;{{p&<721)nDw~hYc=D2E`$advWl*%q8T6|zqc+%uyQ^m= z@ms?*vUwC&6tddb_%hF;v%7e+SrxCm@aAe%<6MFUxv6`QSYeFW_)0H)83!|;8A)mb zi^$^q>|s>Zlukj8KYa>W$C~M$;WHNcuFAGBW&BWS2-_g;vtwQ+2;;}OS6$^QU}D~0 z++$Q@tU|IpJC(%NW~?r1LAMgW;HtuA&z-MP0XaErPM3;p8FA6jIy1l;u^Xpy>$Nc` zBc3*&R?j29uO;;(XbVNsoozZ7&`4g84tctJAZ<)Gzc8EMxQtS_)zv*>$@f!xe6O-< zd1Ox~=jit*2{^y9xoSi{i6Iicl6=HwqVvBx`wFNkx3y~l0V(P3?gkO1yQLdt)0=MT zmhSG7?(XhT8j&tZrMu+ce#djwt@qqB{+F@GhA~)ku6S2H>sj-8Z=l>Z8Phg3LNk?k zLR!b|fps*k(K4U&o0!v(4G&A4u#bsXmjb7x45}1(4zl^glQ;rQ zSkI{@s#^1`4@I`JUfQxL&idlLj7l5fLU*1~Gf9+IUksg@?z5j}B3M3kdz-&$JgxhR zs(K-NRZ&@yEk!Dikv6%ypAN+-dW52xn@=_3q$mWZk+P)>$3o2cbwctxOLI3Pwjk?k zJynA4Pa{GfFAtBUg{7ZpJmd&g|9G|i!6>(4_0w%qT<&VZ5_O_oy2Uw3;OfEv$Hf_G zcUqCqDt-`8OIoyqqsE{NDtC1@)=H_?8!~pK^tT`K3K)}JUTgV!h4C7d5DVR@^2Eg+ zAdRReMZ7zis`(;ynoj|t!zlv2ro6+c)EHQ#o|>Kn^S*~CH!GDN#!C0}JlQpA6U$|c z(|rpQ#~!f?)6%GckiD!qA>5OvasOmbN+b$EUu<_?{-Q@uH9xpPORCu`j=10NAvgBm zlh!ifCMbK9R>St`7M}?vcSnyE3mRVXzO-Yt)+cBrKzLq&DiADxaR{Jl` z&hl53hQBz7m@ELth8GOS_$%JP62|r$Lj>x>qyy)k11RL&un9T$pELx##y-jZvUmN++zJ7GNwmcz9*>1e@(>G{8(U z;ouYW*+PyXX@N|L^p}~weW5i4NdZ2C!@b+y&@>=o#6ewCRil$>&^rVxU6|$0*PBTb zsWQpFwn8Ru*wLhlph}zI$91cJdMND{(fMlgIcM8UrrH&s?*a42bY2cbJ_e1=6sysQ zEy@(AK^V_B7dW7O`6JR3mDsl6$axi&s?L>woZY-8-|{|Wgu9usm`^nZ4`zti{g>+6 zv5oEO4#bK#5?|KpwzX!`nW`nRVz|xds$h@YHcZ#b*IYI=T%r0B$HALuTJ^05DaXxD ztHce=n(0~buutxceWYbiD#8oQb5vz4cvW#IT-_h!*B60%`;?q~GZdeLW6`Xi67M3q z)lD0#zsV{gT7AFXCXbT%&O;G?gm9gzy@sQNuIXcf=F>Mbu6YCEjefC^c~|^MQ-mo? zAge&9+nAh2t0=bpR-zW`2PSL+uMytH2e4zz&@x(M0-Aw)yqJP7uC*!`jBd8bOp-N)Z>#F!%CAka2Fv!V_EFDg_G5cL& zrQqqwxkR~LwAOwjrQ>7u0;<6fcI?5a7@5-xi;&=jU~QAgWkiYttk73iJBW+|@$a$< zK0u;;AP8}PbepMdj}zPK{9>foW(zws=<3n-(^HP&eHk%!{)DqZs|Ul{Zi?9nkjnf8~ZcTQr;<&zX*EHI(2y zpSLGFQ+$qkHAs#vsn-PYis+i-t98Ee0atOQP+6+T#^lCh-vi0aUQDRb(N#0dt3&_U zIfdhTelc&rgg@*{o$aiS>2uMt2HfEIm;Q57xQpOAD7g|-dm2w z)^oVyaCzuS7D6r=B~7uys@5l6-5j;GmVS9z^cQd3$vM(?NZKi^0C`s9p;VskANfW4 zi9ZE&e+@?WH`x@VBhJ;>t8#Gs3}}OzR1vmc6HJB}svz#M^Ea_nA|b%Zb|z^cczA-@ z*;Uc*HjR=tg=0-aFIXvHQd@!5mtYkzrxhk^tg93@XP=#Yb~Tx!i+>JVWnWGFc1~Cs zZuglyadwqLFp2!xat{^?Cv?vjYh6Dq7nIq;F8av$f||D(xz1d`U`1)A{bJ%=7#29xOiIVGUk! z=93k#eV>aEnKQq`kaOK=kD6r9x|b(y66rXma@iF1tRg>V|1Fb?4}(j1(@y`CaC>&z zDSq%ob4^J2gk`z_Yr0q~Pt2OOC|p^V^p&!dE&gmvnqo`HxivA;A!bd2RiGk90 zP1r8bhg_2Hfn)EiRkK2b^9AP!nle_9>lBh-K{!0pbSRi6`Q$%g#d+%P^1vR?-ufH{ zFgt%rvI#l$?!~0q(PsWLk2s?2fZQqGHW|XTy~o#hrdH4HquS&mGNrbT@lR>o_Hz5# zQQj7$4-~7yu6mJGSUyF1Ce2EYSw4N8PVs6F2jyvl1Agq&NM9{Yta?jF<5gNcn@0?m zuK|@2>Dj0O&^MWlR46nJtTMw|yPBUfEKZ&A@8Z5nE%VY0O5I222~a3$$r73CtY%r< z+zl+xkdxO$7uGI8peL(l^hK-qutbq+x?gUm)ar9{!!A*6oVWt9^lBdIli#*Nqt5#` zXnQ>+koO|!auIz-ciaw_4)fI+Vq=;k*qtv~<^(n4Mt2oU-px0?bAc|oP;XO(fbF9* zDQ|HFd*Hi!D&-Rc@{M;q`Kgx{*Wv4^2S$fb$;ZQQYs5M{8CR-tE1Jp(X&O8d<;+S) z*FHb8@S+#nv2WN9rFzwREQZd)uonReD6kjl)x9YLs75u%K+9em9b)0emwA#^#Tg(? zLm*{0OJ@ZP`~WS2=l*&!)p`s`U#tN7-Q&qGl^f{62@y-gk5y~I(OyE{~#uPuxf4U7I0IIKnK1YY1T&BMiPYqU0$kH;F)N6>(ph)aT0oroRN3^GG<+;R1E-r6exBGbn_*b>IRlYLa zrMAClUrE@mWoRMHoa}(p6;*=@r8E?dynFD}6QTF17uFW^HPOV0Y%*-av(V}K$T@!b z=Of-8$U@~0IHRBxJO-X%TmpHd<9fTj`iKN>Lr&2)>%873$K;H}LNC3{BPQJtzU66! zlsF?Hc`^1P(>o#laPL&9#)wb-95F{CNpd{ZXMFs`ScBK|vAl!99i-jkh^;D~m% zLW{FELpf>H2b>0m*ecNypVQIED>JX&&t5@X4~W{K$8H}BoLFstSjurYJ*e^aD9^6M zn-dwcyhC%n9SD$sIki##3eO|a+WL4IUc00lK!dftass0{K`^Fv+TOb@aCh*a3VEVE zPtcK)hg_Ao$SjDbd2W8Y`1E~Cz#Lgz8>Otro06~g%xFZp`{%*w_7Ioz>Dg)B7@`5> zqHXlmZOzv1?Z~>fhcu<833axKdW@*h42>Uoiutti_$Vi_2bC|Z$n?bn)_d!L@OQY@ zcaIt0ws-8m9+zkdqiK&2TY;+C^Mu}8j+7LyvgU>6zRP^}jQ0|&;e4f4r?VEjZN6w_ zE}#`%x$K(e&6kmmvn&Q}VyW&krXHE&1tlVpg(aB`CnTKS`8CdEVd&PAiPY+m2ohh? zC->=JyA7-BD~=qOZ!^lGd2=PdLfwrUvL}$>es!UD9WPX&Z+J~0-YSd%%XhQFcd)K} zQ?Ltb%k8|~j&X6HCyn_*Hv3_jR`$CjoEQ#Y^HAE*&n)Nq3%)iFa9gq0NgQALAFcDH zG4(q^ZyEzy(AHIO%KKa>``mHLJ1^lf0?zeYuuf+HEkyQONjm}FWA{+MT5Htgf#EqI z(;_YCfR_E=m=*<%Kv(SlI-a-t%XCv3=lNn%0H?owCd|R!7YUq(H9!af)O>PrsNO$H)=yID ze?n|i4xCm!caO(WtTzYT)Z_M1uP^2gAr4~JiyfwNlvr`m#a|?<5mX_@FVMXnTByz? z!i)JT-8>lCdeT+j5@6*vkEy7G-gT@>uw<^8lMG8Pt_LIOq(6QZ>(JJ@tX6`Q;p#Cw zz`~*7(z|RsxteWhd6~|*E3Kr32)93NXiFG_=w22`qO1+TF&Qi^;Mh?@($X2w(d)$? z?~K1W@V_$FuG|mipEme9q}!-vadea&rL1lEpnDEAoI70`QB!a>DW;sP`=dfUiwXXI zom%bwY!#>fb2lTyC=G+ixNZQz!iV9e?Fo*DF-v@jF3QYUx|0|i%HIZz zW>#(uL|HU!g!9Nf@TRB?O^?BW&qCmkVx~N*d@m*VvP;S@s|FWdLk>C=H5CaL*#uft zeE)fLivL$!xFo=6K2(Rx1BM#y`3~(zu@l_U7}2BadVwz=n|+{|z6_3Sdole9(Js;` zOrl6LrKEPiS>w`VK#P(Xmp>QZRks5XgB4(2tOb$d(`4SMNQLH6{2_0s?KzW-%L|L&fk zv?uq?&vvq0C%(31LmET2lWs4*3gZY}L@z8T$_oz0_uk);QM#`A{l4C*f*a($6j`Ln z8WbqR-1AAyEDOk6kS13e_eHv$@#aMaar*=1%4c5mG(ZCxB#l_nr^VUXfXDGZ&Peb> zUCM7XL?!ybPD@ZASWX>*7AOh(qg(u{$Pah^rc-8>3ThR|HXiYBM-GEAd&Vw z{qy_SIvhpLb^tqKDR+8n+wxqcZ@pW8ttfT-$RZ=rQ?l@wLX#Od+*7343MKz8wRB@x z&V+z0+2#+)#2lqY9r$Gy(>nb{SEX1Nc-g)9M1GF)Ps6AoX7dPJt-I=m`O8nR&Twht zui;e4+t=xxdLH=CU{5&nWfY}~u1&VEr~t5V;ITVd5szIKA9o8m*rc!2u2D{d0;5`7 z-v};x>;z^-oGB-wqY$bAwg&*}iT%&~bx}^FKzaj&(&|Py2TXTv%QpCqnd`Kw_6t1} zP{rE~-jdLxICKfwBf7Wc?UmKWGvxj|C&pq{jWm50_SNKzfF55Ow=I!o#JBED^{44C zxvlCg$_4Fj2)8ABlYvE7Ck>=8_?e{JIR(*kZK4y(7J$@rY-phug3tuJEi?eY;h|_077@2O;okNXBIgmdeIPVt8T4C-X zPM5$Zw246FDKyLHPuB%8#I6~h>E7GZ9@fc@zbyCEP=xUbjq`R|6Du-Ry3oR8w#t{> z_vG7)y6YHE7a{P4%=uufB6-jr_cDwUk=u+x8>3k|hNr$0=v3x`f}XU6>1qyxjP?(H z-Z0-C+T*~kZ=5JQI05%gLaWEGCHmpwzPq-szgA6`Joqu-U85*@B`8!QDabMQ`S0WU z-})*4<{Yq8bx{pp6ysjD3ea7(LH>kB&F2*g8fuVj#gb;F4_WP{ZuI^7CK?kK2(nTBUjG)H#hXB+z7f+ zbOw}?@L38Y6CHYYrC97!Fp_oW(&>qd#Ag|*PI9`2cM{|37^7^4g$|8HP1!r-Re-8nv=~Te>P*J~FK(VtHyS@Kp)cB`#+sq!@;PkLubEU~@gSpSFI`S5x z!-cs1Z7_DKb5q(8r9k23@ha#T5@hk+PE|oIC7BRw8#2vfxeUNz@410RgBI^-Q)p<( zy#1MiP`$b63-s)=bti ztdv5iRp^aT{8;n&%>*@i6D2Su z&f}~SS3|%x*cu|8*Lx7W?}&*f2GOgi8L=i!akBz-{109xcT?3r1G<1t&P$ z1-(8Bwjttb_9NLooO2PL*r@KdPypZC?o8J!#Di$PJv1X!XUn^wM@s(CS|Wmd5JW*V zLr;71+4zK0EeDWrGu9Dc1}@Pe4Bg(8JD-Gw(lD{67Lf||8KQK?P}61g^h@V-nCTc| za#g=^SE;AZPY0}s#zkP~yDrs)JyCj?v3`3=8TlIXGY;0`RhEQO_&iWW_9`Rz_5}*> zMIfLKcRAf5j!-PQItSMK<-AaCRiUZ#apPHT z)0@E)XV^}GSuI@e$q?Px^IbvM=@c7H#={B0=mU>93UPv4q|%fZBzMZ#)4D3kf-_rw z`rU(>rozoO{GJLJj1={K++We=q#`4%g8>^8sB^e&{bUZ$aMHV8>uh5RrBT|;LU(x+ zk74ElwjY&WRvwX$Obie|jGx4!k13nRmw;J<|&OYd}kO9oC0*kvQvC39usYe*K`w>N-Y6Yd5SwAJ5;WU7hYD8rq4YtDt<> zTtUg8TM3gh`osZBAEu=Bf4UfT z^^ALDx!M?lG}u{;L&4ZB^2HBXNr62%Fuqp8&o%tbU#BcGqI$xQQng)X21!MVxPy+# zN53%TVo16rrE%Y+9k?xXv$x;7-9zZ2($gBq%PWBVf`pK-Su(OW{DV^@8FC`M()$=0 zsBE-6K(_+u+b=#<<*c;@!@{GvzB9K`6U?g`K2Kaa_A6BL`^-qcT?pT;_i}g@-l)kV z!KZqVLAcx{ydrdiEtf*73+<(bAjhkZ$|zd3pJNx)P_aD6P0j7LFz27pMwfo%G_qt9 zAF#s-b$;#>`-#3zf7`!%muki=Z|oIY|Hhe0^SG|6j-mwzFF;F~321GlgeT9E$efxW zLL`SGlFI9CpPb5z-O{0%JpGwIeB9J}ScxT;KO#CjrUYs5tMm)ofW|C6({X(0!lFf6 z)7!>KLY(G~T_1x97C!(qRKBSiLBO8$Al`M`BuZ6sGK2co+62)UZwZZmatWML7s<+}%M`CJI#7C^4NaheQFS<>+jnALTva4Q=^nYG88GFOCgoGVQxO+QQ)jf$#L+ER@} zP`dVDA)7ap;CIbkrT%TtSe0DXzn zAHblsv|jGix#n0cf8+<`QnP!3+ojE6*zGQf7o>mi^c>`)p|%s2hT9C12ep(7R4l&+aQd=bbTN zVPX@sk_cN$BMlwGgjJ+%JjH+`7joqgis2Q1nS=tUqIGv9mN9;XI&pII$n)4tur}6s zQhpXOnjwTWIG0wO(|{Q=jk*w(Y(yI8B1vr^p`d{82098^r;X;5=7y_NwoWnYH zZkb*eDEhQKtjYvGxs0-~!7P`^GO7CmLp2vR;k5oGa%Zp0vV$Vx=Hwy+UC|!(Lh<^k zX~wH2Qtg8&nKej_v{>|0cWz?1ag9xDMzVG`?oV*2)LJA%(M zI1P|19PRHT|4(jHV4iPb(K^!IEExVTjOv@NINOgjdsN4F!>~W&49H`^!!s@!TOi_E z&}lrowRm|6b*rEkFGS1ad!9GweA4#fF*SettK|pQ2>nk8K3WHMgxm2^3z1o;>IQFp zlxEFes-}Q^p}5vuyEbefrME-A&Fj|pNw_L?)cmQ?7!vM=I+hPf16wbmS*<*LUm^eT zB8{R36uD!PY0H4DexhDn%X8`h=(B_GaQBX0{;T(P~c7`(&AIcdrg3@-Am&X?hGrSUIvkQ0`n8;J5ypb`r*0+I9w&t=b zWZjgkO(;5cA0c4fIOoJ{5{1fCoG>Hkl?feEZb7OJCA~LiYFy|7YhG*G*`(S8lbauh z^{RQ+xU|5Bt)$k52j)=&&+YiFsU;pHNoTU3|qm{xr@e=^-Z zmNDiDFrE_}uDLE{zni!pCtf{WSj6#xGq+CNNw~4yw;Ofduii>;^=$uo_u>JNC(;@% zNq@?K(k}`%Du!gm$B$AQQ5QEsM0+y^6SbJYQPjt;nCyeUwQP?A9M|C+KR`(cjl?5> zu!uqrqrcz{Y%6M-ej-hxDyK?q>|S!bqL~Yw)rZf)l{#Zcd+~alpjg4%2u)e@!-z9^ zt*ch#1SgKLOkCB2B%j_}gsnd0GUxb=`M#-G+0+0IQ%0rGf-Zh!i}7v84x67^Eo@$H z>5ghQ6DK`m2I4VN_gIOWERci4$B;)-%=KAz49pa-39?PoXcvn)9;H_0mop@y-#uWH{rj*$%&q= zQIZ}<$Nl&AM*JpZE=CQqE%uIfhl%Tg@b)l z48qpT{2_4x$)+KfFa3SsBMR6UT!?^oUQnP&k}DpCd<-pGyxReh__iBCdcYev!WtIO zQv|t-q31ftAUTDeiX}DF-3vv@;3Cs7F%EX|gwNW<7tVcQ(=}(ByLrcn*rV<+bfBPI zMo;G@C*Q|%xjvV5MXXBgG~h?96NyascHjLvB^`Gm@AAydzC9Uc*+>X8Rk6A(l3|vJ z=YY6Oxmh#7^~=W5SN8z6FGpsefbX}j)~LeQFi~CP-|P_f`3SyT0)7gJP;IVkRXSVnPX&W_`QcT$IKKZ@f_lz8ig~MyN(p7 z8}66LoHHg`l37Fzc70|Wt9W1+@=TacokOmtB(=h;Lm>lUz6P4`xryduc31$(cq{sX zI4LfS&VJJrzIcdZBbO3cFgheBzM&qxmHS|Wc;@(rn+SU`*#MV1?noc!x~e)4bypf% zJ8KzTE<>h@htjGHNSDg$PJ`LOXYH{@BGAg24@4nz#4`zc3h720X zUaP`OqC=0fyI~ecS22c@qTAH3d~AqGZ|6Hi&)Nn*{cxYcIrZX06_fpHVtq(zyeVYyl`Lrjp-?3x6hbhjgst%VZFRWKYHUz%(Xp9GY*wHyX?jZ1 z;%kC1^aj(D7L&LR_DVeOudWa}ND1&YzRV2(xFVXusGUr+fLWpgt%wFF?PLbYrRYAh zA!0;;R$_^RZ9SgTDOgrS=iG@1ZPfHfnA=WGCVj@8e)3MtQ$0$)>OC#$Zq&K?E?J2( zJWF3r$v2+2p}ifmTVSzv8Fym%B=K6}^Dg^_ju4Qc4Usoo+3l9~F`48?lk?GD>Qz6X z>k$%F@6+Z|B_X~O>UIsXmw zM?57ByWVMBzFB%c4IUvzTG!N12P;qJEexFUy*Vd0gJJfo+&i#xZ^5?tupZCqpMzE! zLvVjIc>exM{og^>e_3dJmP1!S`6{QS{*g%@1?3bQKjsS4<_1eeQYgL ztWK3qj~YlT5Lt$!fTGWniZ2)$kXo&ksqW$(dAap2HHmvUDJd<9xBaWz&0~^aL)7$0sVICXRs-?f)7n#!B5+Og`K-VQK*XdhaU#KET% zM!;s+w=6H-ls4oQkFLv!Qm`!!E=VN|+e5Vl^=$azibaC;cHj+YyxHc~`Ve7Z-NlIUfOsQa-g7Wox# zOMwnS*=y7`kt?==mGTV&-^3@5??a#E9tH0(RN}7eM2-2=qq&)29%^@C1?Q_og#psTqs4oi?W>0jekGCLWW;n+15 zy>a*MRBG&^Pr}Yyx|h<~<|)|DYj;Cvg-smohsCq8Y`AoL>%1t}j62sHB;~zg+yL1* z2C+a4JP?8{eXrfWsn8#NSOsk#T@qt&5K-Ll_#=TVRW$2D_B_E9vWZuK3C|&18S|lE zTlUBs;(}L*_agJ8ezhb(JjgE(!fpakW*QbrTg*C9f^rU{s(|+&hXTE8qX$8vJ!^b$`;}-}ps&9|95s z3KS0e(W3`apxZMb;{Pbmg9eB156Xi*!Ee9HiYf~-O3H~b%S->7Y=2<{^P8na8T7&U z_MhLM9Pe*?$^Rsi6_k?{6ID`Xk`)6-_?7@P$^G90n&`ei--r`Izkd_#{ihV59n()K zTE3_FE}8#N2|;q4KPBAyHR1Od2){9#_!tY_>nCyHzXARZ zT=chuICzdCv`)jZK&7_^m0aW(z_0%U5PU%gTG}}|3p&`FfOK7f`aeXA!5O!{sM{5R znC3wrvR@b-L3#K?5hVXE!(aPLaJ+d5Q95XlxlA6^65mdV|9*13bwQ@&Kj48xXU!e# zK=-Z0faZpR`uc`;cCr9VfbriU3BU>T%e|X)K~;nTB4PX+9rT^!T?eB41A&??z#4RI z4`i({0vbDj^qWCK=6}w+f;%B_15|2UP&Z)t1sd@9kI>+iE&+n8$d3#01@Mvj>=){~2wuLnf#P zRQ@2G=6EwR z{}K9otBE=p>O1^LaT^>JMf%m3JrF8AC^`rzhyQtUycwI0)u0Miy8gE)NuSK% zm&FgF>CE4VetTX2sk?!nT>n6x2W?pXWgY$b92>k4;0K03s7CYtiRypMrQnBPKVTIL z{t5Q`fbkDUV&DY;H+2uJK5$#! z5B!#je}VtsEqmbg1#Y1DK_p-EpM~LnGgrt \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +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" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@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 + +@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= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@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 init + +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 init + +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 + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +: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 %CMD_LINE_ARGS% + +: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/lwjgl/build.gradle b/lwjgl/build.gradle new file mode 100644 index 0000000..4a28c46 --- /dev/null +++ b/lwjgl/build.gradle @@ -0,0 +1,12 @@ +// Project information +ext.projectName = 'Caustic LWJGL' +archivesBaseName = 'caustic-lwjgl' +ext.packaging = 'jar' +ext.description = 'LWJGL implementation of the Caustic rendering library API.' + +// Project dependencies +dependencies { + compile 'com.flowpowered:caustic-api:1.0.0-SNAPSHOT' + compile 'org.lwjgl.lwjgl:lwjgl:2.9.1' + compile 'org.lwjgl.lwjgl:lwjgl_util:2.9.1' +} diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..ded588a --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include 'api', 'lwjgl' diff --git a/software/build.gradle b/software/build.gradle new file mode 100644 index 0000000..ad23b3a --- /dev/null +++ b/software/build.gradle @@ -0,0 +1,10 @@ +// Project information +ext.projectName = 'Caustic Software' +archivesBaseName = 'caustic-software' +ext.packaging = 'jar' +ext.description = 'Software implementation of the Caustic rendering library API.' + +// Project dependencies +dependencies { + compile 'com.flowpowered:caustic-api:1.0.0-SNAPSHOT' +} From 14ecc3490b7fc3aaec6393bf8d8c3c584235e6b8 Mon Sep 17 00:00:00 2001 From: Luke Spragg Date: Mon, 16 Feb 2015 20:19:26 -0500 Subject: [PATCH 7/8] Update readme and project files --- .travis.yml | 3 +++ README.md | 8 +++++++- pom.xml | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c0ac547..c4343b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,9 @@ language: java jdk: oraclejdk8 +# Do something so that Gradle isn't run +install: echo "Gradle run suppressed, using Maven instead" + # Compile and test source script: mvn clean install -DbuildNumber=$TRAVIS_BUILD_NUMBER -DciSystem=travis -Dcommit=${TRAVIS_COMMIT:0:7} diff --git a/README.md b/README.md index f8be0ca..95f4e83 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Caustic [![License](http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat)][License] [![Flattr this](http://img.shields.io/badge/flattr-donate-lightgrey.svg?style=flat)][Donate] [![Build Status](http://img.shields.io/travis/flow/caustic/develop.svg?style=flat)](https://travis-ci.org/flow/caustic) [![Coverage Status](http://img.shields.io/coveralls/flow/caustic/develop.svg?style=flat)](https://coveralls.io/r/flow/caustic) - +OpenGL rendering API and library, with support for LWJGL. ## Getting Started * [Examples and code snippets](https://github.com/flow/examples/tree/master/caustic) @@ -16,6 +16,12 @@ The latest and greatest source can be found here on [GitHub](https://github.com/ Or download the latest [development archive](https://github.com/flow/caustic/archive/develop.zip) or the latest [stable archive](https://github.com/flow/caustic/archive/master.zip). ## Test Dependencies +We love open-source libraries! This project uses are few of them to make things easier. If you aren't using Maven or Gradle, you'll need these! +* [com.flowpowered:flow-math](https://oss.sonatype.org/#nexus-search;gav~com.flowpowered~flow-math~~~) +* [net.sf.trove4j:trove4j](https://oss.sonatype.org/#nexus-search;gav~net.sf.trove4j~trove4j~~~) +* [org.lwjgl.lwjgl:lwjgl](https://oss.sonatype.org/#nexus-search;gav~org.lwjgl.lwjgl~lwjgl~~~) +* [org.lwjgl.lwjgl:lwjgl_util](https://oss.sonatype.org/#nexus-search;gav~org.lwjgl.lwjgl~lwjgl_util~~~) + The following dependencies are only needed if you compiling the tests included with this project. Gotta test 'em all! * [junit:junit](https://oss.sonatype.org/#nexus-search;gav~junit~junit~~~) diff --git a/pom.xml b/pom.xml index 478ec40..dabf680 100644 --- a/pom.xml +++ b/pom.xml @@ -117,7 +117,7 @@ . . - LICENSE.txt + ${project.root}/LICENSE.txt From 21339ee94dbb8e2d999d124daee698207c299b5a Mon Sep 17 00:00:00 2001 From: Luke Spragg Date: Mon, 16 Feb 2015 20:26:58 -0500 Subject: [PATCH 8/8] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 95f4e83..a21abb7 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,14 @@ The latest and greatest source can be found here on [GitHub](https://github.com/ Or download the latest [development archive](https://github.com/flow/caustic/archive/develop.zip) or the latest [stable archive](https://github.com/flow/caustic/archive/master.zip). -## Test Dependencies +## Dependencies We love open-source libraries! This project uses are few of them to make things easier. If you aren't using Maven or Gradle, you'll need these! * [com.flowpowered:flow-math](https://oss.sonatype.org/#nexus-search;gav~com.flowpowered~flow-math~~~) * [net.sf.trove4j:trove4j](https://oss.sonatype.org/#nexus-search;gav~net.sf.trove4j~trove4j~~~) * [org.lwjgl.lwjgl:lwjgl](https://oss.sonatype.org/#nexus-search;gav~org.lwjgl.lwjgl~lwjgl~~~) * [org.lwjgl.lwjgl:lwjgl_util](https://oss.sonatype.org/#nexus-search;gav~org.lwjgl.lwjgl~lwjgl_util~~~) +## Test Dependencies The following dependencies are only needed if you compiling the tests included with this project. Gotta test 'em all! * [junit:junit](https://oss.sonatype.org/#nexus-search;gav~junit~junit~~~)