From 500fb1c861bef738f50a58cece13faaca5c61022 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sun, 10 Aug 2014 20:34:11 -0700 Subject: [PATCH 001/141] Added gfm:math as a dependency, started converting usages [skip ci] --- dub.json | 2 +- source/dash/components/animation.d | 60 +++++++++++++------------ source/dash/components/camera.d | 51 ++++++++++----------- source/dash/components/lights.d | 50 +++++++++++---------- source/dash/components/mesh.d | 16 ++++--- source/dash/components/userinterface.d | 9 ++-- source/dash/core/gameobject.d | 42 ++++++++--------- source/dash/core/prefabs.d | 1 - source/dash/graphics/adapters/adapter.d | 1 - source/dash/graphics/shaders/shaders.d | 17 +++---- source/dash/utility/input.d | 17 +++---- source/dash/utility/tasks.d | 5 +-- 12 files changed, 139 insertions(+), 132 deletions(-) diff --git a/dub.json b/dub.json index 758ddc40..78451784 100644 --- a/dub.json +++ b/dub.json @@ -18,7 +18,7 @@ "derelict-fi": "~>1.0", "derelict-assimp3": "~>1.0", "dyaml": "~>0.5", - "gl3n" : "~master", + "gfm" : "~>1.1", "dlogg": "~>0.3", "x11": { "version": "~>1.0", "optional": true } }, diff --git a/source/dash/components/animation.d b/source/dash/components/animation.d index a7fae326..4d306e5f 100644 --- a/source/dash/components/animation.d +++ b/source/dash/components/animation.d @@ -6,8 +6,10 @@ import dash.core.properties; import dash.components.component; import dash.utility; +import gfm.math.vector: vec3f; +import gfm.math.quaternion: quaternionf; +import gfm.math.matrix: mat4f, Matrix; import derelict.assimp3.assimp; -import gl3n.linalg; import std.string: fromStringz; import std.conv: to; @@ -24,7 +26,7 @@ private: /// Current time of the animation float _currentAnimTime; /// Bone transforms for the current pose - mat4[] _currBoneTransforms; + mat4f[] _currBoneTransforms; /// If the gameobject should be animating bool _animating; @@ -307,17 +309,17 @@ public: * * Returns: The boneTransforms, returned to the gameobject animation component */ - mat4[] getTransformsAtTime( int animationNumber, float time ) + mat4f[] getTransformsAtTime( int animationNumber, float time ) { - mat4[] boneTransforms = new mat4[ _numberOfBones ]; + mat4f[] boneTransforms = new mat4f[ _numberOfBones ]; // Check shader/model for( int i = 0; i < _numberOfBones; i++) { - boneTransforms[ i ] = mat4.identity; + boneTransforms[ i ] = mat4f.identity; } - fillTransforms( animationSet[ animationNumber ].bonePoses, boneTransforms, boneHierarchy, time, mat4.identity ); + fillTransforms( animationSet[ animationNumber ].bonePoses, boneTransforms, boneHierarchy, time, mat4f.identity ); return boneTransforms; } @@ -330,10 +332,10 @@ public: * time = The animations current time * parentTransform = The parents transform (which effects this bone) */ - void fillTransforms( BonePose[] bonePoses, mat4[] transforms, Bone bone, float time, mat4 parentTransform ) + void fillTransforms( BonePose[] bonePoses, mat4f[] transforms, Bone bone, float time, mat4f parentTransform ) { BonePose bonePose = bonePoses[ bone.boneNumber ]; - mat4 finalTransform; + mat4f finalTransform; if( bonePose.positionKeys.length == 0 && bonePose.rotationKeys.length == 0 && bonePose.scaleKeys.length == 0 ) { finalTransform = parentTransform * bone.nodeOffset; @@ -341,13 +343,13 @@ public: } else { - mat4 boneTransform = mat4.identity; + mat4f boneTransform = mat4f.identity; if( bonePose.positionKeys.length > cast(int)time ) { - boneTransform = boneTransform.translation( bonePose.positionKeys[ cast(int)time ].vector[ 0 ], - bonePose.positionKeys[ cast(int)time ].vector[ 1 ], - bonePose.positionKeys[ cast(int)time ].vector[ 2 ] ); + boneTransform = boneTransform.translation( vec3f( bonePose.positionKeys[ cast(int)time ].v[ 0 ], + bonePose.positionKeys[ cast(int)time ].v[ 1 ], + bonePose.positionKeys[ cast(int)time ].v[ 2 ] ) ); } if( bonePose.rotationKeys.length > cast(int)time ) { @@ -355,9 +357,9 @@ public: } if( bonePose.scaleKeys.length > cast(int)time ) { - boneTransform = boneTransform.scale( bonePose.scaleKeys[ cast(int)time ].vector[ 0 ], - bonePose.scaleKeys[ cast(int)time ].vector[ 1 ], - bonePose.scaleKeys[ cast(int)time ].vector[ 2 ] ); + boneTransform = boneTransform.scaling( vec3f( bonePose.scaleKeys[ cast(int)time ].v[ 0 ], + bonePose.scaleKeys[ cast(int)time ].v[ 1 ], + bonePose.scaleKeys[ cast(int)time ].v[ 2 ] ) ); } finalTransform = parentTransform * boneTransform; @@ -372,7 +374,7 @@ public: } /** - * Converts a aiVectorKey[] to vec3[]. + * Converts a aiVectorKey[] to vec3f[]. * * Params: * quaternions = aiVectorKey[] to be converted @@ -380,13 +382,13 @@ public: * * Returns: The vectors in vector[] format */ - vec3[] convertVectorArray( const(aiVectorKey*) vectors, int numKeys ) + vec3f[] convertVectorArray( const(aiVectorKey*) vectors, int numKeys ) { - vec3[] keys; + vec3f[] keys; for( int i = 0; i < numKeys; i++ ) { aiVector3D vector = vectors[ i ].mValue; - keys ~= vec3( vector.x, vector.y, vector.z ); + keys ~= vec3f( vector.x, vector.y, vector.z ); } return keys; @@ -400,13 +402,13 @@ public: * * Returns: The quaternions in quat[] format */ - quat[] convertQuat( const(aiQuatKey*) quaternions, int numKeys ) + quaternionf[] convertQuat( const(aiQuatKey*) quaternions, int numKeys ) { - quat[] keys; + quaternionf[] keys; for( int i = 0; i < numKeys; i++ ) { aiQuatKey quaternion = quaternions[ i ]; - keys ~= quat( quaternion.mValue.w, quaternion.mValue.x, quaternion.mValue.y, quaternion.mValue.z ); + keys ~= quaternionf( quaternion.mValue.w, quaternion.mValue.x, quaternion.mValue.y, quaternion.mValue.z ); } return keys; @@ -419,9 +421,9 @@ public: * * Returns: The matrix in mat4 format */ - mat4 convertAIMatrix( aiMatrix4x4 aiMatrix ) + mat4f convertAIMatrix( aiMatrix4x4 aiMatrix ) { - mat4 matrix = mat4.identity; + mat4f matrix = mat4f.identity; matrix[0][0] = aiMatrix.a1; matrix[0][1] = aiMatrix.a2; @@ -465,9 +467,9 @@ public: */ class BonePose { - vec3[] positionKeys; - quat[] rotationKeys; - vec3[] scaleKeys; + vec3f[] positionKeys; + quaternionf[] rotationKeys; + vec3f[] scaleKeys; } /** * A bone in the animation, storing everything it needs @@ -484,7 +486,7 @@ public: int boneNumber; Bone[] children; - mat4 offset; - mat4 nodeOffset; + mat4f offset; + mat4f nodeOffset; } } diff --git a/source/dash/components/camera.d b/source/dash/components/camera.d index c49a20d9..9a2c6814 100644 --- a/source/dash/components/camera.d +++ b/source/dash/components/camera.d @@ -4,7 +4,8 @@ module dash.components.camera; import dash.core, dash.components, dash.graphics, dash.utility; -import gl3n.linalg; +import gfm.math.vector: vec2f, vec3f; +import gfm.math.matrix: mat4f; import std.conv; mixin( registerComponents!q{dash.components.camera} ); @@ -19,14 +20,14 @@ private: float _prevFov, _prevNear, _prevFar, _prevWidth, _prevHeight; - vec2 _projectionConstants; // For rebuilding linear Z in shaders - mat4 _prevLocalMatrix; - mat4 _viewMatrix; - mat4 _inverseViewMatrix; - mat4 _perspectiveMatrix; - mat4 _inversePerspectiveMatrix; - mat4 _orthogonalMatrix; - mat4 _inverseOrthogonalMatrix; + vec2f _projectionConstants; // For rebuilding linear Z in shaders + mat4f _prevLocalMatrix; + mat4f _viewMatrix; + mat4f _inverseViewMatrix; + mat4f _perspectiveMatrix; + mat4f _inversePerspectiveMatrix; + mat4f _orthogonalMatrix; + mat4f _inverseOrthogonalMatrix; public: /// TODO @@ -47,7 +48,7 @@ public: * * Returns: */ - final vec2 projectionConstants() + final vec2f projectionConstants() { if( this.projectionDirty ) { @@ -66,7 +67,7 @@ public: * * Returns: */ - final mat4 perspectiveMatrix() + final mat4f perspectiveMatrix() { if( this.projectionDirty ) { @@ -85,7 +86,7 @@ public: * * Returns: */ - final mat4 inversePerspectiveMatrix() + final mat4f inversePerspectiveMatrix() { if( this.projectionDirty ) { @@ -104,7 +105,7 @@ public: * * Returns: */ - final mat4 orthogonalMatrix() + final mat4f orthogonalMatrix() { if( this.projectionDirty ) { @@ -123,7 +124,7 @@ public: * * Returns: */ - final mat4 inverseOrthogonalMatrix() + final mat4f inverseOrthogonalMatrix() { if( this.projectionDirty ) { @@ -150,14 +151,14 @@ public: float cosYaw = cos( owner.transform.rotation.yaw ); float sinYaw = sin( owner.transform.rotation.yaw ); - vec3 xaxis = vec3( cosYaw, 0.0f, -sinYaw ); - vec3 yaxis = vec3( sinYaw * sinPitch, cosPitch, cosYaw * sinPitch ); - vec3 zaxis = vec3( sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw ); + vec3f xaxis = vec3f( cosYaw, 0.0f, -sinYaw ); + vec3f yaxis = vec3f( sinYaw * sinPitch, cosPitch, cosYaw * sinPitch ); + vec3f zaxis = vec3f( sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw ); _viewMatrix.clear( 0.0f ); - _viewMatrix[ 0 ] = xaxis.vector ~ -( xaxis * owner.transform.position ); - _viewMatrix[ 1 ] = yaxis.vector ~ -( yaxis * owner.transform.position ); - _viewMatrix[ 2 ] = zaxis.vector ~ -( zaxis * owner.transform.position ); + _viewMatrix[ 0 ] = xaxis.v ~ -( xaxis * owner.transform.position ); + _viewMatrix[ 1 ] = yaxis.v ~ -( yaxis * owner.transform.position ); + _viewMatrix[ 2 ] = zaxis.v ~ -( zaxis * owner.transform.position ); _viewMatrix[ 3 ] = [ 0, 0, 0, 1 ]; _inverseViewMatrix = _viewMatrix.inverse(); @@ -174,15 +175,15 @@ public: * Returns: * A right handed view matrix for the given params. */ - final static mat4 lookAt( vec3 targetPos, vec3 cameraPos, vec3 worldUp = vec3(0,1,0) ) + final static mat4f lookAt( vec3f targetPos, vec3f cameraPos, vec3f worldUp = vec3f(0,1,0) ) { - vec3 zaxis = ( cameraPos - targetPos ); + vec3f zaxis = ( cameraPos - targetPos ); zaxis.normalize; - vec3 xaxis = cross( worldUp, zaxis ); + vec3f xaxis = cross( worldUp, zaxis ); xaxis.normalize; - vec3 yaxis = cross( zaxis, xaxis ); + vec3f yaxis = cross( zaxis, xaxis ); - mat4 result = mat4.identity; + mat4f result = mat4f.identity; result[0][0] = xaxis.x; result[1][0] = xaxis.y; diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index a0c90b9c..40376eca 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -6,7 +6,9 @@ module dash.components.lights; import dash.core, dash.components, dash.graphics; import dash.utility; -import gl3n.linalg, gl3n.aabb; +import gfm.math.vector: vec3f; +import gfm.math.matrix: mat4f, Matrix; +import gfm.math.box: box3f; import derelict.opengl3.gl3; mixin( registerComponents!q{dash.components.lights} ); @@ -22,11 +24,11 @@ private: public: /// The color the light gives off. @field( "Color" ) - vec3 color; + vec3f color; /// If it should cast shadows mixin( Property!( _castShadows ) ); - this( vec3 color ) + this( vec3f color ) { this.color = color; _castShadows = false; @@ -42,7 +44,7 @@ public: @yamlComponent() class AmbientLight : Light { - this( vec3 color = vec3() ) + this( vec3f color = vec3f() ) { super( color ); } @@ -57,13 +59,13 @@ class DirectionalLight : Light private: uint _shadowMapFrameBuffer; uint _shadowMapTexture; - mat4 _projView; + mat4f _projView; int _shadowMapSize; public: /// The direction the light points in. @field( "Direction" ) - vec3 direction; + vec3f direction; /// The FrameBuffer for the shadowmap. mixin( Property!( _shadowMapFrameBuffer ) ); /// The shadow map's depth texture. @@ -71,7 +73,7 @@ public: mixin( Property!( _projView ) ); mixin( Property!( _shadowMapSize ) ); - this( vec3 color = vec3(), vec3 direction = vec3(), bool castShadows = false ) + this( vec3f color = vec3f(), vec3f direction = vec3f(), bool castShadows = false ) { this.direction = direction; super( color ); @@ -112,20 +114,20 @@ public: /** * calculates the light's projection and view matrices, and combines them */ - void calculateProjView( AABB frustum ) + void calculateProjView( box3f frustum ) { // determine the center of the frustum - vec3 center = vec3( ( frustum.min + frustum.max ).x/2.0f, + vec3f center = vec3f( ( frustum.min + frustum.max ).x/2.0f, ( frustum.min + frustum.max ).y/2.0f, ( frustum.min + frustum.max ).z/2.0f ); // determine the rotation for the viewing axis // adapted from http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors - vec3 lDirNorm = direction.normalized; - vec3 baseAxis = vec3( 0, 0, -1 ); + vec3f lDirNorm = direction.normalized; + vec3f baseAxis = vec3f( 0, 0, -1 ); float cosTheta = dot( lDirNorm, baseAxis ); float halfCosX2 = sqrt( 0.5f * (1.0f + cosTheta) ) * 2.0f; - vec3 w = cross( lDirNorm, baseAxis ); + vec3f w = cross( lDirNorm, baseAxis ); quat rotation = quat( halfCosX2/2, w.x / halfCosX2, w.y / halfCosX2, w.z / halfCosX2 ); // determine the x,y,z axes @@ -133,12 +135,12 @@ public: float sinPitch = sin( rotation.pitch ); float cosYaw = cos( rotation.yaw ); float sinYaw = sin( rotation.yaw ); - vec3 xaxis = vec3( cosYaw, 0.0f, -sinYaw ); - vec3 yaxis = vec3( sinYaw * sinPitch, cosPitch, cosYaw * sinPitch ); - vec3 zaxis = vec3( sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw ); + vec3f xaxis = vec3f( cosYaw, 0.0f, -sinYaw ); + vec3f yaxis = vec3f( sinYaw * sinPitch, cosPitch, cosYaw * sinPitch ); + vec3f zaxis = vec3f( sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw ); // build the view matrix - mat4 viewMatrix; + mat4f viewMatrix; ///* viewMatrix.clear(0.0f); viewMatrix[ 0 ] = xaxis.vector ~ -( xaxis * center ); @@ -154,7 +156,7 @@ public: frustum.max = (viewMatrix * vec4(frustum.max,1.0f)).xyz; // get mins and maxes in view space - vec3 mins, maxes; + vec3f mins, maxes; for( int i = 0; i < 3; i++ ) { if( frustum.min.vector[ i ] < frustum.max.vector[ i ] ) @@ -170,7 +172,7 @@ public: } float magicNumber = 1.5f; // literally the worst - projView = mat4.orthographic( mins.x * magicNumber, maxes.x* magicNumber, mins.y* magicNumber , maxes.y* magicNumber, maxes.z* magicNumber, mins.z* magicNumber ) * viewMatrix; + projView = mat4f.orthographic( mins.x * magicNumber, maxes.x* magicNumber, mins.y* magicNumber , maxes.y* magicNumber, maxes.z* magicNumber, mins.z* magicNumber ) * viewMatrix; } } @@ -181,7 +183,7 @@ public: class PointLight : Light { private: - mat4 _matrix; + mat4f _matrix; public: /// The area that lighting will be calculated for. @@ -191,7 +193,7 @@ public: @field( "FalloffRate" ) float falloffRate; - this( vec3 color = vec3(), float radius = 0.0f, float falloffRate = 0.0f ) + this( vec3f color = vec3f(), float radius = 0.0f, float falloffRate = 0.0f ) { this.radius = radius; this.falloffRate = falloffRate; @@ -205,15 +207,15 @@ public: * * Returns: */ - public mat4 getTransform() + public mat4f getTransform() { - _matrix = mat4.identity; + _matrix = mat4f.identity; // Scale _matrix[ 0 ][ 0 ] = radius; _matrix[ 1 ][ 1 ] = radius; _matrix[ 2 ][ 2 ] = radius; // Translate - vec3 position = owner.transform.worldPosition; + vec3f position = owner.transform.worldPosition; _matrix[ 0 ][ 3 ] = position.x; _matrix[ 1 ][ 3 ] = position.y; _matrix[ 2 ][ 3 ] = position.z; @@ -229,7 +231,7 @@ public: class SpotLight : Light { public: - this( vec3 color = vec3() ) + this( vec3f color = vec3f() ) { super( color ); } diff --git a/source/dash/components/mesh.d b/source/dash/components/mesh.d index fbf20fc7..7c560091 100644 --- a/source/dash/components/mesh.d +++ b/source/dash/components/mesh.d @@ -4,9 +4,9 @@ module dash.components.mesh; import dash.core, dash.components, dash.graphics, dash.utility; +import gfm.math.vector: vec3f; +import gfm.math.box: box3f; import derelict.opengl3.gl3, derelict.assimp3.assimp; -import gl3n.linalg, gl3n.aabb; - import std.stdio, std.stream, std.format, std.math, std.string; mixin( registerComponents!q{dash.components.mesh} ); @@ -63,7 +63,7 @@ class Mesh : Asset private: uint _glVertexArray, _numVertices, _numIndices, _glIndexBuffer, _glVertexBuffer; bool _animated; - AABB _boundingBox; + box3f _boundingBox; AssetAnimation _animationData; public: @@ -98,7 +98,7 @@ public: float[] outputData; uint[] indices; animated = false; - boundingBox = AABB.from_points( [] ); + boundingBox = box3f( vec3f( 0.0f, 0.0f, 0.0f ), vec3f( 0.0f, 0.0f, 0.0f ) ); if( mesh ) { @@ -175,7 +175,9 @@ public: outputData ~= vertWeights[ face.mIndices[ j ] ][0..4]; // Save the position in verts - boundingBox.expand( vec3( pos.x, pos.y, pos.z ) ); + vec3f newPos = vec3f( pos.x, pos.y, pos.z ); + boundingBox.min = min( boundingBox.min, newPos ); + boundingBox.max = max( boundingBox.max, newPos ); } } } @@ -217,7 +219,9 @@ public: //outputData ~= bitangent.z; // Save the position in verts - boundingBox.expand( vec3( pos.x, pos.y, pos.z ) ); + vec3f newPos = vec3f( pos.x, pos.y, pos.z ); + boundingBox.min = min( boundingBox.min, newPos ); + boundingBox.max = max( boundingBox.max, newPos ); } } } diff --git a/source/dash/components/userinterface.d b/source/dash/components/userinterface.d index a57f4520..d6cbac21 100644 --- a/source/dash/components/userinterface.d +++ b/source/dash/components/userinterface.d @@ -2,9 +2,10 @@ * Handles the creation and life cycle of UI objects and webview textures */ module dash.components.userinterface; -import dash.core; -import dash.utility.awesomium, dash.components, dash.utility, dash.graphics.graphics; -import std.string, gl3n.linalg; +import dash.core, dash.utility.awesomium, dash.components, dash.utility, dash.graphics.graphics; + +import gfm.math.matrix: mat4f; +import std.string; /** * User interface objects handle drawing/updating an AwesomiumView over the screen @@ -14,7 +15,7 @@ class UserInterface private: uint _height; uint _width; - mat4 _scaleMat; + mat4f _scaleMat; AwesomiumView _view; // TODO: Handle JS diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index e76be567..2653ebc9 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -5,7 +5,6 @@ module dash.core.gameobject; import dash.core, dash.components, dash.graphics, dash.utility; import yaml; -import gl3n.linalg, gl3n.math; import std.conv, std.variant, std.array, std.algorithm, std.typecons, std.range, std.string; @@ -437,6 +436,10 @@ public: } } +import gfm.math.vector: vec3f; +import gfm.math.quaternion: quaternionf; +import gfm.math.matrix: mat4f; + /** * Handles 3D Transformations for an object. * Stores position, rotation, and scale @@ -447,10 +450,10 @@ private struct Transform { private: GameObject _owner; - vec3 _prevPos; - quat _prevRot; - vec3 _prevScale; - mat4 _matrix; + vec3f _prevPos; + quaternionf _prevRot; + vec3f _prevScale; + mat4f _matrix; /** * Default constructor, most often created by GameObjects. @@ -461,19 +464,19 @@ private: this( GameObject obj ) { owner = obj; - position = vec3(0,0,0); - scale = vec3(1,1,1); - rotation = quat.identity; + position = vec3f(0,0,0); + scale = vec3f(1,1,1); + rotation = quaternionf.identity; } public: // these should remain public fields, properties return copies not references /// The position of the object in local space. - vec3 position; + vec3f position; /// The rotation of the object in local space. - quat rotation; + quaternionf rotation; /// The absolute scale of the object. Ignores parent scale. - vec3 scale; + vec3f scale; /// The object which this belongs to. mixin( Property!( _owner, AccessModifier.Public ) ); @@ -488,7 +491,7 @@ public: * * Returns: The object's position relative to the world origin, not the parent. */ - final @property vec3 worldPosition() @safe pure nothrow + final @property vec3f worldPosition() @safe pure nothrow { if( owner.parent is null ) return position; @@ -501,7 +504,7 @@ public: * * Returns: The object's rotation relative to the world origin, not the parent. */ - final @property quat worldRotation() @safe pure nothrow + final @property quaternionf worldRotation() @safe pure nothrow { if( owner.parent is null ) return rotation; @@ -529,7 +532,7 @@ public: * * Returns: The forward axis of the current transform. */ - final @property const vec3 forward() + final @property const vec3f forward() { return vec3( -2 * (rotation.x * rotation.z + rotation.w * rotation.y), -2 * (rotation.y * rotation.z - rotation.w * rotation.x), @@ -539,11 +542,10 @@ public: unittest { import std.stdio; - import gl3n.math; writeln( "Dash Transform forward unittest" ); auto trans = new Transform( null ); - auto forward = vec3( 0.0f, 1.0f, 0.0f ); + auto forward = vec3f( 0.0f, 1.0f, 0.0f ); trans.rotation.rotatex( 90.radians ); assert( almost_equal( trans.forward, forward ) ); } @@ -553,7 +555,7 @@ public: * * Returns: The up axis of the current transform. */ - final @property const vec3 up() + final @property const vec3f up() { return vec3( 2 * (rotation.x * rotation.y - rotation.w * rotation.z), 1 - 2 * (rotation.x * rotation.x + rotation.z * rotation.z), @@ -563,7 +565,6 @@ public: unittest { import std.stdio; - import gl3n.math; writeln( "Dash Transform up unittest" ); auto trans = new Transform( null ); @@ -578,7 +579,7 @@ public: * * Returns: The right axis of the current transform. */ - final @property const vec3 right() + final @property const vec3f right() { return vec3( 1 - 2 * (rotation.y * rotation.y + rotation.z * rotation.z), 2 * (rotation.x * rotation.y + rotation.w * rotation.z), @@ -588,7 +589,6 @@ public: unittest { import std.stdio; - import gl3n.math; writeln( "Dash Transform right unittest" ); auto trans = new Transform( null ); @@ -607,7 +607,7 @@ public: _prevRot = rotation; _prevScale = scale; - _matrix = mat4.identity; + _matrix = mat4f.identity; // Scale _matrix[ 0 ][ 0 ] = scale.x; _matrix[ 1 ][ 1 ] = scale.y; diff --git a/source/dash/core/prefabs.d b/source/dash/core/prefabs.d index ef0562d0..8e94934c 100644 --- a/source/dash/core/prefabs.d +++ b/source/dash/core/prefabs.d @@ -5,7 +5,6 @@ module dash.core.prefabs; import dash.core, dash.components, dash.utility; import yaml; -import gl3n.linalg; import std.variant; mixin( registerComponents!q{dash.core.prefabs} ); diff --git a/source/dash/graphics/adapters/adapter.d b/source/dash/graphics/adapters/adapter.d index d9c60866..4aeea77e 100644 --- a/source/dash/graphics/adapters/adapter.d +++ b/source/dash/graphics/adapters/adapter.d @@ -4,7 +4,6 @@ module dash.graphics.adapters.adapter; import dash.core, dash.components, dash.graphics, dash.utility; -import gl3n.linalg, gl3n.frustum, gl3n.math; import derelict.opengl3.gl3; import std.algorithm, std.array; diff --git a/source/dash/graphics/shaders/shaders.d b/source/dash/graphics/shaders/shaders.d index 395be929..6c3518ea 100644 --- a/source/dash/graphics/shaders/shaders.d +++ b/source/dash/graphics/shaders/shaders.d @@ -5,8 +5,9 @@ module dash.graphics.shaders.shaders; import dash.core, dash.components, dash.graphics, dash.utility; import dash.graphics.shaders.glsl; +import gfm.math.vector: vec2f, vec3f; +import gfm.math.matrix: mat4f; import derelict.opengl3.gl3; -import gl3n.linalg; import std.string, std.traits, std.algorithm; @@ -251,7 +252,7 @@ public: /** * Pass through for glUniform2f */ - final void bindUniform2f( uint uniform, const vec2 value ) + final void bindUniform2f( uint uniform, const vec2f value ) { glUniform2f( uniform, value.x, value.y ); } @@ -260,7 +261,7 @@ public: * Pass through for glUniform 3f * Passes to the shader in XYZ order */ - final void bindUniform3f( uint uniform, const vec3 value ) + final void bindUniform3f( uint uniform, const vec3f value ) { glUniform3f( uniform, value.x, value.y, value.z ); } @@ -276,7 +277,7 @@ public: /** * pass through for glUniformMatrix4fv */ - final void bindUniformMatrix4fv( uint uniform, mat4 matrix ) + final void bindUniformMatrix4fv( uint uniform, mat4f matrix ) { glUniformMatrix4fv( uniform, 1, true, matrix.value_ptr ); } @@ -284,7 +285,7 @@ public: /** * Bind an array of mat4s. */ - final void bindUniformMatrix4fvArray( uint uniform, mat4[] matrices ) + final void bindUniformMatrix4fvArray( uint uniform, mat4f[] matrices ) { float[] matptr; foreach( matrix; matrices ) @@ -352,7 +353,7 @@ public: /** * Bind a directional light after a modifying transform */ - final void bindDirectionalLight( DirectionalLight light, mat4 transform ) + final void bindDirectionalLight( DirectionalLight light, mat4f transform ) { bindUniform3f( LightDirection, ( transform * vec4( light.direction, 0.0f ) ).xyz ); bindUniform3f( LightColor, light.color ); @@ -373,7 +374,7 @@ public: /** * Bind a point light after a modifying transform */ - final void bindPointLight( PointLight light, mat4 transform ) + final void bindPointLight( PointLight light, mat4f transform ) { bindUniform3f( LightColor, light.color ); bindUniform3f( LightPosition, ( transform * vec4( light.owner.transform.worldPosition, 1.0f ) ).xyz); @@ -385,7 +386,7 @@ public: /** * Sets the eye position for lighting calculations */ - final void setEyePosition( vec3 pos ) + final void setEyePosition( vec3f pos ) { glUniform3f( EyePosition, pos.x, pos.y, pos.z ); } diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index 45d62fa4..a4b4f9ea 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -4,7 +4,8 @@ module dash.utility.input; import dash.utility, dash.core, dash.graphics; -import yaml, gl3n.linalg; +import yaml; +import gfm.math.vector: vec2ui, vec3f, vec4f; import derelict.opengl3.gl3; import std.typecons, std.conv, std.traits, std.uuid; @@ -207,7 +208,7 @@ public: * * Returns: The position of the mouse cursor. */ - vec2i mousePos() + vec2ui mousePos() { version( Windows ) { @@ -224,11 +225,11 @@ public: i.y -= GetSystemMetrics( SM_CYBORDER ); } - return vec2i( i.x, Graphics.height - i.y ); + return vec2ui( i.x, Graphics.height - i.y ); } else { - return vec2i(); + return vec2ui(); } } @@ -237,7 +238,7 @@ public: * * Returns: The position of the mouse cursor in world space. */ - vec3 mousePosView() + vec3f mousePosView() { if( !DGame.instance.activeScene ) { @@ -252,7 +253,7 @@ public: logWarning( "No camera on active scene." ); return vec3( 0.0f, 0.0f, 0.0f ); } - vec2i mouse = mousePos(); + vec2ui mouse = mousePos(); float depth; int x = mouse.x; int y = mouse.y; @@ -284,9 +285,9 @@ public: * * Returns: The position of the mouse cursor in world space. */ - vec3 mousePosWorld() + vec3f mousePosWorld() { - return (DGame.instance.activeScene.camera.inverseViewMatrix * vec4( mousePosView(), 1.0f )).xyz; + return (DGame.instance.activeScene.camera.inverseViewMatrix * vec4f( mousePosView(), 1.0f )).xyz; } /** diff --git a/source/dash/utility/tasks.d b/source/dash/utility/tasks.d index 29d19c8b..054af9c4 100644 --- a/source/dash/utility/tasks.d +++ b/source/dash/utility/tasks.d @@ -5,9 +5,6 @@ module dash.utility.tasks; import dash.utility.time, dash.utility.output; -import gl3n.util: is_vector, is_matrix, is_quaternion; -import gl3n.interpolate: lerp; - import core.time; import std.algorithm: min; import std.parallelism: parallel; @@ -59,7 +56,7 @@ unittest { import dash.utility.time; import std.stdio; - import gl3n.linalg; + import gfm.math.vector; writeln( "Dash Tasks scheduleInterpolateTask unittest 1" ); From 1128b74a1fe4379cf07d8e7b1239b217fb2d5196 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Fri, 22 Aug 2014 18:46:10 -0400 Subject: [PATCH 002/141] Ported more things [skip ci] --- dub.json | 2 +- source/dash/components/animation.d | 34 +++++++++---------- source/dash/components/camera.d | 53 +++++++++++++++--------------- source/dash/components/lights.d | 2 +- source/dash/components/mesh.d | 8 ++--- 5 files changed, 48 insertions(+), 51 deletions(-) diff --git a/dub.json b/dub.json index 78451784..4072a4a6 100644 --- a/dub.json +++ b/dub.json @@ -18,7 +18,7 @@ "derelict-fi": "~>1.0", "derelict-assimp3": "~>1.0", "dyaml": "~>0.5", - "gfm" : "~>1.1", + "gfm:math" : "~>1.1", "dlogg": "~>0.3", "x11": { "version": "~>1.0", "optional": true } }, diff --git a/source/dash/components/animation.d b/source/dash/components/animation.d index 4d306e5f..7c710e9b 100644 --- a/source/dash/components/animation.d +++ b/source/dash/components/animation.d @@ -353,7 +353,7 @@ public: } if( bonePose.rotationKeys.length > cast(int)time ) { - boneTransform = boneTransform * bonePose.rotationKeys[ cast(int)time ].to_matrix!( 4, 4 ); + boneTransform = boneTransform * cast(mat4f)bonePose.rotationKeys[ cast(int)time ]; } if( bonePose.scaleKeys.length > cast(int)time ) { @@ -425,22 +425,22 @@ public: { mat4f matrix = mat4f.identity; - matrix[0][0] = aiMatrix.a1; - matrix[0][1] = aiMatrix.a2; - matrix[0][2] = aiMatrix.a3; - matrix[0][3] = aiMatrix.a4; - matrix[1][0] = aiMatrix.b1; - matrix[1][1] = aiMatrix.b2; - matrix[1][2] = aiMatrix.b3; - matrix[1][3] = aiMatrix.b4; - matrix[2][0] = aiMatrix.c1; - matrix[2][1] = aiMatrix.c2; - matrix[2][2] = aiMatrix.c3; - matrix[2][3] = aiMatrix.c4; - matrix[3][0] = aiMatrix.d1; - matrix[3][1] = aiMatrix.d2; - matrix[3][2] = aiMatrix.d3; - matrix[3][3] = aiMatrix.d4; + matrix.c[0][0] = aiMatrix.a1; + matrix.c[0][1] = aiMatrix.a2; + matrix.c[0][2] = aiMatrix.a3; + matrix.c[0][3] = aiMatrix.a4; + matrix.c[1][0] = aiMatrix.b1; + matrix.c[1][1] = aiMatrix.b2; + matrix.c[1][2] = aiMatrix.b3; + matrix.c[1][3] = aiMatrix.b4; + matrix.c[2][0] = aiMatrix.c1; + matrix.c[2][1] = aiMatrix.c2; + matrix.c[2][2] = aiMatrix.c3; + matrix.c[2][3] = aiMatrix.c4; + matrix.c[3][0] = aiMatrix.d1; + matrix.c[3][1] = aiMatrix.d2; + matrix.c[3][2] = aiMatrix.d3; + matrix.c[3][3] = aiMatrix.d4; return matrix; } diff --git a/source/dash/components/camera.d b/source/dash/components/camera.d index 9a2c6814..aea356cf 100644 --- a/source/dash/components/camera.d +++ b/source/dash/components/camera.d @@ -4,9 +4,10 @@ module dash.components.camera; import dash.core, dash.components, dash.graphics, dash.utility; -import gfm.math.vector: vec2f, vec3f; +import gfm.math.vector: vec2f, vec3f, vec4f, cross, dot; import gfm.math.matrix: mat4f; -import std.conv; +import std.conv: to; +import std.math: sin, cos; mixin( registerComponents!q{dash.components.camera} ); @@ -155,11 +156,11 @@ public: vec3f yaxis = vec3f( sinYaw * sinPitch, cosPitch, cosYaw * sinPitch ); vec3f zaxis = vec3f( sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw ); - _viewMatrix.clear( 0.0f ); - _viewMatrix[ 0 ] = xaxis.v ~ -( xaxis * owner.transform.position ); - _viewMatrix[ 1 ] = yaxis.v ~ -( yaxis * owner.transform.position ); - _viewMatrix[ 2 ] = zaxis.v ~ -( zaxis * owner.transform.position ); - _viewMatrix[ 3 ] = [ 0, 0, 0, 1 ]; + _viewMatrix.v[] = 0.0f; + _viewMatrix.rows[ 0 ] = xaxis.v ~ -( xaxis * owner.transform.position ); + _viewMatrix.rows[ 1 ] = yaxis.v ~ -( yaxis * owner.transform.position ); + _viewMatrix.rows[ 2 ] = zaxis.v ~ -( zaxis * owner.transform.position ); + _viewMatrix.rows[ 3 ] = vec4f( 0, 0, 0, 1 ); _inverseViewMatrix = _viewMatrix.inverse(); } @@ -185,18 +186,18 @@ public: mat4f result = mat4f.identity; - result[0][0] = xaxis.x; - result[1][0] = xaxis.y; - result[2][0] = xaxis.z; - result[3][0] = -dot( xaxis, cameraPos ); - result[0][1] = yaxis.x; - result[1][1] = yaxis.y; - result[2][1] = yaxis.z; - result[3][1] = -dot( yaxis, cameraPos ); - result[0][2] = zaxis.x; - result[1][2] = zaxis.y; - result[2][2] = zaxis.z; - result[3][2] = -dot( zaxis, cameraPos ); + result.c[0][0] = xaxis.x; + result.c[1][0] = xaxis.y; + result.c[2][0] = xaxis.z; + result.c[3][0] = -dot( xaxis, cameraPos ); + result.c[0][1] = yaxis.x; + result.c[1][1] = yaxis.y; + result.c[2][1] = yaxis.z; + result.c[3][1] = -dot( yaxis, cameraPos ); + result.c[0][2] = zaxis.x; + result.c[1][2] = zaxis.y; + result.c[2][2] = zaxis.z; + result.c[3][2] = -dot( zaxis, cameraPos ); return result.transposed; } @@ -236,8 +237,8 @@ private: */ final void updatePerspective() { - _projectionConstants = vec2( ( -far * near ) / ( far - near ), far / ( far - near ) ); - _perspectiveMatrix = mat4.perspective( cast(float)Graphics.width, cast(float)Graphics.height, fov, near, far ); + _projectionConstants = vec2f( ( -far * near ) / ( far - near ), far / ( far - near ) ); + _perspectiveMatrix = mat4f.perspective( cast(float)Graphics.width, cast(float)Graphics.height, fov, near, far ); _inversePerspectiveMatrix = _perspectiveMatrix.inverse(); } @@ -246,12 +247,12 @@ private: */ final void updateOrthogonal() { - _orthogonalMatrix = mat4.identity; + _orthogonalMatrix = mat4f.identity; - _orthogonalMatrix[0][0] = 2.0f / Graphics.width; - _orthogonalMatrix[1][1] = 2.0f / Graphics.height; - _orthogonalMatrix[2][2] = -2.0f / (far - near); - _orthogonalMatrix[3][3] = 1.0f; + _orthogonalMatrix.c[0][0] = 2.0f / Graphics.width; + _orthogonalMatrix.c[1][1] = 2.0f / Graphics.height; + _orthogonalMatrix.c[2][2] = -2.0f / (far - near); + _orthogonalMatrix.c[3][3] = 1.0f; _inverseOrthogonalMatrix = _orthogonalMatrix.inverse(); } diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index 40376eca..4a8bffdd 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -6,7 +6,7 @@ module dash.components.lights; import dash.core, dash.components, dash.graphics; import dash.utility; -import gfm.math.vector: vec3f; +import gfm.math.vector: vec3f, dot; import gfm.math.matrix: mat4f, Matrix; import gfm.math.box: box3f; import derelict.opengl3.gl3; diff --git a/source/dash/components/mesh.d b/source/dash/components/mesh.d index 7c560091..32e76979 100644 --- a/source/dash/components/mesh.d +++ b/source/dash/components/mesh.d @@ -175,9 +175,7 @@ public: outputData ~= vertWeights[ face.mIndices[ j ] ][0..4]; // Save the position in verts - vec3f newPos = vec3f( pos.x, pos.y, pos.z ); - boundingBox.min = min( boundingBox.min, newPos ); - boundingBox.max = max( boundingBox.max, newPos ); + boundingBox.expand( vec3f( pos.x, pos.y, pos.z ) ); } } } @@ -219,9 +217,7 @@ public: //outputData ~= bitangent.z; // Save the position in verts - vec3f newPos = vec3f( pos.x, pos.y, pos.z ); - boundingBox.min = min( boundingBox.min, newPos ); - boundingBox.max = max( boundingBox.max, newPos ); + boundingBox.expand( vec3f( pos.x, pos.y, pos.z ) ); } } } From 1168a7e7397fc4d6771b01fd6acc801a76af90a3 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sun, 24 Aug 2014 10:53:38 -0400 Subject: [PATCH 003/141] Fixed use of mat4f in `Shaders.bindUniformMatrix4fv{Array,}` [skip ci] --- source/dash/graphics/shaders/shaders.d | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/source/dash/graphics/shaders/shaders.d b/source/dash/graphics/shaders/shaders.d index 6c3518ea..ad91f12c 100644 --- a/source/dash/graphics/shaders/shaders.d +++ b/source/dash/graphics/shaders/shaders.d @@ -279,7 +279,7 @@ public: */ final void bindUniformMatrix4fv( uint uniform, mat4f matrix ) { - glUniformMatrix4fv( uniform, 1, true, matrix.value_ptr ); + glUniformMatrix4fv( uniform, 1, false, matrix.value_ptr ); } /** @@ -290,12 +290,9 @@ public: float[] matptr; foreach( matrix; matrices ) { - for( int i = 0; i < 16; i++ ) - { - matptr ~= matrix.value_ptr()[i]; - } + matptr ~= matrix.v[]; } - glUniformMatrix4fv( uniform, cast(int)matrices.length, true, matptr.ptr ); + glUniformMatrix4fv( uniform, cast(int)matrices.length, false, matptr.ptr ); } /** From 25711714a45290e69bcfb86fb3d4ae2a074bf123 Mon Sep 17 00:00:00 2001 From: Sean Brennan Date: Sun, 31 Aug 2014 17:51:07 -0400 Subject: [PATCH 004/141] Added skeletons for audio listener and emitter, and added audio to the components package. --- source/dash/components/audio.d | 42 ++++++++++++++++++++++++++++++++ source/dash/components/package.d | 1 + 2 files changed, 43 insertions(+) create mode 100644 source/dash/components/audio.d diff --git a/source/dash/components/audio.d b/source/dash/components/audio.d new file mode 100644 index 00000000..3938d84f --- /dev/null +++ b/source/dash/components/audio.d @@ -0,0 +1,42 @@ +/** + * Defines audio related classes, such as the listener and emitter + */ +module dash.components.audio; +import dash.core.properties; +import dash.components.component; +import dash.utility.soloud; + +/** + * Listener object that hears sounds and sends them to the audio output device + * (usually attaced to the camera) + */ +class Listener : Component +{ +private: + +public: + /** + * Create a listener object + */ + this() + { + // Constructor code + } +} + +/** + * Emitter object that plays sounds that listeners can hear if they are close enough + */ +class Emitter : Component +{ +private: + +public: + /** + * Create an emmiter object + */ + this() + { + // Constructor Code + } +} diff --git a/source/dash/components/package.d b/source/dash/components/package.d index 46e4d282..d202560b 100644 --- a/source/dash/components/package.d +++ b/source/dash/components/package.d @@ -8,3 +8,4 @@ import dash.components.mesh; import dash.components.camera; import dash.components.lights; import dash.components.userinterface; +import dash.components.audio; \ No newline at end of file From dde4bc8a1b96590eb5c7650c17b66af6eaa8006b Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Wed, 3 Sep 2014 16:36:40 -0400 Subject: [PATCH 005/141] Added YAML serializer, and basic unittest --- source/dash/utility/yaml.d | 166 +++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 source/dash/utility/yaml.d diff --git a/source/dash/utility/yaml.d b/source/dash/utility/yaml.d new file mode 100644 index 00000000..dafaa96c --- /dev/null +++ b/source/dash/utility/yaml.d @@ -0,0 +1,166 @@ +module dash.utility.yaml; + +public import yaml; +import vibe.data.serialization; + + +/** + * Serializes the given value to YAML. + * + * The following types of values are supported: + * + * All entries of an array or an associative array, as well as all R/W properties and + * all public fields of a struct/class are recursively serialized using the same rules. + * + * Fields ending with an underscore will have the last underscore stripped in the + * serialized output. This makes it possible to use fields with D keywords as their name + * by simply appending an underscore. + * + * The following methods can be used to customize the serialization of structs/classes: + * + * --- + * Node toYaml() const; + * static T fromYaml( Node src ); + * + * string toString() const; + * static T fromString( string src ); + * --- + * + * The methods will have to be defined in pairs. The first pair that is implemented by + * the type will be used for serialization (i.e. toYaml overrides toString). +*/ +Node serializeToYaml( T )( T value ) +{ + return serialize!( YamlSerializer )( value ); +} + +/** +* Deserializes a YAML value into the destination variable. +* +* The same types as for serializeToYaml() are supported and handled inversely. +*/ +T deserializeYaml( T )( Node yaml ) +{ + return deserialize!( YamlSerializer, T )( yaml ); +} +/// ditto +T deserializeYaml( T, R )( R input ) if ( isInputRange!R && !is( R == Node ) ) +{ + return deserialize!( YamlStringSerializer!R, T )( input ); +} + +private struct YamlSerializer +{ +private: + private void enforceYaml( string file = __FILE__, size_t line = __LINE__ )( bool cond, lazy string message = "YAML exception" ) + { + import std.json: JSONException; + import std.exception; + enforceEx!JSONException(cond, message, file, line); + } + + enum isYamlBasicType( T ) = isNumeric!T || isBoolean!T || is( T == string ) || is( T == typeof(null) ); + + enum isSupportedValueType( T ) = isYamlBasicType!T || is( T == Node ); + + enum isYamlSerializable( T ) = is( typeof( T.init.toYaml() ) == Node ) && is( typeof( T.fromYaml( Node() ) ) == T ); + + Node m_current; + Node[] m_compositeStack; + +public: + this( Node data ) { m_current = data; } + + @disable this(this); + + // + // serialization + // + Node getSerializedResult() { return m_current; } + void beginWriteDictionary( T )() { m_compositeStack ~= Node( cast(string[])[], cast(string[])[] ); } + void endWriteDictionary( T )() { m_current = m_compositeStack[$-1]; m_compositeStack.length--; } + void beginWriteDictionaryEntry( T )(string name) {} + void endWriteDictionaryEntry( T )(string name) { m_compositeStack[$-1][name] = m_current; } + + void beginWriteArray( T )( size_t ) { m_compositeStack ~= Node( cast(string[])[] ); } + void endWriteArray( T )() { m_current = m_compositeStack[$-1]; m_compositeStack.length--; } + void beginWriteArrayEntry( T )( size_t ) {} + void endWriteArrayEntry( T )( size_t ) { m_compositeStack[$-1] ~= m_current; } + + void writeValue( T )( T value ) + { + static if( is( T == Node ) ) + m_current = value; + else static if( isYamlSerializable!T ) + m_current = value.toYaml(); + else + m_current = Node( value ); + } + + // + // deserialization + // + void readDictionary( T )( scope void delegate( string ) field_handler ) + { + enforceYaml( m_current.isMapping ); + + auto old = m_current; + foreach( string key, Node value; m_current ) + { + m_current = value; + field_handler( key ); + } + m_current = old; + } + + void readArray( T )( scope void delegate( size_t ) size_callback, scope void delegate() entry_callback ) + { + enforceYaml( m_current.isSequence ); + + auto old = m_current; + size_callback( m_current.length ); + foreach( ent; old ) + { + m_current = ent; + entry_callback(); + } + m_current = old; + } + + T readValue( T )() + { + static if( is( T == Node ) ) + return m_current; + else static if( isYamlSerializable!T ) + return T.fromYaml( m_current ); + else + return m_current.get!T(); + } + + bool tryReadNull() { return m_current.isNull; } +} + +unittest +{ + import std.stdio; + writeln( "Dash Config YamlSerializer unittest" ); + + Node str = serializeToYaml( "MyString" ); + assert( str.isScalar ); + assert( str.get!string == "MyString" ); + + struct LetsSeeWhatHappens + { + string key; + string value; + } + + Node obj = serializeToYaml( LetsSeeWhatHappens( "Key", "Value" ) ); + assert( obj.isMapping ); + assert( obj[ "key" ] == "Key" ); + assert( obj[ "value" ] == "Value" ); + + auto lswh = deserializeYaml!LetsSeeWhatHappens( obj ); + assert( lswh.key == "Key" ); + assert( lswh.value == "Value" ); +} From 311575a1a27adf25665b9d3f59a0f7e696a3d223 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Wed, 3 Sep 2014 17:07:46 -0400 Subject: [PATCH 006/141] Fixed missing imports --- source/dash/utility/yaml.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dash/utility/yaml.d b/source/dash/utility/yaml.d index dafaa96c..64ceb80e 100644 --- a/source/dash/utility/yaml.d +++ b/source/dash/utility/yaml.d @@ -2,7 +2,7 @@ module dash.utility.yaml; public import yaml; import vibe.data.serialization; - +import std.traits, std.range; /** * Serializes the given value to YAML. From c7cab3ca86dedf1c0fadddcab774d2050e7463b5 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sun, 15 Jun 2014 20:56:41 -0700 Subject: [PATCH 007/141] Added basic SDL support, Dash now runs on OSX (but immediately crashes) --- dub.json | 1 + source/dash/graphics/adapters/package.d | 1 + source/dash/graphics/adapters/sdl.d | 81 +++++++++++++++++++++++++ source/dash/graphics/graphics.d | 3 + source/dash/utility/output.d | 36 +++++------ 5 files changed, 105 insertions(+), 17 deletions(-) create mode 100644 source/dash/graphics/adapters/sdl.d diff --git a/dub.json b/dub.json index 3c19f485..454f2c2f 100644 --- a/dub.json +++ b/dub.json @@ -17,6 +17,7 @@ "derelict-gl3": "~>1.0", "derelict-fi": "~>1.0", "derelict-assimp3": "~>1.0", + "derelict-sdl2": "~>1.2", "dyaml": "~>0.5", "gl3n" : "~master", "dlogg": "~>0.3", diff --git a/source/dash/graphics/adapters/package.d b/source/dash/graphics/adapters/package.d index 607b34ca..ecd2a094 100644 --- a/source/dash/graphics/adapters/package.d +++ b/source/dash/graphics/adapters/package.d @@ -1,6 +1,7 @@ module dash.graphics.adapters; public: import dash.graphics.adapters.adapter; +import dash.graphics.adapters.sdl; version( Windows ) import dash.graphics.adapters.win32; else version( linux ) diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d new file mode 100644 index 00000000..76c3c798 --- /dev/null +++ b/source/dash/graphics/adapters/sdl.d @@ -0,0 +1,81 @@ +module dash.graphics.adapters.sdl; +import dash.core.dgame; +import dash.graphics.graphics; +import dash.graphics.adapters.adapter; +import dash.utility; + +import derelict.sdl2.sdl; +import std.string; + +class Sdl : Adapter +{ +private: + SDL_Window* window; + +public: + static @property Sdl get() { return cast(Sdl)Graphics.adapter; } + + override void initialize() + { + logInfo("Initialize begin!"); + + DerelictSDL2.load(); + loadProperties(); + + SDL_Init( SDL_INIT_VIDEO ); + + window = SDL_CreateWindow( + DGame.instance.title.toStringz(), + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + width, height, + SDL_WINDOW_OPENGL + ); + + logInfo("Initialize done!"); + } + + override void shutdown() + { + SDL_DestroyWindow( window ); + SDL_Quit(); + } + + override void resize() + { + loadProperties(); + + if( fullscreen ) + { + + } + else + { + SDL_SetWindowSize( window, width, height ); + } + } + + override void refresh() + { + resize(); + } + + override void swapBuffers() + { + SDL_GL_SwapWindow( window ); + } + + override void openWindow() + { + + } + + override void closeWindow() + { + + } + + override void messageLoop() + { + + } +} diff --git a/source/dash/graphics/graphics.d b/source/dash/graphics/graphics.d index 6c4abc85..a01ee3eb 100644 --- a/source/dash/graphics/graphics.d +++ b/source/dash/graphics/graphics.d @@ -20,6 +20,7 @@ public static: */ final void initialize() { + /* version( Windows ) { adapter = new Win32; @@ -32,6 +33,8 @@ public static: { adapter = null; } + */ + adapter = new Sdl; adapter.initialize(); adapter.initializeDeferredRendering(); diff --git a/source/dash/utility/output.d b/source/dash/utility/output.d index 2fa9896d..3620d6e0 100644 --- a/source/dash/utility/output.d +++ b/source/dash/utility/output.d @@ -23,7 +23,7 @@ enum OutputType Error, /// Messages of the level don't go to output. /// That used with minLoggingLevel and minOutputLevel - /// to suppress any message. + /// to suppress any message. Muted } @@ -86,7 +86,9 @@ void logDebug( A... )( A messages ) void bench( alias func )( lazy string name ) { import std.datetime, core.time; - logDebug( name, " time:\t\t\t", cast(Duration)benchmark!func( 1 ) ); + + auto result = cast(Duration)benchmark!func( 1 ); + logDebug( name, " time:\t\t\t", result ); } /// Global instance of logger @@ -112,12 +114,12 @@ synchronized final class GlobalLogger : StyledStrictLogger!(OutputType ) { enum DEFAULT_LOG_NAME = "dash-preinit.log"; - + this() { super(DEFAULT_LOG_NAME); } - + /** * Loads verbosity from config. */ @@ -125,54 +127,54 @@ synchronized final class GlobalLogger : StyledStrictLogger!(OutputType { debug enum section = "Debug"; else enum section = "Release"; - + enum LognameSection = "Logging.FilePath"; enum OutputVerbositySection = "Logging."~section~".OutputVerbosity"; enum LoggingVerbositySection = "Logging."~section~".LoggingVerbosity"; - + // Try to get new path for logging string newFileName; if( config.tryFind( LognameSection, newFileName ) ) { - string oldFileName = this.name; + string oldFileName = this.name; try { this.name = newFileName; - } + } catch( Exception e ) { std.stdio.writeln( "Error: Failed to reload new log location from '",oldFileName,"' to '",newFileName,"'" ); std.stdio.writeln( "Reason: ", e.msg ); debug std.stdio.writeln( e.toString ); - + // Try to rollback - scope(failure) {} + scope(failure) {} this.name = oldFileName; } } - + // Try to get output verbosity from config Verbosity outputVerbosity; if( config.tryFind( OutputVerbositySection, outputVerbosity ) ) { - minOutputLevel = cast(OutputType)( outputVerbosity ); - } + minOutputLevel = cast(OutputType)( outputVerbosity ); + } else { debug minOutputLevel = OutputType.Info; - else minOutputLevel = OutputType.Warning; + else minOutputLevel = OutputType.Warning; } - + // Try to get logging verbosity from config Verbosity loggingVerbosity; if( config.tryFind( LoggingVerbositySection, loggingVerbosity ) ) { minLoggingLevel = cast(OutputType)( loggingVerbosity ); - } + } else { debug minLoggingLevel = OutputType.Info; - else minLoggingLevel = OutputType.Warning; + else minLoggingLevel = OutputType.Warning; } } } From c8d89903091269937e5fd1140dac918d43a6b650 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Wed, 18 Jun 2014 20:36:53 -0700 Subject: [PATCH 008/141] SDL adapter now creates an OpenGL context --- source/dash/graphics/adapters/sdl.d | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 76c3c798..0e6f0f6e 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -4,6 +4,7 @@ import dash.graphics.graphics; import dash.graphics.adapters.adapter; import dash.utility; +import derelict.opengl3.gl3; import derelict.sdl2.sdl; import std.string; @@ -11,14 +12,14 @@ class Sdl : Adapter { private: SDL_Window* window; + SDL_GLContext context; public: static @property Sdl get() { return cast(Sdl)Graphics.adapter; } override void initialize() { - logInfo("Initialize begin!"); - + DerelictGL3.load(); DerelictSDL2.load(); loadProperties(); @@ -31,11 +32,14 @@ public: SDL_WINDOW_OPENGL ); - logInfo("Initialize done!"); + context = SDL_GL_CreateContext( window ); + + DerelictGL3.reload(); } override void shutdown() { + SDL_GL_DeleteContext( context ); SDL_DestroyWindow( window ); SDL_Quit(); } @@ -44,14 +48,7 @@ public: { loadProperties(); - if( fullscreen ) - { - - } - else - { - SDL_SetWindowSize( window, width, height ); - } + SDL_SetWindowSize( window, width, height ); } override void refresh() From a4e5f86a4dc10656b4d4a9ae00c1669c673bf133 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 18 Aug 2014 22:11:50 -0400 Subject: [PATCH 009/141] Started conversion to OOP wrapper [skip ci] --- dub.json | 2 +- source/dash/graphics/adapters/sdl.d | 36 +++++++++++++++++++---------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/dub.json b/dub.json index 454f2c2f..95b96af4 100644 --- a/dub.json +++ b/dub.json @@ -17,9 +17,9 @@ "derelict-gl3": "~>1.0", "derelict-fi": "~>1.0", "derelict-assimp3": "~>1.0", - "derelict-sdl2": "~>1.2", "dyaml": "~>0.5", "gl3n" : "~master", + "gfm": "~>1.1", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", "vibe-d": "==0.7.21-alpha.4", diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 0e6f0f6e..5bd6e519 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -5,50 +5,62 @@ import dash.graphics.adapters.adapter; import dash.utility; import derelict.opengl3.gl3; -import derelict.sdl2.sdl; +import gfm.sdl.sdl, gfm.sdl.window; import std.string; class Sdl : Adapter { private: - SDL_Window* window; - SDL_GLContext context; + SDL2 sdl; + SDL2Window window; + SDL2GLContext glContext; public: static @property Sdl get() { return cast(Sdl)Graphics.adapter; } override void initialize() { + // Initialize OpenGL DerelictGL3.load(); - DerelictSDL2.load(); + // Initialize SDL + sdl = new SDL2( null ); + // Load properties from config. loadProperties(); - SDL_Init( SDL_INIT_VIDEO ); + //SDL_Init( SDL_INIT_VIDEO ); - window = SDL_CreateWindow( + /*window = SDL_CreateWindow( DGame.instance.title.toStringz(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL - ); + );*/ + window = new SDL2Window( sdl, ( screenWidth - width ) / 2, ( screenHeight - height ) / 2, width, height ); - context = SDL_GL_CreateContext( window ); + window.setTitle( DGame.instance.title ); + + //context = SDL_GL_CreateContext( window ); + glContext = new SDL2GLContext( window ); + glContext.makeCurrent(); DerelictGL3.reload(); } override void shutdown() { - SDL_GL_DeleteContext( context ); + /*SDL_GL_DeleteContext( context ); SDL_DestroyWindow( window ); - SDL_Quit(); + SDL_Quit();*/ + glContext.close(); + window.close(); + sdl.close(); } override void resize() { loadProperties(); - SDL_SetWindowSize( window, width, height ); + window.setSize( width, height ); } override void refresh() @@ -58,7 +70,7 @@ public: override void swapBuffers() { - SDL_GL_SwapWindow( window ); + window.swapBuffers(); } override void openWindow() From 0e1e951f3fa4d9f304d5c98a1bac82983d0bceb7 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 23 Aug 2014 19:02:02 -0400 Subject: [PATCH 010/141] Window now opens and renders! Also, you can quit, so that's good --- .travis.yml | 3 +-- dub.json | 14 +++++++------- source/dash/graphics/adapters/sdl.d | 22 ++++++++++++++++++---- source/dash/utility/input.d | 3 +++ 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 32f5fd4c..17053135 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,7 @@ os: - linux - osx env: -# - DMD_VER=2.065.0 DUB_VER=0.9.21 - - DMD_VER=2.066.0 DUB_VER=0.9.21 + - DMD_VER=2.066.0 DUB_VER=0.9.22-rc.1 install: - bash .travis/setup_linux.sh - bash .travis/setup_osx.sh diff --git a/dub.json b/dub.json index 95b96af4..1ecff804 100644 --- a/dub.json +++ b/dub.json @@ -14,16 +14,16 @@ ], "dependencies": { - "derelict-gl3": "~>1.0", - "derelict-fi": "~>1.0", - "derelict-assimp3": "~>1.0", - "dyaml": "~>0.5", + "derelict-gl3": "~>1.0.0", + "derelict-fi": "~>1.0.0", + "derelict-assimp3": "~>1.0.0", + "dyaml": "~>0.5.0", "gl3n" : "~master", - "gfm": "~>1.1", - "dlogg": "~>0.3", "msgpack-d": "==0.9.2", "vibe-d": "==0.7.21-alpha.4", - "x11": { "version": "~>1.0", "optional": true } + "gfm": "~>1.1.10", + "dlogg": "==0.3.2", + "x11": { "version": "~>1.0.0", "optional": true } }, "targetName": "dash", diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 5bd6e519..45e7ebb2 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -4,8 +4,7 @@ import dash.graphics.graphics; import dash.graphics.adapters.adapter; import dash.utility; -import derelict.opengl3.gl3; -import gfm.sdl.sdl, gfm.sdl.window; +import derelict.opengl3.gl3, gfm.sdl2; import std.string; class Sdl : Adapter @@ -24,6 +23,11 @@ public: DerelictGL3.load(); // Initialize SDL sdl = new SDL2( null ); + + // Get screen size. + screenWidth = sdl.firstDisplaySize().x; + screenHeight = sdl.firstDisplaySize().y; + // Load properties from config. loadProperties(); @@ -35,7 +39,10 @@ public: width, height, SDL_WINDOW_OPENGL );*/ - window = new SDL2Window( sdl, ( screenWidth - width ) / 2, ( screenHeight - height ) / 2, width, height ); + window = new SDL2Window( sdl, + ( screenWidth - width ) / 2, ( screenHeight - height ) / 2, + width, height, + SDL_WINDOW_OPENGL ); window.setTitle( DGame.instance.title ); @@ -85,6 +92,13 @@ public: override void messageLoop() { - + SDL_Event event; + while( sdl.pollEvent( &event ) ) + { + // Handle the messages and stuffs. + } + + if( sdl.wasQuitRequested ) + DGame.instance.currentState = EngineState.Quit; } } diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index 45d62fa4..3c0c5a41 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -211,6 +211,9 @@ public: { version( Windows ) { + if( !Win32.get() ) + return vec2i(); + import dash.graphics; import win32.windows; POINT i; From 072c6e7ef398e9570120764224dea7ee2cee0046 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 23 Aug 2014 19:13:42 -0400 Subject: [PATCH 011/141] Added dub.selections.json to make build faster --- dub.selections.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 dub.selections.json diff --git a/dub.selections.json b/dub.selections.json new file mode 100644 index 00000000..b47d3b3c --- /dev/null +++ b/dub.selections.json @@ -0,0 +1,17 @@ +{ + "fileVersion": 1, + "versions": { + "gl3n": "~master", + "logger": "0.1.0", + "derelict-assimp3": "1.0.0", + "derelict-util": "1.0.2", + "colorize": "1.0.4", + "derelict-fi": "1.0.0", + "gfm": "1.1.10", + "derelict-sdl2": "1.2.4", + "derelict-gl3": "1.0.6", + "dyaml": "0.5.0", + "tinyendian": "0.1.0", + "dlogg": "0.3.2" + } +} From 1a2d2c3849bc15f3235f6a87862d622cbc2f2166 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 23 Aug 2014 20:18:27 -0400 Subject: [PATCH 012/141] Changed dub versions to be specific --- dub.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dub.json b/dub.json index 1ecff804..57575ce9 100644 --- a/dub.json +++ b/dub.json @@ -14,15 +14,15 @@ ], "dependencies": { - "derelict-gl3": "~>1.0.0", - "derelict-fi": "~>1.0.0", - "derelict-assimp3": "~>1.0.0", - "dyaml": "~>0.5.0", + "derelict-gl3": "==1.0.6", + "derelict-fi": "==1.0.0", + "derelict-assimp3": "==1.0.0", + "dyaml": "==0.5.0", "gl3n" : "~master", "msgpack-d": "==0.9.2", "vibe-d": "==0.7.21-alpha.4", - "gfm": "~>1.1.10", "dlogg": "==0.3.2", + "gfm:sdl2": "==1.1.10", "x11": { "version": "~>1.0.0", "optional": true } }, From 11b207d3442e51e0b50c82dd7ff75a301fd27073 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 23 Aug 2014 20:23:44 -0400 Subject: [PATCH 013/141] Fixed crashes on OSX --- source/dash/graphics/adapters/sdl.d | 4 ++++ source/dash/graphics/shaders/shaders.d | 11 ++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 45e7ebb2..145006dd 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -46,6 +46,10 @@ public: window.setTitle( DGame.instance.title ); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + //context = SDL_GL_CreateContext( window ); glContext = new SDL2GLContext( window ); glContext.makeCurrent(); diff --git a/source/dash/graphics/shaders/shaders.d b/source/dash/graphics/shaders/shaders.d index 395be929..9b18d17d 100644 --- a/source/dash/graphics/shaders/shaders.d +++ b/source/dash/graphics/shaders/shaders.d @@ -324,12 +324,17 @@ public: /** * Binds a UI's texture */ - final void bindUI( UserInterface ui ) - { + final void bindUI( UserInterface ui ) + { + // This is part of a bigger problem. But in the interest of dope screenshots... + version( OSX ) + if( !ui.view ) + return; + glUniform1i( UITexture, 0 ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, ui.view.glID ); - } + } /** * Bind an ambient light From 1af000ec4276f128aa655858b0bb1143c85b58c0 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 23 Aug 2014 20:34:35 -0400 Subject: [PATCH 014/141] Final preparations for merge * Removed Mac adapter, because it is no longer necessary. * Setup Windows to use Win32, Linux to use Linux, and everything else to use SDL. --- source/dash/graphics/graphics.d | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source/dash/graphics/graphics.d b/source/dash/graphics/graphics.d index a01ee3eb..f08c5fe1 100644 --- a/source/dash/graphics/graphics.d +++ b/source/dash/graphics/graphics.d @@ -20,7 +20,6 @@ public static: */ final void initialize() { - /* version( Windows ) { adapter = new Win32; @@ -31,10 +30,8 @@ public static: } else { - adapter = null; + adapter = new Sdl; } - */ - adapter = new Sdl; adapter.initialize(); adapter.initializeDeferredRendering(); From e5c95fa42a58714c8c6bdb7ee667393e5d5f0885 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 26 Aug 2014 08:58:04 -0400 Subject: [PATCH 015/141] Added mouse click support, added UseSDL2 version to force usage --- dub.json | 2 +- source/dash/graphics/adapters/sdl.d | 74 +++++++++++++++++++++++++++-- source/dash/graphics/graphics.d | 6 ++- 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/dub.json b/dub.json index 57575ce9..dea89884 100644 --- a/dub.json +++ b/dub.json @@ -33,7 +33,7 @@ "sourcePaths": [ "source/" ], "importPaths": [ "source/" ], - "versions": [ "VibeCustomMain" ], + "versions": [ "VibeCustomMain", "UseSDL2" ], "-ddoxFilterArgs": [ "--min-protection=Protected" ], diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 145006dd..504b83ed 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -100,9 +100,77 @@ public: while( sdl.pollEvent( &event ) ) { // Handle the messages and stuffs. + switch( event.type ) + { + // Handle mouse interactions. + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + { + Mouse.Buttons button; + final switch( event.button.button ) + { + case SDL_BUTTON_LEFT: button = Mouse.Buttons.Left; break; + case SDL_BUTTON_MIDDLE: button = Mouse.Buttons.Middle; break; + case SDL_BUTTON_RIGHT: button = Mouse.Buttons.Right; break; + case SDL_BUTTON_X1: break; + case SDL_BUTTON_X2: break; + } + + Mouse.setButtonState( button, event.button.state == SDL_PRESSED ); + break; + } + + // + case SDL_KEYDOWN: + case SDL_KEYUP: + { + break; + } + + // Handle quitting. + case SDL_QUIT: + DGame.instance.currentState = EngineState.Quit; + break; + + case SDL_APP_TERMINATING: + case SDL_APP_LOWMEMORY: + case SDL_APP_WILLENTERBACKGROUND: + case SDL_APP_DIDENTERBACKGROUND: + case SDL_APP_WILLENTERFOREGROUND: + case SDL_APP_DIDENTERFOREGROUND: + case SDL_WINDOWEVENT: + case SDL_SYSWMEVENT: + case SDL_TEXTEDITING: + case SDL_TEXTINPUT: + case SDL_MOUSEMOTION: + case SDL_MOUSEWHEEL: + case SDL_JOYAXISMOTION: + case SDL_JOYBALLMOTION: + case SDL_JOYHATMOTION: + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: + case SDL_JOYDEVICEADDED: + case SDL_JOYDEVICEREMOVED: + case SDL_CONTROLLERAXISMOTION: + case SDL_CONTROLLERBUTTONDOWN: + case SDL_CONTROLLERBUTTONUP: + case SDL_CONTROLLERDEVICEADDED: + case SDL_CONTROLLERDEVICEREMOVED: + case SDL_CONTROLLERDEVICEREMAPPED: + case SDL_FINGERDOWN: + case SDL_FINGERUP: + case SDL_FINGERMOTION: + case SDL_DOLLARGESTURE: + case SDL_DOLLARRECORD: + case SDL_MULTIGESTURE: + case SDL_CLIPBOARDUPDATE: + case SDL_DROPFILE: + case SDL_RENDER_TARGETS_RESET: + case SDL_USEREVENT: + // Unknown event type + default: + break; + } } - - if( sdl.wasQuitRequested ) - DGame.instance.currentState = EngineState.Quit; } } diff --git a/source/dash/graphics/graphics.d b/source/dash/graphics/graphics.d index f08c5fe1..6b91b911 100644 --- a/source/dash/graphics/graphics.d +++ b/source/dash/graphics/graphics.d @@ -20,7 +20,11 @@ public static: */ final void initialize() { - version( Windows ) + version( UseSDL2 ) + { + adapter = new Sdl; + } + else version( Windows ) { adapter = new Win32; } From 6286f57d13ba5a8e3d0e7f2514b8e8e378f10105 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 4 Sep 2014 14:19:20 -0400 Subject: [PATCH 016/141] Cleaned up YAML code, made utility.data pacakage --- source/dash/utility/{ => data}/yaml.d | 40 ++++++++++++++------------- 1 file changed, 21 insertions(+), 19 deletions(-) rename source/dash/utility/{ => data}/yaml.d (86%) diff --git a/source/dash/utility/yaml.d b/source/dash/utility/data/yaml.d similarity index 86% rename from source/dash/utility/yaml.d rename to source/dash/utility/data/yaml.d index 64ceb80e..0143bd4e 100644 --- a/source/dash/utility/yaml.d +++ b/source/dash/utility/data/yaml.d @@ -1,4 +1,4 @@ -module dash.utility.yaml; +module dash.utility.data.yaml; public import yaml; import vibe.data.serialization; @@ -33,12 +33,13 @@ Node serializeToYaml( T )( T value ) { return serialize!( YamlSerializer )( value ); } +static assert(is(typeof( serializeToYaml( "" ) ))); /** -* Deserializes a YAML value into the destination variable. -* -* The same types as for serializeToYaml() are supported and handled inversely. -*/ + * Deserializes a YAML value into the destination variable. + * + * The same types as for serializeToYaml() are supported and handled inversely. + */ T deserializeYaml( T )( Node yaml ) { return deserialize!( YamlSerializer, T )( yaml ); @@ -48,29 +49,22 @@ T deserializeYaml( T, R )( R input ) if ( isInputRange!R && !is( R == Node ) ) { return deserialize!( YamlStringSerializer!R, T )( input ); } +static assert(is(typeof( deserializeYaml!string( Node( "" ) ) ))); +//static assert(is(typeof( deserializeYaml!string( "" ) ))); -private struct YamlSerializer +/// Serializer for vibe.d framework. +struct YamlSerializer { private: - private void enforceYaml( string file = __FILE__, size_t line = __LINE__ )( bool cond, lazy string message = "YAML exception" ) - { - import std.json: JSONException; - import std.exception; - enforceEx!JSONException(cond, message, file, line); - } + Node m_current; + Node[] m_compositeStack; +public: enum isYamlBasicType( T ) = isNumeric!T || isBoolean!T || is( T == string ) || is( T == typeof(null) ); - enum isSupportedValueType( T ) = isYamlBasicType!T || is( T == Node ); - enum isYamlSerializable( T ) = is( typeof( T.init.toYaml() ) == Node ) && is( typeof( T.fromYaml( Node() ) ) == T ); - Node m_current; - Node[] m_compositeStack; - -public: this( Node data ) { m_current = data; } - @disable this(this); // @@ -164,3 +158,11 @@ unittest assert( lswh.key == "Key" ); assert( lswh.value == "Value" ); } + +private: +void enforceYaml( string file = __FILE__, size_t line = __LINE__ )( bool cond, lazy string message = "YAML exception" ) +{ + import std.json: JSONException; + import std.exception; + enforceEx!JSONException(cond, message, file, line); +} From 2ed3ec5092dcc64881015d3f8569fa7b60802347 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 4 Sep 2014 14:22:17 -0400 Subject: [PATCH 017/141] Deleted the selections file. More pain than it's worth --- dub.selections.json | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 dub.selections.json diff --git a/dub.selections.json b/dub.selections.json deleted file mode 100644 index b47d3b3c..00000000 --- a/dub.selections.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "fileVersion": 1, - "versions": { - "gl3n": "~master", - "logger": "0.1.0", - "derelict-assimp3": "1.0.0", - "derelict-util": "1.0.2", - "colorize": "1.0.4", - "derelict-fi": "1.0.0", - "gfm": "1.1.10", - "derelict-sdl2": "1.2.4", - "derelict-gl3": "1.0.6", - "dyaml": "0.5.0", - "tinyendian": "0.1.0", - "dlogg": "0.3.2" - } -} From af7142204f6e83f97e9b4e7ea05242aa56da181d Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 4 Sep 2014 16:00:49 -0400 Subject: [PATCH 018/141] Started writing serialization framework --- source/dash/components/component.d | 27 ++++++ source/dash/core/gameobject.d | 111 ++++++++++++++++++++++- source/dash/utility/data/package.d | 4 + source/dash/utility/data/serialization.d | 6 ++ source/dash/utility/package.d | 1 + 5 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 source/dash/utility/data/package.d create mode 100644 source/dash/utility/data/serialization.d diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 0bde69f7..72adcf75 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -42,6 +42,33 @@ public: void draw() { } /// Called on shutdown. void shutdown() { } + + // For serialization. + import vibe.data.bson, vibe.data.json, dash.utility.data.yaml; + Bson toBson() + { + return Bson(); + } + static Component fromBson( Bson bson ) + { + return null; + } + Json toJson() + { + return Json(); + } + static Component fromJson( Json json ) + { + return null; + } + Node toYaml() + { + return Node( YAMLNull() ); + } + static Component fromYaml( Node node ) + { + return null; + } } /** diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index e76be567..e7eb8bcf 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -49,7 +49,6 @@ struct ObjectStateFlags final class GameObject { private: - Transform _transform; GameObject _parent; GameObject[] _children; Component[TypeInfo] componentList; @@ -68,8 +67,37 @@ package: Scene scene; public: + /** + * The struct that will be directly deserialized from the ddl. + */ + static struct Description + { + /// The name of the object. + @rename( "Name" ) + string name; + + /// The name of the prefab to create from. Do you use with $(D prefab). + @rename( "InstanceOf" ) @optional + string prefabName; + + /// The Prefab to create from. + @ignore + Prefab prefab; + + /// The transform of the object. + @rename( "Transform" ) @optional + Transform.Description transform; + + /// Children of this object. + @rename( "Children" ) @optional + Description[] children; + + //@rename( "Components" ) @optional + Component[] component; + } + /// The current transform of the object. - mixin( RefGetter!_transform ); + Transform transform; /// The light attached to this object. @property void light( Light v ) { addComponent( v ); } /// ditto @@ -191,12 +219,64 @@ public: return obj; } + /** + * Create a GameObject from a description object. + * + * Params: + * desc = The description to pull info from. + * + * Returns: + * A new game object with components and info pulled from yaml. + */ + static GameObject create( Description desc ) + { + GameObject obj; + + if( desc.prefabName ) + { + obj = Prefabs[ desc.prefabName ].createInstance(); + } + else if( desc.prefab ) + { + obj = desc.prefab.createInstance(); + } + else + { + obj = new GameObject; + } + + // Set object name + obj.name = desc.name; + + // Init transform + obj.transform = desc.transform; + + if( desc.children.length > 0 ) + { + foreach( child; desc.children ) + { + obj.addChild( GameObject.create( child ) ); + } + } + + // Init components + /*foreach( string key, Node componentNode; yamlObj ) + { + + }*/ + + foreach( comp; obj.componentList ) + comp.initialize(); + + return obj; + } + /** * Creates basic GameObject with transform and connection to transform's emitter. */ this() { - _transform = Transform( this ); + transform = Transform( this ); // Create default material material = new Material( "default" ); @@ -452,6 +532,13 @@ private: vec3 _prevScale; mat4 _matrix; + void opAssign( Description desc ) + { + position = desc.position; + rotation = quat( desc.rotation.w, desc.rotation.xyz ); + scale = desc.scale; + } + /** * Default constructor, most often created by GameObjects. * @@ -467,6 +554,24 @@ private: } public: + /** + * The struct that will be directly deserialized from the ddl. + */ + static struct Description + { + /// The position of the object. + @rename( "Position" ) @asArray @optional + vec3 position; + + /// The position of the object. + @rename( "Rotation" ) @asArray @optional + vec4 rotation; + + /// The position of the object. + @rename( "Scale" ) @asArray @optional + vec3 scale; + } + // these should remain public fields, properties return copies not references /// The position of the object in local space. vec3 position; diff --git a/source/dash/utility/data/package.d b/source/dash/utility/data/package.d new file mode 100644 index 00000000..0d7bfb9d --- /dev/null +++ b/source/dash/utility/data/package.d @@ -0,0 +1,4 @@ +module dash.utility.data; +public: +import dash.utility.data.yaml; +import dash.utility.data.serialization; diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d new file mode 100644 index 00000000..3ee12488 --- /dev/null +++ b/source/dash/utility/data/serialization.d @@ -0,0 +1,6 @@ +module dash.utility.data.serialization; + +// Serialization attributes +public import vibe.data.serialization: asArray, byName, ignore, name, optional; +/// Rename a field in the ddl. +alias rename = name; diff --git a/source/dash/utility/package.d b/source/dash/utility/package.d index 28da8d71..a46a4705 100644 --- a/source/dash/utility/package.d +++ b/source/dash/utility/package.d @@ -1,5 +1,6 @@ module dash.utility; public: +import dash.utility.data; import dash.utility.config; import dash.utility.input; import dash.utility.output; From f50f405551f5198601daeaf188825bda6c6392f7 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 6 Sep 2014 15:36:02 -0400 Subject: [PATCH 019/141] Started writing some metacode for the serializers [skip ci] --- source/dash/components/camera.d | 2 +- source/dash/components/component.d | 366 ++++++++--------------------- source/dash/components/lights.d | 2 +- source/dash/components/material.d | 2 +- source/dash/components/mesh.d | 2 +- source/dash/core/gameobject.d | 15 +- source/dash/core/prefabs.d | 2 +- source/dash/utility/data/yaml.d | 3 + 8 files changed, 115 insertions(+), 279 deletions(-) diff --git a/source/dash/components/camera.d b/source/dash/components/camera.d index c49a20d9..da5e3a89 100644 --- a/source/dash/components/camera.d +++ b/source/dash/components/camera.d @@ -7,7 +7,7 @@ import dash.core, dash.components, dash.graphics, dash.utility; import gl3n.linalg; import std.conv; -mixin( registerComponents!q{dash.components.camera} ); +mixin( registerComponents!() ); /** * Camera manages a view and projection matrix. diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 72adcf75..d94ca0b0 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -5,13 +5,16 @@ module dash.components.component; import dash.core, dash.components, dash.graphics, dash.utility; import yaml; -import std.array, std.string, std.traits, std.conv; +import std.array, std.string, std.traits, std.conv, std.typecons; /// Tests if a type can be created from yaml. enum isYamlObject(T) = __traits( compiles, { T obj; obj.yaml = Node( YAMLNull() ); } ); +enum serializationFormats = tuple( "Json", "Bson"/*, "Yaml"*/ ); abstract class YamlObject { +public: + @ignore Node yaml; /// Called when refreshing an object. @@ -30,6 +33,7 @@ abstract class Component : YamlObject { public: /// The node that defined the component. + @ignore Node yaml; /// The GameObject that owns this component. GameObject owner; @@ -45,31 +49,101 @@ public: // For serialization. import vibe.data.bson, vibe.data.json, dash.utility.data.yaml; - Bson toBson() - { - return Bson(); - } - static Component fromBson( Bson bson ) - { - return null; - } - Json toJson() - { - return Json(); - } - static Component fromJson( Json json ) - { - return null; - } - Node toYaml() - { - return Node( YAMLNull() ); - } - static Component fromYaml( Node node ) + mixin( { + import std.string; + string serializers = ""; + + foreach( type; serializationFormats ) + { + serializers ~= q{ + static $type delegate( Component )[ClassInfo] $typeSerializers; + $type to$type() const + { + return $typeSerializers[typeid(this)]( cast()this ); + } + static Component from$type( $type d ) + { + return null; + } + }.replace( "$type", type ); + } + + return serializers; + } () ); + +private: + enum serializers = { + import std.string; + string serializers = ""; + + foreach( type; serializationFormats ) + { + serializers ~= q{ + static $type delegate( Component )[ClassInfo] $typeSerializers; + $type to$type() const + { + return $typeSerializers[typeid(this)]( cast()this ); + } + static Component from$type( $type d ) + { + return null; + } + }.replace( "$type", type ); + } + + return serializers; + } (); +} + +/** +* To be placed at the top of any module defining YamlComponents. +* +* Params: +* modName = The name of the module to register. +*/ +enum registerComponents( string modName = __MODULE__ ) = q{ + static this() { - return null; + // Declarations + import vibe.data.bson, vibe.data.json, dash.utility.data.yaml; + import mod = $modName; + alias helper( alias T ) = T; + + // Foreach definition in the module (classes, structs, functions, etc.) + foreach( memberName; __traits( allMembers, mod ) ) + { + // Alais to the member + alias member = helper!( __traits( getMember, mod, memberName ) ); + + // If member is a class that extends Componen + static if( is( member == class ) && is( member : Component ) && !__traits( isAbstractClass, member ) ) + { + enum generateSerializers = { + import std.string: replace; + string generator = ""; + + foreach( type; serializationFormats ) + { + generator ~= q{ + Component.$typeSerializers[typeid(member)] = ( Component c ) + { + // TODO: Shouldn't not compile + static if( __traits( compiles, serializeTo$type( cast(member)c ) ) ) + return serializeTo$type( cast(member)c ); + else + return $type(); + }; + }.replace( "$type", type ); + } + + return generator; + } (); + + mixin( generateSerializers ); + } + } } -} +}.replace( "$modName", modName ); /** * Meant to be added to components that can be set from YAML. @@ -134,250 +208,6 @@ Component delegate( Node )[string] createYamlComponent; /// Refresh any object defined from yaml. The key is the typeid of the type. void delegate( YamlObject, Node )[TypeInfo] refreshYamlObject; -/** - * To be placed at the top of any module defining YamlComponents. - * - * Params: - * modName = The name of the module to register. - */ -enum registerComponents( string modName ) = q{ - static this() - { - import yaml; - mixin( "import mod = $modName;" ); - - // Foreach definition in the module (classes, structs, functions, etc.) - foreach( member; __traits( allMembers, mod ) ) - { - // If the we can get the attributes of the definition - static if( __traits( compiles, __traits( getAttributes, __traits( getMember, mod, member ) ) ) ) - { - // Iterate over each attribute and try to find a YamlEntry - foreach( attrib; __traits( getAttributes, __traits( getMember, mod, member ) ) ) - { - // If we find one, process it and go to next definition. - static if( is( typeof(attrib) == YamlUDA ) ) - { - if( attrib.type == YamlType.Component ) - { - /*static if( !is( typeof( mixin( member ) ) : Component ) ) - logError( "@yamlComponent() must be placed on a class which extends Component. ", member, " fails this check." );*/ - - // If the type has a loader, register it as the create function. - if( attrib.loader ) - { - typeLoaders[ typeid(mixin( member )) ] = attrib.loader; - createYamlComponent[ member ] = ( node ) { if( node.isScalar ) return cast(Component)attrib.loader( node.get!string ); else { logInfo( "Invalid node for ", member ); return null; } }; - } - } - else if( attrib.type == YamlType.Object ) - { - /*static if( !is( typeof( mixin( member ) ) : YamlObject ) && !isYamlObject!( mixin( member ) ) ) - logError( "@yamlObject() must be placed on a class which extends YamlObject or passes isYamlObject. ", member, " fails this check." );*/ - } - else - { - logError( "@field on a type is illegal." ); - } - - registerYamlObjects!( mixin( member ) )( attrib.name.length == 0 ? member : attrib.name, attrib.type ); - } - } - } - } - } -}.replace( "$modName", modName ); - -/// For internal use only. -LoaderFunction[TypeInfo] typeLoaders; - -/// DON'T MIND ME -void registerYamlObjects( Base )( string yamlName, YamlType type ) if( is( Base : YamlObject ) ) -{ - // If no name specified, use class name. - if( yamlName == "" ) - yamlName = Base.stringof.split( "." )[ $-1 ]; - - refreshYamlObject[ typeid(Base) ] = ( comp, n ) - { - auto b = cast(Base)comp; - - // If node contains reference to this type, grab that as root instead. - Node node; - if( !n.tryFind( yamlName, node ) ) - node = n; - - // Get all members of the class (including inherited ones). - foreach( memberName; __traits( allMembers, Base ) ) - { - // If the attributes are gettable. - static if( __traits( compiles, __traits( getAttributes, __traits( getMember, Base, memberName ) ) ) ) - { - // Iterate over each attribute on the member. - foreach( attrib; __traits( getAttributes, __traits( getMember, Base, memberName ) ) ) - { - // If it is marked as a field, process. - static if( is( typeof(attrib) == YamlUDA ) ) - { - if( attrib.type == YamlType.Field ) - { - string yamlFieldName; - // If a name is not specified, use the name of the member. - if( attrib.name == "" ) - yamlFieldName = memberName; - else - yamlFieldName = attrib.name; - - // If there's an loader on the field, use that. - if( attrib.loader ) - { - static if( is( typeof( mixin( "b." ~ memberName ) ) : YamlObject ) ) - { - string newStringVal; - if( node.tryFind( yamlFieldName, newStringVal ) ) - { - auto newVal = cast(typeof(mixin( "b." ~ memberName )))attrib.loader( newStringVal ); - // If value hasn't changed, or if it was changed through code, ignore. - string oldStringVal; - if( b.yaml.tryFind( yamlFieldName, oldStringVal ) ) - { - auto oldVal = cast(typeof(mixin( "b." ~ memberName )))attrib.loader( oldStringVal ); - if( oldStringVal == newStringVal || oldVal != mixin( "b." ~ memberName ) ) - continue; - } - - mixin( "b." ~ memberName ) = newVal; - } - else - { - logDebug( "Failed using attrib loader for ", yamlFieldName ); - } - } - } - // If the type of the field has a loader, use that. - else if( typeid( mixin( "b." ~ memberName ) ) in typeLoaders ) - { - static if( is( typeof( mixin( "b." ~ memberName ) ) : YamlObject ) ) - { - auto loader = typeid( mixin( "b." ~ memberName ) ) in typeLoaders; - - string newStringVal; - if( node.tryFind( yamlFieldName, newStringVal ) ) - { - auto newVal = cast(typeof(mixin( "b." ~ memberName )))( *loader )( newStringVal ); - // If value hasn't changed, ignore. - string oldStringVal; - if( b.yaml.tryFind( yamlFieldName, oldStringVal ) ) - { - auto oldVal = cast(typeof(mixin( "b." ~ memberName )))( *loader )( oldStringVal ); - if( oldStringVal == newStringVal || oldVal != mixin( "b." ~ memberName ) ) - continue; - } - - mixin( "b." ~ memberName ) = newVal; - } - else - { - logDebug( "Failed using typeloader for ", yamlFieldName ); - } - } - } - // Else just try to parse the yaml. - else - { - typeof( __traits( getMember, b, memberName ) ) val; - - static if( is( typeof( __traits( getMember, b, memberName ) ) == enum ) ) - { - string valName; - bool result = node.tryFind( yamlFieldName, valName ); - - if( result ) - val = valName.to!( typeof( mixin( "b." ~ memberName ) ) ); - } - else - { - bool result = node.tryFind( yamlFieldName, val ); - } - - if( result ) - { - // If value hasn't changed, ignore. - typeof( __traits( getMember, b, memberName ) ) oldVal; - if( b.yaml.tryFind( yamlFieldName, oldVal ) ) - { - if( oldVal == val || oldVal != mixin( "b." ~ memberName ) ) - continue; - } - - mixin( "b." ~ memberName ) = val; - } - else - { - logDebug( "Failed creating ", yamlFieldName, " of type ", typeof( mixin( "b." ~ memberName ) ).stringof ); - logDebug( "Typeloaders: ", typeLoaders ); - } - } - } - - break; - } - // If the user forgot (), remind them. - else static if( is( typeof(attrib == typeof(field) ) ) ) - { - static assert( false, "Don't forget () after field on " ~ memberName ); - } - } - } - } - - // Set the yaml property so the class has access to the yaml that created it. - b.yaml = node; - }; - - // Make sure the type is instantiable - static if( __traits( compiles, new Base ) ) - { - static if( is( Base : Component ) ) - { - if( type == YamlType.Component ) - { - if( auto loader = typeid( Base ) in typeLoaders ) - { - createYamlComponent[ yamlName ] = ( node ) - { - return cast(Component)( *loader )( node.get!string ); - }; - } - else - { - createYamlComponent[ yamlName ] = ( node ) - { - // Create an instance of the class to assign things to. - Component b = new Base; - - refreshYamlObject[ typeid(Base) ]( b, node ); - - return b; - }; - } - } - } - if( type == YamlType.Object ) - { - createYamlObject[ yamlName ] = ( node ) - { - // Create an instance of the class to assign things to. - YamlObject b = new Base; - - refreshYamlObject[ typeid(Base) ]( b, node ); - - return b; - }; - } - } -} - enum YamlType { Object, Component, Field } private alias LoaderFunction = YamlObject delegate( string ); diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index a0c90b9c..d4eba553 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -9,7 +9,7 @@ import dash.utility; import gl3n.linalg, gl3n.aabb; import derelict.opengl3.gl3; -mixin( registerComponents!q{dash.components.lights} ); +mixin( registerComponents!() ); /** * Base class for lights. diff --git a/source/dash/components/material.d b/source/dash/components/material.d index 690cb73b..b77daba5 100644 --- a/source/dash/components/material.d +++ b/source/dash/components/material.d @@ -8,7 +8,7 @@ import yaml; import derelict.opengl3.gl3, derelict.freeimage.freeimage; import std.variant, std.conv, std.string; -mixin( registerComponents!q{dash.components.material} ); +mixin( registerComponents!() ); /** * A collection of textures that serve different purposes in the rendering pipeline. diff --git a/source/dash/components/mesh.d b/source/dash/components/mesh.d index fbf20fc7..925e1f69 100644 --- a/source/dash/components/mesh.d +++ b/source/dash/components/mesh.d @@ -9,7 +9,7 @@ import gl3n.linalg, gl3n.aabb; import std.stdio, std.stream, std.format, std.math, std.string; -mixin( registerComponents!q{dash.components.mesh} ); +mixin( registerComponents!() ); /*Mesh getMesh( string name ) { diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index e7eb8bcf..fbc332b2 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -92,8 +92,8 @@ public: @rename( "Children" ) @optional Description[] children; - //@rename( "Components" ) @optional - Component[] component; + @rename( "Components" ) @optional + Component[] components; } /// The current transform of the object. @@ -232,6 +232,7 @@ public: { GameObject obj; + // Create the object if( desc.prefabName ) { obj = Prefabs[ desc.prefabName ].createInstance(); @@ -251,6 +252,7 @@ public: // Init transform obj.transform = desc.transform; + // Create children if( desc.children.length > 0 ) { foreach( child; desc.children ) @@ -259,12 +261,13 @@ public: } } - // Init components - /*foreach( string key, Node componentNode; yamlObj ) + // Add components + foreach( component; desc.components ) { + obj.addComponent( component ); + } - }*/ - + // Init components foreach( comp; obj.componentList ) comp.initialize(); diff --git a/source/dash/core/prefabs.d b/source/dash/core/prefabs.d index ef0562d0..d4afe5e6 100644 --- a/source/dash/core/prefabs.d +++ b/source/dash/core/prefabs.d @@ -8,7 +8,7 @@ import yaml; import gl3n.linalg; import std.variant; -mixin( registerComponents!q{dash.core.prefabs} ); +mixin( registerComponents!() ); /** * Prefabs manages prefabs and allows access to them. diff --git a/source/dash/utility/data/yaml.d b/source/dash/utility/data/yaml.d index 0143bd4e..e9d122ca 100644 --- a/source/dash/utility/data/yaml.d +++ b/source/dash/utility/data/yaml.d @@ -4,6 +4,9 @@ public import yaml; import vibe.data.serialization; import std.traits, std.range; +/// Convience alias +alias Yaml = Node; + /** * Serializes the given value to YAML. * From 293872c84aaea3a59cc2f628341663c259ee7c8a Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sun, 7 Sep 2014 13:17:33 -0400 Subject: [PATCH 020/141] Fixed compiler crash, simplified code --- source/dash/components/component.d | 86 ++++++++---------------------- 1 file changed, 22 insertions(+), 64 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index d94ca0b0..4042fc1a 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -5,7 +5,7 @@ module dash.components.component; import dash.core, dash.components, dash.graphics, dash.utility; import yaml; -import std.array, std.string, std.traits, std.conv, std.typecons; +import std.algorithm, std.array, std.string, std.traits, std.conv, std.typecons; /// Tests if a type can be created from yaml. enum isYamlObject(T) = __traits( compiles, { T obj; obj.yaml = Node( YAMLNull() ); } ); @@ -50,49 +50,18 @@ public: // For serialization. import vibe.data.bson, vibe.data.json, dash.utility.data.yaml; mixin( { - import std.string; - string serializers = ""; - - foreach( type; serializationFormats ) - { - serializers ~= q{ - static $type delegate( Component )[ClassInfo] $typeSerializers; - $type to$type() const - { - return $typeSerializers[typeid(this)]( cast()this ); - } - static Component from$type( $type d ) - { - return null; - } - }.replace( "$type", type ); - } - - return serializers; + return "".reduce!( ( working, type ) => working ~ q{ + static $type delegate( Component )[ ClassInfo ] $typeSerializers; + $type to$type() const + { + return $typeSerializers[ typeid(this) ]( cast()this ); + } + static Component from$type( $type d ) + { + return null; + } + }.replace( "$type", type ) )( serializationFormats ); } () ); - -private: - enum serializers = { - import std.string; - string serializers = ""; - - foreach( type; serializationFormats ) - { - serializers ~= q{ - static $type delegate( Component )[ClassInfo] $typeSerializers; - $type to$type() const - { - return $typeSerializers[typeid(this)]( cast()this ); - } - static Component from$type( $type d ) - { - return null; - } - }.replace( "$type", type ); - } - - return serializers; - } (); } /** @@ -118,28 +87,17 @@ enum registerComponents( string modName = __MODULE__ ) = q{ // If member is a class that extends Componen static if( is( member == class ) && is( member : Component ) && !__traits( isAbstractClass, member ) ) { - enum generateSerializers = { + mixin( { import std.string: replace; - string generator = ""; - - foreach( type; serializationFormats ) - { - generator ~= q{ - Component.$typeSerializers[typeid(member)] = ( Component c ) - { - // TODO: Shouldn't not compile - static if( __traits( compiles, serializeTo$type( cast(member)c ) ) ) - return serializeTo$type( cast(member)c ); - else - return $type(); - }; - }.replace( "$type", type ); - } - - return generator; - } (); - - mixin( generateSerializers ); + import std.algorithm: reduce; + + return "".reduce!( ( working, type ) => working ~ q{ + Component.$typeSerializers[ typeid(member) ] = ( Component c ) + { + return $type(); + }; + }.replace( "$type", type ) )( serializationFormats ); + } () ); } } } From 18dc056b8488d485e1b016c8fb9a7967af648271 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sun, 7 Sep 2014 18:09:48 -0400 Subject: [PATCH 021/141] Implemented componentMetadata template [skip ci] --- source/dash/components/component.d | 234 +++++++++++++++++++++++++---- 1 file changed, 203 insertions(+), 31 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 4042fc1a..0701b641 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -4,12 +4,20 @@ module dash.components.component; import dash.core, dash.components, dash.graphics, dash.utility; -import yaml; +import vibe.data.bson, vibe.data.json, dash.utility.data.yaml; import std.algorithm, std.array, std.string, std.traits, std.conv, std.typecons; /// Tests if a type can be created from yaml. enum isYamlObject(T) = __traits( compiles, { T obj; obj.yaml = Node( YAMLNull() ); } ); +enum isComponent(alias T) = is( T == class ) && is( T : Component ) && !__traits( isAbstractClass, T ); enum serializationFormats = tuple( "Json", "Bson"/*, "Yaml"*/ ); +private enum perSerializationFormat( string code ) = "".reduce!( ( working, type ) => working ~ code.replace( "$type", type ) )( serializationFormats ); +alias helper( alias T ) = T; + +auto append( Begin, End )( Begin begin, End end ) +{ + return tuple( begin.expand, end ); +} abstract class YamlObject { @@ -48,35 +56,66 @@ public: void shutdown() { } // For serialization. - import vibe.data.bson, vibe.data.json, dash.utility.data.yaml; - mixin( { - return "".reduce!( ( working, type ) => working ~ q{ - static $type delegate( Component )[ ClassInfo ] $typeSerializers; - $type to$type() const + mixin( perSerializationFormat!q{ + static $type delegate( Component )[ ClassInfo ] $typeSerializers; + static Component delegate( $type )[ string ] $typeDeserializers; + $type to$type() const + { + return $typeSerializers[ typeid(this) ]( cast()this ); + } + static Component from$type( $type d ) + { + if( auto type = "Type" in d ) { - return $typeSerializers[ typeid(this) ]( cast()this ); + return $typeDeserializers[ type.get!string ]( d ); } - static Component from$type( $type d ) + else { + logWarning( "Component doesn't have \"Type\" field." ); return null; } - }.replace( "$type", type ) )( serializationFormats ); - } () ); + } + } ); + + const(ComponentDescription)* description() @property + { + if( auto desc = typeid(this) in descriptions ) + return desc; + else + assert( false, "ComponentDescription not found for type " ~ typeid(this).name ); + } + +private: + static const(ComponentDescription)[ ClassInfo ] descriptions; +} + +/// The description for the component +class ComponentDescription +{ +public: + static struct Field + { + public: + string name; + string typeName; + string attributes; + string mod; + } + + Field[] fields; } /** -* To be placed at the top of any module defining YamlComponents. -* -* Params: -* modName = The name of the module to register. -*/ + * To be placed at the top of any module defining YamlComponents. + * + * Params: + * modName = The name of the module to register. + */ enum registerComponents( string modName = __MODULE__ ) = q{ static this() { // Declarations - import vibe.data.bson, vibe.data.json, dash.utility.data.yaml; import mod = $modName; - alias helper( alias T ) = T; // Foreach definition in the module (classes, structs, functions, etc.) foreach( memberName; __traits( allMembers, mod ) ) @@ -85,24 +124,153 @@ enum registerComponents( string modName = __MODULE__ ) = q{ alias member = helper!( __traits( getMember, mod, memberName ) ); // If member is a class that extends Componen - static if( is( member == class ) && is( member : Component ) && !__traits( isAbstractClass, member ) ) + static if( isComponent!member ) { - mixin( { - import std.string: replace; - import std.algorithm: reduce; - - return "".reduce!( ( working, type ) => working ~ q{ - Component.$typeSerializers[ typeid(member) ] = ( Component c ) - { - return $type(); - }; - }.replace( "$type", type ) )( serializationFormats ); - } () ); + componentMetadata!( member ).register(); } } } }.replace( "$modName", modName ); +/// Registers a type as a component +template componentMetadata( T ) if( isComponent!T ) +{ +public: + // Runtime function, registers serializers + void register() + { + // Generate serializers for the type + mixin( perSerializationFormat!q{ + Component.$typeSerializers[ typeid(T) ] = ( Component c ) + { + return $type(); + //return serializeTo$type( Description( cast(T)c ) ); + }; + + Component.$typeDeserializers[ typeid(T).name ] = ( $type node ) + { + return null; + //return deserialize$type!Description( node ).createInstance(); + }; + } ); + + Component.descriptions[ typeid(T) ] = description; + } + + // Generate actual struct + struct Description + { + mixin( descContents ); + + enum fields = getFields(); + + // Create a description from a component. + this( T theThing ) + { + this(); + + foreach( field; __traits( allMembers, T ) ) + { + static if( fields.map!(f => f.name).canFind( field ) ) + { + mixin( field ~ " = theThing." ~ field ~ ";\n" ); + } + } + } + + // Create a component from a description. + T createInstance() const + { + T comp = new T; + foreach( field; __traits( allMembers, T ) ) + { + static if( fields.map!(f => f.name).canFind( field ) ) + { + mixin( "comp." ~ field ~ " = this." ~ field ~ ";\n" ); + } + } + return comp; + } + } + + // Generate description + enum description = Description(); + +private: + // Get a list of fields on the type + ComponentDescription.Field[] getFields( size_t idx = 0 )( ComponentDescription.Field[] fields = [] ) + { + static if( idx == __traits( allMembers, T ).length ) + { + return fields; + } + else + { + enum memberName = helper!( __traits( allMembers, T )[ idx ] ); + + // Make sure member is accessable and that we care about it + static if( !memberName.among( "this", "~this", __traits( allMembers, Component ) ) && + is( typeof( helper!( __traits( getMember, T, memberName ) ) ) ) ) + { + alias member = helper!( __traits( getMember, T, memberName ) ); + + // Process variables + static if( !isSomeFunction!member ) + { + import std.conv; + alias attributes = helper!( __traits( getAttributes, member ) ); + + // Get string form of attributes + static if( is( attributes.length ) ) + enum string attributesStr = attributes.array.map!( attr => attr.to!string ).join( ", " ).to!string; + else + enum string attributesStr = attributes.to!string; + + // Get required module import name + static if( __traits( compiles, moduleName!( typeof( member ) ) ) ) + enum modName = moduleName!(typeof(member)); + else + enum modName = null; + + // Generate field + enum newField = ComponentDescription.Field( memberName, fullyQualifiedName!(typeof(member)), attributesStr, modName ); + return getFields!( idx + 1 )( fields ~ newField ); + } + else + { + return getFields!( idx + 1 )( fields ); + } + } + else + { + return getFields!( idx + 1 )( fields ); + } + } + } + + // Generate static description struct for deserializing + enum descContents = { + return reduce!( ( working, field ) + { + string result = working; + + // Append required import for variable type + if( field.mod ) + result ~= "import " ~ field.mod ~ ";\n"; + + // Append variable attributes + if( field.attributes.length > 0 ) + result ~= "@(" ~ field.attributes ~ ") "; + + // Append variable declaration + result ~= field.typeName ~ " " ~ field.name ~ ";\n"; + + return result; + } + )( "", description.fields ); + } (); +} + /** * Meant to be added to components that can be set from YAML. * Example: @@ -154,10 +322,14 @@ auto yamlComponent( string loader = "null" )( string name = "" ) * } * --- */ -auto field( string loader = "null" )( string name = "" ) +/* +auto field( string name = "" ) { - return YamlUDA( YamlType.Field, name, mixin( loader ) ); + return YamlUDA( YamlType.Field, name, null ); } +*/ +deprecated( "Use rename instead." ) +alias field = rename; /// Used to create objects from yaml. The key is the YAML name of the type. YamlObject delegate( Node )[string] createYamlObject; From c1c98d1118cc091f6676ec35ea1db127ccba212b Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sun, 7 Sep 2014 19:41:43 -0400 Subject: [PATCH 022/141] Flyweightification --- source/dash/components/animation.d | 8 +-- source/dash/components/assets.d | 74 +++++++++++++++++++------- source/dash/components/component.d | 8 +-- source/dash/components/material.d | 55 ++++++++++++++++--- source/dash/components/mesh.d | 10 ++-- source/dash/components/userinterface.d | 3 +- source/dash/core/gameobject.d | 2 +- 7 files changed, 123 insertions(+), 37 deletions(-) diff --git a/source/dash/components/animation.d b/source/dash/components/animation.d index a7fae326..60f7c797 100644 --- a/source/dash/components/animation.d +++ b/source/dash/components/animation.d @@ -3,7 +3,7 @@ */ module dash.components.animation; import dash.core.properties; -import dash.components.component; +import dash.components; import dash.utility; import derelict.assimp3.assimp; @@ -137,7 +137,7 @@ public: /** * Stores the animation skeleton/bones, stores the animations poses, and makes this information accessible to gameobjects */ -class AssetAnimation +class AssetAnimation : Asset { private: /// List of animations, containing all of the information specific to each @@ -167,6 +167,8 @@ public: */ this( const(aiAnimation**) animations, int numAnimations, const(aiMesh*) mesh, const(aiNode*) nodeHierarchy ) { + super( Resource( "" ) ); + for( int i = 0; i < nodeHierarchy.mNumChildren; i++) { string name = nodeHierarchy.mChildren[ i ].mName.data.ptr.fromStringz().to!string; @@ -446,7 +448,7 @@ public: /** * Shutdown the animation bone/pose data */ - void shutdown() + override void shutdown() { } diff --git a/source/dash/components/assets.d b/source/dash/components/assets.d index 32f0ee9f..0d618561 100644 --- a/source/dash/components/assets.d +++ b/source/dash/components/assets.d @@ -16,24 +16,32 @@ abstract final class Assets { static: private: - Material[][Resource] materialResources; + MaterialAsset[][Resource] materialResources; package: - Mesh[string] meshes; - Texture[string] textures; - Material[string] materials; + MeshAsset[string] meshes; + TextureAsset[string] textures; + MaterialAsset[string] materials; public: /// Basic quad, generally used for billboarding. Mesh unitSquare; + /** + * Get a reference to the asset with the given type and name. + */ + AssetRefT get( AssetRefT )( string name ) if( is( AssetRefT AssetT : AssetRef!AssetT ) && !is( AssetRefT == AssetRef!AssetT ) ) + { + return new AssetRefT( get!AssetT( name ) ); + } + /** * Get the asset with the given type and name. */ - T get( T )( string name ) if( is( T == Mesh ) || is( T == Texture ) || is( T == Material ) || is( T == AssetAnimation )) + AssetT getAsset( AssetT )( string name ) if( is( AssetT : Asset ) ) { enum get( Type, string array ) = q{ - static if( is( T == $Type ) ) + static if( is( AssetT == $Type ) ) { if( auto result = name in $array ) { @@ -48,9 +56,9 @@ public: } }.replaceMap( [ "$array": array, "$Type": Type.stringof ] ); - mixin( get!( Mesh, q{meshes} ) ); - mixin( get!( Texture, q{textures} ) ); - mixin( get!( Material, q{materials} ) ); + mixin( get!( MeshAsset, q{meshes} ) ); + mixin( get!( TextureAsset, q{textures} ) ); + mixin( get!( MaterialAsset, q{materials} ) ); } /** @@ -67,7 +75,7 @@ public: assert(aiIsExtensionSupported(".fbx".toStringz), "fbx format isn't supported by assimp instance!"); // Load the unitSquare - unitSquare = new Mesh( "", aiImportFileFromMemory( + unitSquare = new MeshAsset( "", aiImportFileFromMemory( unitSquareMesh.toStringz, unitSquareMesh.length, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType, @@ -88,7 +96,7 @@ public: // Add mesh if( scene.mNumMeshes > 0 ) { - auto newMesh = new Mesh( file.fullPath, scene.mMeshes[ 0 ] ); + auto newMesh = new MeshAsset( file.fullPath, scene.mMeshes[ 0 ] ); if( scene.mNumAnimations > 0 ) newMesh.animationData = new AssetAnimation( scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); @@ -109,7 +117,7 @@ public: if( file.baseFileName in textures ) logWarning( "Texture ", file.baseFileName, " exists more than once." ); - textures[ file.baseFileName ] = new Texture( file.fullPath ); + textures[ file.baseFileName ] = new TextureAsset( file.fullPath ); } foreach( objFile; loadYamlFiles( Resources.Materials ) ) @@ -158,7 +166,7 @@ public: // Iterate over each file, and it's materials refreshYamlObjects!( - node => cast(Material)createYamlObject[ "Material" ]( node ), + node => cast(MaterialAsset)createYamlObject[ "Material" ]( node ), node => node[ "Name" ].get!string in materials, ( node, mat ) => materials[ node[ "Name" ].get!string ] = mat, mat => materials.remove( mat.name ) ) @@ -187,24 +195,54 @@ public: } } -abstract class Asset : Component +abstract class Asset { private: bool _isUsed; - Resource _resource; public: /// Whether or not the material is actually used. mixin( Property!( _isUsed, AccessModifier.Package ) ); /// The resource containing this asset. - mixin( RefGetter!_resource ); + Resource resource; /** * Creates asset with resource. */ - this( Resource resource ) + this( Resource res ) + { + resource = res; + } + + void initialize() { } + void update() { } + void refresh() { } + void shutdown() { } +} + +/** + * A reference to an asset. + */ +abstract class AssetRef( AssetType ) : Component if( is( AssetType : Asset ) ) +{ +public: + //@ignore + AssetType asset; + + @field( "Asset" ) + string assetName; + + this() { } + this( AssetType ass ) + { + asset = ass; + } + + /// Gets a reference to it's asset. + override void initialize() { - _resource = resource; + if( !asset ) + asset = Assets.getAsset!AssetType( assetName ); } } diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 0bde69f7..e0db5f60 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -101,11 +101,11 @@ auto field( string loader = "null" )( string name = "" ) } /// Used to create objects from yaml. The key is the YAML name of the type. -YamlObject delegate( Node )[string] createYamlObject; +Object delegate( Node )[string] createYamlObject; /// Used to create components from yaml. The key is the YAML name of the type. Component delegate( Node )[string] createYamlComponent; /// Refresh any object defined from yaml. The key is the typeid of the type. -void delegate( YamlObject, Node )[TypeInfo] refreshYamlObject; +void delegate( Object, Node )[TypeInfo] refreshYamlObject; /** * To be placed at the top of any module defining YamlComponents. @@ -165,7 +165,7 @@ enum registerComponents( string modName ) = q{ LoaderFunction[TypeInfo] typeLoaders; /// DON'T MIND ME -void registerYamlObjects( Base )( string yamlName, YamlType type ) if( is( Base : YamlObject ) ) +void registerYamlObjects( Base )( string yamlName, YamlType type ) if( isYamlObject!Base ) { // If no name specified, use class name. if( yamlName == "" ) @@ -341,7 +341,7 @@ void registerYamlObjects( Base )( string yamlName, YamlType type ) if( is( Base createYamlObject[ yamlName ] = ( node ) { // Create an instance of the class to assign things to. - YamlObject b = new Base; + Object b = new Base; refreshYamlObject[ typeid(Base) ]( b, node ); diff --git a/source/dash/components/material.d b/source/dash/components/material.d index 690cb73b..a41466c9 100644 --- a/source/dash/components/material.d +++ b/source/dash/components/material.d @@ -13,15 +13,16 @@ mixin( registerComponents!q{dash.components.material} ); /** * A collection of textures that serve different purposes in the rendering pipeline. */ -@yamlComponent!( q{name => Assets.get!Material( name )} )() @yamlObject() -final class Material : Asset +final class MaterialAsset : Asset { package: @field( "Name" ) string _name; public: + /// The defining yaml + Node yaml; /// The diffuse (or color) map. @field( "Diffuse" ) Texture diffuse; @@ -45,6 +46,19 @@ public: _name = name; } + /** + * Duplicate the material. + */ + MaterialAsset clone() + { + auto mat = new MaterialAsset; + mat.diffuse = diffuse; + mat.normal = normal; + mat.specular = specular; + mat._name = _name; + return mat; + } + /** * Shuts down the material, making sure all references are released. */ @@ -54,11 +68,32 @@ public: } } +/** + * A reference to a material. + */ +final class Material : AssetRef!MaterialAsset +{ + alias asset this; + + this() { } + this( MaterialAsset ass ) + { + super( ass ); + } + + override void initialize() + { + super.initialize(); + + // All materials should be unique. + asset = asset.clone(); + } +} + /** * TODO */ -@yamlComponent!( q{name => Assets.get!Texture( name )} )() -class Texture : Asset +class TextureAsset : Asset { protected: uint _width = 1; @@ -151,6 +186,14 @@ private: } } +/** + * A reference to a texture. + */ +class Texture : AssetRef!TextureAsset +{ + alias asset this; +} + /** * A default black texture. */ @@ -159,7 +202,7 @@ private: static Texture def; if( !def ) - def = new Texture( [cast(ubyte)0, cast(ubyte)0, cast(ubyte)0, cast(ubyte)255].ptr ); + def = new TextureAsset( [cast(ubyte)0, cast(ubyte)0, cast(ubyte)0, cast(ubyte)255].ptr ); return def; } @@ -172,7 +215,7 @@ private: static Texture def; if( !def ) - def = new Texture( [cast(ubyte)255, cast(ubyte)127, cast(ubyte)127, cast(ubyte)255].ptr ); + def = new TextureAsset( [cast(ubyte)255, cast(ubyte)127, cast(ubyte)127, cast(ubyte)255].ptr ); return def; } diff --git a/source/dash/components/mesh.d b/source/dash/components/mesh.d index fbf20fc7..7764046f 100644 --- a/source/dash/components/mesh.d +++ b/source/dash/components/mesh.d @@ -57,8 +57,7 @@ mixin( registerComponents!q{dash.components.mesh} ); * Ogre XML * Q3D */ -@yamlComponent!( q{name => Assets.get!Mesh( name )} )() -class Mesh : Asset +class MeshAsset : Asset { private: uint _glVertexArray, _numVertices, _numIndices, _glIndexBuffer, _glVertexBuffer; @@ -306,7 +305,7 @@ public: // Add mesh if( scene.mNumMeshes > 0 ) { - Mesh tempMesh = new Mesh( resource.fullPath, scene.mMeshes[ 0 ] ); + auto tempMesh = new MeshAsset( resource.fullPath, scene.mMeshes[ 0 ] ); if( scene.mNumAnimations > 0 ) tempMesh.animationData = new AssetAnimation( scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); @@ -340,6 +339,11 @@ public: } } +class Mesh : AssetRef!MeshAsset +{ + alias asset this; +} + /** * Helper function that calculates a modifier for the reconstructed bitangent based on regenerating them * May be needed elsewhere diff --git a/source/dash/components/userinterface.d b/source/dash/components/userinterface.d index a57f4520..87fd1fa3 100644 --- a/source/dash/components/userinterface.d +++ b/source/dash/components/userinterface.d @@ -163,7 +163,7 @@ public: /** * Creates an Awesomium web view texture */ -class AwesomiumView : Texture +class AwesomiumView : TextureAsset { private: version( Windows ) @@ -176,7 +176,6 @@ public: _width = w; _height = h; glBuffer = new ubyte[_width*_height*4]; - this.owner = owner; super( cast(ubyte*)null ); diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index e76be567..f06fdd8a 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -199,7 +199,7 @@ public: _transform = Transform( this ); // Create default material - material = new Material( "default" ); + material = new Material( new MaterialAsset( "default" ) ); id = nextId++; stateFlags = new ObjectStateFlags; From 18c25e56cba8b746194f1a58cdfea01df759979f Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sun, 7 Sep 2014 19:44:10 -0400 Subject: [PATCH 023/141] Renamed AssetAnimation to AnimationData to avoid confusion with Assets --- source/dash/components/animation.d | 6 +++--- source/dash/components/assets.d | 2 +- source/dash/components/mesh.d | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/dash/components/animation.d b/source/dash/components/animation.d index 60f7c797..423a02f8 100644 --- a/source/dash/components/animation.d +++ b/source/dash/components/animation.d @@ -18,7 +18,7 @@ class Animation : Component { private: /// Asset animation that the gameobject is animating based off of - AssetAnimation _animationData; + AnimationData _animationData; /// Current animation out of all the animations in the asset animation int _currentAnim; /// Current time of the animation @@ -40,7 +40,7 @@ public: /** * Create animation object based on asset animation */ - this( AssetAnimation assetAnimation ) + this( AnimationData assetAnimation ) { _currentAnim = 0; _currentAnimTime = 0.0f; @@ -137,7 +137,7 @@ public: /** * Stores the animation skeleton/bones, stores the animations poses, and makes this information accessible to gameobjects */ -class AssetAnimation : Asset +class AnimationData : Asset { private: /// List of animations, containing all of the information specific to each diff --git a/source/dash/components/assets.d b/source/dash/components/assets.d index 0d618561..378458ab 100644 --- a/source/dash/components/assets.d +++ b/source/dash/components/assets.d @@ -99,7 +99,7 @@ public: auto newMesh = new MeshAsset( file.fullPath, scene.mMeshes[ 0 ] ); if( scene.mNumAnimations > 0 ) - newMesh.animationData = new AssetAnimation( scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); + newMesh.animationData = new AnimationData( scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); meshes[ file.baseFileName ] = newMesh; } diff --git a/source/dash/components/mesh.d b/source/dash/components/mesh.d index 7764046f..98dabccd 100644 --- a/source/dash/components/mesh.d +++ b/source/dash/components/mesh.d @@ -63,7 +63,7 @@ private: uint _glVertexArray, _numVertices, _numIndices, _glIndexBuffer, _glVertexBuffer; bool _animated; AABB _boundingBox; - AssetAnimation _animationData; + AnimationData _animationData; public: /// TODO @@ -308,7 +308,7 @@ public: auto tempMesh = new MeshAsset( resource.fullPath, scene.mMeshes[ 0 ] ); if( scene.mNumAnimations > 0 ) - tempMesh.animationData = new AssetAnimation( scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); + tempMesh.animationData = new AnimationData( scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); // Copy attributes _glVertexArray = tempMesh._glVertexArray; From 0f3fe00eefe9eaab4a3618a0410983a8de02c793 Mon Sep 17 00:00:00 2001 From: Sean Brennan Date: Sun, 7 Sep 2014 19:59:38 -0400 Subject: [PATCH 024/141] Implemented Audio, Listener, and Emitter. --- source/dash/components/audio.d | 55 ++++++++++++++++++++++++++++++++- source/dash/core/dgame.d | 1 + source/dash/core/scene.d | 2 ++ source/dash/utility/resources.d | 1 + 4 files changed, 58 insertions(+), 1 deletion(-) diff --git a/source/dash/components/audio.d b/source/dash/components/audio.d index 3938d84f..df1e55f9 100644 --- a/source/dash/components/audio.d +++ b/source/dash/components/audio.d @@ -4,12 +4,16 @@ module dash.components.audio; import dash.core.properties; import dash.components.component; -import dash.utility.soloud; +import dash.utility, dash.utility.soloud; +import std.string; + +mixin( registerComponents!q{dash.components.audio} ); /** * Listener object that hears sounds and sends them to the audio output device * (usually attaced to the camera) */ +@yamlComponent( "Listener" ) class Listener : Component { private: @@ -22,11 +26,19 @@ public: { // Constructor code } + + override void update() + { + Audio.soloud.set3dListenerAt(owner.transform.position.x, + owner.transform.position.y, + owner.transform.position.z); + } } /** * Emitter object that plays sounds that listeners can hear if they are close enough */ +@yamlComponent( "Emitter" ) class Emitter : Component { private: @@ -39,4 +51,45 @@ public: { // Constructor Code } + + // call: + // emmiter.play(Audio.sounds["baseFileName"]); + void play( string soundName ) + { + string filePath = Audio.sounds[soundName]; + Wav toPlay = Wav.create(); + toPlay.load(filePath.toStringz); + Audio.soloud.play3d(toPlay, + owner.transform.position.x, + owner.transform.position.y, + owner.transform.position.z); + } } + +/** + * TODO + * implement sound struct +struct Sound +{ + Wav soundfile; +} + */ + +final abstract class Audio +{ +static: +private: + Soloud soloud; + +public: + string[string] sounds; + + void initialize() + { + soloud = Soloud.create(); + foreach( file; scanDirectory( Resources.Audio ) ) + { + sounds[file.baseFileName] = file.fullPath; + } + } +} \ No newline at end of file diff --git a/source/dash/core/dgame.d b/source/dash/core/dgame.d index e7cda67f..5ba1354a 100644 --- a/source/dash/core/dgame.d +++ b/source/dash/core/dgame.d @@ -204,6 +204,7 @@ private: bench!( { Input.initialize(); } )( "Input init" ); bench!( { Graphics.initialize(); } )( "Graphics init" ); bench!( { Assets.initialize(); } )( "Assets init" ); + bench!( { Audio.initialize(); } )( "Audio init" ); bench!( { Prefabs.initialize(); } )( "Prefabs init" ); bench!( { UserInterface.initializeAwesomium(); } )( "UI init" ); bench!( { DGame.instance.onInitialize(); } )( "Game init" ); diff --git a/source/dash/core/scene.d b/source/dash/core/scene.d index 4a3c127e..135a3476 100644 --- a/source/dash/core/scene.d +++ b/source/dash/core/scene.d @@ -25,6 +25,8 @@ package: public: /// The camera to render with. Camera camera; + Listener listener; + /// The root object of the scene. mixin( Getter!_root ); diff --git a/source/dash/utility/resources.d b/source/dash/utility/resources.d index 73ffd335..d8d281b0 100644 --- a/source/dash/utility/resources.d +++ b/source/dash/utility/resources.d @@ -15,6 +15,7 @@ enum Resources : string Materials = Home ~ "/Materials", Meshes = Home ~ "/Meshes", Textures = Home ~ "/Textures", + Audio = Home ~ "/Audio", Scripts = Home ~ "/Scripts", Prefabs = Home ~ "/Prefabs", Objects = Home ~ "/Objects", From a5a7d9c5dc1910ac4546a11c43d2338ed4f16053 Mon Sep 17 00:00:00 2001 From: Sean Brennan Date: Mon, 8 Sep 2014 12:14:33 -0400 Subject: [PATCH 025/141] Trying to get soloud to load sounds properly --- source/dash/components/audio.d | 45 ++++++++++++++++++++++++++++------ source/dash/core/dgame.d | 1 + source/dash/core/gameobject.d | 2 ++ source/dash/utility/soloud.d | 26 ++++++++++---------- 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/source/dash/components/audio.d b/source/dash/components/audio.d index df1e55f9..c2e21ee5 100644 --- a/source/dash/components/audio.d +++ b/source/dash/components/audio.d @@ -42,7 +42,7 @@ public: class Emitter : Component { private: - + Wav toPlay; public: /** * Create an emmiter object @@ -52,17 +52,34 @@ public: // Constructor Code } + override void initialize() { + super.initialize; + toPlay = Wav.create(); + + } + // call: // emmiter.play(Audio.sounds["baseFileName"]); void play( string soundName ) { - string filePath = Audio.sounds[soundName]; - Wav toPlay = Wav.create(); - toPlay.load(filePath.toStringz); - Audio.soloud.play3d(toPlay, + + /*string filePath = Audio.sounds[soundName]; + logInfo( "playing: ", filePath ); + toPlay = Wav.create(); + toPlay.load( filePath.toStringz() ); + Speech speech = Speech.create(); + speech.setText("hello".toStringz());*/ + toPlay.load( "C:\\Circular\\Sample-Dash-Game\\Audio\\airhorn.wav".toStringz() ); + + auto result = Audio.soloud.play( toPlay, 1.0 ); + + logInfo( Audio.soloud.getErrorString( result ) ); + /*Audio.soloud.play3d(toPlay, owner.transform.position.x, owner.transform.position.y, - owner.transform.position.z); + owner.transform.position.z);*/ + //logInfo( "playing: ", soundName, " with id: ", Audio.effects[soundName].objhandle ); + //Audio.soloud.play( Audio.effects[soundName] ); } } @@ -78,18 +95,32 @@ struct Sound final abstract class Audio { static: -private: +//private: Soloud soloud; public: string[string] sounds; + Wav[string] effects; + void initialize() { soloud = Soloud.create(); + soloud.init(); foreach( file; scanDirectory( Resources.Audio ) ) { sounds[file.baseFileName] = file.fullPath; + + /*effects[file.baseFileName] = Wav.create(); + effects[file.baseFileName].load( file.fullPath.toStringz ); + logInfo( "baseFileName: ", file.baseFileName ); + logInfo( "fullPath: ", file.fullPath.toStringz );*/ } } + + void shutdown() + { + soloud.deinit(); + soloud.destroy(); + } } \ No newline at end of file diff --git a/source/dash/core/dgame.d b/source/dash/core/dgame.d index 8a9e1f07..c46eae25 100644 --- a/source/dash/core/dgame.d +++ b/source/dash/core/dgame.d @@ -229,6 +229,7 @@ private: UserInterface.shutdownAwesomium(); Assets.shutdown(); Graphics.shutdown(); + Audio.shutdown(); } /** diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index e76be567..f9795e2b 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -93,6 +93,8 @@ public: mixin( componentProperty!Animation ); /// The camera attached to this object. mixin( componentProperty!Camera ); + /// The emitter attached to this object. + mixin( componentProperty!Emitter ); /// The object that this object belongs to. mixin( Property!_parent ); /// All of the objects which list this as parent diff --git a/source/dash/utility/soloud.d b/source/dash/utility/soloud.d index 44b684b7..657bec3e 100644 --- a/source/dash/utility/soloud.d +++ b/source/dash/utility/soloud.d @@ -37,7 +37,7 @@ pure @safe nothrow @nogc: return Soloud(SoloudObject(Soloud_create())); } - ~this() + public void destroy() { Soloud_destroy(objhandle); } @@ -424,7 +424,7 @@ pure @safe nothrow @nogc: return BiquadResonantFilter(SoloudObject(BiquadResonantFilter_create())); } - ~this() + public void destroy() { BiquadResonantFilter_destroy(objhandle); } @@ -448,7 +448,7 @@ pure @safe nothrow @nogc: return Bus(SoloudObject(Bus_create())); } - ~this() + public void destroy() { Bus_destroy(objhandle); } @@ -552,7 +552,7 @@ pure @safe nothrow @nogc: return EchoFilter(SoloudObject(EchoFilter_create())); } - ~this() + public void destroy() { EchoFilter_destroy(objhandle); } @@ -579,7 +579,7 @@ pure @safe nothrow @nogc: return FFTFilter(SoloudObject(FFTFilter_create())); } - ~this() + public void destroy() { FFTFilter_destroy(objhandle); } @@ -606,7 +606,7 @@ pure @safe nothrow @nogc: return FlangerFilter(SoloudObject(FlangerFilter_create())); } - ~this() + public void destroy() { FlangerFilter_destroy(objhandle); } @@ -633,7 +633,7 @@ pure @safe nothrow @nogc: return LofiFilter(SoloudObject(LofiFilter_create())); } - ~this() + public void destroy() { LofiFilter_destroy(objhandle); } @@ -657,7 +657,7 @@ pure @safe nothrow @nogc: return Modplug(SoloudObject(Modplug_create())); } - ~this() + public void destroy() { Modplug_destroy(objhandle); } @@ -731,7 +731,7 @@ pure @safe nothrow @nogc: return Prg(SoloudObject(Prg_create())); } - ~this() + public void destroy() { Prg_destroy(objhandle); } @@ -767,7 +767,7 @@ pure @safe nothrow @nogc: return Sfxr(SoloudObject(Sfxr_create())); } - ~this() + public void destroy() { Sfxr_destroy(objhandle); } @@ -851,7 +851,7 @@ pure @safe nothrow @nogc: return Speech(SoloudObject(Speech_create())); } - ~this() + public void destroy() { Speech_destroy(objhandle); } @@ -925,7 +925,7 @@ pure @safe nothrow @nogc: return Wav(SoloudObject(Wav_create())); } - ~this() + public void destroy() { Wav_destroy(objhandle); } @@ -1009,7 +1009,7 @@ pure @safe nothrow @nogc: return WavStream(SoloudObject(WavStream_create())); } - ~this() + public void destroy() { WavStream_destroy(objhandle); } From 7faa399d386282f2217d7f4f25a13ad53bb182ab Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 8 Sep 2014 12:29:56 -0400 Subject: [PATCH 026/141] Small bug fixes --- source/dash/components/assets.d | 12 +++++++----- source/dash/components/material.d | 12 +++++++++--- source/dash/components/mesh.d | 12 +++++------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/source/dash/components/assets.d b/source/dash/components/assets.d index 378458ab..56268437 100644 --- a/source/dash/components/assets.d +++ b/source/dash/components/assets.d @@ -32,7 +32,9 @@ public: */ AssetRefT get( AssetRefT )( string name ) if( is( AssetRefT AssetT : AssetRef!AssetT ) && !is( AssetRefT == AssetRef!AssetT ) ) { - return new AssetRefT( get!AssetT( name ) ); + static if( is( AssetRefT AssetT : AssetRef!AssetT ) ) + return new AssetRefT( getAsset!AssetT( name ) ); + else static assert( false ); } /** @@ -75,11 +77,11 @@ public: assert(aiIsExtensionSupported(".fbx".toStringz), "fbx format isn't supported by assimp instance!"); // Load the unitSquare - unitSquare = new MeshAsset( "", aiImportFileFromMemory( - unitSquareMesh.toStringz, unitSquareMesh.length, + unitSquare = new Mesh( new MeshAsset( "", aiImportFileFromMemory( + unitSquareMesh.toStringz(), unitSquareMesh.length, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType, - "obj" ).mMeshes[0] ); + "obj" ).mMeshes[0] ) ); foreach( file; scanDirectory( Resources.Meshes ) ) { @@ -128,7 +130,7 @@ public: if( name in materials ) logWarning( "Material ", name, " exists more than once." ); - auto newMat = cast(Material)createYamlObject[ "Material" ]( object ); + auto newMat = cast(MaterialAsset)createYamlObject[ "Material" ]( object ); materials[ name ] = newMat; materialResources[ objFile[ 1 ] ] ~= newMat; } diff --git a/source/dash/components/material.d b/source/dash/components/material.d index a41466c9..e17e1519 100644 --- a/source/dash/components/material.d +++ b/source/dash/components/material.d @@ -86,7 +86,8 @@ final class Material : AssetRef!MaterialAsset super.initialize(); // All materials should be unique. - asset = asset.clone(); + if( asset ) + asset = asset.clone(); } } @@ -192,6 +193,11 @@ private: class Texture : AssetRef!TextureAsset { alias asset this; + + this( TextureAsset ass ) + { + super( ass ); + } } /** @@ -202,7 +208,7 @@ class Texture : AssetRef!TextureAsset static Texture def; if( !def ) - def = new TextureAsset( [cast(ubyte)0, cast(ubyte)0, cast(ubyte)0, cast(ubyte)255].ptr ); + def = new Texture( new TextureAsset( [cast(ubyte)0, cast(ubyte)0, cast(ubyte)0, cast(ubyte)255].ptr ) ); return def; } @@ -215,7 +221,7 @@ class Texture : AssetRef!TextureAsset static Texture def; if( !def ) - def = new TextureAsset( [cast(ubyte)255, cast(ubyte)127, cast(ubyte)127, cast(ubyte)255].ptr ); + def = new Texture( new TextureAsset( [cast(ubyte)255, cast(ubyte)127, cast(ubyte)127, cast(ubyte)255].ptr ) ); return def; } diff --git a/source/dash/components/mesh.d b/source/dash/components/mesh.d index 98dabccd..99d6bd68 100644 --- a/source/dash/components/mesh.d +++ b/source/dash/components/mesh.d @@ -11,13 +11,6 @@ import std.stdio, std.stream, std.format, std.math, std.string; mixin( registerComponents!q{dash.components.mesh} ); -/*Mesh getMesh( string name ) -{ - auto mesh = Assets.get!Mesh( yml.get!string ); - - return mesh; -}*/ - /** * Loads and manages meshes into OpenGL. * @@ -342,6 +335,11 @@ public: class Mesh : AssetRef!MeshAsset { alias asset this; + + this( MeshAsset ass ) + { + super( ass ); + } } /** From b0f1b453c4aad10c1b2c6e51e95704ba27a7e0ca Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 8 Sep 2014 15:12:48 -0400 Subject: [PATCH 027/141] Serialization should theoretically work now --- source/dash/components/component.d | 3 +-- source/dash/core/gameobject.d | 39 ++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 21a3e10b..31ff103d 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -42,7 +42,6 @@ abstract class Component : YamlObject { public: /// The node that defined the component. - @ignore Node yaml; /// The GameObject that owns this component. GameObject owner; @@ -151,7 +150,7 @@ public: Component.$typeDeserializers[ typeid(T).name ] = ( $type node ) { return null; - //return deserialize$type!SerializationDescription( node ).createInstance(); + //return deserialize$type!( SerializationDescription )( node ).createInstance(); }; } ); diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 3f079ddc..e8c41e1a 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -93,7 +93,23 @@ public: Description[] children; @rename( "Components" ) @optional - Component[] components; + Component[] components; + + /** + * Create a description from a GameObject. + * + * Returns: + * A new description with components and info. + */ + this( GameObject obj ) + { + name = obj.name; + prefabName = ""; + prefab = null; + transform = typeof(obj.transform).Description( obj.transform ); + children = obj.children.map!( child => typeof(child).Description( child ) ).array(); + components = obj.componentList.values.dup; + } } /// The current transform of the object. @@ -226,7 +242,7 @@ public: * desc = The description to pull info from. * * Returns: - * A new game object with components and info pulled from yaml. + * A new game object with components and info pulled from desc. */ static GameObject create( Description desc ) { @@ -537,9 +553,9 @@ private: void opAssign( Description desc ) { - position = desc.position; - rotation = quat( desc.rotation.w, desc.rotation.xyz ); - scale = desc.scale; + position = vec3( desc.position[] ); + rotation = quat( vec4( desc.rotation ) ); + scale = vec3( desc.scale[] ); } /** @@ -564,15 +580,22 @@ public: { /// The position of the object. @rename( "Position" ) @asArray @optional - vec3 position; + float[3] position; /// The position of the object. @rename( "Rotation" ) @asArray @optional - vec4 rotation; + float[4] rotation; /// The position of the object. @rename( "Scale" ) @asArray @optional - vec3 scale; + float[3] scale; + + this( Transform t ) + { + position = t.position.vector[ 0..3 ]; + rotation = t.rotation.quaternion[ 0..4 ]; + scale = t.scale.vector[ 0..3 ]; + } } // these should remain public fields, properties return copies not references From bd23829c2f31cf25f0f4f089f94c5023cdad34ed Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 8 Sep 2014 16:05:56 -0400 Subject: [PATCH 028/141] Started migrating to new serialization framework --- source/dash/components/assets.d | 31 ++++--- source/dash/components/component.d | 26 ++---- source/dash/components/material.d | 2 - source/dash/core/gameobject.d | 62 +------------ source/dash/core/prefabs.d | 12 +-- source/dash/core/scene.d | 8 +- source/dash/utility/config.d | 83 ------------------ source/dash/utility/data/serialization.d | 105 +++++++++++++++++++++++ 8 files changed, 134 insertions(+), 195 deletions(-) diff --git a/source/dash/components/assets.d b/source/dash/components/assets.d index 56268437..860d09ea 100644 --- a/source/dash/components/assets.d +++ b/source/dash/components/assets.d @@ -3,6 +3,7 @@ */ module dash.components.assets; import dash.core.properties, dash.components, dash.utility; +import dash.utility.data.serialization; import std.string, std.array, std.algorithm; @@ -122,17 +123,15 @@ public: textures[ file.baseFileName ] = new TextureAsset( file.fullPath ); } - foreach( objFile; loadYamlFiles( Resources.Materials ) ) + foreach( res; scanDirectory( Resources.Materials ) ) { - Node object = objFile[ 0 ]; - auto name = object[ "Name" ].as!string; + auto newMat = deserializeFile!MaterialAsset( res ); - if( name in materials ) - logWarning( "Material ", name, " exists more than once." ); + if( newMat.name in materials ) + logWarning( "Material ", newMat.name, " exists more than once." ); - auto newMat = cast(MaterialAsset)createYamlObject[ "Material" ]( object ); - materials[ name ] = newMat; - materialResources[ objFile[ 1 ] ] ~= newMat; + materials[ newMat.name ] = newMat; + materialResources[ res ] ~= newMat; } meshes.rehash(); @@ -167,12 +166,7 @@ public: mixin( refresh!q{textures} ); // Iterate over each file, and it's materials - refreshYamlObjects!( - node => cast(MaterialAsset)createYamlObject[ "Material" ]( node ), - node => node[ "Name" ].get!string in materials, - ( node, mat ) => materials[ node[ "Name" ].get!string ] = mat, - mat => materials.remove( mat.name ) ) - ( materialResources ); + //TODO: Implement } /** @@ -206,11 +200,16 @@ public: /// Whether or not the material is actually used. mixin( Property!( _isUsed, AccessModifier.Package ) ); /// The resource containing this asset. + @ignore Resource resource; /** * Creates asset with resource. */ + this() + { + resource = Resource( "" ); + } this( Resource res ) { resource = res; @@ -228,10 +227,10 @@ public: abstract class AssetRef( AssetType ) : Component if( is( AssetType : Asset ) ) { public: - //@ignore + @ignore AssetType asset; - @field( "Asset" ) + @rename( "Asset" ) string assetName; this() { } diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 31ff103d..7d110cde 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -20,30 +20,14 @@ auto append( Begin, End )( Begin begin, End end ) return tuple( begin.expand, end ); } -abstract class YamlObject -{ -public: - @ignore - Node yaml; - - /// Called when refreshing an object. - void refresh() { } - - this() - { - yaml = Node( YAMLNull() ); - } -} - /** * Interface for components to implement. */ -abstract class Component : YamlObject +abstract class Component { public: - /// The node that defined the component. - Node yaml; /// The GameObject that owns this component. + @ignore GameObject owner; /// The function called on initialization of the object. @@ -57,8 +41,8 @@ public: // For serialization. mixin( perSerializationFormat!q{ - static $type delegate( Component )[ ClassInfo ] $typeSerializers; - static Component delegate( $type )[ string ] $typeDeserializers; + @ignore static $type delegate( Component )[ ClassInfo ] $typeSerializers; + @ignore static Component delegate( $type )[ string ] $typeDeserializers; $type to$type() const { return $typeSerializers[ typeid(this) ]( cast()this ); @@ -345,7 +329,7 @@ Component delegate( Node )[string] createYamlComponent; void delegate( Object, Node )[TypeInfo] refreshYamlObject; enum YamlType { Object, Component, Field } -private alias LoaderFunction = YamlObject delegate( string ); +private alias LoaderFunction = Object delegate( string ); struct YamlUDA { diff --git a/source/dash/components/material.d b/source/dash/components/material.d index d5ea83ca..dec41854 100644 --- a/source/dash/components/material.d +++ b/source/dash/components/material.d @@ -21,8 +21,6 @@ package: string _name; public: - /// The defining yaml - Node yaml; /// The diffuse (or color) map. @field( "Diffuse" ) Texture diffuse; diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index e8c41e1a..a2fffb1f 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -364,67 +364,11 @@ public: * Refreshes the object with the given YAML node. * * Params: - * node = The node to refresh the object with. + * desc = The node to refresh the object with. */ - final void refresh( Node node ) + final void refresh( Description node ) { - // Update components - foreach( type; componentList.keys ) - { - if( auto refresher = type in refreshYamlObject ) - { - ( *refresher )( componentList[ type ], node ); - componentList[ type ].refresh(); - } - else - { - componentList.remove( type ); - } - } - - // Update children - Node yamlChildren; - if( node.tryFind( "Children", yamlChildren ) && yamlChildren.isSequence ) - { - auto childNames = children.map!( child => child.name ); - bool[string] childFound = childNames.zip( false.repeat( childNames.length ) ).assocArray(); - - foreach( Node yamlChild; yamlChildren ) - { - // Find 0 based index of child in yamlChildren - if( auto index = childNames.countUntil( yamlChild[ "Name" ].get!string ) + 1 ) - { - // Refresh with YAML node. - children[ index - 1 ].refresh( yamlChild ); - childFound[ yamlChild[ "Name" ].get!string ] = true; - } - // If not in children, add it. - else - { - addChild( GameObject.createFromYaml( yamlChild ) ); - } - } - - // Filter out found children's names, and then get the objects. - auto unfoundChildren = childFound.keys - .filter!( name => !childFound[ name ] ) - .map!( name => children[ childNames.countUntil( name ) ] ); - foreach( unfound; unfoundChildren ) - { - logDebug( "Removing child ", unfound.name, " from ", name, "." ); - unfound.shutdown(); - removeChild( unfound ); - } - } - // Remove all children - else - { - foreach( child; children ) - { - child.shutdown(); - removeChild( child ); - } - } + //TODO: Implement } /** diff --git a/source/dash/core/prefabs.d b/source/dash/core/prefabs.d index d4afe5e6..d0ff8e4a 100644 --- a/source/dash/core/prefabs.d +++ b/source/dash/core/prefabs.d @@ -64,12 +64,7 @@ public: */ void refresh() { - refreshYamlObjects!( - node => cast(Prefab)createYamlObject[ "Prefab" ]( node ), - node => node[ "Name" ].get!string in prefabs, - ( node, fab ) => prefabs[ node[ "Name" ].get!string ] = fab, - fab => prefabs.remove( fab.name ) ) - ( prefabResources ); + //TODO: Implement } private: @@ -80,7 +75,7 @@ private: * A prefab that allows for quick object creation. */ @yamlObject() -final class Prefab : YamlObject +final class Prefab { public: /// The name of the prefab. @@ -94,7 +89,8 @@ public: */ GameObject createInstance() { - return GameObject.createFromYaml( yaml ); + //TODO: Fix this + return null;//GameObject.createFromYaml( yaml ); } private: diff --git a/source/dash/core/scene.d b/source/dash/core/scene.d index 84faae0d..48b7cc13 100644 --- a/source/dash/core/scene.d +++ b/source/dash/core/scene.d @@ -57,6 +57,7 @@ public: */ final void clear() { + destroy( _root ); _root = new GameObject; } @@ -82,12 +83,7 @@ public: final void refresh() { // Iterate over each file, and it's objects - refreshYamlObjects!( - GameObject.createFromYaml, - node => this[ node[ "Name" ].get!string ], - ( node, obj ) => _root.addChild( obj ), - ( obj ) { if( obj.parent ) obj.parent.removeChild( obj ); } ) - ( goResources ); + //TODO: Implement } /** diff --git a/source/dash/utility/config.d b/source/dash/utility/config.d index 6c403389..5542bfbe 100644 --- a/source/dash/utility/config.d +++ b/source/dash/utility/config.d @@ -227,89 +227,6 @@ Node[] loadAllDocumentsInYamlFile( string filePath ) } } -/** - * Refreshs a set of objects based on yaml files. - * - * Params: - * createFunc = The function used to create a new object of type ObjectType. - * existsFunc = The function that checks if a node is already stored. Returns a pointer to the object. - * addToResourcesFunc =Adds the - * ObjectType = The type of object stored in YAML. - * objectResources = The map of files to the objects they store. - */ -void refreshYamlObjects( alias createFunc, alias existsFunc, alias addToResourcesFunc, alias removeFunc, ObjectType )( ref ObjectType[][Resource] objectResources ) -{ - // Disable refreshing YAML from a single file. - if( !contentNode.isNull ) - return; - - // Iterate over each file, and it's objects - foreach( file, ref objs; objectResources.dup ) - { - // If the file was deleted, remove all objects in it. - if( !file.exists ) - { - foreach( asset; objs ) - { - static if( __traits( compiles, asset.shutdown() ) ) - asset.shutdown(); - removeFunc( asset ); - } - - objs = []; - } - // Else if the file changed, update each material. - else if( file.needsRefresh ) - { - // For each material, whether or not it still exists - bool[ObjectType] objsFound = objs.zip( false.repeat( objs.length ) ).assocArray(); - - // Reset objectResources for this file - objs = []; - - // Foreach material currently in the file - foreach( node; loadAllDocumentsInYamlFile( file.fullPath ) ) - { - // If the material already existed, update it. - if( auto oldMat = existsFunc( node ) ) - { - // If is pointer, dereference - static if( isPointer!( typeof(oldMat) ) ) - auto mat = *oldMat; - else - auto mat = oldMat; - - if( mat.yaml != node ) - { - static if( __traits( compiles, mat.refresh( node ) ) ) - mat.refresh( node ); - else - refreshYamlObject[ typeid(mat) ]( mat, node ); - mat.yaml = node; - } - - objsFound[ mat ] = true; - objectResources[ file ] ~= mat; - } - // Else add new objects - else - { - auto newMat = createFunc( node ); - addToResourcesFunc( node, newMat ); - objectResources[ file ] ~= newMat; - } - } - - foreach( mat; objsFound.keys.filter!( object => !objsFound[ object ] ) ) - { - static if( __traits( compiles, mat.shutdown() ) ) - mat.shutdown(); - removeFunc( mat ); - } - } - } -} - /** * Get the element, cast to the given type, at the given path, in the given node. * diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index 3ee12488..c32206de 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -1,6 +1,111 @@ module dash.utility.data.serialization; +import dash.utility.resources; +import dash.utility.data.yaml; +import vibe.data.json, vibe.data.bson; // Serialization attributes public import vibe.data.serialization: asArray, byName, ignore, name, optional; /// Rename a field in the ddl. alias rename = name; + +/** + * Modes of serialization. + */ +enum SerializationMode +{ + Default, + Json, + Bson, + Yaml, +} + +/** + * Deserializes a file. + * + * Params: + * file = The name of the file to deserialize. + * + * Returns: The deserialized object. + */ +T deserializeFile( T )( Resource file, SerializationMode mode = SerializationMode.Default ) +{ + import std.path: extension; + import std.string: toLower; + + T handleJson() + { + return deserializeJson!T( file.readText().parseJsonString() ); + } + + T handleBson() + { + throw new Exception( "Not implemented." ); + } + + T handleYaml() + { + Yaml content = Loader.fromString( file.readText() ).load(); + return deserializeYaml!T( content ); + } + + final switch( mode ) with( SerializationMode ) + { + case Json: return handleJson(); + case Bson: return handleBson(); + case Yaml: return handleYaml(); + case Default: + switch( file.extension.toLower ) + { + case ".json": return handleJson(); + case ".bson": return handleBson(); + case ".yaml": + case ".yml": return handleYaml(); + default: throw new Exception( "File extension " ~ file.extension.toLower ~ " not supported." ); + } + } +} + +/** + * Serializes an object to a file. + */ +template serializeToFile( bool prettyPrint = true ) +{ + void serializeToFile( T )( T t, string outPath, SerializationMode mode = SerializationMode.Default ) + { + import std.path: extension; + import std.string: toLower; + import std.file: File; + + void handleJson() + { + writeJsonString!( File, prettyPrint )( new File( outPath ), serializeToJson( t ) ); + } + + void handleBson() + { + throw new Exception( "Not implemented." ); + } + + void handleYaml() + { + throw new Exception( "Not implemented." ); + } + + final switch( mode ) with( SerializationMode ) + { + case Json: handleJson(); break; + case Bson: handleBson(); break; + case Yaml: handleYaml(); break; + case Default: + switch( file.extension.toLower ) + { + case ".json": handleJson(); break; + case ".bson": handleBson(); break; + case ".yaml": + case ".yml": handleYaml(); break; + default: throw new Exception( "File extension " ~ file.extension.toLower ~ " not supported." ); + } + break; + } + } +} From d3ff06bbb3f675a7c066e90f529c667cc464d842 Mon Sep 17 00:00:00 2001 From: Berulacks Date: Mon, 8 Sep 2014 22:58:44 -0400 Subject: [PATCH 029/141] Improved SDL support to the point that it appears to be on par with windows. Fixes #207 --- source/dash/graphics/adapters/package.d | 1 + source/dash/graphics/adapters/sdl.d | 29 +++-- source/dash/utility/input.d | 147 +++++++++++++++++++++++- 3 files changed, 168 insertions(+), 9 deletions(-) diff --git a/source/dash/graphics/adapters/package.d b/source/dash/graphics/adapters/package.d index 314e2418..a3cf5340 100644 --- a/source/dash/graphics/adapters/package.d +++ b/source/dash/graphics/adapters/package.d @@ -2,6 +2,7 @@ module dash.graphics.adapters; public: import dash.graphics.adapters.adapter; import dash.graphics.adapters.sdl; +import dash.graphics.adapters.gl; version( Windows ) import dash.graphics.adapters.win32gl; diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 504b83ed..193b3571 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -1,13 +1,14 @@ module dash.graphics.adapters.sdl; import dash.core.dgame; -import dash.graphics.graphics; +//import dash.graphics.graphics; +import dash.graphics; import dash.graphics.adapters.adapter; import dash.utility; import derelict.opengl3.gl3, gfm.sdl2; import std.string; -class Sdl : Adapter +class Sdl : OpenGL { private: SDL2 sdl; @@ -70,13 +71,16 @@ public: override void resize() { loadProperties(); - window.setSize( width, height ); + + resizeDefferedRenderBuffer(); + glViewport( 0, 0, width, height ); } override void refresh() { resize(); + swapBuffers(); } override void swapBuffers() @@ -84,6 +88,7 @@ public: window.swapBuffers(); } + //Don't know if we need this... override void openWindow() { @@ -91,6 +96,7 @@ public: override void closeWindow() { + window.close(); } @@ -120,19 +126,29 @@ public: break; } - // + //On keypress case SDL_KEYDOWN: + Keyboard.setButtonState( cast(Keyboard.Buttons)event.key.keysym.sym, true ); + break; + + //On keyrelease case SDL_KEYUP: - { + Keyboard.setButtonState( cast(Keyboard.Buttons)event.key.keysym.sym, false ); break; - } // Handle quitting. case SDL_QUIT: DGame.instance.currentState = EngineState.Quit; break; + case SDL_MOUSEWHEEL: + Mouse.setAxisState( Mouse.Axes.ScrollWheel, Mouse.getAxisState( Mouse.Axes.ScrollWheel ) + ( ( cast(int)event.wheel.y >> 16 ) / 120 ) ); + break; + case SDL_APP_TERMINATING: + shutdown(); + break; + case SDL_APP_LOWMEMORY: case SDL_APP_WILLENTERBACKGROUND: case SDL_APP_DIDENTERBACKGROUND: @@ -143,7 +159,6 @@ public: case SDL_TEXTEDITING: case SDL_TEXTINPUT: case SDL_MOUSEMOTION: - case SDL_MOUSEWHEEL: case SDL_JOYAXISMOTION: case SDL_JOYBALLMOTION: case SDL_JOYHATMOTION: diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index e7309cea..f68e8367 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -3,6 +3,7 @@ */ module dash.utility.input; import dash.utility, dash.core, dash.graphics; +import gfm.sdl2; import yaml, gl3n.linalg; import derelict.opengl3.gl3; @@ -325,7 +326,15 @@ public: } } -alias Keyboard = InputSystem!( KeyboardButtons, void ); +//alias Keyboard; +version(UseSDL2) +{ + alias Keyboard = InputSystem!( KeyboardButtonsWin, void ); +} +else +{ + alias Keyboard = InputSystem!( KeyboardButtonsWin, void ); +} alias Mouse = InputSystem!( MouseButtons, MouseAxes ); private: @@ -643,7 +652,7 @@ enum MouseAxes * * From: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx */ -enum KeyboardButtons: uint +enum KeyboardButtonsWin: uint { Cancel = 0x03, /// Control-break //Unused = 0x07, @@ -773,6 +782,140 @@ enum KeyboardButtons: uint END, } + +enum KeyboardButtonsSDL: uint +{ + Cancel = SDLK_CANCEL, /// Control-break + //Unused = 0x07, + Backspace = SDLK_BACKSPACE, /// Backspace key + Tab = SDLK_TAB, /// Tab key + //Reserved = 0x0A-0x0B, + Clear = SDLK_CLEAR, /// Clear key + Return = SDLK_RETURN, /// Enter key + //Undefined = 0x0E-0x0F + // * See Left/Right Shift, Ctrl, Alt below * + //Shift = SDLK_LSHIFT, /// Shift key + //Control = SDLK_LCTRL, /// Control key + //Alt = SDLK_LALT, /// Menu/alt key + // + Pause = SDLK_PAUSE, /// Pause key + CapsLock = SDLK_CAPSLOCK, + //Who Cares = 0x15-0x1A, + Escape = SDLK_ESCAPE, + //Who Cares = 0x1C-0x1F + Space = SDLK_SPACE, /// Space bar + PageUp = SDLK_PAGEUP, /// Page Up/Prior key + PageDown = SDLK_PAGEDOWN, /// Page Down/Next key + End = SDLK_END, /// End key + Home = SDLK_HOME, /// Home key + Left = SDLK_LEFT, /// Left arrow key + Up = SDLK_UP, /// Up arrow key + Right = SDLK_RIGHT, /// Right arrow key + Down = SDLK_DOWN, /// Down arrow key + Select = SDLK_SELECT, /// Select key + Print = SDLK_PRINTSCREEN, /// Print key + PrintScreen = SDLK_PRINTSCREEN, /// Print Screen/Snapshot key + Execute = SDLK_EXECUTE, /// Execute key + Insert = SDLK_INSERT, /// Insert key + Delete = SDLK_DELETE, /// Delete key + Help = SDLK_HELP, /// Help key + Keyboard0 = SDLK_0, /// 0 key + Keyboard1 = SDLK_1, /// 1 key + Keyboard2 = SDLK_2, /// 2 key + Keyboard3 = SDLK_3, /// 3 key + Keyboard4 = SDLK_4, /// 4 key + Keyboard5 = SDLK_5, /// 5 key + Keyboard6 = SDLK_6, /// 6 key + Keyboard7 = SDLK_7, /// 7 key + Keyboard8 = SDLK_8, /// 8 key + Keyboard9 = SDLK_9, /// 9 key + //Unused = 0x3A-0x40 + A = SDLK_a, /// A key + B = SDLK_b, /// B key + C = SDLK_c, /// C key + D = SDLK_d, /// D key + E = SDLK_e, /// E key + F = SDLK_f, /// F key + G = SDLK_g, /// G key + H = SDLK_h, /// H key + I = SDLK_i, /// I key + J = SDLK_j, /// J key + K = SDLK_k, /// K key + L = SDLK_l, /// L key + M = SDLK_m, /// M key + N = SDLK_n, /// N key + O = SDLK_o, /// O key + P = SDLK_p, /// P key + Q = SDLK_q, /// Q key + R = SDLK_r, /// R key + S = SDLK_s, /// S key + T = SDLK_t, /// T key + U = SDLK_u, /// U key + V = SDLK_v, /// V key + W = SDLK_w, /// W key + X = SDLK_x, /// X key + Y = SDLK_y, /// Y key + Z = SDLK_z, /// Z key + GuiLeft = SDLK_LGUI, /// Left GUI key + GuiRight = SDLK_RGUI, /// Right GUI key + Apps = SDLK_APPLICATION, /// Applications key + //Reserved = 0x5E + Sleep = SDLK_SLEEP, /// Sleep key + Numpad0 = SDLK_KP_0, /// 0 key + Numpad1 = SDLK_KP_1, /// 1 key + Numpad2 = SDLK_KP_2, /// 2 key + Numpad3 = SDLK_KP_3, /// 3 key + Numpad4 = SDLK_KP_4, /// 4 key + Numpad5 = SDLK_KP_5, /// 5 key + Numpad6 = SDLK_KP_6, /// 6 key + Numpad7 = SDLK_KP_7, /// 7 key + Numpad8 = SDLK_KP_8, /// 8 key + Numpad9 = SDLK_KP_9, /// 9 key + // * Unused * + //Multiply = 0x6A, /// Multiply key + //Add = 0x6B, /// Addition key + //Separator = 0x6C, /// Seperator key + //Subtract = 0x6D, /// Subtraction key + //Decimal = 0x6E, /// Decimal key + //Divide = 0x6F, /// Division key + F1 = SDLK_F1, /// Function 1 key + F2 = SDLK_F2, /// Function 2 key + F3 = SDLK_F3, /// Function 3 key + F4 = SDLK_F4, /// Function 4 key + F5 = SDLK_F5, /// Function 5 key + F6 = SDLK_F6, /// Function 6 key + F7 = SDLK_F7, /// Function 7 key + F8 = SDLK_F8, /// Function 8 key + F9 = SDLK_F9, /// Function 9 key + F10 = SDLK_F10, /// Function 10 key + F11 = SDLK_F11, /// Function 11 key + F12 = SDLK_F12, /// Function 12 key + F13 = SDLK_F13, /// Function 13 key + F14 = SDLK_F14, /// Function 14 key + F15 = SDLK_F15, /// Function 15 key + F16 = SDLK_F16, /// Function 16 key + F17 = SDLK_F17, /// Function 17 key + F18 = SDLK_F18, /// Function 18 key + F19 = SDLK_F19, /// Function 19 key + F20 = SDLK_F20, /// Function 20 key + F21 = SDLK_F21, /// Function 21 key + F22 = SDLK_F22, /// Function 22 key + F23 = SDLK_F23, /// Function 23 key + F24 = SDLK_F24, /// Function 24 key + //Unused = 0x88-0x8F, + NumLock = SDLK_NUMLOCKCLEAR, /// Num Lock key + ScrollLock = SDLK_SCROLLLOCK, /// Scroll Lock key + //OEM = 0x92-0x96, + //Unused = 0x97-0x9F, + ShiftLeft = SDLK_LSHIFT, /// Left shift key + ShiftRight = SDLK_LSHIFT, /// Right shift key + ControlLeft = SDLK_LCTRL, /// Left control key + ControlRight= SDLK_RCTRL, /// Right control key + AltLeft = SDLK_LALT, /// Left Alt key + AltRight = SDLK_RALT, /// Right Alt key + END, +} + unittest { import std.stdio; From fb3f9798a7287e98d7f66c8a2fd0612c9892f188 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 9 Sep 2014 09:19:05 -0400 Subject: [PATCH 030/141] Recompiled SoLoud --- lib/windows/soloud_dll_x86.lib | Bin 26624 -> 48016 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/windows/soloud_dll_x86.lib b/lib/windows/soloud_dll_x86.lib index fc37631d129ae5866f0cfad8618b6e9fe6a14931..c78c0b8ef94bd23583e7ef251d4633a131d42f10 100644 GIT binary patch literal 48016 zcmeHQd5~U3wLb*K7y%I@q9P6&*~CDW84wXkNFc}r#>o&7fyrdPFUf?-e8YS*A%qb2 z0Ab(4zK0O@J#2~*QF%Oy;t$HQEMAqBvMkE7{KK*=%kt^__3hiY`i@2I|!{uM`0Ikb)cn=yOFVKY09=s2u{^AF2|GiJ1R%+7uc056sbZWYWh!kD^Crvj^B2u(znxB1Jd7ujyuBD!O%@ribPdWdxgtKwI|Jbnj6_imq6y>C(+aimuFSL{ ziZ*s=x@H9F16}#1rmLqy4!WvM)8)fRH|VP<#( z;|aQFfu_5_S9Iq|IYD+OXvzMXdLJcHv}CiUzJC&BbUmJ+fq!XQiaaT*16xrId_{GX zo1*@sHPv9Fs2_1Esv)n6R=%&PZyMqSEnT5$m*XNqD|AlM({x^P=<<@ z!;gxVy{>8bY=l8)!5@kS@mtYZkSiL5uA)`@Y8skMq-YiVuV`p(PJh7@)Yy>|($oMA zBThwU&($>iF2bO*w`m%=izuT*@B}q?)pX8lM2c3!R#6i;ipI{=wE8{pL1VwwGzwfr z&A)0IU5PO0oK8(^W)dkn7x61vbDySj*C4D2wu;uiloRaMg4XS#={%HoM#%GdpbJsn ziY}O^X&vHFw7yHz1xUN1^>1oA|2IU6*8N%2`AZQ7T?k(*x@fAVhmpsOkj95WkKd8g zfp~%*eO=STe}o+L$Xl8oJDNz*qezdUN01IhTY-@gu(yI9gWnZBF-6n!e;~>TxX*)L z*sf{Y!9YEb^}CDdbVnGf11FXSZm2W-G#=rytk!)GN>fJ&iI~ z^c>oQqUWb5>g_#YVb{ssJ-zehFFLmSgsz^GyL+3B!Nypvcg+zU)Z2T~DV?3Z4qafC zv`Wu{Q%*Xucix&a^!Oc2Lmb@*VP)U4Kx-t#zy*Ol~ovXT&c0D zj~+KLI9ea+>Ko}>RmTqr6Hv%)QODA@A%)y_SzoQ5HV$g!){SQWz~CSnW;%+vn#}?9UCltjof;mxwvm|pqAM#=o_jH zN-u>JEOK`pB?{~=G^0hsb*}>fbU?-0cQu-$#|{n*FY51uqeL}UITmtjdHi5wY2TnJ z7uKd>$ECSdQ}UUWC$&~G71B=19m_zy0}!uwh7ss5a#hx61YIhV6!*G9i`OzwYV+dO zSPAFKtcBl3vaF)vFr7I|n`n04h^=+4(Aoq`9qNW}HRqvzo~skr6txTbT$)>{KFmbK zvgryOT|bjb(d`LTI8Yv5M$eE57X|d^uNoee(`nZz zm*)tb*zpC zyqdvmt&SUmp4S)i^q}{Bom32A&&xQZ-*b84QPu*pd`JyH4K{}{YpdZ~FB}+J*tcdL z>SN!KH@9_CAocv1=8U3Bk7a#msQT!PFeN{Zd5vK;Ge54cf3zW|olate+T4M&$NFmB z^=4zJZzx|!^@=@-v`$cJwkEV&lPWv|g&k{)!idQV z3(@X`jgS^rSl0B{n@v9}vuduW&^LpTnN+%!HOrB&P}rJ|EL%c&hC*6c9orbhV%sis z0|Jl5YfzRh6O9sO`p#tChUfRMXy`^N8+%CN@OaY?2pksD!~34FEX1`Li%Bun4QC)A zuq>W@pKm!P@oEdL=sct1h`?qep>W(_-_UZ5H`%tGERKkfvqi30d`8ACOzv#Xn2{sy zY%CiHCoLp#cm`NE(15^UIe4DBBU{+04G)ejmp<~?hQX5{xh6c==qom$InRWU1kn$M zBo5E-@N~A4Don`wzJM{4GfU9}25f}}vvxbffT=5Hc7Aslu=bT$9HM6oL?ASnwdwdw zhZ_+F*|wcV#g0HXhX9Td6uM5|%XwWRUM*%U72vhk<*45y*pM|zuwnJ9DMdMB(Xuro zvgvSM7UHmsl?6uXPK(rK3_Z4C#2R2+ZY8W~IT-{z z*7NQH!`g@@C9Q5L-LhxIz-2XPZ@6X1J!^@Z=b- z)^eJX!%$l#{VTj$Ex5UssM%V{FmoLga!-AY-9OMu1=nhc0U;o;tY~d4V)r#%YgXxU zCpo4}?AnQH=UWN|*Ve6lzM(61t^B&@+xj|g45AA9=0d@>^=hf(Br6M9I5jn3qomf# z)JvH(!#A34jm;y?SlEA+6_&A7z|=~O;d0b(cgAAF=GVgdD$|cLmI`2b*I6H0KDxry zaF|NR?`9=85BrtYCO7LW<)W~#V>MP7FCaUik<|~@+1$XDF^fd~wWhw3h=bKvnb@ouFb!cXYHrY8=!h8HiX1d|6@;x{ zor5v>Y9by{yMvJk9T9`A?m=TKj@Yp_;g+7UR0_=2G=%`35jpz2tr!5s{SfD@4>#wm z-zK6RIBmE08ARP@;)LEMI30R1QO~tR+d-WOtK-yvx}0dzO+?dh^6yBT%zhFygz#H9 zrT0Fb-FU9Mm1yomkb(Ba>Aa)v#YxpGaO(F`oEW|yrez_Wo`~kLMQ1rh@nGW}-Ll!Rg-(u)U0E zGM;UC-iS0#Mp`!Bh!fm5;5VLo;kgaz>4weUE+YCp($Ir6yobCVjP$JsZ!6NU57M~_ zY5(;dM1MzoOKv0j9cbz8z(<_F!}Cm|)_o z;Gf4355isey>u(=LEFHa@&wTzo`)@H`wJ+)Z75efx4lAi`pZZI!Yf}wKJa@7o_~1} z7@+l_1<=|5Rg@*-SPgpTN!&63-TWNzp9SVqi0>KHG5p?&=i^VKO@KEO&o<~x0p=|` z5iO=u=m%7zAJVB*ryo%-_0dvVLTAvKbULk|RWw9{G(cz3a#~5J(K70%2AxgAG(t@p zqfuH-=g_&dhSt(LI*-n$3urxENSDwRbR}I*m(m8hm@cD@bP-*J26#1HOV`m2bUocf zH`9%DE8RtR)17o1-9ek^cDjddp?hgAeTP0y$IxW@7|o$C&}^DXvuFk#Py5jn+MB*k z-=%$NADTvO^fmeleThCvU#6pJ7y1N!m5!x(^hG+7j-YSR;q)o`G<}Blq&;Xi+MRZ# zcIu$d(uuTyPN45mCoQDoXc6^LH=RT$Qx|=o4x`W0w`qU+CQYXU=^#3QzCj1mA#@ZS zN>k}`v=_~%`{_PjNTWK>rOpnup^Z-3UKc&~`XSAK(p#Pw^=uP?s{fd50 zzoh@9*XeC~ik_rr>1ld~UZ7X#ReG7W(M$9^y+}W%=jbQ26HWU6Qu#kuDm&vHK@h56E#@(Wy_lsHe1Gy(h~)aH5V%veoN4AHd9c`i z$ivZhfch}9^A^RFy~8TX%HcWX9O5dM*moKxPRl8xv@8>2{zfGt$RcJhBZ|lw*8(uM z0l|w6=lz0-!eJHm4$m<*+qK5hgbOpn&?^@cLJVS$kV#C1qTV1|<(&ycUE?x-Oo7S# zI>*Ga-Z7zD_Z)$#e-5jtg9R^}CCi=a!ezm2>TEO5csUCc`dLW%*K|0Rk?$5~47MSi zar{!SY+D3APx;?+h4UQ&_q-MOZnrY&b1QKjZn(zVCS15$GcrHtCs$%;-HM($*DHLi zugmD5dmJv;6PHwMX|QWH0Yi0^Ri`^EFManQk5tKm=OxE^9@dG*945_K*bd+a;4D9S zupKs``!Zn1(hpHE`QWRf$q!0eX!n3BboiNW#fY9=M{RIU`P&%HK?LVCy%h$ISOY|_ zQuS2`t6N+-a#;Dz2Ft<97iUECFuSy*0$DrJ)gf^Oz&#vk<8n@5@)MKA@!VJ$6biwT zD5S3I3ufGVg^H+GdX|!VKn1)DNyWT_DLIo5#&>+CVhb6EO&!DW9Lvr@`Gq9aMoi}v zJN{TSS`3{02rKxw48?ZTe6g5{`3hcVtSfUi zZsdm@&Gjka4Jnnr$mKy#Xj$kWWbm>9QWI+m5XH`s2O9_U-DaVKq1zL@qssJfJ3w49 ziF95{JJflBA8&pT20AZrgA-a?lA^WhS*{Udcw|Xd;lN!vc@A5@q$$Qp9kk=0^J0kC zKS$uqE&|-FvN(J>!*E4nj^T(*LpDxDb9JO%)plfTrcv;9C39o3vyDPYzZ5k<+5E%q zjvAL)PT@7nQbT3_>d7+YzCQ|H%%81pCbJHX2$YY7NVr)_xu=EHceYTF{uW}_QWz-*chn2c4%y z0k>&^aF}8`u2MnQNxiz^`&Y)tb*((VDjwYDFm+nL9tf%wl{}$?^qSR6u7&-EVruTN z*u8YMsF$&Wg@Q%_6_Ht#Kq? zO$^DbgYEVV$Fh6@Wd#OlJV$38K(>z~K$%PeGob-5PPRJxJ3LZHAYybRUUX)!gU4mK zA|k`q!<;Tf!$Ztss0+wti(tk^Xnn}U!Ir@_c)uOMkF^jMO}LdX6~Co8V%}ODfoL&> z#Ay@mW|L08;)r6f8&6h+os!IURd|VJED=w}b2p@Pbe8QOVq}|Bj(V*0v$!&$DP7YU z`Vw32Ru(LDM;t0~D~=Vn)d-ihmHP#4WW1COR}`^kJLQ{C>Ag*^+?DxWmU#)mxok+y zBhrQJ?p`q)v-u^M&G?sPqEQ96!&tojrkE$rR&5^F%>28sk)WpJ#X;aalPY4fKw`$2 zK=92nDfPF^qz2nKlR{m_#ZEy{b#*ZTov%)%xvC72JIB5w5L@W#x?+pXH3@?{>TIz| zX)EUfz+JIQb9d8C%8IQwPZ0UEh&$WM%Qo;?A+sgNVhwG~Nrmy;g$`YNF80jQ$V$rLID7Ug{{A?#2{XF|}}XB8}3~ z2+U3kshFP@d^tlc1fhE(&de2KcYaKi7lY-ClCT0yG0aw}E>A0RSCW>CiWn?Cpf$WhfMa#VB<`B`I`bg(=j+B4rA^RGCN=tRv&4SZur&Wg*v>Fm*R!t)3_? zyCG{;5=EysL<5D!1+2KVC{|FpG*U!bnkXEt5G@uh4i<ff%Q-MaT&IM6@RXf~FOwjJ1gP+R8-C!Lr{#eYg!8L9{f zXHnHJm4=UJzc>(5(%)D$j3n>Y{a^I&e;Y_;rT(cjP9l@@V{qhGaaI^kmPduPv*FBE zI$&6xcFR%xuc`m?e=07VRL?`|F$pJn@nz=^xuIWWt(noV(tDdc?rQV(af1~pM2Meg2l_%l&McXttesPf*7V0|6l{ItRHRy;gM<=bGYUF^Y7i?x)1JsBon{c)TR;oSu8XE`ogS56eSBhoStMt-L2{bui6r{j1A+WGhAfuC9H?~9m#S5JF_Kks1Xi}#75%?S6lUjf?Q z4w~5&5OAgYqYkr#6D9c#;C;ct3+>`g6nl1J4)VnUTWvK>6e-pJeMuoXCw=n0NCC-% zty@TYByVbMzmGtSOdm^^WqV?5`Le*QZsy;f=>7JMq57SD`P@co?tbv_R}`*2ZWS)l z@`#C}pp~k=>i=s9!TY z?8;YBk$zb1R?qa%t6fQ@YT7IhyTa8}B+qJxZnnU!XhoG6d)ftJRjaC0FWJE`t61Hn z_QMZXXwDJviS~=Bef}d1R#jt7q~z2d^|uUG_9@>9=PJ?-lZU zf8SO}+4=79tcO#$^8{{cx>FiAQiIiA-+YeSYN}J-*NK_@aU456(J76b+EF;3BgdyXHx5CtZ#rJ)@xLeC3C;Iko2RU@-Zo;{al&N|fxJY2LyAT4H2V2+SR1579xayV# zkH376kUHUYioi3c@Vkl&h!aImy~A28(DUmQ0+I*E;or#mLA_7^frE%6N$k!f$N3O` zPSoX7Ij(mbbE4R(eZL=aZ1=K!$f?owM;tlTbW8VF zsW6wcfrBOftHw&ohi}OADHFzsT2(CN*v{oRj#9p7OriD*)KSb6 zS7o0zoG@x)&$h-<&HZfw$%EtYZe#>d@Am5gQC|$_2p__;iJ9Uuju<+ATe{7p_5qhW zc-dukkvSe5hc^@b-U@-`Z>y9=OO0g%E?RRj{+he~8|4e|r`qt>+&Pp8jw7FuHK{s_ zyOJZ@d;Jr{O!c~FMKJXT0|apC8q^Wl9Xt%V9dwY3yZ;r>98$C4RU!P3Z2mA5La$&% zKRnWo)OEK;2($W8Co$3vhf)w;2$ZgCsov^r2RC$KfYsZ)@v1zu&oO_b<4VN5@xY+#Z(`1 z;gO4AYphhOT*t7m-(lX6;0rMVwshS|-Q7DshFk0ac*gJTjTrHxqJ#D z{e-$Zc|kM<<`dEr^?$0|FN~q%OFR?BP0gS#is2UDu$d@&D%TfFbm!|q6UFU_^djoa z)g=L3@m(ST&x5Vocxu*sX&9Y<@Q4G7Ixr6WL|eNoj9>Bl&{VD45KcjreNANKQumZE zZ-rh(PZQZ$Q18I6h~QV%&!kQ|UKz&zNLu?wj?KP>C8~S*o;@<-RCm;_;pZmLTV|p<@nGxTGj-k74vFV{q>z_d z`Fu}2d~w2BktvKw8%s+ zbg#s%?$m8!rgC2lwTd}-VorF!#I5$^Z36iL54qB_w}~B&2PLxETQZ~F#OD-|9$&3` zHcRx1*PE&S@ga#_%5Zi1v%O97OaD8A{}s>Q3E@vH2VAE9DWi60645g?9J4oM2*!j*(1epR`gs<=ocPO4nwSxKrA(mgXh z^XvKM+jGT_#QY(|bkDD6dV0EhdS*YK+dy;^(FSUe`)9nDc3<7QYq{OIwL2Uvv=>H) zdi_y%X>NY0+a7gk^?DjV*q}Xg6PVTw2mQfvXKv-?S4_luPt(i9KgauMPZ7G)9gda; zchl+(ZUB4B0|;C&g2`x=A&k$XeMR}h?&wH+seO7#t2et5oLe42Vk z_e_UYQ9r&7Fr0n@r|M^#Hmm%Z&cXg*{w-aGx!et8OB_ff0a~G-8JgdZ=g@Qoe|Cjd zU*RNdtxA|(0U5=tn^Xf zG3YmRlR@VCjU>Q~`i(?V)VMte*I$71^*3{m>(874YP^lM%6xg-&vXuqM%{(w_NX^l zpw+9~q|b4a&Z#iUa_=}$oxejkIOz9#o$ivIzaas#o4+CIpwske9PG>Ri6YRxG9t)u z_LY&1l<^MQ7WH#YZ#Zf%%y+Npy50I3r=jghLxv7g>JXxq(uAzM!Qx`SyL6~MKN_&o zs`8LtmWLc>VnO71H|>n`yOHPDUFa^|%JUob#JkP9Deg*B%vnI{1e`R{@lM(vE&iwDC+@0L#TQ#|5J$5`Qr}e`=6rZR#&8 zBtR_mGtkZ;##?C%fM}>+eVNn4^jwt&5=uQY5#mn)gI$YeUFuIuRFF~b9i@nWC?SZ; zQ~yw=gN!;CGKWpG*Nz{MVvVhD9I7zD5*P(uU;UtFzd$3XaDp5g7xpx#W z-cILOgt$hpa*Mugu1E$6HT}H^w?1b4x<`wqBDog!Il?D<@Ju?xq-hh!N8uPOf6=alqM=26-4i7qu{pFMKh^+C( zwgYC~BcicBIDgiDQ5l*)X9Pg3^ifF3@3mWh(B`9w=J(hNNS0e+qC*?+q8-|km6_$d z2c3!UoU7viIrS(;rtBw!mU3X-Pen3Fs_E~=$bKpUi1$%{SHl1@YB9`YSc{TR7&y(| zLQbstL_H5korDwwSLKQ_d-O@UMWY626;o`_{7`z=zjC&+ut_LLYvuC=GcqH0e2k^M7F#k=WrKCF;HMxkGI zM&h3VB<9rWpQ|*GQ0ke9K>y@(-rPTBd2jSj)!bKePlBOV_3L0{dRAPiYGvB`yOqUQcHV_s|1e==RRKx!42SUX;Y}#f+(_2Tb&U$r^}<#_wA>X)iFdB21Sd`PHQr?eK&|vqV2iiZ zObA(U)OcLO08(l(q9C1*m1ja)^w%H{ z8EWJqOVwX<{7-Os)Jye*dLEEE2`Nle^0kDO2Sd%*>Nr4FJ&IAOwGRkf1^Y-;kOTIS z=t+%|Z|i6^*lE6P+W|B00V9t7g7;$#ZpL3E0w8+-lSpxZ;;;QUTmeV@b!-9*;7bFN z`ovLxeb(-Djt_eC-D87mmj=sR4bu8VnGVQx2uVzI=uV$rUc7RO`ZVo;zcGwJdjPJ~ z^OPE{oV1>2ngK222QVI`^9NxZ4$rA1C?xuWG6TriZiEAdmB#YY_&eR+LXV?IHh$j> z*gF2eZxKPiF=A%=4efxa`qdr)>GrdqZlJ&7$I->ETn*mfQn}~O{0h2QB;OM;+*63v7Q8<0)C{{;75AWB=~1m&2hd~agPNu z|C~sGto}I>6Kqt`Sk9|a1M2?cc{QT|dbO9+3B*U1>!0jo@iDXmmc~cz5w*+fC-n$F z3ZGrYdPHgjB*P0ZX}&366FfPHX8yo81E%_ez;98(Klg^m`MTHV;MZ~aMy`7^|6FAO zIqILQOt5ZpzpnZiVk(#UO9qj%fJ=NqMzJr>2>cO3%${Bx@q4MvA5}O&lKP_x4@^e( z=lOJQn9pE1-|O>3h-%V!i}MlZsgI~*1nFyH>YO3}im)bT<@r~U3nXj)RphgC7o&vr zj6GbG%GMK!AWhd3$wtWd0y;m}Z^gmV>TOQL`zso*u!8LG0avvgw;$$%am?yys54pl*TH)Sg!Tm>&SXsZUlUm^Xf?|H8vTs1FE!A>R0A7&Y1p^VG|M*(70`9OhMt6gKT?jPt}>PRBP0U4`XeMKaPfC3o)5d-w^a6{Gy>lGu!4@) zYQozb*te^YYlZXxpY<~P&gdXT?K|Tz16O~-@4e%g_&lrfVu=IZdr#&A`D-D<#K-&T zyvev?Vn>}jKVRLsnO7RAvE#K--6$YlTGYX?=ijkr^@<`F%w6MUk*~S}b?bdwwccqE zZ^O56#r0+c(6f59y7?aO^3&~}Lq4eUVfojXJCfBbAFN}9F=#$m#~M|U?=L^G z{2rvVze=1i0<*tLynYC|y?M^GXUq1MbAep5zjD4fZ8dk2-?LQLKgk#Gal|M=8y<2sDNC!zUKjZ*0 zaf&5*HRlN)H=gV!$qNWzmnsnQImRp16MZwFYd#nFEvUQS_Zg1O+Y9;STvk7} zWWd+@v1JI#f_kN+m+F;D08Gutl@wJE`MA;!^!pUwb0^>7(o&`Ys^;U^)2f4@{vceF z>!B46kfrs93QwGhTT*L3rkYvUk4OhuV6VtwC3y>y_hv~)mE(1KZ#IDmBu~W3RO{y} z?=hmiK}9pKSF+v`6(p8>M^QF^DEz!3z2{5AD6oM<$R7%fnUbNN$um$-kkvCI1*B*_ zGtxXTo>$yCD62naug%u$q=YvrMV$x#8|tId)$N_EJ{sC#Y+4`H9srE?D|pMD-oQus zYCN%Yz>oH8IZ6|N^XKwnhl_RmqE}>A>J^3xvebSIJxOx@l`lT$PsQiau|A8OLdOM!(YfU>KZVZUp10dafv+u{2l09dR_swMnkgz>Ss9=Dov|j-(z0iv1 z{Q?yvZAD43cNF97r+^@NUX0g8I>^{ol2IvL`1#0vCg5c+wqm`!js>Jnz=_lI`458G zlSEM-vee2$rewb4@^_G@^#S$tkiSph0;zjYTNSi4QKwz@FLM74$oa`7=Fhb}AbS#0 zkeu5O$G`ZKzmokVI><5hlQ=-FVRk$}xvz?2*UU2d_lyEEs=eF{-2GbY6<>74`?Z_| zh?~NBSR@}`{T;YFW`q7F3v{<=Z}#6rL7h^0Q6K={J&#_qz&(W&(N(gG1= z6#JqSiO&hb{{lwW%eDh*-U9$-Kc;>acOTD}^*kVF5>k*U@hQWKPCvefs$l?0wHPq9 z=+A55B!sActz`k3J8PN1a>c)9d|3$5dfX%~kUAMHpRV)oIkE`_u^u>yYm$6}R+Z29 zr5SQ1D8%~M8jLWCH8FJ{lHX^rd5F>a;6yf%y#}62_AX2685uAHj5>QuEFgCRPLgT; z4ewtKIeH&r2IGk!1N=?uo6tF)@p;TZXef#2u@V&|lzT@J)}P4%BE=s-=61jYf985b zG#)SiUWWU{NTI)%No|0GoB>1Pm+;2Opyw%Q1O&qi!$|Rq-*ZS;hy;3GFwKCO@mo~+ z{f%_=p8o<@={$2zTL2|-833K1^grA^o#L}Xa3i3&`6;gf3NsA$G2we50-VPckRbL^ zp(lqL;#;InzG-xe6BJ1 zUHrc`wrNie5b!#Cb5msbIw({8@kicm-qPHt?f$)Aze!O#PX+HIPPD2NUvccUB0Bd; zb<~fwcF*aFOsYqA|NLiby^A#d(|O~mjqbl&Qwn$4jtAz-B=eEYH8ls2UFjNtz1BD`i;}mL|EWy?Cy%Ra-={ z`riD)%pT%9;TxLY!=t#5Hp#xV@D*6Qx|g)#=-ifASZv8&h&2FHOMIrqb1@F;%Tu%& z*3wUY@AtEi|2rGF*ms+z2l_-0(ydoLOtbXDw-bHjkLgWBk287SGh1N)hgJSOe>5_# zr(`_;O=r5FCCd+$k2iQ<$ghr_`Q~Bn!;MXm8qDC4M%tCUj`+KhR&xuiaCk9&dy{r) zE5At1-s#@eq%|LxzN<;m*Ti>+c%OKGlSk<-Qw({gGrRIfO}2Es5#WbS&o+tY8E;?Q zsQGn+-Vq;eC2n^954Vz!GS%`Y*zW|}$Xw{Be)#rq>Cy#6CwOzR_a}OlSi?KzkK3-7 zKm9-No&2@UGmW2DXEnR>&c@ET&be>=MB2Ae`+WQQp(cAc)o6GRca(MaSJrEDEQ!B! zxWC2g2)iz~wtwPP5bcJn{QXnxLy~`$)=Q?aMPl+jKYYEbZvQ|0``mkJo<2ZBHAc7Pc5smXt?nC*cXGrFU&qTg z_&vlsInq+{_YPwF2<_eyR*6D9kj?1qVtA^N{5!{k%w)DVlZ`Qz{l-O2!HD^vd#i9+ zlOt?u^O@Y6n$ahV^?b%5`L*@d`o)&y7``P~^p_?31M5%^_jSn^p*>BqG37ElAO4j6 z<5N7R#oNg16Hy7~JkWST^=*#Gh^g#Euob%nqi_d}ov-D#6 zIRBMXLZaU#+DlJYKHWM??DI?C$@>&r1bh=F<*u_Un;?4&n*EyO331i(Uw5u+#(Z2> z8GQaLtq+*#JOcTizEyTc@Qs9Fe8Yj!cbYN&J4*hR?h486E3sW)t{rN{{DXUE_W6dE z&(rPt&#ruOiu00ejq`Bz`nq+J)%d~xa}&K)Kp*kQFL(n{k7(vKbcjAp(;uRHX(zja zC(;*{FNWNn7uSF9_@%^_UHgf?FNv){oM3(VP5xbi582$&5HFj)RP)mf;qa9 zTN}iAg&I8O*q6k;?$`Sa-sPz+WU?Ek zI1lDEcKOBwQ`J3<6`~_Q+QlxJ&o$i0AAl!0__-Y~OjpPsyW|hLV?WWI_`UFbocHVL zPLkr+vcC-eJgDG)&I`adgf;qP?irGAy1bFRx3dm@)pk$VL*aDH4#3|G{=^hpli5Q- z>hk}+E}g=D%>KBF=stG$f5F54y;+*SoBrBQU}67nT_zUszVAMH?D+{FFdj(-sOD>u z-;_!K?0g?#zb)}zV?;2H{~*p0wavL>6Z^JvoUl~fMf)0@Cq_@9;r8bm@!Tj`rw{-C zCI9P!xRsmnPvK9H#;;j7+bt(euSt@Ep~G4S&N z1m1mpP9jb8JbXaJssBTZ&&}d(yv~sH$dt=AJSC4ZkDJZXzxcPO=}&pxJJ-?gzhcDs zpdy2e?q77?uLmIm8svJj)eU$&J8tN`q5##n-D z?|wV`_NI*(s^EC689tYK%Q~BvukV&<5_1c0nx78m)G+3IHIB%9zG{}sZ_ppipVRly zx9H$80ekE#5B>dJ7t=rAOE3Qjy@2Q`ZaX>0fBfR}YyH12HirrzducYt?u#_{_ZAZm zbXST$fXLvNl}&Apk3nA8;C`_3KK#B?R^6>?P}#iJmE1YPeX#9xL(Tx=8{qqGOAXHO zgTL@lpJ}WMEv)QE!6IU9!mrUo%~%IEQ+u>&>xETom|gkzCZ0mIRs?y?zLsP>(JJ^< zqi@HT-I*j%c!caPekVJ7=+>KE`Bp2QU)b*Cz0vfPiZ63XJSlV~?fTv(ZZ$?6u^hiC)HGu>h~n@C~acQXN{N z1-gOnz_}$D_z7zV(ZK&C%P`drZd*K~6)Td?b@|hV@kB3drP#zgmDuz_sV_%gZ|C=g Xa5Lc7IAvB(PO-l=*^<%P%+&t?O0bQN From e82d614f29484fb535eb14d222332a38d4b0f934 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 9 Sep 2014 09:23:45 -0400 Subject: [PATCH 031/141] Updated SoLoud lib to OMF --- lib/windows/soloud_dll_x86.lib | Bin 48016 -> 26624 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/windows/soloud_dll_x86.lib b/lib/windows/soloud_dll_x86.lib index c78c0b8ef94bd23583e7ef251d4633a131d42f10..fc37631d129ae5866f0cfad8618b6e9fe6a14931 100644 GIT binary patch literal 26624 zcmdU2dyt&Paqr!|KR`l4(h0pKKo~m?7)YJLHuxpP2`~r*62gV;oL9GtwB^<9al02E zCUI?S>>Q3E@vH2VAE9DWi60645g?9J4oM2*!j*(1epR`gs<=ocPO4nwSxKrA(mgXh z^XvKM+jGT_#QY(|bkDD6dV0EhdS*YK+dy;^(FSUe`)9nDc3<7QYq{OIwL2Uvv=>H) zdi_y%X>NY0+a7gk^?DjV*q}Xg6PVTw2mQfvXKv-?S4_luPt(i9KgauMPZ7G)9gda; zchl+(ZUB4B0|;C&g2`x=A&k$XeMR}h?&wH+seO7#t2et5oLe42Vk z_e_UYQ9r&7Fr0n@r|M^#Hmm%Z&cXg*{w-aGx!et8OB_ff0a~G-8JgdZ=g@Qoe|Cjd zU*RNdtxA|(0U5=tn^Xf zG3YmRlR@VCjU>Q~`i(?V)VMte*I$71^*3{m>(874YP^lM%6xg-&vXuqM%{(w_NX^l zpw+9~q|b4a&Z#iUa_=}$oxejkIOz9#o$ivIzaas#o4+CIpwske9PG>Ri6YRxG9t)u z_LY&1l<^MQ7WH#YZ#Zf%%y+Npy50I3r=jghLxv7g>JXxq(uAzM!Qx`SyL6~MKN_&o zs`8LtmWLc>VnO71H|>n`yOHPDUFa^|%JUob#JkP9Deg*B%vnI{1e`R{@lM(vE&iwDC+@0L#TQ#|5J$5`Qr}e`=6rZR#&8 zBtR_mGtkZ;##?C%fM}>+eVNn4^jwt&5=uQY5#mn)gI$YeUFuIuRFF~b9i@nWC?SZ; zQ~yw=gN!;CGKWpG*Nz{MVvVhD9I7zD5*P(uU;UtFzd$3XaDp5g7xpx#W z-cILOgt$hpa*Mugu1E$6HT}H^w?1b4x<`wqBDog!Il?D<@Ju?xq-hh!N8uPOf6=alqM=26-4i7qu{pFMKh^+C( zwgYC~BcicBIDgiDQ5l*)X9Pg3^ifF3@3mWh(B`9w=J(hNNS0e+qC*?+q8-|km6_$d z2c3!UoU7viIrS(;rtBw!mU3X-Pen3Fs_E~=$bKpUi1$%{SHl1@YB9`YSc{TR7&y(| zLQbstL_H5korDwwSLKQ_d-O@UMWY626;o`_{7`z=zjC&+ut_LLYvuC=GcqH0e2k^M7F#k=WrKCF;HMxkGI zM&h3VB<9rWpQ|*GQ0ke9K>y@(-rPTBd2jSj)!bKePlBOV_3L0{dRAPiYGvB`yOqUQcHV_s|1e==RRKx!42SUX;Y}#f+(_2Tb&U$r^}<#_wA>X)iFdB21Sd`PHQr?eK&|vqV2iiZ zObA(U)OcLO08(l(q9C1*m1ja)^w%H{ z8EWJqOVwX<{7-Os)Jye*dLEEE2`Nle^0kDO2Sd%*>Nr4FJ&IAOwGRkf1^Y-;kOTIS z=t+%|Z|i6^*lE6P+W|B00V9t7g7;$#ZpL3E0w8+-lSpxZ;;;QUTmeV@b!-9*;7bFN z`ovLxeb(-Djt_eC-D87mmj=sR4bu8VnGVQx2uVzI=uV$rUc7RO`ZVo;zcGwJdjPJ~ z^OPE{oV1>2ngK222QVI`^9NxZ4$rA1C?xuWG6TriZiEAdmB#YY_&eR+LXV?IHh$j> z*gF2eZxKPiF=A%=4efxa`qdr)>GrdqZlJ&7$I->ETn*mfQn}~O{0h2QB;OM;+*63v7Q8<0)C{{;75AWB=~1m&2hd~agPNu z|C~sGto}I>6Kqt`Sk9|a1M2?cc{QT|dbO9+3B*U1>!0jo@iDXmmc~cz5w*+fC-n$F z3ZGrYdPHgjB*P0ZX}&366FfPHX8yo81E%_ez;98(Klg^m`MTHV;MZ~aMy`7^|6FAO zIqILQOt5ZpzpnZiVk(#UO9qj%fJ=NqMzJr>2>cO3%${Bx@q4MvA5}O&lKP_x4@^e( z=lOJQn9pE1-|O>3h-%V!i}MlZsgI~*1nFyH>YO3}im)bT<@r~U3nXj)RphgC7o&vr zj6GbG%GMK!AWhd3$wtWd0y;m}Z^gmV>TOQL`zso*u!8LG0avvgw;$$%am?yys54pl*TH)Sg!Tm>&SXsZUlUm^Xf?|H8vTs1FE!A>R0A7&Y1p^VG|M*(70`9OhMt6gKT?jPt}>PRBP0U4`XeMKaPfC3o)5d-w^a6{Gy>lGu!4@) zYQozb*te^YYlZXxpY<~P&gdXT?K|Tz16O~-@4e%g_&lrfVu=IZdr#&A`D-D<#K-&T zyvev?Vn>}jKVRLsnO7RAvE#K--6$YlTGYX?=ijkr^@<`F%w6MUk*~S}b?bdwwccqE zZ^O56#r0+c(6f59y7?aO^3&~}Lq4eUVfojXJCfBbAFN}9F=#$m#~M|U?=L^G z{2rvVze=1i0<*tLynYC|y?M^GXUq1MbAep5zjD4fZ8dk2-?LQLKgk#Gal|M=8y<2sDNC!zUKjZ*0 zaf&5*HRlN)H=gV!$qNWzmnsnQImRp16MZwFYd#nFEvUQS_Zg1O+Y9;STvk7} zWWd+@v1JI#f_kN+m+F;D08Gutl@wJE`MA;!^!pUwb0^>7(o&`Ys^;U^)2f4@{vceF z>!B46kfrs93QwGhTT*L3rkYvUk4OhuV6VtwC3y>y_hv~)mE(1KZ#IDmBu~W3RO{y} z?=hmiK}9pKSF+v`6(p8>M^QF^DEz!3z2{5AD6oM<$R7%fnUbNN$um$-kkvCI1*B*_ zGtxXTo>$yCD62naug%u$q=YvrMV$x#8|tId)$N_EJ{sC#Y+4`H9srE?D|pMD-oQus zYCN%Yz>oH8IZ6|N^XKwnhl_RmqE}>A>J^3xvebSIJxOx@l`lT$PsQiau|A8OLdOM!(YfU>KZVZUp10dafv+u{2l09dR_swMnkgz>Ss9=Dov|j-(z0iv1 z{Q?yvZAD43cNF97r+^@NUX0g8I>^{ol2IvL`1#0vCg5c+wqm`!js>Jnz=_lI`458G zlSEM-vee2$rewb4@^_G@^#S$tkiSph0;zjYTNSi4QKwz@FLM74$oa`7=Fhb}AbS#0 zkeu5O$G`ZKzmokVI><5hlQ=-FVRk$}xvz?2*UU2d_lyEEs=eF{-2GbY6<>74`?Z_| zh?~NBSR@}`{T;YFW`q7F3v{<=Z}#6rL7h^0Q6K={J&#_qz&(W&(N(gG1= z6#JqSiO&hb{{lwW%eDh*-U9$-Kc;>acOTD}^*kVF5>k*U@hQWKPCvefs$l?0wHPq9 z=+A55B!sActz`k3J8PN1a>c)9d|3$5dfX%~kUAMHpRV)oIkE`_u^u>yYm$6}R+Z29 zr5SQ1D8%~M8jLWCH8FJ{lHX^rd5F>a;6yf%y#}62_AX2685uAHj5>QuEFgCRPLgT; z4ewtKIeH&r2IGk!1N=?uo6tF)@p;TZXef#2u@V&|lzT@J)}P4%BE=s-=61jYf985b zG#)SiUWWU{NTI)%No|0GoB>1Pm+;2Opyw%Q1O&qi!$|Rq-*ZS;hy;3GFwKCO@mo~+ z{f%_=p8o<@={$2zTL2|-833K1^grA^o#L}Xa3i3&`6;gf3NsA$G2we50-VPckRbL^ zp(lqL;#;InzG-xe6BJ1 zUHrc`wrNie5b!#Cb5msbIw({8@kicm-qPHt?f$)Aze!O#PX+HIPPD2NUvccUB0Bd; zb<~fwcF*aFOsYqA|NLiby^A#d(|O~mjqbl&Qwn$4jtAz-B=eEYH8ls2UFjNtz1BD`i;}mL|EWy?Cy%Ra-={ z`riD)%pT%9;TxLY!=t#5Hp#xV@D*6Qx|g)#=-ifASZv8&h&2FHOMIrqb1@F;%Tu%& z*3wUY@AtEi|2rGF*ms+z2l_-0(ydoLOtbXDw-bHjkLgWBk287SGh1N)hgJSOe>5_# zr(`_;O=r5FCCd+$k2iQ<$ghr_`Q~Bn!;MXm8qDC4M%tCUj`+KhR&xuiaCk9&dy{r) zE5At1-s#@eq%|LxzN<;m*Ti>+c%OKGlSk<-Qw({gGrRIfO}2Es5#WbS&o+tY8E;?Q zsQGn+-Vq;eC2n^954Vz!GS%`Y*zW|}$Xw{Be)#rq>Cy#6CwOzR_a}OlSi?KzkK3-7 zKm9-No&2@UGmW2DXEnR>&c@ET&be>=MB2Ae`+WQQp(cAc)o6GRca(MaSJrEDEQ!B! zxWC2g2)iz~wtwPP5bcJn{QXnxLy~`$)=Q?aMPl+jKYYEbZvQ|0``mkJo<2ZBHAc7Pc5smXt?nC*cXGrFU&qTg z_&vlsInq+{_YPwF2<_eyR*6D9kj?1qVtA^N{5!{k%w)DVlZ`Qz{l-O2!HD^vd#i9+ zlOt?u^O@Y6n$ahV^?b%5`L*@d`o)&y7``P~^p_?31M5%^_jSn^p*>BqG37ElAO4j6 z<5N7R#oNg16Hy7~JkWST^=*#Gh^g#Euob%nqi_d}ov-D#6 zIRBMXLZaU#+DlJYKHWM??DI?C$@>&r1bh=F<*u_Un;?4&n*EyO331i(Uw5u+#(Z2> z8GQaLtq+*#JOcTizEyTc@Qs9Fe8Yj!cbYN&J4*hR?h486E3sW)t{rN{{DXUE_W6dE z&(rPt&#ruOiu00ejq`Bz`nq+J)%d~xa}&K)Kp*kQFL(n{k7(vKbcjAp(;uRHX(zja zC(;*{FNWNn7uSF9_@%^_UHgf?FNv){oM3(VP5xbi582$&5HFj)RP)mf;qa9 zTN}iAg&I8O*q6k;?$`Sa-sPz+WU?Ek zI1lDEcKOBwQ`J3<6`~_Q+QlxJ&o$i0AAl!0__-Y~OjpPsyW|hLV?WWI_`UFbocHVL zPLkr+vcC-eJgDG)&I`adgf;qP?irGAy1bFRx3dm@)pk$VL*aDH4#3|G{=^hpli5Q- z>hk}+E}g=D%>KBF=stG$f5F54y;+*SoBrBQU}67nT_zUszVAMH?D+{FFdj(-sOD>u z-;_!K?0g?#zb)}zV?;2H{~*p0wavL>6Z^JvoUl~fMf)0@Cq_@9;r8bm@!Tj`rw{-C zCI9P!xRsmnPvK9H#;;j7+bt(euSt@Ep~G4S&N z1m1mpP9jb8JbXaJssBTZ&&}d(yv~sH$dt=AJSC4ZkDJZXzxcPO=}&pxJJ-?gzhcDs zpdy2e?q77?uLmIm8svJj)eU$&J8tN`q5##n-D z?|wV`_NI*(s^EC689tYK%Q~BvukV&<5_1c0nx78m)G+3IHIB%9zG{}sZ_ppipVRly zx9H$80ekE#5B>dJ7t=rAOE3Qjy@2Q`ZaX>0fBfR}YyH12HirrzducYt?u#_{_ZAZm zbXST$fXLvNl}&Apk3nA8;C`_3KK#B?R^6>?P}#iJmE1YPeX#9xL(Tx=8{qqGOAXHO zgTL@lpJ}WMEv)QE!6IU9!mrUo%~%IEQ+u>&>xETom|gkzCZ0mIRs?y?zLsP>(JJ^< zqi@HT-I*j%c!caPekVJ7=+>KE`Bp2QU)b*Cz0vfPiZ63XJSlV~?fTv(ZZ$?6u^hiC)HGu>h~n@C~acQXN{N z1-gOnz_}$D_z7zV(ZK&C%P`drZd*K~6)Td?b@|hV@kB3drP#zgmDuz_sV_%gZ|C=g Xa5Lc7IAvB(PO-l=*^<%P%+&t?O0bQN literal 48016 zcmeHQd5~U3wLb*K7y%I@q9P6&*~CDW84wXkNFc}r#>o&7fyrdPFUf?-e8YS*A%qb2 z0Ab(4zK0O@J#2~*QF%Oy;t$HQEMAqBvMkE7{KK*=%kt^__3hiY`i@2I|!{uM`0Ikb)cn=yOFVKY09=s2u{^AF2|GiJ1R%+7uc056sbZWYWh!kD^Crvj^B2u(znxB1Jd7ujyuBD!O%@ribPdWdxgtKwI|Jbnj6_imq6y>C(+aimuFSL{ ziZ*s=x@H9F16}#1rmLqy4!WvM)8)fRH|VP<#( z;|aQFfu_5_S9Iq|IYD+OXvzMXdLJcHv}CiUzJC&BbUmJ+fq!XQiaaT*16xrId_{GX zo1*@sHPv9Fs2_1Esv)n6R=%&PZyMqSEnT5$m*XNqD|AlM({x^P=<<@ z!;gxVy{>8bY=l8)!5@kS@mtYZkSiL5uA)`@Y8skMq-YiVuV`p(PJh7@)Yy>|($oMA zBThwU&($>iF2bO*w`m%=izuT*@B}q?)pX8lM2c3!R#6i;ipI{=wE8{pL1VwwGzwfr z&A)0IU5PO0oK8(^W)dkn7x61vbDySj*C4D2wu;uiloRaMg4XS#={%HoM#%GdpbJsn ziY}O^X&vHFw7yHz1xUN1^>1oA|2IU6*8N%2`AZQ7T?k(*x@fAVhmpsOkj95WkKd8g zfp~%*eO=STe}o+L$Xl8oJDNz*qezdUN01IhTY-@gu(yI9gWnZBF-6n!e;~>TxX*)L z*sf{Y!9YEb^}CDdbVnGf11FXSZm2W-G#=rytk!)GN>fJ&iI~ z^c>oQqUWb5>g_#YVb{ssJ-zehFFLmSgsz^GyL+3B!Nypvcg+zU)Z2T~DV?3Z4qafC zv`Wu{Q%*Xucix&a^!Oc2Lmb@*VP)U4Kx-t#zy*Ol~ovXT&c0D zj~+KLI9ea+>Ko}>RmTqr6Hv%)QODA@A%)y_SzoQ5HV$g!){SQWz~CSnW;%+vn#}?9UCltjof;mxwvm|pqAM#=o_jH zN-u>JEOK`pB?{~=G^0hsb*}>fbU?-0cQu-$#|{n*FY51uqeL}UITmtjdHi5wY2TnJ z7uKd>$ECSdQ}UUWC$&~G71B=19m_zy0}!uwh7ss5a#hx61YIhV6!*G9i`OzwYV+dO zSPAFKtcBl3vaF)vFr7I|n`n04h^=+4(Aoq`9qNW}HRqvzo~skr6txTbT$)>{KFmbK zvgryOT|bjb(d`LTI8Yv5M$eE57X|d^uNoee(`nZz zm*)tb*zpC zyqdvmt&SUmp4S)i^q}{Bom32A&&xQZ-*b84QPu*pd`JyH4K{}{YpdZ~FB}+J*tcdL z>SN!KH@9_CAocv1=8U3Bk7a#msQT!PFeN{Zd5vK;Ge54cf3zW|olate+T4M&$NFmB z^=4zJZzx|!^@=@-v`$cJwkEV&lPWv|g&k{)!idQV z3(@X`jgS^rSl0B{n@v9}vuduW&^LpTnN+%!HOrB&P}rJ|EL%c&hC*6c9orbhV%sis z0|Jl5YfzRh6O9sO`p#tChUfRMXy`^N8+%CN@OaY?2pksD!~34FEX1`Li%Bun4QC)A zuq>W@pKm!P@oEdL=sct1h`?qep>W(_-_UZ5H`%tGERKkfvqi30d`8ACOzv#Xn2{sy zY%CiHCoLp#cm`NE(15^UIe4DBBU{+04G)ejmp<~?hQX5{xh6c==qom$InRWU1kn$M zBo5E-@N~A4Don`wzJM{4GfU9}25f}}vvxbffT=5Hc7Aslu=bT$9HM6oL?ASnwdwdw zhZ_+F*|wcV#g0HXhX9Td6uM5|%XwWRUM*%U72vhk<*45y*pM|zuwnJ9DMdMB(Xuro zvgvSM7UHmsl?6uXPK(rK3_Z4C#2R2+ZY8W~IT-{z z*7NQH!`g@@C9Q5L-LhxIz-2XPZ@6X1J!^@Z=b- z)^eJX!%$l#{VTj$Ex5UssM%V{FmoLga!-AY-9OMu1=nhc0U;o;tY~d4V)r#%YgXxU zCpo4}?AnQH=UWN|*Ve6lzM(61t^B&@+xj|g45AA9=0d@>^=hf(Br6M9I5jn3qomf# z)JvH(!#A34jm;y?SlEA+6_&A7z|=~O;d0b(cgAAF=GVgdD$|cLmI`2b*I6H0KDxry zaF|NR?`9=85BrtYCO7LW<)W~#V>MP7FCaUik<|~@+1$XDF^fd~wWhw3h=bKvnb@ouFb!cXYHrY8=!h8HiX1d|6@;x{ zor5v>Y9by{yMvJk9T9`A?m=TKj@Yp_;g+7UR0_=2G=%`35jpz2tr!5s{SfD@4>#wm z-zK6RIBmE08ARP@;)LEMI30R1QO~tR+d-WOtK-yvx}0dzO+?dh^6yBT%zhFygz#H9 zrT0Fb-FU9Mm1yomkb(Ba>Aa)v#YxpGaO(F`oEW|yrez_Wo`~kLMQ1rh@nGW}-Ll!Rg-(u)U0E zGM;UC-iS0#Mp`!Bh!fm5;5VLo;kgaz>4weUE+YCp($Ir6yobCVjP$JsZ!6NU57M~_ zY5(;dM1MzoOKv0j9cbz8z(<_F!}Cm|)_o z;Gf4355isey>u(=LEFHa@&wTzo`)@H`wJ+)Z75efx4lAi`pZZI!Yf}wKJa@7o_~1} z7@+l_1<=|5Rg@*-SPgpTN!&63-TWNzp9SVqi0>KHG5p?&=i^VKO@KEO&o<~x0p=|` z5iO=u=m%7zAJVB*ryo%-_0dvVLTAvKbULk|RWw9{G(cz3a#~5J(K70%2AxgAG(t@p zqfuH-=g_&dhSt(LI*-n$3urxENSDwRbR}I*m(m8hm@cD@bP-*J26#1HOV`m2bUocf zH`9%DE8RtR)17o1-9ek^cDjddp?hgAeTP0y$IxW@7|o$C&}^DXvuFk#Py5jn+MB*k z-=%$NADTvO^fmeleThCvU#6pJ7y1N!m5!x(^hG+7j-YSR;q)o`G<}Blq&;Xi+MRZ# zcIu$d(uuTyPN45mCoQDoXc6^LH=RT$Qx|=o4x`W0w`qU+CQYXU=^#3QzCj1mA#@ZS zN>k}`v=_~%`{_PjNTWK>rOpnup^Z-3UKc&~`XSAK(p#Pw^=uP?s{fd50 zzoh@9*XeC~ik_rr>1ld~UZ7X#ReG7W(M$9^y+}W%=jbQ26HWU6Qu#kuDm&vHK@h56E#@(Wy_lsHe1Gy(h~)aH5V%veoN4AHd9c`i z$ivZhfch}9^A^RFy~8TX%HcWX9O5dM*moKxPRl8xv@8>2{zfGt$RcJhBZ|lw*8(uM z0l|w6=lz0-!eJHm4$m<*+qK5hgbOpn&?^@cLJVS$kV#C1qTV1|<(&ycUE?x-Oo7S# zI>*Ga-Z7zD_Z)$#e-5jtg9R^}CCi=a!ezm2>TEO5csUCc`dLW%*K|0Rk?$5~47MSi zar{!SY+D3APx;?+h4UQ&_q-MOZnrY&b1QKjZn(zVCS15$GcrHtCs$%;-HM($*DHLi zugmD5dmJv;6PHwMX|QWH0Yi0^Ri`^EFManQk5tKm=OxE^9@dG*945_K*bd+a;4D9S zupKs``!Zn1(hpHE`QWRf$q!0eX!n3BboiNW#fY9=M{RIU`P&%HK?LVCy%h$ISOY|_ zQuS2`t6N+-a#;Dz2Ft<97iUECFuSy*0$DrJ)gf^Oz&#vk<8n@5@)MKA@!VJ$6biwT zD5S3I3ufGVg^H+GdX|!VKn1)DNyWT_DLIo5#&>+CVhb6EO&!DW9Lvr@`Gq9aMoi}v zJN{TSS`3{02rKxw48?ZTe6g5{`3hcVtSfUi zZsdm@&Gjka4Jnnr$mKy#Xj$kWWbm>9QWI+m5XH`s2O9_U-DaVKq1zL@qssJfJ3w49 ziF95{JJflBA8&pT20AZrgA-a?lA^WhS*{Udcw|Xd;lN!vc@A5@q$$Qp9kk=0^J0kC zKS$uqE&|-FvN(J>!*E4nj^T(*LpDxDb9JO%)plfTrcv;9C39o3vyDPYzZ5k<+5E%q zjvAL)PT@7nQbT3_>d7+YzCQ|H%%81pCbJHX2$YY7NVr)_xu=EHceYTF{uW}_QWz-*chn2c4%y z0k>&^aF}8`u2MnQNxiz^`&Y)tb*((VDjwYDFm+nL9tf%wl{}$?^qSR6u7&-EVruTN z*u8YMsF$&Wg@Q%_6_Ht#Kq? zO$^DbgYEVV$Fh6@Wd#OlJV$38K(>z~K$%PeGob-5PPRJxJ3LZHAYybRUUX)!gU4mK zA|k`q!<;Tf!$Ztss0+wti(tk^Xnn}U!Ir@_c)uOMkF^jMO}LdX6~Co8V%}ODfoL&> z#Ay@mW|L08;)r6f8&6h+os!IURd|VJED=w}b2p@Pbe8QOVq}|Bj(V*0v$!&$DP7YU z`Vw32Ru(LDM;t0~D~=Vn)d-ihmHP#4WW1COR}`^kJLQ{C>Ag*^+?DxWmU#)mxok+y zBhrQJ?p`q)v-u^M&G?sPqEQ96!&tojrkE$rR&5^F%>28sk)WpJ#X;aalPY4fKw`$2 zK=92nDfPF^qz2nKlR{m_#ZEy{b#*ZTov%)%xvC72JIB5w5L@W#x?+pXH3@?{>TIz| zX)EUfz+JIQb9d8C%8IQwPZ0UEh&$WM%Qo;?A+sgNVhwG~Nrmy;g$`YNF80jQ$V$rLID7Ug{{A?#2{XF|}}XB8}3~ z2+U3kshFP@d^tlc1fhE(&de2KcYaKi7lY-ClCT0yG0aw}E>A0RSCW>CiWn?Cpf$WhfMa#VB<`B`I`bg(=j+B4rA^RGCN=tRv&4SZur&Wg*v>Fm*R!t)3_? zyCG{;5=EysL<5D!1+2KVC{|FpG*U!bnkXEt5G@uh4i<ff%Q-MaT&IM6@RXf~FOwjJ1gP+R8-C!Lr{#eYg!8L9{f zXHnHJm4=UJzc>(5(%)D$j3n>Y{a^I&e;Y_;rT(cjP9l@@V{qhGaaI^kmPduPv*FBE zI$&6xcFR%xuc`m?e=07VRL?`|F$pJn@nz=^xuIWWt(noV(tDdc?rQV(af1~pM2Meg2l_%l&McXttesPf*7V0|6l{ItRHRy;gM<=bGYUF^Y7i?x)1JsBon{c)TR;oSu8XE`ogS56eSBhoStMt-L2{bui6r{j1A+WGhAfuC9H?~9m#S5JF_Kks1Xi}#75%?S6lUjf?Q z4w~5&5OAgYqYkr#6D9c#;C;ct3+>`g6nl1J4)VnUTWvK>6e-pJeMuoXCw=n0NCC-% zty@TYByVbMzmGtSOdm^^WqV?5`Le*QZsy;f=>7JMq57SD`P@co?tbv_R}`*2ZWS)l z@`#C}pp~k=>i=s9!TY z?8;YBk$zb1R?qa%t6fQ@YT7IhyTa8}B+qJxZnnU!XhoG6d)ftJRjaC0FWJE`t61Hn z_QMZXXwDJviS~=Bef}d1R#jt7q~z2d^|uUG_9@>9=PJ?-lZU zf8SO}+4=79tcO#$^8{{cx>FiAQiIiA-+YeSYN}J-*NK_@aU456(J76b+EF;3BgdyXHx5CtZ#rJ)@xLeC3C;Iko2RU@-Zo;{al&N|fxJY2LyAT4H2V2+SR1579xayV# zkH376kUHUYioi3c@Vkl&h!aImy~A28(DUmQ0+I*E;or#mLA_7^frE%6N$k!f$N3O` zPSoX7Ij(mbbE4R(eZL=aZ1=K!$f?owM;tlTbW8VF zsW6wcfrBOftHw&ohi}OADHFzsT2(CN*v{oRj#9p7OriD*)KSb6 zS7o0zoG@x)&$h-<&HZfw$%EtYZe#>d@Am5gQC|$_2p__;iJ9Uuju<+ATe{7p_5qhW zc-dukkvSe5hc^@b-U@-`Z>y9=OO0g%E?RRj{+he~8|4e|r`qt>+&Pp8jw7FuHK{s_ zyOJZ@d;Jr{O!c~FMKJXT0|apC8q^Wl9Xt%V9dwY3yZ;r>98$C4RU!P3Z2mA5La$&% zKRnWo)OEK;2($W8Co$3vhf)w;2$ZgCsov^r2RC$KfYsZ)@v1zu&oO_b<4VN5@xY+#Z(`1 z;gO4AYphhOT*t7m-(lX6;0rMVwshS|-Q7DshFk0ac*gJTjTrHxqJ#D z{e-$Zc|kM<<`dEr^?$0|FN~q%OFR?BP0gS#is2UDu$d@&D%TfFbm!|q6UFU_^djoa z)g=L3@m(ST&x5Vocxu*sX&9Y<@Q4G7Ixr6WL|eNoj9>Bl&{VD45KcjreNANKQumZE zZ-rh(PZQZ$Q18I6h~QV%&!kQ|UKz&zNLu?wj?KP>C8~S*o;@<-RCm;_;pZmLTV|p<@nGxTGj-k74vFV{q>z_d z`Fu}2d~w2BktvKw8%s+ zbg#s%?$m8!rgC2lwTd}-VorF!#I5$^Z36iL54qB_w}~B&2PLxETQZ~F#OD-|9$&3` zHcRx1*PE&S@ga#_%5Zi1v%O97OaD8A{}s Date: Tue, 9 Sep 2014 09:57:35 -0400 Subject: [PATCH 032/141] Added deserializeMultiFile, materials now deserialize from JSON --- source/dash/components/assets.d | 13 +++--- source/dash/components/material.d | 19 ++++---- source/dash/utility/data/serialization.d | 56 +++++++++++++++++++++++- source/dash/utility/data/yaml.d | 21 ++++++--- 4 files changed, 85 insertions(+), 24 deletions(-) diff --git a/source/dash/components/assets.d b/source/dash/components/assets.d index 860d09ea..91836290 100644 --- a/source/dash/components/assets.d +++ b/source/dash/components/assets.d @@ -125,13 +125,16 @@ public: foreach( res; scanDirectory( Resources.Materials ) ) { - auto newMat = deserializeFile!MaterialAsset( res ); + auto newMat = deserializeMultiFile!MaterialAsset( res ); - if( newMat.name in materials ) - logWarning( "Material ", newMat.name, " exists more than once." ); + foreach( mat; newMat ) + { + if( mat.name in materials ) + logWarning( "Material ", mat.name, " exists more than once." ); - materials[ newMat.name ] = newMat; - materialResources[ res ] ~= newMat; + materials[ mat.name ] = mat; + materialResources[ res ] ~= mat; + } } meshes.rehash(); diff --git a/source/dash/components/material.d b/source/dash/components/material.d index dec41854..d0c4870c 100644 --- a/source/dash/components/material.d +++ b/source/dash/components/material.d @@ -16,22 +16,19 @@ mixin( registerComponents!() ); @yamlObject() final class MaterialAsset : Asset { -package: - @field( "Name" ) - string _name; - public: + /// The name of the material. + @rename( "Name" ) + string name; /// The diffuse (or color) map. - @field( "Diffuse" ) + @rename( "Diffuse" ) @asArray Texture diffuse; /// The normal map, which specifies which way a face is pointing at a given pixel. - @field( "Normal" ) + @rename( "Normal" ) @asArray Texture normal; /// The specular map, which specifies how shiny a given point is. - @field( "Specular" ) + @rename( "Specular" ) @asArray Texture specular; - /// The name of the material. - mixin( Getter!_name ); /** * Default constructor, makes sure everything is initialized to default. @@ -41,7 +38,7 @@ public: super( Resource( "" ) ); diffuse = specular = defaultTex; normal = defaultNormal; - _name = name; + this.name = name; } /** @@ -53,7 +50,7 @@ public: mat.diffuse = diffuse; mat.normal = normal; mat.specular = specular; - mat._name = _name; + mat.name = name; return mat; } diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index c32206de..4a768b9a 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -62,7 +62,61 @@ T deserializeFile( T )( Resource file, SerializationMode mode = SerializationMod case ".yml": return handleYaml(); default: throw new Exception( "File extension " ~ file.extension.toLower ~ " not supported." ); } - } + } +} + +/** + * Deserializes a file with multiple documents. + * + * Params: + * file = The name of the file to deserialize. + * + * Returns: The deserialized object. + */ +T[] deserializeMultiFile( T )( Resource file, SerializationMode mode = SerializationMode.Default ) +{ + import dash.utility.output; + logInfo( "Deserializing ", file.baseFileName, " to ", T.stringof ); + + import std.path: extension; + import std.string: toLower; + + T[] handleJson() + { + return [deserializeJson!T( file.readText().parseJsonString() )]; + } + + T[] handleBson() + { + throw new Exception( "Not implemented." ); + } + + T[] handleYaml() + { + import std.algorithm: map; + import std.array: array; + return Loader + .fromString( cast(char[])file.readText() ) + .loadAll() + .map!( node => node.deserializeYaml!T() ) + .array(); + } + + final switch( mode ) with( SerializationMode ) + { + case Json: return handleJson(); + case Bson: return handleBson(); + case Yaml: return handleYaml(); + case Default: + switch( file.extension.toLower ) + { + case ".json": return handleJson(); + case ".bson": return handleBson(); + case ".yaml": + case ".yml": return handleYaml(); + default: throw new Exception( "File extension " ~ file.extension.toLower ~ " not supported." ); + } + } } /** diff --git a/source/dash/utility/data/yaml.d b/source/dash/utility/data/yaml.d index e9d122ca..a9c7b92f 100644 --- a/source/dash/utility/data/yaml.d +++ b/source/dash/utility/data/yaml.d @@ -18,7 +18,7 @@ alias Yaml = Node; * Fields ending with an underscore will have the last underscore stripped in the * serialized output. This makes it possible to use fields with D keywords as their name * by simply appending an underscore. - * + * * The following methods can be used to customize the serialization of structs/classes: * * --- @@ -112,16 +112,23 @@ public: void readArray( T )( scope void delegate( size_t ) size_callback, scope void delegate() entry_callback ) { - enforceYaml( m_current.isSequence ); + enforceYaml( m_current.isSequence || m_current.isScalar ); - auto old = m_current; - size_callback( m_current.length ); - foreach( ent; old ) + if( m_current.isSequence ) + { + auto old = m_current; + size_callback( m_current.length ); + foreach( Node ent; old ) + { + m_current = ent; + entry_callback(); + } + m_current = old; + } + else { - m_current = ent; entry_callback(); } - m_current = old; } T readValue( T )() From 772be78f612aacbf7c1c122380debffdf5f063c6 Mon Sep 17 00:00:00 2001 From: Sean Brennan Date: Tue, 9 Sep 2014 10:18:13 -0400 Subject: [PATCH 033/141] Switched to using Modplug objects, which now can play sounds loaded in from files. --- source/dash/components/audio.d | 37 +++++++++------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/source/dash/components/audio.d b/source/dash/components/audio.d index c2e21ee5..ae114b50 100644 --- a/source/dash/components/audio.d +++ b/source/dash/components/audio.d @@ -42,7 +42,7 @@ public: class Emitter : Component { private: - Wav toPlay; + Modplug toPlay; public: /** * Create an emmiter object @@ -54,32 +54,21 @@ public: override void initialize() { super.initialize; - toPlay = Wav.create(); - + toPlay = Modplug.create(); } // call: - // emmiter.play(Audio.sounds["baseFileName"]); + // emmiter.play( filename ); void play( string soundName ) { + // Load in the sound + toPlay.load( Audio.sounds[soundName].toStringz() ); - /*string filePath = Audio.sounds[soundName]; - logInfo( "playing: ", filePath ); - toPlay = Wav.create(); - toPlay.load( filePath.toStringz() ); - Speech speech = Speech.create(); - speech.setText("hello".toStringz());*/ - toPlay.load( "C:\\Circular\\Sample-Dash-Game\\Audio\\airhorn.wav".toStringz() ); - - auto result = Audio.soloud.play( toPlay, 1.0 ); - - logInfo( Audio.soloud.getErrorString( result ) ); - /*Audio.soloud.play3d(toPlay, + // play the sound from the location of the parent object + Audio.soloud.play3d(toPlay, owner.transform.position.x, owner.transform.position.y, - owner.transform.position.z);*/ - //logInfo( "playing: ", soundName, " with id: ", Audio.effects[soundName].objhandle ); - //Audio.soloud.play( Audio.effects[soundName] ); + owner.transform.position.z); } } @@ -101,20 +90,14 @@ static: public: string[string] sounds; - Wav[string] effects; - void initialize() { soloud = Soloud.create(); soloud.init(); + foreach( file; scanDirectory( Resources.Audio ) ) { - sounds[file.baseFileName] = file.fullPath; - - /*effects[file.baseFileName] = Wav.create(); - effects[file.baseFileName].load( file.fullPath.toStringz ); - logInfo( "baseFileName: ", file.baseFileName ); - logInfo( "fullPath: ", file.fullPath.toStringz );*/ + sounds[file.baseFileName] = file.relativePath; } } From 5bd7d9e5afb97df2ff3e18c8c33dff7ca94d5ce9 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 9 Sep 2014 10:23:02 -0400 Subject: [PATCH 034/141] Prefab fixes --- dub.json | 2 +- source/dash/components/component.d | 1 + source/dash/core/prefabs.d | 31 +++++++++++++++--------------- source/dash/utility/data/yaml.d | 4 +++- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/dub.json b/dub.json index 9952dfe4..d42eeb4c 100644 --- a/dub.json +++ b/dub.json @@ -21,7 +21,7 @@ "gl3n" : "~master", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", - "vibe-d": "==0.7.21-alpha.4", + "vibe-d": "==0.7.21-beta.1", "x11": { "version": "~>1.0", "optional": true } }, diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 7d110cde..c0dcd9ab 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -59,6 +59,7 @@ public: return null; } } + static assert( is$typeSerializable!Component ); } ); const(Description)* description() @property diff --git a/source/dash/core/prefabs.d b/source/dash/core/prefabs.d index d0ff8e4a..c761ac5a 100644 --- a/source/dash/core/prefabs.d +++ b/source/dash/core/prefabs.d @@ -46,16 +46,13 @@ public: foreach( key; prefabs.keys ) prefabs.remove( key ); - foreach( objFile; loadYamlFiles( Resources.Prefabs ) ) + foreach( res; scanDirectory( Resources.Prefabs ) ) { - auto object = objFile[0]; - auto name = object[ "Name" ].as!string; - - //auto newFab = new Prefab( object ); - auto newFab = cast(Prefab)createYamlObject[ "Prefab" ]( object ); - newFab.name = name; - prefabs[ name ] = newFab; - prefabResources[ objFile[1] ] ~= newFab; + foreach( newFab; deserializeMultiFile!( GameObject.Description )( res ) ) + { + prefabs[ newFab.name ] = newFab; + prefabResources[ res ] ~= newFab; + } } } @@ -79,7 +76,15 @@ final class Prefab { public: /// The name of the prefab. - mixin( Property!_name ); + string name; + /// The description to create objects from. + GameObject.Description description; + + /// Creates a prefab from a description. + this( GameObject.Description desc ) + { + description = desc; + } /** * Creates a GameObject instance from the prefab. @@ -89,10 +94,6 @@ public: */ GameObject createInstance() { - //TODO: Fix this - return null;//GameObject.createFromYaml( yaml ); + return GameObject.create( description ); } - -private: - string _name; } diff --git a/source/dash/utility/data/yaml.d b/source/dash/utility/data/yaml.d index a9c7b92f..86e3461c 100644 --- a/source/dash/utility/data/yaml.d +++ b/source/dash/utility/data/yaml.d @@ -55,6 +55,9 @@ T deserializeYaml( T, R )( R input ) if ( isInputRange!R && !is( R == Node ) ) static assert(is(typeof( deserializeYaml!string( Node( "" ) ) ))); //static assert(is(typeof( deserializeYaml!string( "" ) ))); +/// Does the type support custom serialization. +enum isYamlSerializable( T ) = is( typeof( T.init.toYaml() ) == Node ) && is( typeof( T.fromYaml( Node() ) ) == T ); + /// Serializer for vibe.d framework. struct YamlSerializer { @@ -65,7 +68,6 @@ private: public: enum isYamlBasicType( T ) = isNumeric!T || isBoolean!T || is( T == string ) || is( T == typeof(null) ); enum isSupportedValueType( T ) = isYamlBasicType!T || is( T == Node ); - enum isYamlSerializable( T ) = is( typeof( T.init.toYaml() ) == Node ) && is( typeof( T.fromYaml( Node() ) ) == T ); this( Node data ) { m_current = data; } @disable this(this); From 713d0c1ed390401e9ba1df4a92e60c94da422c06 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 11 Sep 2014 10:03:56 -0400 Subject: [PATCH 035/141] Cleaned up code, fixed Yaml serializer. Now compiles with vibe-d master --- source/dash/components/component.d | 7 ------- source/dash/core/gameobject.d | 14 +++++++++++++- source/dash/core/prefabs.d | 4 ++-- source/dash/utility/data/serialization.d | 4 ++++ source/dash/utility/data/yaml.d | 2 +- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index c0dcd9ab..e8607066 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -8,18 +8,11 @@ import vibe.data.bson, vibe.data.json, dash.utility.data.yaml; import std.algorithm, std.array, std.string, std.traits, std.conv, std.typecons; /// Tests if a type can be created from yaml. -enum isYamlObject(T) = __traits( compiles, { T obj; obj.yaml = Node( YAMLNull() ); } ); enum isComponent(alias T) = is( T == class ) && is( T : Component ) && !__traits( isAbstractClass, T ); -enum serializationFormats = tuple( "Json"/*, "Bson"/*, "Yaml"*/ ); private enum perSerializationFormat( string code ) = "".reduce!( ( working, type ) => working ~ code.replace( "$type", type ) )( serializationFormats ); alias helper( alias T ) = T; alias helper() = TypeTuple!(); -auto append( Begin, End )( Begin begin, End end ) -{ - return tuple( begin.expand, end ); -} - /** * Interface for components to implement. */ diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index a2fffb1f..f790e650 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -93,7 +93,7 @@ public: Description[] children; @rename( "Components" ) @optional - Component[] components; + Component[] components; /** * Create a description from a GameObject. @@ -290,6 +290,18 @@ public: return obj; } + /// To complement the descriptions, and make serialization easier. + static GameObject fromRepresentation( Description desc ) + { + return GameObject.create( desc ); + } + /// ditto + Description toRepresentation() + { + return GameObject.Description( this ); + } + static assert( isCustomSerializable!GameObject ); + /** * Creates basic GameObject with transform and connection to transform's emitter. */ diff --git a/source/dash/core/prefabs.d b/source/dash/core/prefabs.d index c761ac5a..7af710f7 100644 --- a/source/dash/core/prefabs.d +++ b/source/dash/core/prefabs.d @@ -6,7 +6,6 @@ import dash.core, dash.components, dash.utility; import yaml; import gl3n.linalg; -import std.variant; mixin( registerComponents!() ); @@ -48,8 +47,9 @@ public: foreach( res; scanDirectory( Resources.Prefabs ) ) { - foreach( newFab; deserializeMultiFile!( GameObject.Description )( res ) ) + foreach( fabDesc; res.deserializeMultiFile!( GameObject.Description )() ) { + auto newFab = new Prefab( fabDesc ); prefabs[ newFab.name ] = newFab; prefabResources[ res ] ~= newFab; } diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index 4a768b9a..42eb0a9c 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -2,12 +2,16 @@ module dash.utility.data.serialization; import dash.utility.resources; import dash.utility.data.yaml; import vibe.data.json, vibe.data.bson; +import std.typecons: tuple; // Serialization attributes public import vibe.data.serialization: asArray, byName, ignore, name, optional; /// Rename a field in the ddl. alias rename = name; +/// Supported serialization formats. +enum serializationFormats = tuple( "Json"/*, "Bson"*/, "Yaml" ); + /** * Modes of serialization. */ diff --git a/source/dash/utility/data/yaml.d b/source/dash/utility/data/yaml.d index 86e3461c..d3360c20 100644 --- a/source/dash/utility/data/yaml.d +++ b/source/dash/utility/data/yaml.d @@ -66,7 +66,7 @@ private: Node[] m_compositeStack; public: - enum isYamlBasicType( T ) = isNumeric!T || isBoolean!T || is( T == string ) || is( T == typeof(null) ); + enum isYamlBasicType( T ) = isNumeric!T || isBoolean!T || is( T == string ) || is( T == typeof(null) ) || isYamlSerializable!T; enum isSupportedValueType( T ) = isYamlBasicType!T || is( T == Node ); this( Node data ) { m_current = data; } From f02f3779b9bcdb83ec64a33d06748c3bbbb62264 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 16 Sep 2014 09:37:13 -0400 Subject: [PATCH 036/141] Closer! --- dub.json | 4 ++-- source/dash/components/camera.d | 25 +++++++------------------ source/dash/components/lights.d | 9 +++++---- source/dash/core/gameobject.d | 6 +++--- source/dash/graphics/adapters/adapter.d | 6 +++--- source/dash/graphics/adapters/gl.d | 10 +++++----- source/dash/utility/config.d | 8 ++++---- source/dash/utility/input.d | 12 ++++++------ 8 files changed, 35 insertions(+), 45 deletions(-) diff --git a/dub.json b/dub.json index 1e7f9db3..e820ce72 100644 --- a/dub.json +++ b/dub.json @@ -21,10 +21,10 @@ "derelict-fi": "~>1.0", "derelict-assimp3": "~>1.0", "dyaml": "~>0.5", - "gfm:math" : "~>1.1", + "gfm:math" : "==1.2.3", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", - "vibe-d": "==0.7.21-alpha.4", + "vibe-d": "==0.7.21-beta.1", "x11": { "version": "~>1.0", "optional": true } }, diff --git a/source/dash/components/camera.d b/source/dash/components/camera.d index aea356cf..d5b5b678 100644 --- a/source/dash/components/camera.d +++ b/source/dash/components/camera.d @@ -6,6 +6,7 @@ import dash.core, dash.components, dash.graphics, dash.utility; import gfm.math.vector: vec2f, vec3f, vec4f, cross, dot; import gfm.math.matrix: mat4f; +import gfm.math.funcs: radians; import std.conv: to; import std.math: sin, cos; @@ -20,7 +21,6 @@ final class Camera : Component, IDirtyable private: float _prevFov, _prevNear, _prevFar, _prevWidth, _prevHeight; - vec2f _projectionConstants; // For rebuilding linear Z in shaders mat4f _prevLocalMatrix; mat4f _viewMatrix; @@ -45,8 +45,6 @@ public: /** * TODO * - * Params: - * * Returns: */ final vec2f projectionConstants() @@ -64,8 +62,6 @@ public: /** * TODO * - * Params: - * * Returns: */ final mat4f perspectiveMatrix() @@ -83,8 +79,6 @@ public: /** * TODO * - * Params: - * * Returns: */ final mat4f inversePerspectiveMatrix() @@ -102,8 +96,6 @@ public: /** * TODO * - * Params: - * * Returns: */ final mat4f orthogonalMatrix() @@ -121,8 +113,6 @@ public: /** * TODO * - * Params: - * * Returns: */ final mat4f inverseOrthogonalMatrix() @@ -140,17 +130,16 @@ public: /** * TODO * - * Params: - * * Returns: */ final void updateViewMatrix() { //Assuming pitch & yaw are in radians - float cosPitch = cos( owner.transform.rotation.pitch ); - float sinPitch = sin( owner.transform.rotation.pitch ); - float cosYaw = cos( owner.transform.rotation.yaw ); - float sinYaw = sin( owner.transform.rotation.yaw ); + vec3f eulers = owner.transform.rotation.toEulerAngles(); + float cosPitch = cos( eulers.x ); + float sinPitch = sin( eulers.x ); + float cosYaw = cos( eulers.y ); + float sinYaw = sin( eulers.y ); vec3f xaxis = vec3f( cosYaw, 0.0f, -sinYaw ); vec3f yaxis = vec3f( sinYaw * sinPitch, cosPitch, cosYaw * sinPitch ); @@ -238,7 +227,7 @@ private: final void updatePerspective() { _projectionConstants = vec2f( ( -far * near ) / ( far - near ), far / ( far - near ) ); - _perspectiveMatrix = mat4f.perspective( cast(float)Graphics.width, cast(float)Graphics.height, fov, near, far ); + _perspectiveMatrix = mat4f.perspective( fov.radians, cast(float)Graphics.width / cast(float)Graphics.height, near, far ); _inversePerspectiveMatrix = _perspectiveMatrix.inverse(); } diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index 13d17a42..cd090a28 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -135,10 +135,11 @@ public: quatf rotation = quatf( halfCosX2/2, w.x / halfCosX2, w.y / halfCosX2, w.z / halfCosX2 ); // determine the x,y,z axes - float cosPitch = cos( rotation.pitch ); - float sinPitch = sin( rotation.pitch ); - float cosYaw = cos( rotation.yaw ); - float sinYaw = sin( rotation.yaw ); + vec3f eulers = rotation.toEulerAngles(); + float cosPitch = cos( eulers.x ); + float sinPitch = sin( eulers.x ); + float cosYaw = cos( eulers.y ); + float sinYaw = sin( eulers.y ); vec3f xaxis = vec3f( cosYaw, 0.0f, -sinYaw ); vec3f yaxis = vec3f( sinYaw * sinPitch, cosPitch, cosYaw * sinPitch ); vec3f zaxis = vec3f( sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw ); diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 0861e1cc..ca1566b2 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -5,7 +5,7 @@ module dash.core.gameobject; import dash.core, dash.components, dash.graphics, dash.utility; import yaml; - +import gfm.math.funcs: radians; import std.conv, std.variant, std.array, std.algorithm, std.typecons, std.range, std.string; enum AnonymousName = "__anonymous"; @@ -145,7 +145,7 @@ public: if( innerNode.tryFind( "Position", transVec ) ) obj.transform.position = transVec; if( innerNode.tryFind( "Rotation", transVec ) ) - obj.transform.rotation = quatf.IDENTITY.rotatex( transVec.x.radians ).rotatey( transVec.y.radians ).rotatez( transVec.z.radians ); + obj.transform.rotation = quatf.fromEulerAngles( transVec.x.radians, transVec.y.radians, transVec.z.radians ); } if( yamlObj.tryFind( "Children", innerNode ) ) @@ -466,7 +466,7 @@ private: owner = obj; position = vec3f(0,0,0); scale = vec3f(1,1,1); - rotation = quatf.IDENTITY; + rotation = quatf.identity; } public: diff --git a/source/dash/graphics/adapters/adapter.d b/source/dash/graphics/adapters/adapter.d index dd1ac380..a04121ab 100644 --- a/source/dash/graphics/adapters/adapter.d +++ b/source/dash/graphics/adapters/adapter.d @@ -4,7 +4,7 @@ module dash.graphics.adapters.adapter; import dash.core.properties, dash.components.userinterface, dash.utility.config; -import gfm.math.vector: vec2i; +import gfm.math.vector: vec2ui; import std.typecons: BlackHole; alias NullAdapter = BlackHole!Adapter; @@ -81,12 +81,12 @@ public: /** * Read from the depth buffer at the given point. */ - abstract float getDepthAtScreenPoint( vec2i point ); + abstract float getDepthAtScreenPoint( vec2ui point ); /** * Read from the depth buffer at the given point. */ - abstract uint getObjectIDAtScreenPoint( vec2i point ); + abstract uint getObjectIDAtScreenPoint( vec2ui point ); /// TODO: Remove in favor of pipelines abstract void initializeDeferredRendering(); diff --git a/source/dash/graphics/adapters/gl.d b/source/dash/graphics/adapters/gl.d index 7d3be030..9baef38b 100644 --- a/source/dash/graphics/adapters/gl.d +++ b/source/dash/graphics/adapters/gl.d @@ -107,7 +107,7 @@ public: /** * Read from the depth buffer at the given point. */ - override float getDepthAtScreenPoint( vec2i point ) + override float getDepthAtScreenPoint( vec2ui point ) { float depth; glBindFramebuffer( GL_FRAMEBUFFER, deferredFrameBuffer ); @@ -120,7 +120,7 @@ public: /** * Read from the depth buffer at the given point. */ - override uint getObjectIDAtScreenPoint( vec2i point ) + override uint getObjectIDAtScreenPoint( vec2ui point ) { float fId; glBindFramebuffer( GL_FRAMEBUFFER, deferredFrameBuffer ); @@ -188,7 +188,7 @@ public: mat4f worldView = scene.camera.viewMatrix * object.transform.matrix; mat4f worldViewProj = projection * worldView; - if( !( object.mesh.boundingBox in Frustum( worldViewProj ) ) ) + if( !( object.mesh.boundingBox in Frustum!float( worldViewProj ) ) ) { // If we can't see an object, don't draw it. continue; @@ -237,8 +237,8 @@ public: { if( object.mesh && object.stateFlags.drawMesh ) { - frustum = frustum.expand( (object.transform.matrix * vec4(object.mesh.boundingBox.min, 1.0f)).xyz ); - frustum = frustum.expand( (object.transform.matrix * vec4(object.mesh.boundingBox.max, 1.0f)).xyz ); + frustum = frustum.expand( (object.transform.matrix * vec4f(object.mesh.boundingBox.min, 1.0f)).xyz ); + frustum = frustum.expand( (object.transform.matrix * vec4f(object.mesh.boundingBox.max, 1.0f)).xyz ); } } diff --git a/source/dash/utility/config.d b/source/dash/utility/config.d index 6c403389..d83b387e 100644 --- a/source/dash/utility/config.d +++ b/source/dash/utility/config.d @@ -48,11 +48,11 @@ static this() import dash.components.lights; import dash.graphics.shaders.shaders; import dash.utility.output; - import gl3n.linalg; + import gfm.math.vector, gfm.math.quaternion; constructor.addConstructorScalar( "!Vector2", ( ref Node node ) { - vec2 result; + vec2f result; string[] vals = node.as!string.split(); if( vals.length != 2 ) throw new Exception( "Invalid number of values: " ~ node.as!string ); @@ -63,7 +63,7 @@ static this() } ); constructor.addConstructorScalar( "!Vector3", ( ref Node node ) { - vec3 result; + vec3f result; string[] vals = node.as!string.split(); if( vals.length != 3 ) throw new Exception( "Invalid number of values: " ~ node.as!string ); @@ -75,7 +75,7 @@ static this() } ); constructor.addConstructorScalar( "!Quaternion", ( ref Node node ) { - quat result; + quatf result; string[] vals = node.as!string.split(); if( vals.length != 3 ) throw new Exception( "Invalid number of values: " ~ node.as!string ); diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index 113d123d..5c900b64 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -243,7 +243,7 @@ public: if( !DGame.instance.activeScene ) { logWarning( "No active scene." ); - return vec3( 0.0f, 0.0f, 0.0f ); + return vec3f( 0.0f, 0.0f, 0.0f ); } auto scene = DGame.instance.activeScene; @@ -251,13 +251,13 @@ public: if( !scene.camera ) { logWarning( "No camera on active scene." ); - return vec3( 0.0f, 0.0f, 0.0f ); + return vec3f( 0.0f, 0.0f, 0.0f ); } vec2ui mouse = mousePos(); float depth; int x = mouse.x; int y = mouse.y; - auto view = vec3( 0, 0, 0 ); + auto view = vec3f( 0, 0, 0 ); if( x >= 0 && x <= Graphics.width && y >= 0 && y <= Graphics.height ) { @@ -268,8 +268,8 @@ public: float screenX = ( mouse.x / cast(float)Graphics.width ) * 2 - 1; float screenY = -( ( mouse.y / cast(float)Graphics.height ) * 2 - 1 ); - auto viewSpace = scene.camera.inversePerspectiveMatrix * vec4( screenX, screenY, 1.0f, 1.0f); - auto viewRay = vec3( viewSpace.xy * (1.0f / viewSpace.z), 1.0f); + auto viewSpace = scene.camera.inversePerspectiveMatrix * vec4f( screenX, screenY, 1.0f, 1.0f); + auto viewRay = vec3f( viewSpace.xy * (1.0f / viewSpace.z), 1.0f); view = viewRay * linearDepth; } @@ -307,7 +307,7 @@ public: return null; } - vec2i mouse = mousePos(); + vec2ui mouse = mousePos(); if( mouse.x >= 0 && mouse.x <= Graphics.width && mouse.y >= 0 && mouse.y <= Graphics.height ) { From c0d45a7aa4930912055386d34fbc4c8e90073521 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 16 Sep 2014 10:13:32 -0400 Subject: [PATCH 037/141] Game doesn't crash! --- dub.json | 2 +- source/dash/core/gameobject.d | 6 +++--- source/dash/core/prefabs.d | 11 ++++++++++- source/dash/utility/data/serialization.d | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/dub.json b/dub.json index d42eeb4c..bc1c8583 100644 --- a/dub.json +++ b/dub.json @@ -21,7 +21,7 @@ "gl3n" : "~master", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", - "vibe-d": "==0.7.21-beta.1", + "vibe-d": "~master", "x11": { "version": "~>1.0", "optional": true } }, diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index f790e650..97be0477 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -510,7 +510,7 @@ private: void opAssign( Description desc ) { position = vec3( desc.position[] ); - rotation = quat( vec4( desc.rotation ) ); + rotation = quat.euler_rotation( desc.rotation[ 1 ], desc.rotation[ 0 ], desc.rotation[ 2 ] ); scale = vec3( desc.scale[] ); } @@ -540,7 +540,7 @@ public: /// The position of the object. @rename( "Rotation" ) @asArray @optional - float[4] rotation; + float[3] rotation; /// The position of the object. @rename( "Scale" ) @asArray @optional @@ -549,7 +549,7 @@ public: this( Transform t ) { position = t.position.vector[ 0..3 ]; - rotation = t.rotation.quaternion[ 0..4 ]; + rotation = [ t.rotation.yaw, t.rotation.pitch, t.rotation.roll ]; scale = t.scale.vector[ 0..3 ]; } } diff --git a/source/dash/core/prefabs.d b/source/dash/core/prefabs.d index 7af710f7..2d698947 100644 --- a/source/dash/core/prefabs.d +++ b/source/dash/core/prefabs.d @@ -27,7 +27,15 @@ public: { Prefab opIndex( string index ) { - return prefabs[ index ]; + if( auto fab = index in prefabs ) + { + return *fab; + } + else + { + logWarning( "Prefab ", index, " not found." ); + return null; + } } Prefab opIndexAssign( Prefab newFab, string index ) @@ -84,6 +92,7 @@ public: this( GameObject.Description desc ) { description = desc; + name = description.name; } /** diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index 42eb0a9c..84ebb164 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -5,7 +5,7 @@ import vibe.data.json, vibe.data.bson; import std.typecons: tuple; // Serialization attributes -public import vibe.data.serialization: asArray, byName, ignore, name, optional; +public import vibe.data.serialization: asArray, byName, ignore, name, optional, isCustomSerializable; /// Rename a field in the ddl. alias rename = name; From a832cdb3fb23be66f21733f2ad97fb61d2cae49c Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 16 Sep 2014 10:43:31 -0400 Subject: [PATCH 038/141] Setup Scene to deserialize objects using new framework --- source/dash/core/scene.d | 15 ++++++++++----- source/dash/utility/data/serialization.d | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/source/dash/core/scene.d b/source/dash/core/scene.d index 48b7cc13..0112a69e 100644 --- a/source/dash/core/scene.d +++ b/source/dash/core/scene.d @@ -43,12 +43,17 @@ public: */ final void loadObjects( string objectPath = "" ) { - foreach( ymlFile; buildNormalizedPath( Resources.Objects, objectPath ).loadYamlFiles() ) + foreach( file; buildNormalizedPath( Resources.Objects, objectPath ).scanDirectory() ) { - // Create the object - auto newObj = GameObject.createFromYaml( ymlFile[ 0 ] ); - _root.addChild( newObj ); - goResources[ ymlFile[ 1 ] ] ~= newObj; + // Create the objects + foreach( desc; file.deserializeMultiFile!( GameObject.Description )() ) + { + auto newObj = GameObject.create( desc ); + _root.addChild( newObj ); + goResources[ file ] ~= newObj; + + logDebug( "Adding object with components: ", desc.components ); + } } } diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index 84ebb164..5bde0b7a 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -48,7 +48,7 @@ T deserializeFile( T )( Resource file, SerializationMode mode = SerializationMod T handleYaml() { - Yaml content = Loader.fromString( file.readText() ).load(); + Yaml content = Loader.fromString( cast(char[])file.readText() ).load(); return deserializeYaml!T( content ); } From 6472b7cbf0c6a1eda609572c36a8502ed30c51b5 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 16 Sep 2014 13:08:29 -0400 Subject: [PATCH 039/141] Fixed auto serialization registration of Components --- source/dash/components/component.d | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index e8607066..7b191842 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -44,7 +44,15 @@ public: { if( auto type = "Type" in d ) { - return $typeDeserializers[ type.get!string ]( d ); + if( auto cereal = type.get!string in $typeDeserializers ) + { + return ( *cereal )( d ); + } + else + { + logWarning( "Component's \"Type\" not found: ", type.get!string ); + return null; + } } else { @@ -124,8 +132,7 @@ public: return $type(); //return serializeTo$type( SerializationDescription( cast(T)c ) ); }; - - Component.$typeDeserializers[ typeid(T).name ] = ( $type node ) + Component.$typeDeserializers[ T.stringof ] = ( $type node ) { return null; //return deserialize$type!( SerializationDescription )( node ).createInstance(); From b0a7686a6476735777d3e95af4754347945d93df Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 16 Sep 2014 13:20:03 -0400 Subject: [PATCH 040/141] Restructure descriptions --- source/dash/core/gameobject.d | 58 ++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 97be0477..cf5a4caf 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -94,22 +94,6 @@ public: @rename( "Components" ) @optional Component[] components; - - /** - * Create a description from a GameObject. - * - * Returns: - * A new description with components and info. - */ - this( GameObject obj ) - { - name = obj.name; - prefabName = ""; - prefab = null; - transform = typeof(obj.transform).Description( obj.transform ); - children = obj.children.map!( child => typeof(child).Description( child ) ).array(); - components = obj.componentList.values.dup; - } } /// The current transform of the object. @@ -290,6 +274,27 @@ public: return obj; } + /** + * Create a description from a GameObject. + * + * Returns: + * A new description with components and info. + */ + Description toDescription() + { + Description desc; + with( desc ) + { + name = this.name; + prefabName = ""; + prefab = null; + transform = this.transform.toDescription(); + children = this.children.map!( child => child.toDescription() ).array(); + components = this.componentList.values.dup; + } + return desc; + } + /// To complement the descriptions, and make serialization easier. static GameObject fromRepresentation( Description desc ) { @@ -298,7 +303,7 @@ public: /// ditto Description toRepresentation() { - return GameObject.Description( this ); + return toDescription(); } static assert( isCustomSerializable!GameObject ); @@ -545,13 +550,24 @@ public: /// The position of the object. @rename( "Scale" ) @asArray @optional float[3] scale; + } - this( Transform t ) + /** + * Create a description from a Transform. + * + * Returns: + * A new description with components. + */ + Description toDescription() + { + Description desc; + with( desc ) { - position = t.position.vector[ 0..3 ]; - rotation = [ t.rotation.yaw, t.rotation.pitch, t.rotation.roll ]; - scale = t.scale.vector[ 0..3 ]; + position = this.position.vector[ 0..3 ]; + rotation = [ this.rotation.yaw, this.rotation.pitch, this.rotation.roll ]; + scale = this.scale.vector[ 0..3 ]; } + return desc; } // these should remain public fields, properties return copies not references From c514c7fa3709393274610fa485ba5b39db6ca635 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Wed, 17 Sep 2014 12:48:36 -0400 Subject: [PATCH 041/141] Fixed view-space culling [skip ci] --- source/dash/graphics/adapters/gl.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dash/graphics/adapters/gl.d b/source/dash/graphics/adapters/gl.d index 9baef38b..d6743369 100644 --- a/source/dash/graphics/adapters/gl.d +++ b/source/dash/graphics/adapters/gl.d @@ -188,7 +188,7 @@ public: mat4f worldView = scene.camera.viewMatrix * object.transform.matrix; mat4f worldViewProj = projection * worldView; - if( !( object.mesh.boundingBox in Frustum!float( worldViewProj ) ) ) + if( worldViewProj.frustum().contains( object.mesh.boundingBox ) == Frustum!float.OUTSIDE ) { // If we can't see an object, don't draw it. continue; From 7b763562da8ce0aaa326e8ef7eef3021b830501c Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Wed, 17 Sep 2014 13:25:21 -0400 Subject: [PATCH 042/141] Removed old yaml attributes, merge cleanup [skip ci] --- source/dash/components/camera.d | 7 +- source/dash/components/component.d | 77 ------ source/dash/components/lights.d | 13 +- source/dash/components/material.d | 1 - source/dash/components/mesh.d | 4 +- source/dash/core/gameobject.d | 93 +------ source/dash/core/prefabs.d | 3 +- source/dash/utility/config.d | 428 +---------------------------- source/dash/utility/data/yaml.d | 301 +++++++++++++++++++- 9 files changed, 319 insertions(+), 608 deletions(-) diff --git a/source/dash/components/camera.d b/source/dash/components/camera.d index 4b1350c8..d8cd955f 100644 --- a/source/dash/components/camera.d +++ b/source/dash/components/camera.d @@ -15,7 +15,6 @@ mixin( registerComponents!() ); /** * Camera manages a view and projection matrix. */ -@yamlComponent( "Camera" ) final class Camera : Component, IDirtyable { private: @@ -35,11 +34,11 @@ public: mixin( ThisDirtyGetter!( _viewMatrix, updateViewMatrix ) ); /// TODO mixin( ThisDirtyGetter!( _inverseViewMatrix, updateViewMatrix ) ); - @field( "FOV" ) + @rename( "FOV" ) float fov; - @field( "Near" ) + @rename( "Near" ) float near; - @field( "Far" ) + @rename( "Far" ) float far; /** diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 7b191842..79624b75 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -261,80 +261,3 @@ private: )( "", description.fields ); } (); } - -/** - * Meant to be added to components that can be set from YAML. - * Example: - * --- - * @yamlObject("Test") - * class Test : YamlObject - * { - * @field("X") - * int x; - * } - * --- - */ -auto yamlObject( string name = "" ) -{ - return YamlUDA( YamlType.Object, name, null ); -} - -/** - * Meant to be added to components that can be set from YAML. - * Example: - * --- - * @yamlComponent("Test") - * class Test : Component - * { - * @field("X") - * int x; - * } - * --- - */ -auto yamlComponent( string loader = "null" )( string name = "" ) -{ - return YamlUDA( YamlType.Component, name, mixin( loader ) ); -} - -/** - * Meant to be added to members for making them YAML accessible. - * - * Params: - * name = The name of the tag in YAML. - * loader = If cannot be loaded directly, specify function used to load it. - * - * Example: - * --- - * @yamlComponent("Test") - * class Test : Component - * { - * @field("X") - * int x; - * } - * --- - */ -/* -auto field( string name = "" ) -{ - return YamlUDA( YamlType.Field, name, null ); -} -*/ -deprecated( "Use rename instead." ) -alias field = rename; - -/// Used to create objects from yaml. The key is the YAML name of the type. -Object delegate( Node )[string] createYamlObject; -/// Used to create components from yaml. The key is the YAML name of the type. -Component delegate( Node )[string] createYamlComponent; -/// Refresh any object defined from yaml. The key is the typeid of the type. -void delegate( Object, Node )[TypeInfo] refreshYamlObject; - -enum YamlType { Object, Component, Field } -private alias LoaderFunction = Object delegate( string ); - -struct YamlUDA -{ - YamlType type; - string name; - LoaderFunction loader; -} diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index d49d2aa6..c910abe8 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -21,10 +21,10 @@ abstract class Light : Component { public: /// The color the light gives off. - @field( "Color" ) + @rename( "Color" ) vec3f color; /// If it should cast shadows - @field( "CastShadows" ) + @rename( "CastShadows" ) bool castShadows; this( vec3f color ) @@ -40,7 +40,6 @@ public: /** * Ambient Light */ -@yamlComponent() class AmbientLight : Light { this( vec3f color = vec3f() ) @@ -52,7 +51,6 @@ class AmbientLight : Light /** * Directional Light */ -@yamlComponent() class DirectionalLight : Light { private: @@ -63,7 +61,6 @@ private: public: /// The direction the light points in. - @field( "Direction" ) vec3f direction; /// The FrameBuffer for the shadowmap. mixin( Property!( _shadowMapFrameBuffer ) ); @@ -183,7 +180,6 @@ public: /** * Point Light */ -@yamlComponent() class PointLight : Light { private: @@ -191,10 +187,10 @@ private: public: /// The area that lighting will be calculated for. - @field( "Radius" ) + @rename( "Radius" ) float radius; /// The light's exponential attenuation modifier. - @field( "FalloffRate" ) + @rename( "FalloffRate" ) float falloffRate; this( vec3f color = vec3f(), float radius = 0.0f, float falloffRate = 0.0f ) @@ -231,7 +227,6 @@ public: /** * SpotLight Stub */ -@yamlComponent() class SpotLight : Light { public: diff --git a/source/dash/components/material.d b/source/dash/components/material.d index d0c4870c..bc85ef28 100644 --- a/source/dash/components/material.d +++ b/source/dash/components/material.d @@ -13,7 +13,6 @@ mixin( registerComponents!() ); /** * A collection of textures that serve different purposes in the rendering pipeline. */ -@yamlObject() final class MaterialAsset : Asset { public: diff --git a/source/dash/components/mesh.d b/source/dash/components/mesh.d index 583e95f7..ab44e29d 100644 --- a/source/dash/components/mesh.d +++ b/source/dash/components/mesh.d @@ -298,10 +298,10 @@ public: // Add mesh if( scene.mNumMeshes > 0 ) { - Mesh tempMesh = new Mesh( resource.fullPath, scene.mMeshes[ 0 ] ); + auto tempMesh = new MeshAsset( resource.fullPath, scene.mMeshes[ 0 ] ); if( scene.mNumAnimations > 0 ) - tempMesh.animationData = new AssetAnimation( scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); + tempMesh.animationData = new AnimationData( scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); // Copy attributes _glVertexArray = tempMesh._glVertexArray; diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index b811d885..549299ab 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -137,87 +137,6 @@ public: /// Allow setting of state flags directly. //alias stateFlags this; - /** - * Create a GameObject from a Yaml node. - * - * Params: - * yamlObj = The YAML node to pull info from. - * - * Returns: - * A new game object with components and info pulled from yaml. - */ - static GameObject createFromYaml( Node yamlObj ) - { - GameObject obj; - string prop; - Node innerNode; - - if( yamlObj.tryFind( "InstanceOf", prop ) ) - { - obj = Prefabs[ prop ].createInstance(); - } - else - { - obj = new GameObject; - } - - // Set object name - obj.name = yamlObj[ "Name" ].as!string; - - // Init transform - if( yamlObj.tryFind( "Transform", innerNode ) ) - { - vec3f transVec; - if( innerNode.tryFind( "Scale", transVec ) ) - obj.transform.scale = transVec; - if( innerNode.tryFind( "Position", transVec ) ) - obj.transform.position = transVec; - if( innerNode.tryFind( "Rotation", transVec ) ) - obj.transform.rotation = quatf.fromEulerAngles( transVec.x.radians, transVec.y.radians, transVec.z.radians ); - } - - if( yamlObj.tryFind( "Children", innerNode ) ) - { - if( innerNode.isSequence ) - { - foreach( Node child; innerNode ) - { - // If inline object, create it and add it as a child. - if( child.isMapping ) - obj.addChild( GameObject.createFromYaml( child ) ); - // Add child name to map. - else - logWarning( "Specifing child objects by name is deprecated. Please add ", child.get!string, " as an inline child of ", obj.name, "." ); - } - } - else - { - logWarning( "Scalar values and mappings in 'Children' of ", obj.name, " are not supported, and it is being ignored." ); - } - } - - // Init components - foreach( string key, Node componentNode; yamlObj ) - { - if( key == "Name" || key == "InstanceOf" || key == "Transform" || key == "Children" ) - continue; - - if( auto init = key in createYamlComponent ) - { - auto newComp = cast(Component)(*init)( componentNode ); - obj.addComponent( newComp ); - newComp.owner = obj; - } - else - logWarning( "Unknown key: ", key ); - } - - foreach( comp; obj.componentList ) - comp.initialize(); - - return obj; - } - /** * Create a GameObject from a description object. * @@ -517,9 +436,9 @@ private: void opAssign( Description desc ) { - position = vec3( desc.position[] ); - rotation = quat.euler_rotation( desc.rotation[ 1 ], desc.rotation[ 0 ], desc.rotation[ 2 ] ); - scale = vec3( desc.scale[] ); + position = vec3f( desc.position[] ); + rotation = quatf.fromEulerAngles( desc.rotation[ 1 ], desc.rotation[ 0 ], desc.rotation[ 2 ] ); + scale = vec3f( desc.scale[] ); } /** @@ -566,9 +485,9 @@ public: Description desc; with( desc ) { - position = this.position.vector[ 0..3 ]; - rotation = [ this.rotation.yaw, this.rotation.pitch, this.rotation.roll ]; - scale = this.scale.vector[ 0..3 ]; + position = this.position.v[ 0..3 ]; + rotation = this.rotation.toEulerAngles()[ 0..3 ]; + scale = this.scale.v[ 0..3 ]; } return desc; } diff --git a/source/dash/core/prefabs.d b/source/dash/core/prefabs.d index 5493284c..83cd2639 100644 --- a/source/dash/core/prefabs.d +++ b/source/dash/core/prefabs.d @@ -76,8 +76,7 @@ private: /** * A prefab that allows for quick object creation. */ -@yamlObject() -final class Prefab +final class Prefab : Asset { public: /// The name of the prefab. diff --git a/source/dash/utility/config.d b/source/dash/utility/config.d index ecf2709e..459a7cdf 100644 --- a/source/dash/utility/config.d +++ b/source/dash/utility/config.d @@ -3,15 +3,13 @@ */ module dash.utility.config; import dash.components.component; -import dash.utility.resources, dash.utility.output; +import dash.utility.resources, dash.utility.output, dash.utility.data; public import yaml; import std.variant, std.algorithm, std.traits, std.range, std.array, std.conv, std.file, std.typecons, std.path; -private string fileToYaml( string filePath ) { return filePath.relativePath( getcwd() ).replace( "\\", "/" ).replace( "../", "" ).replace( "/", "." ).replace( ".yml", "" ); } - /** * Place this mixin anywhere in your game code to allow the Content.yml file * to be imported at compile time. Note that this will only actually import @@ -29,368 +27,6 @@ mixin template ContentImport() } } -/// The node config values are stored. -Node config; -/// The constructor used to load load new yaml files. -Constructor constructor; -/// The string to store imported yaml content in. -version( EmbedContent ) string contentYML; -private Node contentNode; -/// The file storing config. -private Resource configFile = Resource( "" ); - -/// Initializes contentNode and constructor. -static this() -{ - constructor = new Constructor; - contentNode = Node( YAMLNull() ); - - import dash.components.lights; - import dash.graphics.shaders.shaders; - import dash.utility.output; - import gfm.math.vector, gfm.math.quaternion; - - constructor.addConstructorScalar( "!Vector2", ( ref Node node ) - { - vec2f result; - string[] vals = node.as!string.split(); - if( vals.length != 2 ) - throw new Exception( "Invalid number of values: " ~ node.as!string ); - - result.x = vals[ 0 ].to!float; - result.y = vals[ 1 ].to!float; - return result; - } ); - constructor.addConstructorScalar( "!Vector3", ( ref Node node ) - { - vec3f result; - string[] vals = node.as!string.split(); - if( vals.length != 3 ) - throw new Exception( "Invalid number of values: " ~ node.as!string ); - - result.x = vals[ 0 ].to!float; - result.y = vals[ 1 ].to!float; - result.z = vals[ 2 ].to!float; - return result; - } ); - constructor.addConstructorScalar( "!Quaternion", ( ref Node node ) - { - quatf result; - string[] vals = node.as!string.split(); - if( vals.length != 3 ) - throw new Exception( "Invalid number of values: " ~ node.as!string ); - - result.x = vals[ 0 ].to!float; - result.y = vals[ 1 ].to!float; - result.z = vals[ 2 ].to!float; - result.w = vals[ 3 ].to!float; - return result; - } ); - constructor.addConstructorScalar( "!Verbosity", &constructConv!Verbosity ); - constructor.addConstructorScalar( "!Shader", ( ref Node node ) => Shaders.get( node.get!string ) ); - //constructor.addConstructorScalar( "!Texture", ( ref Node node ) => Assets.get!Texture( node.get!string ) ); - //constructor.addConstructorScalar( "!Mesh", ( ref Node node ) => Assets.get!Mesh( node.get!string ) ); - //constructor.addConstructorScalar( "!Material", ( ref Node node ) => Assets.get!Material( node.get!string ) ); -} - -/** - * Process all yaml files in a directory. - * - * Params: - * folder = The folder to iterate over. - */ -Tuple!( Node, Resource )[] loadYamlFiles( string folder ) -{ - Tuple!( Node, Resource )[] nodes; - - if( contentNode.isNull ) - { - // Actually scan directories - foreach( file; scanDirectory( folder, "*.yml" ) ) - { - auto loader = Loader( file.fullPath ); - loader.constructor = constructor; - - try - { - // Iterate over all documents in a file - foreach( doc; loader ) - { - nodes ~= tuple( doc, file ); - } - } - catch( YAMLException e ) - { - logFatal( "Error parsing file ", file.baseFileName, ": ", e.msg ); - } - } - } - else - { - auto fileNode = contentNode.find( folder.fileToYaml ); - - foreach( string fileName, Node fileContent; fileNode ) - { - if( fileContent.isSequence ) - { - foreach( Node childChild; fileContent ) - nodes ~= tuple( childChild, configFile ); - } - else if( fileContent.isMapping ) - { - nodes ~= tuple( fileContent, configFile ); - } - } - } - - return nodes; -} - -/** - * Process all documents files in a directory. - * - * Params: - * folder = The folder to iterate over. - */ -Node[] loadYamlDocuments( string path ) -{ - return loadYamlFiles( path ).map!( tup => tup[ 0 ] ).array; -} - -/** - * Processes all yaml files in a directory, and converts each document into an object of type T. - * - * Params: - * folder = The folder to look in. - */ -T[] loadYamlObjects( T )( string folder ) -{ - return folder.loadYamlDocuments.map!(yml => yml.getObject!T() ); -} - -/** - * Load a yaml file with the engine-specific mappings. - * - * Params: - * filePath = The path to file to load. - */ -Node loadYamlFile( string filePath ) -{ - if( contentNode.isNull ) - { - auto loader = Loader( filePath ); - loader.constructor = constructor; - try - { - return loader.load(); - } - catch( YAMLException e ) - { - logFatal( "Error parsing file ", Resource( filePath ).baseFileName, ": ", e.msg ); - return Node(); - } - } - else - { - return contentNode.find( filePath.fileToYaml ); - } -} - -/** - * Load a yaml file with the engine-specific mappings. - * - * Params: - * filePath = The path to file to load. - */ -Node[] loadAllDocumentsInYamlFile( string filePath ) -{ - if( contentNode.isNull ) - { - auto loader = Loader( filePath ); - loader.constructor = constructor; - try - { - Node[] nodes; - foreach( document; loader ) - nodes ~= document; - return nodes; - } - catch( YAMLException e ) - { - logFatal( "Error parsing file ", Resource( filePath ).baseFileName, ": ", e.msg ); - return []; - } - } - else - { - return contentNode.find( filePath.fileToYaml ).get!( Node[] ); - } -} - -/** - * Get the element, cast to the given type, at the given path, in the given node. - * - * Params: - * node = The node to search. - * path = The path to find the item at. - */ -final T find( T = Node )( Node node, string path ) -{ - T temp; - if( node.tryFind( path, temp ) ) - return temp; - else - throw new YAMLException( "Path " ~ path ~ " not found in the given node." ); -} -/// -unittest -{ - import std.stdio; - import std.exception; - - writeln( "Dash Config find unittest" ); - - auto n1 = Node( [ "test1": 10 ] ); - - assert( n1.find!int( "test1" ) == 10, "Config.find error." ); - - assertThrown!YAMLException(n1.find!int( "dontexist" )); - - // nested test - auto n2 = Node( ["test2": n1] ); - auto n3 = Node( ["test3": n2] ); - - assert( n3.find!int( "test3.test2.test1" ) == 10, "Config.find nested test failed"); - - auto n4 = Loader.fromString( - "test3:\n" ~ - " test2:\n" ~ - " test1: 10" ).load; - assert( n4.find!int( "test3.test2.test1" ) == 10, "Config.find nested test failed"); -} - -/** - * Try to get the value at path, assign to result, and return success. - * - * Params: - * node = The node to search. - * path = The path to look for in the node. - * result = [ref] The value to assign the result to. - * - * Returns: Whether or not the path was found. - */ -final bool tryFind( T )( Node node, string path, ref T result ) nothrow @safe -{ - // If anything goes wrong, it means the node wasn't found. - scope( failure ) return false; - - Node res; - bool found = node.tryFind( path, res ); - - if( found ) - { - static if( !isSomeString!T && is( T U : U[] ) ) - { - assert( res.isSequence, "Trying to access non-sequence node " ~ path ~ " as an array." ); - - foreach( Node element; res ) - result ~= element.get!U; - } - else static if( __traits( compiles, res.getObject!T ) ) - { - result = res.getObject!T; - } - else - { - result = res.get!T; - } - } - - return found; -} - -/// ditto -final bool tryFind( T: Node )( Node node, string path, ref T result ) nothrow @safe -{ - // If anything goes wrong, it means the node wasn't found. - scope( failure ) return false; - - Node current; - string left; - string right = path; - - for( current = node; right.length; ) - { - auto split = right.countUntil( '.' ); - - if( split == -1 ) - { - left = right; - right.length = 0; - } - else - { - left = right[ 0..split ]; - right = right[ split + 1..$ ]; - } - - if( !current.isMapping || !current.containsKey( left ) ) - return false; - - current = current[ left ]; - } - - result = current; - - return true; -} - -/// ditto -final bool tryFind( T = Node )( Node node, string path, ref Variant result ) nothrow @safe -{ - // Get the value - T temp; - bool found = node.tryFind( path, temp ); - - // Assign and return results - if( found ) - result = temp; - - return found; -} - -/** - * You may not get a variant from a node. You may assign to one, - * but you must specify a type to search for. - */ -@disable bool tryFind( T: Variant )( Node node, string path, ref Variant result ); - -unittest -{ - import std.stdio; - writeln( "Dash Config tryFind unittest" ); - - auto n1 = Node( [ "test1": 10 ] ); - - int val; - assert( n1.tryFind( "test1", val ), "Config.tryFind failed." ); - assert( !n1.tryFind( "dontexist", val ), "Config.tryFind returned true." ); -} - -/** - * Get element as a file path relative to the content home. - * - * Params: - * node = The node to search for the path in. - * path = The path to search the node for. - * - * Returns: The value at path relative to FilePath.ResourceHome. - */ -final string findPath( Node node, string path ) -{ - return Resources.Home ~ node.find!string( path );//buildNormalizedPath( FilePath.ResourceHome, get!string( path ) );; -} - /** * Get a YAML map as a D object of type T. * @@ -400,67 +36,9 @@ final string findPath( Node node, string path ) * * Returns: An object of type T that has all fields from the YAML node assigned to it. */ -final T getObject( T )( Node node ) -{ - T toReturn; - - static if( is( T == class ) ) - toReturn = new T; +deprecated( "Use deserializeYaml" ) +alias getObject = deserializeYaml; - // Get each member of the type - foreach( memberName; __traits(derivedMembers, T) ) - { - // Make sure member is accessable - enum protection = __traits( getProtection, __traits( getMember, toReturn, memberName ) ); - static if( protection == "public" || protection == "export" && - __traits( compiles, isMutable!( __traits( getMember, toReturn, memberName ) ) ) ) - { - // If it is a field and not a function, tryGet it's value - static if( !__traits( compiles, ParameterTypeTuple!( __traits( getMember, toReturn, memberName ) ) ) && - !__traits( compiles, isBasicType!( __traits( getMember, toReturn, memberName ) ) ) ) - { - // Make sure member is mutable - static if( isMutable!( typeof( __traits( getMember, toReturn, memberName ) ) ) ) - { - node.tryFind( memberName, __traits( getMember, toReturn, memberName ) ); - } - } - else - { - // Iterate over each overload of the function (common to have getter and setter) - foreach( func; __traits( getOverloads, T, memberName ) ) - { - enum funcProtection = __traits( getProtection, func ); - static if( funcProtection == "public" || funcProtection == "export" ) - { - // Get the param types of the function - alias params = ParameterTypeTuple!func; - - // If it can be a setter and is a property - static if( params.length == 1 && ( functionAttributes!func & FunctionAttribute.property ) ) - { - // Else, set as temp - static if( is( params[ 0 ] == enum ) ) - { - string tempValue; - } - else - { - params[ 0 ] otherTempValue; - auto tempValue = cast()otherTempValue; - } - - if( node.tryFind( memberName, tempValue ) ) - mixin( "toReturn." ~ memberName ) = tempValue.to!(params[0]); - } - } - } - } - } - } - - return toReturn; -} unittest { import std.stdio; diff --git a/source/dash/utility/data/yaml.d b/source/dash/utility/data/yaml.d index d3360c20..9c52ec1b 100644 --- a/source/dash/utility/data/yaml.d +++ b/source/dash/utility/data/yaml.d @@ -1,8 +1,9 @@ module dash.utility.data.yaml; +import dash.utility.resources, dash.utility.output; public import yaml; import vibe.data.serialization; -import std.traits, std.range; +import std.traits, std.range, std.typecons, std.variant; /// Convience alias alias Yaml = Node; @@ -58,6 +59,304 @@ static assert(is(typeof( deserializeYaml!string( Node( "" ) ) ))); /// Does the type support custom serialization. enum isYamlSerializable( T ) = is( typeof( T.init.toYaml() ) == Node ) && is( typeof( T.fromYaml( Node() ) ) == T ); +/** +* Process all yaml files in a directory. +* +* Params: +* folder = The folder to iterate over. +*/ +Tuple!( Node, Resource )[] loadYamlFiles( string folder ) +{ + Tuple!( Node, Resource )[] nodes; + + if( contentNode.isNull ) + { + // Actually scan directories + foreach( file; scanDirectory( folder, "*.yml" ) ) + { + auto loader = Loader( file.fullPath ); + loader.constructor = constructor; + + try + { + // Iterate over all documents in a file + foreach( doc; loader ) + { + nodes ~= tuple( doc, file ); + } + } + catch( YAMLException e ) + { + logFatal( "Error parsing file ", file.baseFileName, ": ", e.msg ); + } + } + } + else + { + auto fileNode = contentNode.find( folder.fileToYaml ); + + foreach( string fileName, Node fileContent; fileNode ) + { + if( fileContent.isSequence ) + { + foreach( Node childChild; fileContent ) + nodes ~= tuple( childChild, configFile ); + } + else if( fileContent.isMapping ) + { + nodes ~= tuple( fileContent, configFile ); + } + } + } + + return nodes; +} + +/** +* Process all documents files in a directory. +* +* Params: +* folder = The folder to iterate over. +*/ +Node[] loadYamlDocuments( string path ) +{ + return loadYamlFiles( path ).map!( tup => tup[ 0 ] ).array; +} + +/** +* Processes all yaml files in a directory, and converts each document into an object of type T. +* +* Params: +* folder = The folder to look in. +*/ +T[] loadYamlObjects( T )( string folder ) +{ + return folder.loadYamlDocuments.map!(yml => yml.getObject!T() ); +} + +/** +* Load a yaml file with the engine-specific mappings. +* +* Params: +* filePath = The path to file to load. +*/ +Node loadYamlFile( string filePath ) +{ + if( contentNode.isNull ) + { + auto loader = Loader( filePath ); + loader.constructor = constructor; + try + { + return loader.load(); + } + catch( YAMLException e ) + { + logFatal( "Error parsing file ", Resource( filePath ).baseFileName, ": ", e.msg ); + return Node(); + } + } + else + { + return contentNode.find( filePath.fileToYaml ); + } +} + +/** +* Load a yaml file with the engine-specific mappings. +* +* Params: +* filePath = The path to file to load. +*/ +Node[] loadAllDocumentsInYamlFile( string filePath ) +{ + if( contentNode.isNull ) + { + auto loader = Loader( filePath ); + loader.constructor = constructor; + try + { + Node[] nodes; + foreach( document; loader ) + nodes ~= document; + return nodes; + } + catch( YAMLException e ) + { + logFatal( "Error parsing file ", Resource( filePath ).baseFileName, ": ", e.msg ); + return []; + } + } + else + { + return contentNode.find( filePath.fileToYaml ).get!( Node[] ); + } +} + +/** +* Get the element, cast to the given type, at the given path, in the given node. +* +* Params: +* node = The node to search. +* path = The path to find the item at. +*/ +final T find( T = Node )( Node node, string path ) +{ + T temp; + if( node.tryFind( path, temp ) ) + return temp; + else + throw new YAMLException( "Path " ~ path ~ " not found in the given node." ); +} +/// +unittest +{ + import std.stdio; + import std.exception; + + writeln( "Dash Config find unittest" ); + + auto n1 = Node( [ "test1": 10 ] ); + + assert( n1.find!int( "test1" ) == 10, "Config.find error." ); + + assertThrown!YAMLException(n1.find!int( "dontexist" )); + + // nested test + auto n2 = Node( ["test2": n1] ); + auto n3 = Node( ["test3": n2] ); + + assert( n3.find!int( "test3.test2.test1" ) == 10, "Config.find nested test failed"); + + auto n4 = Loader.fromString( + "test3:\n" ~ + " test2:\n" ~ + " test1: 10" ).load; + assert( n4.find!int( "test3.test2.test1" ) == 10, "Config.find nested test failed"); +} + +/** +* Try to get the value at path, assign to result, and return success. +* +* Params: +* node = The node to search. +* path = The path to look for in the node. +* result = [ref] The value to assign the result to. +* +* Returns: Whether or not the path was found. +*/ +final bool tryFind( T )( Node node, string path, ref T result ) nothrow @safe +{ + // If anything goes wrong, it means the node wasn't found. + scope( failure ) return false; + + Node res; + bool found = node.tryFind( path, res ); + + if( found ) + { + static if( !isSomeString!T && is( T U : U[] ) ) + { + assert( res.isSequence, "Trying to access non-sequence node " ~ path ~ " as an array." ); + + foreach( Node element; res ) + result ~= element.get!U; + } + else static if( __traits( compiles, res.getObject!T ) ) + { + result = res.getObject!T; + } + else + { + result = res.get!T; + } + } + + return found; +} + +/// ditto +final bool tryFind( T: Node )( Node node, string path, ref T result ) nothrow @safe +{ + // If anything goes wrong, it means the node wasn't found. + scope( failure ) return false; + + Node current; + string left; + string right = path; + + for( current = node; right.length; ) + { + auto split = right.countUntil( '.' ); + + if( split == -1 ) + { + left = right; + right.length = 0; + } + else + { + left = right[ 0..split ]; + right = right[ split + 1..$ ]; + } + + if( !current.isMapping || !current.containsKey( left ) ) + return false; + + current = current[ left ]; + } + + result = current; + + return true; +} + +/// ditto +final bool tryFind( T = Node )( Node node, string path, ref Variant result ) nothrow @safe +{ + // Get the value + T temp; + bool found = node.tryFind( path, temp ); + + // Assign and return results + if( found ) + result = temp; + + return found; +} + +/** +* You may not get a variant from a node. You may assign to one, +* but you must specify a type to search for. +*/ +@disable bool tryFind( T: Variant )( Node node, string path, ref Variant result ); + +unittest +{ + import std.stdio; + writeln( "Dash Config tryFind unittest" ); + + auto n1 = Node( [ "test1": 10 ] ); + + int val; + assert( n1.tryFind( "test1", val ), "Config.tryFind failed." ); + assert( !n1.tryFind( "dontexist", val ), "Config.tryFind returned true." ); +} + +/** +* Get element as a file path relative to the content home. +* +* Params: +* node = The node to search for the path in. +* path = The path to search the node for. +* +* Returns: The value at path relative to FilePath.ResourceHome. +*/ +final string findPath( Node node, string path ) +{ + return Resources.Home ~ node.find!string( path );//buildNormalizedPath( FilePath.ResourceHome, get!string( path ) );; +} + /// Serializer for vibe.d framework. struct YamlSerializer { From 3216c194b141ccedca09fb015e3b0d40fc50cdeb Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Wed, 17 Sep 2014 17:49:14 -0400 Subject: [PATCH 043/141] More conversions [skip ci] --- source/dash/editor/websockets.d | 2 +- source/dash/utility/config.d | 158 ++++++++++------------- source/dash/utility/data/serialization.d | 23 +++- source/dash/utility/data/yaml.d | 28 ---- source/dash/utility/resources.d | 4 +- 5 files changed, 89 insertions(+), 126 deletions(-) diff --git a/source/dash/editor/websockets.d b/source/dash/editor/websockets.d index d0a7413f..0a23f91f 100644 --- a/source/dash/editor/websockets.d +++ b/source/dash/editor/websockets.d @@ -16,7 +16,7 @@ public: // Default port to 8080 ushort bindPort = 8080; - config.tryFind( "Editor.Port", bindPort ); + bindPort = config.Editor.Port; auto router = new URLRouter; router.get( "/ws", handleWebSockets( &handleConnection ) ); diff --git a/source/dash/utility/config.d b/source/dash/utility/config.d index 459a7cdf..89ccf44c 100644 --- a/source/dash/utility/config.d +++ b/source/dash/utility/config.d @@ -7,25 +7,7 @@ import dash.utility.resources, dash.utility.output, dash.utility.data; public import yaml; -import std.variant, std.algorithm, std.traits, std.range, - std.array, std.conv, std.file, std.typecons, std.path; - -/** - * Place this mixin anywhere in your game code to allow the Content.yml file - * to be imported at compile time. Note that this will only actually import - * the file when EmbedContent is listed as a defined version. - */ -mixin template ContentImport() -{ - version( EmbedContent ) - { - static this() - { - import dash.utility.config; - contentYML = import( "Content.yml" ); - } - } -} +import std.datetime; /** * Get a YAML map as a D object of type T. @@ -39,94 +21,86 @@ mixin template ContentImport() deprecated( "Use deserializeYaml" ) alias getObject = deserializeYaml; -unittest -{ - import std.stdio; - writeln( "Dash Config getObject unittest" ); - - auto t = Node( ["x": 5, "y": 7, "z": 9] ).getObject!Test(); - - assert( t.x == 5 ); - assert( t.y == 7 ); - assert( t.z == 9 ); -} -version(unittest) class Test +/** + * The global instance of config. + */ +private Config configInst; +/// ditto +const(Config) config() @property { - int x; - int y; - private int _z; - - @property int z() { return _z; } - @property void z( int newZ ) { _z = newZ; } + return configInst; } /** * Static class which handles the configuration options and YAML interactions. */ -final abstract class Config +struct Config { -public static: - /** - * TODO - */ - void initialize() +public: + LoggerSettings Logging; + DisplaySettings Display; + GraphicsSettings Graphics; + UserInterfaceSettings UserInterface; + EditorSettings Editor; + + static struct LoggerSettings { - version( EmbedContent ) - { - logDebug( "Using imported Content.yml file." ); - assert( contentYML, "EmbedContent version set, mixin not used." ); - auto loader = Loader.fromString( contentYML ); - loader.constructor = constructor; - contentNode = loader.load(); - // Null content yml so it can be collected. - contentYML = null; - } - else version( unittest ) - { - auto loader = Loader.fromString( testYML ); - loader.constructor = constructor; - contentNode = loader.load(); - } - else + string FilePath; + Verbosities Debug; + Verbosities Release; + + static struct Verbosities { - if( exists( Resources.CompactContentFile ) ) - { - logDebug( "Using Content.yml file." ); - configFile = Resource( Resources.CompactContentFile ); - contentNode = Resources.CompactContentFile.loadYamlFile(); - } - else - { - logDebug( "Using normal content directory." ); - configFile = Resource( Resources.ConfigFile ); - } + Verbosity OutputVerbosity; + Verbosity LoggingVerbosity; } + } + + static struct DisplaySettings + { + bool Fullscreen; + uint Height; + uint Width; + } + + static struct GraphicsSettings + { + bool BackfaceCulling; + bool VSync; + } + + static struct UserInterfaceSettings + { + string FilePath; + } + + static struct EditorSettings + { + ushort Port; + } - config = Resources.ConfigFile.loadYamlFile(); +static: + private Resource resource = Resource( "" ); + private SysTime lastModified; + + void initialize() + { + import std.file: timeLastModified; + + auto res = deserializeFileByName!Config( Resources.ConfigFile ); + config = res[ 0 ]; + resource = res[ 1 ]; + lastModified = resource.fullPath.timeLastModified; } - void refresh() + void update() { - // No need to refresh, there can be no changes. - version( EmbedContent ) { } - else + import std.file: timeLastModified; + + if( lastModified < resource.fullPath.timeLastModified ) { - if( exists( Resources.CompactContentFile ) ) - { - logDebug( "Using Content.yml file." ); - if( configFile.needsRefresh ) - { - contentNode = Node( YAMLNull() ); - contentNode = Resources.CompactContentFile.loadYamlFile(); - config = Resources.ConfigFile.loadYamlFile(); - } - } - else - { - logDebug( "Using normal content directory." ); - if( configFile.needsRefresh ) - config = Resources.ConfigFile.loadYamlFile(); - } + config = deserializeFile( resource ); + lastModified = resource.fullPath.timeLastModified; } } } diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index 5bde0b7a..4b47d9d6 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -2,7 +2,7 @@ module dash.utility.data.serialization; import dash.utility.resources; import dash.utility.data.yaml; import vibe.data.json, vibe.data.bson; -import std.typecons: tuple; +import std.typecons: Tuple, tuple; // Serialization attributes public import vibe.data.serialization: asArray, byName, ignore, name, optional, isCustomSerializable; @@ -23,6 +23,23 @@ enum SerializationMode Yaml, } +/** + * Deserializes a file. + * + * Params: + * fileName = The name of the file to deserialize. + * + * Returns: The deserialized object. + */ +Tuple!( T, Resource ) deserializeFileByName( T )( string fileName, SerializationMode mode = SerializationMode.Default ) +{ + import std.path: dirName; + import std.array: front; + + Resource file = Resource( fileName.dirName.scanDirectory( fileName.baseName ~ ".*" ).front ); + return tuple( deserializeFile( file ), file ); +} + /** * Deserializes a file. * @@ -87,12 +104,12 @@ T[] deserializeMultiFile( T )( Resource file, SerializationMode mode = Serializa T[] handleJson() { - return [deserializeJson!T( file.readText().parseJsonString() )]; + return [deserializeFile!T( file, SerializationMode.Json )]; } T[] handleBson() { - throw new Exception( "Not implemented." ); + return [deserializeFile!T( file, SerializationMode.Bson )]; } T[] handleYaml() diff --git a/source/dash/utility/data/yaml.d b/source/dash/utility/data/yaml.d index 9c52ec1b..4df8b5f9 100644 --- a/source/dash/utility/data/yaml.d +++ b/source/dash/utility/data/yaml.d @@ -134,34 +134,6 @@ T[] loadYamlObjects( T )( string folder ) return folder.loadYamlDocuments.map!(yml => yml.getObject!T() ); } -/** -* Load a yaml file with the engine-specific mappings. -* -* Params: -* filePath = The path to file to load. -*/ -Node loadYamlFile( string filePath ) -{ - if( contentNode.isNull ) - { - auto loader = Loader( filePath ); - loader.constructor = constructor; - try - { - return loader.load(); - } - catch( YAMLException e ) - { - logFatal( "Error parsing file ", Resource( filePath ).baseFileName, ": ", e.msg ); - return Node(); - } - } - else - { - return contentNode.find( filePath.fileToYaml ); - } -} - /** * Load a yaml file with the engine-specific mappings. * diff --git a/source/dash/utility/resources.d b/source/dash/utility/resources.d index 73ffd335..1ca27f61 100644 --- a/source/dash/utility/resources.d +++ b/source/dash/utility/resources.d @@ -21,8 +21,8 @@ enum Resources : string Shaders = Home ~ "/Shaders", UI = Home ~ "/UI", ConfigDir = Home ~ "/Config", - ConfigFile = ConfigDir ~ "/Config.yml", - InputBindings = ConfigDir ~ "/Input.yml", + ConfigFile = ConfigDir ~ "/Config", + InputBindings = ConfigDir ~ "/Input", CompactContentFile = Home ~ "/Content.yml", } From 0e2010319dd07a5fe59ca096acb0b596114abe41 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 18 Sep 2014 16:30:12 -0400 Subject: [PATCH 044/141] Improved new Config system, started switching engine to it --- source/dash/components/camera.d | 6 +- source/dash/components/lights.d | 8 +- source/dash/core/gameobject.d | 12 +-- source/dash/editor/websockets.d | 8 +- source/dash/graphics/adapters/adapter.d | 10 +- source/dash/utility/config.d | 84 ++++++++------- source/dash/utility/data/serialization.d | 6 +- source/dash/utility/data/yaml.d | 127 +---------------------- source/dash/utility/input.d | 3 +- source/dash/utility/output.d | 35 ++----- source/dash/utility/tasks.d | 29 +++--- 11 files changed, 91 insertions(+), 237 deletions(-) diff --git a/source/dash/components/camera.d b/source/dash/components/camera.d index d8cd955f..f851cfb0 100644 --- a/source/dash/components/camera.d +++ b/source/dash/components/camera.d @@ -145,9 +145,9 @@ public: vec3f zaxis = vec3f( sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw ); _viewMatrix.v[] = 0.0f; - _viewMatrix.rows[ 0 ] = xaxis.v ~ -( xaxis * owner.transform.position ); - _viewMatrix.rows[ 1 ] = yaxis.v ~ -( yaxis * owner.transform.position ); - _viewMatrix.rows[ 2 ] = zaxis.v ~ -( zaxis * owner.transform.position ); + _viewMatrix.rows[ 0 ] = vec4f( xaxis, -xaxis.dot( owner.transform.position ) ); + _viewMatrix.rows[ 1 ] = vec4f( yaxis, -yaxis.dot( owner.transform.position ) ); + _viewMatrix.rows[ 2 ] = vec4f( zaxis, -zaxis.dot( owner.transform.position ) ); _viewMatrix.rows[ 3 ] = vec4f( 0, 0, 0, 1 ); _inverseViewMatrix = _viewMatrix.inverse(); diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index c910abe8..f413a51c 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -144,10 +144,10 @@ public: // build the view matrix mat4f viewMatrix; ///* - viewMatrix.rows[ 0 ] = xaxis.v ~ -( xaxis * center ); - viewMatrix.rows[ 1 ] = yaxis.v ~ -( yaxis * center ); - viewMatrix.rows[ 2 ] = zaxis.v ~ -( zaxis * center ); - viewMatrix.rows[ 3 ] = [ 0, 0, 0, 1 ]; + viewMatrix.rows[ 0 ] = vec4f( xaxis, -xaxis.dot( center ) ); + viewMatrix.rows[ 1 ] = vec4f( yaxis, -yaxis.dot( center ) ); + viewMatrix.rows[ 2 ] = vec4f( zaxis, -zaxis.dot( center ) ); + viewMatrix.rows[ 3 ] = vec4f( 0, 0, 0, 1 ); /*/ // using lookAt works for everying but a light direction of (0,+/-1,0) light.view = Camera.lookAt( center - light.direction.normalized, center ); //*/ diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 549299ab..23fc8941 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -568,8 +568,8 @@ public: auto trans = new Transform( null ); auto forward = vec3f( 0.0f, 1.0f, 0.0f ); - trans.rotation.rotatex( 90.radians ); - assert( almost_equal( trans.forward, forward ) ); + trans.rotation *= quatf.fromEulerAngles( 90.0f.radians, 0.0f, 0.0f ); + assert( trans.forward.dot( forward ) > 0.999999f ); } /* @@ -592,8 +592,8 @@ public: auto trans = new Transform( null ); auto up = vec3f( 0.0f, 0.0f, 1.0f ); - trans.rotation.rotatex( 90.radians ); - assert( almost_equal( trans.up, up ) ); + trans.rotation *= quatf.fromEulerAngles( 90.0f.radians, 0.0f, 0.0f ); + assert( trans.up.dot( up ) > 0.999999f ); } /* @@ -616,8 +616,8 @@ public: auto trans = new Transform( null ); auto right = vec3f( 0.0f, 0.0f, -1.0f ); - trans.rotation.rotatey( 90.radians ); - assert( almost_equal( trans.right, right ) ); + trans.rotation *= quatf.fromEulerAngles( 0.0f, 90.0f.radians, 0.0f ); + assert( trans.right.dot( right ) > 0.999999f ); } /** diff --git a/source/dash/editor/websockets.d b/source/dash/editor/websockets.d index 0a23f91f..ed42baaf 100644 --- a/source/dash/editor/websockets.d +++ b/source/dash/editor/websockets.d @@ -14,15 +14,11 @@ public: { this.editor = editor; - // Default port to 8080 - ushort bindPort = 8080; - bindPort = config.Editor.Port; - auto router = new URLRouter; - router.get( "/ws", handleWebSockets( &handleConnection ) ); + router.get( "/" ~ config.editor.route, handleWebSockets( &handleConnection ) ); auto settings = new HTTPServerSettings; - settings.port = bindPort; + settings.port = config.editor.port; settings.bindAddresses = [ "::1", "127.0.0.1" ]; listenHTTP( settings, router ); diff --git a/source/dash/graphics/adapters/adapter.d b/source/dash/graphics/adapters/adapter.d index a04121ab..a7c071f8 100644 --- a/source/dash/graphics/adapters/adapter.d +++ b/source/dash/graphics/adapters/adapter.d @@ -106,7 +106,7 @@ protected: */ final void loadProperties() { - fullscreen = config.find!bool( "Display.Fullscreen" ); + fullscreen = config.display.fullscreen; if( fullscreen ) { width = screenWidth; @@ -114,11 +114,11 @@ protected: } else { - width = config.find!uint( "Display.Width" ); - height = config.find!uint( "Display.Height" ); + width = config.display.width; + height = config.display.height; } - backfaceCulling = config.find!bool( "Graphics.BackfaceCulling" ); - vsync = config.find!bool( "Graphics.VSync" ); + backfaceCulling = config.graphics.backfaceCulling; + vsync = config.graphics.vsync; } } diff --git a/source/dash/utility/config.d b/source/dash/utility/config.d index 89ccf44c..3c2cce60 100644 --- a/source/dash/utility/config.d +++ b/source/dash/utility/config.d @@ -2,25 +2,10 @@ * Defines the static class Config, which handles all configuration options. */ module dash.utility.config; -import dash.components.component; import dash.utility.resources, dash.utility.output, dash.utility.data; -public import yaml; - import std.datetime; -/** - * Get a YAML map as a D object of type T. - * - * Params: - * T = The type to get from the node. - * node = The node to turn into the object. - * - * Returns: An object of type T that has all fields from the YAML node assigned to it. - */ -deprecated( "Use deserializeYaml" ) -alias getObject = deserializeYaml; - /** * The global instance of config. */ @@ -37,70 +22,83 @@ const(Config) config() @property struct Config { public: - LoggerSettings Logging; - DisplaySettings Display; - GraphicsSettings Graphics; - UserInterfaceSettings UserInterface; - EditorSettings Editor; + @rename( "Logging" ) @optional + LoggerSettings logging; + @rename( "Display" ) @optional + DisplaySettings display; + @rename( "Graphics" ) @optional + GraphicsSettings graphics; + @rename( "UserInterface" ) @optional + UserInterfaceSettings userInterface; + @rename( "Editor" ) @optional + EditorSettings editor; static struct LoggerSettings { - string FilePath; - Verbosities Debug; - Verbosities Release; + @rename( "FilePath" ) @optional + string filePath = null; + @rename( "Debug" ) @optional + Verbosities debug_ = Verbosities( Verbosity.Debug, Verbosity.Debug ); + @rename( "Release" ) @optional + Verbosities release = Verbosities( Verbosity.Off, Verbosity.High ); static struct Verbosities { - Verbosity OutputVerbosity; - Verbosity LoggingVerbosity; + @rename( "OutputVerbosity" ) @optional @byName + Verbosity outputVerbosity = Verbosity.Low; + @rename( "LoggingVerbosity" ) @optional @byName + Verbosity loggingVerbosity = Verbosity.Debug; } } static struct DisplaySettings { - bool Fullscreen; - uint Height; - uint Width; + @rename( "Fullscreen" ) + bool fullscreen; + @rename( "Height" ) @optional + uint height = 1920; + @rename( "Width" ) @optional + uint width = 720; } static struct GraphicsSettings { - bool BackfaceCulling; - bool VSync; + @rename( "BackfaceCulling" ) @optional + bool backfaceCulling = true; + @rename( "VSync" ) @optional + bool vsync = false; } static struct UserInterfaceSettings { - string FilePath; + @rename( "FilePath" ) @optional + string filePath = null; } static struct EditorSettings { - ushort Port; + @rename( "Port" ) @optional + ushort port = 8080; + @rename( "Route" ) @optional + string route = "ws"; } static: + @ignore private Resource resource = Resource( "" ); - private SysTime lastModified; void initialize() { - import std.file: timeLastModified; - auto res = deserializeFileByName!Config( Resources.ConfigFile ); - config = res[ 0 ]; + configInst = res[ 0 ]; resource = res[ 1 ]; - lastModified = resource.fullPath.timeLastModified; } - void update() + void refresh() { - import std.file: timeLastModified; - - if( lastModified < resource.fullPath.timeLastModified ) + if( resource.needsRefresh ) { - config = deserializeFile( resource ); - lastModified = resource.fullPath.timeLastModified; + configInst = deserializeFile!Config( resource ); } } } diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index 4b47d9d6..e9e1bfc1 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -33,11 +33,11 @@ enum SerializationMode */ Tuple!( T, Resource ) deserializeFileByName( T )( string fileName, SerializationMode mode = SerializationMode.Default ) { - import std.path: dirName; + import std.path: dirName, baseName; import std.array: front; - Resource file = Resource( fileName.dirName.scanDirectory( fileName.baseName ~ ".*" ).front ); - return tuple( deserializeFile( file ), file ); + Resource file = fileName.dirName.scanDirectory( fileName.baseName ~ ".*" ).front; + return tuple( deserializeFile!T( file ), file ); } /** diff --git a/source/dash/utility/data/yaml.d b/source/dash/utility/data/yaml.d index 4df8b5f9..7a5cf937 100644 --- a/source/dash/utility/data/yaml.d +++ b/source/dash/utility/data/yaml.d @@ -59,112 +59,6 @@ static assert(is(typeof( deserializeYaml!string( Node( "" ) ) ))); /// Does the type support custom serialization. enum isYamlSerializable( T ) = is( typeof( T.init.toYaml() ) == Node ) && is( typeof( T.fromYaml( Node() ) ) == T ); -/** -* Process all yaml files in a directory. -* -* Params: -* folder = The folder to iterate over. -*/ -Tuple!( Node, Resource )[] loadYamlFiles( string folder ) -{ - Tuple!( Node, Resource )[] nodes; - - if( contentNode.isNull ) - { - // Actually scan directories - foreach( file; scanDirectory( folder, "*.yml" ) ) - { - auto loader = Loader( file.fullPath ); - loader.constructor = constructor; - - try - { - // Iterate over all documents in a file - foreach( doc; loader ) - { - nodes ~= tuple( doc, file ); - } - } - catch( YAMLException e ) - { - logFatal( "Error parsing file ", file.baseFileName, ": ", e.msg ); - } - } - } - else - { - auto fileNode = contentNode.find( folder.fileToYaml ); - - foreach( string fileName, Node fileContent; fileNode ) - { - if( fileContent.isSequence ) - { - foreach( Node childChild; fileContent ) - nodes ~= tuple( childChild, configFile ); - } - else if( fileContent.isMapping ) - { - nodes ~= tuple( fileContent, configFile ); - } - } - } - - return nodes; -} - -/** -* Process all documents files in a directory. -* -* Params: -* folder = The folder to iterate over. -*/ -Node[] loadYamlDocuments( string path ) -{ - return loadYamlFiles( path ).map!( tup => tup[ 0 ] ).array; -} - -/** -* Processes all yaml files in a directory, and converts each document into an object of type T. -* -* Params: -* folder = The folder to look in. -*/ -T[] loadYamlObjects( T )( string folder ) -{ - return folder.loadYamlDocuments.map!(yml => yml.getObject!T() ); -} - -/** -* Load a yaml file with the engine-specific mappings. -* -* Params: -* filePath = The path to file to load. -*/ -Node[] loadAllDocumentsInYamlFile( string filePath ) -{ - if( contentNode.isNull ) - { - auto loader = Loader( filePath ); - loader.constructor = constructor; - try - { - Node[] nodes; - foreach( document; loader ) - nodes ~= document; - return nodes; - } - catch( YAMLException e ) - { - logFatal( "Error parsing file ", Resource( filePath ).baseFileName, ": ", e.msg ); - return []; - } - } - else - { - return contentNode.find( filePath.fileToYaml ).get!( Node[] ); - } -} - /** * Get the element, cast to the given type, at the given path, in the given node. * @@ -200,7 +94,7 @@ unittest assert( n3.find!int( "test3.test2.test1" ) == 10, "Config.find nested test failed"); - auto n4 = Loader.fromString( + auto n4 = Loader.fromString( cast(char[]) "test3:\n" ~ " test2:\n" ~ " test1: 10" ).load; @@ -250,6 +144,8 @@ final bool tryFind( T )( Node node, string path, ref T result ) nothrow @safe /// ditto final bool tryFind( T: Node )( Node node, string path, ref T result ) nothrow @safe { + import std.algorithm: countUntil; + // If anything goes wrong, it means the node wasn't found. scope( failure ) return false; @@ -315,20 +211,6 @@ unittest assert( !n1.tryFind( "dontexist", val ), "Config.tryFind returned true." ); } -/** -* Get element as a file path relative to the content home. -* -* Params: -* node = The node to search for the path in. -* path = The path to search the node for. -* -* Returns: The value at path relative to FilePath.ResourceHome. -*/ -final string findPath( Node node, string path ) -{ - return Resources.Home ~ node.find!string( path );//buildNormalizedPath( FilePath.ResourceHome, get!string( path ) );; -} - /// Serializer for vibe.d framework. struct YamlSerializer { @@ -445,7 +327,6 @@ unittest private: void enforceYaml( string file = __FILE__, size_t line = __LINE__ )( bool cond, lazy string message = "YAML exception" ) { - import std.json: JSONException; import std.exception; - enforceEx!JSONException(cond, message, file, line); + enforceEx!YAMLException(cond, message, file, line); } diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index 5c900b64..24a51fec 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -54,7 +54,8 @@ public: */ void initialize() { - auto bindings = Resources.InputBindings.loadYamlFile(); + // TODO: Implement + auto bindings = Node();//Resources.InputBindings.loadYamlFile(); Keyboard.initialize(); Mouse.initialize(); diff --git a/source/dash/utility/output.d b/source/dash/utility/output.d index 2fa9896d..bad3104a 100644 --- a/source/dash/utility/output.d +++ b/source/dash/utility/output.d @@ -123,16 +123,9 @@ synchronized final class GlobalLogger : StyledStrictLogger!(OutputType */ final void initialize() { - debug enum section = "Debug"; - else enum section = "Release"; - - enum LognameSection = "Logging.FilePath"; - enum OutputVerbositySection = "Logging."~section~".OutputVerbosity"; - enum LoggingVerbositySection = "Logging."~section~".LoggingVerbosity"; - // Try to get new path for logging - string newFileName; - if( config.tryFind( LognameSection, newFileName ) ) + string newFileName = config.logging.filePath; + if( newFileName ) { string oldFileName = this.name; try @@ -152,27 +145,11 @@ synchronized final class GlobalLogger : StyledStrictLogger!(OutputType } // Try to get output verbosity from config - Verbosity outputVerbosity; - if( config.tryFind( OutputVerbositySection, outputVerbosity ) ) - { - minOutputLevel = cast(OutputType)( outputVerbosity ); - } - else - { - debug minOutputLevel = OutputType.Info; - else minOutputLevel = OutputType.Warning; - } + debug minOutputLevel = cast(OutputType)config.logging.debug_.outputVerbosity; + else minOutputLevel = cast(OutputType)config.logging.release.outputVerbosity; // Try to get logging verbosity from config - Verbosity loggingVerbosity; - if( config.tryFind( LoggingVerbositySection, loggingVerbosity ) ) - { - minLoggingLevel = cast(OutputType)( loggingVerbosity ); - } - else - { - debug minLoggingLevel = OutputType.Info; - else minLoggingLevel = OutputType.Warning; - } + debug minLoggingLevel = cast(OutputType)config.logging.debug_.loggingVerbosity; + else minLoggingLevel = cast(OutputType)config.logging.release.loggingVerbosity; } } diff --git a/source/dash/utility/tasks.d b/source/dash/utility/tasks.d index 054af9c4..ea47c021 100644 --- a/source/dash/utility/tasks.d +++ b/source/dash/utility/tasks.d @@ -5,6 +5,7 @@ module dash.utility.tasks; import dash.utility.time, dash.utility.output; +import gfm.math.funcs: lerp; import core.time; import std.algorithm: min; import std.parallelism: parallel; @@ -44,7 +45,7 @@ UUID scheduleTask( bool delegate() dg ) * scheduleInterpolateTask( position, startNode, endNode, 100.msecs ); * --- */ -UUID scheduleInterpolateTask(T)( ref T val, T start, T end, Duration duration, T function( T, T, float ) interpFunc = &lerp!T ) if( is_vector!T || is_quaternion!T ) +UUID scheduleInterpolateTask(T)( ref T val, T start, T end, Duration duration, T function( T, T, float ) interpFunc = &lerp!( T, float ) )// if( is_vector!T || is_quaternion!T ) { return scheduleTimedTask( duration, ( elapsed ) { @@ -60,9 +61,9 @@ unittest writeln( "Dash Tasks scheduleInterpolateTask unittest 1" ); - vec3 interpVec = vec3( 0, 0, 0 ); - vec3 start = vec3( 0, 1, 0 ); - vec3 end = vec3( 0, 1, 1 ); + vec3f interpVec = vec3f( 0, 0, 0 ); + vec3f start = vec3f( 0, 1, 0 ); + vec3f end = vec3f( 0, 1, 1 ); scheduleInterpolateTask( interpVec, start, end, 100.msecs ); while( scheduledTasks.length ) @@ -93,8 +94,8 @@ unittest * scheduleInterpolateTask!q{position}( transform, startNode, endNode, 100.msecs ); * --- */ -UUID scheduleInterpolateTask( string prop, T, Owner )( ref Owner own, T start, T end, Duration duration, T function( T, T, float ) interpFunc = &lerp!T ) - if( ( is_vector!T || is_quaternion!T ) && __traits( compiles, mixin( "own." ~ prop ) ) ) +UUID scheduleInterpolateTask( string prop, T, Owner )( ref Owner own, T start, T end, Duration duration, T function( T, T, float ) interpFunc = &lerp!( T, float ) ) + if( __traits( compiles, mixin( "own." ~ prop ) ) ) { auto startTime = Time.totalTime; return scheduleTimedTask( duration, ( elapsed ) @@ -107,14 +108,14 @@ unittest { import dash.utility.time; import std.stdio; - import gl3n.linalg; + import gfm.math.vector; writeln( "Dash Tasks scheduleInterpolateTask unittest 2" ); auto testClass = new TestPropertyInterpolate; - testClass.vector = vec3( 0, 0, 0 ); - vec3 start = vec3( 0, 1, 0 ); - vec3 end = vec3( 0, 1, 1 ); + testClass.vector = vec3f( 0, 0, 0 ); + vec3f start = vec3f( 0, 1, 0 ); + vec3f end = vec3f( 0, 1, 1 ); scheduleInterpolateTask!q{vector}( testClass, start, end, 100.msecs ); while( scheduledTasks.length ) @@ -128,11 +129,11 @@ unittest version( unittest ) class TestPropertyInterpolate { - import gl3n.linalg; + import gfm.math.vector; - private vec3 _vector; - public @property vec3 vector() { return _vector; } - public @property void vector( vec3 newVal ) { _vector = newVal; } + private vec3f _vector; + public @property vec3f vector() { return _vector; } + public @property void vector( vec3f newVal ) { _vector = newVal; } } /** From 996618ddee423e39e02a9aea8c3660fb7dd0e055 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 18 Sep 2014 16:34:37 -0400 Subject: [PATCH 045/141] Updated travis dub version --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 32f5fd4c..4194abe8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ os: - osx env: # - DMD_VER=2.065.0 DUB_VER=0.9.21 - - DMD_VER=2.066.0 DUB_VER=0.9.21 + - DMD_VER=2.066.0 DUB_VER=0.9.22-rc.3 install: - bash .travis/setup_linux.sh - bash .travis/setup_osx.sh From c6588a25f08520beacb27d8482941930094f7583 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 18 Sep 2014 16:39:05 -0400 Subject: [PATCH 046/141] Fixed size_t error on linux --- source/dash/utility/data/yaml.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dash/utility/data/yaml.d b/source/dash/utility/data/yaml.d index 7a5cf937..c7d04f72 100644 --- a/source/dash/utility/data/yaml.d +++ b/source/dash/utility/data/yaml.d @@ -328,5 +328,5 @@ private: void enforceYaml( string file = __FILE__, size_t line = __LINE__ )( bool cond, lazy string message = "YAML exception" ) { import std.exception; - enforceEx!YAMLException(cond, message, file, line); + enforceEx!Exception(cond, message, file, line); } From 0dc955d906a5142c9e87eaf820d0635de9a42d25 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Fri, 19 Sep 2014 12:52:13 -0400 Subject: [PATCH 047/141] Fixed some crashes and failed unittests --- dub.json | 2 +- source/dash/core/gameobject.d | 20 ++++++++++++-------- source/dash/utility/data/serialization.d | 8 +++++--- source/dash/utility/input.d | 3 +++ 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/dub.json b/dub.json index 84dd1f5d..5434e713 100644 --- a/dub.json +++ b/dub.json @@ -21,7 +21,7 @@ "derelict-fi": "~>1.0", "derelict-assimp3": "~>1.0", "dyaml": "~>0.5", - "gfm:math" : "==1.2.3", + "gfm:math": "==1.2.3", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", "vibe-d": "~master", diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 23fc8941..84e1d32e 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -6,7 +6,7 @@ import dash.core, dash.components, dash.graphics, dash.utility; import yaml; import gfm.math.funcs: radians; -import std.conv, std.variant, std.array, std.algorithm, std.typecons, std.range, std.string; +import std.conv, std.variant, std.array, std.algorithm, std.typecons, std.range, std.string, std.math; enum AnonymousName = "__anonymous"; @@ -569,7 +569,9 @@ public: auto trans = new Transform( null ); auto forward = vec3f( 0.0f, 1.0f, 0.0f ); trans.rotation *= quatf.fromEulerAngles( 90.0f.radians, 0.0f, 0.0f ); - assert( trans.forward.dot( forward ) > 0.999999f ); + + foreach( i, v; trans.forward.v ) + assert( abs( v - forward.v[ i ] ) < 0.000001f ); } /* @@ -577,7 +579,7 @@ public: * * Returns: The up axis of the current transform. */ - final @property const vec3f up() + final @property const vec3f up() { return vec3f( 2 * (rotation.x * rotation.y - rotation.w * rotation.z), 1 - 2 * (rotation.x * rotation.x + rotation.z * rotation.z), @@ -590,10 +592,11 @@ public: writeln( "Dash Transform up unittest" ); auto trans = new Transform( null ); - auto up = vec3f( 0.0f, 0.0f, 1.0f ); trans.rotation *= quatf.fromEulerAngles( 90.0f.radians, 0.0f, 0.0f ); - assert( trans.up.dot( up ) > 0.999999f ); + + foreach( i, v; trans.up.v ) + assert( abs( v - up.v[ i ] ) < 0.000001f ); } /* @@ -601,7 +604,7 @@ public: * * Returns: The right axis of the current transform. */ - final @property const vec3f right() + final @property const vec3f right() { return vec3f( 1 - 2 * (rotation.y * rotation.y + rotation.z * rotation.z), 2 * (rotation.x * rotation.y + rotation.w * rotation.z), @@ -614,10 +617,11 @@ public: writeln( "Dash Transform right unittest" ); auto trans = new Transform( null ); - auto right = vec3f( 0.0f, 0.0f, -1.0f ); trans.rotation *= quatf.fromEulerAngles( 0.0f, 90.0f.radians, 0.0f ); - assert( trans.right.dot( right ) > 0.999999f ); + + foreach( i, v; trans.right.v ) + assert( abs( v - right.v[ i ] ) < 0.000001f ); } /** diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index e9e1bfc1..a4834851 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -34,10 +34,12 @@ enum SerializationMode Tuple!( T, Resource ) deserializeFileByName( T )( string fileName, SerializationMode mode = SerializationMode.Default ) { import std.path: dirName, baseName; - import std.array: front; + import std.array: empty, front; - Resource file = fileName.dirName.scanDirectory( fileName.baseName ~ ".*" ).front; - return tuple( deserializeFile!T( file ), file ); + auto files = fileName.dirName.scanDirectory( fileName.baseName ~ ".*" ); + return files.empty + ? tuple( T.init, Resource( "" ) ) + : tuple( deserializeFile!T( files.front ), files.front ); } /** diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index 24a51fec..bbdaae04 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -60,6 +60,9 @@ public: Keyboard.initialize(); Mouse.initialize(); + if( !bindings.isMapping ) + return; + foreach( string name, Node bind; bindings ) { if( !bind.isMapping ) From a13fd77c4a6ed62ce598712dac31eff291e6b4d5 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Fri, 19 Sep 2014 16:10:05 -0400 Subject: [PATCH 048/141] Serialization now compiles --- source/dash/components/component.d | 3 +-- source/dash/utility/data/yaml.d | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 79624b75..b89830b9 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -129,8 +129,7 @@ public: mixin( perSerializationFormat!q{ Component.$typeSerializers[ typeid(T) ] = ( Component c ) { - return $type(); - //return serializeTo$type( SerializationDescription( cast(T)c ) ); + return serializeTo$type( SerializationDescription( cast(T)c ) ); }; Component.$typeDeserializers[ T.stringof ] = ( $type node ) { diff --git a/source/dash/utility/data/yaml.d b/source/dash/utility/data/yaml.d index c7d04f72..7795f03f 100644 --- a/source/dash/utility/data/yaml.d +++ b/source/dash/utility/data/yaml.d @@ -237,7 +237,7 @@ public: void beginWriteArray( T )( size_t ) { m_compositeStack ~= Node( cast(string[])[] ); } void endWriteArray( T )() { m_current = m_compositeStack[$-1]; m_compositeStack.length--; } void beginWriteArrayEntry( T )( size_t ) {} - void endWriteArrayEntry( T )( size_t ) { m_compositeStack[$-1] ~= m_current; } + void endWriteArrayEntry( T )( size_t ) { m_compositeStack[$-1].add( m_current ); } void writeValue( T )( T value ) { @@ -245,6 +245,8 @@ public: m_current = value; else static if( isYamlSerializable!T ) m_current = value.toYaml(); + else static if( is( T == typeof(null) ) ) + m_current = Node( YAMLNull() ); else m_current = Node( value ); } From 45e59f8fb7d05341416d45004187aa3e8bd05e72 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Fri, 19 Sep 2014 16:46:38 -0400 Subject: [PATCH 049/141] Deserialization fixes [skip ci] --- source/dash/components/assets.d | 2 +- source/dash/components/component.d | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/source/dash/components/assets.d b/source/dash/components/assets.d index 91836290..a36ce725 100644 --- a/source/dash/components/assets.d +++ b/source/dash/components/assets.d @@ -245,7 +245,7 @@ public: /// Gets a reference to it's asset. override void initialize() { - if( !asset ) + if( !asset && assetName ) asset = Assets.getAsset!AssetType( assetName ); } } diff --git a/source/dash/components/component.d b/source/dash/components/component.d index b89830b9..2c7e61c9 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -11,6 +11,7 @@ import std.algorithm, std.array, std.string, std.traits, std.conv, std.typecons; enum isComponent(alias T) = is( T == class ) && is( T : Component ) && !__traits( isAbstractClass, T ); private enum perSerializationFormat( string code ) = "".reduce!( ( working, type ) => working ~ code.replace( "$type", type ) )( serializationFormats ); alias helper( alias T ) = T; +alias helper( T... ) = T; alias helper() = TypeTuple!(); /** @@ -133,8 +134,7 @@ public: }; Component.$typeDeserializers[ T.stringof ] = ( $type node ) { - return null; - //return deserialize$type!( SerializationDescription )( node ).createInstance(); + return deserialize$type!( SerializationDescription )( node ).createInstance(); }; } ); @@ -210,10 +210,7 @@ private: else static if( is( attributes.to!string ) ) return attributes.to!string; else - { - __ctfeWriteln( "No attributes on member " ~ memberName ); return null; - } } // Get required module import name From 20c95c7629689c36208862ecdad3e5accb81fe08 Mon Sep 17 00:00:00 2001 From: Sean Brennan Date: Sat, 20 Sep 2014 12:35:26 -0400 Subject: [PATCH 050/141] Added a playFollow function that will play a sound and have the sound follow the emitter until the sound is finished playing. --- source/dash/components/audio.d | 44 +++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/source/dash/components/audio.d b/source/dash/components/audio.d index ae114b50..67fe757f 100644 --- a/source/dash/components/audio.d +++ b/source/dash/components/audio.d @@ -29,6 +29,7 @@ public: override void update() { + Audio.soloud.update3dAudio(); Audio.soloud.set3dListenerAt(owner.transform.position.x, owner.transform.position.y, owner.transform.position.z); @@ -36,13 +37,14 @@ public: } /** - * Emitter object that plays sounds that listeners can hear if they are close enough + * Emitter object that plays sounds that listeners can hear */ @yamlComponent( "Emitter" ) class Emitter : Component { private: Modplug toPlay; + uint[] handles; public: /** * Create an emmiter object @@ -70,6 +72,46 @@ public: owner.transform.position.y, owner.transform.position.z); } + + void playFollow( string soundName ) { + // Load in the sound + toPlay.load( Audio.sounds[soundName].toStringz() ); + + // play the sound from the location of the parent object + // and set the sound to move with the emitter + handles ~= Audio.soloud.play3d( toPlay, + owner.transform.position.x, + owner.transform.position.y, + owner.transform.position.z ); + + } + + override void update() + { + foreach_reverse( i, handle; handles ) + { + if( !Audio.soloud.isValidVoiceHandle( handle ) ) + { + auto end = handles[i+1..$]; + handles = handles[0..i]; + handles ~= end; + } else { + Audio.soloud.set3dSourcePosition( handle, + owner.transform.position.x, + owner.transform.position.y, + owner.transform.position.z ); + } + } + } + + + /** + * Plays a sound that will follow the emitter for however long you set the length to be. + */ + void playFollow( string soundName, float soundLength ) + { + + } } /** From f3061ae5548baddcac2b343a366c32a21002b753 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 20 Sep 2014 15:56:12 -0400 Subject: [PATCH 051/141] Compiles and runs! Immediately crashes. --- source/dash/components/component.d | 8 +++----- source/dash/components/mesh.d | 10 +++++++++- source/dash/core/gameobject.d | 21 +++++++-------------- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 2c7e61c9..b72fa2d8 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -66,10 +66,8 @@ public: const(Description)* description() @property { - if( auto desc = typeid(this) in descriptions ) - return desc; - else - assert( false, "ComponentDescription not found for type " ~ typeid(this).name ); + assert( typeid(this) in descriptions, "ComponentDescription not found for type " ~ typeid(this).name ); + return &descriptions[ typeid(this) ]; } /// The description for the component @@ -207,7 +205,7 @@ private: { static if( is( attributes.length ) ) return attributes.array.map!( attr => attr.to!string ).join( ", " ).to!string; - else static if( is( attributes.to!string ) ) + else static if( is( typeof(attributes.to!string()) == string ) ) return attributes.to!string; else return null; diff --git a/source/dash/components/mesh.d b/source/dash/components/mesh.d index ab44e29d..514cb58d 100644 --- a/source/dash/components/mesh.d +++ b/source/dash/components/mesh.d @@ -90,7 +90,6 @@ public: float[] outputData; uint[] indices; animated = false; - boundingBox = box3f( vec3f( 0.0f, 0.0f, 0.0f ), vec3f( 0.0f, 0.0f, 0.0f ) ); if( mesh ) { @@ -341,6 +340,15 @@ class Mesh : AssetRef!MeshAsset { super( ass ); } + + override void initialize() + { + super.initialize(); + + if( animated && owner ) + owner.addComponent( animationData.getComponent() ); + } + } /** diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 84e1d32e..9bb843ca 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -310,21 +310,14 @@ public: * Adds a component to the object. */ final void addComponent( Component newComponent ) + in { - if( newComponent ) - { - componentList[ typeid(newComponent) ] = newComponent; - - newComponent.owner = this; - - if( typeid(newComponent) == typeid(Mesh) ) - { - auto mesh = cast(Mesh)newComponent; - - if( mesh.animated ) - addComponent( mesh.animationData.getComponent() ); - } - } + assert( newComponent, "Null component added." ); + } + body + { + componentList[ typeid(newComponent) ] = newComponent; + newComponent.owner = this; } /** From 99bb6a11b3e70e90170179a71b097e983585e443 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 20 Sep 2014 16:11:52 -0400 Subject: [PATCH 052/141] This should have been done a long time ago --- source/dash/core/gameobject.d | 3 +-- source/dash/core/scene.d | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index e76be567..74102409 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -446,7 +446,6 @@ public: private struct Transform { private: - GameObject _owner; vec3 _prevPos; quat _prevRot; vec3 _prevScale; @@ -476,7 +475,7 @@ public: vec3 scale; /// The object which this belongs to. - mixin( Property!( _owner, AccessModifier.Public ) ); + GameObject owner; /// The world matrix of the transform. mixin( Getter!_matrix ); //mixin( ThisDirtyGetter!( _matrix, updateMatrix ) ); diff --git a/source/dash/core/scene.d b/source/dash/core/scene.d index 84faae0d..85a54684 100644 --- a/source/dash/core/scene.d +++ b/source/dash/core/scene.d @@ -57,6 +57,8 @@ public: */ final void clear() { + _root.shutdown(); + destroy( _root ); _root = new GameObject; } From a88856a683086020163bc7a7eda9a119ca1063ee Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 20 Sep 2014 20:14:40 -0400 Subject: [PATCH 053/141] Code cleanup for days --- source/dash/components/lights.d | 5 ++-- source/dash/core/scene.d | 2 +- source/dash/utility/config.d | 52 --------------------------------- 3 files changed, 4 insertions(+), 55 deletions(-) diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index f413a51c..24364c9a 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -21,10 +21,10 @@ abstract class Light : Component { public: /// The color the light gives off. - @rename( "Color" ) + @rename( "Color" ) @optional vec3f color; /// If it should cast shadows - @rename( "CastShadows" ) + @rename( "CastShadows" ) @optional bool castShadows; this( vec3f color ) @@ -61,6 +61,7 @@ private: public: /// The direction the light points in. + @rename( "Direction" ) @optional vec3f direction; /// The FrameBuffer for the shadowmap. mixin( Property!( _shadowMapFrameBuffer ) ); diff --git a/source/dash/core/scene.d b/source/dash/core/scene.d index 0112a69e..7fcf0427 100644 --- a/source/dash/core/scene.d +++ b/source/dash/core/scene.d @@ -52,7 +52,7 @@ public: _root.addChild( newObj ); goResources[ file ] ~= newObj; - logDebug( "Adding object with components: ", desc.components ); + logDebug( "Adding object ", newObj.name, " with components: ", desc.components ); } } } diff --git a/source/dash/utility/config.d b/source/dash/utility/config.d index 3c2cce60..3eebcce8 100644 --- a/source/dash/utility/config.d +++ b/source/dash/utility/config.d @@ -102,55 +102,3 @@ static: } } } - -/** - * TODO - */ -T constructConv( T )( ref Node node ) if( is( T == enum ) ) -{ - if( node.isScalar ) - { - return node.get!string.to!T; - } - else - { - throw new Exception( "Enum must be represented as a scalar." ); - } -} - -version( unittest ) -{ - import std.string; - /// The string to store test yaml content in. - string testYML = q{--- -Config: - Input: - Forward: - Keyboard: W - Backward: - Keyboard: S - Jump: - Keyboard: Space - Config: - Logging: - FilePath: "dash.log" - Debug: - OutputVerbosity: !Verbosity Debug - LoggingVerbosity: !Verbosity Debug - Release: - OutputVerbosity: !Verbosity Medium - LoggingVerbosity: !Verbosity Medium - Display: - Fullscreen: false - Height: 720 - Width: 1280 - Graphics: - BackfaceCulling: true - VSync: false - Physics: - Gravity: !Vector3 0.0 -10.0 0.0 - UserInterface: - FilePath: "uitest.html" - Scale: !Vector2 1.0 1.0 - }; -} From 3d610f7451d21182c93b4a2cf544737ce912b26e Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 20 Sep 2014 20:15:42 -0400 Subject: [PATCH 054/141] Description is now a centralized class that serialization descriptions extend --- source/dash/components/component.d | 94 +++++++++++++++++------------- 1 file changed, 52 insertions(+), 42 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index b72fa2d8..eb91c403 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -33,6 +33,17 @@ public: /// Called on shutdown. void shutdown() { } + /** + * Create a description from the this parameter. + */ + const(Description) description() @property + { + assert( typeid(this) in descriptionCreators, "ComponentDescription not found for type " ~ typeid(this).name ); + return descriptionCreators[ typeid(this) ]( this ); + } + private alias DescriptionCreator = const(Description) function( Component ); + private static DescriptionCreator[ ClassInfo ] descriptionCreators; + // For serialization. mixin( perSerializationFormat!q{ @ignore static $type delegate( Component )[ ClassInfo ] $typeSerializers; @@ -63,31 +74,22 @@ public: } static assert( is$typeSerializable!Component ); } ); +} - const(Description)* description() @property - { - assert( typeid(this) in descriptions, "ComponentDescription not found for type " ~ typeid(this).name ); - return &descriptions[ typeid(this) ]; - } - - /// The description for the component - struct Description +/// The description for the component +abstract class Description +{ +public: + static struct Field { public: - static struct Field - { - public: - string name; - string typeName; - string attributes; - string mod; - } - - Field[] fields; + string name; + string typeName; + string attributes; + string mod; } -private: - static const(Description)[ ClassInfo ] descriptions; + abstract immutable(Field[]) fields() const @property; } /** @@ -128,7 +130,7 @@ public: mixin( perSerializationFormat!q{ Component.$typeSerializers[ typeid(T) ] = ( Component c ) { - return serializeTo$type( SerializationDescription( cast(T)c ) ); + return serializeTo$type( SerializationDescription.create( cast(T)c ) ); }; Component.$typeDeserializers[ T.stringof ] = ( $type node ) { @@ -136,26 +138,39 @@ public: }; } ); - Component.descriptions[ typeid(T) ] = description; + Component.descriptionCreators[ typeid(T) ] = &SerializationDescription.create; } + // Generate description + enum fieldList = getFields(); + +private: // Generate actual struct - struct SerializationDescription + final class SerializationDescription : Description { + pragma( msg, T.stringof ~ "\n" ~ descContents ); mixin( descContents ); - enum fields = getFields(); + override immutable(Description.Field[]) fields() const @property + { + return fieldList; + } // Create a description from a component. - this( T theThing ) + static const(SerializationDescription) create( Component comp ) { + auto theThing = cast(T)comp; + auto desc = new SerializationDescription; + foreach( field; __traits( allMembers, T ) ) { - static if( fields.map!(f => f.name).canFind( field ) ) + static if( fieldList.map!(f => f.name).canFind( field ) ) { - mixin( field ~ " = theThing." ~ field ~ ";\n" ); + mixin( "desc."~field~" = theThing."~field~";\n" ); } } + + return desc; } // Create a component from a description. @@ -164,7 +179,7 @@ public: T comp = new T; foreach( field; __traits( allMembers, T ) ) { - static if( fields.map!(f => f.name).canFind( field ) ) + static if( fieldList.map!(f => f.name).canFind( field ) ) { mixin( "comp." ~ field ~ " = this." ~ field ~ ";\n" ); } @@ -173,12 +188,8 @@ public: } } - // Generate description - enum description = Component.Description( getFields() ); - -private: // Get a list of fields on the type - Component.Description.Field[] getFields( size_t idx = 0 )( Component.Description.Field[] fields = [] ) + Description.Field[] getFields( size_t idx = 0 )( Description.Field[] fields = [] ) { static if( idx == __traits( allMembers, T ).length ) { @@ -198,17 +209,16 @@ private: static if( !isSomeFunction!member ) { import std.conv; - alias attributes = helper!( __traits( getAttributes, member ) ); // Get string form of attributes string attributesStr() { - static if( is( attributes.length ) ) - return attributes.array.map!( attr => attr.to!string ).join( ", " ).to!string; - else static if( is( typeof(attributes.to!string()) == string ) ) - return attributes.to!string; - else - return null; + string[] attrs; + foreach( attr; __traits( getAttributes, member ) ) + { + attrs ~= attr.to!string; + } + return attrs.join( ", " ).to!string; } // Get required module import name @@ -218,7 +228,7 @@ private: enum modName = null; // Generate field - enum newField = Component.Description.Field( memberName, fullyQualifiedName!(Unqual!(typeof(member))), attributesStr, modName ); + enum newField = Description.Field( memberName, fullyQualifiedName!(Unqual!(typeof(member))), attributesStr, modName ); return getFields!( idx + 1 )( fields ~ newField ); } else @@ -252,6 +262,6 @@ private: return result; } - )( "", description.fields ); + )( "", fieldList ); } (); } From 0a40988071335e38dc0b38b95b7b08e77b9cefc1 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 20 Sep 2014 21:42:01 -0400 Subject: [PATCH 055/141] Code cleanup. The game now runs (and doesn't render anything) --- source/dash/components/component.d | 2 +- source/dash/components/material.d | 4 ++++ source/dash/core/gameobject.d | 21 +++++++++++---------- source/dash/core/prefabs.d | 6 ++++-- source/dash/core/scene.d | 2 +- source/dash/graphics/shaders/shaders.d | 1 + 6 files changed, 22 insertions(+), 14 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index eb91c403..66d0da5a 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -148,7 +148,7 @@ private: // Generate actual struct final class SerializationDescription : Description { - pragma( msg, T.stringof ~ "\n" ~ descContents ); + //pragma( msg, T.stringof ~ "\n" ~ descContents ); mixin( descContents ); override immutable(Description.Field[]) fields() const @property diff --git a/source/dash/components/material.d b/source/dash/components/material.d index bc85ef28..cf481ae6 100644 --- a/source/dash/components/material.d +++ b/source/dash/components/material.d @@ -82,6 +82,10 @@ final class Material : AssetRef!MaterialAsset // All materials should be unique. if( asset ) asset = asset.clone(); + + asset.diffuse.initialize(); + asset.normal.initialize(); + asset.specular.initialize(); } } diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 9bb843ca..93d15193 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -50,11 +50,10 @@ final class GameObject private: GameObject _parent; GameObject[] _children; + Prefab _prefab; Component[TypeInfo] componentList; string _name; - ObjectStateFlags* _stateFlags; bool canChangeName; - Node _yaml; static uint nextId = 1; enum componentProperty( Type ) = q{ @@ -77,7 +76,7 @@ public: /// The name of the prefab to create from. Do you use with $(D prefab). @rename( "InstanceOf" ) @optional - string prefabName; + string prefabName = null; /// The Prefab to create from. @ignore @@ -124,16 +123,16 @@ public: mixin( Property!_parent ); /// All of the objects which list this as parent mixin( Property!_children ); - /// The yaml node that created the object. - mixin( RefGetter!_yaml ); - /// The current update settings - mixin( Property!( _stateFlags, AccessModifier.Public ) ); /// The name of the object. mixin( Getter!_name ); + /// The prefab that this object is based on. + mixin( Property!_prefab ); /// ditto mixin( ConditionalSetter!( _name, q{canChangeName}, AccessModifier.Public ) ); /// The ID of the object. immutable uint id; + /// The current update settings + ObjectStateFlags* stateFlags; /// Allow setting of state flags directly. //alias stateFlags this; @@ -153,7 +152,9 @@ public: // Create the object if( desc.prefabName ) { - obj = Prefabs[ desc.prefabName ].createInstance(); + auto fab = Prefabs[ desc.prefabName ]; + obj = fab.createInstance(); + obj.prefab = fab; } else if( desc.prefab ) { @@ -204,8 +205,8 @@ public: with( desc ) { name = this.name; - prefabName = ""; - prefab = null; + prefab = this.prefab; + prefabName = prefab ? prefab.name : null; transform = this.transform.toDescription(); children = this.children.map!( child => child.toDescription() ).array(); components = this.componentList.values.dup; diff --git a/source/dash/core/prefabs.d b/source/dash/core/prefabs.d index 83cd2639..ed9bb0e0 100644 --- a/source/dash/core/prefabs.d +++ b/source/dash/core/prefabs.d @@ -80,7 +80,10 @@ final class Prefab : Asset { public: /// The name of the prefab. - string name; + const(string) name() @property + { + return description.name; + } /// The description to create objects from. GameObject.Description description; @@ -88,7 +91,6 @@ public: this( GameObject.Description desc ) { description = desc; - name = description.name; } /** diff --git a/source/dash/core/scene.d b/source/dash/core/scene.d index 7fcf0427..9e691a9f 100644 --- a/source/dash/core/scene.d +++ b/source/dash/core/scene.d @@ -52,7 +52,7 @@ public: _root.addChild( newObj ); goResources[ file ] ~= newObj; - logDebug( "Adding object ", newObj.name, " with components: ", desc.components ); + logDebug( "Adding object ", newObj.name, " with diffuse: ", newObj.material.diffuse ); } } } diff --git a/source/dash/graphics/shaders/shaders.d b/source/dash/graphics/shaders/shaders.d index 869a2390..f7db34cf 100644 --- a/source/dash/graphics/shaders/shaders.d +++ b/source/dash/graphics/shaders/shaders.d @@ -302,6 +302,7 @@ public: in { assert( material, "Cannot bind null material." ); + assert( material.diffuse && material.normal && material.specular, "Material must have diffuse, normal, and specular components." ); } body { From 64d9a506168364417993ecf9b6ac84437ff0d084 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sun, 21 Sep 2014 16:38:23 -0400 Subject: [PATCH 056/141] Switched back to gl3n for performance/things not drawing reasons --- dub.json | 7 ++- source/dash/components/animation.d | 17 +++--- source/dash/components/camera.d | 13 ++--- source/dash/components/lights.d | 21 +++---- source/dash/components/mesh.d | 6 +- source/dash/components/userinterface.d | 1 - source/dash/core/gameobject.d | 39 +++++-------- source/dash/graphics/adapters/adapter.d | 3 +- source/dash/graphics/adapters/gl.d | 9 ++- source/dash/graphics/shaders/shaders.d | 4 +- source/dash/utility/data/serialization.d | 4 +- source/dash/utility/input.d | 1 - source/dash/utility/math.d | 71 ++++++++++++++++++++++++ source/dash/utility/package.d | 1 + source/dash/utility/tasks.d | 1 - 15 files changed, 121 insertions(+), 77 deletions(-) create mode 100644 source/dash/utility/math.d diff --git a/dub.json b/dub.json index 5434e713..9006e62b 100644 --- a/dub.json +++ b/dub.json @@ -21,7 +21,7 @@ "derelict-fi": "~>1.0", "derelict-assimp3": "~>1.0", "dyaml": "~>0.5", - "gfm:math": "==1.2.3", + "gl3n": "==1.0.0", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", "vibe-d": "~master", @@ -35,7 +35,10 @@ "sourcePaths": [ "source/" ], "importPaths": [ "source/" ], - "versions": [ "VibeCustomMain" ], + "versions": [ + "DashUseGl3n", + "VibeCustomMain" + ], "-ddoxFilterArgs": [ "--min-protection=Protected" ], diff --git a/source/dash/components/animation.d b/source/dash/components/animation.d index 3e2d84de..acfed550 100644 --- a/source/dash/components/animation.d +++ b/source/dash/components/animation.d @@ -6,9 +6,6 @@ import dash.core.properties; import dash.components; import dash.utility; -import gfm.math.vector: vec3f; -import gfm.math.quaternion: quatf; -import gfm.math.matrix: mat4f, Matrix; import derelict.assimp3.assimp; import std.string: fromStringz; import std.conv: to; @@ -349,19 +346,19 @@ public: if( bonePose.positionKeys.length > cast(int)time ) { - boneTransform = boneTransform.translation( vec3f( bonePose.positionKeys[ cast(int)time ].v[ 0 ], - bonePose.positionKeys[ cast(int)time ].v[ 1 ], - bonePose.positionKeys[ cast(int)time ].v[ 2 ] ) ); + boneTransform = boneTransform.translation( bonePose.positionKeys[ cast(int)time ].vector[ 0 ], + bonePose.positionKeys[ cast(int)time ].vector[ 1 ], + bonePose.positionKeys[ cast(int)time ].vector[ 2 ] ); } if( bonePose.rotationKeys.length > cast(int)time ) { - boneTransform = boneTransform * cast(mat4f)bonePose.rotationKeys[ cast(int)time ]; + boneTransform = boneTransform * bonePose.rotationKeys[ cast(int)time ].toMatrix!4; } if( bonePose.scaleKeys.length > cast(int)time ) { - boneTransform = boneTransform.scaling( vec3f( bonePose.scaleKeys[ cast(int)time ].v[ 0 ], - bonePose.scaleKeys[ cast(int)time ].v[ 1 ], - bonePose.scaleKeys[ cast(int)time ].v[ 2 ] ) ); + boneTransform = boneTransform.scaling( bonePose.scaleKeys[ cast(int)time ].vector[ 0 ], + bonePose.scaleKeys[ cast(int)time ].vector[ 1 ], + bonePose.scaleKeys[ cast(int)time ].vector[ 2 ] ); } finalTransform = parentTransform * boneTransform; diff --git a/source/dash/components/camera.d b/source/dash/components/camera.d index f851cfb0..bcd3f50a 100644 --- a/source/dash/components/camera.d +++ b/source/dash/components/camera.d @@ -4,9 +4,6 @@ module dash.components.camera; import dash.core, dash.components, dash.graphics, dash.utility; -import gfm.math.vector: vec2f, vec3f, vec4f, cross, dot; -import gfm.math.matrix: mat4f; -import gfm.math.funcs: radians; import std.conv: to; import std.math: sin, cos; @@ -145,10 +142,10 @@ public: vec3f zaxis = vec3f( sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw ); _viewMatrix.v[] = 0.0f; - _viewMatrix.rows[ 0 ] = vec4f( xaxis, -xaxis.dot( owner.transform.position ) ); - _viewMatrix.rows[ 1 ] = vec4f( yaxis, -yaxis.dot( owner.transform.position ) ); - _viewMatrix.rows[ 2 ] = vec4f( zaxis, -zaxis.dot( owner.transform.position ) ); - _viewMatrix.rows[ 3 ] = vec4f( 0, 0, 0, 1 ); + _viewMatrix.c[ 0 ] = vec4f( xaxis, -xaxis.dot( owner.transform.position ) ).vector; + _viewMatrix.c[ 1 ] = vec4f( yaxis, -yaxis.dot( owner.transform.position ) ).vector; + _viewMatrix.c[ 2 ] = vec4f( zaxis, -zaxis.dot( owner.transform.position ) ).vector; + _viewMatrix.c[ 3 ] = vec4f( 0, 0, 0, 1 ).vector; _inverseViewMatrix = _viewMatrix.inverse(); } @@ -226,7 +223,7 @@ private: final void updatePerspective() { _projectionConstants = vec2f( ( -far * near ) / ( far - near ), far / ( far - near ) ); - _perspectiveMatrix = mat4f.perspective( fov.radians, cast(float)Graphics.width / cast(float)Graphics.height, near, far ); + _perspectiveMatrix = perspectiveMat( cast(float)Graphics.width, cast(float)Graphics.height, fov.radians, near, far ); _inversePerspectiveMatrix = _perspectiveMatrix.inverse(); } diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index 24364c9a..e43a18b2 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -6,9 +6,6 @@ module dash.components.lights; import dash.core, dash.components, dash.graphics; import dash.utility; -import gfm.math.vector: vec3f, dot; -import gfm.math.matrix: mat4f, Matrix; -import gfm.math.box: box3f; import derelict.opengl3.gl3; import std.math; @@ -145,10 +142,10 @@ public: // build the view matrix mat4f viewMatrix; ///* - viewMatrix.rows[ 0 ] = vec4f( xaxis, -xaxis.dot( center ) ); - viewMatrix.rows[ 1 ] = vec4f( yaxis, -yaxis.dot( center ) ); - viewMatrix.rows[ 2 ] = vec4f( zaxis, -zaxis.dot( center ) ); - viewMatrix.rows[ 3 ] = vec4f( 0, 0, 0, 1 ); + viewMatrix.c[ 0 ] = vec4f( xaxis, -xaxis.dot( center ) ).vector; + viewMatrix.c[ 1 ] = vec4f( yaxis, -yaxis.dot( center ) ).vector; + viewMatrix.c[ 2 ] = vec4f( zaxis, -zaxis.dot( center ) ).vector; + viewMatrix.c[ 3 ] = vec4f( 0, 0, 0, 1 ).vector; /*/ // using lookAt works for everying but a light direction of (0,+/-1,0) light.view = Camera.lookAt( center - light.direction.normalized, center ); //*/ @@ -161,15 +158,15 @@ public: vec3f mins, maxes; for( int i = 0; i < 3; i++ ) { - if( frustum.min.v[ i ] < frustum.max.v[ i ] ) + if( frustum.min.vector[ i ] < frustum.max.vector[ i ] ) { - mins.v[ i ] = frustum.min.v[ i ]; - maxes.v[ i ] = frustum.max.v[ i ]; + mins.vector[ i ] = frustum.min.vector[ i ]; + maxes.vector[ i ] = frustum.max.vector[ i ]; } else { - mins.v[ i ] = frustum.max.v[ i ]; - maxes.v[ i ] = frustum.min.v[ i ]; + mins.vector[ i ] = frustum.max.vector[ i ]; + maxes.vector[ i ] = frustum.min.vector[ i ]; } } diff --git a/source/dash/components/mesh.d b/source/dash/components/mesh.d index 514cb58d..ec3c0931 100644 --- a/source/dash/components/mesh.d +++ b/source/dash/components/mesh.d @@ -4,8 +4,6 @@ module dash.components.mesh; import dash.core, dash.components, dash.graphics, dash.utility; -import gfm.math.vector: vec3f; -import gfm.math.box: box3f; import derelict.opengl3.gl3, derelict.assimp3.assimp; import std.stdio, std.stream, std.format, std.math, std.string; @@ -166,7 +164,7 @@ public: outputData ~= vertWeights[ face.mIndices[ j ] ][0..4]; // Save the position in verts - boundingBox = boundingBox.expand( vec3f( pos.x, pos.y, pos.z ) ); + boundingBox.expandInPlace( vec3f( pos.x, pos.y, pos.z ) ); } } } @@ -208,7 +206,7 @@ public: //outputData ~= bitangent.z; // Save the position in verts - boundingBox = boundingBox.expand( vec3f( pos.x, pos.y, pos.z ) ); + boundingBox.expandInPlace( vec3f( pos.x, pos.y, pos.z ) ); } } } diff --git a/source/dash/components/userinterface.d b/source/dash/components/userinterface.d index ca4e3dc0..26e095b9 100644 --- a/source/dash/components/userinterface.d +++ b/source/dash/components/userinterface.d @@ -4,7 +4,6 @@ module dash.components.userinterface; import dash.core, dash.utility.awesomium, dash.components, dash.utility, dash.graphics.graphics; -import gfm.math.matrix: mat4f; import std.string; /** diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 93d15193..73699a68 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -5,7 +5,6 @@ module dash.core.gameobject; import dash.core, dash.components, dash.graphics, dash.utility; import yaml; -import gfm.math.funcs: radians; import std.conv, std.variant, std.array, std.algorithm, std.typecons, std.range, std.string, std.math; enum AnonymousName = "__anonymous"; @@ -202,15 +201,12 @@ public: Description toDescription() { Description desc; - with( desc ) - { - name = this.name; - prefab = this.prefab; - prefabName = prefab ? prefab.name : null; - transform = this.transform.toDescription(); - children = this.children.map!( child => child.toDescription() ).array(); - components = this.componentList.values.dup; - } + desc.name = name; + desc.prefab = prefab; + desc.prefabName = prefab ? prefab.name : null; + desc.transform = transform.toDescription(); + desc.children = children.map!( child => child.toDescription() ).array(); + desc.components = componentList.values.dup; return desc; } @@ -409,10 +405,6 @@ public: } } -import gfm.math.vector: vec3f; -import gfm.math.quaternion: quatf; -import gfm.math.matrix: mat4f; - /** * Handles 3D Transformations for an object. * Stores position, rotation, and scale @@ -431,7 +423,7 @@ private: void opAssign( Description desc ) { position = vec3f( desc.position[] ); - rotation = quatf.fromEulerAngles( desc.rotation[ 1 ], desc.rotation[ 0 ], desc.rotation[ 2 ] ); + rotation = fromEulerAngles( desc.rotation[ 1 ], desc.rotation[ 0 ], desc.rotation[ 2 ] ); scale = vec3f( desc.scale[] ); } @@ -477,12 +469,9 @@ public: Description toDescription() { Description desc; - with( desc ) - { - position = this.position.v[ 0..3 ]; - rotation = this.rotation.toEulerAngles()[ 0..3 ]; - scale = this.scale.v[ 0..3 ]; - } + desc.position = position.vector[ 0..3 ]; + desc.rotation = rotation.toEulerAngles().vector[ 0..3 ]; + desc.scale = scale.vector[ 0..3 ]; return desc; } @@ -562,7 +551,7 @@ public: auto trans = new Transform( null ); auto forward = vec3f( 0.0f, 1.0f, 0.0f ); - trans.rotation *= quatf.fromEulerAngles( 90.0f.radians, 0.0f, 0.0f ); + trans.rotation *= fromEulerAngles( 90.0f.radians, 0.0f, 0.0f ); foreach( i, v; trans.forward.v ) assert( abs( v - forward.v[ i ] ) < 0.000001f ); @@ -587,7 +576,7 @@ public: auto trans = new Transform( null ); auto up = vec3f( 0.0f, 0.0f, 1.0f ); - trans.rotation *= quatf.fromEulerAngles( 90.0f.radians, 0.0f, 0.0f ); + trans.rotation *= fromEulerAngles( 90.0f.radians, 0.0f, 0.0f ); foreach( i, v; trans.up.v ) assert( abs( v - up.v[ i ] ) < 0.000001f ); @@ -612,7 +601,7 @@ public: auto trans = new Transform( null ); auto right = vec3f( 0.0f, 0.0f, -1.0f ); - trans.rotation *= quatf.fromEulerAngles( 0.0f, 90.0f.radians, 0.0f ); + trans.rotation *= fromEulerAngles( 0.0f, 90.0f.radians, 0.0f ); foreach( i, v; trans.right.v ) assert( abs( v - right.v[ i ] ) < 0.000001f ); @@ -634,7 +623,7 @@ public: _matrix.c[ 2 ][ 2 ] = scale.z; // Rotate - _matrix = _matrix * cast(mat4f)rotation; + _matrix = _matrix * rotation.toMatrix!4; // Translate _matrix.c[ 0 ][ 3 ] = position.x; diff --git a/source/dash/graphics/adapters/adapter.d b/source/dash/graphics/adapters/adapter.d index a7c071f8..0c16fdc5 100644 --- a/source/dash/graphics/adapters/adapter.d +++ b/source/dash/graphics/adapters/adapter.d @@ -2,9 +2,8 @@ * Contains all core code for the Graphics adapters, which is similar across all platforms */ module dash.graphics.adapters.adapter; -import dash.core.properties, dash.components.userinterface, dash.utility.config; +import dash.core.properties, dash.components.userinterface, dash.utility.config, dash.utility.math; -import gfm.math.vector: vec2ui; import std.typecons: BlackHole; alias NullAdapter = BlackHole!Adapter; diff --git a/source/dash/graphics/adapters/gl.d b/source/dash/graphics/adapters/gl.d index d6743369..935bbf8a 100644 --- a/source/dash/graphics/adapters/gl.d +++ b/source/dash/graphics/adapters/gl.d @@ -1,8 +1,7 @@ module dash.graphics.adapters.gl; import dash.core, dash.components, dash.graphics; -import dash.utility.output; +import dash.utility.output, dash.utility.math; -import gfm.math; import derelict.opengl3.gl3; import std.algorithm, std.array; @@ -188,7 +187,7 @@ public: mat4f worldView = scene.camera.viewMatrix * object.transform.matrix; mat4f worldViewProj = projection * worldView; - if( worldViewProj.frustum().contains( object.mesh.boundingBox ) == Frustum!float.OUTSIDE ) + if( !( object.mesh.boundingBox in Frustum( worldViewProj ) ) ) { // If we can't see an object, don't draw it. continue; @@ -237,8 +236,8 @@ public: { if( object.mesh && object.stateFlags.drawMesh ) { - frustum = frustum.expand( (object.transform.matrix * vec4f(object.mesh.boundingBox.min, 1.0f)).xyz ); - frustum = frustum.expand( (object.transform.matrix * vec4f(object.mesh.boundingBox.max, 1.0f)).xyz ); + frustum.expandInPlace( (object.transform.matrix * vec4f(object.mesh.boundingBox.min, 1.0f)).xyz ); + frustum.expandInPlace( (object.transform.matrix * vec4f(object.mesh.boundingBox.max, 1.0f)).xyz ); } } diff --git a/source/dash/graphics/shaders/shaders.d b/source/dash/graphics/shaders/shaders.d index f7db34cf..dad60a29 100644 --- a/source/dash/graphics/shaders/shaders.d +++ b/source/dash/graphics/shaders/shaders.d @@ -5,8 +5,6 @@ module dash.graphics.shaders.shaders; import dash.core, dash.components, dash.graphics, dash.utility; import dash.graphics.shaders.glsl; -import gfm.math.vector: vec2f, vec3f; -import gfm.math.matrix: mat4f; import derelict.opengl3.gl3; import std.string, std.traits, std.algorithm; @@ -279,7 +277,7 @@ public: */ final void bindUniformMatrix4fv( uint uniform, mat4f matrix ) { - glUniformMatrix4fv( uniform, 1, false, matrix.ptr ); + glUniformMatrix4fv( uniform, 1, true, matrix.value_ptr ); } /** diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index a4834851..da6b88c1 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -5,9 +5,7 @@ import vibe.data.json, vibe.data.bson; import std.typecons: Tuple, tuple; // Serialization attributes -public import vibe.data.serialization: asArray, byName, ignore, name, optional, isCustomSerializable; -/// Rename a field in the ddl. -alias rename = name; +public import vibe.data.serialization: rename = name, asArray, byName, ignore, optional, isCustomSerializable; /// Supported serialization formats. enum serializationFormats = tuple( "Json"/*, "Bson"*/, "Yaml" ); diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index bbdaae04..4abb7b22 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -5,7 +5,6 @@ module dash.utility.input; import dash.utility, dash.core, dash.graphics; import yaml; -import gfm.math.vector: vec2ui, vec3f, vec4f; import derelict.opengl3.gl3; import std.typecons, std.conv, std.traits, std.uuid; diff --git a/source/dash/utility/math.d b/source/dash/utility/math.d new file mode 100644 index 00000000..2dc61f72 --- /dev/null +++ b/source/dash/utility/math.d @@ -0,0 +1,71 @@ +module dash.utility.math; + +version( DashUseGl3n ) +{ +public: + // Linear Algebra types + import gl3n.linalg; + + // Vectors + alias vec2f = Vector!( float, 2 ); + alias vec2ui = Vector!( uint, 2 ); + alias vec3f = Vector!( float, 3 ); + alias vec4f = Vector!( float, 4 ); + + // Quaternions + alias quatf = Quaternion!float; + + inout(Matrix!( Floating, Size, Size )) toMatrix( uint Size, Floating )( inout Quaternion!Floating q ) @property + if( Size == 3 || Size == 4 ) + { + return q.to_matrix!( Size, Size ); + } + + inout(Vector!( Floating, 3 )) toEulerAngles( Floating )( inout Quaternion!Floating q ) @property + { + return typeof(return)( q.pitch, q.yaw, q.roll ); + } + + Quaternion!Floating fromEulerAngles( Floating = float )( Floating pitch, Floating yaw, Floating roll ) + { + return Quaternion!Floating.identity.rotatex( pitch ).rotatey( yaw ).rotatez( roll ); + } + + // Matrices + alias mat4f = Matrix!( float, 4, 4 ); + + Floating[Size][Size] c( Floating, uint Size )( Matrix!( Floating, Size, Size ) m ) @property + { + return m.matrix; + } + + Floating[] v( Floating, uint Size )( Matrix!( Floating, Size, Size ) m ) @property + { + return m.value_ptr[ 0..Size*Size ]; + } + + mat4f perspectiveMat( float width, float height, float fov, float near, float far ) + { + return mat4f.perspective( width, height, fov, near, far ); + } + + // Interpolation functions + import gl3n.interpolate; + + // AABB types + import gl3n.aabb; + alias box3f = AABBT!float; + + void expandInPlace( Floating )( ref AABBT!Floating box, Vector!( Floating, 3 ) v ) + { + box.expand( v ); + } + + // Other functions + import gl3n.frustum; + import gl3n.math; +} +else version( DashUseGfmMath ) +{ + +} \ No newline at end of file diff --git a/source/dash/utility/package.d b/source/dash/utility/package.d index a46a4705..d3a4967c 100644 --- a/source/dash/utility/package.d +++ b/source/dash/utility/package.d @@ -3,6 +3,7 @@ public: import dash.utility.data; import dash.utility.config; import dash.utility.input; +import dash.utility.math; import dash.utility.output; import dash.utility.time; import dash.utility.string; diff --git a/source/dash/utility/tasks.d b/source/dash/utility/tasks.d index ea47c021..031a44ec 100644 --- a/source/dash/utility/tasks.d +++ b/source/dash/utility/tasks.d @@ -5,7 +5,6 @@ module dash.utility.tasks; import dash.utility.time, dash.utility.output; -import gfm.math.funcs: lerp; import core.time; import std.algorithm: min; import std.parallelism: parallel; From cb93f099ee7b009451115f45c77e2868e1ec53a5 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sun, 21 Sep 2014 18:30:15 -0400 Subject: [PATCH 057/141] Removed .c and .v for matrices, fixed matrices being NaN --- source/dash/components/animation.d | 32 ++++++++++---------- source/dash/components/camera.d | 42 +++++++++++++------------- source/dash/components/lights.d | 20 ++++++------ source/dash/components/userinterface.d | 4 +-- source/dash/core/gameobject.d | 24 +++++++-------- source/dash/graphics/adapters/gl.d | 30 ++++++++---------- source/dash/graphics/shaders/shaders.d | 2 +- source/dash/utility/math.d | 10 ------ 8 files changed, 74 insertions(+), 90 deletions(-) diff --git a/source/dash/components/animation.d b/source/dash/components/animation.d index acfed550..c668692a 100644 --- a/source/dash/components/animation.d +++ b/source/dash/components/animation.d @@ -424,22 +424,22 @@ public: { mat4f matrix = mat4f.identity; - matrix.c[0][0] = aiMatrix.a1; - matrix.c[0][1] = aiMatrix.a2; - matrix.c[0][2] = aiMatrix.a3; - matrix.c[0][3] = aiMatrix.a4; - matrix.c[1][0] = aiMatrix.b1; - matrix.c[1][1] = aiMatrix.b2; - matrix.c[1][2] = aiMatrix.b3; - matrix.c[1][3] = aiMatrix.b4; - matrix.c[2][0] = aiMatrix.c1; - matrix.c[2][1] = aiMatrix.c2; - matrix.c[2][2] = aiMatrix.c3; - matrix.c[2][3] = aiMatrix.c4; - matrix.c[3][0] = aiMatrix.d1; - matrix.c[3][1] = aiMatrix.d2; - matrix.c[3][2] = aiMatrix.d3; - matrix.c[3][3] = aiMatrix.d4; + matrix[0][0] = aiMatrix.a1; + matrix[0][1] = aiMatrix.a2; + matrix[0][2] = aiMatrix.a3; + matrix[0][3] = aiMatrix.a4; + matrix[1][0] = aiMatrix.b1; + matrix[1][1] = aiMatrix.b2; + matrix[1][2] = aiMatrix.b3; + matrix[1][3] = aiMatrix.b4; + matrix[2][0] = aiMatrix.c1; + matrix[2][1] = aiMatrix.c2; + matrix[2][2] = aiMatrix.c3; + matrix[2][3] = aiMatrix.c4; + matrix[3][0] = aiMatrix.d1; + matrix[3][1] = aiMatrix.d2; + matrix[3][2] = aiMatrix.d3; + matrix[3][3] = aiMatrix.d4; return matrix; } diff --git a/source/dash/components/camera.d b/source/dash/components/camera.d index bcd3f50a..612666aa 100644 --- a/source/dash/components/camera.d +++ b/source/dash/components/camera.d @@ -141,11 +141,11 @@ public: vec3f yaxis = vec3f( sinYaw * sinPitch, cosPitch, cosYaw * sinPitch ); vec3f zaxis = vec3f( sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw ); - _viewMatrix.v[] = 0.0f; - _viewMatrix.c[ 0 ] = vec4f( xaxis, -xaxis.dot( owner.transform.position ) ).vector; - _viewMatrix.c[ 1 ] = vec4f( yaxis, -yaxis.dot( owner.transform.position ) ).vector; - _viewMatrix.c[ 2 ] = vec4f( zaxis, -zaxis.dot( owner.transform.position ) ).vector; - _viewMatrix.c[ 3 ] = vec4f( 0, 0, 0, 1 ).vector; + _viewMatrix.clear( 0.0f ); + _viewMatrix[ 0 ] = vec4f( xaxis, -xaxis.dot( owner.transform.position ) ).vector; + _viewMatrix[ 1 ] = vec4f( yaxis, -yaxis.dot( owner.transform.position ) ).vector; + _viewMatrix[ 2 ] = vec4f( zaxis, -zaxis.dot( owner.transform.position ) ).vector; + _viewMatrix[ 3 ] = vec4f( 0, 0, 0, 1 ).vector; _inverseViewMatrix = _viewMatrix.inverse(); } @@ -171,18 +171,18 @@ public: mat4f result = mat4f.identity; - result.c[0][0] = xaxis.x; - result.c[1][0] = xaxis.y; - result.c[2][0] = xaxis.z; - result.c[3][0] = -dot( xaxis, cameraPos ); - result.c[0][1] = yaxis.x; - result.c[1][1] = yaxis.y; - result.c[2][1] = yaxis.z; - result.c[3][1] = -dot( yaxis, cameraPos ); - result.c[0][2] = zaxis.x; - result.c[1][2] = zaxis.y; - result.c[2][2] = zaxis.z; - result.c[3][2] = -dot( zaxis, cameraPos ); + result[0][0] = xaxis.x; + result[1][0] = xaxis.y; + result[2][0] = xaxis.z; + result[3][0] = -dot( xaxis, cameraPos ); + result[0][1] = yaxis.x; + result[1][1] = yaxis.y; + result[2][1] = yaxis.z; + result[3][1] = -dot( yaxis, cameraPos ); + result[0][2] = zaxis.x; + result[1][2] = zaxis.y; + result[2][2] = zaxis.z; + result[3][2] = -dot( zaxis, cameraPos ); return result.transposed; } @@ -234,10 +234,10 @@ private: { _orthogonalMatrix = mat4f.identity; - _orthogonalMatrix.c[0][0] = 2.0f / Graphics.width; - _orthogonalMatrix.c[1][1] = 2.0f / Graphics.height; - _orthogonalMatrix.c[2][2] = -2.0f / (far - near); - _orthogonalMatrix.c[3][3] = 1.0f; + _orthogonalMatrix[0][0] = 2.0f / Graphics.width; + _orthogonalMatrix[1][1] = 2.0f / Graphics.height; + _orthogonalMatrix[2][2] = -2.0f / (far - near); + _orthogonalMatrix[3][3] = 1.0f; _inverseOrthogonalMatrix = _orthogonalMatrix.inverse(); } diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index e43a18b2..a12cf948 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -142,10 +142,10 @@ public: // build the view matrix mat4f viewMatrix; ///* - viewMatrix.c[ 0 ] = vec4f( xaxis, -xaxis.dot( center ) ).vector; - viewMatrix.c[ 1 ] = vec4f( yaxis, -yaxis.dot( center ) ).vector; - viewMatrix.c[ 2 ] = vec4f( zaxis, -zaxis.dot( center ) ).vector; - viewMatrix.c[ 3 ] = vec4f( 0, 0, 0, 1 ).vector; + viewMatrix[ 0 ] = vec4f( xaxis, -xaxis.dot( center ) ).vector; + viewMatrix[ 1 ] = vec4f( yaxis, -yaxis.dot( center ) ).vector; + viewMatrix[ 2 ] = vec4f( zaxis, -zaxis.dot( center ) ).vector; + viewMatrix[ 3 ] = vec4f( 0, 0, 0, 1 ).vector; /*/ // using lookAt works for everying but a light direction of (0,+/-1,0) light.view = Camera.lookAt( center - light.direction.normalized, center ); //*/ @@ -209,14 +209,14 @@ public: { _matrix = mat4f.identity; // Scale - _matrix.c[ 0 ][ 0 ] = radius; - _matrix.c[ 1 ][ 1 ] = radius; - _matrix.c[ 2 ][ 2 ] = radius; + _matrix[ 0 ][ 0 ] = radius; + _matrix[ 1 ][ 1 ] = radius; + _matrix[ 2 ][ 2 ] = radius; // Translate vec3f position = owner.transform.worldPosition; - _matrix.c[ 0 ][ 3 ] = position.x; - _matrix.c[ 1 ][ 3 ] = position.y; - _matrix.c[ 2 ][ 3 ] = position.z; + _matrix[ 0 ][ 3 ] = position.x; + _matrix[ 1 ][ 3 ] = position.y; + _matrix[ 2 ][ 3 ] = position.z; return _matrix; } diff --git a/source/dash/components/userinterface.d b/source/dash/components/userinterface.d index 26e095b9..df8db007 100644 --- a/source/dash/components/userinterface.d +++ b/source/dash/components/userinterface.d @@ -35,8 +35,8 @@ public: this( uint w, uint h, string filePath ) { _scaleMat = mat4f.identity; - _scaleMat.c[0][0] = cast(float)w/2.0f; - _scaleMat.c[1][1] = cast(float)h/2.0f; + _scaleMat[0][0] = cast(float)w/2.0f; + _scaleMat[1][1] = cast(float)h/2.0f; _height = h; _width = w; version(Windows) diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 73699a68..eda84493 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -448,16 +448,16 @@ public: static struct Description { /// The position of the object. - @rename( "Position" ) @asArray @optional - float[3] position; + @rename( "Position" ) @optional + float[3] position = [ 0.0f, 0.0f, 0.0f ]; /// The position of the object. - @rename( "Rotation" ) @asArray @optional - float[3] rotation; + @rename( "Rotation" ) @optional + float[3] rotation = [ 0.0f, 0.0f, 0.0f ]; /// The position of the object. - @rename( "Scale" ) @asArray @optional - float[3] scale; + @rename( "Scale" ) @optional + float[3] scale = [ 0.0f, 0.0f, 0.0f ]; } /** @@ -618,17 +618,17 @@ public: _matrix = mat4f.identity; // Scale - _matrix.c[ 0 ][ 0 ] = scale.x; - _matrix.c[ 1 ][ 1 ] = scale.y; - _matrix.c[ 2 ][ 2 ] = scale.z; + _matrix[ 0 ][ 0 ] = scale.x; + _matrix[ 1 ][ 1 ] = scale.y; + _matrix[ 2 ][ 2 ] = scale.z; // Rotate _matrix = _matrix * rotation.toMatrix!4; // Translate - _matrix.c[ 0 ][ 3 ] = position.x; - _matrix.c[ 1 ][ 3 ] = position.y; - _matrix.c[ 2 ][ 3 ] = position.z; + _matrix[ 0 ][ 3 ] = position.x; + _matrix[ 1 ][ 3 ] = position.y; + _matrix[ 2 ][ 3 ] = position.z; // include parent objects' transforms if( owner.parent ) diff --git a/source/dash/graphics/adapters/gl.d b/source/dash/graphics/adapters/gl.d index 935bbf8a..b703eb06 100644 --- a/source/dash/graphics/adapters/gl.d +++ b/source/dash/graphics/adapters/gl.d @@ -167,50 +167,44 @@ public: mat4f projection = scene.camera.perspectiveMatrix; mat4f invProj = scene.camera.inversePerspectiveMatrix; - void updateMatricies( GameObject current ) - { - current.transform.updateMatrix(); - foreach( child; current.children ) - updateMatricies( child ); - } - updateMatricies( scene.root ); + scene.root.transform.updateMatrix(); /** * Pass for all objects with Meshes */ void geometryPass() { - foreach( object; scene.objects ) + foreach( obj; scene.objects ) { - if( object.mesh && object.stateFlags.drawMesh ) + if( obj.mesh && obj.stateFlags.drawMesh ) { - mat4f worldView = scene.camera.viewMatrix * object.transform.matrix; + mat4f worldView = scene.camera.viewMatrix * obj.transform.matrix; mat4f worldViewProj = projection * worldView; - if( !( object.mesh.boundingBox in Frustum( worldViewProj ) ) ) + if( !( obj.mesh.boundingBox in Frustum( worldViewProj ) ) ) { // If we can't see an object, don't draw it. continue; } // set the shader - Shader shader = object.mesh.animated + Shader shader = obj.mesh.animated ? Shaders.animatedGeometry : Shaders.geometry; glUseProgram( shader.programID ); - glBindVertexArray( object.mesh.glVertexArray ); + glBindVertexArray( obj.mesh.glVertexArray ); shader.bindUniformMatrix4fv( shader.WorldView, worldView ); shader.bindUniformMatrix4fv( shader.WorldViewProjection, worldViewProj ); - shader.bindUniform1ui( shader.ObjectId, object.id ); + shader.bindUniform1ui( shader.ObjectId, obj.id ); - if( object.mesh.animated ) - shader.bindUniformMatrix4fvArray( shader.Bones, object.animation.currBoneTransforms ); + if( obj.mesh.animated ) + shader.bindUniformMatrix4fvArray( shader.Bones, obj.animation.currBoneTransforms ); - shader.bindMaterial( object.material ); + shader.bindMaterial( obj.material ); - glDrawElements( GL_TRIANGLES, object.mesh.numVertices, GL_UNSIGNED_INT, null ); + glDrawElements( GL_TRIANGLES, obj.mesh.numVertices, GL_UNSIGNED_INT, null ); glBindVertexArray(0); } diff --git a/source/dash/graphics/shaders/shaders.d b/source/dash/graphics/shaders/shaders.d index dad60a29..5f0c0723 100644 --- a/source/dash/graphics/shaders/shaders.d +++ b/source/dash/graphics/shaders/shaders.d @@ -288,7 +288,7 @@ public: float[] matptr; foreach( matrix; matrices ) { - matptr ~= matrix.v[]; + matptr ~= matrix.value_ptr()[0..16]; } glUniformMatrix4fv( uniform, cast(int)matrices.length, false, matptr.ptr ); } diff --git a/source/dash/utility/math.d b/source/dash/utility/math.d index 2dc61f72..9e0a5e54 100644 --- a/source/dash/utility/math.d +++ b/source/dash/utility/math.d @@ -34,16 +34,6 @@ public: // Matrices alias mat4f = Matrix!( float, 4, 4 ); - Floating[Size][Size] c( Floating, uint Size )( Matrix!( Floating, Size, Size ) m ) @property - { - return m.matrix; - } - - Floating[] v( Floating, uint Size )( Matrix!( Floating, Size, Size ) m ) @property - { - return m.value_ptr[ 0..Size*Size ]; - } - mat4f perspectiveMat( float width, float height, float fov, float near, float far ) { return mat4f.perspective( width, height, fov, near, far ); From 0d2bf8248e22d97dd73a30e15d2c4a8ffc093513 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sun, 21 Sep 2014 18:41:44 -0400 Subject: [PATCH 058/141] Fixed unittests --- source/dash/core/gameobject.d | 20 +++++++------------- source/dash/utility/tasks.d | 12 ++++-------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index eda84493..e54296be 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -551,10 +551,8 @@ public: auto trans = new Transform( null ); auto forward = vec3f( 0.0f, 1.0f, 0.0f ); - trans.rotation *= fromEulerAngles( 90.0f.radians, 0.0f, 0.0f ); - - foreach( i, v; trans.forward.v ) - assert( abs( v - forward.v[ i ] ) < 0.000001f ); + trans.rotation.rotatex( 90.radians ); + assert( almost_equal( trans.forward, forward ) ); } /* @@ -576,10 +574,8 @@ public: auto trans = new Transform( null ); auto up = vec3f( 0.0f, 0.0f, 1.0f ); - trans.rotation *= fromEulerAngles( 90.0f.radians, 0.0f, 0.0f ); - - foreach( i, v; trans.up.v ) - assert( abs( v - up.v[ i ] ) < 0.000001f ); + trans.rotation.rotatex( 90.radians ); + assert( almost_equal( trans.up, up ) ); } /* @@ -600,11 +596,9 @@ public: writeln( "Dash Transform right unittest" ); auto trans = new Transform( null ); - auto right = vec3f( 0.0f, 0.0f, -1.0f ); - trans.rotation *= fromEulerAngles( 0.0f, 90.0f.radians, 0.0f ); - - foreach( i, v; trans.right.v ) - assert( abs( v - right.v[ i ] ) < 0.000001f ); + auto right = vec3( 0.0f, 0.0f, -1.0f ); + trans.rotation.rotatey( 90.radians ); + assert( almost_equal( trans.right, right ) ); } /** diff --git a/source/dash/utility/tasks.d b/source/dash/utility/tasks.d index 031a44ec..af9a0f23 100644 --- a/source/dash/utility/tasks.d +++ b/source/dash/utility/tasks.d @@ -3,7 +3,7 @@ * */ module dash.utility.tasks; -import dash.utility.time, dash.utility.output; +import dash.utility.time, dash.utility.output, dash.utility.math; import core.time; import std.algorithm: min; @@ -44,7 +44,7 @@ UUID scheduleTask( bool delegate() dg ) * scheduleInterpolateTask( position, startNode, endNode, 100.msecs ); * --- */ -UUID scheduleInterpolateTask(T)( ref T val, T start, T end, Duration duration, T function( T, T, float ) interpFunc = &lerp!( T, float ) )// if( is_vector!T || is_quaternion!T ) +UUID scheduleInterpolateTask(T)( ref T val, T start, T end, Duration duration, T function( T, T, float ) interpFunc = &lerp!( T ) )// if( is_vector!T || is_quaternion!T ) { return scheduleTimedTask( duration, ( elapsed ) { @@ -54,9 +54,7 @@ UUID scheduleInterpolateTask(T)( ref T val, T start, T end, Duration duration, T /// unittest { - import dash.utility.time; import std.stdio; - import gfm.math.vector; writeln( "Dash Tasks scheduleInterpolateTask unittest 1" ); @@ -93,7 +91,7 @@ unittest * scheduleInterpolateTask!q{position}( transform, startNode, endNode, 100.msecs ); * --- */ -UUID scheduleInterpolateTask( string prop, T, Owner )( ref Owner own, T start, T end, Duration duration, T function( T, T, float ) interpFunc = &lerp!( T, float ) ) +UUID scheduleInterpolateTask( string prop, T, Owner )( ref Owner own, T start, T end, Duration duration, T function( T, T, float ) interpFunc = &lerp!( T ) ) if( __traits( compiles, mixin( "own." ~ prop ) ) ) { auto startTime = Time.totalTime; @@ -105,9 +103,7 @@ UUID scheduleInterpolateTask( string prop, T, Owner )( ref Owner own, T start, T /// unittest { - import dash.utility.time; import std.stdio; - import gfm.math.vector; writeln( "Dash Tasks scheduleInterpolateTask unittest 2" ); @@ -128,7 +124,7 @@ unittest version( unittest ) class TestPropertyInterpolate { - import gfm.math.vector; + import dash.utility.math; private vec3f _vector; public @property vec3f vector() { return _vector; } From 2b8a04597e32abe14dec547bd709e63859d3dc00 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sun, 21 Sep 2014 19:27:41 -0400 Subject: [PATCH 059/141] Fixed NaNs being passed to gl --- source/dash/components/component.d | 7 ++++--- source/dash/components/lights.d | 8 ++++---- source/dash/graphics/shaders/shaders.d | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 66d0da5a..54628dd4 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -203,16 +203,17 @@ private: static if( !memberName.among( "this", "~this", __traits( allMembers, Component ) ) && is( typeof( helper!( __traits( getMember, T, memberName ) ) ) ) ) { + import vibe.internal.meta.uda; + alias member = helper!( __traits( getMember, T, memberName ) ); // Process variables - static if( !isSomeFunction!member ) + static if( !isSomeFunction!member && !findFirstUDA!( IgnoreAttribute, member ).found ) { - import std.conv; - // Get string form of attributes string attributesStr() { + import std.conv; string[] attrs; foreach( attr; __traits( getAttributes, member ) ) { diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index a12cf948..dbabc29c 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -18,7 +18,7 @@ abstract class Light : Component { public: /// The color the light gives off. - @rename( "Color" ) @optional + @rename( "Color" ) @ignore vec3f color; /// If it should cast shadows @rename( "CastShadows" ) @optional @@ -58,7 +58,7 @@ private: public: /// The direction the light points in. - @rename( "Direction" ) @optional + @rename( "Direction" ) @ignore vec3f direction; /// The FrameBuffer for the shadowmap. mixin( Property!( _shadowMapFrameBuffer ) ); @@ -67,7 +67,7 @@ public: mixin( Property!( _projView ) ); mixin( Property!( _shadowMapSize ) ); - this( vec3f color = vec3f(), vec3f direction = vec3f(), bool castShadows = false ) + this( vec3f color = vec3f( 1.0f ), vec3f direction = vec3f( 0.0f ), bool castShadows = false ) { this.direction = direction; super( color ); @@ -191,7 +191,7 @@ public: @rename( "FalloffRate" ) float falloffRate; - this( vec3f color = vec3f(), float radius = 0.0f, float falloffRate = 0.0f ) + this( vec3f color = vec3f( 1.0f ), float radius = 0.0f, float falloffRate = 0.0f ) { this.radius = radius; this.falloffRate = falloffRate; diff --git a/source/dash/graphics/shaders/shaders.d b/source/dash/graphics/shaders/shaders.d index 5f0c0723..f47cc5e3 100644 --- a/source/dash/graphics/shaders/shaders.d +++ b/source/dash/graphics/shaders/shaders.d @@ -290,7 +290,7 @@ public: { matptr ~= matrix.value_ptr()[0..16]; } - glUniformMatrix4fv( uniform, cast(int)matrices.length, false, matptr.ptr ); + glUniformMatrix4fv( uniform, cast(int)matrices.length, true, matptr.ptr ); } /** From b5cdaab235d1ddf02c4dbe6ba754d83ca2dd724b Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 22 Sep 2014 13:10:22 -0400 Subject: [PATCH 060/141] Added default light color, fixed boneTransform scale. --- source/dash/components/animation.d | 6 +++--- source/dash/components/lights.d | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/dash/components/animation.d b/source/dash/components/animation.d index c668692a..84e33048 100644 --- a/source/dash/components/animation.d +++ b/source/dash/components/animation.d @@ -356,9 +356,9 @@ public: } if( bonePose.scaleKeys.length > cast(int)time ) { - boneTransform = boneTransform.scaling( bonePose.scaleKeys[ cast(int)time ].vector[ 0 ], - bonePose.scaleKeys[ cast(int)time ].vector[ 1 ], - bonePose.scaleKeys[ cast(int)time ].vector[ 2 ] ); + boneTransform = boneTransform.scale( bonePose.scaleKeys[ cast(int)time ].vector[ 0 ], + bonePose.scaleKeys[ cast(int)time ].vector[ 1 ], + bonePose.scaleKeys[ cast(int)time ].vector[ 2 ] ); } finalTransform = parentTransform * boneTransform; diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index dbabc29c..ccb971f5 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -39,7 +39,7 @@ public: */ class AmbientLight : Light { - this( vec3f color = vec3f() ) + this( vec3f color = vec3f( 1.0f ) ) { super( color ); } From d9367ac1466c26767a5fe86634246983278b035c Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 22 Sep 2014 13:31:19 -0400 Subject: [PATCH 061/141] Stupid radians --- dub.json | 2 +- source/dash/components/camera.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dub.json b/dub.json index 9006e62b..2cc5f036 100644 --- a/dub.json +++ b/dub.json @@ -24,7 +24,7 @@ "gl3n": "==1.0.0", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", - "vibe-d": "~master", + "vibe-d": "0.7.21-beta.4", "x11": { "version": "~>1.0", "optional": true } }, diff --git a/source/dash/components/camera.d b/source/dash/components/camera.d index 612666aa..4bbeef4e 100644 --- a/source/dash/components/camera.d +++ b/source/dash/components/camera.d @@ -223,7 +223,7 @@ private: final void updatePerspective() { _projectionConstants = vec2f( ( -far * near ) / ( far - near ), far / ( far - near ) ); - _perspectiveMatrix = perspectiveMat( cast(float)Graphics.width, cast(float)Graphics.height, fov.radians, near, far ); + _perspectiveMatrix = perspectiveMat( cast(float)Graphics.width, cast(float)Graphics.height, fov, near, far ); _inversePerspectiveMatrix = _perspectiveMatrix.inverse(); } From 1eb42f9c12f4d6f01464ca6a25659895be141cc9 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 22 Sep 2014 13:42:06 -0400 Subject: [PATCH 062/141] Blame it on the ra ra ra ra ra radians --- source/dash/core/gameobject.d | 2 +- source/dash/utility/math.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index e54296be..c1b3605e 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -423,7 +423,7 @@ private: void opAssign( Description desc ) { position = vec3f( desc.position[] ); - rotation = fromEulerAngles( desc.rotation[ 1 ], desc.rotation[ 0 ], desc.rotation[ 2 ] ); + rotation = fromEulerAngles( desc.rotation[ 0 ], desc.rotation[ 1 ], desc.rotation[ 2 ] ); scale = vec3f( desc.scale[] ); } diff --git a/source/dash/utility/math.d b/source/dash/utility/math.d index 9e0a5e54..5eb5b823 100644 --- a/source/dash/utility/math.d +++ b/source/dash/utility/math.d @@ -28,7 +28,7 @@ public: Quaternion!Floating fromEulerAngles( Floating = float )( Floating pitch, Floating yaw, Floating roll ) { - return Quaternion!Floating.identity.rotatex( pitch ).rotatey( yaw ).rotatez( roll ); + return Quaternion!Floating.identity.rotatex( pitch.radians ).rotatey( yaw.radians ).rotatez( roll.radians ); } // Matrices From 7207b6fdbf46b05a346c80e7d2aa4b6e069248be Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 22 Sep 2014 14:59:35 -0400 Subject: [PATCH 063/141] Fixed the test failure in tasks.d --- source/dash/utility/tasks.d | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/dash/utility/tasks.d b/source/dash/utility/tasks.d index 29d19c8b..35ff2f1a 100644 --- a/source/dash/utility/tasks.d +++ b/source/dash/utility/tasks.d @@ -59,7 +59,7 @@ unittest { import dash.utility.time; import std.stdio; - import gl3n.linalg; + import gl3n.linalg. gl3n.math; writeln( "Dash Tasks scheduleInterpolateTask unittest 1" ); @@ -74,7 +74,7 @@ unittest executeTasks(); } - assert( interpVec == end ); + assert( almost_equal( interpVec, end ) ); } /** @@ -110,7 +110,7 @@ unittest { import dash.utility.time; import std.stdio; - import gl3n.linalg; + import gl3n.linalg, gl3n.math; writeln( "Dash Tasks scheduleInterpolateTask unittest 2" ); @@ -126,7 +126,7 @@ unittest Time.update(); } - assert( testClass.vector == end ); + assert( almost_equal( testClass.vector, end ) ); } version( unittest ) class TestPropertyInterpolate From 097bfae371a43de8a5c3884ba2f3009d1be1b7f7 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 22 Sep 2014 15:54:18 -0400 Subject: [PATCH 064/141] That's what I get for writing code in GitHub --- source/dash/utility/tasks.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dash/utility/tasks.d b/source/dash/utility/tasks.d index 35ff2f1a..fd5cdd57 100644 --- a/source/dash/utility/tasks.d +++ b/source/dash/utility/tasks.d @@ -59,7 +59,7 @@ unittest { import dash.utility.time; import std.stdio; - import gl3n.linalg. gl3n.math; + import gl3n.linalg, gl3n.math; writeln( "Dash Tasks scheduleInterpolateTask unittest 1" ); From 060bf713eb68219edfc30d87304d0907f29e45dd Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 22 Sep 2014 18:12:57 -0400 Subject: [PATCH 065/141] Implemented custom serializer for external types, some code cleanup --- source/dash/components/component.d | 89 ++++++++++++++---------- source/dash/components/lights.d | 4 +- source/dash/utility/data/serialization.d | 64 +++++++++++++++-- source/dash/utility/math.d | 15 ++++ 4 files changed, 130 insertions(+), 42 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 54628dd4..d11632b2 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -87,6 +87,7 @@ public: string typeName; string attributes; string mod; + string serializer; } abstract immutable(Field[]) fields() const @property; @@ -134,7 +135,7 @@ public: }; Component.$typeDeserializers[ T.stringof ] = ( $type node ) { - return deserialize$type!( SerializationDescription )( node ).createInstance(); + return deserialize$type!SerializationDescription( node ).createInstance(); }; } ); @@ -148,47 +149,74 @@ private: // Generate actual struct final class SerializationDescription : Description { - //pragma( msg, T.stringof ~ "\n" ~ descContents ); - mixin( descContents ); + mixin( { return reduce!( ( working, field ) + { + string result = working; + + // Append required import for variable type + if( field.mod ) + result ~= "import " ~ field.mod ~ ";\n"; + + // Append variable attributes + if( field.attributes ) + result ~= "@(" ~ field.attributes ~ ")\n"; + // Append variable declaration + result ~= field.typeName ~ " " ~ field.name ~ ";\n"; + + return result; + } + )( "", fieldList ); } () ); + + /// Get a list of field descriptions override immutable(Description.Field[]) fields() const @property { return fieldList; } - // Create a description from a component. + /// Create a description from a component. static const(SerializationDescription) create( Component comp ) { auto theThing = cast(T)comp; auto desc = new SerializationDescription; - foreach( field; __traits( allMembers, T ) ) + foreach( fieldName; __traits( allMembers, T ) ) { - static if( fieldList.map!(f => f.name).canFind( field ) ) + enum idx = fieldList.map!(f => f.name).countUntil( fieldName ); + static if( idx >= 0 ) { - mixin( "desc."~field~" = theThing."~field~";\n" ); + enum field = fieldList[ idx ]; + mixin( "auto ser = "~field.serializer~".serialize(theThing."~field.name~");" ); + mixin( "desc."~field.name~" = ser;" ); } } return desc; } - // Create a component from a description. + /// Create a component from a description. T createInstance() { T comp = new T; - foreach( field; __traits( allMembers, T ) ) + foreach( fieldName; __traits( allMembers, T ) ) { - static if( fieldList.map!(f => f.name).canFind( field ) ) + enum idx = fieldList.map!(f => f.name).countUntil( fieldName ); + static if( idx >= 0 ) { - mixin( "comp." ~ field ~ " = this." ~ field ~ ";\n" ); + enum field = fieldList[ idx ]; + // Check if the field was actually set + if( mixin( field.name ) != mixin( "new SerializationDescription()." ~ field.name ) ) + { + mixin( "auto ser = "~field.serializer~".deserialize(this."~field.name~");" ); + mixin( "comp."~field.name~" = ser;" ); + } } } return comp; } } - // Get a list of fields on the type + /// Get a list of fields on the type Description.Field[] getFields( size_t idx = 0 )( Description.Field[] fields = [] ) { static if( idx == __traits( allMembers, T ).length ) @@ -206,6 +234,7 @@ private: import vibe.internal.meta.uda; alias member = helper!( __traits( getMember, T, memberName ) ); + alias memberType = typeof(member); // Process variables static if( !isSomeFunction!member && !findFirstUDA!( IgnoreAttribute, member ).found ) @@ -228,9 +257,19 @@ private: else enum modName = null; + // Get the serializer for the type + alias serializer = serializerFor!memberType; + alias descMemberType = serializer.Rep; // Generate field - enum newField = Description.Field( memberName, fullyQualifiedName!(Unqual!(typeof(member))), attributesStr, modName ); - return getFields!( idx + 1 )( fields ~ newField ); + return getFields!( idx + 1 )( fields ~ + Description.Field( + memberName, + fullyQualifiedName!(Unqual!descMemberType), + attributesStr, + modName, + serializer.stringof + ) + ); } else { @@ -243,26 +282,4 @@ private: } } } - - // Generate static description struct for deserializing - enum descContents = { - return reduce!( ( working, field ) - { - string result = working; - - // Append required import for variable type - if( field.mod ) - result ~= "import " ~ field.mod ~ ";\n"; - - // Append variable attributes - if( field.attributes ) - result ~= "@(" ~ field.attributes ~ ") "; - - // Append variable declaration - result ~= field.typeName ~ " " ~ field.name ~ ";\n"; - - return result; - } - )( "", fieldList ); - } (); } diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index ccb971f5..58d31e26 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -18,7 +18,7 @@ abstract class Light : Component { public: /// The color the light gives off. - @rename( "Color" ) @ignore + @rename( "Color" ) @optional vec3f color; /// If it should cast shadows @rename( "CastShadows" ) @optional @@ -58,7 +58,7 @@ private: public: /// The direction the light points in. - @rename( "Direction" ) @ignore + @rename( "Direction" ) @optional vec3f direction; /// The FrameBuffer for the shadowmap. mixin( Property!( _shadowMapFrameBuffer ) ); diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index da6b88c1..df94b39d 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -1,8 +1,12 @@ module dash.utility.data.serialization; -import dash.utility.resources; import dash.utility.data.yaml; +import dash.utility.resources; +import dash.utility.math; + import vibe.data.json, vibe.data.bson; import std.typecons: Tuple, tuple; +import std.typetuple; +import std.math; // Serialization attributes public import vibe.data.serialization: rename = name, asArray, byName, ignore, optional, isCustomSerializable; @@ -10,6 +14,61 @@ public import vibe.data.serialization: rename = name, asArray, byName, ignore, o /// Supported serialization formats. enum serializationFormats = tuple( "Json"/*, "Bson"*/, "Yaml" ); +/// Type to use when defining custom +struct CustomSerializer( _T, _Rep, alias _ser, alias _deser, alias _check = (_) => true ) + if( is( typeof( _ser( _T.init ) ) == _Rep ) && + is( typeof( _deser( _Rep.init ) ) == _T ) && + is( typeof( _check( _Rep.init ) ) == bool ) ) +{ + /// The type being serialized + alias T = _T; + /// The serialized representation + alias Rep = _Rep; + /// Function to convert the type to its rep + alias serialize = _ser; + /// Function to convert the rep to the type + alias deserialize = _deser; + /// Function called to ensure the representation is valid + alias check = _check; +} + +/// For calling templated templates. +template PApply( alias Target, T... ) +{ + alias PApply( U... ) = Target!( T, U ); +} + +/// Checks if a serializer is for a type. +enum serializerTypesMatch( Type, alias CS ) = is( CS.T == Type ); + +/// Predicate for std.typetupple +alias isSerializerFor( T ) = PApply!( serializerTypesMatch, T ); + +/// Does a given type have a serializer +enum hasSerializer( T ) = anySatisfy!( isSerializerFor!T, customSerializers ); + +/// Get the serializer for a type +template serializerFor( T ) +{ + static if( hasSerializer!T ) + alias serializerFor = Filter!( isSerializerFor!T, customSerializers )[ 0 ]; + else + alias serializerFor = defaultSerializer!T; +} + +/// A tuple of all supported serializers +alias customSerializers = TypeTuple!( + CustomSerializer!( vec2f, float[], vec => vec.vector[], arr => vec2f( arr ), arr => arr.length == 2 ), + CustomSerializer!( vec3f, float[], vec => vec.vector[], arr => vec3f( arr ), arr => arr.length == 3 ), + CustomSerializer!( quatf, float[], vec => vec.toEulerAngles.vector[], arr => fromEulerAngles( arr ), arr => arr.length == 3 ), +); +static assert( hasSerializer!vec2f ); +static assert( hasSerializer!vec3f ); +static assert( hasSerializer!quatf ); + +/// Serializer for all other types +alias defaultSerializer( T ) = CustomSerializer!( T, T, t => t, t => t, t => true ); + /** * Modes of serialization. */ @@ -96,9 +155,6 @@ T deserializeFile( T )( Resource file, SerializationMode mode = SerializationMod */ T[] deserializeMultiFile( T )( Resource file, SerializationMode mode = SerializationMode.Default ) { - import dash.utility.output; - logInfo( "Deserializing ", file.baseFileName, " to ", T.stringof ); - import std.path: extension; import std.string: toLower; diff --git a/source/dash/utility/math.d b/source/dash/utility/math.d index 5eb5b823..d4a68d96 100644 --- a/source/dash/utility/math.d +++ b/source/dash/utility/math.d @@ -31,6 +31,21 @@ public: return Quaternion!Floating.identity.rotatex( pitch.radians ).rotatey( yaw.radians ).rotatez( roll.radians ); } + Quaternion!Floating fromEulerAngles( Floating = float )( Vector!( Floating, 3 ) vec ) + { + return fromEulerAngles( vec.x, vec.y, vec.z ); + } + + Quaternion!Floating fromEulerAngles( Floating = float )( Floating[] angles ) + in + { + assert( angles.length >= 3, "Invalid array given." ); + } + body + { + return fromEulerAngles( angles[ 0 ], angles[ 1 ], angles[ 2 ] ); + } + // Matrices alias mat4f = Matrix!( float, 4, 4 ); From bf671de4fcc7f5a0ca0736bd747bf9b54380dd71 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 22 Sep 2014 18:27:50 -0400 Subject: [PATCH 066/141] Added type field to Description --- source/dash/components/component.d | 3 + source/dash/utility/data/serialization.d | 127 ++++++++++++----------- 2 files changed, 68 insertions(+), 62 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index d11632b2..598ed5d3 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -90,6 +90,8 @@ public: string serializer; } + @rename( "Type" ) + string type; abstract immutable(Field[]) fields() const @property; } @@ -179,6 +181,7 @@ private: { auto theThing = cast(T)comp; auto desc = new SerializationDescription; + desc.type = T.stringof; foreach( fieldName; __traits( allMembers, T ) ) { diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index df94b39d..de7172d3 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -11,64 +11,6 @@ import std.math; // Serialization attributes public import vibe.data.serialization: rename = name, asArray, byName, ignore, optional, isCustomSerializable; -/// Supported serialization formats. -enum serializationFormats = tuple( "Json"/*, "Bson"*/, "Yaml" ); - -/// Type to use when defining custom -struct CustomSerializer( _T, _Rep, alias _ser, alias _deser, alias _check = (_) => true ) - if( is( typeof( _ser( _T.init ) ) == _Rep ) && - is( typeof( _deser( _Rep.init ) ) == _T ) && - is( typeof( _check( _Rep.init ) ) == bool ) ) -{ - /// The type being serialized - alias T = _T; - /// The serialized representation - alias Rep = _Rep; - /// Function to convert the type to its rep - alias serialize = _ser; - /// Function to convert the rep to the type - alias deserialize = _deser; - /// Function called to ensure the representation is valid - alias check = _check; -} - -/// For calling templated templates. -template PApply( alias Target, T... ) -{ - alias PApply( U... ) = Target!( T, U ); -} - -/// Checks if a serializer is for a type. -enum serializerTypesMatch( Type, alias CS ) = is( CS.T == Type ); - -/// Predicate for std.typetupple -alias isSerializerFor( T ) = PApply!( serializerTypesMatch, T ); - -/// Does a given type have a serializer -enum hasSerializer( T ) = anySatisfy!( isSerializerFor!T, customSerializers ); - -/// Get the serializer for a type -template serializerFor( T ) -{ - static if( hasSerializer!T ) - alias serializerFor = Filter!( isSerializerFor!T, customSerializers )[ 0 ]; - else - alias serializerFor = defaultSerializer!T; -} - -/// A tuple of all supported serializers -alias customSerializers = TypeTuple!( - CustomSerializer!( vec2f, float[], vec => vec.vector[], arr => vec2f( arr ), arr => arr.length == 2 ), - CustomSerializer!( vec3f, float[], vec => vec.vector[], arr => vec3f( arr ), arr => arr.length == 3 ), - CustomSerializer!( quatf, float[], vec => vec.toEulerAngles.vector[], arr => fromEulerAngles( arr ), arr => arr.length == 3 ), -); -static assert( hasSerializer!vec2f ); -static assert( hasSerializer!vec3f ); -static assert( hasSerializer!quatf ); - -/// Serializer for all other types -alias defaultSerializer( T ) = CustomSerializer!( T, T, t => t, t => t, t => true ); - /** * Modes of serialization. */ @@ -205,11 +147,14 @@ template serializeToFile( bool prettyPrint = true ) { import std.path: extension; import std.string: toLower; - import std.file: File; + import std.file: write; + import std.array: appender; void handleJson() { - writeJsonString!( File, prettyPrint )( new File( outPath ), serializeToJson( t ) ); + auto json = appender!string; + writeJsonString!( typeof(json), prettyPrint )( json, serializeToJson( t ) ); + write( outPath, json.data ); } void handleBson() @@ -228,15 +173,73 @@ template serializeToFile( bool prettyPrint = true ) case Bson: handleBson(); break; case Yaml: handleYaml(); break; case Default: - switch( file.extension.toLower ) + switch( outPath.extension.toLower ) { case ".json": handleJson(); break; case ".bson": handleBson(); break; case ".yaml": case ".yml": handleYaml(); break; - default: throw new Exception( "File extension " ~ file.extension.toLower ~ " not supported." ); + default: throw new Exception( "File extension " ~ outPath.extension.toLower ~ " not supported." ); } break; } } } + +/// Supported serialization formats. +enum serializationFormats = tuple( "Json"/*, "Bson"*/, "Yaml" ); + +/// Type to use when defining custom +struct CustomSerializer( _T, _Rep, alias _ser, alias _deser, alias _check = (_) => true ) + if( is( typeof( _ser( _T.init ) ) == _Rep ) && + is( typeof( _deser( _Rep.init ) ) == _T ) && + is( typeof( _check( _Rep.init ) ) == bool ) ) +{ + /// The type being serialized + alias T = _T; + /// The serialized representation + alias Rep = _Rep; + /// Function to convert the type to its rep + alias serialize = _ser; + /// Function to convert the rep to the type + alias deserialize = _deser; + /// Function called to ensure the representation is valid + alias check = _check; +} + +/// For calling templated templates. +template PApply( alias Target, T... ) +{ + alias PApply( U... ) = Target!( T, U ); +} + +/// Checks if a serializer is for a type. +enum serializerTypesMatch( Type, alias CS ) = is( CS.T == Type ); + +/// Predicate for std.typetupple +alias isSerializerFor( T ) = PApply!( serializerTypesMatch, T ); + +/// Does a given type have a serializer +enum hasSerializer( T ) = anySatisfy!( isSerializerFor!T, customSerializers ); + +/// Get the serializer for a type +template serializerFor( T ) +{ + static if( hasSerializer!T ) + alias serializerFor = Filter!( isSerializerFor!T, customSerializers )[ 0 ]; + else + alias serializerFor = defaultSerializer!T; +} + +/// A tuple of all supported serializers +alias customSerializers = TypeTuple!( + CustomSerializer!( vec2f, float[], vec => vec.vector[], arr => vec2f( arr ), arr => arr.length == 2 ), + CustomSerializer!( vec3f, float[], vec => vec.vector[], arr => vec3f( arr ), arr => arr.length == 3 ), + CustomSerializer!( quatf, float[], vec => vec.toEulerAngles.vector[], arr => fromEulerAngles( arr ), arr => arr.length == 3 ), +); +static assert( hasSerializer!vec2f ); +static assert( hasSerializer!vec3f ); +static assert( hasSerializer!quatf ); + +/// Serializer for all other types +alias defaultSerializer( T ) = CustomSerializer!( T, T, t => t, t => t, t => true ); From 0e1896527c312578f06a8f9691310594bf66f46d Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 22 Sep 2014 18:39:03 -0400 Subject: [PATCH 067/141] Serialize to yaml! --- source/dash/utility/data/serialization.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index de7172d3..f8917ec9 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -164,7 +164,7 @@ template serializeToFile( bool prettyPrint = true ) void handleYaml() { - throw new Exception( "Not implemented." ); + Dumper( outPath ).dump( serializeToYaml( t ) ); } final switch( mode ) with( SerializationMode ) From a0839c9afd954c01965001a001d23403bec3c6ca Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 22 Sep 2014 23:10:27 -0400 Subject: [PATCH 068/141] Implemented BSON serialization --- source/dash/components/component.d | 10 ++++++++-- source/dash/utility/data/serialization.d | 9 ++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 598ed5d3..6a2bc71d 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -52,13 +52,19 @@ public: { return $typeSerializers[ typeid(this) ]( cast()this ); } - static Component from$type( $type d ) + static Component from$type( $type data ) { + // If it's Bson, convert it to a json object. + static if( is( $type == Bson ) ) + auto d = data.toJson(); + else + auto d = data; + if( auto type = "Type" in d ) { if( auto cereal = type.get!string in $typeDeserializers ) { - return ( *cereal )( d ); + return ( *cereal )( data ); } else { diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index f8917ec9..26fecff8 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -61,13 +61,12 @@ T deserializeFile( T )( Resource file, SerializationMode mode = SerializationMod T handleBson() { - throw new Exception( "Not implemented." ); + return deserializeBson!T( Bson( Bson.Type.object, file.read().idup ) ); } T handleYaml() { - Yaml content = Loader.fromString( cast(char[])file.readText() ).load(); - return deserializeYaml!T( content ); + return deserializeYaml!T( Loader.fromString( cast(char[])file.readText() ).load() ); } final switch( mode ) with( SerializationMode ) @@ -159,7 +158,7 @@ template serializeToFile( bool prettyPrint = true ) void handleBson() { - throw new Exception( "Not implemented." ); + write( outPath, serializeToBson( t ).data ); } void handleYaml() @@ -187,7 +186,7 @@ template serializeToFile( bool prettyPrint = true ) } /// Supported serialization formats. -enum serializationFormats = tuple( "Json"/*, "Bson"*/, "Yaml" ); +enum serializationFormats = tuple( "Json", "Bson", "Yaml" ); /// Type to use when defining custom struct CustomSerializer( _T, _Rep, alias _ser, alias _deser, alias _check = (_) => true ) From 5d25eb3a0010580d4854754290b95d1923f8bbb7 Mon Sep 17 00:00:00 2001 From: Berulacks Date: Tue, 23 Sep 2014 04:05:13 -0400 Subject: [PATCH 069/141] Changed keys in state to an adaptive array --- source/dash/utility/input.d | 56 +++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index f68e8367..3561d3be 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -328,13 +328,13 @@ public: //alias Keyboard; version(UseSDL2) -{ - alias Keyboard = InputSystem!( KeyboardButtonsWin, void ); -} + + alias Keyboard = InputSystem!( KeyboardButtonsSDL, void ); + else -{ + alias Keyboard = InputSystem!( KeyboardButtonsWin, void ); -} + alias Mouse = InputSystem!( MouseButtons, MouseAxes ); private: @@ -496,7 +496,9 @@ public: */ void setButtonState( Buttons buttonCode, ButtonStorageType newState ) { - buttonStaging[ buttonCode ] = newState; + logDebug("Setting buttonstate for buttoncode ", cast(size_t) buttonCode); + buttonStaging[ cast(size_t) buttonCode ] = newState; + //logDebug("Kk, buttonStaging[", buttonCode, "] is now = ", buttonStaging[ buttonCode ]); } private: @@ -582,34 +584,60 @@ private: struct State( T, InputEnum ) if( is( InputEnum == enum ) ) { private: - enum totalSize = Inputs.END; + //enum totalSize = Inputs.END; + enum totalSize = EnumMembers!Inputs.length; alias StorageType = T; alias Inputs = InputEnum; public: - T[ totalSize ] keys; + T[ size_t ] keys; ref typeof(this) opAssign( const ref typeof(this) other ) { - for( uint ii = 0; ii < other.keys.length; ++ii ) + /*for( size_t ii = 0; ii < other.keys.length; ++ii ) + { keys[ ii ] = other.keys[ ii ]; + }*/ + foreach(size_t index, T value; other.keys) + { + keys[index] = value; + } return this; } - T opIndex( size_t keyCode ) const + T opIndex( size_t keyCode ) { - return keys[ keyCode ]; + if(keyCode in keys) + { + return keys[ keyCode ]; + } + else + { + auto keyDefinitions = EnumMembers!Inputs; + foreach(immutable value; keyDefinitions) + { + if(keyCode == cast(size_t)value) + { + logDebug("You just pressed an unrecorded key: ", cast(Inputs)keyCode); + keys[ keyCode ] = T(); + return keys[ keyCode ]; + } + } + + return T(); + } + } T opIndexAssign( T newValue, size_t keyCode ) { - if( keyCode < totalSize ) - keys[ keyCode ] = newValue; + //if( keyCode < totalSize ) + keys[ keyCode ] = newValue; return newValue; } - Tuple!( InputEnum, T )[] opBinary( string Op : "-" )( const ref typeof(this) other ) + Tuple!( InputEnum, T )[] opBinary( string Op : "-" )( ref typeof(this) other ) { Tuple!( InputEnum, T )[] differences; From 52996972a30a696abebd80162f7c94750b231aec Mon Sep 17 00:00:00 2001 From: Berulacks Date: Tue, 23 Sep 2014 04:38:15 -0400 Subject: [PATCH 070/141] Cleaned up unnecessary code. This fixes #207 --- source/dash/utility/input.d | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index 3561d3be..97965271 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -496,9 +496,7 @@ public: */ void setButtonState( Buttons buttonCode, ButtonStorageType newState ) { - logDebug("Setting buttonstate for buttoncode ", cast(size_t) buttonCode); - buttonStaging[ cast(size_t) buttonCode ] = newState; - //logDebug("Kk, buttonStaging[", buttonCode, "] is now = ", buttonStaging[ buttonCode ]); + buttonStaging[ buttonCode ] = newState; } private: @@ -593,10 +591,6 @@ public: ref typeof(this) opAssign( const ref typeof(this) other ) { - /*for( size_t ii = 0; ii < other.keys.length; ++ii ) - { - keys[ ii ] = other.keys[ ii ]; - }*/ foreach(size_t index, T value; other.keys) { keys[index] = value; @@ -607,31 +601,19 @@ public: T opIndex( size_t keyCode ) { - if(keyCode in keys) - { - return keys[ keyCode ]; - } - else - { - auto keyDefinitions = EnumMembers!Inputs; - foreach(immutable value; keyDefinitions) - { - if(keyCode == cast(size_t)value) - { - logDebug("You just pressed an unrecorded key: ", cast(Inputs)keyCode); - keys[ keyCode ] = T(); - return keys[ keyCode ]; - } - } - - return T(); - } + + //If the key being pressed doesn't have + //an entry in keys, add it, and set it + //to the default value + if(!(keyCode in keys)) + keys[ keyCode ] = T(); + + return keys[ keyCode ]; } T opIndexAssign( T newValue, size_t keyCode ) { - //if( keyCode < totalSize ) keys[ keyCode ] = newValue; return newValue; From d30c7f9e6a752903532efa8bed634714957b0cc5 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Wed, 24 Sep 2014 16:31:42 -0400 Subject: [PATCH 071/141] Optimized binding of multiple matrices to shaders --- source/dash/graphics/shaders/shaders.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/dash/graphics/shaders/shaders.d b/source/dash/graphics/shaders/shaders.d index 395be929..48f5e53f 100644 --- a/source/dash/graphics/shaders/shaders.d +++ b/source/dash/graphics/shaders/shaders.d @@ -8,7 +8,7 @@ import dash.graphics.shaders.glsl; import derelict.opengl3.gl3; import gl3n.linalg; -import std.string, std.traits, std.algorithm; +import std.string, std.traits, std.algorithm, std.array; /* * String constants for our shader uniforms @@ -286,7 +286,7 @@ public: */ final void bindUniformMatrix4fvArray( uint uniform, mat4[] matrices ) { - float[] matptr; + auto matptr = appender!(float[]); foreach( matrix; matrices ) { for( int i = 0; i < 16; i++ ) @@ -294,7 +294,7 @@ public: matptr ~= matrix.value_ptr()[i]; } } - glUniformMatrix4fv( uniform, cast(int)matrices.length, true, matptr.ptr ); + glUniformMatrix4fv( uniform, cast(int)matrices.length, true, matptr.data.ptr ); } /** From 5b47ea089f77cc0ab302acdd6166e7e85bb8c5d5 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Wed, 24 Sep 2014 16:55:47 -0400 Subject: [PATCH 072/141] Cleaned up resources.d --- source/dash/utility/resources.d | 101 ++++++-------------------------- 1 file changed, 17 insertions(+), 84 deletions(-) diff --git a/source/dash/utility/resources.d b/source/dash/utility/resources.d index 1ca27f61..b1bd3695 100644 --- a/source/dash/utility/resources.d +++ b/source/dash/utility/resources.d @@ -4,7 +4,7 @@ module dash.utility.resources; import dash.utility; -import std.file, std.path, std.stdio, std.array, std.datetime; +import std.file, std.path, std.stdio, std.array, std.algorithm, std.datetime; /** * Paths to the different resource files. @@ -23,7 +23,6 @@ enum Resources : string ConfigDir = Home ~ "/Config", ConfigFile = ConfigDir ~ "/Config", InputBindings = ConfigDir ~ "/Input", - CompactContentFile = Home ~ "/Content.yml", } /** @@ -41,20 +40,17 @@ Resource[] scanDirectory( string path, string pattern = "" ) } // Start array - Resource[] files; - - auto dirs = pattern.length + return ( pattern.length ? safePath.dirEntries( pattern, SpanMode.breadth ).array - : safePath.dirEntries( SpanMode.breadth ).array; - - // Find files - foreach( entry; dirs ) - if( entry.isFile ) - files ~= Resource( entry.name ); - - return files; + : safePath.dirEntries( SpanMode.breadth ).array ) + .filter!( entry => entry.isFile ) + .map!( entry => Resource( entry ) ) + .array(); } +/** + * Represents a resource on the file system. + */ struct Resource { public: @@ -74,8 +70,6 @@ public: _fullPath = filePath.absolutePath().buildNormalizedPath(); else throw new Exception( "invalid file name." ); - - markRead(); } /** @@ -88,62 +82,19 @@ public: } /// The full path to the file. - @property string fullPath() { return _fullPath; } + @property string fullPath() { return _fullPath; } /// The relative path from the executable to the file. - @property string relativePath() - { - if( invalid ) - return ""; - - if( !_relativePath ) - _relativePath = _fullPath.relativePath(); - - return _relativePath; - } + @property string relativePath() { return _fullPath.relativePath(); } /// The name of the file with its extension. - @property string fileName() - { - if( invalid ) - return ""; - - if( !_fileName ) - _fileName = _fullPath.baseName(); - - return _fileName; - } + @property string fileName() { return _fullPath.baseName(); } /// The name of the file without its extension. - @property string baseFileName() - { - if( invalid ) - return ""; - - if( !_baseFileName ) - _baseFileName = fileName.stripExtension(); - - return _baseFileName; - } + @property string baseFileName() { return fileName().stripExtension(); } /// The path to the directory containing the file. - @property string directory() - { - if( invalid ) - return ""; - - if( !_directory ) - _directory = _fullPath.dirName(); - - return _directory; - } + @property string directory() { return _fullPath.dirName(); } /// The extensino of the file. - @property string extension() - { - if( invalid ) - return ""; - - if( !_extension ) - _extension = _fullPath.extension( ); - - return _extension; - } + @property string extension() { return _fullPath.extension(); } + /// Checks if the file still exists. + bool exists() @property { return invalid || fullPath.isFile(); } /// Converts to a std.stdio.File File* getFile( string mode = "r" ) { @@ -197,26 +148,8 @@ public: return fullPath.timeLastModified > timeRead; } - /** - * Checks if the file still exists. - * - * Returns: True if file exists. - */ - bool exists() - { - if( invalid ) - return true; - - return fullPath.isFile(); - } - private: string _fullPath; - string _relativePath; - string _fileName; - string _baseFileName; - string _directory; - string _extension; bool invalid; std.stdio.File* file; SysTime timeRead; From f33659fe6df041e34494e5bf9352d95c59c9c5b8 Mon Sep 17 00:00:00 2001 From: Sean Brennan Date: Wed, 24 Sep 2014 21:48:09 -0400 Subject: [PATCH 073/141] Fixed some tabbing issues, and removed an unneeded overload --- source/dash/components/audio.d | 208 ++-- source/dash/core/dgame.d | 6 +- source/dash/core/gameobject.d | 12 +- source/dash/core/scene.d | 2 +- source/dash/utility/resources.d | 2 +- source/dash/utility/soloud.d | 1918 +++++++++++++++---------------- 6 files changed, 1075 insertions(+), 1073 deletions(-) diff --git a/source/dash/components/audio.d b/source/dash/components/audio.d index 67fe757f..e70e295b 100644 --- a/source/dash/components/audio.d +++ b/source/dash/components/audio.d @@ -19,21 +19,21 @@ class Listener : Component private: public: - /** - * Create a listener object - */ - this() - { - // Constructor code - } - - override void update() - { - Audio.soloud.update3dAudio(); - Audio.soloud.set3dListenerAt(owner.transform.position.x, - owner.transform.position.y, - owner.transform.position.z); - } + /** + * Create a listener object + */ + this() + { + // Constructor code + } + + override void update() + { + Audio.soloud.update3dAudio(); + Audio.soloud.set3dListenerAt(owner.transform.position.x, + owner.transform.position.y, + owner.transform.position.z); + } } /** @@ -43,75 +43,77 @@ public: class Emitter : Component { private: - Modplug toPlay; - uint[] handles; + Modplug toPlay; + uint[] handles; public: - /** - * Create an emmiter object - */ - this() - { - // Constructor Code - } - - override void initialize() { - super.initialize; - toPlay = Modplug.create(); - } - - // call: - // emmiter.play( filename ); - void play( string soundName ) - { - // Load in the sound - toPlay.load( Audio.sounds[soundName].toStringz() ); - - // play the sound from the location of the parent object - Audio.soloud.play3d(toPlay, - owner.transform.position.x, - owner.transform.position.y, - owner.transform.position.z); - } - - void playFollow( string soundName ) { - // Load in the sound - toPlay.load( Audio.sounds[soundName].toStringz() ); - - // play the sound from the location of the parent object - // and set the sound to move with the emitter - handles ~= Audio.soloud.play3d( toPlay, - owner.transform.position.x, - owner.transform.position.y, - owner.transform.position.z ); - - } - - override void update() - { - foreach_reverse( i, handle; handles ) - { - if( !Audio.soloud.isValidVoiceHandle( handle ) ) - { - auto end = handles[i+1..$]; - handles = handles[0..i]; - handles ~= end; - } else { - Audio.soloud.set3dSourcePosition( handle, - owner.transform.position.x, - owner.transform.position.y, - owner.transform.position.z ); - } - } - } - - - /** - * Plays a sound that will follow the emitter for however long you set the length to be. - */ - void playFollow( string soundName, float soundLength ) - { - - } + /** + * Create an emmiter object + */ + this() + { + // Constructor Code + } + + override void initialize() { + super.initialize; + toPlay = Modplug.create(); + } + + // call: + // emmiter.play( filename ); + void play( string soundName ) + { + // Load in the sound + toPlay.load( Audio.sounds[soundName].toStringz() ); + + // play the sound from the location of the parent object + Audio.soloud.play3d(toPlay, + owner.transform.position.x, + owner.transform.position.y, + owner.transform.position.z); + } + + + /** + * Plays a sound that will follow the emitter for however long you set the length to be. + */ + void playFollow( string soundName ) { + // Load in the sound + toPlay.load( Audio.sounds[soundName].toStringz() ); + + // play the sound from the location of the parent object + // and set the sound to move with the emitter + handles ~= Audio.soloud.play3d( toPlay, + owner.transform.position.x, + owner.transform.position.y, + owner.transform.position.z ); + + } + + override void update() + { + foreach_reverse( i, handle; handles ) + { + if( !Audio.soloud.isValidVoiceHandle( handle ) ) + { + auto end = handles[i+1..$]; + handles = handles[0..i]; + handles ~= end; + } else { + Audio.soloud.set3dSourcePosition( handle, + owner.transform.position.x, + owner.transform.position.y, + owner.transform.position.z ); + } + } + } + + + + void playFollow( string soundName, float soundLength ) + { + + } } /** @@ -119,7 +121,7 @@ public: * implement sound struct struct Sound { - Wav soundfile; + Wav soundfile; } */ @@ -127,25 +129,25 @@ final abstract class Audio { static: //private: - Soloud soloud; + Soloud soloud; public: - string[string] sounds; - - void initialize() - { - soloud = Soloud.create(); - soloud.init(); - - foreach( file; scanDirectory( Resources.Audio ) ) - { - sounds[file.baseFileName] = file.relativePath; - } - } - - void shutdown() - { - soloud.deinit(); - soloud.destroy(); - } + string[string] sounds; + + void initialize() + { + soloud = Soloud.create(); + soloud.init(); + + foreach( file; scanDirectory( Resources.Audio ) ) + { + sounds[file.baseFileName] = file.relativePath; + } + } + + void shutdown() + { + soloud.deinit(); + soloud.destroy(); + } } \ No newline at end of file diff --git a/source/dash/core/dgame.d b/source/dash/core/dgame.d index c46eae25..6ea0b452 100644 --- a/source/dash/core/dgame.d +++ b/source/dash/core/dgame.d @@ -30,7 +30,7 @@ struct GameStateFlags bool updateScene; bool updateUI; bool updateTasks; - bool autoRefresh; + bool autoRefresh; //bool updatePhysics; /** @@ -209,7 +209,7 @@ private: bench!( { Input.initialize(); } )( "Input init" ); bench!( { Graphics.initialize(); } )( "Graphics init" ); bench!( { Assets.initialize(); } )( "Assets init" ); - bench!( { Audio.initialize(); } )( "Audio init" ); + bench!( { Audio.initialize(); } )( "Audio init" ); bench!( { Prefabs.initialize(); } )( "Prefabs init" ); bench!( { UserInterface.initializeAwesomium(); } )( "UI init" ); bench!( { editor.initialize( this ); } )( "Editor init" ); @@ -229,7 +229,7 @@ private: UserInterface.shutdownAwesomium(); Assets.shutdown(); Graphics.shutdown(); - Audio.shutdown(); + Audio.shutdown(); } /** diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 8fa7dcf5..297b9d6d 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -93,8 +93,8 @@ public: mixin( componentProperty!Animation ); /// The camera attached to this object. mixin( componentProperty!Camera ); - /// The emitter attached to this object. - mixin( componentProperty!Emitter ); + /// The emitter attached to this object. + mixin( componentProperty!Emitter ); /// The object that this object belongs to. mixin( Property!_parent ); /// All of the objects which list this as parent @@ -244,8 +244,8 @@ public: */ final void draw() { - foreach( component; componentList ) - component.draw(); + foreach( component; componentList ) + component.draw(); foreach( obj; children ) obj.draw(); @@ -256,8 +256,8 @@ public: */ final void shutdown() { - foreach( component; componentList ) - component.shutdown(); + foreach( component; componentList ) + component.shutdown(); foreach( obj; children ) obj.shutdown(); diff --git a/source/dash/core/scene.d b/source/dash/core/scene.d index 3fa94bd4..3d39c625 100644 --- a/source/dash/core/scene.d +++ b/source/dash/core/scene.d @@ -25,7 +25,7 @@ package: public: /// The camera to render with. Camera camera; - Listener listener; + Listener listener; /// The root object of the scene. mixin( Getter!_root ); diff --git a/source/dash/utility/resources.d b/source/dash/utility/resources.d index d8d281b0..e0f77e46 100644 --- a/source/dash/utility/resources.d +++ b/source/dash/utility/resources.d @@ -15,7 +15,7 @@ enum Resources : string Materials = Home ~ "/Materials", Meshes = Home ~ "/Meshes", Textures = Home ~ "/Textures", - Audio = Home ~ "/Audio", + Audio = Home ~ "/Audio", Scripts = Home ~ "/Scripts", Prefabs = Home ~ "/Prefabs", Objects = Home ~ "/Objects", diff --git a/source/dash/utility/soloud.d b/source/dash/utility/soloud.d index 657bec3e..c2916ba6 100644 --- a/source/dash/utility/soloud.d +++ b/source/dash/utility/soloud.d @@ -16,423 +16,423 @@ private struct SoloudObject public struct Soloud { pure @safe nothrow @nogc: - public enum WASAPI = 6; - public enum AUTO = 0; - public enum CLIP_ROUNDOFF = 1; - public enum SDL2 = 2; - public enum ENABLE_VISUALIZATION = 2; - public enum SDL = 1; - public enum PORTAUDIO = 3; - public enum OPENAL = 8; - public enum BACKEND_MAX = 9; - public enum XAUDIO2 = 5; - public enum WINMM = 4; - public enum OSS = 7; - - public SoloudObject soloudObject; - alias soloudObject this; - - public static create() - { - return Soloud(SoloudObject(Soloud_create())); - } - - public void destroy() - { - Soloud_destroy(objhandle); - } - - public int init(uint aFlags = CLIP_ROUNDOFF, uint aBackend = AUTO, uint aSamplerate = AUTO, uint aBufferSize = AUTO) - { - return Soloud_initEx(objhandle, aFlags, aBackend, aSamplerate, aBufferSize); - } - - public void deinit() - { - Soloud_deinit(objhandle); - } - - public uint getVersion() - { - return Soloud_getVersion(objhandle); - } - - public const(char)* getErrorString(int aErrorCode) - { - return Soloud_getErrorString(objhandle, aErrorCode); - } - - public uint play(SoloudObject aSound, float aVolume = 1.0f, float aPan = 0.0f, int aPaused = 0, uint aBus = 0) - { - return Soloud_playEx(objhandle, aSound.objhandle, aVolume, aPan, aPaused, aBus); - } - - public uint playClocked(double aSoundTime, SoloudObject aSound, float aVolume = 1.0f, float aPan = 0.0f, uint aBus = 0) - { - return Soloud_playClockedEx(objhandle, aSoundTime, aSound.objhandle, aVolume, aPan, aBus); - } - - public uint play3d(SoloudObject aSound, float aPosX, float aPosY, float aPosZ, float aVelX = 0.0f, float aVelY = 0.0f, float aVelZ = 0.0f, float aVolume = 1.0f, int aPaused = 0, uint aBus = 0) - { - return Soloud_play3dEx(objhandle, aSound.objhandle, aPosX, aPosY, aPosZ, aVelX, aVelY, aVelZ, aVolume, aPaused, aBus); - } - - public uint play3dClocked(double aSoundTime, SoloudObject aSound, float aPosX, float aPosY, float aPosZ, float aVelX = 0.0f, float aVelY = 0.0f, float aVelZ = 0.0f, float aVolume = 1.0f, uint aBus = 0) - { - return Soloud_play3dClockedEx(objhandle, aSoundTime, aSound.objhandle, aPosX, aPosY, aPosZ, aVelX, aVelY, aVelZ, aVolume, aBus); - } - - public void seek(uint aVoiceHandle, double aSeconds) - { - Soloud_seek(objhandle, aVoiceHandle, aSeconds); - } - - public void stop(uint aVoiceHandle) - { - Soloud_stop(objhandle, aVoiceHandle); - } - - public void stopAll() - { - Soloud_stopAll(objhandle); - } - - public void stopAudioSource(SoloudObject aSound) - { - Soloud_stopAudioSource(objhandle, aSound.objhandle); - } - - public void setFilterParameter(uint aVoiceHandle, uint aFilterId, uint aAttributeId, float aValue) - { - Soloud_setFilterParameter(objhandle, aVoiceHandle, aFilterId, aAttributeId, aValue); - } - - public float getFilterParameter(uint aVoiceHandle, uint aFilterId, uint aAttributeId) - { - return Soloud_getFilterParameter(objhandle, aVoiceHandle, aFilterId, aAttributeId); - } - - public void fadeFilterParameter(uint aVoiceHandle, uint aFilterId, uint aAttributeId, float aTo, double aTime) - { - Soloud_fadeFilterParameter(objhandle, aVoiceHandle, aFilterId, aAttributeId, aTo, aTime); - } - - public void oscillateFilterParameter(uint aVoiceHandle, uint aFilterId, uint aAttributeId, float aFrom, float aTo, double aTime) - { - Soloud_oscillateFilterParameter(objhandle, aVoiceHandle, aFilterId, aAttributeId, aFrom, aTo, aTime); - } - - public double getStreamTime(uint aVoiceHandle) - { - return Soloud_getStreamTime(objhandle, aVoiceHandle); - } - - public int getPause(uint aVoiceHandle) - { - return Soloud_getPause(objhandle, aVoiceHandle); - } - - public float getVolume(uint aVoiceHandle) - { - return Soloud_getVolume(objhandle, aVoiceHandle); - } - - public float getPan(uint aVoiceHandle) - { - return Soloud_getPan(objhandle, aVoiceHandle); - } - - public float getSamplerate(uint aVoiceHandle) - { - return Soloud_getSamplerate(objhandle, aVoiceHandle); - } - - public int getProtectVoice(uint aVoiceHandle) - { - return Soloud_getProtectVoice(objhandle, aVoiceHandle); - } - - public uint getActiveVoiceCount() - { - return Soloud_getActiveVoiceCount(objhandle); - } - - public int isValidVoiceHandle(uint aVoiceHandle) - { - return Soloud_isValidVoiceHandle(objhandle, aVoiceHandle); - } - - public float getRelativePlaySpeed(uint aVoiceHandle) - { - return Soloud_getRelativePlaySpeed(objhandle, aVoiceHandle); - } - - public float getPostClipScaler() - { - return Soloud_getPostClipScaler(objhandle); - } - - public float getGlobalVolume() - { - return Soloud_getGlobalVolume(objhandle); - } - - public void setGlobalVolume(float aVolume) - { - Soloud_setGlobalVolume(objhandle, aVolume); - } - - public void setPostClipScaler(float aScaler) - { - Soloud_setPostClipScaler(objhandle, aScaler); - } - - public void setPause(uint aVoiceHandle, int aPause) - { - Soloud_setPause(objhandle, aVoiceHandle, aPause); - } - - public void setPauseAll(int aPause) - { - Soloud_setPauseAll(objhandle, aPause); - } - - public void setRelativePlaySpeed(uint aVoiceHandle, float aSpeed) - { - Soloud_setRelativePlaySpeed(objhandle, aVoiceHandle, aSpeed); - } - - public void setProtectVoice(uint aVoiceHandle, int aProtect) - { - Soloud_setProtectVoice(objhandle, aVoiceHandle, aProtect); - } - - public void setSamplerate(uint aVoiceHandle, float aSamplerate) - { - Soloud_setSamplerate(objhandle, aVoiceHandle, aSamplerate); - } - - public void setPan(uint aVoiceHandle, float aPan) - { - Soloud_setPan(objhandle, aVoiceHandle, aPan); - } - - public void setPanAbsolute(uint aVoiceHandle, float aLVolume, float aRVolume) - { - Soloud_setPanAbsolute(objhandle, aVoiceHandle, aLVolume, aRVolume); - } - - public void setVolume(uint aVoiceHandle, float aVolume) - { - Soloud_setVolume(objhandle, aVoiceHandle, aVolume); - } - - public void setDelaySamples(uint aVoiceHandle, uint aSamples) - { - Soloud_setDelaySamples(objhandle, aVoiceHandle, aSamples); - } - - public void fadeVolume(uint aVoiceHandle, float aTo, double aTime) - { - Soloud_fadeVolume(objhandle, aVoiceHandle, aTo, aTime); - } - - public void fadePan(uint aVoiceHandle, float aTo, double aTime) - { - Soloud_fadePan(objhandle, aVoiceHandle, aTo, aTime); - } - - public void fadeRelativePlaySpeed(uint aVoiceHandle, float aTo, double aTime) - { - Soloud_fadeRelativePlaySpeed(objhandle, aVoiceHandle, aTo, aTime); - } - - public void fadeGlobalVolume(float aTo, double aTime) - { - Soloud_fadeGlobalVolume(objhandle, aTo, aTime); - } - - public void schedulePause(uint aVoiceHandle, double aTime) - { - Soloud_schedulePause(objhandle, aVoiceHandle, aTime); - } - - public void scheduleStop(uint aVoiceHandle, double aTime) - { - Soloud_scheduleStop(objhandle, aVoiceHandle, aTime); - } - - public void oscillateVolume(uint aVoiceHandle, float aFrom, float aTo, double aTime) - { - Soloud_oscillateVolume(objhandle, aVoiceHandle, aFrom, aTo, aTime); - } - - public void oscillatePan(uint aVoiceHandle, float aFrom, float aTo, double aTime) - { - Soloud_oscillatePan(objhandle, aVoiceHandle, aFrom, aTo, aTime); - } - - public void oscillateRelativePlaySpeed(uint aVoiceHandle, float aFrom, float aTo, double aTime) - { - Soloud_oscillateRelativePlaySpeed(objhandle, aVoiceHandle, aFrom, aTo, aTime); - } - - public void oscillateGlobalVolume(float aFrom, float aTo, double aTime) - { - Soloud_oscillateGlobalVolume(objhandle, aFrom, aTo, aTime); - } - - public void setGlobalFilter(uint aFilterId, SoloudObject aFilter) - { - Soloud_setGlobalFilter(objhandle, aFilterId, aFilter.objhandle); - } - - public void setVisualizationEnable(int aEnable) - { - Soloud_setVisualizationEnable(objhandle, aEnable); - } - - public float[] calcFFT() - { - return Soloud_calcFFT(objhandle); - } - - public float[] getWave() - { - return Soloud_getWave(objhandle); - } - - public uint getLoopCount(uint aVoiceHandle) - { - return Soloud_getLoopCount(objhandle, aVoiceHandle); - } - - public uint createVoiceGroup() - { - return Soloud_createVoiceGroup(objhandle); - } - - public int destroyVoiceGroup(uint aVoiceGroupHandle) - { - return Soloud_destroyVoiceGroup(objhandle, aVoiceGroupHandle); - } - - public int addVoiceToGroup(uint aVoiceGroupHandle, uint aVoiceHandle) - { - return Soloud_addVoiceToGroup(objhandle, aVoiceGroupHandle, aVoiceHandle); - } - - public int isVoiceGroup(uint aVoiceGroupHandle) - { - return Soloud_isVoiceGroup(objhandle, aVoiceGroupHandle); - } - - public int isVoiceGroupEmpty(uint aVoiceGroupHandle) - { - return Soloud_isVoiceGroupEmpty(objhandle, aVoiceGroupHandle); - } - - public void update3dAudio() - { - Soloud_update3dAudio(objhandle); - } - - public int set3dSoundSpeed(float aSpeed) - { - return Soloud_set3dSoundSpeed(objhandle, aSpeed); - } - - public float get3dSoundSpeed() - { - return Soloud_get3dSoundSpeed(objhandle); - } - - public void set3dListenerParameters(float aPosX, float aPosY, float aPosZ, float aAtX, float aAtY, float aAtZ, float aUpX, float aUpY, float aUpZ, float aVelocityX = 0.0f, float aVelocityY = 0.0f, float aVelocityZ = 0.0f) - { - Soloud_set3dListenerParametersEx(objhandle, aPosX, aPosY, aPosZ, aAtX, aAtY, aAtZ, aUpX, aUpY, aUpZ, aVelocityX, aVelocityY, aVelocityZ); - } - - public void set3dListenerPosition(float aPosX, float aPosY, float aPosZ) - { - Soloud_set3dListenerPosition(objhandle, aPosX, aPosY, aPosZ); - } - - public void set3dListenerAt(float aAtX, float aAtY, float aAtZ) - { - Soloud_set3dListenerAt(objhandle, aAtX, aAtY, aAtZ); - } - - public void set3dListenerUp(float aUpX, float aUpY, float aUpZ) - { - Soloud_set3dListenerUp(objhandle, aUpX, aUpY, aUpZ); - } - - public void set3dListenerVelocity(float aVelocityX, float aVelocityY, float aVelocityZ) - { - Soloud_set3dListenerVelocity(objhandle, aVelocityX, aVelocityY, aVelocityZ); - } - - public void set3dSourceParameters(uint aVoiceHandle, float aPosX, float aPosY, float aPosZ, float aVelocityX = 0.0f, float aVelocityY = 0.0f, float aVelocityZ = 0.0f) - { - Soloud_set3dSourceParametersEx(objhandle, aVoiceHandle, aPosX, aPosY, aPosZ, aVelocityX, aVelocityY, aVelocityZ); - } - - public void set3dSourcePosition(uint aVoiceHandle, float aPosX, float aPosY, float aPosZ) - { - Soloud_set3dSourcePosition(objhandle, aVoiceHandle, aPosX, aPosY, aPosZ); - } - - public void set3dSourceVelocity(uint aVoiceHandle, float aVelocityX, float aVelocityY, float aVelocityZ) - { - Soloud_set3dSourceVelocity(objhandle, aVoiceHandle, aVelocityX, aVelocityY, aVelocityZ); - } - - public void set3dSourceMinMaxDistance(uint aVoiceHandle, float aMinDistance, float aMaxDistance) - { - Soloud_set3dSourceMinMaxDistance(objhandle, aVoiceHandle, aMinDistance, aMaxDistance); - } - - public void set3dSourceAttenuation(uint aVoiceHandle, uint aAttenuationModel, float aAttenuationRolloffFactor) - { - Soloud_set3dSourceAttenuation(objhandle, aVoiceHandle, aAttenuationModel, aAttenuationRolloffFactor); - } - - public void set3dSourceDopplerFactor(uint aVoiceHandle, float aDopplerFactor) - { - Soloud_set3dSourceDopplerFactor(objhandle, aVoiceHandle, aDopplerFactor); - } + public enum WASAPI = 6; + public enum AUTO = 0; + public enum CLIP_ROUNDOFF = 1; + public enum SDL2 = 2; + public enum ENABLE_VISUALIZATION = 2; + public enum SDL = 1; + public enum PORTAUDIO = 3; + public enum OPENAL = 8; + public enum BACKEND_MAX = 9; + public enum XAUDIO2 = 5; + public enum WINMM = 4; + public enum OSS = 7; + + public SoloudObject soloudObject; + alias soloudObject this; + + public static create() + { + return Soloud(SoloudObject(Soloud_create())); + } + + public void destroy() + { + Soloud_destroy(objhandle); + } + + public int init(uint aFlags = CLIP_ROUNDOFF, uint aBackend = AUTO, uint aSamplerate = AUTO, uint aBufferSize = AUTO) + { + return Soloud_initEx(objhandle, aFlags, aBackend, aSamplerate, aBufferSize); + } + + public void deinit() + { + Soloud_deinit(objhandle); + } + + public uint getVersion() + { + return Soloud_getVersion(objhandle); + } + + public const(char)* getErrorString(int aErrorCode) + { + return Soloud_getErrorString(objhandle, aErrorCode); + } + + public uint play(SoloudObject aSound, float aVolume = 1.0f, float aPan = 0.0f, int aPaused = 0, uint aBus = 0) + { + return Soloud_playEx(objhandle, aSound.objhandle, aVolume, aPan, aPaused, aBus); + } + + public uint playClocked(double aSoundTime, SoloudObject aSound, float aVolume = 1.0f, float aPan = 0.0f, uint aBus = 0) + { + return Soloud_playClockedEx(objhandle, aSoundTime, aSound.objhandle, aVolume, aPan, aBus); + } + + public uint play3d(SoloudObject aSound, float aPosX, float aPosY, float aPosZ, float aVelX = 0.0f, float aVelY = 0.0f, float aVelZ = 0.0f, float aVolume = 1.0f, int aPaused = 0, uint aBus = 0) + { + return Soloud_play3dEx(objhandle, aSound.objhandle, aPosX, aPosY, aPosZ, aVelX, aVelY, aVelZ, aVolume, aPaused, aBus); + } + + public uint play3dClocked(double aSoundTime, SoloudObject aSound, float aPosX, float aPosY, float aPosZ, float aVelX = 0.0f, float aVelY = 0.0f, float aVelZ = 0.0f, float aVolume = 1.0f, uint aBus = 0) + { + return Soloud_play3dClockedEx(objhandle, aSoundTime, aSound.objhandle, aPosX, aPosY, aPosZ, aVelX, aVelY, aVelZ, aVolume, aBus); + } + + public void seek(uint aVoiceHandle, double aSeconds) + { + Soloud_seek(objhandle, aVoiceHandle, aSeconds); + } + + public void stop(uint aVoiceHandle) + { + Soloud_stop(objhandle, aVoiceHandle); + } + + public void stopAll() + { + Soloud_stopAll(objhandle); + } + + public void stopAudioSource(SoloudObject aSound) + { + Soloud_stopAudioSource(objhandle, aSound.objhandle); + } + + public void setFilterParameter(uint aVoiceHandle, uint aFilterId, uint aAttributeId, float aValue) + { + Soloud_setFilterParameter(objhandle, aVoiceHandle, aFilterId, aAttributeId, aValue); + } + + public float getFilterParameter(uint aVoiceHandle, uint aFilterId, uint aAttributeId) + { + return Soloud_getFilterParameter(objhandle, aVoiceHandle, aFilterId, aAttributeId); + } + + public void fadeFilterParameter(uint aVoiceHandle, uint aFilterId, uint aAttributeId, float aTo, double aTime) + { + Soloud_fadeFilterParameter(objhandle, aVoiceHandle, aFilterId, aAttributeId, aTo, aTime); + } + + public void oscillateFilterParameter(uint aVoiceHandle, uint aFilterId, uint aAttributeId, float aFrom, float aTo, double aTime) + { + Soloud_oscillateFilterParameter(objhandle, aVoiceHandle, aFilterId, aAttributeId, aFrom, aTo, aTime); + } + + public double getStreamTime(uint aVoiceHandle) + { + return Soloud_getStreamTime(objhandle, aVoiceHandle); + } + + public int getPause(uint aVoiceHandle) + { + return Soloud_getPause(objhandle, aVoiceHandle); + } + + public float getVolume(uint aVoiceHandle) + { + return Soloud_getVolume(objhandle, aVoiceHandle); + } + + public float getPan(uint aVoiceHandle) + { + return Soloud_getPan(objhandle, aVoiceHandle); + } + + public float getSamplerate(uint aVoiceHandle) + { + return Soloud_getSamplerate(objhandle, aVoiceHandle); + } + + public int getProtectVoice(uint aVoiceHandle) + { + return Soloud_getProtectVoice(objhandle, aVoiceHandle); + } + + public uint getActiveVoiceCount() + { + return Soloud_getActiveVoiceCount(objhandle); + } + + public int isValidVoiceHandle(uint aVoiceHandle) + { + return Soloud_isValidVoiceHandle(objhandle, aVoiceHandle); + } + + public float getRelativePlaySpeed(uint aVoiceHandle) + { + return Soloud_getRelativePlaySpeed(objhandle, aVoiceHandle); + } + + public float getPostClipScaler() + { + return Soloud_getPostClipScaler(objhandle); + } + + public float getGlobalVolume() + { + return Soloud_getGlobalVolume(objhandle); + } + + public void setGlobalVolume(float aVolume) + { + Soloud_setGlobalVolume(objhandle, aVolume); + } + + public void setPostClipScaler(float aScaler) + { + Soloud_setPostClipScaler(objhandle, aScaler); + } + + public void setPause(uint aVoiceHandle, int aPause) + { + Soloud_setPause(objhandle, aVoiceHandle, aPause); + } + + public void setPauseAll(int aPause) + { + Soloud_setPauseAll(objhandle, aPause); + } + + public void setRelativePlaySpeed(uint aVoiceHandle, float aSpeed) + { + Soloud_setRelativePlaySpeed(objhandle, aVoiceHandle, aSpeed); + } + + public void setProtectVoice(uint aVoiceHandle, int aProtect) + { + Soloud_setProtectVoice(objhandle, aVoiceHandle, aProtect); + } + + public void setSamplerate(uint aVoiceHandle, float aSamplerate) + { + Soloud_setSamplerate(objhandle, aVoiceHandle, aSamplerate); + } + + public void setPan(uint aVoiceHandle, float aPan) + { + Soloud_setPan(objhandle, aVoiceHandle, aPan); + } + + public void setPanAbsolute(uint aVoiceHandle, float aLVolume, float aRVolume) + { + Soloud_setPanAbsolute(objhandle, aVoiceHandle, aLVolume, aRVolume); + } + + public void setVolume(uint aVoiceHandle, float aVolume) + { + Soloud_setVolume(objhandle, aVoiceHandle, aVolume); + } + + public void setDelaySamples(uint aVoiceHandle, uint aSamples) + { + Soloud_setDelaySamples(objhandle, aVoiceHandle, aSamples); + } + + public void fadeVolume(uint aVoiceHandle, float aTo, double aTime) + { + Soloud_fadeVolume(objhandle, aVoiceHandle, aTo, aTime); + } + + public void fadePan(uint aVoiceHandle, float aTo, double aTime) + { + Soloud_fadePan(objhandle, aVoiceHandle, aTo, aTime); + } + + public void fadeRelativePlaySpeed(uint aVoiceHandle, float aTo, double aTime) + { + Soloud_fadeRelativePlaySpeed(objhandle, aVoiceHandle, aTo, aTime); + } + + public void fadeGlobalVolume(float aTo, double aTime) + { + Soloud_fadeGlobalVolume(objhandle, aTo, aTime); + } + + public void schedulePause(uint aVoiceHandle, double aTime) + { + Soloud_schedulePause(objhandle, aVoiceHandle, aTime); + } + + public void scheduleStop(uint aVoiceHandle, double aTime) + { + Soloud_scheduleStop(objhandle, aVoiceHandle, aTime); + } + + public void oscillateVolume(uint aVoiceHandle, float aFrom, float aTo, double aTime) + { + Soloud_oscillateVolume(objhandle, aVoiceHandle, aFrom, aTo, aTime); + } + + public void oscillatePan(uint aVoiceHandle, float aFrom, float aTo, double aTime) + { + Soloud_oscillatePan(objhandle, aVoiceHandle, aFrom, aTo, aTime); + } + + public void oscillateRelativePlaySpeed(uint aVoiceHandle, float aFrom, float aTo, double aTime) + { + Soloud_oscillateRelativePlaySpeed(objhandle, aVoiceHandle, aFrom, aTo, aTime); + } + + public void oscillateGlobalVolume(float aFrom, float aTo, double aTime) + { + Soloud_oscillateGlobalVolume(objhandle, aFrom, aTo, aTime); + } + + public void setGlobalFilter(uint aFilterId, SoloudObject aFilter) + { + Soloud_setGlobalFilter(objhandle, aFilterId, aFilter.objhandle); + } + + public void setVisualizationEnable(int aEnable) + { + Soloud_setVisualizationEnable(objhandle, aEnable); + } + + public float[] calcFFT() + { + return Soloud_calcFFT(objhandle); + } + + public float[] getWave() + { + return Soloud_getWave(objhandle); + } + + public uint getLoopCount(uint aVoiceHandle) + { + return Soloud_getLoopCount(objhandle, aVoiceHandle); + } + + public uint createVoiceGroup() + { + return Soloud_createVoiceGroup(objhandle); + } + + public int destroyVoiceGroup(uint aVoiceGroupHandle) + { + return Soloud_destroyVoiceGroup(objhandle, aVoiceGroupHandle); + } + + public int addVoiceToGroup(uint aVoiceGroupHandle, uint aVoiceHandle) + { + return Soloud_addVoiceToGroup(objhandle, aVoiceGroupHandle, aVoiceHandle); + } + + public int isVoiceGroup(uint aVoiceGroupHandle) + { + return Soloud_isVoiceGroup(objhandle, aVoiceGroupHandle); + } + + public int isVoiceGroupEmpty(uint aVoiceGroupHandle) + { + return Soloud_isVoiceGroupEmpty(objhandle, aVoiceGroupHandle); + } + + public void update3dAudio() + { + Soloud_update3dAudio(objhandle); + } + + public int set3dSoundSpeed(float aSpeed) + { + return Soloud_set3dSoundSpeed(objhandle, aSpeed); + } + + public float get3dSoundSpeed() + { + return Soloud_get3dSoundSpeed(objhandle); + } + + public void set3dListenerParameters(float aPosX, float aPosY, float aPosZ, float aAtX, float aAtY, float aAtZ, float aUpX, float aUpY, float aUpZ, float aVelocityX = 0.0f, float aVelocityY = 0.0f, float aVelocityZ = 0.0f) + { + Soloud_set3dListenerParametersEx(objhandle, aPosX, aPosY, aPosZ, aAtX, aAtY, aAtZ, aUpX, aUpY, aUpZ, aVelocityX, aVelocityY, aVelocityZ); + } + + public void set3dListenerPosition(float aPosX, float aPosY, float aPosZ) + { + Soloud_set3dListenerPosition(objhandle, aPosX, aPosY, aPosZ); + } + + public void set3dListenerAt(float aAtX, float aAtY, float aAtZ) + { + Soloud_set3dListenerAt(objhandle, aAtX, aAtY, aAtZ); + } + + public void set3dListenerUp(float aUpX, float aUpY, float aUpZ) + { + Soloud_set3dListenerUp(objhandle, aUpX, aUpY, aUpZ); + } + + public void set3dListenerVelocity(float aVelocityX, float aVelocityY, float aVelocityZ) + { + Soloud_set3dListenerVelocity(objhandle, aVelocityX, aVelocityY, aVelocityZ); + } + + public void set3dSourceParameters(uint aVoiceHandle, float aPosX, float aPosY, float aPosZ, float aVelocityX = 0.0f, float aVelocityY = 0.0f, float aVelocityZ = 0.0f) + { + Soloud_set3dSourceParametersEx(objhandle, aVoiceHandle, aPosX, aPosY, aPosZ, aVelocityX, aVelocityY, aVelocityZ); + } + + public void set3dSourcePosition(uint aVoiceHandle, float aPosX, float aPosY, float aPosZ) + { + Soloud_set3dSourcePosition(objhandle, aVoiceHandle, aPosX, aPosY, aPosZ); + } + + public void set3dSourceVelocity(uint aVoiceHandle, float aVelocityX, float aVelocityY, float aVelocityZ) + { + Soloud_set3dSourceVelocity(objhandle, aVoiceHandle, aVelocityX, aVelocityY, aVelocityZ); + } + + public void set3dSourceMinMaxDistance(uint aVoiceHandle, float aMinDistance, float aMaxDistance) + { + Soloud_set3dSourceMinMaxDistance(objhandle, aVoiceHandle, aMinDistance, aMaxDistance); + } + + public void set3dSourceAttenuation(uint aVoiceHandle, uint aAttenuationModel, float aAttenuationRolloffFactor) + { + Soloud_set3dSourceAttenuation(objhandle, aVoiceHandle, aAttenuationModel, aAttenuationRolloffFactor); + } + + public void set3dSourceDopplerFactor(uint aVoiceHandle, float aDopplerFactor) + { + Soloud_set3dSourceDopplerFactor(objhandle, aVoiceHandle, aDopplerFactor); + } } public struct BiquadResonantFilter { pure @safe nothrow @nogc: - public enum NONE = 0; - public enum HIGHPASS = 2; - public enum WET = 0; - public enum LOWPASS = 1; - public enum SAMPLERATE = 1; - public enum BANDPASS = 3; - public enum FREQUENCY = 2; - public enum RESONANCE = 3; - - public SoloudObject soloudObject; - alias soloudObject this; - - public static create() - { - return BiquadResonantFilter(SoloudObject(BiquadResonantFilter_create())); - } - - public void destroy() - { - BiquadResonantFilter_destroy(objhandle); - } - - public int setParams(int aType, float aSampleRate, float aFrequency, float aResonance) - { - return BiquadResonantFilter_setParams(objhandle, aType, aSampleRate, aFrequency, aResonance); - } + public enum NONE = 0; + public enum HIGHPASS = 2; + public enum WET = 0; + public enum LOWPASS = 1; + public enum SAMPLERATE = 1; + public enum BANDPASS = 3; + public enum FREQUENCY = 2; + public enum RESONANCE = 3; + + public SoloudObject soloudObject; + alias soloudObject this; + + public static create() + { + return BiquadResonantFilter(SoloudObject(BiquadResonantFilter_create())); + } + + public void destroy() + { + BiquadResonantFilter_destroy(objhandle); + } + + public int setParams(int aType, float aSampleRate, float aFrequency, float aResonance) + { + return BiquadResonantFilter_setParams(objhandle, aType, aSampleRate, aFrequency, aResonance); + } } @@ -440,103 +440,103 @@ public struct Bus { pure @safe nothrow @nogc: - public SoloudObject soloudObject; - alias soloudObject this; - - public static create() - { - return Bus(SoloudObject(Bus_create())); - } - - public void destroy() - { - Bus_destroy(objhandle); - } - - public void setFilter(uint aFilterId, SoloudObject aFilter) - { - Bus_setFilter(objhandle, aFilterId, aFilter.objhandle); - } - - public uint play(SoloudObject aSound, float aVolume = 1.0f, float aPan = 0.0f, int aPaused = 0) - { - return Bus_playEx(objhandle, aSound.objhandle, aVolume, aPan, aPaused); - } - - public uint playClocked(double aSoundTime, SoloudObject aSound, float aVolume = 1.0f, float aPan = 0.0f) - { - return Bus_playClockedEx(objhandle, aSoundTime, aSound.objhandle, aVolume, aPan); - } - - public uint play3d(SoloudObject aSound, float aPosX, float aPosY, float aPosZ, float aVelX = 0.0f, float aVelY = 0.0f, float aVelZ = 0.0f, float aVolume = 1.0f, int aPaused = 0) - { - return Bus_play3dEx(objhandle, aSound.objhandle, aPosX, aPosY, aPosZ, aVelX, aVelY, aVelZ, aVolume, aPaused); - } - - public uint play3dClocked(double aSoundTime, SoloudObject aSound, float aPosX, float aPosY, float aPosZ, float aVelX = 0.0f, float aVelY = 0.0f, float aVelZ = 0.0f, float aVolume = 1.0f) - { - return Bus_play3dClockedEx(objhandle, aSoundTime, aSound.objhandle, aPosX, aPosY, aPosZ, aVelX, aVelY, aVelZ, aVolume); - } - - public void setVisualizationEnable(int aEnable) - { - Bus_setVisualizationEnable(objhandle, aEnable); - } - - public float[] calcFFT() - { - return Bus_calcFFT(objhandle); - } - - public float[] getWave() - { - return Bus_getWave(objhandle); - } - - public void setLooping(int aLoop) - { - Bus_setLooping(objhandle, aLoop); - } - - public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) - { - Bus_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); - } - - public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) - { - Bus_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); - } - - public void set3dDopplerFactor(float aDopplerFactor) - { - Bus_set3dDopplerFactor(objhandle, aDopplerFactor); - } - - public void set3dProcessing(int aDo3dProcessing) - { - Bus_set3dProcessing(objhandle, aDo3dProcessing); - } - - public void set3dListenerRelative(int aListenerRelative) - { - Bus_set3dListenerRelative(objhandle, aListenerRelative); - } - - public void set3dDistanceDelay(int aDistanceDelay) - { - Bus_set3dDistanceDelay(objhandle, aDistanceDelay); - } - - public void set3dCollider(SoloudObject aCollider, int aUserData = 0) - { - Bus_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); - } - - public void stop() - { - Bus_stop(objhandle); - } + public SoloudObject soloudObject; + alias soloudObject this; + + public static create() + { + return Bus(SoloudObject(Bus_create())); + } + + public void destroy() + { + Bus_destroy(objhandle); + } + + public void setFilter(uint aFilterId, SoloudObject aFilter) + { + Bus_setFilter(objhandle, aFilterId, aFilter.objhandle); + } + + public uint play(SoloudObject aSound, float aVolume = 1.0f, float aPan = 0.0f, int aPaused = 0) + { + return Bus_playEx(objhandle, aSound.objhandle, aVolume, aPan, aPaused); + } + + public uint playClocked(double aSoundTime, SoloudObject aSound, float aVolume = 1.0f, float aPan = 0.0f) + { + return Bus_playClockedEx(objhandle, aSoundTime, aSound.objhandle, aVolume, aPan); + } + + public uint play3d(SoloudObject aSound, float aPosX, float aPosY, float aPosZ, float aVelX = 0.0f, float aVelY = 0.0f, float aVelZ = 0.0f, float aVolume = 1.0f, int aPaused = 0) + { + return Bus_play3dEx(objhandle, aSound.objhandle, aPosX, aPosY, aPosZ, aVelX, aVelY, aVelZ, aVolume, aPaused); + } + + public uint play3dClocked(double aSoundTime, SoloudObject aSound, float aPosX, float aPosY, float aPosZ, float aVelX = 0.0f, float aVelY = 0.0f, float aVelZ = 0.0f, float aVolume = 1.0f) + { + return Bus_play3dClockedEx(objhandle, aSoundTime, aSound.objhandle, aPosX, aPosY, aPosZ, aVelX, aVelY, aVelZ, aVolume); + } + + public void setVisualizationEnable(int aEnable) + { + Bus_setVisualizationEnable(objhandle, aEnable); + } + + public float[] calcFFT() + { + return Bus_calcFFT(objhandle); + } + + public float[] getWave() + { + return Bus_getWave(objhandle); + } + + public void setLooping(int aLoop) + { + Bus_setLooping(objhandle, aLoop); + } + + public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) + { + Bus_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); + } + + public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) + { + Bus_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); + } + + public void set3dDopplerFactor(float aDopplerFactor) + { + Bus_set3dDopplerFactor(objhandle, aDopplerFactor); + } + + public void set3dProcessing(int aDo3dProcessing) + { + Bus_set3dProcessing(objhandle, aDo3dProcessing); + } + + public void set3dListenerRelative(int aListenerRelative) + { + Bus_set3dListenerRelative(objhandle, aListenerRelative); + } + + public void set3dDistanceDelay(int aDistanceDelay) + { + Bus_set3dDistanceDelay(objhandle, aDistanceDelay); + } + + public void set3dCollider(SoloudObject aCollider, int aUserData = 0) + { + Bus_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); + } + + public void stop() + { + Bus_stop(objhandle); + } } @@ -544,104 +544,104 @@ public struct EchoFilter { pure @safe nothrow @nogc: - public SoloudObject soloudObject; - alias soloudObject this; + public SoloudObject soloudObject; + alias soloudObject this; - public static create() - { - return EchoFilter(SoloudObject(EchoFilter_create())); - } + public static create() + { + return EchoFilter(SoloudObject(EchoFilter_create())); + } - public void destroy() - { - EchoFilter_destroy(objhandle); - } + public void destroy() + { + EchoFilter_destroy(objhandle); + } - public int setParams(float aDelay, float aDecay = 0.7f, float aFilter = 0.0f) - { - return EchoFilter_setParamsEx(objhandle, aDelay, aDecay, aFilter); - } + public int setParams(float aDelay, float aDecay = 0.7f, float aFilter = 0.0f) + { + return EchoFilter_setParamsEx(objhandle, aDelay, aDecay, aFilter); + } } public struct FFTFilter { pure @safe nothrow @nogc: - public enum OVER = 0; - public enum MULTIPLY = 2; - public enum SUBTRACT = 1; + public enum OVER = 0; + public enum MULTIPLY = 2; + public enum SUBTRACT = 1; - public SoloudObject soloudObject; - alias soloudObject this; + public SoloudObject soloudObject; + alias soloudObject this; - public static create() - { - return FFTFilter(SoloudObject(FFTFilter_create())); - } + public static create() + { + return FFTFilter(SoloudObject(FFTFilter_create())); + } - public void destroy() - { - FFTFilter_destroy(objhandle); - } + public void destroy() + { + FFTFilter_destroy(objhandle); + } - public int setParameters(int aShift, int aCombine = 0, float aScale = 0.002f) - { - return FFTFilter_setParametersEx(objhandle, aShift, aCombine, aScale); - } + public int setParameters(int aShift, int aCombine = 0, float aScale = 0.002f) + { + return FFTFilter_setParametersEx(objhandle, aShift, aCombine, aScale); + } } public struct FlangerFilter { pure @safe nothrow @nogc: - public enum FREQ = 2; - public enum WET = 0; - public enum DELAY = 1; + public enum FREQ = 2; + public enum WET = 0; + public enum DELAY = 1; - public SoloudObject soloudObject; - alias soloudObject this; + public SoloudObject soloudObject; + alias soloudObject this; - public static create() - { - return FlangerFilter(SoloudObject(FlangerFilter_create())); - } + public static create() + { + return FlangerFilter(SoloudObject(FlangerFilter_create())); + } - public void destroy() - { - FlangerFilter_destroy(objhandle); - } + public void destroy() + { + FlangerFilter_destroy(objhandle); + } - public int setParams(float aDelay, float aFreq) - { - return FlangerFilter_setParams(objhandle, aDelay, aFreq); - } + public int setParams(float aDelay, float aFreq) + { + return FlangerFilter_setParams(objhandle, aDelay, aFreq); + } } public struct LofiFilter { pure @safe nothrow @nogc: - public enum BITDEPTH = 2; - public enum WET = 0; - public enum SAMPLERATE = 1; + public enum BITDEPTH = 2; + public enum WET = 0; + public enum SAMPLERATE = 1; - public SoloudObject soloudObject; - alias soloudObject this; + public SoloudObject soloudObject; + alias soloudObject this; - public static create() - { - return LofiFilter(SoloudObject(LofiFilter_create())); - } + public static create() + { + return LofiFilter(SoloudObject(LofiFilter_create())); + } - public void destroy() - { - LofiFilter_destroy(objhandle); - } + public void destroy() + { + LofiFilter_destroy(objhandle); + } - public int setParams(float aSampleRate, float aBitdepth) - { - return LofiFilter_setParams(objhandle, aSampleRate, aBitdepth); - } + public int setParams(float aSampleRate, float aBitdepth) + { + return LofiFilter_setParams(objhandle, aSampleRate, aBitdepth); + } } @@ -649,73 +649,73 @@ public struct Modplug { pure @safe nothrow @nogc: - public SoloudObject soloudObject; - alias soloudObject this; - - public static create() - { - return Modplug(SoloudObject(Modplug_create())); - } - - public void destroy() - { - Modplug_destroy(objhandle); - } - - public int load(const(char)* aFilename) - { - return Modplug_load(objhandle, aFilename); - } - - public void setLooping(int aLoop) - { - Modplug_setLooping(objhandle, aLoop); - } - - public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) - { - Modplug_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); - } - - public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) - { - Modplug_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); - } - - public void set3dDopplerFactor(float aDopplerFactor) - { - Modplug_set3dDopplerFactor(objhandle, aDopplerFactor); - } - - public void set3dProcessing(int aDo3dProcessing) - { - Modplug_set3dProcessing(objhandle, aDo3dProcessing); - } - - public void set3dListenerRelative(int aListenerRelative) - { - Modplug_set3dListenerRelative(objhandle, aListenerRelative); - } - - public void set3dDistanceDelay(int aDistanceDelay) - { - Modplug_set3dDistanceDelay(objhandle, aDistanceDelay); - } - - public void set3dCollider(SoloudObject aCollider, int aUserData = 0) - { - Modplug_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); - } - - public void setFilter(uint aFilterId, SoloudObject aFilter) - { - Modplug_setFilter(objhandle, aFilterId, aFilter.objhandle); - } - - public void stop() - { - Modplug_stop(objhandle); - } + public SoloudObject soloudObject; + alias soloudObject this; + + public static create() + { + return Modplug(SoloudObject(Modplug_create())); + } + + public void destroy() + { + Modplug_destroy(objhandle); + } + + public int load(const(char)* aFilename) + { + return Modplug_load(objhandle, aFilename); + } + + public void setLooping(int aLoop) + { + Modplug_setLooping(objhandle, aLoop); + } + + public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) + { + Modplug_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); + } + + public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) + { + Modplug_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); + } + + public void set3dDopplerFactor(float aDopplerFactor) + { + Modplug_set3dDopplerFactor(objhandle, aDopplerFactor); + } + + public void set3dProcessing(int aDo3dProcessing) + { + Modplug_set3dProcessing(objhandle, aDo3dProcessing); + } + + public void set3dListenerRelative(int aListenerRelative) + { + Modplug_set3dListenerRelative(objhandle, aListenerRelative); + } + + public void set3dDistanceDelay(int aDistanceDelay) + { + Modplug_set3dDistanceDelay(objhandle, aDistanceDelay); + } + + public void set3dCollider(SoloudObject aCollider, int aUserData = 0) + { + Modplug_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); + } + + public void setFilter(uint aFilterId, SoloudObject aFilter) + { + Modplug_setFilter(objhandle, aFilterId, aFilter.objhandle); + } + + public void stop() + { + Modplug_stop(objhandle); + } } @@ -723,119 +723,119 @@ public struct Prg { pure @safe nothrow @nogc: - public SoloudObject soloudObject; - alias soloudObject this; + public SoloudObject soloudObject; + alias soloudObject this; - public static create() - { - return Prg(SoloudObject(Prg_create())); - } + public static create() + { + return Prg(SoloudObject(Prg_create())); + } - public void destroy() - { - Prg_destroy(objhandle); - } + public void destroy() + { + Prg_destroy(objhandle); + } - public uint rand() - { - return Prg_rand(objhandle); - } + public uint rand() + { + return Prg_rand(objhandle); + } - public void srand(int aSeed) - { - Prg_srand(objhandle, aSeed); - } + public void srand(int aSeed) + { + Prg_srand(objhandle, aSeed); + } } public struct Sfxr { pure @safe nothrow @nogc: - public enum HURT = 4; - public enum LASER = 1; - public enum BLIP = 6; - public enum JUMP = 5; - public enum COIN = 0; - public enum EXPLOSION = 2; - public enum POWERUP = 3; - - public SoloudObject soloudObject; - alias soloudObject this; - - public static create() - { - return Sfxr(SoloudObject(Sfxr_create())); - } - - public void destroy() - { - Sfxr_destroy(objhandle); - } - - public void resetParams() - { - Sfxr_resetParams(objhandle); - } - - public int loadParams(const(char)* aFilename) - { - return Sfxr_loadParams(objhandle, aFilename); - } - - public int loadPreset(int aPresetNo, int aRandSeed) - { - return Sfxr_loadPreset(objhandle, aPresetNo, aRandSeed); - } - - public void setLooping(int aLoop) - { - Sfxr_setLooping(objhandle, aLoop); - } - - public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) - { - Sfxr_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); - } - - public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) - { - Sfxr_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); - } - - public void set3dDopplerFactor(float aDopplerFactor) - { - Sfxr_set3dDopplerFactor(objhandle, aDopplerFactor); - } - - public void set3dProcessing(int aDo3dProcessing) - { - Sfxr_set3dProcessing(objhandle, aDo3dProcessing); - } - - public void set3dListenerRelative(int aListenerRelative) - { - Sfxr_set3dListenerRelative(objhandle, aListenerRelative); - } - - public void set3dDistanceDelay(int aDistanceDelay) - { - Sfxr_set3dDistanceDelay(objhandle, aDistanceDelay); - } - - public void set3dCollider(SoloudObject aCollider, int aUserData = 0) - { - Sfxr_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); - } - - public void setFilter(uint aFilterId, SoloudObject aFilter) - { - Sfxr_setFilter(objhandle, aFilterId, aFilter.objhandle); - } - - public void stop() - { - Sfxr_stop(objhandle); - } + public enum HURT = 4; + public enum LASER = 1; + public enum BLIP = 6; + public enum JUMP = 5; + public enum COIN = 0; + public enum EXPLOSION = 2; + public enum POWERUP = 3; + + public SoloudObject soloudObject; + alias soloudObject this; + + public static create() + { + return Sfxr(SoloudObject(Sfxr_create())); + } + + public void destroy() + { + Sfxr_destroy(objhandle); + } + + public void resetParams() + { + Sfxr_resetParams(objhandle); + } + + public int loadParams(const(char)* aFilename) + { + return Sfxr_loadParams(objhandle, aFilename); + } + + public int loadPreset(int aPresetNo, int aRandSeed) + { + return Sfxr_loadPreset(objhandle, aPresetNo, aRandSeed); + } + + public void setLooping(int aLoop) + { + Sfxr_setLooping(objhandle, aLoop); + } + + public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) + { + Sfxr_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); + } + + public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) + { + Sfxr_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); + } + + public void set3dDopplerFactor(float aDopplerFactor) + { + Sfxr_set3dDopplerFactor(objhandle, aDopplerFactor); + } + + public void set3dProcessing(int aDo3dProcessing) + { + Sfxr_set3dProcessing(objhandle, aDo3dProcessing); + } + + public void set3dListenerRelative(int aListenerRelative) + { + Sfxr_set3dListenerRelative(objhandle, aListenerRelative); + } + + public void set3dDistanceDelay(int aDistanceDelay) + { + Sfxr_set3dDistanceDelay(objhandle, aDistanceDelay); + } + + public void set3dCollider(SoloudObject aCollider, int aUserData = 0) + { + Sfxr_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); + } + + public void setFilter(uint aFilterId, SoloudObject aFilter) + { + Sfxr_setFilter(objhandle, aFilterId, aFilter.objhandle); + } + + public void stop() + { + Sfxr_stop(objhandle); + } } @@ -843,73 +843,73 @@ public struct Speech { pure @safe nothrow @nogc: - public SoloudObject soloudObject; - alias soloudObject this; - - public static create() - { - return Speech(SoloudObject(Speech_create())); - } - - public void destroy() - { - Speech_destroy(objhandle); - } - - public int setText(const(char)* aText) - { - return Speech_setText(objhandle, aText); - } - - public void setLooping(int aLoop) - { - Speech_setLooping(objhandle, aLoop); - } - - public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) - { - Speech_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); - } - - public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) - { - Speech_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); - } - - public void set3dDopplerFactor(float aDopplerFactor) - { - Speech_set3dDopplerFactor(objhandle, aDopplerFactor); - } - - public void set3dProcessing(int aDo3dProcessing) - { - Speech_set3dProcessing(objhandle, aDo3dProcessing); - } - - public void set3dListenerRelative(int aListenerRelative) - { - Speech_set3dListenerRelative(objhandle, aListenerRelative); - } - - public void set3dDistanceDelay(int aDistanceDelay) - { - Speech_set3dDistanceDelay(objhandle, aDistanceDelay); - } - - public void set3dCollider(SoloudObject aCollider, int aUserData = 0) - { - Speech_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); - } - - public void setFilter(uint aFilterId, SoloudObject aFilter) - { - Speech_setFilter(objhandle, aFilterId, aFilter.objhandle); - } - - public void stop() - { - Speech_stop(objhandle); - } + public SoloudObject soloudObject; + alias soloudObject this; + + public static create() + { + return Speech(SoloudObject(Speech_create())); + } + + public void destroy() + { + Speech_destroy(objhandle); + } + + public int setText(const(char)* aText) + { + return Speech_setText(objhandle, aText); + } + + public void setLooping(int aLoop) + { + Speech_setLooping(objhandle, aLoop); + } + + public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) + { + Speech_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); + } + + public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) + { + Speech_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); + } + + public void set3dDopplerFactor(float aDopplerFactor) + { + Speech_set3dDopplerFactor(objhandle, aDopplerFactor); + } + + public void set3dProcessing(int aDo3dProcessing) + { + Speech_set3dProcessing(objhandle, aDo3dProcessing); + } + + public void set3dListenerRelative(int aListenerRelative) + { + Speech_set3dListenerRelative(objhandle, aListenerRelative); + } + + public void set3dDistanceDelay(int aDistanceDelay) + { + Speech_set3dDistanceDelay(objhandle, aDistanceDelay); + } + + public void set3dCollider(SoloudObject aCollider, int aUserData = 0) + { + Speech_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); + } + + public void setFilter(uint aFilterId, SoloudObject aFilter) + { + Speech_setFilter(objhandle, aFilterId, aFilter.objhandle); + } + + public void stop() + { + Speech_stop(objhandle); + } } @@ -917,83 +917,83 @@ public struct Wav { pure @safe nothrow @nogc: - public SoloudObject soloudObject; - alias soloudObject this; - - public static create() - { - return Wav(SoloudObject(Wav_create())); - } - - public void destroy() - { - Wav_destroy(objhandle); - } - - public int load(const(char)* aFilename) - { - return Wav_load(objhandle, aFilename); - } - - public int loadMem(ubyte* aMem, uint aLength) - { - return Wav_loadMem(objhandle, aMem, aLength); - } - - public double getLength() - { - return Wav_getLength(objhandle); - } - - public void setLooping(int aLoop) - { - Wav_setLooping(objhandle, aLoop); - } - - public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) - { - Wav_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); - } - - public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) - { - Wav_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); - } - - public void set3dDopplerFactor(float aDopplerFactor) - { - Wav_set3dDopplerFactor(objhandle, aDopplerFactor); - } - - public void set3dProcessing(int aDo3dProcessing) - { - Wav_set3dProcessing(objhandle, aDo3dProcessing); - } - - public void set3dListenerRelative(int aListenerRelative) - { - Wav_set3dListenerRelative(objhandle, aListenerRelative); - } - - public void set3dDistanceDelay(int aDistanceDelay) - { - Wav_set3dDistanceDelay(objhandle, aDistanceDelay); - } - - public void set3dCollider(SoloudObject aCollider, int aUserData = 0) - { - Wav_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); - } - - public void setFilter(uint aFilterId, SoloudObject aFilter) - { - Wav_setFilter(objhandle, aFilterId, aFilter.objhandle); - } - - public void stop() - { - Wav_stop(objhandle); - } + public SoloudObject soloudObject; + alias soloudObject this; + + public static create() + { + return Wav(SoloudObject(Wav_create())); + } + + public void destroy() + { + Wav_destroy(objhandle); + } + + public int load(const(char)* aFilename) + { + return Wav_load(objhandle, aFilename); + } + + public int loadMem(ubyte* aMem, uint aLength) + { + return Wav_loadMem(objhandle, aMem, aLength); + } + + public double getLength() + { + return Wav_getLength(objhandle); + } + + public void setLooping(int aLoop) + { + Wav_setLooping(objhandle, aLoop); + } + + public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) + { + Wav_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); + } + + public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) + { + Wav_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); + } + + public void set3dDopplerFactor(float aDopplerFactor) + { + Wav_set3dDopplerFactor(objhandle, aDopplerFactor); + } + + public void set3dProcessing(int aDo3dProcessing) + { + Wav_set3dProcessing(objhandle, aDo3dProcessing); + } + + public void set3dListenerRelative(int aListenerRelative) + { + Wav_set3dListenerRelative(objhandle, aListenerRelative); + } + + public void set3dDistanceDelay(int aDistanceDelay) + { + Wav_set3dDistanceDelay(objhandle, aDistanceDelay); + } + + public void set3dCollider(SoloudObject aCollider, int aUserData = 0) + { + Wav_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); + } + + public void setFilter(uint aFilterId, SoloudObject aFilter) + { + Wav_setFilter(objhandle, aFilterId, aFilter.objhandle); + } + + public void stop() + { + Wav_stop(objhandle); + } } @@ -1001,78 +1001,78 @@ public struct WavStream { pure @safe nothrow @nogc: - public SoloudObject soloudObject; - alias soloudObject this; - - public static create() - { - return WavStream(SoloudObject(WavStream_create())); - } - - public void destroy() - { - WavStream_destroy(objhandle); - } - - public int load(const(char)* aFilename) - { - return WavStream_load(objhandle, aFilename); - } - - public double getLength() - { - return WavStream_getLength(objhandle); - } - - public void setLooping(int aLoop) - { - WavStream_setLooping(objhandle, aLoop); - } - - public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) - { - WavStream_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); - } - - public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) - { - WavStream_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); - } - - public void set3dDopplerFactor(float aDopplerFactor) - { - WavStream_set3dDopplerFactor(objhandle, aDopplerFactor); - } - - public void set3dProcessing(int aDo3dProcessing) - { - WavStream_set3dProcessing(objhandle, aDo3dProcessing); - } - - public void set3dListenerRelative(int aListenerRelative) - { - WavStream_set3dListenerRelative(objhandle, aListenerRelative); - } - - public void set3dDistanceDelay(int aDistanceDelay) - { - WavStream_set3dDistanceDelay(objhandle, aDistanceDelay); - } - - public void set3dCollider(SoloudObject aCollider, int aUserData = 0) - { - WavStream_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); - } - - public void setFilter(uint aFilterId, SoloudObject aFilter) - { - WavStream_setFilter(objhandle, aFilterId, aFilter.objhandle); - } - - public void stop() - { - WavStream_stop(objhandle); - } + public SoloudObject soloudObject; + alias soloudObject this; + + public static create() + { + return WavStream(SoloudObject(WavStream_create())); + } + + public void destroy() + { + WavStream_destroy(objhandle); + } + + public int load(const(char)* aFilename) + { + return WavStream_load(objhandle, aFilename); + } + + public double getLength() + { + return WavStream_getLength(objhandle); + } + + public void setLooping(int aLoop) + { + WavStream_setLooping(objhandle, aLoop); + } + + public void set3dMinMaxDistance(float aMinDistance, float aMaxDistance) + { + WavStream_set3dMinMaxDistance(objhandle, aMinDistance, aMaxDistance); + } + + public void set3dAttenuation(uint aAttenuationModel, float aAttenuationRolloffFactor) + { + WavStream_set3dAttenuation(objhandle, aAttenuationModel, aAttenuationRolloffFactor); + } + + public void set3dDopplerFactor(float aDopplerFactor) + { + WavStream_set3dDopplerFactor(objhandle, aDopplerFactor); + } + + public void set3dProcessing(int aDo3dProcessing) + { + WavStream_set3dProcessing(objhandle, aDo3dProcessing); + } + + public void set3dListenerRelative(int aListenerRelative) + { + WavStream_set3dListenerRelative(objhandle, aListenerRelative); + } + + public void set3dDistanceDelay(int aDistanceDelay) + { + WavStream_set3dDistanceDelay(objhandle, aDistanceDelay); + } + + public void set3dCollider(SoloudObject aCollider, int aUserData = 0) + { + WavStream_set3dColliderEx(objhandle, aCollider.objhandle, aUserData); + } + + public void setFilter(uint aFilterId, SoloudObject aFilter) + { + WavStream_setFilter(objhandle, aFilterId, aFilter.objhandle); + } + + public void stop() + { + WavStream_stop(objhandle); + } } private static extern(C) int* Soloud_create(); From bed064d0785b2d87d1ea1c5a90bff1e0557f8751 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 25 Sep 2014 11:38:49 -0400 Subject: [PATCH 074/141] Updated travis to use dub 0.9.22 release --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4194abe8..788b72b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,7 @@ os: - linux - osx env: -# - DMD_VER=2.065.0 DUB_VER=0.9.21 - - DMD_VER=2.066.0 DUB_VER=0.9.22-rc.3 + - DMD_VER=2.066.0 DUB_VER=0.9.22 install: - bash .travis/setup_linux.sh - bash .travis/setup_osx.sh From 8ead7d2eda9176c10f5fa4632b666e8e49e576ae Mon Sep 17 00:00:00 2001 From: Brandon Littell Date: Thu, 25 Sep 2014 11:51:33 -0400 Subject: [PATCH 075/141] Updated audio.d for the reenwritening PR. --- source/dash/components/audio.d | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/source/dash/components/audio.d b/source/dash/components/audio.d index e70e295b..f0017237 100644 --- a/source/dash/components/audio.d +++ b/source/dash/components/audio.d @@ -2,18 +2,15 @@ * Defines audio related classes, such as the listener and emitter */ module dash.components.audio; -import dash.core.properties; -import dash.components.component; -import dash.utility, dash.utility.soloud; +import dash.core.properties, dash.components, dash.utility, dash.utility.soloud; import std.string; -mixin( registerComponents!q{dash.components.audio} ); +mixin( registerComponents!() ); /** * Listener object that hears sounds and sends them to the audio output device * (usually attaced to the camera) */ -@yamlComponent( "Listener" ) class Listener : Component { private: @@ -39,7 +36,6 @@ public: /** * Emitter object that plays sounds that listeners can hear */ -@yamlComponent( "Emitter" ) class Emitter : Component { private: From 4e5c5a55fffa27beb477dbe898e36710f93be759 Mon Sep 17 00:00:00 2001 From: Brandon Littell Date: Thu, 25 Sep 2014 12:32:00 -0400 Subject: [PATCH 076/141] Fixed compiler errors. --- source/dash/utility/input.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index 0ed73cee..bbc50d94 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -216,8 +216,8 @@ public: { version( Windows ) { - if( !Win32.get() ) - return vec2i(); + if( !Win32GL.get() ) + return vec2ui(); import dash.graphics; import win32.windows; From 1f24b2c631405ada6617a05f12bd2e568ce99067 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 25 Sep 2014 14:36:55 -0400 Subject: [PATCH 077/141] Fixed assets having invalid resource references --- source/dash/components/animation.d | 4 ++-- source/dash/components/assets.d | 22 ++++++++++++++-------- source/dash/components/material.d | 18 +++++++++--------- source/dash/components/mesh.d | 8 ++++---- source/dash/components/userinterface.d | 2 +- source/dash/core/gameobject.d | 3 +++ source/dash/core/prefabs.d | 5 +++-- 7 files changed, 36 insertions(+), 26 deletions(-) diff --git a/source/dash/components/animation.d b/source/dash/components/animation.d index 84e33048..47ed9104 100644 --- a/source/dash/components/animation.d +++ b/source/dash/components/animation.d @@ -164,9 +164,9 @@ public: * mesh = Assimp mesh/bone object * nodeHierarchy = Hierarchy of bones/filler nodes used for the animation */ - this( const(aiAnimation**) animations, int numAnimations, const(aiMesh*) mesh, const(aiNode*) nodeHierarchy ) + this( Resource res, const(aiAnimation**) animations, int numAnimations, const(aiMesh*) mesh, const(aiNode*) nodeHierarchy ) { - super( Resource( "" ) ); + super( res ); for( int i = 0; i < nodeHierarchy.mNumChildren; i++) { diff --git a/source/dash/components/assets.d b/source/dash/components/assets.d index a36ce725..e510ebf2 100644 --- a/source/dash/components/assets.d +++ b/source/dash/components/assets.d @@ -78,7 +78,7 @@ public: assert(aiIsExtensionSupported(".fbx".toStringz), "fbx format isn't supported by assimp instance!"); // Load the unitSquare - unitSquare = new Mesh( new MeshAsset( "", aiImportFileFromMemory( + unitSquare = new Mesh( new MeshAsset( Resource( "" ), aiImportFileFromMemory( unitSquareMesh.toStringz(), unitSquareMesh.length, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType, @@ -99,10 +99,10 @@ public: // Add mesh if( scene.mNumMeshes > 0 ) { - auto newMesh = new MeshAsset( file.fullPath, scene.mMeshes[ 0 ] ); + auto newMesh = new MeshAsset( file, scene.mMeshes[ 0 ] ); if( scene.mNumAnimations > 0 ) - newMesh.animationData = new AnimationData( scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); + newMesh.animationData = new AnimationData( file, scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); meshes[ file.baseFileName ] = newMesh; } @@ -120,7 +120,7 @@ public: if( file.baseFileName in textures ) logWarning( "Texture ", file.baseFileName, " exists more than once." ); - textures[ file.baseFileName ] = new TextureAsset( file.fullPath ); + textures[ file.baseFileName ] = new TextureAsset( file ); } foreach( res; scanDirectory( Resources.Materials ) ) @@ -132,6 +132,7 @@ public: if( mat.name in materials ) logWarning( "Material ", mat.name, " exists more than once." ); + mat.resource = res; materials[ mat.name ] = mat; materialResources[ res ] ~= mat; } @@ -194,6 +195,9 @@ public: } } +/// A tuple of a resource and an asset +alias AssetResource = Tuple!( Resource, "resource", Asset, "asset" ); + abstract class Asset { private: @@ -209,10 +213,6 @@ public: /** * Creates asset with resource. */ - this() - { - resource = Resource( "" ); - } this( Resource res ) { resource = res; @@ -242,6 +242,12 @@ public: asset = ass; } + /// Is the asset null? + bool isNull() @property const pure @safe nothrow + { + return asset is null; + } + /// Gets a reference to it's asset. override void initialize() { diff --git a/source/dash/components/material.d b/source/dash/components/material.d index cf481ae6..db806144 100644 --- a/source/dash/components/material.d +++ b/source/dash/components/material.d @@ -20,13 +20,13 @@ public: @rename( "Name" ) string name; /// The diffuse (or color) map. - @rename( "Diffuse" ) @asArray + @rename( "Diffuse" ) @asArray @optional Texture diffuse; /// The normal map, which specifies which way a face is pointing at a given pixel. - @rename( "Normal" ) @asArray + @rename( "Normal" ) @asArray @optional Texture normal; /// The specular map, which specifies how shiny a given point is. - @rename( "Specular" ) @asArray + @rename( "Specular" ) @asArray @optional Texture specular; /** @@ -104,9 +104,9 @@ protected: * * Params: */ - this( ubyte* buffer, string filePath = "" ) + this( ubyte* buffer, Resource filePath ) { - super( Resource( filePath ) ); + super( filePath ); glGenTextures( 1, &_glID ); glBindTexture( GL_TEXTURE_2D, glID ); updateBuffer( buffer ); @@ -142,9 +142,9 @@ public: * * Params: */ - this( string filePath ) + this( Resource filePath ) { - auto imageData = loadFreeImage( filePath ); + auto imageData = loadFreeImage( filePath.fullPath ); this( cast(ubyte*)FreeImage_GetBits( imageData ), filePath ); @@ -207,7 +207,7 @@ class Texture : AssetRef!TextureAsset static Texture def; if( !def ) - def = new Texture( new TextureAsset( [cast(ubyte)0, cast(ubyte)0, cast(ubyte)0, cast(ubyte)255].ptr ) ); + def = new Texture( new TextureAsset( [cast(ubyte)0, cast(ubyte)0, cast(ubyte)0, cast(ubyte)255].ptr, Resource( "" ) ) ); return def; } @@ -220,7 +220,7 @@ class Texture : AssetRef!TextureAsset static Texture def; if( !def ) - def = new Texture( new TextureAsset( [cast(ubyte)255, cast(ubyte)127, cast(ubyte)127, cast(ubyte)255].ptr ) ); + def = new Texture( new TextureAsset( [cast(ubyte)255, cast(ubyte)127, cast(ubyte)127, cast(ubyte)255].ptr, Resource( "" ) ) ); return def; } diff --git a/source/dash/components/mesh.d b/source/dash/components/mesh.d index ec3c0931..65a597ad 100644 --- a/source/dash/components/mesh.d +++ b/source/dash/components/mesh.d @@ -81,9 +81,9 @@ public: * filePath = The path to the file. * mesh = The AssImp mesh object to pull data from. */ - this( string filePath, const(aiMesh*) mesh ) + this( Resource filePath, const(aiMesh*) mesh ) { - super( Resource( filePath ) ); + super( filePath ); int floatsPerVertex, vertexSize; float[] outputData; uint[] indices; @@ -295,10 +295,10 @@ public: // Add mesh if( scene.mNumMeshes > 0 ) { - auto tempMesh = new MeshAsset( resource.fullPath, scene.mMeshes[ 0 ] ); + auto tempMesh = new MeshAsset( resource, scene.mMeshes[ 0 ] ); if( scene.mNumAnimations > 0 ) - tempMesh.animationData = new AnimationData( scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); + tempMesh.animationData = new AnimationData( resource, scene.mAnimations, scene.mNumAnimations, scene.mMeshes[ 0 ], scene.mRootNode ); // Copy attributes _glVertexArray = tempMesh._glVertexArray; diff --git a/source/dash/components/userinterface.d b/source/dash/components/userinterface.d index df8db007..4b0474e2 100644 --- a/source/dash/components/userinterface.d +++ b/source/dash/components/userinterface.d @@ -177,7 +177,7 @@ public: _height = h; glBuffer = new ubyte[_width*_height*4]; - super( cast(ubyte*)null ); + super( cast(ubyte*)null, Resource( "" ) ); version( Windows ) { diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 7b3d2190..1e054ecc 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -41,6 +41,9 @@ struct ObjectStateFlags } } +/// A tuple of a resource and a gameobject reference +alias GameObjectResource = Tuple!( Resource, "resource", GameObject, "object" ); + /** * Manages all components and transform in the world. Can be overridden. */ diff --git a/source/dash/core/prefabs.d b/source/dash/core/prefabs.d index ed9bb0e0..4d5c9a72 100644 --- a/source/dash/core/prefabs.d +++ b/source/dash/core/prefabs.d @@ -54,7 +54,7 @@ public: { foreach( fabDesc; res.deserializeMultiFile!( GameObject.Description )() ) { - auto newFab = new Prefab( fabDesc ); + auto newFab = new Prefab( fabDesc, res ); prefabs[ newFab.name ] = newFab; prefabResources[ res ] ~= newFab; } @@ -88,9 +88,10 @@ public: GameObject.Description description; /// Creates a prefab from a description. - this( GameObject.Description desc ) + this( GameObject.Description desc, Resource filePath ) { description = desc; + super( filePath ); } /** From 366f1d113a75ccfaf381290abcf9ccb22fc31e70 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 25 Sep 2014 17:57:25 -0400 Subject: [PATCH 078/141] Moved serialization calls into Description to clean up code and allow for refreshing --- source/dash/components/component.d | 94 ++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 6a2bc71d..3093f20b 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -46,11 +46,9 @@ public: // For serialization. mixin( perSerializationFormat!q{ - @ignore static $type delegate( Component )[ ClassInfo ] $typeSerializers; - @ignore static Component delegate( $type )[ string ] $typeDeserializers; $type to$type() const { - return $typeSerializers[ typeid(this) ]( cast()this ); + return getDescription( typeid(this) ).serializeComponentTo$type( cast()this ); } static Component from$type( $type data ) { @@ -62,9 +60,9 @@ public: if( auto type = "Type" in d ) { - if( auto cereal = type.get!string in $typeDeserializers ) + if( auto desc = getDescription( type.get!string ) ) { - return ( *cereal )( data ); + return desc.deserializeFrom$type( data ).createInstance(); } else { @@ -96,9 +94,41 @@ public: string serializer; } + /// The type of the component. @rename( "Type" ) string type; + + /// Get a list of teh fields on a component. abstract immutable(Field[]) fields() const @property; + + /// Create an instance of the component the description is for. + abstract Component createInstance() const; + + /// Serializers and deserializers + mixin( perSerializationFormat!q{ + abstract $type serializeComponentTo$type( Component c ) const; + abstract Description deserializeFrom$type( $type node ) const; + } ); +} + +/// A map of all registered Component types to their descriptions +private immutable(Description)[ClassInfo] descriptionsByClassInfo; +private immutable(Description)[string] descriptionsByName; + +immutable(Description) getDescription( ClassInfo type ) +{ + if( auto desc = type in descriptionsByClassInfo ) + return *desc; + else + return null; +} + +immutable(Description) getDescription( string name ) +{ + if( auto desc = name in descriptionsByName ) + return *desc; + else + return null; } /** @@ -135,19 +165,9 @@ public: // Runtime function, registers serializers void register() { - // Generate serializers for the type - mixin( perSerializationFormat!q{ - Component.$typeSerializers[ typeid(T) ] = ( Component c ) - { - return serializeTo$type( SerializationDescription.create( cast(T)c ) ); - }; - Component.$typeDeserializers[ T.stringof ] = ( $type node ) - { - return deserialize$type!SerializationDescription( node ).createInstance(); - }; - } ); - - Component.descriptionCreators[ typeid(T) ] = &SerializationDescription.create; + immutable desc = new immutable SerializationDescription; + descriptionsByClassInfo[ typeid(T) ] = desc; + descriptionsByName[ T.stringof ] = desc; } // Generate description @@ -157,24 +177,34 @@ private: // Generate actual struct final class SerializationDescription : Description { - mixin( { return reduce!( ( working, field ) - { - string result = working; + mixin( { return reduce!( ( working, field ) { + string result = working; + + // Append required import for variable type + if( field.mod ) + result ~= "import " ~ field.mod ~ ";\n"; - // Append required import for variable type - if( field.mod ) - result ~= "import " ~ field.mod ~ ";\n"; + // Append variable attributes + if( field.attributes ) + result ~= "@(" ~ field.attributes ~ ")\n"; - // Append variable attributes - if( field.attributes ) - result ~= "@(" ~ field.attributes ~ ")\n"; + // Append variable declaration + result ~= field.typeName ~ " " ~ field.name ~ ";\n"; - // Append variable declaration - result ~= field.typeName ~ " " ~ field.name ~ ";\n"; + return result; + } )( "", fieldList ); } () ); - return result; + // Generate serializers for the type + mixin( perSerializationFormat!q{ + override $type serializeComponentTo$type( Component c ) const + { + return serializeTo$type( SerializationDescription.create( cast(T)c ) ); } - )( "", fieldList ); } () ); + override SerializationDescription deserializeFrom$type( $type node ) const + { + return deserialize$type!SerializationDescription( node ); + } + } ); /// Get a list of field descriptions override immutable(Description.Field[]) fields() const @property @@ -204,7 +234,7 @@ private: } /// Create a component from a description. - T createInstance() + override T createInstance() const { T comp = new T; foreach( fieldName; __traits( allMembers, T ) ) From c3cd5c633028559804066ece995511254907b8bc Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 25 Sep 2014 18:02:54 -0400 Subject: [PATCH 079/141] Removed the old description creation infrastructure --- source/dash/components/component.d | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 3093f20b..ec5d953a 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -38,11 +38,8 @@ public: */ const(Description) description() @property { - assert( typeid(this) in descriptionCreators, "ComponentDescription not found for type " ~ typeid(this).name ); - return descriptionCreators[ typeid(this) ]( this ); + return getDescription( typeid(this) ).create( this ); } - private alias DescriptionCreator = const(Description) function( Component ); - private static DescriptionCreator[ ClassInfo ] descriptionCreators; // For serialization. mixin( perSerializationFormat!q{ @@ -104,6 +101,9 @@ public: /// Create an instance of the component the description is for. abstract Component createInstance() const; + /// Creates a description from a component. + abstract const(Description) create( const Component comp ) const; + /// Serializers and deserializers mixin( perSerializationFormat!q{ abstract $type serializeComponentTo$type( Component c ) const; @@ -213,7 +213,7 @@ private: } /// Create a description from a component. - static const(SerializationDescription) create( Component comp ) + override const(SerializationDescription) create( const Component comp ) const { auto theThing = cast(T)comp; auto desc = new SerializationDescription; From 8849fa274830bfcfd6eb0013d02ee4d5604e9ca4 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 25 Sep 2014 18:36:50 -0400 Subject: [PATCH 080/141] Switched all component storage to be by description --- source/dash/components/component.d | 162 +++++++++++++++++++---------- source/dash/core/gameobject.d | 8 +- source/dash/core/prefabs.d | 2 +- 3 files changed, 110 insertions(+), 62 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index ec5d953a..791a08ab 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -24,6 +24,10 @@ public: @ignore GameObject owner; + /// The description from the last creation/refresh. + @ignore + Description lastDesc; + /// The function called on initialization of the object. void initialize() { } /// Called on the update cycle. @@ -36,45 +40,35 @@ public: /** * Create a description from the this parameter. */ - const(Description) description() @property + final const(Description) description() @property { return getDescription( typeid(this) ).create( this ); } - // For serialization. - mixin( perSerializationFormat!q{ - $type to$type() const - { - return getDescription( typeid(this) ).serializeComponentTo$type( cast()this ); - } - static Component from$type( $type data ) - { - // If it's Bson, convert it to a json object. - static if( is( $type == Bson ) ) - auto d = data.toJson(); - else - auto d = data; + /** + * Refresh an object with a new description + */ + final void refresh( Description desc ) + { + lastDesc.refresh( this, desc ); + } - if( auto type = "Type" in d ) - { - if( auto desc = getDescription( type.get!string ) ) - { - return desc.deserializeFrom$type( data ).createInstance(); - } - else - { - logWarning( "Component's \"Type\" not found: ", type.get!string ); - return null; - } - } - else - { - logWarning( "Component doesn't have \"Type\" field." ); - return null; - } - } - static assert( is$typeSerializable!Component ); - } ); + /// For easy external access + alias Description = .Description; +} + +/// A map of all registered Component types to their descriptions +private immutable(Description)[ClassInfo] descriptionsByClassInfo; +private immutable(Description)[string] descriptionsByName; + +immutable(Description) getDescription( ClassInfo type ) +{ + return descriptionsByClassInfo.get( type, null ); +} + +immutable(Description) getDescription( string name ) +{ + return descriptionsByName.get( name, null ); } /// The description for the component @@ -96,39 +90,57 @@ public: string type; /// Get a list of teh fields on a component. + @ignore abstract immutable(Field[]) fields() const @property; /// Create an instance of the component the description is for. abstract Component createInstance() const; + /// Refresh a component by comparing descriptions. + abstract void refresh( Component comp, const Description newDesc ); + /// Creates a description from a component. abstract const(Description) create( const Component comp ) const; /// Serializers and deserializers mixin( perSerializationFormat!q{ - abstract $type serializeComponentTo$type( Component c ) const; + // Overridable serializers + abstract $type serializeDescriptionTo$type( Description c ) const; abstract Description deserializeFrom$type( $type node ) const; - } ); -} -/// A map of all registered Component types to their descriptions -private immutable(Description)[ClassInfo] descriptionsByClassInfo; -private immutable(Description)[string] descriptionsByName; - -immutable(Description) getDescription( ClassInfo type ) -{ - if( auto desc = type in descriptionsByClassInfo ) - return *desc; - else - return null; -} + // Serializers for vibe + final $type to$type() const + { + return getDescription( typeid(this) ).serializeDescriptionTo$type( cast()this ); + } + static Description from$type( $type data ) + { + // If it's Bson, convert it to a json object. + static if( is( $type == Bson ) ) + auto d = data.toJson(); + else + auto d = data; -immutable(Description) getDescription( string name ) -{ - if( auto desc = name in descriptionsByName ) - return *desc; - else - return null; + if( auto type = "Type" in d ) + { + if( auto desc = getDescription( type.get!string ) ) + { + return desc.deserializeFrom$type( data ); + } + else + { + logWarning( "Component's \"Type\" not found: ", type.get!string ); + return null; + } + } + else + { + logWarning( "Component doesn't have \"Type\" field." ); + return null; + } + } + static assert( is$typeSerializable!Description ); + } ); } /** @@ -196,9 +208,9 @@ private: // Generate serializers for the type mixin( perSerializationFormat!q{ - override $type serializeComponentTo$type( Component c ) const + override $type serializeDescriptionTo$type( Description desc ) const { - return serializeTo$type( SerializationDescription.create( cast(T)c ) ); + return serializeTo$type( cast(SerializationDescription)desc ); } override SerializationDescription deserializeFrom$type( $type node ) const { @@ -225,7 +237,9 @@ private: static if( idx >= 0 ) { enum field = fieldList[ idx ]; + // Serialize the value for the description mixin( "auto ser = "~field.serializer~".serialize(theThing."~field.name~");" ); + // Copy the value to the description mixin( "desc."~field.name~" = ser;" ); } } @@ -233,6 +247,38 @@ private: return desc; } + /// Refresh a component by comparing descriptions. + override void refresh( Component comp, const Description desc ) + in + { + assert( cast(T)comp, "Component of the wrong type passed to the wrong description." ); + assert( cast(SerializationDescription)desc, "Invalid description type." ); + } + body + { + auto t = cast(T)comp; + auto newDesc = cast(SerializationDescription)desc; + + foreach( fieldName; __traits( allMembers, T ) ) + { + enum idx = fieldList.map!(f => f.name).countUntil( fieldName ); + static if( idx >= 0 ) + { + enum field = fieldList[ idx ]; + // Check if the field was actually changed, and that it hasn't changed on component + if( mixin( field.name ) == mixin( "newDesc." ~ field.name ) ) + { + // Copy the value into this description + mixin( "this."~field.name~" = newDesc."~field.name~";" ); + // Deserialize it for the component + mixin( "auto ser = "~field.serializer~".deserialize(newDesc."~field.name~");" ); + // Copy the new value to the component + mixin( "t."~field.name~" = ser;" ); + } + } + } + } + /// Create a component from a description. override T createInstance() const { @@ -246,14 +292,16 @@ private: // Check if the field was actually set if( mixin( field.name ) != mixin( "new SerializationDescription()." ~ field.name ) ) { + // Deserialize it for the component mixin( "auto ser = "~field.serializer~".deserialize(this."~field.name~");" ); + // Copy the new value to the component mixin( "comp."~field.name~" = ser;" ); } } } return comp; } - } + } // SerializationDescription /// Get a list of fields on the type Description.Field[] getFields( size_t idx = 0 )( Description.Field[] fields = [] ) diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 1e054ecc..65423fd8 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -93,7 +93,7 @@ public: Description[] children; @rename( "Components" ) @optional - Component[] components; + Component.Description[] components; } /// The current transform of the object. @@ -147,7 +147,7 @@ public: * Returns: * A new game object with components and info pulled from desc. */ - static GameObject create( Description desc ) + static GameObject create( const Description desc ) { GameObject obj; @@ -185,7 +185,7 @@ public: // Add components foreach( component; desc.components ) { - obj.addComponent( component ); + obj.addComponent( component.createInstance() ); } // Init components @@ -209,7 +209,7 @@ public: desc.prefabName = prefab ? prefab.name : null; desc.transform = transform.toDescription(); desc.children = children.map!( child => child.toDescription() ).array(); - desc.components = componentList.values.dup; + desc.components = componentList.values.map!( comp => cast()comp.description ).array(); return desc; } diff --git a/source/dash/core/prefabs.d b/source/dash/core/prefabs.d index 4d5c9a72..4e055bd2 100644 --- a/source/dash/core/prefabs.d +++ b/source/dash/core/prefabs.d @@ -100,7 +100,7 @@ public: * Returns: * The new GameObject from the Prefab. */ - GameObject createInstance() + GameObject createInstance() const { return GameObject.create( description ); } From 9fa460ab98f030bee31d2e27e26ebfa1c456d89f Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 25 Sep 2014 18:39:24 -0400 Subject: [PATCH 081/141] Code cleanup --- source/dash/components/component.d | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 791a08ab..bce0bca8 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -19,15 +19,16 @@ alias helper() = TypeTuple!(); */ abstract class Component { +private: + /// The description from the last creation/refresh. + @ignore + Description lastDesc; + public: /// The GameObject that owns this component. @ignore GameObject owner; - /// The description from the last creation/refresh. - @ignore - Description lastDesc; - /// The function called on initialization of the object. void initialize() { } /// Called on the update cycle. @@ -190,20 +191,12 @@ private: final class SerializationDescription : Description { mixin( { return reduce!( ( working, field ) { - string result = working; - // Append required import for variable type - if( field.mod ) - result ~= "import " ~ field.mod ~ ";\n"; - + if( field.mod ) working ~= "import " ~ field.mod ~ ";\n"; // Append variable attributes - if( field.attributes ) - result ~= "@(" ~ field.attributes ~ ")\n"; - + if( field.attributes ) working ~= "@(" ~ field.attributes ~ ")\n"; // Append variable declaration - result ~= field.typeName ~ " " ~ field.name ~ ";\n"; - - return result; + return working ~ field.typeName ~ " " ~ field.name ~ ";\n"; } )( "", fieldList ); } () ); // Generate serializers for the type From af748ebd348f58c7c639e242b7c190757ff30fc9 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 25 Sep 2014 20:34:37 -0400 Subject: [PATCH 082/141] Started implementing GameObject.refresh --- source/dash/components/component.d | 12 ++++++++- source/dash/core/gameobject.d | 40 +++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index bce0bca8..1e848863 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -92,7 +92,7 @@ public: /// Get a list of teh fields on a component. @ignore - abstract immutable(Field[]) fields() const @property; + abstract immutable(Field[]) fields() @property const; /// Create an instance of the component the description is for. abstract Component createInstance() const; @@ -103,6 +103,10 @@ public: /// Creates a description from a component. abstract const(Description) create( const Component comp ) const; + /// Get the type of the component the description is for. + @ignore + abstract ClassInfo componentType() @property const; + /// Serializers and deserializers mixin( perSerializationFormat!q{ // Overridable serializers @@ -294,6 +298,12 @@ private: } return comp; } + + /// Get the type of the component the description is for. + override ClassInfo componentType() @property const + { + return typeid(T); + } } // SerializationDescription /// Get a list of fields on the type diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 65423fd8..c13f0fb2 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -53,7 +53,7 @@ private: GameObject _parent; GameObject[] _children; Prefab _prefab; - Component[TypeInfo] componentList; + Component[ClassInfo] componentList; string _name; bool canChangeName; static uint nextId = 1; @@ -276,8 +276,8 @@ public: */ final void draw() { - foreach( component; componentList ) - component.draw(); + foreach( component; componentList ) + component.draw(); foreach( obj; children ) obj.draw(); @@ -288,8 +288,8 @@ public: */ final void shutdown() { - foreach( component; componentList ) - component.shutdown(); + foreach( component; componentList ) + component.shutdown(); foreach( obj; children ) obj.shutdown(); @@ -303,7 +303,30 @@ public: */ final void refresh( Description node ) { - //TODO: Implement + if( name != node.name ) + name = node.name; + + transform.refresh( node.transform ); + + bool[string] componentExists = zip( StoppingPolicy.shortest, componentList.byKey.map!( k => k.name ), false.repeat ).assocArray(); + + foreach( compDesc; node.components ) + { + // Found it! + componentExists[ compDesc.componentType.name ] = true; + + // Refresh, or add if it's new + if( auto comp = compDesc.componentType in componentList ) + comp.refresh( compDesc ); + else + addComponent( compDesc.createInstance() ); + } + + // Remove old components + foreach( key; componentExists.keys.filter!( k => componentExists[k] ) ) + componentList.remove( cast(ClassInfo)ClassInfo.find( key ) ); + + //TODO: Refresh children } /** @@ -429,6 +452,11 @@ private: scale = vec3f( desc.scale[] ); } + void refresh( Description desc ) + { + //TODO: Implement + } + /** * Default constructor, most often created by GameObjects. * From efd9112cb06633b547430e953ee689ab6c4f1be7 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Fri, 26 Sep 2014 12:24:18 -0400 Subject: [PATCH 083/141] Implemented refreshing of GO children --- source/dash/core/gameobject.d | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index c13f0fb2..f988baf1 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -308,8 +308,8 @@ public: transform.refresh( node.transform ); + // Refresh components bool[string] componentExists = zip( StoppingPolicy.shortest, componentList.byKey.map!( k => k.name ), false.repeat ).assocArray(); - foreach( compDesc; node.components ) { // Found it! @@ -326,7 +326,19 @@ public: foreach( key; componentExists.keys.filter!( k => componentExists[k] ) ) componentList.remove( cast(ClassInfo)ClassInfo.find( key ) ); - //TODO: Refresh children + // Refresh children + bool[string] childrenExist = zip( StoppingPolicy.shortest, _children.map!( child => child.name ), false.repeat ).assocArray(); + foreach( childDesc; node.children ) + { + // Found it! + childrenExist[ childDesc.name ] = true; + + // Refresh, or add if it's new + if( auto child = _children.filter!( child => child.name == childDesc.name ).front ) + child.refresh( childDesc ); + else + addChild( GameObject.create( childDesc ) ); + } } /** @@ -402,7 +414,6 @@ public: par.scene.idByName[ child.name ] = child.id; } } - } /** From ba8237630b25894f4fd14b722c0bf891358a358c Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Fri, 26 Sep 2014 12:31:10 -0400 Subject: [PATCH 084/141] Abstracted out findScene so that it may be reimplemented soon --- source/dash/core/gameobject.d | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index f988baf1..3a04239b 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -64,8 +64,19 @@ private: }.replaceMap( [ "$property": Type.stringof.toLower, "$type": Type.stringof ] ); package: + /// THIS IS ONLY SET IF THIS OBJECT IS SCENE _ROOT Scene scene; + /// Searche the parent tree until we find the scene object + Scene findScene() + { + // Get root object + GameObject par; + for( par = this; par.parent; par = par.parent ) { } + + return par.scene; + } + public: /** * The struct that will be directly deserialized from the ddl. @@ -385,11 +396,9 @@ public: newChild.parent = this; newChild.canChangeName = false; - // Get root object - GameObject par; - for( par = this; par.parent; par = par.parent ) { } + Scene currentScene = findScene(); - if( par.scene ) + if( currentScene ) { GameObject[] objectChildren; { @@ -410,8 +419,8 @@ public: // If adding to the scene, make sure all new children are in. foreach( child; objectChildren ) { - par.scene.objectById[ child.id ] = child; - par.scene.idByName[ child.name ] = child.id; + currentScene.objectById[ child.id ] = child; + currentScene.idByName[ child.name ] = child.id; } } } @@ -429,15 +438,13 @@ public: oldChild.canChangeName = true; oldChild.parent = null; - // Get root object - GameObject par; - for( par = this; par.parent; par = par.parent ) { } + Scene currentScene = findScene(); // Remove from scene. - if( par.scene ) + if( currentScene ) { - par.scene.objectById.remove( oldChild.id ); - par.scene.idByName.remove( oldChild.name ); + currentScene.objectById.remove( oldChild.id ); + currentScene.idByName.remove( oldChild.name ); } } } From cb3cb580a7e0ec44719f82cebc9d55fa2c33cfff Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 30 Sep 2014 15:12:14 -0400 Subject: [PATCH 085/141] Implemented refreshing on a per-component basis --- source/dash/components/assets.d | 2 +- source/dash/core/gameobject.d | 41 ++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/source/dash/components/assets.d b/source/dash/components/assets.d index e510ebf2..b6af7517 100644 --- a/source/dash/components/assets.d +++ b/source/dash/components/assets.d @@ -196,7 +196,7 @@ public: } /// A tuple of a resource and an asset -alias AssetResource = Tuple!( Resource, "resource", Asset, "asset" ); +alias AssetResource = Tuple!( Resource, "resource", Asset, "asset" ); abstract class Asset { diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 3a04239b..73043613 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -42,7 +42,7 @@ struct ObjectStateFlags } /// A tuple of a resource and a gameobject reference -alias GameObjectResource = Tuple!( Resource, "resource", GameObject, "object" ); +alias GameObjectResource = Tuple!( Resource, "resource", GameObject, "object" ); /** * Manages all components and transform in the world. Can be overridden. @@ -352,6 +352,45 @@ public: } } + /** + * Refresh the component of the given type. + * + * Params: + * componentType = The type of teh component to refresh. + * desc = The new description of the component. + */ + final void refreshComponent( ClassInfo componentType, Component.Description desc ) + { + if( auto comp = componentType in componentList ) + { + comp.refresh( desc ); + } + } + + /** + * Refresh the component of the given type. + * + * Params: + * ComponentType = The type of teh component to refresh. + * desc = The new description of the component. + */ + final void refreshComponent( ComponentType )( Component.Description desc ) + { + refreshComponent( typeid(ComponentType), desc ); + } + + /** + * Refresh the component of the given type. + * + * Params: + * componentName = The type of teh component to refresh. + * desc = The new description of the component. + */ + final void refreshComponent( string componentName, Component.Description desc ) + { + refreshComponent( getDescription( componentName ).componentType, desc ); + } + /** * Adds a component to the object. */ From 1d95640559d51d7703fcb3a8a8d149d4782aca87 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 30 Sep 2014 16:11:43 -0400 Subject: [PATCH 086/141] Implemented a proper changeName function for objects --- source/dash/core/gameobject.d | 41 ++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 61abbfc3..669894dd 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -138,12 +138,40 @@ public: mixin( Property!_parent ); /// All of the objects which list this as parent mixin( Property!_children ); - /// The name of the object. - mixin( Getter!_name ); /// The prefab that this object is based on. mixin( Property!_prefab ); - /// ditto - mixin( ConditionalSetter!( _name, q{canChangeName}, AccessModifier.Public ) ); + /// The name of the object. + mixin( Property!( _name, AccessModifier.Package ) ); + /// Change the name of the object. + void changeName( string newName ) + in + { + assert( newName && newName.length, "Invalid name given." ); + } + body + { + // Ignore an unchanging name. + if( name == newName ) + { + return; + } + else if( canChangeName || DGame.instance.currentState == EngineState.Editor ) + { + // Update mappings in the scene. + if( auto scene = findScene() ) + { + scene.idByName.remove( name ); + scene.idByName[ newName ] = id; + } + + // Change the name. + name = newName; + } + else + { + throw new Exception( "Unable to rename gameobject at this time." ); + } + } /// The ID of the object. immutable uint id; /// The current update settings @@ -317,7 +345,7 @@ public: final void refresh( Description node ) { if( name != node.name ) - name = node.name; + changeName( node.name ); transform.refresh( node.transform ); @@ -513,7 +541,8 @@ private: void refresh( Description desc ) { - //TODO: Implement + // TODO: Track if the transform actually changed. + this = desc; } /** From 13a2ac8987c828270bca82fb7bd97a1c3b4af23d Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 30 Sep 2014 16:13:45 -0400 Subject: [PATCH 087/141] Fixed refresh removing found components --- source/dash/core/gameobject.d | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 669894dd..341cd912 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -364,7 +364,7 @@ public: } // Remove old components - foreach( key; componentExists.keys.filter!( k => componentExists[k] ) ) + foreach( key; componentExists.keys.filter!( k => !componentExists[k] ) ) componentList.remove( cast(ClassInfo)ClassInfo.find( key ) ); // Refresh children @@ -380,6 +380,9 @@ public: else addChild( GameObject.create( childDesc ) ); } + + foreach( key; childrenExist.keys.filter!( k => !childrenExist[k] ) ) + childrenExist.remove( key ); } /** From b7538ad82d93f34ba079c09893749ab1b815c64b Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 30 Sep 2014 19:50:38 -0400 Subject: [PATCH 088/141] Fixed the docs link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 00509bf9..d60ea852 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Dash Logo](https://cloud.githubusercontent.com/assets/512416/2726786/6618d624-c5c2-11e3-9049-23637e5a1739.png)](https://github.com/Circular-Studios/Dash/wiki) -# [![Build Status](http://img.shields.io/travis/Circular-Studios/Dash/develop.svg?style=flat)](https://travis-ci.org/Circular-Studios/Dash) [![Docs](http://img.shields.io/badge/docs-ddoc-yellow.svg?style=flat)](http://circular-studios.github.io/Dash/docs/latest) [![Gitter Chat](http://img.shields.io/badge/chat-gitter-brightgreen.svg?style=flat)](https://gitter.im/Circular-Studios/Dash) [![Release](http://img.shields.io/github/release/Circular-Studios/Dash.svg?style=flat)](http://code.dlang.org/packages/dash) +# [![Build Status](http://img.shields.io/travis/Circular-Studios/Dash/develop.svg?style=flat)](https://travis-ci.org/Circular-Studios/Dash) [![Docs](http://img.shields.io/badge/docs-ddoc-yellow.svg?style=flat)](http://circularstudios.com/dash/api/latest/) [![Gitter Chat](http://img.shields.io/badge/chat-gitter-brightgreen.svg?style=flat)](https://gitter.im/Circular-Studios/Dash) [![Release](http://img.shields.io/github/release/Circular-Studios/Dash.svg?style=flat)](http://code.dlang.org/packages/dash) If you're reading this page, chances are you fall into one of the following categories: From 6d65393ae8bb04aa2cd0553f48e4180878bceb19 Mon Sep 17 00:00:00 2001 From: Berulacks Date: Thu, 2 Oct 2014 01:57:13 -0400 Subject: [PATCH 089/141] Fixed opBinary in keyboard (the type of 'keys' was changed to an associative array, rendering the old for loop void and prone to breaking everything) --- source/dash/utility/input.d | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index bbc50d94..81230372 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -394,6 +394,8 @@ private: buttonPrevious = buttonCurrent; buttonCurrent = buttonStaging; + logDebug(buttonCurrent); + foreach( state; diffButtons ) if( auto buttonEvent = state[ 0 ] in buttonEvents ) foreach( event; *buttonEvent ) @@ -627,9 +629,9 @@ public: { Tuple!( InputEnum, T )[] differences; - for( uint ii = 0; ii < keys.length; ++ii ) - if( this[ ii ] != other[ ii ] ) - differences ~= tuple( cast(InputEnum)ii, this[ ii ] ); + foreach( size_t index, T value; keys) + if( value != other[ index ] ) + differences ~= tuple( cast(InputEnum)index, value ); return differences; } From 7bb4449174a45137af8d7f6b39a48782d60d3c05 Mon Sep 17 00:00:00 2001 From: Berulacks Date: Thu, 2 Oct 2014 02:00:52 -0400 Subject: [PATCH 090/141] Removed an unnecessary debug line --- source/dash/utility/input.d | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index 81230372..289ee41d 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -394,8 +394,6 @@ private: buttonPrevious = buttonCurrent; buttonCurrent = buttonStaging; - logDebug(buttonCurrent); - foreach( state; diffButtons ) if( auto buttonEvent = state[ 0 ] in buttonEvents ) foreach( event; *buttonEvent ) From 27ed17371e190cabbe5ff981e7478c4916f3304d Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 2 Oct 2014 15:33:02 -0400 Subject: [PATCH 091/141] Implemented scene.refresh, some minor refactorings --- source/dash/components/assets.d | 24 +++++++---------- source/dash/components/component.d | 2 ++ source/dash/components/material.d | 6 ++--- source/dash/components/userinterface.d | 2 +- source/dash/core/gameobject.d | 1 + source/dash/core/scene.d | 34 ++++++++++++++++++++---- source/dash/utility/config.d | 2 +- source/dash/utility/data/serialization.d | 2 +- source/dash/utility/resources.d | 30 ++++++++++++--------- 9 files changed, 64 insertions(+), 39 deletions(-) diff --git a/source/dash/components/assets.d b/source/dash/components/assets.d index b6af7517..82ba87ef 100644 --- a/source/dash/components/assets.d +++ b/source/dash/components/assets.d @@ -75,30 +75,27 @@ public: DerelictASSIMP3.load(); // Make sure fbxs are supported. - assert(aiIsExtensionSupported(".fbx".toStringz), "fbx format isn't supported by assimp instance!"); + assert( aiIsExtensionSupported( ".fbx".toStringz ), "fbx format isn't supported by assimp instance!" ); + + enum aiImportOptions = aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType; // Load the unitSquare - unitSquare = new Mesh( new MeshAsset( Resource( "" ), aiImportFileFromMemory( + unitSquare = new Mesh( new MeshAsset( internalResource, aiImportFileFromMemory( unitSquareMesh.toStringz(), unitSquareMesh.length, - aiProcess_CalcTangentSpace | aiProcess_Triangulate | - aiProcess_JoinIdenticalVertices | aiProcess_SortByPType, - "obj" ).mMeshes[0] ) ); + aiImportOptions, "obj" ).mMeshes[0] ) ); foreach( file; scanDirectory( Resources.Meshes ) ) { // Load mesh - const aiScene* scene = aiImportFile( file.fullPath.toStringz, - aiProcess_CalcTangentSpace | aiProcess_Triangulate | - aiProcess_JoinIdenticalVertices | aiProcess_SortByPType ); + const aiScene* scene = aiImportFile( file.fullPath.toStringz, aiImportOptions ); assert( scene, "Failed to load scene file '" ~ file.fullPath ~ "' Error: " ~ aiGetErrorString().fromStringz() ); - // If animation data, add animation - if( file.baseFileName in meshes ) - logWarning( "Mesh ", file.baseFileName, " exsists more than once." ); - // Add mesh if( scene.mNumMeshes > 0 ) { + if( file.baseFileName in meshes ) + logWarning( "Mesh ", file.baseFileName, " exsists more than once." ); + auto newMesh = new MeshAsset( file, scene.mMeshes[ 0 ] ); if( scene.mNumAnimations > 0 ) @@ -195,9 +192,6 @@ public: } } -/// A tuple of a resource and an asset -alias AssetResource = Tuple!( Resource, "resource", Asset, "asset" ); - abstract class Asset { private: diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 1e848863..7da1ef31 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -280,6 +280,8 @@ private: override T createInstance() const { T comp = new T; + comp.lastDesc = cast()this; + foreach( fieldName; __traits( allMembers, T ) ) { enum idx = fieldList.map!(f => f.name).countUntil( fieldName ); diff --git a/source/dash/components/material.d b/source/dash/components/material.d index db806144..c6d112e7 100644 --- a/source/dash/components/material.d +++ b/source/dash/components/material.d @@ -34,7 +34,7 @@ public: */ this( string name = "" ) { - super( Resource( "" ) ); + super( internalResource ); diffuse = specular = defaultTex; normal = defaultNormal; this.name = name; @@ -207,7 +207,7 @@ class Texture : AssetRef!TextureAsset static Texture def; if( !def ) - def = new Texture( new TextureAsset( [cast(ubyte)0, cast(ubyte)0, cast(ubyte)0, cast(ubyte)255].ptr, Resource( "" ) ) ); + def = new Texture( new TextureAsset( [cast(ubyte)0, cast(ubyte)0, cast(ubyte)0, cast(ubyte)255].ptr, internalResource ) ); return def; } @@ -220,7 +220,7 @@ class Texture : AssetRef!TextureAsset static Texture def; if( !def ) - def = new Texture( new TextureAsset( [cast(ubyte)255, cast(ubyte)127, cast(ubyte)127, cast(ubyte)255].ptr, Resource( "" ) ) ); + def = new Texture( new TextureAsset( [cast(ubyte)255, cast(ubyte)127, cast(ubyte)127, cast(ubyte)255].ptr, internalResource ) ); return def; } diff --git a/source/dash/components/userinterface.d b/source/dash/components/userinterface.d index 4b0474e2..e610d2bc 100644 --- a/source/dash/components/userinterface.d +++ b/source/dash/components/userinterface.d @@ -177,7 +177,7 @@ public: _height = h; glBuffer = new ubyte[_width*_height*4]; - super( cast(ubyte*)null, Resource( "" ) ); + super( cast(ubyte*)null, internalResource ); version( Windows ) { diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index 341cd912..b5c69975 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -43,6 +43,7 @@ struct ObjectStateFlags /// A tuple of a resource and a gameobject reference alias GameObjectResource = Tuple!( Resource, "resource", GameObject, "object" ); +GameObjectResource[][Resource] objectsByResource; /** * Manages all components and transform in the world. Can be overridden. diff --git a/source/dash/core/scene.d b/source/dash/core/scene.d index d3aa5c9b..7d589b8f 100644 --- a/source/dash/core/scene.d +++ b/source/dash/core/scene.d @@ -16,7 +16,6 @@ final class Scene { private: GameObject _root; - GameObject[][Resource] goResources; package: GameObject[uint] objectById; @@ -52,9 +51,7 @@ public: { auto newObj = GameObject.create( desc ); _root.addChild( newObj ); - goResources[ file ] ~= newObj; - - logDebug( "Adding object ", newObj.name, " with diffuse: ", newObj.material.diffuse ); + objectsByResource[ file ] ~= GameObjectResource( file, newObj ); } } } @@ -91,7 +88,34 @@ public: final void refresh() { // Iterate over each file, and it's objects - //TODO: Implement + foreach_reverse( file; objectsByResource.keys ) + { + auto objReses = objectsByResource[ file ]; + + if( file.exists() ) + { + if( file.needsRefresh() ) + { + auto descs = deserializeMultiFile!( GameObject.Description )( file ); + assert( descs.length == objReses.length, "Adding or removing objects from a file is currently unsupported." ); + + foreach( i, objRes; objReses ) + { + objRes.object.refresh( descs[ i ] ); + } + } + } + else + { + foreach( objRes; objReses ) + { + objRes.object.shutdown(); + removeChild( objRes.object ); + } + + objectsByResource.remove( file ); + } + } } /** diff --git a/source/dash/utility/config.d b/source/dash/utility/config.d index 3eebcce8..bbe05488 100644 --- a/source/dash/utility/config.d +++ b/source/dash/utility/config.d @@ -85,7 +85,7 @@ public: static: @ignore - private Resource resource = Resource( "" ); + private Resource resource = internalResource; void initialize() { diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index 26fecff8..26c82505 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -37,7 +37,7 @@ Tuple!( T, Resource ) deserializeFileByName( T )( string fileName, Serialization auto files = fileName.dirName.scanDirectory( fileName.baseName ~ ".*" ); return files.empty - ? tuple( T.init, Resource( "" ) ) + ? tuple( T.init, internalResource ) : tuple( deserializeFile!T( files.front ), files.front ); } diff --git a/source/dash/utility/resources.d b/source/dash/utility/resources.d index 476fe092..ddd5fc87 100644 --- a/source/dash/utility/resources.d +++ b/source/dash/utility/resources.d @@ -49,6 +49,8 @@ Resource[] scanDirectory( string path, string pattern = "" ) .array(); } +enum internalResource = Resource( true ); + /** * Represents a resource on the file system. */ @@ -65,12 +67,8 @@ public: */ this( string filePath ) { - if( filePath.length == 0 ) - invalid = true; - else if( filePath.isFile() ) - _fullPath = filePath.absolutePath().buildNormalizedPath(); - else - throw new Exception( "invalid file name." ); + assert( filePath.isFile(), "Invalid file name." ); + _fullPath = filePath.absolutePath().buildNormalizedPath(); } /** @@ -95,11 +93,11 @@ public: /// The extensino of the file. @property string extension() { return _fullPath.extension(); } /// Checks if the file still exists. - bool exists() @property { return invalid || fullPath.isFile(); } + bool exists() @property { return isInternal || fullPath.isFile(); } /// Converts to a std.stdio.File File* getFile( string mode = "r" ) { - if( invalid ) + if( isInternal ) return null; if( !file ) @@ -115,7 +113,7 @@ public: */ ubyte[] read() { - if( invalid ) + if( isInternal ) return []; markRead(); @@ -129,7 +127,7 @@ public: */ string readText() { - if( invalid ) + if( isInternal ) return ""; markRead(); @@ -143,7 +141,7 @@ public: */ bool needsRefresh() { - if( invalid ) + if( isInternal ) return false; return fullPath.timeLastModified > timeRead; @@ -151,13 +149,19 @@ public: private: string _fullPath; - bool invalid; + bool isInternal; std.stdio.File* file; SysTime timeRead; + this( bool internal ) + { + isInternal = internal; + _fullPath = "__internal"; + } + void markRead() { - if( !invalid ) + if( !isInternal ) timeRead = fullPath.timeLastModified(); } } From a92f70e70c7730106b7fe06d86ad0993d5a8346f Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 7 Oct 2014 09:18:32 -0400 Subject: [PATCH 092/141] Fixed openssl version issues --- dub.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dub.json b/dub.json index 39e0b030..ad78a629 100644 --- a/dub.json +++ b/dub.json @@ -25,7 +25,7 @@ "gfm:sdl2": "==1.3.1", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", - "vibe-d": "0.7.21-beta.4", + "vibe-d": "0.7.21-rc.2", "x11": { "version": "~>1.0", "optional": true } }, From 77044590469e55a0b348defdd1ff2f124987cc8d Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 7 Oct 2014 09:18:32 -0400 Subject: [PATCH 093/141] Fixed openssl version issues --- dub.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dub.json b/dub.json index 2cc5f036..5905f6d6 100644 --- a/dub.json +++ b/dub.json @@ -24,7 +24,7 @@ "gl3n": "==1.0.0", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", - "vibe-d": "0.7.21-beta.4", + "vibe-d": "0.7.21-rc.2", "x11": { "version": "~>1.0", "optional": true } }, From c0af72f46199439c6557277501d123669e1986c6 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 30 Sep 2014 16:50:41 -0400 Subject: [PATCH 094/141] Switched event responses to be returned instead of callbacks, added events module for more verbose event registration --- source/dash/editor/editor.d | 79 +++++++++++++++++++------------------ source/dash/editor/events.d | 9 +++++ 2 files changed, 49 insertions(+), 39 deletions(-) create mode 100644 source/dash/editor/events.d diff --git a/source/dash/editor/editor.d b/source/dash/editor/editor.d index dcaf1ef1..afa52810 100644 --- a/source/dash/editor/editor.d +++ b/source/dash/editor/editor.d @@ -1,9 +1,10 @@ module dash.editor.editor; import dash.core.dgame; -import dash.editor.websockets; +import dash.editor.websockets, dash.editor.events; import dash.utility.output; import vibe.data.json; +import vibe.http.status: HTTPStatus; import std.uuid, std.typecons; /** @@ -16,9 +17,9 @@ class Editor public: // Event handlers alias JsonEventHandler = void delegate( Json ); - alias JsonEventResponseHandler = void delegate( Json, void delegate( Json ) ); + alias JsonEventResponseHandler = Json delegate( Json ); alias TypedEventHandler( DataType ) = void delegate( DataType ); - alias TypedEventResponseHandler( ResponseType, DataType ) = void delegate( DataType, void delegate( ResponseType ) ); + alias TypedEventResponseHandler( ResponseType, DataType ) = ResponseType delegate( DataType ); /** * Initializes the editor with a DGame instance. @@ -151,17 +152,14 @@ public: { void handler( EventMessage msg ) { - void writeback( Json json ) - { - EventMessage newMsg; - newMsg.key = CallbackMessageKey; - newMsg.value = json; - newMsg.callbackId = msg.callbackId; + Json res = event( msg.value ); - server.send( newMsg ); - } + EventMessage newMsg; + newMsg.key = CallbackMessageKey; + newMsg.value = res; + newMsg.callbackId = msg.callbackId; - event( msg.value, &writeback ); + server.send( newMsg ); } return registerInternalMessageHandler( key, &handler ); @@ -200,22 +198,19 @@ public: { void handler( EventMessage msg ) { - void writeback( ResponseType res ) - { - EventMessage newMsg; - newMsg.key = CallbackMessageKey; - newMsg.value = res.serializeToJsonString(); - newMsg.callbackId = msg.callbackId; + ResponseType res = event( msg.value.deserializeJson!DataType ); - server.send( newMsg ); - } + EventMessage newMsg; + newMsg.key = CallbackMessageKey; + newMsg.value = res.serializeToJsonString(); + newMsg.callbackId = msg.callbackId; - event( msg.value.deserializeJson!DataType, &writeback ); + server.send( newMsg ); } return registerInternalMessageHandler( key, &handler ); } - static assert(is(typeof( registerEventHandler!( string, string )( "key", ( data, writeback ) { } ) ))); + static assert(is(typeof( registerEventHandler!( string, string )( "key", ( data ) { return data; } ) ))); /** * Unregisters an event callback. @@ -238,12 +233,6 @@ public: } } -package: - final void queueEvent( EventMessage msg ) - { - pendingEvents ~= msg; - } - protected: DGame game; WebSocketServer server; @@ -284,8 +273,10 @@ protected: } } -private: - enum CallbackMessageKey = "__callback__"; +package: + /// The message key for callbacks + package enum CallbackMessageKey = "__callback__"; + alias InternalEventHandler = void delegate( EventMessage ); alias EventHandlerTuple = Tuple!(UUID, "id", InternalEventHandler, "handler"); @@ -293,6 +284,11 @@ private: EventHandlerTuple[][string] eventHandlers; InternalEventHandler[UUID] callbacks; + final void queueEvent( EventMessage msg ) + { + pendingEvents ~= msg; + } + /// Register a final UUID registerInternalMessageHandler( string key, InternalEventHandler handler ) { @@ -306,7 +302,20 @@ private: callbacks[ id ] = handler; } - /// Handle an event that is a callback. + final void registerDefaultEvents() + { + registerInternalMessageHandler( CallbackMessageKey, &handleCallback ); + + // Test handler, responds with request + registerEventHandler( "loopback", json => json ); + // Triggers an engine refresh + registerEventHandler!( int, Json )( "dgame:refresh", ( json ) { + game.currentState = EngineState.Refresh; + return HTTPStatus.ok; + } ); + } + + /// Handles callback messages final void handleCallback( EventMessage msg ) { // If it's a callback, dispatch it as such. @@ -321,12 +330,4 @@ private: logFatal( "Callback reference lost: ", msg.callbackId ); } } - - final void registerDefaultEvents() - { - registerInternalMessageHandler( CallbackMessageKey, &handleCallback ); - - registerEventHandler( "dgame:refresh", ( json ) { game.currentState = EngineState.Refresh; } ); - registerEventHandler( "loopback", ( json, cb ) => cb( json ) ); - } } diff --git a/source/dash/editor/events.d b/source/dash/editor/events.d new file mode 100644 index 00000000..e9929b9c --- /dev/null +++ b/source/dash/editor/events.d @@ -0,0 +1,9 @@ +module dash.editor.events; +import dash.editor.editor, dash.editor.websockets; +import dash.core.dgame; + +import vibe.http.status: HTTPStatus; + + + +private: From 6348d5c3864a6b4bb2f837ffc136e65ec64e75b1 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 30 Sep 2014 17:37:32 -0400 Subject: [PATCH 095/141] Removed all Json-based event handlers/senders, added response structure --- source/dash/editor/editor.d | 115 ++++++------------------------------ source/dash/editor/events.d | 58 +++++++++++++++++- 2 files changed, 73 insertions(+), 100 deletions(-) diff --git a/source/dash/editor/editor.d b/source/dash/editor/editor.d index afa52810..0e95beee 100644 --- a/source/dash/editor/editor.d +++ b/source/dash/editor/editor.d @@ -16,10 +16,8 @@ class Editor { public: // Event handlers - alias JsonEventHandler = void delegate( Json ); - alias JsonEventResponseHandler = Json delegate( Json ); - alias TypedEventHandler( DataType ) = void delegate( DataType ); - alias TypedEventResponseHandler( ResponseType, DataType ) = ResponseType delegate( DataType ); + alias EventHandler( DataType ) = void delegate( DataType ); + alias EventResponseHandler( DataType, ResponseType ) = ResponseType delegate( DataType ); /** * Initializes the editor with a DGame instance. @@ -63,14 +61,15 @@ public: * key = The key of the event. * value = The data along side it. */ - final void send( string key, Json value ) + final void send( DataType )( string key, DataType value ) { EventMessage msg; msg.key = key; - msg.value = value; + msg.value = value.serializeToJson(); server.send( msg ); } + static assert(is(typeof( send( "key", "data" ) ))); /** * Sends a message to all attached editors. @@ -80,45 +79,19 @@ public: * value = The data along side it. * cb = The callback to call when a response is received. */ - final void send( string key, Json value, JsonEventHandler cb ) + final void send( ResponseType = EventResponse, DataType )( string key, DataType value, EventHandler!ResponseType cb ) { UUID cbId = randomUUID(); - registerCallbackHandler( cbId, msg => cb( msg.value ) ); + registerCallbackHandler( cbId, msg => cb( msg.value.deserializeJson!ResponseType ) ); EventMessage msg; msg.key = key; - msg.value = value; + msg.value = value.serializeToJson(); msg.callbackId = cbId.toString(); server.send( msg ); } - - /** - * Sends a message to all attached editors. - * - * Params: - * key = The key of the event. - * value = The data along side it. - */ - final void send( DataType )( string key, DataType value ) - { - send( key, value.serializeToJson() ); - } - static assert(is(typeof( send!( string )( "key", "data" ) ))); - - /** - * Sends a message to all attached editors. - * - * Params: - * key = The key of the event. - * value = The data along side it. - * cb = The callback to call when a response is received. - */ - final void send( ResponseType, DataType )( string key, DataType value, TypedEventHandler!ResponseType cb ) - { - send( key, value.serializeToJson(), ( Json json ) { cb( json.deserializeJson!ResponseType ); } ); - } - static assert(is(typeof( send!( string, string )( "key", "data", ( response ) { } ) ))); + static assert(is(typeof( send!( string )( "key", "data", ( string response ) { } ) ))); /** * Registers an event callback, for when an event with the given key is received. @@ -129,15 +102,11 @@ public: * * Returns: The ID of the event, so it can be unregistered later. */ - final UUID registerEventHandler( string key, JsonEventHandler event ) + final UUID registerEventHandler( DataType )( string key, EventHandler!DataType event ) { - void handler( EventMessage msg ) - { - event( msg.value ); - } - - return registerInternalMessageHandler( key, &handler ); + return registerInternalMessageHandler( key, msg => event( msg.value.deserializeJson!DataType ) ); } + static assert(is(typeof( registerEventHandler!string( "key", ( string resp ) { } ) ))); /** * Registers an event callback, for when an event with the given key is received. @@ -148,53 +117,7 @@ public: * * Returns: The ID of the event, so it can be unregistered later. */ - final UUID registerEventHandler( string key, JsonEventResponseHandler event ) - { - void handler( EventMessage msg ) - { - Json res = event( msg.value ); - - EventMessage newMsg; - newMsg.key = CallbackMessageKey; - newMsg.value = res; - newMsg.callbackId = msg.callbackId; - - server.send( newMsg ); - } - - return registerInternalMessageHandler( key, &handler ); - } - - /** - * Registers an event callback, for when an event with the given key is received. - * - * Params: - * key = The key of the event. - * event = The handler to call. - * - * Returns: The ID of the event, so it can be unregistered later. - */ - final UUID registerEventHandler( DataType )( string key, TypedEventHandler!DataType event ) - { - void handler( EventMessage msg ) - { - event( msg.value.deserializeJson!DataType() ); - } - - return registerInternalMessageHandler( key, &handler ); - } - static assert(is(typeof( registerEventHandler!( string )( "key", ( data ) { } ) ))); - - /** - * Registers an event callback, for when an event with the given key is received. - * - * Params: - * key = The key of the event. - * event = The handler to call. - * - * Returns: The ID of the event, so it can be unregistered later. - */ - final UUID registerEventHandler( ResponseType, DataType )( string key, TypedEventResponseHandler!( ResponseType, DataType ) event ) + final UUID registerEventHandler( DataType, ResponseType )( string key, EventResponseHandler!( DataType, ResponseType ) event ) { void handler( EventMessage msg ) { @@ -210,7 +133,7 @@ public: return registerInternalMessageHandler( key, &handler ); } - static assert(is(typeof( registerEventHandler!( string, string )( "key", ( data ) { return data; } ) ))); + static assert(is(typeof( registerEventHandler!( string, string )( "key", data => data ) ))); /** * Unregisters an event callback. @@ -307,12 +230,10 @@ package: registerInternalMessageHandler( CallbackMessageKey, &handleCallback ); // Test handler, responds with request - registerEventHandler( "loopback", json => json ); - // Triggers an engine refresh - registerEventHandler!( int, Json )( "dgame:refresh", ( json ) { - game.currentState = EngineState.Refresh; - return HTTPStatus.ok; - } ); + registerEventHandler!( Json, Json )( "loopback", json => json ); + + registerGameEvents( this, game ); + registerObjectEvents( this, game ); } /// Handles callback messages diff --git a/source/dash/editor/events.d b/source/dash/editor/events.d index e9929b9c..5ae9f6bf 100644 --- a/source/dash/editor/events.d +++ b/source/dash/editor/events.d @@ -1,9 +1,61 @@ module dash.editor.events; import dash.editor.editor, dash.editor.websockets; -import dash.core.dgame; +import dash.core, dash.components.component; -import vibe.http.status: HTTPStatus; +import vibe.data.json; +import std.typecons; +public: +/// Status of a request +enum Status +{ + ok, + warning, + error, +} +/// Easy to handle response struct. +struct EventResponse +{ + Status status; + string message; +} +/// Shortcut to generate response. +EventResponse res( Status s, string m ) +{ + return EventResponse( s, m ); +} +/// Basic ok response. +enum ok = EventResponse( Status.ok, "success" ); +package: +void registerGameEvents( Editor ed, DGame game ) +{ + // Triggers an engine refresh + ed.registerEventHandler!( Json, EventResponse )( "dgame:refresh", ( Json json ) { + game.currentState = EngineState.Refresh; + return ok; + } ); +} -private: +void registerObjectEvents( Editor ed, DGame game ) +{ + static struct RefreshRequest + { + string objectName; + GameObject.Description description; + } + ed.registerEventHandler!( RefreshRequest, EventResponse )( "object:refresh", ( req ) { + game.activeScene[ req.objectName ].refresh( req.description ); + return ok; + } ); + + static struct ComponentRefreshRequest + { + string objectName; + string componentName; + Component.Description description; + } + ed.registerEventHandler!ComponentRefreshRequest( "object:component:refresh", ( req ) { + + } ); +} From 99f820d46fc0811f0085ce69c381aa4b8704b535 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 30 Sep 2014 17:50:18 -0400 Subject: [PATCH 096/141] Fleshed out refresh events, added warning and error responses --- source/dash/editor/events.d | 43 ++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/source/dash/editor/events.d b/source/dash/editor/events.d index 5ae9f6bf..31378a22 100644 --- a/source/dash/editor/events.d +++ b/source/dash/editor/events.d @@ -3,7 +3,7 @@ import dash.editor.editor, dash.editor.websockets; import dash.core, dash.components.component; import vibe.data.json; -import std.typecons; +import std.typecons, std.functional; public: /// Status of a request @@ -24,8 +24,18 @@ EventResponse res( Status s, string m ) { return EventResponse( s, m ); } -/// Basic ok response. -enum ok = EventResponse( Status.ok, "success" ); + +struct response +{ + @disable this(); + + /// Basic ok response. + enum ok = EventResponse( Status.ok, "success" ); + /// Warning response + alias warning = partial!( res, Status.warning ); + /// Error response + alias error = partial!( res, Status.error ); +} package: void registerGameEvents( Editor ed, DGame game ) @@ -33,29 +43,46 @@ void registerGameEvents( Editor ed, DGame game ) // Triggers an engine refresh ed.registerEventHandler!( Json, EventResponse )( "dgame:refresh", ( Json json ) { game.currentState = EngineState.Refresh; - return ok; + return response.ok; } ); } void registerObjectEvents( Editor ed, DGame game ) { + // Refresh an object static struct RefreshRequest { string objectName; GameObject.Description description; } ed.registerEventHandler!( RefreshRequest, EventResponse )( "object:refresh", ( req ) { - game.activeScene[ req.objectName ].refresh( req.description ); - return ok; + if( auto obj = game.activeScene[ req.objectName ] ) + { + obj.refresh( req.description ); + return response.ok; + } + else + { + return response.error( "Object " ~ req.objectName ~ " not found." ); + } } ); + // Refresh a component static struct ComponentRefreshRequest { string objectName; string componentName; Component.Description description; } - ed.registerEventHandler!ComponentRefreshRequest( "object:component:refresh", ( req ) { - + ed.registerEventHandler!( ComponentRefreshRequest, EventResponse )( "object:component:refresh", ( req ) { + if( auto obj = game.activeScene[ req.objectName ] ) + { + obj.refreshComponent( req.componentName, req.description ); + return response.ok; + } + else + { + return response.error( "Object " ~ req.objectName ~ " not found." ); + } } ); } From ac143833a20860e80f92b459895c3209e8f1ce8c Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 30 Sep 2014 17:57:17 -0400 Subject: [PATCH 097/141] Added data field to EventResponse, implemented "dgame:scene:get_objects" --- source/dash/editor/events.d | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/source/dash/editor/events.d b/source/dash/editor/events.d index 31378a22..d1c28c58 100644 --- a/source/dash/editor/events.d +++ b/source/dash/editor/events.d @@ -18,11 +18,12 @@ struct EventResponse { Status status; string message; + Json data; } /// Shortcut to generate response. -EventResponse res( Status s, string m ) +EventResponse res( DataType = Json )( Status s, string m = "success", DataType d = DataType.init ) { - return EventResponse( s, m ); + return EventResponse( s, m, d.serializeToJson() ); } struct response @@ -30,7 +31,7 @@ struct response @disable this(); /// Basic ok response. - enum ok = EventResponse( Status.ok, "success" ); + alias ok = partial!( res, Status.ok ); /// Warning response alias warning = partial!( res, Status.warning ); /// Error response @@ -41,10 +42,14 @@ package: void registerGameEvents( Editor ed, DGame game ) { // Triggers an engine refresh - ed.registerEventHandler!( Json, EventResponse )( "dgame:refresh", ( Json json ) { + ed.registerEventHandler!( Json, EventResponse )( "dgame:refresh", ( _ ) { game.currentState = EngineState.Refresh; return response.ok; } ); + + ed.registerEventHandler!( Json, EventResponse )( "dgame:scene:get_objects", ( _ ) { + return response.ok( "success", game.activeScene.objects ); + } ); } void registerObjectEvents( Editor ed, DGame game ) From 24cc1a25d667166a61d972cb65abe43186730995 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 30 Sep 2014 19:17:27 -0400 Subject: [PATCH 098/141] Fixed some small things based on testing results --- source/dash/components/animation.d | 20 +++++++++++++++++--- source/dash/components/component.d | 17 +++++++++++++++-- source/dash/editor/events.d | 6 +++--- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/source/dash/components/animation.d b/source/dash/components/animation.d index 47ed9104..d720e36b 100644 --- a/source/dash/components/animation.d +++ b/source/dash/components/animation.d @@ -10,6 +10,8 @@ import derelict.assimp3.assimp; import std.string: fromStringz; import std.conv: to; +mixin( registerComponents!() ); + /** * Animation object which handles all animation specific to the gameobject */ @@ -17,34 +19,46 @@ class Animation : Component { private: /// Asset animation that the gameobject is animating based off of + @ignore AnimationData _animationData; /// Current animation out of all the animations in the asset animation + @ignore int _currentAnim; /// Current time of the animation + @ignore float _currentAnimTime; /// Bone transforms for the current pose + @ignore mat4f[] _currBoneTransforms; /// If the gameobject should be animating + @ignore bool _animating; /// Animation to return to if _animateOnce is true + @ignore int _returnAnimation; /// If the animation is animating once, then returning to _returnAnimation + @ignore bool _animateOnce; public: /// Bone transforms for the current pose (Passed to the shader) mixin( Property!_currBoneTransforms ); + this() + { + _currentAnim = 0; + _currentAnimTime = 0.0f; + _animating = true; + } + /** * Create animation object based on asset animation */ this( AnimationData assetAnimation ) { - _currentAnim = 0; - _currentAnimTime = 0.0f; + this(); _animationData = assetAnimation; - _animating = true; } /** diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 7da1ef31..373b9f83 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -42,6 +42,11 @@ public: * Create a description from the this parameter. */ final const(Description) description() @property + in + { + assert( getDescription( typeid(this) ), "No description found for type: " ~ typeid(this).name ); + } + body { return getDescription( typeid(this) ).create( this ); } @@ -116,7 +121,15 @@ public: // Serializers for vibe final $type to$type() const { - return getDescription( typeid(this) ).serializeDescriptionTo$type( cast()this ); + if( auto desc = getDescription( componentType ) ) + { + return desc.serializeDescriptionTo$type( cast()this ); + } + else + { + logError( "Description of type ", typeid(this).name, " not found! Did you forget a mixin(registerComponents!())?" ); + return $type(); + } } static Description from$type( $type data ) { @@ -161,7 +174,7 @@ enum registerComponents( string modName = __MODULE__ ) = q{ import mod = $modName; // Foreach definition in the module (classes, structs, functions, etc.) - foreach( memberName; __traits( allMembers, mod ) ) + foreach( memberName; __traits( allMembers, mod ) ) static if( __traits( compiles, __traits( getMember, mod, memberName ) ) ) { // Alais to the member alias member = helper!( __traits( getMember, mod, memberName ) ); diff --git a/source/dash/editor/events.d b/source/dash/editor/events.d index d1c28c58..72c2ae82 100644 --- a/source/dash/editor/events.d +++ b/source/dash/editor/events.d @@ -9,9 +9,9 @@ public: /// Status of a request enum Status { - ok, - warning, - error, + ok = 0, + warning = 1, + error = 2, } /// Easy to handle response struct. struct EventResponse From d84fd376ea4c92cc463dcc174f563cbdb3127d28 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 7 Oct 2014 09:18:32 -0400 Subject: [PATCH 099/141] Fixed openssl version issues --- dub.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dub.json b/dub.json index 2cc5f036..5905f6d6 100644 --- a/dub.json +++ b/dub.json @@ -24,7 +24,7 @@ "gl3n": "==1.0.0", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", - "vibe-d": "0.7.21-beta.4", + "vibe-d": "0.7.21-rc.2", "x11": { "version": "~>1.0", "optional": true } }, From 88394f81013b388b9b75552c41198e323a2cd1b2 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 7 Oct 2014 09:50:40 -0400 Subject: [PATCH 100/141] Fixed spacing --- source/dash/graphics/adapters/sdl.d | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 193b3571..0cfd5afe 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -73,14 +73,14 @@ public: loadProperties(); window.setSize( width, height ); - resizeDefferedRenderBuffer(); + resizeDefferedRenderBuffer(); glViewport( 0, 0, width, height ); } override void refresh() { resize(); - swapBuffers(); + swapBuffers(); } override void swapBuffers() @@ -96,7 +96,7 @@ public: override void closeWindow() { - window.close(); + window.close(); } @@ -126,14 +126,14 @@ public: break; } - //On keypress + //On keypress case SDL_KEYDOWN: - Keyboard.setButtonState( cast(Keyboard.Buttons)event.key.keysym.sym, true ); - break; + Keyboard.setButtonState( cast(Keyboard.Buttons)event.key.keysym.sym, true ); + break; - //On keyrelease + //On keyrelease case SDL_KEYUP: - Keyboard.setButtonState( cast(Keyboard.Buttons)event.key.keysym.sym, false ); + Keyboard.setButtonState( cast(Keyboard.Buttons)event.key.keysym.sym, false ); break; // Handle quitting. @@ -142,12 +142,12 @@ public: break; case SDL_MOUSEWHEEL: - Mouse.setAxisState( Mouse.Axes.ScrollWheel, Mouse.getAxisState( Mouse.Axes.ScrollWheel ) + ( ( cast(int)event.wheel.y >> 16 ) / 120 ) ); - break; + Mouse.setAxisState( Mouse.Axes.ScrollWheel, Mouse.getAxisState( Mouse.Axes.ScrollWheel ) + ( ( cast(int)event.wheel.y >> 16 ) / 120 ) ); + break; case SDL_APP_TERMINATING: - shutdown(); - break; + shutdown(); + break; case SDL_APP_LOWMEMORY: case SDL_APP_WILLENTERBACKGROUND: From 024c92e75642dad394adf411920ddae6c3d9edcf Mon Sep 17 00:00:00 2001 From: Berulacks Date: Wed, 8 Oct 2014 15:54:58 -0400 Subject: [PATCH 101/141] Fixed vsync in SDL The SDL GL swap interval now properly reflects the value of config.graphics.vsync --- source/dash/graphics/adapters/sdl.d | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 0cfd5afe..ffb30ad8 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -56,6 +56,17 @@ public: glContext.makeCurrent(); DerelictGL3.reload(); + + if(config.graphics.vsync) + { + SDL_GL_SetSwapInterval(1); + logDebug("vsync enabled!"); + } + else + { + SDL_GL_SetSwapInterval(0); + logDebug("vsync disabled!"); + } } override void shutdown() From efc27133f69e81aa69deb728ada190126957e91c Mon Sep 17 00:00:00 2001 From: Berulacks Date: Wed, 8 Oct 2014 15:58:44 -0400 Subject: [PATCH 102/141] Fixed spacing in input.d --- source/dash/utility/input.d | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index 289ee41d..6c881839 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -333,11 +333,11 @@ public: //alias Keyboard; version(UseSDL2) - alias Keyboard = InputSystem!( KeyboardButtonsSDL, void ); + alias Keyboard = InputSystem!( KeyboardButtonsSDL, void ); else - alias Keyboard = InputSystem!( KeyboardButtonsWin, void ); + alias Keyboard = InputSystem!( KeyboardButtonsWin, void ); alias Mouse = InputSystem!( MouseButtons, MouseAxes ); @@ -595,10 +595,10 @@ public: ref typeof(this) opAssign( const ref typeof(this) other ) { - foreach(size_t index, T value; other.keys) - { - keys[index] = value; - } + foreach(size_t index, T value; other.keys) + { + keys[index] = value; + } return this; } @@ -606,13 +606,13 @@ public: T opIndex( size_t keyCode ) { - //If the key being pressed doesn't have - //an entry in keys, add it, and set it - //to the default value - if(!(keyCode in keys)) - keys[ keyCode ] = T(); + //If the key being pressed doesn't have + //an entry in keys, add it, and set it + //to the default value + if(!(keyCode in keys)) + keys[ keyCode ] = T(); - return keys[ keyCode ]; + return keys[ keyCode ]; } @@ -627,9 +627,9 @@ public: { Tuple!( InputEnum, T )[] differences; - foreach( size_t index, T value; keys) - if( value != other[ index ] ) - differences ~= tuple( cast(InputEnum)index, value ); + foreach( size_t index, T value; keys) + if( value != other[ index ] ) + differences ~= tuple( cast(InputEnum)index, value ); return differences; } From 2fc3a6ae6d02209ceb9c1beebf0ce0f3bc9740a6 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Fri, 10 Oct 2014 12:29:57 -0400 Subject: [PATCH 103/141] Added better version support to choosing an adapter --- dub.json | 3 +-- source/dash/graphics/graphics.d | 30 ++++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/dub.json b/dub.json index ad78a629..63ddb17f 100644 --- a/dub.json +++ b/dub.json @@ -38,8 +38,7 @@ "versions": [ "DashUseGl3n", - "VibeCustomMain", - "UseSDL2" + "VibeCustomMain" ], "-ddoxFilterArgs": [ "--min-protection=Protected" ], diff --git a/source/dash/graphics/graphics.d b/source/dash/graphics/graphics.d index a5d8c51b..980f15e2 100644 --- a/source/dash/graphics/graphics.d +++ b/source/dash/graphics/graphics.d @@ -20,21 +20,35 @@ public static: */ final void initialize() { - version( UseSDL2 ) + version( DashUseSDL2 ) { adapter = new Sdl; } - else version( Windows ) + else version( DashUseNativeAdapter ) { - adapter = new Win32GL; - } - else version( linux ) - { - adapter = new Linux; + version( Windows ) + { + adapter = new Win32GL; + } + else version( linux ) + { + adapter = new Linux; + } } else { - adapter = new Sdl; + version( Windows ) + { + adapter = new Win32GL; + } + else version( linux ) + { + adapter = new Linux; + } + else + { + adapter = new Sdl; + } } adapter.initialize(); From 6a7edc31f267d5542514de5166ce249620be0049 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 7 Oct 2014 09:18:32 -0400 Subject: [PATCH 104/141] Code cleanup, documentation --- source/dash/editor/editor.d | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/source/dash/editor/editor.d b/source/dash/editor/editor.d index 0e95beee..5f273721 100644 --- a/source/dash/editor/editor.d +++ b/source/dash/editor/editor.d @@ -198,21 +198,18 @@ protected: package: /// The message key for callbacks - package enum CallbackMessageKey = "__callback__"; + enum CallbackMessageKey = "__callback__"; alias InternalEventHandler = void delegate( EventMessage ); alias EventHandlerTuple = Tuple!(UUID, "id", InternalEventHandler, "handler"); - EventMessage[] pendingEvents; - EventHandlerTuple[][string] eventHandlers; - InternalEventHandler[UUID] callbacks; - + /// Register an event from the front end. final void queueEvent( EventMessage msg ) { pendingEvents ~= msg; } - /// Register a + /// Register a message internally, after generating a handler for it. final UUID registerInternalMessageHandler( string key, InternalEventHandler handler ) { auto id = randomUUID(); @@ -220,11 +217,13 @@ package: return id; } + /// If a send call requests a callback, register it. final void registerCallbackHandler( UUID id, InternalEventHandler handler ) { callbacks[ id ] = handler; } + /// Register built-in event handlers. final void registerDefaultEvents() { registerInternalMessageHandler( CallbackMessageKey, &handleCallback ); @@ -251,4 +250,9 @@ package: logFatal( "Callback reference lost: ", msg.callbackId ); } } + +private: + EventMessage[] pendingEvents; + EventHandlerTuple[][string] eventHandlers; + InternalEventHandler[UUID] callbacks; } From e6be1a1a3c3b7ab3ff82f520657edca5a63843ab Mon Sep 17 00:00:00 2001 From: Berulacks Date: Mon, 13 Oct 2014 17:51:33 -0400 Subject: [PATCH 105/141] Added icon support for SDL (searches for icon.bmp in Textures) Also changed the version call in input.d to DashUseSDL2, as per the change in graphics.d --- source/dash/graphics/adapters/sdl.d | 13 ++++++++++++- source/dash/utility/input.d | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index ffb30ad8..6153ad9b 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -6,7 +6,7 @@ import dash.graphics.adapters.adapter; import dash.utility; import derelict.opengl3.gl3, gfm.sdl2; -import std.string; +import std.string, std.file; class Sdl : OpenGL { @@ -47,6 +47,17 @@ public: window.setTitle( DGame.instance.title ); + string iconPath = Resources.Textures ~ "/icon.bmp"; + + if( exists( iconPath ) ) + { + SDLImage imageLib = new SDLImage( sdl, 0 ); + SDL2Surface icon = imageLib.load( iconPath ); + SDL_SetWindowIcon( SDL_GetWindowFromID( window.id() ) , icon.handle() ); + } + else + logDebug("Could not find icon.bmp in Textures folder!"); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d index 6c881839..2d5837f2 100644 --- a/source/dash/utility/input.d +++ b/source/dash/utility/input.d @@ -331,7 +331,7 @@ public: } //alias Keyboard; -version(UseSDL2) +version(DashUseSDL2) alias Keyboard = InputSystem!( KeyboardButtonsSDL, void ); From 8848aae9cc8cfaf889054dfbb7ce0ad2dce1441a Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 14 Oct 2014 11:56:56 -0400 Subject: [PATCH 106/141] Updated gfm:sdl2 to use window.setIcon() --- dub.json | 2 +- source/dash/graphics/adapters/sdl.d | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/dub.json b/dub.json index 63ddb17f..17bdae7a 100644 --- a/dub.json +++ b/dub.json @@ -22,7 +22,7 @@ "derelict-assimp3": "~>1.0", "dyaml": "~>0.5", "gl3n": "==1.0.0", - "gfm:sdl2": "==1.3.1", + "gfm:sdl2": "==1.3.3", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", "vibe-d": "0.7.21-rc.2", diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 6153ad9b..e52d7a10 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -52,8 +52,7 @@ public: if( exists( iconPath ) ) { SDLImage imageLib = new SDLImage( sdl, 0 ); - SDL2Surface icon = imageLib.load( iconPath ); - SDL_SetWindowIcon( SDL_GetWindowFromID( window.id() ) , icon.handle() ); + window.setIcon( imageLib.load( iconPath ) ); } else logDebug("Could not find icon.bmp in Textures folder!"); From f50c97717a1e5a639c150fc583963f95664cc372 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 14 Oct 2014 15:27:16 -0400 Subject: [PATCH 107/141] Fixed D-YAML listing files as --- source/dash/utility/data/serialization.d | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index 26fecff8..83b3bf95 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -66,7 +66,7 @@ T deserializeFile( T )( Resource file, SerializationMode mode = SerializationMod T handleYaml() { - return deserializeYaml!T( Loader.fromString( cast(char[])file.readText() ).load() ); + return deserializeYaml!T( Loader( file.fullPath ).load() ); } final switch( mode ) with( SerializationMode ) @@ -113,8 +113,7 @@ T[] deserializeMultiFile( T )( Resource file, SerializationMode mode = Serializa { import std.algorithm: map; import std.array: array; - return Loader - .fromString( cast(char[])file.readText() ) + return Loader( file.fullPath ) .loadAll() .map!( node => node.deserializeYaml!T() ) .array(); From 255569f135635b5a97f451f5f1c95f22484d5952 Mon Sep 17 00:00:00 2001 From: Berulacks Date: Mon, 20 Oct 2014 18:21:34 -0400 Subject: [PATCH 108/141] Added OpenGL3.3 support Set the "OpenGL3.3" flag to true, under Graphics in the main configuration file to enable. Additionally, disabled ui on Linux systems until we get that fixed. --- source/dash/graphics/adapters/gl.d | 5 ++++- source/dash/graphics/adapters/sdl.d | 8 +++++++ source/dash/graphics/shaders/shaders.d | 29 +++++++++++++++++++++++++- source/dash/utility/config.d | 2 ++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/source/dash/graphics/adapters/gl.d b/source/dash/graphics/adapters/gl.d index b703eb06..d8ad632d 100644 --- a/source/dash/graphics/adapters/gl.d +++ b/source/dash/graphics/adapters/gl.d @@ -431,7 +431,10 @@ public: glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - uiPass(); + //ui is currently broken on Linux + //TODO: Repair the UI on Linux systems + version(!linux) + uiPass(); // put it on the screen swapBuffers(); diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 0cfd5afe..89348845 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -47,8 +47,16 @@ public: window.setTitle( DGame.instance.title ); + if(config.graphics.usingGl33) + { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + } + else + { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + } SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); //context = SDL_GL_CreateContext( window ); diff --git a/source/dash/graphics/shaders/shaders.d b/source/dash/graphics/shaders/shaders.d index 5557c221..995f333b 100644 --- a/source/dash/graphics/shaders/shaders.d +++ b/source/dash/graphics/shaders/shaders.d @@ -7,7 +7,7 @@ import dash.graphics.shaders.glsl; import derelict.opengl3.gl3; -import std.string, std.traits, std.algorithm, std.array; +import std.string, std.traits, std.algorithm, std.array, std.regex; /* * String constants for our shader uniforms @@ -140,6 +140,8 @@ final package class Shader private: uint _programID, _vertexShaderID, _fragmentShaderID; string _shaderName; + auto versionRegex = ctRegex!r"\#version\s400"; + auto layoutRegex = ctRegex!r"layout\(location\s\=\s[0-9]\)\s"; public: /// The program ID for the shader @@ -170,10 +172,35 @@ public: auto fragmentFile = Resource( fragment ); string vertexBody = vertexFile.readText(); string fragmentBody = fragmentFile.readText(); + + //If we're using OpenGL 3.3 then we need to + //change our GLSL version to match, and remove + //any layout(location = x) qualifiers (they + //aren't supported in GLSL 330) + if(config.graphics.usingGl33) + { + vertexBody = replaceAll(vertexBody, layoutRegex, ""); + vertexBody = replaceAll(vertexBody, versionRegex, "#version 330"); + + fragmentBody = replaceAll(fragmentBody, layoutRegex, ""); + fragmentBody = replaceAll(fragmentBody, versionRegex, "#version 330"); + + logDebug( vertexBody ); + } + compile( vertexBody, fragmentBody ); } else { + if(config.graphics.usingGl33) + { + vertex = replaceAll(vertex, layoutRegex, ""); + vertex = replaceAll(vertex, versionRegex, "#version 330"); + + fragment = replaceAll(fragment, layoutRegex, ""); + fragment = replaceAll(fragment, versionRegex, "#version 330"); + } + compile( vertex, fragment ); } diff --git a/source/dash/utility/config.d b/source/dash/utility/config.d index 3eebcce8..5a59be7e 100644 --- a/source/dash/utility/config.d +++ b/source/dash/utility/config.d @@ -67,6 +67,8 @@ public: bool backfaceCulling = true; @rename( "VSync" ) @optional bool vsync = false; + @rename( "OpenGL3.3" ) @optional + bool usingGl33 = false; } static struct UserInterfaceSettings From 1ec3496fbfc25fa1ac0ae7253130e2434114743e Mon Sep 17 00:00:00 2001 From: Berulacks Date: Mon, 20 Oct 2014 18:29:07 -0400 Subject: [PATCH 109/141] Fixed the disabling of uiPass --- source/dash/graphics/adapters/gl.d | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/dash/graphics/adapters/gl.d b/source/dash/graphics/adapters/gl.d index d8ad632d..f71ba71e 100644 --- a/source/dash/graphics/adapters/gl.d +++ b/source/dash/graphics/adapters/gl.d @@ -433,7 +433,8 @@ public: //ui is currently broken on Linux //TODO: Repair the UI on Linux systems - version(!linux) + version(linux){} + else uiPass(); // put it on the screen From 93ce26adaf27cee3720b896d5afc24b6aab71aa8 Mon Sep 17 00:00:00 2001 From: Berulacks Date: Mon, 20 Oct 2014 18:37:25 -0400 Subject: [PATCH 110/141] Fixed spacing, fixed regex for gl3.3 --- source/dash/graphics/adapters/sdl.d | 22 +++++++++++----------- source/dash/graphics/shaders/shaders.d | 2 +- source/dash/utility/config.d | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 73bb2d58..1e06b9c6 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -47,17 +47,17 @@ public: window.setTitle( DGame.instance.title ); - if(config.graphics.usingGl33) - { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); - } - else - { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - } - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + if(config.graphics.usingGl33) + { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + } + else + { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + } + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); string iconPath = Resources.Textures ~ "/icon.bmp"; diff --git a/source/dash/graphics/shaders/shaders.d b/source/dash/graphics/shaders/shaders.d index 995f333b..7778eb97 100644 --- a/source/dash/graphics/shaders/shaders.d +++ b/source/dash/graphics/shaders/shaders.d @@ -141,7 +141,7 @@ private: uint _programID, _vertexShaderID, _fragmentShaderID; string _shaderName; auto versionRegex = ctRegex!r"\#version\s400"; - auto layoutRegex = ctRegex!r"layout\(location\s\=\s[0-9]\)\s"; + auto layoutRegex = ctRegex!r"layout\(location\s\=\s[0-9]+\)\s"; public: /// The program ID for the shader diff --git a/source/dash/utility/config.d b/source/dash/utility/config.d index 5a59be7e..b57e8f89 100644 --- a/source/dash/utility/config.d +++ b/source/dash/utility/config.d @@ -67,8 +67,8 @@ public: bool backfaceCulling = true; @rename( "VSync" ) @optional bool vsync = false; - @rename( "OpenGL3.3" ) @optional - bool usingGl33 = false; + @rename( "OpenGL33" ) @optional + bool usingGl33 = false; } static struct UserInterfaceSettings From f3da70962e292295d3699d8021650d959872605b Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Mon, 20 Oct 2014 18:47:42 -0400 Subject: [PATCH 111/141] Updated Input for new serialization system, split into package Still needs support for events for bindings --- dub.json | 2 +- source/dash/utility/input.d | 993 ------------------------ source/dash/utility/input/input.d | 313 ++++++++ source/dash/utility/input/inputsystem.d | 304 ++++++++ source/dash/utility/input/keyboard.d | 284 +++++++ source/dash/utility/input/mouse.d | 29 + source/dash/utility/input/package.d | 6 + 7 files changed, 937 insertions(+), 994 deletions(-) delete mode 100644 source/dash/utility/input.d create mode 100644 source/dash/utility/input/input.d create mode 100644 source/dash/utility/input/inputsystem.d create mode 100644 source/dash/utility/input/keyboard.d create mode 100644 source/dash/utility/input/mouse.d create mode 100644 source/dash/utility/input/package.d diff --git a/dub.json b/dub.json index 17bdae7a..644775af 100644 --- a/dub.json +++ b/dub.json @@ -25,7 +25,7 @@ "gfm:sdl2": "==1.3.3", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", - "vibe-d": "0.7.21-rc.2", + "vibe-d": "0.7.21-rc.3", "x11": { "version": "~>1.0", "optional": true } }, diff --git a/source/dash/utility/input.d b/source/dash/utility/input.d deleted file mode 100644 index 2d5837f2..00000000 --- a/source/dash/utility/input.d +++ /dev/null @@ -1,993 +0,0 @@ -/** - * Defines the static Input class, which is responsible for handling all keyboard/mouse/controller interactions. - */ -module dash.utility.input; -import dash.utility, dash.core, dash.graphics; -import gfm.sdl2; - -import yaml; -import derelict.opengl3.gl3; -import std.typecons, std.conv, std.traits, std.uuid; - -/** - * Manages all input events. - */ -final abstract class Input -{ -static: -private: - struct Binding - { - public: - string name; - Keyboard.Buttons[] KeyboardButtons; - Mouse.Buttons[] MouseButtons; - //Mouse.Axes[] MouseAxes; - - this( string bind ) - { - name = bind; - } - } - Binding[string] inputBindings; - - enum passThrough( string functionName, string args ) = q{ - void $functionName( string inputName, void delegate( $args ) func ) - { - if( auto binding = inputName in inputBindings ) - { - foreach( key; binding.KeyboardButtons ) - Keyboard.$functionName( key, cast(ParameterTypeTuple!(__traits(getMember, Keyboard, "$functionName"))[ 1 ])func ); - - foreach( mb; binding.MouseButtons ) - Mouse.$functionName( mb, cast(ParameterTypeTuple!(__traits(getMember, Mouse, "$functionName"))[ 1 ])func ); - } - else - { - throw new Exception( "Name " ~ inputName ~ " not bound." ); - } - } - }.replaceMap( [ "$functionName": functionName, "$args": args ] ); -public: - /** - * Processes Config/Input.yml and pulls input string bindings. - */ - void initialize() - { - // TODO: Implement - auto bindings = Node();//Resources.InputBindings.loadYamlFile(); - - Keyboard.initialize(); - Mouse.initialize(); - - if( !bindings.isMapping ) - return; - - foreach( string name, Node bind; bindings ) - { - if( !bind.isMapping ) - { - logWarning( "Unsupported input format for ", name, "." ); - continue; - } - - inputBindings[ name ] = Binding( name ); - - foreach( string type, Node value; bind ) - { - enum parseType( string type ) = q{ - case "$type": - if( value.isScalar ) - { - try - { - inputBindings[ name ].$typeButtons ~= value.get!string.to!($type.Buttons); - } - catch( Exception e ) - { - logFatal( "Failed to parse keybinding for input ", name, ": ", e.msg ); - } - } - else if( value.isSequence ) - { - foreach( Node element; value ) - { - try - { - inputBindings[ name ].$typeButtons ~= element.get!string.to!($type.Buttons); - } - catch( Exception e ) - { - logFatal( "Failed to parse keybinding for input ", name, ": ", e.msg ); - } - } - } - else - { - logFatal( "Failed to parse $type binding for input ", name, ": Mappings not allowed." ); - } - break; - }.replaceMap( [ "$type": type ] ); - - final switch( type ) - { - mixin( parseType!q{Keyboard} ); - mixin( parseType!q{Mouse} ); - } - } - } - } - - /** - * Updates the key states, and calls all key events. - */ - void update() - { - Keyboard.update(); - Mouse.update(); - } - - /** - * Gets the state of a string-bound input. - * - * Params: - * input = The input to check for. - * checkPrevious = Whether or not to make sure the key was up last frame. - */ - T getState( T = bool )( string input, bool checkPrevious = false ) if( is( T == bool ) || is( T == float ) ) - { - static if( is( T == bool ) ) - { - if( auto binding = input in inputBindings ) - { - foreach( key; binding.KeyboardButtons ) - if( Keyboard.isButtonDown( key, checkPrevious ) ) - return true; - foreach( mb; binding.MouseButtons ) - if( Mouse.isButtonDown( mb, checkPrevious ) ) - return true; - - return false; - } - } - /*else static if( is( T == float ) ) - { - if( input in Keyboard.axisBindings ) - { - return Keyboard.getAxisState( input ); - } - else if( input in Mouse.axisBindings ) - { - return Mouse.getAxisState( input ); - } - }*/ - - throw new Exception( "Input " ~ input ~ " not bound." ); - } - - /** - * Check if a given button is down. - * - * Params: - * buttonName = The name of the button to check. - * checkPrevious = Whether or not to make sure the button was down last frame. - */ - bool isButtonDown( string buttonName, bool checkPrevious = false ) - { - if( auto binding = buttonName in inputBindings ) - { - foreach( key; binding.KeyboardButtons ) - if( Keyboard.isButtonDown( key, checkPrevious ) ) - return true; - - foreach( mb; binding.MouseButtons ) - if( Mouse.isButtonDown( mb, checkPrevious ) ) - return true; - } - - return false; - } - - /** - * Add an event to be fired when the given button changes. - * - * Params: - * inputName = The name of the input to add the event to. - * func = The function to call when the button state changes. - */ - mixin( passThrough!( "addButtonEvent", "uint, bool" ) ); - - /** - * Add a button event only when the button is down. - */ - mixin( passThrough!( "addButtonDownEvent", "uint" ) ); - - /** - * Add a button event only when the button is up. - */ - mixin( passThrough!( "addButtonUpEvent", "uint" ) ); - - /** - * Gets the position of the cursor. - * - * Returns: The position of the mouse cursor. - */ - vec2ui mousePos() - { - version( Windows ) - { - if( !Win32GL.get() ) - return vec2ui(); - - import dash.graphics; - import win32.windows; - POINT i; - GetCursorPos( &i ); - ScreenToClient( Win32GL.get().hWnd, &i ); - - // Adjust for border - if( !Graphics.adapter.fullscreen ) - { - i.x -= GetSystemMetrics( SM_CXBORDER ); - i.y -= GetSystemMetrics( SM_CYBORDER ); - } - - return vec2ui( i.x, Graphics.height - i.y ); - } - else - { - return vec2ui(); - } - } - - /** - * Gets the world position of the cursor in the active scene. - * - * Returns: The position of the mouse cursor in world space. - */ - vec3f mousePosView() - { - if( !DGame.instance.activeScene ) - { - logWarning( "No active scene." ); - return vec3f( 0.0f, 0.0f, 0.0f ); - } - - auto scene = DGame.instance.activeScene; - - if( !scene.camera ) - { - logWarning( "No camera on active scene." ); - return vec3f( 0.0f, 0.0f, 0.0f ); - } - vec2ui mouse = mousePos(); - float depth; - int x = mouse.x; - int y = mouse.y; - auto view = vec3f( 0, 0, 0 ); - - if( x >= 0 && x <= Graphics.width && y >= 0 && y <= Graphics.height ) - { - depth = Graphics.getDepthAtScreenPoint( mouse ); - - auto linearDepth = scene.camera.projectionConstants.x / ( scene.camera.projectionConstants.y - depth ); - //Convert x and y to normalized device coords - float screenX = ( mouse.x / cast(float)Graphics.width ) * 2 - 1; - float screenY = -( ( mouse.y / cast(float)Graphics.height ) * 2 - 1 ); - - auto viewSpace = scene.camera.inversePerspectiveMatrix * vec4f( screenX, screenY, 1.0f, 1.0f); - auto viewRay = vec3f( viewSpace.xy * (1.0f / viewSpace.z), 1.0f); - view = viewRay * linearDepth; - } - - return view; - } - - /** - * Gets the world position of the cursor in the active scene. - * - * Returns: The position of the mouse cursor in world space. - */ - vec3f mousePosWorld() - { - return (DGame.instance.activeScene.camera.inverseViewMatrix * vec4f( mousePosView(), 1.0f )).xyz; - } - - /** - * Gets the world position of the cursor in the active scene. - * - * Returns: The GameObject located at the current mouse Position - */ - GameObject mouseObject() - { - if( !DGame.instance.activeScene ) - { - logWarning( "No active scene." ); - return null; - } - - auto scene = DGame.instance.activeScene; - - if( !scene.camera ) - { - logWarning( "No camera on active scene." ); - return null; - } - - vec2ui mouse = mousePos(); - - if( mouse.x >= 0 && mouse.x <= Graphics.width && mouse.y >= 0 && mouse.y <= Graphics.height ) - { - uint id = Graphics.getObjectIDAtScreenPoint( mouse ); - - if( id > 0 ) - { - return scene[ id ]; - } - } - - return null; - } -} - -//alias Keyboard; -version(DashUseSDL2) - - alias Keyboard = InputSystem!( KeyboardButtonsSDL, void ); - -else - - alias Keyboard = InputSystem!( KeyboardButtonsWin, void ); - -alias Mouse = InputSystem!( MouseButtons, MouseAxes ); - -private: -/** - * Defines a system of inputs, buttons, axes or both. - * - * Params: - * ButtonEnum = The enum of buttons for this system. - * AxisEnum = The enum of axes for this system. - */ -final abstract class InputSystem( ButtonEnum, AxisEnum ) -{ -static: -public: - /// Whether or not the system has buttons. - enum HasButtons = !is( ButtonEnum == void ); - /// Whether or not the system has axes. - enum HasAxes = !is( AxisEnum == void ); - -private: - /** - * Initialize all states and events. - */ - void initialize() - { - static if( HasButtons ) - { - buttonCurrent.reset(); - buttonPrevious.reset(); - buttonStaging.reset(); - - foreach( key; buttonEvents.keys ) - buttonEvents.remove( key ); - } - static if( HasAxes ) - { - axisCurrent.reset(); - axisStaging.reset(); - - foreach( key; axisEvents.keys ) - axisEvents.remove( key ); - } - } - - /** - * Update all events and states. - */ - void update() - { - static if( HasButtons ) - { - auto diffButtons = buttonStaging - buttonCurrent; - buttonPrevious = buttonCurrent; - buttonCurrent = buttonStaging; - - foreach( state; diffButtons ) - if( auto buttonEvent = state[ 0 ] in buttonEvents ) - foreach( event; *buttonEvent ) - event( state[ 0 ], state[ 1 ] ); - } - static if( HasAxes ) - { - auto diffAxis = axisStaging - axisCurrent; - axisCurrent = axisStaging; - - foreach( state; diffAxis ) - if( auto axisEvent = state[ 0 ] in axisEvents ) - foreach( event; *axisEvent ) - event( state[ 0 ], state[ 1 ] ); - } - } - -// If we have buttons -static if( HasButtons ) -{ -public: - /// The enum of buttons that the input system has. - alias Buttons = ButtonState.Inputs; - /// The type each button is stored as. - alias ButtonStorageType = bool; - /// A delegate that takes the changed button and the new state. - alias ButtonEvent = void delegate( Buttons, ButtonStorageType ); - /// A delegate that takes the changed button. - alias ButtonStateEvent = void delegate( Buttons ); - - /** - * Check if a given button is down. - * - * Params: - * buttonCode = The button to check. - * checkPrevious = Whether or not to make sure the button was down last frame. - * - * Returns: The state of the button. - */ - ButtonStorageType getButtonState( Buttons buttonCode ) - { - return buttonCurrent[ buttonCode ]; - } - - /** - * Check if a given button is down. - * - * Params: - * buttonCode = The code of the button to check. - * checkPrevious = Whether or not to make sure the button was down last frame. - * - * Returns: The state of the button. - */ - ButtonStorageType isButtonDown( Buttons buttonCode, bool checkPrevious = false ) - { - return buttonCurrent[ buttonCode ] && ( !checkPrevious || !buttonPrevious[ buttonCode ] ); - } - - /** - * Check if a given button is up. - * - * Params: - * buttonCode = The code of the button to check. - * checkPrevious = Whether or not to make sure the button was up last frame. - * - * Returns: The state of the button. - */ - ButtonStorageType isButtonUp( Buttons buttonCode, bool checkPrevious = false ) - { - return !buttonCurrent[ buttonCode ] && ( !checkPrevious || buttonPrevious[ buttonCode ] ); - } - - /** - * Add an event to be fired when the given button changes. - * - * Params: - * buttonCode = The code of the button to add the event to. - * func = The function to call when the button state changes. - */ - void addButtonEvent( Buttons buttonCode, ButtonEvent func ) - { - buttonEvents[ buttonCode ] ~= func; - } - - /** - * Add a button event only when the button is down. - */ - void addButtonDownEvent( Buttons buttonCode, ButtonStateEvent func ) - { - addButtonEvent( buttonCode, ( Buttons buttonCode, ButtonStorageType newState ) { if( newState ) func( buttonCode ); } ); - } - - /** - * Add a button event only when the button is up. - */ - void addButtonUpEvent( Buttons buttonCode, ButtonStateEvent func ) - { - addButtonEvent( buttonCode, ( Buttons buttonCode, ButtonStorageType newState ) { if( !newState ) func( buttonCode ); } ); - } - - /** - * Sets the state of the button to be assigned at the beginning of next frame. - * Should only be called from a window controller. - */ - void setButtonState( Buttons buttonCode, ButtonStorageType newState ) - { - buttonStaging[ buttonCode ] = newState; - } - -private: - /// The struct storing the state of the buttons. - alias ButtonState = State!( ButtonStorageType, ButtonEnum ); - - /// The state of the buttons as of the beginning of the current frame. - ButtonState buttonCurrent; - /// The state of the buttons for the last frame. - ButtonState buttonPrevious; - /// The state of the buttons that has not been applied yet. - ButtonState buttonStaging; - - /// The events tied to the buttons of this system. - ButtonEvent[][ Buttons ] buttonEvents; -} - -// If we have axes -static if( HasAxes ) -{ -public: - /// The enum of axes that the input system has. - alias Axes = AxisState.Inputs; - /// The type each axis is stored as. - alias AxisStorageType = float; - /// A delegate that takes the changed axis and the new state. - alias AxisEvent = void delegate( Axes, AxisStorageType ); - - /** - * Get the state of a given axis. - * - * Params: - * axis = The axis to get the state of. - * - * Returns: The state of the axis. - */ - AxisStorageType getAxisState( Axes axis ) - { - return axisCurrent[ axis ]; - } - - /** - * Add an event to be fired when the given axis changes. - * - * Params: - * axis = The name of the input to add the event to. - * event = The event to trigger when the axis state changes. - */ - void addAxisEvent( Axes axis, AxisEvent event ) - { - axisEvents[ axis ] ~= event; - } - - /** - * Sets the state of the axis to be assigned at the beginning of next frame. - * Should only be called from a window controller. - */ - void setAxisState( Axes axisCode, AxisStorageType newState ) - { - axisStaging[ axisCode ] = newState; - } - -private: - /// The struct storing the state of the axes. - alias AxisState = State!( AxisStorageType, AxisEnum ); - /// The state of the axes as of the beginning of the current frame. - AxisState axisCurrent; - /// The state of the axes that has not been applied yet. - AxisState axisStaging; - - /// The events tied to the axes of this system. - AxisEvent[][ Axes ] axisEvents; -} -} - -/** - * Represents the state of an input method (ie. keyboard, gamepad, etc.). - * - * Params: - * T = The type being stored (ie. bool for keys, floats for axes, etc.). - * totalSize = The number of inputs to store. - */ -struct State( T, InputEnum ) if( is( InputEnum == enum ) ) -{ -private: - //enum totalSize = Inputs.END; - enum totalSize = EnumMembers!Inputs.length; - alias StorageType = T; - alias Inputs = InputEnum; -public: - T[ size_t ] keys; - - ref typeof(this) opAssign( const ref typeof(this) other ) - { - foreach(size_t index, T value; other.keys) - { - keys[index] = value; - } - - return this; - } - - T opIndex( size_t keyCode ) - { - - //If the key being pressed doesn't have - //an entry in keys, add it, and set it - //to the default value - if(!(keyCode in keys)) - keys[ keyCode ] = T(); - - return keys[ keyCode ]; - - } - - T opIndexAssign( T newValue, size_t keyCode ) - { - keys[ keyCode ] = newValue; - - return newValue; - } - - Tuple!( InputEnum, T )[] opBinary( string Op : "-" )( ref typeof(this) other ) - { - Tuple!( InputEnum, T )[] differences; - - foreach( size_t index, T value; keys) - if( value != other[ index ] ) - differences ~= tuple( cast(InputEnum)index, value ); - - return differences; - } - - void reset() - { - for( uint ii = 0; ii < keys.length; ++ii ) - keys[ ii ] = 0; - } -} - -// Enums of inputs -enum MouseButtons -{ - Left = 0x01, /// Left mouse button - Right = 0x02, /// Right mouse button - Middle = 0x04, /// Middle mouse button - X1 = 0x05, /// X1 mouse button - X2 = 0x06, /// X2 mouse button - END, -} - -/// Axes of input for the mouse. -enum MouseAxes -{ - ScrollWheel, - XPos, - YPos, - END, -} - -/** - * Virtual key codes. - * - * From: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx - */ -enum KeyboardButtonsWin: uint -{ - Cancel = 0x03, /// Control-break - //Unused = 0x07, - Backspace = 0x08, /// Backspace key - Tab = 0x09, /// Tab key - //Reserved = 0x0A-0x0B, - Clear = 0x0C, /// Clear key - Return = 0x0D, /// Enter key - //Undefined = 0x0E-0x0F - Shift = 0x10, /// Shift key - Control = 0x11, /// Control key - Alt = 0x12, /// Menu/alt key - Pause = 0x13, /// Pause key - CapsLock = 0x14, /// Capital/Caps Lock key - //Who Cares = 0x15-0x1A, - Escape = 0x1B, /// Escape key - //Who Cares = 0x1C-0x1F - Space = 0x20, /// Space bar - PageUp = 0x21, /// Page Up/Prior key - PageDown = 0x22, /// Page Down/Next key - End = 0x23, /// End key - Home = 0x24, /// Home key - Left = 0x25, /// Left arrow key - Up = 0x26, /// Up arrow key - Right = 0x27, /// Right arrow key - Down = 0x28, /// Down arrow key - Select = 0x29, /// Select key - Print = 0x2A, /// Print key - Execute = 0x2B, /// Execute key - PrintScreen = 0x2C, /// Print Screen/Snapshot key - Insert = 0x2D, /// Insert key - Delete = 0x2E, /// Delete key - Help = 0x2F, /// Help key - Keyboard0 = 0x30, /// 0 key - Keyboard1 = 0x31, /// 1 key - Keyboard2 = 0x32, /// 2 key - Keyboard3 = 0x33, /// 3 key - Keyboard4 = 0x34, /// 4 key - Keyboard5 = 0x35, /// 5 key - Keyboard6 = 0x36, /// 6 key - Keyboard7 = 0x37, /// 7 key - Keyboard8 = 0x38, /// 8 key - Keyboard9 = 0x39, /// 9 key - //Unused = 0x3A-0x40 - A = 0x41, /// A key - B = 0x42, /// B key - C = 0x43, /// C key - D = 0x44, /// D key - E = 0x45, /// E key - F = 0x46, /// F key - G = 0x47, /// G key - H = 0x48, /// H key - I = 0x49, /// I key - J = 0x4A, /// J key - K = 0x4B, /// K key - L = 0x4C, /// L key - M = 0x4D, /// M key - N = 0x4E, /// N key - O = 0x4F, /// O key - P = 0x50, /// P key - Q = 0x51, /// Q key - R = 0x52, /// R key - S = 0x53, /// S key - T = 0x54, /// T key - U = 0x55, /// U key - V = 0x56, /// V key - W = 0x57, /// W key - X = 0x58, /// X key - Y = 0x59, /// Y key - Z = 0x5A, /// Z key - WindowsLeft = 0x5B, /// Left windows key - WindowsRight= 0x5C, /// Right windows key - Apps = 0x5D, /// Applications key - //Reserved = 0x5E - Sleep = 0x5F, /// Sleep key - Numpad0 = 0x60, /// 0 key - Numpad1 = 0x61, /// 1 key - Numpad2 = 0x62, /// 2 key - Numpad3 = 0x63, /// 3 key - Numpad4 = 0x64, /// 4 key - Numpad5 = 0x65, /// 5 key - Numpad6 = 0x66, /// 6 key - Numpad7 = 0x67, /// 7 key - Numpad8 = 0x68, /// 8 key - Numpad9 = 0x69, /// 9 key - Multiply = 0x6A, /// Multiply key - Add = 0x6B, /// Addition key - Separator = 0x6C, /// Seperator key - Subtract = 0x6D, /// Subtraction key - Decimal = 0x6E, /// Decimal key - Divide = 0x6F, /// Division key - F1 = 0x70, /// Function 1 key - F2 = 0x71, /// Function 2 key - F3 = 0x72, /// Function 3 key - F4 = 0x73, /// Function 4 key - F5 = 0x74, /// Function 5 key - F6 = 0x75, /// Function 6 key - F7 = 0x76, /// Function 7 key - F8 = 0x77, /// Function 8 key - F9 = 0x78, /// Function 9 key - F10 = 0x79, /// Function 10 key - F11 = 0x7A, /// Function 11 key - F12 = 0x7B, /// Function 12 key - F13 = 0x7C, /// Function 13 key - F14 = 0x7D, /// Function 14 key - F15 = 0x7E, /// Function 15 key - F16 = 0x7F, /// Function 16 key - F17 = 0x80, /// Function 17 key - F18 = 0x81, /// Function 18 key - F19 = 0x82, /// Function 19 key - F20 = 0x83, /// Function 20 key - F21 = 0x84, /// Function 21 key - F22 = 0x85, /// Function 22 key - F23 = 0x86, /// Function 23 key - F24 = 0x87, /// Function 24 key - //Unused = 0x88-0x8F, - NumLock = 0x90, /// Num Lock key - ScrollLock = 0x91, /// Scroll Lock key - //OEM = 0x92-0x96, - //Unused = 0x97-0x9F, - ShiftLeft = 0xA0, /// Left shift key - ShiftRight = 0xA1, /// Right shift key - ControlLeft = 0xA2, /// Left control key - ControlRight= 0xA3, /// Right control key - AltLeft = 0xA4, /// Left Alt key - AltRight = 0xA5, /// Right Alt key - END, -} - - -enum KeyboardButtonsSDL: uint -{ - Cancel = SDLK_CANCEL, /// Control-break - //Unused = 0x07, - Backspace = SDLK_BACKSPACE, /// Backspace key - Tab = SDLK_TAB, /// Tab key - //Reserved = 0x0A-0x0B, - Clear = SDLK_CLEAR, /// Clear key - Return = SDLK_RETURN, /// Enter key - //Undefined = 0x0E-0x0F - // * See Left/Right Shift, Ctrl, Alt below * - //Shift = SDLK_LSHIFT, /// Shift key - //Control = SDLK_LCTRL, /// Control key - //Alt = SDLK_LALT, /// Menu/alt key - // - Pause = SDLK_PAUSE, /// Pause key - CapsLock = SDLK_CAPSLOCK, - //Who Cares = 0x15-0x1A, - Escape = SDLK_ESCAPE, - //Who Cares = 0x1C-0x1F - Space = SDLK_SPACE, /// Space bar - PageUp = SDLK_PAGEUP, /// Page Up/Prior key - PageDown = SDLK_PAGEDOWN, /// Page Down/Next key - End = SDLK_END, /// End key - Home = SDLK_HOME, /// Home key - Left = SDLK_LEFT, /// Left arrow key - Up = SDLK_UP, /// Up arrow key - Right = SDLK_RIGHT, /// Right arrow key - Down = SDLK_DOWN, /// Down arrow key - Select = SDLK_SELECT, /// Select key - Print = SDLK_PRINTSCREEN, /// Print key - PrintScreen = SDLK_PRINTSCREEN, /// Print Screen/Snapshot key - Execute = SDLK_EXECUTE, /// Execute key - Insert = SDLK_INSERT, /// Insert key - Delete = SDLK_DELETE, /// Delete key - Help = SDLK_HELP, /// Help key - Keyboard0 = SDLK_0, /// 0 key - Keyboard1 = SDLK_1, /// 1 key - Keyboard2 = SDLK_2, /// 2 key - Keyboard3 = SDLK_3, /// 3 key - Keyboard4 = SDLK_4, /// 4 key - Keyboard5 = SDLK_5, /// 5 key - Keyboard6 = SDLK_6, /// 6 key - Keyboard7 = SDLK_7, /// 7 key - Keyboard8 = SDLK_8, /// 8 key - Keyboard9 = SDLK_9, /// 9 key - //Unused = 0x3A-0x40 - A = SDLK_a, /// A key - B = SDLK_b, /// B key - C = SDLK_c, /// C key - D = SDLK_d, /// D key - E = SDLK_e, /// E key - F = SDLK_f, /// F key - G = SDLK_g, /// G key - H = SDLK_h, /// H key - I = SDLK_i, /// I key - J = SDLK_j, /// J key - K = SDLK_k, /// K key - L = SDLK_l, /// L key - M = SDLK_m, /// M key - N = SDLK_n, /// N key - O = SDLK_o, /// O key - P = SDLK_p, /// P key - Q = SDLK_q, /// Q key - R = SDLK_r, /// R key - S = SDLK_s, /// S key - T = SDLK_t, /// T key - U = SDLK_u, /// U key - V = SDLK_v, /// V key - W = SDLK_w, /// W key - X = SDLK_x, /// X key - Y = SDLK_y, /// Y key - Z = SDLK_z, /// Z key - GuiLeft = SDLK_LGUI, /// Left GUI key - GuiRight = SDLK_RGUI, /// Right GUI key - Apps = SDLK_APPLICATION, /// Applications key - //Reserved = 0x5E - Sleep = SDLK_SLEEP, /// Sleep key - Numpad0 = SDLK_KP_0, /// 0 key - Numpad1 = SDLK_KP_1, /// 1 key - Numpad2 = SDLK_KP_2, /// 2 key - Numpad3 = SDLK_KP_3, /// 3 key - Numpad4 = SDLK_KP_4, /// 4 key - Numpad5 = SDLK_KP_5, /// 5 key - Numpad6 = SDLK_KP_6, /// 6 key - Numpad7 = SDLK_KP_7, /// 7 key - Numpad8 = SDLK_KP_8, /// 8 key - Numpad9 = SDLK_KP_9, /// 9 key - // * Unused * - //Multiply = 0x6A, /// Multiply key - //Add = 0x6B, /// Addition key - //Separator = 0x6C, /// Seperator key - //Subtract = 0x6D, /// Subtraction key - //Decimal = 0x6E, /// Decimal key - //Divide = 0x6F, /// Division key - F1 = SDLK_F1, /// Function 1 key - F2 = SDLK_F2, /// Function 2 key - F3 = SDLK_F3, /// Function 3 key - F4 = SDLK_F4, /// Function 4 key - F5 = SDLK_F5, /// Function 5 key - F6 = SDLK_F6, /// Function 6 key - F7 = SDLK_F7, /// Function 7 key - F8 = SDLK_F8, /// Function 8 key - F9 = SDLK_F9, /// Function 9 key - F10 = SDLK_F10, /// Function 10 key - F11 = SDLK_F11, /// Function 11 key - F12 = SDLK_F12, /// Function 12 key - F13 = SDLK_F13, /// Function 13 key - F14 = SDLK_F14, /// Function 14 key - F15 = SDLK_F15, /// Function 15 key - F16 = SDLK_F16, /// Function 16 key - F17 = SDLK_F17, /// Function 17 key - F18 = SDLK_F18, /// Function 18 key - F19 = SDLK_F19, /// Function 19 key - F20 = SDLK_F20, /// Function 20 key - F21 = SDLK_F21, /// Function 21 key - F22 = SDLK_F22, /// Function 22 key - F23 = SDLK_F23, /// Function 23 key - F24 = SDLK_F24, /// Function 24 key - //Unused = 0x88-0x8F, - NumLock = SDLK_NUMLOCKCLEAR, /// Num Lock key - ScrollLock = SDLK_SCROLLLOCK, /// Scroll Lock key - //OEM = 0x92-0x96, - //Unused = 0x97-0x9F, - ShiftLeft = SDLK_LSHIFT, /// Left shift key - ShiftRight = SDLK_LSHIFT, /// Right shift key - ControlLeft = SDLK_LCTRL, /// Left control key - ControlRight= SDLK_RCTRL, /// Right control key - AltLeft = SDLK_LALT, /// Left Alt key - AltRight = SDLK_RALT, /// Right Alt key - END, -} - -unittest -{ - import std.stdio; - writeln( "Dash Input isKeyUp unittest" ); - - Config.initialize(); - Input.initialize(); - Keyboard.setButtonState( Keyboard.Buttons.Space, true ); - - Keyboard.update(); - Keyboard.setButtonState( Keyboard.Buttons.Space, false ); - - Keyboard.update(); - assert( Keyboard.isButtonUp( Keyboard.Buttons.Space, true ) ); - assert( Keyboard.isButtonUp( Keyboard.Buttons.Space, false ) ); - - Keyboard.update(); - assert( !Keyboard.isButtonUp( Keyboard.Buttons.Space, true ) ); - assert( Keyboard.isButtonUp( Keyboard.Buttons.Space, false ) ); -} - -unittest -{ - import std.stdio; - writeln( "Dash Input addKeyEvent unittest" ); - - Config.initialize(); - Input.initialize(); - - bool keyDown; - Keyboard.addButtonEvent( Keyboard.Buttons.Space, ( keyCode, newState ) - { - keyDown = newState; - } ); - - Keyboard.setButtonState( Keyboard.Buttons.Space, true ); - Input.update(); - assert( keyDown ); - - Keyboard.setButtonState( Keyboard.Buttons.Space, false ); - Input.update(); - assert( !keyDown ); -} - -unittest -{ - import std.stdio; - writeln( "Dash Input isKeyDown unittest" ); - - Config.initialize(); - Input.initialize(); - Keyboard.setButtonState( Keyboard.Buttons.Space, true ); - - Input.update(); - assert( Keyboard.isButtonDown( Keyboard.Buttons.Space, true ) ); - assert( Keyboard.isButtonDown( Keyboard.Buttons.Space, false ) ); - - Input.update(); - assert( !Keyboard.isButtonDown( Keyboard.Buttons.Space, true ) ); - assert( Keyboard.isButtonDown( Keyboard.Buttons.Space, false ) ); -} diff --git a/source/dash/utility/input/input.d b/source/dash/utility/input/input.d new file mode 100644 index 00000000..07d1b851 --- /dev/null +++ b/source/dash/utility/input/input.d @@ -0,0 +1,313 @@ +/** + * Defines the static Input class, which is responsible for handling all keyboard/mouse/controller interactions. + */ +module dash.utility.input.input; +import dash.utility, dash.core, dash.graphics; + +import yaml; +import derelict.opengl3.gl3; +import std.conv, std.uuid; + +/** + * Manages all input events. + */ +final abstract class Input +{ +static: +private: + static struct Binding + { + public: + @ignore + string name; + + @rename( "Keyboard" ) @byName @optional + Keyboard.Buttons[] keyboardButtons; + + @rename( "Mouse" ) @byName @optional + Mouse.Buttons[] mouseButtons; + + //@rename( "MouseAxes" ) @optional + //Mouse.Axes[] mouseAxes; + } + Binding[string] bindings; + Resource bindingFile = Resource( "" ); + +public: + /** + * Processes Config/Input.yml and pulls input string bindings. + */ + void initialize() + { + try + { + auto bindingRes = deserializeFileByName!(typeof(bindings))( Resources.InputBindings ); + bindings = bindingRes[ 0 ]; + bindingFile = bindingRes[ 1 ]; + + foreach( name, ref binding; bindings ) + binding.name = name; + } + catch( Exception e ) + { + logError( "Error parsing config file:\n", e.toString() ); + } + + Keyboard.initialize(); + Mouse.initialize(); + } + + /** + * Updates the key states, and calls all key events. + */ + void update() + { + Keyboard.update(); + Mouse.update(); + } + + /** + * Gets the state of a string-bound input. + * + * Params: + * input = The input to check for. + * checkPrevious = Whether or not to make sure the key was up last frame. + */ + T getState( T = bool )( string input, bool checkPrevious = false ) if( is( T == bool ) || is( T == float ) ) + { + if( auto binding = input in bindings ) + { + static if( is( T == bool ) ) + { + foreach( key; binding.keyboardButtons ) + if( Keyboard.isButtonDown( key, checkPrevious ) ) + return true; + foreach( mb; binding.mouseButtons ) + if( Mouse.isButtonDown( mb, checkPrevious ) ) + return true; + + return false; + } + else static if( is( T == float ) ) + { + foreach( ma; binding.mouseAxes ) + { + auto state = Mouse.getAxisState( ma, checkPrevious ); + if( state != 0.0f ) + return state; + } + + return 0.0f; + } + } + + throw new Exception( "Input " ~ input ~ " not bound." ); + } + + /** + * Check if a given button is down. + * + * Params: + * buttonName = The name of the button to check. + * checkPrevious = Whether or not to make sure the button was down last frame. + */ + bool isButtonDown( string buttonName, bool checkPrevious = false ) + { + if( auto binding = buttonName in bindings ) + { + foreach( key; binding.keyboardButtons ) + if( Keyboard.isButtonDown( key, checkPrevious ) ) + return true; + + foreach( mb; binding.mouseButtons ) + if( Mouse.isButtonDown( mb, checkPrevious ) ) + return true; + } + + return false; + } + + /** + * Gets the position of the cursor. + * + * Returns: The position of the mouse cursor. + */ + vec2ui mousePos() + { + version( Windows ) + { + if( !Win32GL.get() ) + return vec2ui(); + + import dash.graphics; + import win32.windows; + POINT i; + GetCursorPos( &i ); + ScreenToClient( Win32GL.get().hWnd, &i ); + + // Adjust for border + if( !Graphics.adapter.fullscreen ) + { + i.x -= GetSystemMetrics( SM_CXBORDER ); + i.y -= GetSystemMetrics( SM_CYBORDER ); + } + + return vec2ui( i.x, Graphics.height - i.y ); + } + else + { + return vec2ui(); + } + } + + /** + * Gets the world position of the cursor in the active scene. + * + * Returns: The position of the mouse cursor in world space. + */ + vec3f mousePosView() + { + if( !DGame.instance.activeScene ) + { + logWarning( "No active scene." ); + return vec3f( 0.0f, 0.0f, 0.0f ); + } + + auto scene = DGame.instance.activeScene; + + if( !scene.camera ) + { + logWarning( "No camera on active scene." ); + return vec3f( 0.0f, 0.0f, 0.0f ); + } + vec2ui mouse = mousePos(); + float depth; + int x = mouse.x; + int y = mouse.y; + auto view = vec3f( 0, 0, 0 ); + + if( x >= 0 && x <= Graphics.width && y >= 0 && y <= Graphics.height ) + { + depth = Graphics.getDepthAtScreenPoint( mouse ); + + auto linearDepth = scene.camera.projectionConstants.x / ( scene.camera.projectionConstants.y - depth ); + //Convert x and y to normalized device coords + float screenX = ( mouse.x / cast(float)Graphics.width ) * 2 - 1; + float screenY = -( ( mouse.y / cast(float)Graphics.height ) * 2 - 1 ); + + auto viewSpace = scene.camera.inversePerspectiveMatrix * vec4f( screenX, screenY, 1.0f, 1.0f); + auto viewRay = vec3f( viewSpace.xy * (1.0f / viewSpace.z), 1.0f); + view = viewRay * linearDepth; + } + + return view; + } + + /** + * Gets the world position of the cursor in the active scene. + * + * Returns: The position of the mouse cursor in world space. + */ + vec3f mousePosWorld() + { + return (DGame.instance.activeScene.camera.inverseViewMatrix * vec4f( mousePosView(), 1.0f )).xyz; + } + + /** + * Gets the world position of the cursor in the active scene. + * + * Returns: The GameObject located at the current mouse Position + */ + GameObject mouseObject() + { + if( !DGame.instance.activeScene ) + { + logWarning( "No active scene." ); + return null; + } + + auto scene = DGame.instance.activeScene; + + if( !scene.camera ) + { + logWarning( "No camera on active scene." ); + return null; + } + + vec2ui mouse = mousePos(); + + if( mouse.x >= 0 && mouse.x <= Graphics.width && mouse.y >= 0 && mouse.y <= Graphics.height ) + { + uint id = Graphics.getObjectIDAtScreenPoint( mouse ); + + if( id > 0 ) + { + return scene[ id ]; + } + } + + return null; + } +} + +unittest +{ + import std.stdio; + writeln( "Dash Input isKeyUp unittest" ); + + Config.initialize(); + Input.initialize(); + Keyboard.setButtonState( Keyboard.Buttons.Space, true ); + + Keyboard.update(); + Keyboard.setButtonState( Keyboard.Buttons.Space, false ); + + Keyboard.update(); + assert( Keyboard.isButtonUp( Keyboard.Buttons.Space, true ) ); + assert( Keyboard.isButtonUp( Keyboard.Buttons.Space, false ) ); + + Keyboard.update(); + assert( !Keyboard.isButtonUp( Keyboard.Buttons.Space, true ) ); + assert( Keyboard.isButtonUp( Keyboard.Buttons.Space, false ) ); +} + +unittest +{ + import std.stdio; + writeln( "Dash Input addKeyEvent unittest" ); + + Config.initialize(); + Input.initialize(); + + bool keyDown; + Keyboard.addButtonEvent( Keyboard.Buttons.Space, ( keyCode, newState ) + { + keyDown = newState; + } ); + + Keyboard.setButtonState( Keyboard.Buttons.Space, true ); + Input.update(); + assert( keyDown ); + + Keyboard.setButtonState( Keyboard.Buttons.Space, false ); + Input.update(); + assert( !keyDown ); +} + +unittest +{ + import std.stdio; + writeln( "Dash Input isKeyDown unittest" ); + + Config.initialize(); + Input.initialize(); + Keyboard.setButtonState( Keyboard.Buttons.Space, true ); + + Input.update(); + assert( Keyboard.isButtonDown( Keyboard.Buttons.Space, true ) ); + assert( Keyboard.isButtonDown( Keyboard.Buttons.Space, false ) ); + + Input.update(); + assert( !Keyboard.isButtonDown( Keyboard.Buttons.Space, true ) ); + assert( Keyboard.isButtonDown( Keyboard.Buttons.Space, false ) ); +} diff --git a/source/dash/utility/input/inputsystem.d b/source/dash/utility/input/inputsystem.d new file mode 100644 index 00000000..2abed509 --- /dev/null +++ b/source/dash/utility/input/inputsystem.d @@ -0,0 +1,304 @@ +/** + * Defines InputSystem and State, which are used for defining an input device (keyboard, mouse, gamepad, etc.) + */ +module dash.utility.input.inputsystem; + +import std.typecons, std.traits; + +package: +/** + * Defines a system of inputs, buttons, axes or both. + * + * Params: + * ButtonEnum = The enum of buttons for this system. + * AxisEnum = The enum of axes for this system. + */ +final abstract class InputSystem( ButtonEnum, AxisEnum ) +{ +static: +public: + /// Whether or not the system has buttons. + enum HasButtons = !is( ButtonEnum == void ); + /// Whether or not the system has axes. + enum HasAxes = !is( AxisEnum == void ); + +package: + /** + * Initialize all states and events. + */ + void initialize() + { + static if( HasButtons ) + { + buttonCurrent.reset(); + buttonPrevious.reset(); + buttonStaging.reset(); + + foreach( key; buttonEvents.keys ) + buttonEvents.remove( key ); + } + static if( HasAxes ) + { + axisCurrent.reset(); + axisStaging.reset(); + + foreach( key; axisEvents.keys ) + axisEvents.remove( key ); + } + } + + /** + * Update all events and states. + */ + void update() + { + static if( HasButtons ) + { + auto diffButtons = buttonStaging - buttonCurrent; + buttonPrevious = buttonCurrent; + buttonCurrent = buttonStaging; + + foreach( state; diffButtons ) + if( auto buttonEvent = state[ 0 ] in buttonEvents ) + foreach( event; *buttonEvent ) + event( state[ 0 ], state[ 1 ] ); + } + static if( HasAxes ) + { + auto diffAxis = axisStaging - axisCurrent; + axisCurrent = axisStaging; + + foreach( state; diffAxis ) + if( auto axisEvent = state[ 0 ] in axisEvents ) + foreach( event; *axisEvent ) + event( state[ 0 ], state[ 1 ] ); + } + } + +// If we have buttons +static if( HasButtons ) +{ +public: + /// The enum of buttons that the input system has. + alias Buttons = ButtonState.Inputs; + /// The type each button is stored as. + alias ButtonStorageType = bool; + /// A delegate that takes the changed button and the new state. + alias ButtonEvent = void delegate( Buttons, ButtonStorageType ); + /// A delegate that takes the changed button. + alias ButtonStateEvent = void delegate( Buttons ); + + /** + * Check if a given button is down. + * + * Params: + * buttonCode = The button to check. + * checkPrevious = Whether or not to make sure the button was down last frame. + * + * Returns: The state of the button. + */ + ButtonStorageType getButtonState( Buttons buttonCode ) + { + return buttonCurrent[ buttonCode ]; + } + + /** + * Check if a given button is down. + * + * Params: + * buttonCode = The code of the button to check. + * checkPrevious = Whether or not to make sure the button was down last frame. + * + * Returns: The state of the button. + */ + ButtonStorageType isButtonDown( Buttons buttonCode, bool checkPrevious = false ) + { + return buttonCurrent[ buttonCode ] && ( !checkPrevious || !buttonPrevious[ buttonCode ] ); + } + + /** + * Check if a given button is up. + * + * Params: + * buttonCode = The code of the button to check. + * checkPrevious = Whether or not to make sure the button was up last frame. + * + * Returns: The state of the button. + */ + ButtonStorageType isButtonUp( Buttons buttonCode, bool checkPrevious = false ) + { + return !buttonCurrent[ buttonCode ] && ( !checkPrevious || buttonPrevious[ buttonCode ] ); + } + + /** + * Add an event to be fired when the given button changes. + * + * Params: + * buttonCode = The code of the button to add the event to. + * func = The function to call when the button state changes. + */ + void addButtonEvent( Buttons buttonCode, ButtonEvent func ) + { + buttonEvents[ buttonCode ] ~= func; + } + + /** + * Add a button event only when the button is down. + */ + void addButtonDownEvent( Buttons buttonCode, ButtonStateEvent func ) + { + addButtonEvent( buttonCode, ( Buttons buttonCode, ButtonStorageType newState ) { if( newState ) func( buttonCode ); } ); + } + + /** + * Add a button event only when the button is up. + */ + void addButtonUpEvent( Buttons buttonCode, ButtonStateEvent func ) + { + addButtonEvent( buttonCode, ( Buttons buttonCode, ButtonStorageType newState ) { if( !newState ) func( buttonCode ); } ); + } + + /** + * Sets the state of the button to be assigned at the beginning of next frame. + * Should only be called from a window controller. + */ + void setButtonState( Buttons buttonCode, ButtonStorageType newState ) + { + buttonStaging[ buttonCode ] = newState; + } + +private: + /// The struct storing the state of the buttons. + alias ButtonState = State!( ButtonStorageType, ButtonEnum ); + + /// The state of the buttons as of the beginning of the current frame. + ButtonState buttonCurrent; + /// The state of the buttons for the last frame. + ButtonState buttonPrevious; + /// The state of the buttons that has not been applied yet. + ButtonState buttonStaging; + + /// The events tied to the buttons of this system. + ButtonEvent[][ Buttons ] buttonEvents; +} + +// If we have axes +static if( HasAxes ) +{ +public: + /// The enum of axes that the input system has. + alias Axes = AxisState.Inputs; + /// The type each axis is stored as. + alias AxisStorageType = float; + /// A delegate that takes the changed axis and the new state. + alias AxisEvent = void delegate( Axes, AxisStorageType ); + + /** + * Get the state of a given axis. + * + * Params: + * axis = The axis to get the state of. + * + * Returns: The state of the axis. + */ + AxisStorageType getAxisState( Axes axis ) + { + return axisCurrent[ axis ]; + } + + /** + * Add an event to be fired when the given axis changes. + * + * Params: + * axis = The name of the input to add the event to. + * event = The event to trigger when the axis state changes. + */ + void addAxisEvent( Axes axis, AxisEvent event ) + { + axisEvents[ axis ] ~= event; + } + + /** + * Sets the state of the axis to be assigned at the beginning of next frame. + * Should only be called from a window controller. + */ + void setAxisState( Axes axisCode, AxisStorageType newState ) + { + axisStaging[ axisCode ] = newState; + } + +private: + /// The struct storing the state of the axes. + alias AxisState = State!( AxisStorageType, AxisEnum ); + /// The state of the axes as of the beginning of the current frame. + AxisState axisCurrent; + /// The state of the axes that has not been applied yet. + AxisState axisStaging; + + /// The events tied to the axes of this system. + AxisEvent[][ Axes ] axisEvents; +} +} + +/** + * Represents the state of an input method (ie. keyboard, gamepad, etc.). + * + * Params: + * T = The type being stored (ie. bool for keys, floats for axes, etc.). + * totalSize = The number of inputs to store. + */ +struct State( T, InputEnum ) if( is( InputEnum == enum ) ) +{ +private: + // enum totalSize = Inputs.END; + enum totalSize = EnumMembers!Inputs.length; + alias StorageType = T; + alias Inputs = InputEnum; +public: + T[ size_t ] keys; + + ref typeof(this) opAssign( const ref typeof(this) other ) + { + foreach(size_t index, T value; other.keys) + { + keys[index] = value; + } + + return this; + } + + T opIndex( size_t keyCode ) + { + // If the key being pressed doesn't have + // an entry in keys, add it, and set it + // to the default value + if( !( keyCode in keys ) ) + keys[ keyCode ] = T(); + + return keys[ keyCode ]; + } + + T opIndexAssign( T newValue, size_t keyCode ) + { + keys[ keyCode ] = newValue; + + return newValue; + } + + Tuple!( InputEnum, T )[] opBinary( string Op : "-" )( ref typeof(this) other ) + { + Tuple!( InputEnum, T )[] differences; + + foreach( size_t index, T value; keys) + if( value != other[ index ] ) + differences ~= tuple( cast(InputEnum)index, value ); + + return differences; + } + + void reset() + { + for( uint ii = 0; ii < keys.length; ++ii ) + keys[ ii ] = 0; + } +} \ No newline at end of file diff --git a/source/dash/utility/input/keyboard.d b/source/dash/utility/input/keyboard.d new file mode 100644 index 00000000..c865cf7c --- /dev/null +++ b/source/dash/utility/input/keyboard.d @@ -0,0 +1,284 @@ +/** +* Defines the Keyboard input device. +*/ +module dash.utility.input.keyboard; +import dash.utility.input.inputsystem; + +import gfm.sdl2; + +version( DashUseSDL2 ) + /// Defines the Mouse input device. + alias Keyboard = InputSystem!( KeyboardButtonsSDL, void ); +else + /// Defines the Mouse input device. + alias Keyboard = InputSystem!( KeyboardButtonsWin, void ); + +package: +/** + * Virtual key codes. + * + * From: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx + */ +enum KeyboardButtonsWin: uint +{ + Cancel = 0x03, /// Control-break + //Unused = 0x07, + Backspace = 0x08, /// Backspace key + Tab = 0x09, /// Tab key + //Reserved = 0x0A-0x0B, + Clear = 0x0C, /// Clear key + Return = 0x0D, /// Enter key + //Undefined = 0x0E-0x0F + Shift = 0x10, /// Shift key + Control = 0x11, /// Control key + Alt = 0x12, /// Menu/alt key + Pause = 0x13, /// Pause key + CapsLock = 0x14, /// Capital/Caps Lock key + //Who Cares = 0x15-0x1A, + Escape = 0x1B, /// Escape key + //Who Cares = 0x1C-0x1F + Space = 0x20, /// Space bar + PageUp = 0x21, /// Page Up/Prior key + PageDown = 0x22, /// Page Down/Next key + End = 0x23, /// End key + Home = 0x24, /// Home key + Left = 0x25, /// Left arrow key + Up = 0x26, /// Up arrow key + Right = 0x27, /// Right arrow key + Down = 0x28, /// Down arrow key + Select = 0x29, /// Select key + Print = 0x2A, /// Print key + Execute = 0x2B, /// Execute key + PrintScreen = 0x2C, /// Print Screen/Snapshot key + Insert = 0x2D, /// Insert key + Delete = 0x2E, /// Delete key + Help = 0x2F, /// Help key + Keyboard0 = 0x30, /// 0 key + Keyboard1 = 0x31, /// 1 key + Keyboard2 = 0x32, /// 2 key + Keyboard3 = 0x33, /// 3 key + Keyboard4 = 0x34, /// 4 key + Keyboard5 = 0x35, /// 5 key + Keyboard6 = 0x36, /// 6 key + Keyboard7 = 0x37, /// 7 key + Keyboard8 = 0x38, /// 8 key + Keyboard9 = 0x39, /// 9 key + //Unused = 0x3A-0x40 + A = 0x41, /// A key + B = 0x42, /// B key + C = 0x43, /// C key + D = 0x44, /// D key + E = 0x45, /// E key + F = 0x46, /// F key + G = 0x47, /// G key + H = 0x48, /// H key + I = 0x49, /// I key + J = 0x4A, /// J key + K = 0x4B, /// K key + L = 0x4C, /// L key + M = 0x4D, /// M key + N = 0x4E, /// N key + O = 0x4F, /// O key + P = 0x50, /// P key + Q = 0x51, /// Q key + R = 0x52, /// R key + S = 0x53, /// S key + T = 0x54, /// T key + U = 0x55, /// U key + V = 0x56, /// V key + W = 0x57, /// W key + X = 0x58, /// X key + Y = 0x59, /// Y key + Z = 0x5A, /// Z key + WindowsLeft = 0x5B, /// Left windows key + WindowsRight= 0x5C, /// Right windows key + Apps = 0x5D, /// Applications key + //Reserved = 0x5E + Sleep = 0x5F, /// Sleep key + Numpad0 = 0x60, /// 0 key + Numpad1 = 0x61, /// 1 key + Numpad2 = 0x62, /// 2 key + Numpad3 = 0x63, /// 3 key + Numpad4 = 0x64, /// 4 key + Numpad5 = 0x65, /// 5 key + Numpad6 = 0x66, /// 6 key + Numpad7 = 0x67, /// 7 key + Numpad8 = 0x68, /// 8 key + Numpad9 = 0x69, /// 9 key + Multiply = 0x6A, /// Multiply key + Add = 0x6B, /// Addition key + Separator = 0x6C, /// Seperator key + Subtract = 0x6D, /// Subtraction key + Decimal = 0x6E, /// Decimal key + Divide = 0x6F, /// Division key + F1 = 0x70, /// Function 1 key + F2 = 0x71, /// Function 2 key + F3 = 0x72, /// Function 3 key + F4 = 0x73, /// Function 4 key + F5 = 0x74, /// Function 5 key + F6 = 0x75, /// Function 6 key + F7 = 0x76, /// Function 7 key + F8 = 0x77, /// Function 8 key + F9 = 0x78, /// Function 9 key + F10 = 0x79, /// Function 10 key + F11 = 0x7A, /// Function 11 key + F12 = 0x7B, /// Function 12 key + F13 = 0x7C, /// Function 13 key + F14 = 0x7D, /// Function 14 key + F15 = 0x7E, /// Function 15 key + F16 = 0x7F, /// Function 16 key + F17 = 0x80, /// Function 17 key + F18 = 0x81, /// Function 18 key + F19 = 0x82, /// Function 19 key + F20 = 0x83, /// Function 20 key + F21 = 0x84, /// Function 21 key + F22 = 0x85, /// Function 22 key + F23 = 0x86, /// Function 23 key + F24 = 0x87, /// Function 24 key + //Unused = 0x88-0x8F, + NumLock = 0x90, /// Num Lock key + ScrollLock = 0x91, /// Scroll Lock key + //OEM = 0x92-0x96, + //Unused = 0x97-0x9F, + ShiftLeft = 0xA0, /// Left shift key + ShiftRight = 0xA1, /// Right shift key + ControlLeft = 0xA2, /// Left control key + ControlRight= 0xA3, /// Right control key + AltLeft = 0xA4, /// Left Alt key + AltRight = 0xA5, /// Right Alt key + END, +} + + +enum KeyboardButtonsSDL: uint +{ + Cancel = SDLK_CANCEL, /// Control-break + //Unused = 0x07, + Backspace = SDLK_BACKSPACE, /// Backspace key + Tab = SDLK_TAB, /// Tab key + //Reserved = 0x0A-0x0B, + Clear = SDLK_CLEAR, /// Clear key + Return = SDLK_RETURN, /// Enter key + //Undefined = 0x0E-0x0F + // * See Left/Right Shift, Ctrl, Alt below * + //Shift = SDLK_LSHIFT, /// Shift key + //Control = SDLK_LCTRL, /// Control key + //Alt = SDLK_LALT, /// Menu/alt key + // + Pause = SDLK_PAUSE, /// Pause key + CapsLock = SDLK_CAPSLOCK, + //Who Cares = 0x15-0x1A, + Escape = SDLK_ESCAPE, + //Who Cares = 0x1C-0x1F + Space = SDLK_SPACE, /// Space bar + PageUp = SDLK_PAGEUP, /// Page Up/Prior key + PageDown = SDLK_PAGEDOWN, /// Page Down/Next key + End = SDLK_END, /// End key + Home = SDLK_HOME, /// Home key + Left = SDLK_LEFT, /// Left arrow key + Up = SDLK_UP, /// Up arrow key + Right = SDLK_RIGHT, /// Right arrow key + Down = SDLK_DOWN, /// Down arrow key + Select = SDLK_SELECT, /// Select key + Print = SDLK_PRINTSCREEN, /// Print key + PrintScreen = SDLK_PRINTSCREEN, /// Print Screen/Snapshot key + Execute = SDLK_EXECUTE, /// Execute key + Insert = SDLK_INSERT, /// Insert key + Delete = SDLK_DELETE, /// Delete key + Help = SDLK_HELP, /// Help key + Keyboard0 = SDLK_0, /// 0 key + Keyboard1 = SDLK_1, /// 1 key + Keyboard2 = SDLK_2, /// 2 key + Keyboard3 = SDLK_3, /// 3 key + Keyboard4 = SDLK_4, /// 4 key + Keyboard5 = SDLK_5, /// 5 key + Keyboard6 = SDLK_6, /// 6 key + Keyboard7 = SDLK_7, /// 7 key + Keyboard8 = SDLK_8, /// 8 key + Keyboard9 = SDLK_9, /// 9 key + //Unused = 0x3A-0x40 + A = SDLK_a, /// A key + B = SDLK_b, /// B key + C = SDLK_c, /// C key + D = SDLK_d, /// D key + E = SDLK_e, /// E key + F = SDLK_f, /// F key + G = SDLK_g, /// G key + H = SDLK_h, /// H key + I = SDLK_i, /// I key + J = SDLK_j, /// J key + K = SDLK_k, /// K key + L = SDLK_l, /// L key + M = SDLK_m, /// M key + N = SDLK_n, /// N key + O = SDLK_o, /// O key + P = SDLK_p, /// P key + Q = SDLK_q, /// Q key + R = SDLK_r, /// R key + S = SDLK_s, /// S key + T = SDLK_t, /// T key + U = SDLK_u, /// U key + V = SDLK_v, /// V key + W = SDLK_w, /// W key + X = SDLK_x, /// X key + Y = SDLK_y, /// Y key + Z = SDLK_z, /// Z key + GuiLeft = SDLK_LGUI, /// Left GUI key + GuiRight = SDLK_RGUI, /// Right GUI key + Apps = SDLK_APPLICATION, /// Applications key + //Reserved = 0x5E + Sleep = SDLK_SLEEP, /// Sleep key + Numpad0 = SDLK_KP_0, /// 0 key + Numpad1 = SDLK_KP_1, /// 1 key + Numpad2 = SDLK_KP_2, /// 2 key + Numpad3 = SDLK_KP_3, /// 3 key + Numpad4 = SDLK_KP_4, /// 4 key + Numpad5 = SDLK_KP_5, /// 5 key + Numpad6 = SDLK_KP_6, /// 6 key + Numpad7 = SDLK_KP_7, /// 7 key + Numpad8 = SDLK_KP_8, /// 8 key + Numpad9 = SDLK_KP_9, /// 9 key + // * Unused * + //Multiply = 0x6A, /// Multiply key + //Add = 0x6B, /// Addition key + //Separator = 0x6C, /// Seperator key + //Subtract = 0x6D, /// Subtraction key + //Decimal = 0x6E, /// Decimal key + //Divide = 0x6F, /// Division key + F1 = SDLK_F1, /// Function 1 key + F2 = SDLK_F2, /// Function 2 key + F3 = SDLK_F3, /// Function 3 key + F4 = SDLK_F4, /// Function 4 key + F5 = SDLK_F5, /// Function 5 key + F6 = SDLK_F6, /// Function 6 key + F7 = SDLK_F7, /// Function 7 key + F8 = SDLK_F8, /// Function 8 key + F9 = SDLK_F9, /// Function 9 key + F10 = SDLK_F10, /// Function 10 key + F11 = SDLK_F11, /// Function 11 key + F12 = SDLK_F12, /// Function 12 key + F13 = SDLK_F13, /// Function 13 key + F14 = SDLK_F14, /// Function 14 key + F15 = SDLK_F15, /// Function 15 key + F16 = SDLK_F16, /// Function 16 key + F17 = SDLK_F17, /// Function 17 key + F18 = SDLK_F18, /// Function 18 key + F19 = SDLK_F19, /// Function 19 key + F20 = SDLK_F20, /// Function 20 key + F21 = SDLK_F21, /// Function 21 key + F22 = SDLK_F22, /// Function 22 key + F23 = SDLK_F23, /// Function 23 key + F24 = SDLK_F24, /// Function 24 key + //Unused = 0x88-0x8F, + NumLock = SDLK_NUMLOCKCLEAR, /// Num Lock key + ScrollLock = SDLK_SCROLLLOCK, /// Scroll Lock key + //OEM = 0x92-0x96, + //Unused = 0x97-0x9F, + ShiftLeft = SDLK_LSHIFT, /// Left shift key + ShiftRight = SDLK_LSHIFT, /// Right shift key + ControlLeft = SDLK_LCTRL, /// Left control key + ControlRight= SDLK_RCTRL, /// Right control key + AltLeft = SDLK_LALT, /// Left Alt key + AltRight = SDLK_RALT, /// Right Alt key + END, +} \ No newline at end of file diff --git a/source/dash/utility/input/mouse.d b/source/dash/utility/input/mouse.d new file mode 100644 index 00000000..5d244ff0 --- /dev/null +++ b/source/dash/utility/input/mouse.d @@ -0,0 +1,29 @@ +/** + * Defines the Mouse input device. + */ +module dash.utility.input.mouse; +import dash.utility.input.inputsystem; + +/// Defines the Mouse input device. +alias Mouse = InputSystem!( MouseButtons, MouseAxes ); + +package: +// Enums of inputs +enum MouseButtons +{ + Left = 0x01, /// Left mouse button + Right = 0x02, /// Right mouse button + Middle = 0x04, /// Middle mouse button + X1 = 0x05, /// X1 mouse button + X2 = 0x06, /// X2 mouse button + END, +} + +/// Axes of input for the mouse. +enum MouseAxes +{ + ScrollWheel, + XPos, + YPos, + END, +} \ No newline at end of file diff --git a/source/dash/utility/input/package.d b/source/dash/utility/input/package.d new file mode 100644 index 00000000..d8a8fbd7 --- /dev/null +++ b/source/dash/utility/input/package.d @@ -0,0 +1,6 @@ +module dash.utility.input; +public: +import dash.utility.input.input; +import dash.utility.input.inputsystem; +import dash.utility.input.keyboard; +import dash.utility.input.mouse; From 8c9e41b92a82e033b637019f63f9615087a54fd9 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Tue, 21 Oct 2014 15:09:11 -0400 Subject: [PATCH 112/141] Added support for adding an event to a named input --- source/dash/utility/input/input.d | 161 +++++++++++++++++++++++- source/dash/utility/input/inputsystem.d | 14 ++- source/dash/utility/input/keyboard.d | 1 - 3 files changed, 169 insertions(+), 7 deletions(-) diff --git a/source/dash/utility/input/input.d b/source/dash/utility/input/input.d index 07d1b851..08372607 100644 --- a/source/dash/utility/input/input.d +++ b/source/dash/utility/input/input.d @@ -6,7 +6,12 @@ import dash.utility, dash.core, dash.graphics; import yaml; import derelict.opengl3.gl3; -import std.conv, std.uuid; +import std.algorithm, std.conv, std.uuid; + +/// The event type for button events. +package alias ButtonEvent = void delegate( ButtonStorageType ); +/// The event type for axis events. +package alias AxisEvent = void delegate( AxisStorageType ); /** * Manages all input events. @@ -28,11 +33,20 @@ private: Mouse.Buttons[] mouseButtons; //@rename( "MouseAxes" ) @optional - //Mouse.Axes[] mouseAxes; + @ignore + Mouse.Axes[] mouseAxes; } + + /// Bindings directly from Config/Input Binding[string] bindings; + /// The file the bindings came from. Resource bindingFile = Resource( "" ); + /// The registered button events. + Tuple!( UUID, ButtonEvent )[][ string ] buttonEvents; + /// The registered axis events. + Tuple!( UUID, AxisEvent )[][ string ] axisEvents; + public: /** * Processes Config/Input.yml and pulls input string bindings. @@ -66,6 +80,50 @@ public: Mouse.update(); } + /// Called by InputSystem to report changed inputs. + package void processDiffs( InputSystem, InputEnum, StateRep )( Tuple!( InputEnum, StateRep )[] diffs ) + { + // Iterate over each diff. + foreach( diff; diffs ) + { + // Iterate over each binding. + foreach( name, binding; bindings ) + { + // Get the array of bindings to check and events to call. + static if( is( InputEnum == Keyboard.Buttons ) ) + { + auto bindingArray = binding.keyboardButtons; + auto eventArray = buttonEvents; + } + else static if( is( InputEnum == Mouse.Buttons ) ) + { + auto bindingArray = binding.mouseButtons; + auto eventArray = buttonEvents; + } + else static if( is( InputEnum == Mouse.Axes ) ) + { + auto bindingArray = binding.mouseAxes; + auto eventArray = axisEvents; + } + else static assert( false, "InputEnum unsupported." ); + + // Check the binding for the changed input. + bindingsLoop: + foreach( button; bindingArray ) + { + if( button == diff[ 0 ] && name in eventArray ) + { + foreach( eventTup; eventArray[ name ] ) + { + eventTup[ 1 ]( diff[ 1 ] ); + break bindingsLoop; + } + } + } + } + } + } + /** * Gets the state of a string-bound input. * @@ -99,6 +157,7 @@ public: return 0.0f; } + else static assert( false, "Unsupported return type." ); } throw new Exception( "Input " ~ input ~ " not bound." ); @@ -127,6 +186,104 @@ public: return false; } + /** + * Check if a given button is down. + * + * Params: + * buttonName = The name of the button to check. + * checkPrevious = Whether or not to make sure the button was down last frame. + */ + bool isButtonUp( string buttonName, bool checkPrevious = false ) + { + if( auto binding = buttonName in bindings ) + { + foreach( key; binding.keyboardButtons ) + if( Keyboard.isButtonUp( key, checkPrevious ) ) + return true; + + foreach( mb; binding.mouseButtons ) + if( Mouse.isButtonUp( mb, checkPrevious ) ) + return true; + } + + return false; + } + + /** + * Add an event for when a button state changes. + * + * Params: + * buttonName = The binding name of the button for the event. + * event = The event to call when the button changes. + * + * Returns: The id of the new event. + */ + UUID addButtonEvent( string buttonName, ButtonEvent event ) + { + auto id = randomUUID(); + buttonEvents[ buttonName ] ~= tuple( id, event ); + return id; + } + + /** + * Add an event for when a button goes down. + * + * Params: + * buttonName = The binding name of the button for the event. + * event = The event to call when the button changes. + * + * Returns: The id of the new event. + */ + UUID addButtonDownEvent( string buttonName, ButtonEvent event ) + { + return addButtonEvent( buttonName, ( newState ) { if( newState ) event( newState ); } ); + } + + /** + * Add an event for when a button goes up. + * + * Params: + * buttonName = The binding name of the button for the event. + * event = The event to call when the button changes. + * + * Returns: The id of the new event. + */ + UUID addButtonUpEvent( string buttonName, ButtonEvent event ) + { + return addButtonEvent( buttonName, ( newState ) { if( !newState ) event( newState ); } ); + } + + /** + * Remove a button event. + * + * Params: + * buttonName = The binding name of the button for the event. + * event = The event to call when the button changes. + * + * Returns: The id of the new event. + */ + bool removeButtonEvent( UUID id ) + { + foreach( name, ref eventGroup; buttonEvents ) + { + auto i = eventGroup.countUntil!( tup => tup[ 0 ] == id ); + + if( i == -1 ) + continue; + + // Get tasks after one being removed.s + auto end = eventGroup[ i+1..$ ]; + // Get tasks before one being removed. + eventGroup = eventGroup[ 0..i ]; + // Add end back. + eventGroup ~= end; + + return true; + } + + return false; + } + /** * Gets the position of the cursor. * diff --git a/source/dash/utility/input/inputsystem.d b/source/dash/utility/input/inputsystem.d index 2abed509..47e8c896 100644 --- a/source/dash/utility/input/inputsystem.d +++ b/source/dash/utility/input/inputsystem.d @@ -2,10 +2,16 @@ * Defines InputSystem and State, which are used for defining an input device (keyboard, mouse, gamepad, etc.) */ module dash.utility.input.inputsystem; +import dash.utility.input.input; import std.typecons, std.traits; package: +/// The type each button is stored as. +alias ButtonStorageType = bool; +/// The type each axis is stored as. +alias AxisStorageType = float; + /** * Defines a system of inputs, buttons, axes or both. * @@ -62,6 +68,8 @@ package: if( auto buttonEvent = state[ 0 ] in buttonEvents ) foreach( event; *buttonEvent ) event( state[ 0 ], state[ 1 ] ); + + Input.processDiffs!(typeof(this))( diffButtons ); } static if( HasAxes ) { @@ -72,6 +80,8 @@ package: if( auto axisEvent = state[ 0 ] in axisEvents ) foreach( event; *axisEvent ) event( state[ 0 ], state[ 1 ] ); + + Input.processDiffs!(typeof(this))( diffAxis ); } } @@ -81,8 +91,6 @@ static if( HasButtons ) public: /// The enum of buttons that the input system has. alias Buttons = ButtonState.Inputs; - /// The type each button is stored as. - alias ButtonStorageType = bool; /// A delegate that takes the changed button and the new state. alias ButtonEvent = void delegate( Buttons, ButtonStorageType ); /// A delegate that takes the changed button. @@ -188,8 +196,6 @@ static if( HasAxes ) public: /// The enum of axes that the input system has. alias Axes = AxisState.Inputs; - /// The type each axis is stored as. - alias AxisStorageType = float; /// A delegate that takes the changed axis and the new state. alias AxisEvent = void delegate( Axes, AxisStorageType ); diff --git a/source/dash/utility/input/keyboard.d b/source/dash/utility/input/keyboard.d index c865cf7c..a132b344 100644 --- a/source/dash/utility/input/keyboard.d +++ b/source/dash/utility/input/keyboard.d @@ -149,7 +149,6 @@ enum KeyboardButtonsWin: uint END, } - enum KeyboardButtonsSDL: uint { Cancel = SDLK_CANCEL, /// Control-break From 3db9f86c6aa188dd750fca4a7cef8fc3c40e0dfe Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Wed, 22 Oct 2014 13:05:07 -0400 Subject: [PATCH 113/141] Deprecated button events on InputSystem in favor of Input, added axis event support --- source/dash/utility/input/input.d | 19 +++++++++++++++++-- source/dash/utility/input/inputsystem.d | 10 +++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/source/dash/utility/input/input.d b/source/dash/utility/input/input.d index 08372607..8324444c 100644 --- a/source/dash/utility/input/input.d +++ b/source/dash/utility/input/input.d @@ -32,8 +32,7 @@ private: @rename( "Mouse" ) @byName @optional Mouse.Buttons[] mouseButtons; - //@rename( "MouseAxes" ) @optional - @ignore + @rename( "MouseAxes" ) @byName @optional Mouse.Axes[] mouseAxes; } @@ -253,6 +252,22 @@ public: return addButtonEvent( buttonName, ( newState ) { if( !newState ) event( newState ); } ); } + /** + * Add an event for when an axis changes. + * + * Params: + * axisName = The binding name of the axis for the event. + * event = The event to call when the button changes. + * + * Returns: The id of the new event. + */ + UUID addAxisEvent( string axisName, AxisEvent event ) + { + auto id = randomUUID(); + axisEvents[ axisName ] ~= tuple( id, event ); + return id; + } + /** * Remove a button event. * diff --git a/source/dash/utility/input/inputsystem.d b/source/dash/utility/input/inputsystem.d index 47e8c896..f0019935 100644 --- a/source/dash/utility/input/inputsystem.d +++ b/source/dash/utility/input/inputsystem.d @@ -145,6 +145,7 @@ public: * buttonCode = The code of the button to add the event to. * func = The function to call when the button state changes. */ + deprecated( "Use Input.addButtonEvent with a binding instead." ) void addButtonEvent( Buttons buttonCode, ButtonEvent func ) { buttonEvents[ buttonCode ] ~= func; @@ -153,6 +154,7 @@ public: /** * Add a button event only when the button is down. */ + deprecated( "Use Input.addButtonDownEvent with a binding instead." ) void addButtonDownEvent( Buttons buttonCode, ButtonStateEvent func ) { addButtonEvent( buttonCode, ( Buttons buttonCode, ButtonStorageType newState ) { if( newState ) func( buttonCode ); } ); @@ -161,6 +163,7 @@ public: /** * Add a button event only when the button is up. */ + deprecated( "Use Input.addButtonUpEvent with a binding instead." ) void addButtonUpEvent( Buttons buttonCode, ButtonStateEvent func ) { addButtonEvent( buttonCode, ( Buttons buttonCode, ButtonStorageType newState ) { if( !newState ) func( buttonCode ); } ); @@ -219,6 +222,7 @@ public: * axis = The name of the input to add the event to. * event = The event to trigger when the axis state changes. */ + deprecated( "Use Input.addAxisEvent with a binding instead." ) void addAxisEvent( Axes axis, AxisEvent event ) { axisEvents[ axis ] ~= event; @@ -279,7 +283,7 @@ public: // an entry in keys, add it, and set it // to the default value if( !( keyCode in keys ) ) - keys[ keyCode ] = T(); + keys[ keyCode ] = cast(T)0; return keys[ keyCode ]; } @@ -304,7 +308,7 @@ public: void reset() { - for( uint ii = 0; ii < keys.length; ++ii ) - keys[ ii ] = 0; + foreach( ii; keys.keys ) + keys[ ii ] = cast(T)0; } } \ No newline at end of file From 15f2f13f7a7206f5a00978a637d8bb891ff43704 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Wed, 22 Oct 2014 17:38:17 -0400 Subject: [PATCH 114/141] Added better diagnostic messages when a (de)serialization fails --- source/dash/utility/data/serialization.d | 106 ++++++++++++++--------- 1 file changed, 64 insertions(+), 42 deletions(-) diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index 83b3bf95..8f4c6af5 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -1,7 +1,6 @@ module dash.utility.data.serialization; import dash.utility.data.yaml; -import dash.utility.resources; -import dash.utility.math; +import dash.utility.resources, dash.utility.math, dash.utility.output; import vibe.data.json, vibe.data.bson; import std.typecons: Tuple, tuple; @@ -69,20 +68,28 @@ T deserializeFile( T )( Resource file, SerializationMode mode = SerializationMod return deserializeYaml!T( Loader( file.fullPath ).load() ); } - final switch( mode ) with( SerializationMode ) + try { - case Json: return handleJson(); - case Bson: return handleBson(); - case Yaml: return handleYaml(); - case Default: - switch( file.extension.toLower ) - { - case ".json": return handleJson(); - case ".bson": return handleBson(); - case ".yaml": - case ".yml": return handleYaml(); - default: throw new Exception( "File extension " ~ file.extension.toLower ~ " not supported." ); - } + final switch( mode ) with( SerializationMode ) + { + case Json: return handleJson(); + case Bson: return handleBson(); + case Yaml: return handleYaml(); + case Default: + switch( file.extension.toLower ) + { + case ".json": return handleJson(); + case ".bson": return handleBson(); + case ".yaml": + case ".yml": return handleYaml(); + default: throw new Exception( "File extension " ~ file.extension.toLower ~ " not supported." ); + } + } + } + catch( Exception e ) + { + logError( "Error deserializing file ", file.fileName, " to type ", T.stringof, ". ", e.msg ); + return T.init; } } @@ -119,20 +126,28 @@ T[] deserializeMultiFile( T )( Resource file, SerializationMode mode = Serializa .array(); } - final switch( mode ) with( SerializationMode ) + try { - case Json: return handleJson(); - case Bson: return handleBson(); - case Yaml: return handleYaml(); - case Default: - switch( file.extension.toLower ) - { - case ".json": return handleJson(); - case ".bson": return handleBson(); - case ".yaml": - case ".yml": return handleYaml(); - default: throw new Exception( "File extension " ~ file.extension.toLower ~ " not supported." ); - } + final switch( mode ) with( SerializationMode ) + { + case Json: return handleJson(); + case Bson: return handleBson(); + case Yaml: return handleYaml(); + case Default: + switch( file.extension.toLower ) + { + case ".json": return handleJson(); + case ".bson": return handleBson(); + case ".yaml": + case ".yml": return handleYaml(); + default: throw new Exception( "File extension " ~ file.extension.toLower ~ " not supported." ); + } + } + } + catch( Exception e ) + { + logError( "Error deserializing file ", file.fileName, " to type ", T.stringof, ". ", e.msg ); + return []; } } @@ -165,21 +180,28 @@ template serializeToFile( bool prettyPrint = true ) Dumper( outPath ).dump( serializeToYaml( t ) ); } - final switch( mode ) with( SerializationMode ) + try { - case Json: handleJson(); break; - case Bson: handleBson(); break; - case Yaml: handleYaml(); break; - case Default: - switch( outPath.extension.toLower ) - { - case ".json": handleJson(); break; - case ".bson": handleBson(); break; - case ".yaml": - case ".yml": handleYaml(); break; - default: throw new Exception( "File extension " ~ outPath.extension.toLower ~ " not supported." ); - } - break; + final switch( mode ) with( SerializationMode ) + { + case Json: handleJson(); break; + case Bson: handleBson(); break; + case Yaml: handleYaml(); break; + case Default: + switch( outPath.extension.toLower ) + { + case ".json": handleJson(); break; + case ".bson": handleBson(); break; + case ".yaml": + case ".yml": handleYaml(); break; + default: throw new Exception( "File extension " ~ outPath.extension.toLower ~ " not supported." ); + } + break; + } + } + catch( Exception e ) + { + logError( "Error serializing ", T.stringof, " to file ", file.fileName, ". ", e.msg ); } } } From 8e5a2449337f292f93082eeef456abeca2d46553 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 23 Oct 2014 15:38:30 -0400 Subject: [PATCH 115/141] Improve diagnostic messages for the yaml deserializer --- source/dash/utility/data/yaml.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/dash/utility/data/yaml.d b/source/dash/utility/data/yaml.d index 7795f03f..4b0e42f3 100644 --- a/source/dash/utility/data/yaml.d +++ b/source/dash/utility/data/yaml.d @@ -256,7 +256,7 @@ public: // void readDictionary( T )( scope void delegate( string ) field_handler ) { - enforceYaml( m_current.isMapping ); + enforceYaml( m_current.isMapping, "Yaml map expected, got a " ~ ( m_current.isScalar ? "scalar" : "sequence" ) ~ " instead." ); auto old = m_current; foreach( string key, Node value; m_current ) @@ -269,7 +269,7 @@ public: void readArray( T )( scope void delegate( size_t ) size_callback, scope void delegate() entry_callback ) { - enforceYaml( m_current.isSequence || m_current.isScalar ); + enforceYaml( m_current.isSequence || m_current.isScalar, "Yaml scalar or sequence expected, got a map instead." ); if( m_current.isSequence ) { From 87d8514bc9111a39eeeaa36bdd4c0d0bb1c1a58f Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 23 Oct 2014 16:48:23 -0400 Subject: [PATCH 116/141] Fixed merge issue with Input and develop --- source/dash/utility/input/input.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dash/utility/input/input.d b/source/dash/utility/input/input.d index 8324444c..9fc6e3b5 100644 --- a/source/dash/utility/input/input.d +++ b/source/dash/utility/input/input.d @@ -39,7 +39,7 @@ private: /// Bindings directly from Config/Input Binding[string] bindings; /// The file the bindings came from. - Resource bindingFile = Resource( "" ); + Resource bindingFile = internalResource; /// The registered button events. Tuple!( UUID, ButtonEvent )[][ string ] buttonEvents; From 946d919ef50234b4d466c2d8e87b7a5beec5e7a5 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Fri, 24 Oct 2014 12:18:29 -0400 Subject: [PATCH 117/141] Add check for mutability to serialization selection --- source/dash/components/component.d | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 7da1ef31..85b9ac6d 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -14,6 +14,20 @@ alias helper( alias T ) = T; alias helper( T... ) = T; alias helper() = TypeTuple!(); +template isSerializableField( alias field ) +{ + import vibe.internal.meta.uda; + +public: + enum isSerializableField = + !isSomeFunction!field && + isMutable!fieldType && + !findFirstUDA!( IgnoreAttribute, field ).found; + +private: + alias fieldType = typeof(field); +} + /** * Interface for components to implement. */ @@ -323,13 +337,11 @@ private: static if( !memberName.among( "this", "~this", __traits( allMembers, Component ) ) && is( typeof( helper!( __traits( getMember, T, memberName ) ) ) ) ) { - import vibe.internal.meta.uda; - alias member = helper!( __traits( getMember, T, memberName ) ); alias memberType = typeof(member); // Process variables - static if( !isSomeFunction!member && !findFirstUDA!( IgnoreAttribute, member ).found ) + static if( isSerializableField!member ) { // Get string form of attributes string attributesStr() From 09c9424b9bbaf723fc614fd6f5570977ca0b8f73 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Fri, 24 Oct 2014 12:32:46 -0400 Subject: [PATCH 118/141] Added an option to self-register a component --- source/dash/components/audio.d | 6 ++---- source/dash/components/component.d | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/source/dash/components/audio.d b/source/dash/components/audio.d index e57cbae5..34610734 100644 --- a/source/dash/components/audio.d +++ b/source/dash/components/audio.d @@ -5,13 +5,11 @@ module dash.components.audio; import dash.core.properties, dash.components, dash.utility, dash.utility.soloud; import std.string; -mixin( registerComponents!() ); - /** * Listener object that hears sounds and sends them to the audio output device * (usually attaced to the camera) */ -class Listener : Component +class Listener : ComponentReg!Listener { private: @@ -36,7 +34,7 @@ public: /** * Emitter object that plays sounds that listeners can hear */ -class Emitter : Component +class Emitter : ComponentReg!Emitter { private: Modplug toPlay; diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 85b9ac6d..42bd14b5 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -72,6 +72,30 @@ public: alias Description = .Description; } +/** + * A self-registering component. + * Useful for when you receive circular dependency errors. + * Recommended for use only when extending Component directly. + * + * Params: + * BaseType = The type being registered. + * + * Examples: + * --- + * class MyComponent : ComponentReg!MyComponent + * { + * // ... + * } + * --- + */ +abstract class ComponentReg( BaseType ) : Component +{ + static this() + { + componentMetadata!(Unqual!(BaseType)).register(); + } +} + /// A map of all registered Component types to their descriptions private immutable(Description)[ClassInfo] descriptionsByClassInfo; private immutable(Description)[string] descriptionsByName; From ed94e3e48932e455244e8c958f46abb851bf0343 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 30 Oct 2014 14:45:36 -0400 Subject: [PATCH 119/141] Moved bindings into special dash.utility.bindings package --- source/dash/components/audio.d | 2 +- source/dash/components/userinterface.d | 2 +- source/dash/core/dgame.d | 2 +- source/dash/utility/{ => bindings}/awesomium.d | 2 +- source/dash/utility/{ => bindings}/soloud.d | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename source/dash/utility/{ => bindings}/awesomium.d (99%) rename source/dash/utility/{ => bindings}/soloud.d (99%) diff --git a/source/dash/components/audio.d b/source/dash/components/audio.d index 34610734..82e9fc26 100644 --- a/source/dash/components/audio.d +++ b/source/dash/components/audio.d @@ -2,7 +2,7 @@ * Defines audio related classes, such as the listener and emitter */ module dash.components.audio; -import dash.core.properties, dash.components, dash.utility, dash.utility.soloud; +import dash.core.properties, dash.components, dash.utility, dash.utility.bindings.soloud; import std.string; /** diff --git a/source/dash/components/userinterface.d b/source/dash/components/userinterface.d index e610d2bc..5a325df1 100644 --- a/source/dash/components/userinterface.d +++ b/source/dash/components/userinterface.d @@ -2,7 +2,7 @@ * Handles the creation and life cycle of UI objects and webview textures */ module dash.components.userinterface; -import dash.core, dash.utility.awesomium, dash.components, dash.utility, dash.graphics.graphics; +import dash, dash.utility.bindings.awesomium; import std.string; diff --git a/source/dash/core/dgame.d b/source/dash/core/dgame.d index 6ea0b452..c625a4f3 100644 --- a/source/dash/core/dgame.d +++ b/source/dash/core/dgame.d @@ -2,7 +2,7 @@ * Defines the DGame class, the base class for all game logic. */ module dash.core.dgame; -import dash, dash.utility.awesomium; +import dash; import core.memory; /** diff --git a/source/dash/utility/awesomium.d b/source/dash/utility/bindings/awesomium.d similarity index 99% rename from source/dash/utility/awesomium.d rename to source/dash/utility/bindings/awesomium.d index 398410d1..6744c886 100644 --- a/source/dash/utility/awesomium.d +++ b/source/dash/utility/bindings/awesomium.d @@ -1,4 +1,4 @@ -module dash.utility.awesomium; +module dash.utility.bindings.awesomium; version( Windows ): diff --git a/source/dash/utility/soloud.d b/source/dash/utility/bindings/soloud.d similarity index 99% rename from source/dash/utility/soloud.d rename to source/dash/utility/bindings/soloud.d index c2916ba6..438b7560 100644 --- a/source/dash/utility/soloud.d +++ b/source/dash/utility/bindings/soloud.d @@ -2,7 +2,7 @@ // SoLoud wrapper for D // This file is autogenerated; any changes will be overwritten -module dash.utility.soloud; +module dash.utility.bindings.soloud; pure @safe nothrow @nogc: From 689989887a03bec2f78df6e174e6bf0b5de7143c Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 30 Oct 2014 14:52:31 -0400 Subject: [PATCH 120/141] Renamed Description.create to Description.fromComponent, added docs --- source/dash/components/component.d | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 42bd14b5..766d5b2d 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -57,7 +57,7 @@ public: */ final const(Description) description() @property { - return getDescription( typeid(this) ).create( this ); + return getDescription( typeid(this) ).fromComponent( this ); } /** @@ -139,7 +139,7 @@ public: abstract void refresh( Component comp, const Description newDesc ); /// Creates a description from a component. - abstract const(Description) create( const Component comp ) const; + abstract const(Description) fromComponent( const Component comp ) const; /// Get the type of the component the description is for. @ignore @@ -217,7 +217,7 @@ enum registerComponents( string modName = __MODULE__ ) = q{ template componentMetadata( T ) if( isComponent!T ) { public: - // Runtime function, registers serializers + /// Runtime function, registers serializers. void register() { immutable desc = new immutable SerializationDescription; @@ -225,11 +225,24 @@ public: descriptionsByName[ T.stringof ] = desc; } - // Generate description + /// A list of fields on the component. enum fieldList = getFields(); + /// The size of an instance of the component. + enum instanceSize = __traits( classInstanceSize, T ); + private: - // Generate actual struct + /** + * Generate actual description of a component. + * + * Contains: + * * A represenetation of each field on the component at root level. + * * A list of the fields ($(D fields)). + * * A method to create a description from an instance of a component ($(D fromComponent)). + * * A method to refresh an instance of the component with a newer description ($(D refresh)). + * * A method to create an instance of the component ($(D createInstance)). + * * The ClassInfo of the component ($(D componentType)). + */ final class SerializationDescription : Description { mixin( { return reduce!( ( working, field ) { @@ -260,7 +273,7 @@ private: } /// Create a description from a component. - override const(SerializationDescription) create( const Component comp ) const + override const(SerializationDescription) fromComponent( const Component comp ) const { auto theThing = cast(T)comp; auto desc = new SerializationDescription; From 193af06c1887f420042d3ff208344b77c23a515b Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 30 Oct 2014 15:30:36 -0400 Subject: [PATCH 121/141] "Fixed" circular component references --- source/dash/components/component.d | 62 ++++++++++++++++++++++-- source/dash/utility/data/serialization.d | 7 +++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index 766d5b2d..c406cdf5 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -5,7 +5,7 @@ module dash.components.component; import dash.core, dash.components, dash.graphics, dash.utility; import vibe.data.bson, vibe.data.json, dash.utility.data.yaml; -import std.algorithm, std.array, std.string, std.traits, std.conv, std.typecons; +import std.algorithm, std.array, std.string, std.traits, std.conv, std.typecons, std.uuid; /// Tests if a type can be created from yaml. enum isComponent(alias T) = is( T == class ) && is( T : Component ) && !__traits( isAbstractClass, T ); @@ -35,14 +35,41 @@ abstract class Component { private: /// The description from the last creation/refresh. - @ignore Description lastDesc; + /// The id of the component. + UUID _id; + public: + this() + { + _id = randomUUID(); + instantiatedComponents[ _id ] = this; + } + /// The GameObject that owns this component. @ignore GameObject owner; + /// The id of the component. + @optional + UUID id() const pure nothrow @safe @property + { + return _id; + } + ///ditto + @optional + void id( UUID newId ) nothrow @safe @property + { + if( _id in instantiatedComponents ) + { + instantiatedComponents.remove( _id ); + } + + _id = newId; + instantiatedComponents[ _id ] = this; + } + /// The function called on initialization of the object. void initialize() { } /// Called on the update cycle. @@ -99,6 +126,7 @@ abstract class ComponentReg( BaseType ) : Component /// A map of all registered Component types to their descriptions private immutable(Description)[ClassInfo] descriptionsByClassInfo; private immutable(Description)[string] descriptionsByName; +private Component[UUID] instantiatedComponents; immutable(Description) getDescription( ClassInfo type ) { @@ -110,6 +138,16 @@ immutable(Description) getDescription( string name ) return descriptionsByName.get( name, null ); } +Component getComponent( UUID id ) +{ + return instantiatedComponents.get( id, null ); +} + +T getComponent( T )( UUID id ) if( is( T : Component ) ) +{ + return cast(T)getComponent( id ); +} + /// The description for the component abstract class Description { @@ -186,6 +224,19 @@ public: } ); } +//package( dash ) +/** + * Used when serializing components, stores the type name and the id of that component. + */ +struct ComponentReference +{ + @rename( "Type" ) + string type; + + @rename( "Id" ) + uint id; +} + /** * To be placed at the top of any module defining YamlComponents. * @@ -222,7 +273,7 @@ public: { immutable desc = new immutable SerializationDescription; descriptionsByClassInfo[ typeid(T) ] = desc; - descriptionsByName[ T.stringof ] = desc; + descriptionsByName[ name ] = desc; } /// A list of fields on the component. @@ -231,6 +282,9 @@ public: /// The size of an instance of the component. enum instanceSize = __traits( classInstanceSize, T ); + /// The name of the component. + enum name = __traits( identifier, T ); + private: /** * Generate actual description of a component. @@ -277,7 +331,7 @@ private: { auto theThing = cast(T)comp; auto desc = new SerializationDescription; - desc.type = T.stringof; + desc.type = name; foreach( fieldName; __traits( allMembers, T ) ) { diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index d0d598be..1fcca659 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -245,8 +245,15 @@ enum hasSerializer( T ) = anySatisfy!( isSerializerFor!T, customSerializers ); /// Get the serializer for a type template serializerFor( T ) { + import dash.components.component; + static if( hasSerializer!T ) alias serializerFor = Filter!( isSerializerFor!T, customSerializers )[ 0 ]; + else static if( is( T : Component ) ) + alias serializerFor = CustomSerializer!( T, ComponentReference, + t => ComponentReference( componentMetadata!T.name, t.id ), + r => getComponent( r.id ), + r => !r.id.empty && t.name ); else alias serializerFor = defaultSerializer!T; } From 5c5583454e141cebfaf7bc17180f271ea2421a4d Mon Sep 17 00:00:00 2001 From: Daniel Jost Date: Thu, 30 Oct 2014 15:53:03 -0400 Subject: [PATCH 122/141] Updated description in dub.json. --- dub.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dub.json b/dub.json index 644775af..99239503 100644 --- a/dub.json +++ b/dub.json @@ -1,6 +1,6 @@ { "name": "dash", - "description": "A 3D game engine in dlang.", + "description": "A free and open 3D game engine written in D.", "copyright": "Circular Studios 2013 - 2014", "license": "MIT", "homepage": "http://circularstudios.com", From e91b85085bb765a9af1dba559c9d209dfe08477c Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 6 Nov 2014 14:11:27 -0500 Subject: [PATCH 123/141] Revert ""Fixed" circular component references" --- source/dash/components/component.d | 55 ++---------------------------- 1 file changed, 2 insertions(+), 53 deletions(-) diff --git a/source/dash/components/component.d b/source/dash/components/component.d index c406cdf5..d87360eb 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -5,7 +5,7 @@ module dash.components.component; import dash.core, dash.components, dash.graphics, dash.utility; import vibe.data.bson, vibe.data.json, dash.utility.data.yaml; -import std.algorithm, std.array, std.string, std.traits, std.conv, std.typecons, std.uuid; +import std.algorithm, std.array, std.string, std.traits, std.conv, std.typecons; /// Tests if a type can be created from yaml. enum isComponent(alias T) = is( T == class ) && is( T : Component ) && !__traits( isAbstractClass, T ); @@ -35,41 +35,14 @@ abstract class Component { private: /// The description from the last creation/refresh. + @ignore Description lastDesc; - /// The id of the component. - UUID _id; - public: - this() - { - _id = randomUUID(); - instantiatedComponents[ _id ] = this; - } - /// The GameObject that owns this component. @ignore GameObject owner; - /// The id of the component. - @optional - UUID id() const pure nothrow @safe @property - { - return _id; - } - ///ditto - @optional - void id( UUID newId ) nothrow @safe @property - { - if( _id in instantiatedComponents ) - { - instantiatedComponents.remove( _id ); - } - - _id = newId; - instantiatedComponents[ _id ] = this; - } - /// The function called on initialization of the object. void initialize() { } /// Called on the update cycle. @@ -126,7 +99,6 @@ abstract class ComponentReg( BaseType ) : Component /// A map of all registered Component types to their descriptions private immutable(Description)[ClassInfo] descriptionsByClassInfo; private immutable(Description)[string] descriptionsByName; -private Component[UUID] instantiatedComponents; immutable(Description) getDescription( ClassInfo type ) { @@ -138,16 +110,6 @@ immutable(Description) getDescription( string name ) return descriptionsByName.get( name, null ); } -Component getComponent( UUID id ) -{ - return instantiatedComponents.get( id, null ); -} - -T getComponent( T )( UUID id ) if( is( T : Component ) ) -{ - return cast(T)getComponent( id ); -} - /// The description for the component abstract class Description { @@ -224,19 +186,6 @@ public: } ); } -//package( dash ) -/** - * Used when serializing components, stores the type name and the id of that component. - */ -struct ComponentReference -{ - @rename( "Type" ) - string type; - - @rename( "Id" ) - uint id; -} - /** * To be placed at the top of any module defining YamlComponents. * From 20dadb3587aeaf02002c63790d896c0c34d6bd8d Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 8 Nov 2014 14:44:40 -0500 Subject: [PATCH 124/141] Made editor template functions inferrable --- dub.json | 2 +- source/dash/editor/editor.d | 79 ++++++++++++++++++++++++------------- source/dash/editor/events.d | 28 ++++++------- 3 files changed, 65 insertions(+), 44 deletions(-) diff --git a/dub.json b/dub.json index 99239503..b163b641 100644 --- a/dub.json +++ b/dub.json @@ -25,7 +25,7 @@ "gfm:sdl2": "==1.3.3", "dlogg": "~>0.3", "msgpack-d": "==0.9.2", - "vibe-d": "0.7.21-rc.3", + "vibe-d": "0.7.21-rc.4", "x11": { "version": "~>1.0", "optional": true } }, diff --git a/source/dash/editor/editor.d b/source/dash/editor/editor.d index 5f273721..e6c8369b 100644 --- a/source/dash/editor/editor.d +++ b/source/dash/editor/editor.d @@ -15,10 +15,6 @@ import std.uuid, std.typecons; class Editor { public: - // Event handlers - alias EventHandler( DataType ) = void delegate( DataType ); - alias EventResponseHandler( DataType, ResponseType ) = ResponseType delegate( DataType ); - /** * Initializes the editor with a DGame instance. * @@ -74,12 +70,23 @@ public: /** * Sends a message to all attached editors. * + * In most cases, you won't have to manually specify template parameters, + * they should be inferred. + * * Params: * key = The key of the event. * value = The data along side it. * cb = The callback to call when a response is received. + * + * Examples: + * --- + * // DataType inferred as string, ResponseType inferred as string. + * editor.send( "my_key", "my_value", ( string response ) { + * // Handle response + * } ); + * --- */ - final void send( ResponseType = EventResponse, DataType )( string key, DataType value, EventHandler!ResponseType cb ) + final void send( DataType, ResponseType )( string key, DataType value, void delegate( ResponseType ) cb ) { UUID cbId = randomUUID(); registerCallbackHandler( cbId, msg => cb( msg.value.deserializeJson!ResponseType ) ); @@ -91,7 +98,7 @@ public: server.send( msg ); } - static assert(is(typeof( send!( string )( "key", "data", ( string response ) { } ) ))); + static assert(is(typeof( send( "key", "data", ( string response ) { } ) ))); /** * Registers an event callback, for when an event with the given key is received. @@ -100,40 +107,56 @@ public: * key = The key of the event. * event = The handler to call. * - * Returns: The ID of the event, so it can be unregistered later. - */ - final UUID registerEventHandler( DataType )( string key, EventHandler!DataType event ) - { - return registerInternalMessageHandler( key, msg => event( msg.value.deserializeJson!DataType ) ); - } - static assert(is(typeof( registerEventHandler!string( "key", ( string resp ) { } ) ))); - - /** - * Registers an event callback, for when an event with the given key is received. - * - * Params: - * key = The key of the event. - * event = The handler to call. + * * Examples: + * --- + * // DataType inferred as string, ResponseType inferred as string. + * editor.registerEventHandler( "loopback", ( string receivedData ) { + * // Handle response + * // Return your response, or nothing if signify success without response. + * return receivedData; + * } ); * * Returns: The ID of the event, so it can be unregistered later. */ - final UUID registerEventHandler( DataType, ResponseType )( string key, EventResponseHandler!( DataType, ResponseType ) event ) + final UUID registerEventHandler( DataType, ResponseType )( string key, ResponseType delegate( DataType ) event ) { void handler( EventMessage msg ) { - ResponseType res = event( msg.value.deserializeJson!DataType ); + // Automatically deserialize received data to requested type. + try + { + DataType receivedData = msg.value.deserializeJson!DataType; + } + catch( JSONException e ) + { + logError( "Error deserializing received message with key \"", key, "\" to ", __traits( identifier, DataType ), ": ", e.msg ); + return; + } - EventMessage newMsg; - newMsg.key = CallbackMessageKey; - newMsg.value = res.serializeToJsonString(); - newMsg.callbackId = msg.callbackId; + static if(is( ResponseType == void )) + { + // Call the event handler. + event( receivedData ); + } + else + { + // Call the event handler, and capture the result. + ResponseType res = event( receivedData ); + + // Create a message with the callback id, and the response of the event. + EventMessage newMsg; + newMsg.key = CallbackMessageKey; + newMsg.value = res.serializeToJson(); + newMsg.callbackId = msg.callbackId; - server.send( newMsg ); + server.send( newMsg ); + } } return registerInternalMessageHandler( key, &handler ); } - static assert(is(typeof( registerEventHandler!( string, string )( "key", data => data ) ))); + static assert(is(typeof( registerEventHandler( "key", ( string data ) { } ) ))); + static assert(is(typeof( registerEventHandler( "key", ( string data ) => data ) ))); /** * Unregisters an event callback. diff --git a/source/dash/editor/events.d b/source/dash/editor/events.d index 72c2ae82..2e219f71 100644 --- a/source/dash/editor/events.d +++ b/source/dash/editor/events.d @@ -6,24 +6,24 @@ import vibe.data.json; import std.typecons, std.functional; public: -/// Status of a request -enum Status -{ - ok = 0, - warning = 1, - error = 2, -} /// Easy to handle response struct. struct EventResponse { + /// Status of a request + enum Status + { + ok = 0, + warning = 1, + error = 2, + } + Status status; - string message; Json data; } /// Shortcut to generate response. -EventResponse res( DataType = Json )( Status s, string m = "success", DataType d = DataType.init ) +EventResponse res( DataType = Json )( EventResponse.Status s, DataType d = DataType.init ) { - return EventResponse( s, m, d.serializeToJson() ); + return EventResponse( s, d.serializeToJson() ); } struct response @@ -31,11 +31,9 @@ struct response @disable this(); /// Basic ok response. - alias ok = partial!( res, Status.ok ); - /// Warning response - alias warning = partial!( res, Status.warning ); + alias ok = partial!( res, EventResponse.Status.ok ); /// Error response - alias error = partial!( res, Status.error ); + alias error = partial!( res, EventResponse.Status.error ); } package: @@ -48,7 +46,7 @@ void registerGameEvents( Editor ed, DGame game ) } ); ed.registerEventHandler!( Json, EventResponse )( "dgame:scene:get_objects", ( _ ) { - return response.ok( "success", game.activeScene.objects ); + return response.ok( game.activeScene.objects ); } ); } From bfddf781ee2613557d3e89c2c673b8bf4974bd43 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 8 Nov 2014 15:17:07 -0500 Subject: [PATCH 125/141] [Editor] Greatly simplified method for responding from event handlers --- source/dash/editor/editor.d | 74 +++++++++++++++++++++++++++++-------- source/dash/editor/events.d | 48 ++++-------------------- 2 files changed, 65 insertions(+), 57 deletions(-) diff --git a/source/dash/editor/editor.d b/source/dash/editor/editor.d index e6c8369b..dd5cd906 100644 --- a/source/dash/editor/editor.d +++ b/source/dash/editor/editor.d @@ -123,34 +123,53 @@ public: void handler( EventMessage msg ) { // Automatically deserialize received data to requested type. + DataType receivedData; try { - DataType receivedData = msg.value.deserializeJson!DataType; + receivedData = msg.value.deserializeJson!DataType; } catch( JSONException e ) { - logError( "Error deserializing received message with key \"", key, "\" to ", __traits( identifier, DataType ), ": ", e.msg ); + logError( "Error deserializing received message with key \"", key, "\" to ", DataType.stringof, ": ", e.msg ); return; } - static if(is( ResponseType == void )) + // Create a message with the callback id, and the response of the event. + EventMessage newMsg; + newMsg.key = CallbackMessageKey; + newMsg.callbackId = msg.callbackId; + + // Build response to send back + EventResponse res; + + try { - // Call the event handler. - event( receivedData ); + static if(is( ResponseType == void )) + { + // Call the event handler. + event( receivedData ); + res.data = Json( "success" ); + } + else + { + // Call the event handler, and capture the result. + ResponseType result = event( receivedData ); + res.data = result.serializeToJson(); + } + + // If we've made it this far, it's a success + res.status = EventResponse.Status.ok; } - else + catch( Exception e ) { - // Call the event handler, and capture the result. - ResponseType res = event( receivedData ); - - // Create a message with the callback id, and the response of the event. - EventMessage newMsg; - newMsg.key = CallbackMessageKey; - newMsg.value = res.serializeToJson(); - newMsg.callbackId = msg.callbackId; - - server.send( newMsg ); + // If failure, send exception. + res.status = EventResponse.Status.error; + res.data = e.exceptionToJson(); } + + // Serialize response, and sent it across. + newMsg.value = res.serializeToJson(); + server.send( newMsg ); } return registerInternalMessageHandler( key, &handler ); @@ -279,3 +298,26 @@ private: EventHandlerTuple[][string] eventHandlers; InternalEventHandler[UUID] callbacks; } + +/// Easy to handle response struct. +private struct EventResponse +{ + /// Status of a request + enum Status + { + ok = 0, + error = 2, + } + + Status status; + Json data; +} + +Json exceptionToJson( Exception e ) +{ + Json except = Json.emptyObject; + except[ "msg" ] = e.msg; + except[ "line" ] = e.line; + except[ "file" ] = e.file; + return except; +} diff --git a/source/dash/editor/events.d b/source/dash/editor/events.d index 2e219f71..8206c079 100644 --- a/source/dash/editor/events.d +++ b/source/dash/editor/events.d @@ -5,48 +5,16 @@ import dash.core, dash.components.component; import vibe.data.json; import std.typecons, std.functional; -public: -/// Easy to handle response struct. -struct EventResponse -{ - /// Status of a request - enum Status - { - ok = 0, - warning = 1, - error = 2, - } - - Status status; - Json data; -} -/// Shortcut to generate response. -EventResponse res( DataType = Json )( EventResponse.Status s, DataType d = DataType.init ) -{ - return EventResponse( s, d.serializeToJson() ); -} - -struct response -{ - @disable this(); - - /// Basic ok response. - alias ok = partial!( res, EventResponse.Status.ok ); - /// Error response - alias error = partial!( res, EventResponse.Status.error ); -} - package: void registerGameEvents( Editor ed, DGame game ) { // Triggers an engine refresh - ed.registerEventHandler!( Json, EventResponse )( "dgame:refresh", ( _ ) { + ed.registerEventHandler( "dgame:refresh", ( Json _ ) { game.currentState = EngineState.Refresh; - return response.ok; } ); - ed.registerEventHandler!( Json, EventResponse )( "dgame:scene:get_objects", ( _ ) { - return response.ok( game.activeScene.objects ); + ed.registerEventHandler( "dgame:scene:get_objects", ( Json _ ) { + return game.activeScene.objects; } ); } @@ -58,15 +26,14 @@ void registerObjectEvents( Editor ed, DGame game ) string objectName; GameObject.Description description; } - ed.registerEventHandler!( RefreshRequest, EventResponse )( "object:refresh", ( req ) { + ed.registerEventHandler( "object:refresh", ( RefreshRequest req ) { if( auto obj = game.activeScene[ req.objectName ] ) { obj.refresh( req.description ); - return response.ok; } else { - return response.error( "Object " ~ req.objectName ~ " not found." ); + throw new Exception( "Object " ~ req.objectName ~ " not found." ); } } ); @@ -77,15 +44,14 @@ void registerObjectEvents( Editor ed, DGame game ) string componentName; Component.Description description; } - ed.registerEventHandler!( ComponentRefreshRequest, EventResponse )( "object:component:refresh", ( req ) { + ed.registerEventHandler( "object:component:refresh", ( ComponentRefreshRequest req ) { if( auto obj = game.activeScene[ req.objectName ] ) { obj.refreshComponent( req.componentName, req.description ); - return response.ok; } else { - return response.error( "Object " ~ req.objectName ~ " not found." ); + throw new Exception( "Object " ~ req.objectName ~ " not found." ); } } ); } From ab9444ce794f8c3e1d734fd59543dd09b194242f Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 8 Nov 2014 15:48:28 -0500 Subject: [PATCH 126/141] [Editor] dash.js now responds with EventResponses, so they should be handled --- source/dash/editor/editor.d | 45 ++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/source/dash/editor/editor.d b/source/dash/editor/editor.d index dd5cd906..a55428b1 100644 --- a/source/dash/editor/editor.d +++ b/source/dash/editor/editor.d @@ -59,11 +59,7 @@ public: */ final void send( DataType )( string key, DataType value ) { - EventMessage msg; - msg.key = key; - msg.value = value.serializeToJson(); - - server.send( msg ); + send( key, value, ( Json res ) { } ); } static assert(is(typeof( send( "key", "data" ) ))); @@ -89,7 +85,17 @@ public: final void send( DataType, ResponseType )( string key, DataType value, void delegate( ResponseType ) cb ) { UUID cbId = randomUUID(); - registerCallbackHandler( cbId, msg => cb( msg.value.deserializeJson!ResponseType ) ); + + void callbackHandler( EventMessage msg ) + { + auto response = msg.value.deserializeJson!EventResponse; + + if( response.status == EventResponse.Status.ok ) + cb( response.data.deserializeJson!ResponseType ); + else + throw response.data.deserializeJson!TransferableException().toException(); + } + registerCallbackHandler( cbId, &callbackHandler ); EventMessage msg; msg.key = key; @@ -164,7 +170,7 @@ public: { // If failure, send exception. res.status = EventResponse.Status.error; - res.data = e.exceptionToJson(); + res.data = TransferableException.fromException( e ).serializeToJson(); } // Serialize response, and sent it across. @@ -313,11 +319,24 @@ private struct EventResponse Json data; } -Json exceptionToJson( Exception e ) +// Exception that can be serialized +struct TransferableException { - Json except = Json.emptyObject; - except[ "msg" ] = e.msg; - except[ "line" ] = e.line; - except[ "file" ] = e.file; - return except; + string msg; + size_t line; + string file; + + static TransferableException fromException( Exception e ) + { + TransferableException except; + except.msg = e.msg; + except.line = e.line; + except.file = e.file; + return except; + } + + Exception toException() + { + return new Exception( msg, file, line ); + } } From 2971f51edee30dd04aaaff2ef7507f49325d76a4 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 6 Nov 2014 17:23:06 -0500 Subject: [PATCH 127/141] dash.utility.output now implements the std.logger standard --- dub.json | 5 +- source/dash/core/dgame.d | 3 +- source/dash/utility/config.d | 18 ++- source/dash/utility/output.d | 251 +++++++++++++++++------------------ 4 files changed, 139 insertions(+), 138 deletions(-) diff --git a/dub.json b/dub.json index b163b641..f1fa4315 100644 --- a/dub.json +++ b/dub.json @@ -22,8 +22,9 @@ "derelict-assimp3": "~>1.0", "dyaml": "~>0.5", "gl3n": "==1.0.0", - "gfm:sdl2": "==1.3.3", - "dlogg": "~>0.3", + "gfm:sdl2": "==1.3.8", + "logger": "==0.3.3", + "colorize": "==1.0.5", "msgpack-d": "==0.9.2", "vibe-d": "0.7.21-rc.4", "x11": { "version": "~>1.0", "optional": true } diff --git a/source/dash/core/dgame.d b/source/dash/core/dgame.d index c625a4f3..4ee0ce8d 100644 --- a/source/dash/core/dgame.d +++ b/source/dash/core/dgame.d @@ -203,9 +203,8 @@ private: stateFlags = new GameStateFlags; stateFlags.resumeAll(); - logDebug( "Initializing..." ); bench!( { Config.initialize(); } )( "Config init" ); - bench!( { Logger.initialize(); } )( "Logger init" ); + bench!( { DashLogger.initialize(); } )( "Logger init" ); bench!( { Input.initialize(); } )( "Input init" ); bench!( { Graphics.initialize(); } )( "Graphics init" ); bench!( { Assets.initialize(); } )( "Assets init" ); diff --git a/source/dash/utility/config.d b/source/dash/utility/config.d index dedc8a7c..d35497ad 100644 --- a/source/dash/utility/config.d +++ b/source/dash/utility/config.d @@ -4,6 +4,7 @@ module dash.utility.config; import dash.utility.resources, dash.utility.output, dash.utility.data; +import std.experimental.logger; import std.datetime; /** @@ -36,18 +37,25 @@ public: static struct LoggerSettings { @rename( "FilePath" ) @optional - string filePath = null; + string filePath = "dash.log"; @rename( "Debug" ) @optional - Verbosities debug_ = Verbosities( Verbosity.Debug, Verbosity.Debug ); + Verbosities debug_ = Verbosities( LogLevel.all, LogLevel.all ); @rename( "Release" ) @optional - Verbosities release = Verbosities( Verbosity.Off, Verbosity.High ); + Verbosities release = Verbosities( LogLevel.off, LogLevel.error ); + + @ignore + Verbosities verbosities() const @property pure @safe nothrow @nogc + { + debug return debug_; + else return release; + } static struct Verbosities { @rename( "OutputVerbosity" ) @optional @byName - Verbosity outputVerbosity = Verbosity.Low; + LogLevel outputVerbosity = LogLevel.info; @rename( "LoggingVerbosity" ) @optional @byName - Verbosity loggingVerbosity = Verbosity.Debug; + LogLevel loggingVerbosity = LogLevel.all; } } diff --git a/source/dash/utility/output.d b/source/dash/utility/output.d index b8e9e710..1ceeaccf 100644 --- a/source/dash/utility/output.d +++ b/source/dash/utility/output.d @@ -1,157 +1,150 @@ /** - * Defines the static Output class, which handles all output to the console window. + * Defines the Dash logger, using the std.logger proposal. */ module dash.utility.output; -import dash.utility.config; -import dlogg.strict; -import std.conv; -import std.stdio; -import std.functional; +public import std.experimental.logger; + +import colorize; + +deprecated( "Use trace() instead" ) +alias logDebug = trace; +deprecated( "Use info() instead" ) +alias logInfo = info; +deprecated( "Use info() instead" ) +alias logNotice = info; +deprecated( "Use warning() instead" ) +alias logWarning = warning; +deprecated( "Use error() instead" ) +alias logError = error; +deprecated( "Use fatal() instead" ) +alias logFatal = fatal; /** -* Custom logging level type for global logger. +* Benchmark the running of a function, and log the result to the debug buffer. +* +* Params: +* func = The function to benchmark +* name = The name to print in the log */ -enum OutputType +void bench( alias func )( lazy string name ) { - /// Debug messages, aren't compiled in release version - Debug, - /// Diagnostic messages about program state - Info, - /// Non fatal errors - Warning, - /// Fatal errors that usually stop application - Error, - /// Messages of the level don't go to output. - /// That used with minLoggingLevel and minOutputLevel - /// to suppress any message. - Muted + import std.datetime, core.time; + auto result = cast(Duration)benchmark!func( 1 ); + tracef( "%s time:\t\t\t%s", name, result ); } /** - * The levels of output available. + * Dash's custom logger. */ -enum Verbosity +class DashLogger : FileLogger { - /// Show me everything++. - /// Debug msgs are cut off in release - /// version. - Debug, - /// Show me everything. - High, - /// Show me things that shouldn't have happened. - Medium, - /// I only care about things gone horribly wrong. - Low, - /// I like to live on the edge. - Off, -} + static MultiLogger multiLogger; + static DashLogger consoleLogger; + static DashLogger fileLogger; -/** - * Wrapper for logging into default logger instance - * - * Params: - * type - level of logging - * messages - compile-time tuple of printable things - * to be written into the log. - */ -void log( A... )( OutputType type, lazy A messages ) -{ - Logger.log( messages.text, type ); -} -/// Wrapper for logging with Info level -alias logInfo = curry!( log, OutputType.Info ); -alias logNotice = logInfo; -/// Wrapper for logging with Warning level -alias logWarning = curry!( log, OutputType.Warning ); -/// Wrapper for logging with Error level -alias logError = curry!( log, OutputType.Error ); -alias logFatal = logError; - -/// Special case is debug logging -/** - * Debug messages are removed in release build. - */ -void logDebug( A... )( A messages ) -{ - debug Logger.log( messages.text, OutputType.Debug ); -} + static this() + { + import dash.utility.config; -/** - * Benchmark the running of a function, and log the result to the debug buffer. - * - * Params: - * func = The function to benchmark - * name = The name to print in the log - */ -void bench( alias func )( lazy string name ) -{ - import std.datetime, core.time; + // Create loggers + consoleLogger = new DashLogger( config.logging.verbosities.outputVerbosity ); + fileLogger = new DashLogger( config.logging.verbosities.loggingVerbosity, config.logging.filePath ); - auto result = cast(Duration)benchmark!func( 1 ); - logDebug( name, " time:\t\t\t", result ); -} + // Create multilogger + multiLogger = new MultiLogger( LogLevel.all ); + multiLogger.insertLogger( "Dash Console Logger", consoleLogger ); + multiLogger.insertLogger( "Dash File Logger", fileLogger ); + stdlog = multiLogger; + } -/// Global instance of logger -shared GlobalLogger Logger; + static void initialize() + { + import dash.utility.config; -shared static this() -{ - Logger = new shared GlobalLogger; -} + consoleLogger.logLevel = config.logging.verbosities.outputVerbosity; + fileLogger.logLevel = config.logging.verbosities.loggingVerbosity; + } -/** -* Children of StyledStrictLogger with $(B initialize) method to -* handle loading verbosity from config. -* -* Overwrites default style to use with local OutputType. -*/ -synchronized final class GlobalLogger : StyledStrictLogger!(OutputType - , OutputType.Debug, "Debug: %1$s", "[%2$s] Debug: %1$s" - , OutputType.Info, "Info: %1$s", "[%2$s] Info: %1$s" - , OutputType.Warning, "Warning: %1$s", "[%2$s] Warning: %1$s" - , OutputType.Error, "Error: %1$s", "[%2$s] Error: %1$s" - , OutputType.Muted, "", "" - ) -{ - enum DEFAULT_LOG_NAME = "dash-preinit.log"; + override protected void writeLogMsg( ref LogEntry payload ) + { + import std.conv: to; + import std.path: baseName; + import std.array: appender; + import std.format: formattedWrite; - this() + auto msg = appender!string; + + // Log file and line info in the console only + if( !isConsole ) + { + msg.formattedWrite( + "[%s] {%s:%d} ", + payload.timestamp.toSimpleString(), + payload.file.baseName, + payload.line, + ); + } + + // Log level and message + msg.formattedWrite( + "%s: %s", + payload.logLevel.to!string, + payload.msg, + ); + + // Color and print the message + file.cwritef( "%s\n", isConsole + ? msg.data.color( getColor( payload.logLevel ), bg.init, getMode( payload.logLevel ) ) + : msg.data ); + } + +private: + bool isConsole; + + this( LogLevel level, string fileName = null ) { - super(DEFAULT_LOG_NAME); + import std.stdio: stdout; + + if( !fileName ) + { + super( stdout, level ); + isConsole = true; + } + else + { + super( fileName, level ); + isConsole = false; + } } - /** - * Loads verbosity from config. - */ - final void initialize() + fg getColor( LogLevel level ) { - // Try to get new path for logging - string newFileName = config.logging.filePath; - if( newFileName ) + final switch( level ) with( LogLevel ) with( fg ) { - string oldFileName = this.name; - try - { - this.name = newFileName; - } - catch( Exception e ) - { - std.stdio.writeln( "Error: Failed to reload new log location from '",oldFileName,"' to '",newFileName,"'" ); - std.stdio.writeln( "Reason: ", e.msg ); - debug std.stdio.writeln( e.toString ); - - // Try to rollback - scope(failure) {} - this.name = oldFileName; - } + case trace: + case info: + case off: + case all: + return init; + case warning: + return yellow; + case error: + case critical: + case fatal: + return red; } + } - // Try to get output verbosity from config - debug minOutputLevel = cast(OutputType)config.logging.debug_.outputVerbosity; - else minOutputLevel = cast(OutputType)config.logging.release.outputVerbosity; - - // Try to get logging verbosity from config - debug minLoggingLevel = cast(OutputType)config.logging.debug_.loggingVerbosity; - else minLoggingLevel = cast(OutputType)config.logging.release.loggingVerbosity; + mode getMode( LogLevel level ) + { + switch( level ) with( LogLevel ) with( mode ) + { + case critical: + return underline; + case fatal: + return bold; + default: + return init; + } } } From 944238bfe3c530bead3cbcecbaebabe2c6aeaccc Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 13 Nov 2014 15:16:53 -0500 Subject: [PATCH 128/141] Broke DashLogger into Console, File, and Editor loggers --- source/dash/utility/output.d | 129 +++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 45 deletions(-) diff --git a/source/dash/utility/output.d b/source/dash/utility/output.d index 1ceeaccf..23d57928 100644 --- a/source/dash/utility/output.d +++ b/source/dash/utility/output.d @@ -36,24 +36,26 @@ void bench( alias func )( lazy string name ) /** * Dash's custom logger. */ -class DashLogger : FileLogger +abstract final class DashLogger { - static MultiLogger multiLogger; - static DashLogger consoleLogger; - static DashLogger fileLogger; + static MultiLogger multiLogger; + static DashConsoleLogger consoleLogger; + static DashFileLogger fileLogger; + static DashEditorLogger editorLogger; static this() { import dash.utility.config; // Create loggers - consoleLogger = new DashLogger( config.logging.verbosities.outputVerbosity ); - fileLogger = new DashLogger( config.logging.verbosities.loggingVerbosity, config.logging.filePath ); + consoleLogger = new DashConsoleLogger( config.logging.verbosities.outputVerbosity ); + fileLogger = new DashFileLogger( config.logging.verbosities.loggingVerbosity, config.logging.filePath ); + editorLogger = new DashEditorLogger(); // Create multilogger multiLogger = new MultiLogger( LogLevel.all ); multiLogger.insertLogger( "Dash Console Logger", consoleLogger ); - multiLogger.insertLogger( "Dash File Logger", fileLogger ); + multiLogger.insertLogger( "Dash Editor Logger", editorLogger ); stdlog = multiLogger; } @@ -61,11 +63,28 @@ class DashLogger : FileLogger { import dash.utility.config; + // Reinitialize the logger with file path. + multiLogger.removeLogger( "Dash File Logger" ); + fileLogger = new DashFileLogger( config.logging.verbosities.loggingVerbosity, config.logging.filePath ); + multiLogger.insertLogger( "Dash File Logger", fileLogger ); + + // Update levels of existing loggers. consoleLogger.logLevel = config.logging.verbosities.outputVerbosity; - fileLogger.logLevel = config.logging.verbosities.loggingVerbosity; + } +} + +private: +/// Logs messages to the console +final class DashConsoleLogger : FileLogger +{ + this( LogLevel level ) + { + import std.stdio: stdout; + + super( stdout, level ); } - override protected void writeLogMsg( ref LogEntry payload ) + override void writeLogMsg( ref LogEntry payload ) { import std.conv: to; import std.path: baseName; @@ -74,17 +93,6 @@ class DashLogger : FileLogger auto msg = appender!string; - // Log file and line info in the console only - if( !isConsole ) - { - msg.formattedWrite( - "[%s] {%s:%d} ", - payload.timestamp.toSimpleString(), - payload.file.baseName, - payload.line, - ); - } - // Log level and message msg.formattedWrite( "%s: %s", @@ -92,35 +100,66 @@ class DashLogger : FileLogger payload.msg, ); - // Color and print the message - file.cwritef( "%s\n", isConsole - ? msg.data.color( getColor( payload.logLevel ), bg.init, getMode( payload.logLevel ) ) - : msg.data ); + // Color and log file + file.cwritef( msg.data.color( payload.logLevel.getColor(), bg.init, payload.logLevel.getMode() ) ); } +} -private: - bool isConsole; +/// Logs messages to a file +final class DashFileLogger : FileLogger +{ + this( LogLevel level, string filename ) + { + super( filename, level ); + } + + override void writeLogMsg( ref LogEntry payload ) + { + import std.conv: to; + import std.path: baseName; + import std.array: appender; + import std.format: formattedWrite; + + auto msg = appender!string; + + // Log file and line info in the console only + msg.formattedWrite( + "[%s] {%s:%d} %s: %s", + payload.timestamp.toSimpleString(), + payload.file.baseName, + payload.line, + payload.logLevel.to!string, + payload.msg, + ); + + // Color and print the message + logMsgPart( msg.data ); + finishLogMsg(); + } +} - this( LogLevel level, string fileName = null ) +/// Logs messages to the editor interface +final class DashEditorLogger : Logger +{ + this() { import std.stdio: stdout; - if( !fileName ) - { - super( stdout, level ); - isConsole = true; - } - else - { - super( fileName, level ); - isConsole = false; - } + // File not actually used for anything, but required by FileLogger + super( LogLevel.all ); } - fg getColor( LogLevel level ) + override void writeLogMsg( ref LogEntry payload ) + { + //TODO + } +} + +/// Helper to get the color of the log level +fg getColor( LogLevel level ) +{ + final switch( level ) with( LogLevel ) with( fg ) { - final switch( level ) with( LogLevel ) with( fg ) - { case trace: case info: case off: @@ -132,19 +171,19 @@ private: case critical: case fatal: return red; - } } +} - mode getMode( LogLevel level ) +/// Helper to get the print mode of the log level +mode getMode( LogLevel level ) +{ + switch( level ) with( LogLevel ) with( mode ) { - switch( level ) with( LogLevel ) with( mode ) - { case critical: return underline; case fatal: return bold; default: return init; - } } } From 3bdef0ffe5de349b5b949f0e37c2761a93621240 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Thu, 13 Nov 2014 15:43:53 -0500 Subject: [PATCH 129/141] Switched to new logging functions --- source/dash/components/animation.d | 4 ++-- source/dash/components/assets.d | 14 ++++++------- source/dash/components/component.d | 6 +++--- source/dash/components/lights.d | 2 +- source/dash/components/mesh.d | 6 +++--- source/dash/components/userinterface.d | 2 +- source/dash/core/prefabs.d | 2 +- source/dash/editor/editor.d | 6 +++--- source/dash/editor/websockets.d | 6 +++--- source/dash/graphics/adapters/gl.d | 8 ++++---- source/dash/graphics/adapters/sdl.d | 26 +++++++++++++----------- source/dash/graphics/adapters/win32gl.d | 2 +- source/dash/graphics/shaders/shaders.d | 22 ++++++++++---------- source/dash/utility/data/serialization.d | 6 +++--- source/dash/utility/input/input.d | 10 ++++----- source/dash/utility/output.d | 4 +++- source/dash/utility/resources.d | 2 +- source/dash/utility/time.d | 2 +- 18 files changed, 67 insertions(+), 63 deletions(-) diff --git a/source/dash/components/animation.d b/source/dash/components/animation.d index d720e36b..8e618f75 100644 --- a/source/dash/components/animation.d +++ b/source/dash/components/animation.d @@ -120,7 +120,7 @@ public: _currentAnimTime = startAnimTime; } else - logWarning( "Could not change to new animation, the animation did not exist." ); + warning( "Could not change to new animation, the animation did not exist." ); } /** * Runs an animation once, then returns @@ -135,7 +135,7 @@ public: _currentAnimTime = 0; } else - logWarning( "Could not change to new animation, the animation did not exist." ); + warning( "Could not change to new animation, the animation did not exist." ); } /** diff --git a/source/dash/components/assets.d b/source/dash/components/assets.d index 82ba87ef..1db04c1d 100644 --- a/source/dash/components/assets.d +++ b/source/dash/components/assets.d @@ -53,7 +53,7 @@ public: } else { - logFatal( "Unable to find ", name, " in $array." ); + errorf( "Unable to find %s in $array.", name ); return null; } } @@ -94,7 +94,7 @@ public: if( scene.mNumMeshes > 0 ) { if( file.baseFileName in meshes ) - logWarning( "Mesh ", file.baseFileName, " exsists more than once." ); + warning( "Mesh ", file.baseFileName, " exsists more than once." ); auto newMesh = new MeshAsset( file, scene.mMeshes[ 0 ] ); @@ -105,7 +105,7 @@ public: } else { - logWarning( "Assimp did not contain mesh data, ensure you are loading a valid mesh." ); + warning( "Assimp did not contain mesh data, ensure you are loading a valid mesh." ); } // Release mesh @@ -115,7 +115,7 @@ public: foreach( file; scanDirectory( Resources.Textures ) ) { if( file.baseFileName in textures ) - logWarning( "Texture ", file.baseFileName, " exists more than once." ); + warningf( "Texture %s exists more than once.", file.baseFileName ); textures[ file.baseFileName ] = new TextureAsset( file ); } @@ -127,7 +127,7 @@ public: foreach( mat; newMat ) { if( mat.name in materials ) - logWarning( "Material ", mat.name, " exists more than once." ); + warningf( "Material %s exists more than once.", mat.name ); mat.resource = res; materials[ mat.name ] = mat; @@ -157,7 +157,7 @@ public: } else if( asset.resource.needsRefresh ) { - logDebug( "Refreshing ", name, "." ); + tracef( "Refreshing %s.", name ); asset.refresh(); } } @@ -179,7 +179,7 @@ public: foreach_reverse( name; $aaName.keys ) { if( !$aaName[ name ].isUsed ) - logWarning( "$friendlyName ", name, " not used during this run." ); + warningf( "$friendlyName %s not used during this run.", name ); $aaName[ name ].shutdown(); $aaName.remove( name ); diff --git a/source/dash/components/component.d b/source/dash/components/component.d index f3ea6421..1b5d60bf 100644 --- a/source/dash/components/component.d +++ b/source/dash/components/component.d @@ -165,7 +165,7 @@ public: } else { - logError( "Description of type ", typeid(this).name, " not found! Did you forget a mixin(registerComponents!())?" ); + errorf( "Description of type %s not found! Did you forget a mixin(registerComponents!())?", typeid(this).name ); return $type(); } } @@ -185,13 +185,13 @@ public: } else { - logWarning( "Component's \"Type\" not found: ", type.get!string ); + warningf( "Component's \"Type\" not found: %s", type.get!string ); return null; } } else { - logWarning( "Component doesn't have \"Type\" field." ); + warningf( "Component doesn't have \"Type\" field." ); return null; } } diff --git a/source/dash/components/lights.d b/source/dash/components/lights.d index 58d31e26..f5158d96 100644 --- a/source/dash/components/lights.d +++ b/source/dash/components/lights.d @@ -104,7 +104,7 @@ public: // check for success if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE ) { - logFatal("Shadow map frame buffer failure."); + fatal( "Shadow map frame buffer failure." ); assert(false); } } diff --git a/source/dash/components/mesh.d b/source/dash/components/mesh.d index 65a597ad..34759d6e 100644 --- a/source/dash/components/mesh.d +++ b/source/dash/components/mesh.d @@ -131,7 +131,7 @@ public: } if( maxBonesAttached > 4 ) { - logWarning( filePath, " has more than 4 bones for some vertex, data will be truncated. (has ", maxBonesAttached, ")" ); + warningf( "%s has more than 4 bones for some vertex, data will be truncated. (has %s)", filePath, maxBonesAttached ); } // For each vertex on each face @@ -221,7 +221,7 @@ public: else { // Did not load - logFatal( "Mesh not loaded: ", filePath ); + fatalf( "Mesh not loaded: %s", filePath ); } // make and bind the VAO @@ -311,7 +311,7 @@ public: } else { - logWarning( "Assimp did not contain mesh data, ensure you are loading a valid mesh." ); + warning( "Assimp did not contain mesh data, ensure you are loading a valid mesh." ); return; } diff --git a/source/dash/components/userinterface.d b/source/dash/components/userinterface.d index 5a325df1..12f1cdb4 100644 --- a/source/dash/components/userinterface.d +++ b/source/dash/components/userinterface.d @@ -43,7 +43,7 @@ public: { _view = new AwesomiumView( w, h, filePath, null ); } - logDebug( "UI File: ", filePath ); + tracef( "UI File: %s", filePath ); } /** diff --git a/source/dash/core/prefabs.d b/source/dash/core/prefabs.d index 4e055bd2..929f2b63 100644 --- a/source/dash/core/prefabs.d +++ b/source/dash/core/prefabs.d @@ -30,7 +30,7 @@ public: } else { - logWarning( "Prefab ", index, " not found." ); + warningf( "Prefab %s not found.", index ); return null; } } diff --git a/source/dash/editor/editor.d b/source/dash/editor/editor.d index a55428b1..bded696f 100644 --- a/source/dash/editor/editor.d +++ b/source/dash/editor/editor.d @@ -136,7 +136,7 @@ public: } catch( JSONException e ) { - logError( "Error deserializing received message with key \"", key, "\" to ", DataType.stringof, ": ", e.msg ); + errorf( "Error deserializing received message with key \"%s\" to %s: %s", key, DataType.stringof, e.msg ); return; } @@ -239,7 +239,7 @@ protected: } else { - logWarning( "Invalid editor event received with key ", event.key ); + warningf( "Invalid editor event received with key %s", event.key ); } } } @@ -295,7 +295,7 @@ package: } else { - logFatal( "Callback reference lost: ", msg.callbackId ); + errorf( "Callback reference lost: %s", msg.callbackId ); } } diff --git a/source/dash/editor/websockets.d b/source/dash/editor/websockets.d index ed42baaf..75b4d4b9 100644 --- a/source/dash/editor/websockets.d +++ b/source/dash/editor/websockets.d @@ -52,18 +52,18 @@ public: try msg = jsonStr.deserializeJson!EventMessage(); catch( JSONException e ) { - logError( "Invalid json string sent: ", jsonStr ); + errorf( "Invalid json string sent: %s", jsonStr ); continue; } if( msg.key.length == 0 ) { - logWarning( "Received a packet without a \"key.\"" ); + warning( "Received a packet without a \"key.\"" ); continue; } if( msg.value.type == Json.Type.null_ || msg.value.type == Json.Type.undefined ) { - logWarning( "Received a packet without a \"value.\"" ); + warning( "Received a packet without a \"value.\"" ); continue; } diff --git a/source/dash/graphics/adapters/gl.d b/source/dash/graphics/adapters/gl.d index f71ba71e..a2b7f79c 100644 --- a/source/dash/graphics/adapters/gl.d +++ b/source/dash/graphics/adapters/gl.d @@ -70,7 +70,7 @@ public: } } - logFatal( "Deffered rendering Frame Buffer was not initialized correctly. Error: ", mapFramebufferError(status) ); + fatalf( "Deffered rendering Frame Buffer was not initialized correctly. Error: %s", mapFramebufferError(status) ); assert(false); } } @@ -136,7 +136,7 @@ public: { if( !DGame.instance.activeScene ) { - logWarning( "No active scene." ); + warning( "No active scene." ); return; } @@ -144,7 +144,7 @@ public: if( !scene.camera ) { - logWarning( "No camera on active scene." ); + warning( "No camera on active scene." ); return; } @@ -313,7 +313,7 @@ public: if( !ambientLights.empty ) { - logWarning( "Only one ambient light per scene is utilized." ); + warning( "Only one ambient light per scene is utilized." ); } } diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 1e06b9c6..1eb7c79c 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -49,25 +49,27 @@ public: if(config.graphics.usingGl33) { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); } else { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); } - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); string iconPath = Resources.Textures ~ "/icon.bmp"; if( exists( iconPath ) ) { - SDLImage imageLib = new SDLImage( sdl, 0 ); - window.setIcon( imageLib.load( iconPath ) ); + SDLImage imageLib = new SDLImage( sdl, 0 ); + window.setIcon( imageLib.load( iconPath ) ); } else - logDebug("Could not find icon.bmp in Textures folder!"); + { + trace("Could not find icon.bmp in Textures folder!"); + } //context = SDL_GL_CreateContext( window ); glContext = new SDL2GLContext( window ); @@ -77,13 +79,13 @@ public: if(config.graphics.vsync) { - SDL_GL_SetSwapInterval(1); - logDebug("vsync enabled!"); + SDL_GL_SetSwapInterval(1); + trace("vsync enabled!"); } else { - SDL_GL_SetSwapInterval(0); - logDebug("vsync disabled!"); + SDL_GL_SetSwapInterval(0); + trace("vsync disabled!"); } } diff --git a/source/dash/graphics/adapters/win32gl.d b/source/dash/graphics/adapters/win32gl.d index a26bb54f..948baa3b 100644 --- a/source/dash/graphics/adapters/win32gl.d +++ b/source/dash/graphics/adapters/win32gl.d @@ -126,7 +126,7 @@ public: if( DerelictGL3.loadedVersion < GLVersion.GL40 ) { - logFatal( "Your version of OpenGL is unsupported. Required: GL40 Yours: ", DerelictGL3.loadedVersion ); + fatalf( "Your version of OpenGL is unsupported. Required: GL40 Yours: %s", DerelictGL3.loadedVersion ); //throw new Exception( "Unsupported version of OpenGL." ); return; } diff --git a/source/dash/graphics/shaders/shaders.d b/source/dash/graphics/shaders/shaders.d index 7778eb97..0ab8a4ba 100644 --- a/source/dash/graphics/shaders/shaders.d +++ b/source/dash/graphics/shaders/shaders.d @@ -179,13 +179,13 @@ public: //aren't supported in GLSL 330) if(config.graphics.usingGl33) { - vertexBody = replaceAll(vertexBody, layoutRegex, ""); - vertexBody = replaceAll(vertexBody, versionRegex, "#version 330"); + vertexBody = replaceAll(vertexBody, layoutRegex, ""); + vertexBody = replaceAll(vertexBody, versionRegex, "#version 330"); - fragmentBody = replaceAll(fragmentBody, layoutRegex, ""); - fragmentBody = replaceAll(fragmentBody, versionRegex, "#version 330"); + fragmentBody = replaceAll(fragmentBody, layoutRegex, ""); + fragmentBody = replaceAll(fragmentBody, versionRegex, "#version 330"); - logDebug( vertexBody ); + trace( vertexBody ); } compile( vertexBody, fragmentBody ); @@ -229,11 +229,11 @@ public: glGetShaderiv( vertexShaderID, GL_COMPILE_STATUS, &compileStatus ); if( compileStatus != GL_TRUE ) { - logFatal( shaderName ~ " Vertex Shader compile error" ); + errorf( "%s Vertex Shader compile error", shaderName ); char[1000] errorLog; auto info = errorLog.ptr; glGetShaderInfoLog( vertexShaderID, 1000, null, info ); - logFatal( errorLog ); + error( errorLog ); assert(false); } @@ -241,11 +241,11 @@ public: glGetShaderiv( fragmentShaderID, GL_COMPILE_STATUS, &compileStatus ); if( compileStatus != GL_TRUE ) { - logFatal( shaderName ~ " Fragment Shader compile error" ); + errorf( "%s Fragment Shader compile error", shaderName ); char[1000] errorLog; auto info = errorLog.ptr; glGetShaderInfoLog( fragmentShaderID, 1000, null, info ); - logFatal( errorLog ); + error( errorLog ); assert(false); } @@ -257,11 +257,11 @@ public: glGetProgramiv( programID, GL_LINK_STATUS, &compileStatus ); if( compileStatus != GL_TRUE ) { - logFatal( shaderName ~ " Shader program linking error" ); + errorf( "%s Shader program linking error", shaderName ); char[1000] errorLog; auto info = errorLog.ptr; glGetProgramInfoLog( programID, 1000, null, info ); - logFatal( errorLog ); + error( errorLog ); assert(false); } } diff --git a/source/dash/utility/data/serialization.d b/source/dash/utility/data/serialization.d index 1fcca659..6d7db0c8 100644 --- a/source/dash/utility/data/serialization.d +++ b/source/dash/utility/data/serialization.d @@ -88,7 +88,7 @@ T deserializeFile( T )( Resource file, SerializationMode mode = SerializationMod } catch( Exception e ) { - logError( "Error deserializing file ", file.fileName, " to type ", T.stringof, ". ", e.msg ); + errorf( "Error deserializing file %s to type %s: %s", file.fileName, T.stringof, e.msg ); return T.init; } } @@ -146,7 +146,7 @@ T[] deserializeMultiFile( T )( Resource file, SerializationMode mode = Serializa } catch( Exception e ) { - logError( "Error deserializing file ", file.fileName, " to type ", T.stringof, ". ", e.msg ); + errorf( "Error deserializing file %s to type %s: %s", file.fileName, T.stringof, e.msg ); return []; } } @@ -201,7 +201,7 @@ template serializeToFile( bool prettyPrint = true ) } catch( Exception e ) { - logError( "Error serializing ", T.stringof, " to file ", file.fileName, ". ", e.msg ); + errorf( "Error serializing %s to file %s: %s", T.stringof, file.fileName, e.msg ); } } } diff --git a/source/dash/utility/input/input.d b/source/dash/utility/input/input.d index 9fc6e3b5..bc3ab492 100644 --- a/source/dash/utility/input/input.d +++ b/source/dash/utility/input/input.d @@ -63,7 +63,7 @@ public: } catch( Exception e ) { - logError( "Error parsing config file:\n", e.toString() ); + errorf( "Error parsing config file:%s\n", e.toString() ); } Keyboard.initialize(); @@ -341,7 +341,7 @@ public: { if( !DGame.instance.activeScene ) { - logWarning( "No active scene." ); + warning( "No active scene." ); return vec3f( 0.0f, 0.0f, 0.0f ); } @@ -349,7 +349,7 @@ public: if( !scene.camera ) { - logWarning( "No camera on active scene." ); + warning( "No camera on active scene." ); return vec3f( 0.0f, 0.0f, 0.0f ); } vec2ui mouse = mousePos(); @@ -394,7 +394,7 @@ public: { if( !DGame.instance.activeScene ) { - logWarning( "No active scene." ); + warning( "No active scene." ); return null; } @@ -402,7 +402,7 @@ public: if( !scene.camera ) { - logWarning( "No camera on active scene." ); + warning( "No camera on active scene." ); return null; } diff --git a/source/dash/utility/output.d b/source/dash/utility/output.d index 23d57928..e8b799c8 100644 --- a/source/dash/utility/output.d +++ b/source/dash/utility/output.d @@ -2,7 +2,9 @@ * Defines the Dash logger, using the std.logger proposal. */ module dash.utility.output; -public import std.experimental.logger; +import std.experimental.logger; +// Logging functions for the others +public import std.experimental.logger: log, logf, trace, tracef, info, infof, warning, warningf, error, errorf, critical, criticalf, fatal, fatalf; import colorize; diff --git a/source/dash/utility/resources.d b/source/dash/utility/resources.d index ddd5fc87..f558d778 100644 --- a/source/dash/utility/resources.d +++ b/source/dash/utility/resources.d @@ -36,7 +36,7 @@ Resource[] scanDirectory( string path, string pattern = "" ) if( !safePath.exists() ) { - logDebug( path, " does not exist." ); + tracef( "%s does not exist.", path ); return []; } diff --git a/source/dash/utility/time.d b/source/dash/utility/time.d index b7bdbced..2a6f0419 100644 --- a/source/dash/utility/time.d +++ b/source/dash/utility/time.d @@ -106,7 +106,7 @@ void updateTime() second += delta; if( second >= 1.seconds ) { - logDebug( "Framerate: ", frameCount ); + tracef( "Framerate: %d", frameCount ); second = Duration.zero; frameCount = 0; } From 05978d28e0bc6d5268c0f2faba36c719c0c495e6 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Fri, 14 Nov 2014 16:22:38 -0500 Subject: [PATCH 130/141] Fixed console logger not writing an endline --- source/dash/utility/output.d | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/dash/utility/output.d b/source/dash/utility/output.d index e8b799c8..f9b33beb 100644 --- a/source/dash/utility/output.d +++ b/source/dash/utility/output.d @@ -65,7 +65,7 @@ abstract final class DashLogger { import dash.utility.config; - // Reinitialize the logger with file path. + // Reinitialize the logger with file path. multiLogger.removeLogger( "Dash File Logger" ); fileLogger = new DashFileLogger( config.logging.verbosities.loggingVerbosity, config.logging.filePath ); multiLogger.insertLogger( "Dash File Logger", fileLogger ); @@ -104,6 +104,7 @@ final class DashConsoleLogger : FileLogger // Color and log file file.cwritef( msg.data.color( payload.logLevel.getColor(), bg.init, payload.logLevel.getMode() ) ); + finishLogMsg(); } } From ab7286b31e4c918760d36bf17ab41f9a48445388 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 15 Nov 2014 12:08:36 -0500 Subject: [PATCH 131/141] Fixed module circular ctor chain --- source/dash/core/dgame.d | 4 ++++ source/dash/utility/config.d | 2 +- source/dash/utility/output.d | 2 +- source/dash/utility/resources.d | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/source/dash/core/dgame.d b/source/dash/core/dgame.d index 4ee0ce8d..fd7e97a8 100644 --- a/source/dash/core/dgame.d +++ b/source/dash/core/dgame.d @@ -203,6 +203,10 @@ private: stateFlags = new GameStateFlags; stateFlags.resumeAll(); + // This is so that the bench marks will log properly, + // and config options will be update upon second call. + DashLogger.setDefaults(); + bench!( { Config.initialize(); } )( "Config init" ); bench!( { DashLogger.initialize(); } )( "Logger init" ); bench!( { Input.initialize(); } )( "Input init" ); diff --git a/source/dash/utility/config.d b/source/dash/utility/config.d index d35497ad..cc33d10e 100644 --- a/source/dash/utility/config.d +++ b/source/dash/utility/config.d @@ -2,7 +2,7 @@ * Defines the static class Config, which handles all configuration options. */ module dash.utility.config; -import dash.utility.resources, dash.utility.output, dash.utility.data; +import dash.utility.resources, dash.utility.data; import std.experimental.logger; import std.datetime; diff --git a/source/dash/utility/output.d b/source/dash/utility/output.d index f9b33beb..8097eba8 100644 --- a/source/dash/utility/output.d +++ b/source/dash/utility/output.d @@ -45,7 +45,7 @@ abstract final class DashLogger static DashFileLogger fileLogger; static DashEditorLogger editorLogger; - static this() + static void setDefaults() { import dash.utility.config; diff --git a/source/dash/utility/resources.d b/source/dash/utility/resources.d index f558d778..20bcb628 100644 --- a/source/dash/utility/resources.d +++ b/source/dash/utility/resources.d @@ -2,7 +2,7 @@ * TODO */ module dash.utility.resources; -import dash.utility; +import dash.utility.output; import std.file, std.path, std.stdio, std.array, std.algorithm, std.datetime; From ad63c05cad3f693bdeab086ff1bae0fe6efa113a Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 15 Nov 2014 12:39:20 -0500 Subject: [PATCH 132/141] Implemented DashEditorLogger --- source/dash/utility/output.d | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/source/dash/utility/output.d b/source/dash/utility/output.d index 8097eba8..16b27c92 100644 --- a/source/dash/utility/output.d +++ b/source/dash/utility/output.d @@ -154,7 +154,33 @@ final class DashEditorLogger : Logger override void writeLogMsg( ref LogEntry payload ) { - //TODO + import dash.core.dgame; + + static struct LogMessage + { + string file; + int line; + string funcName; + string prettyFuncName; + string moduleName; + LogLevel logLevel; + string timestamp; + string msg; + + this( LogEntry entry ) + { + file = entry.file; + line = entry.line; + funcName = entry.funcName; + prettyFuncName = entry.prettyFuncName; + moduleName = entry.moduleName; + logLevel = entry.logLevel; + timestamp = entry.timestamp.toSimpleString(); + msg = entry.msg; + } + } + + DGame.instance.editor.send( "dash:logger:message", LogMessage( payload ) ); } } From c4af6ed53cf5732f977dc4ab434e4868894193ce Mon Sep 17 00:00:00 2001 From: Sean Brennan Date: Sat, 15 Nov 2014 13:58:10 -0500 Subject: [PATCH 133/141] Implemented ui click events and filtering --- source/dash/components/userinterface.d | 26 ++++++++--------- source/dash/core/dgame.d | 2 -- source/dash/core/scene.d | 7 +++++ source/dash/graphics/adapters/adapter.d | 13 --------- source/dash/graphics/adapters/gl.d | 15 ++++------ source/dash/utility/input/inputsystem.d | 39 ++++++++++++++++++++++++- 6 files changed, 63 insertions(+), 39 deletions(-) diff --git a/source/dash/components/userinterface.d b/source/dash/components/userinterface.d index 12f1cdb4..9cdffebc 100644 --- a/source/dash/components/userinterface.d +++ b/source/dash/components/userinterface.d @@ -58,18 +58,13 @@ public: auto mousePos = Input.mousePos(); awe_webview_inject_mouse_move( _view.webView, cast(int)mousePos.x,cast(int)( Graphics.height - mousePos.y ) ); + auto mouseUp = Mouse.isButtonUp(Mouse.Buttons.Left, true); + if( mouseUp ) awe_webview_inject_mouse_up( _view.webView, awe_mousebutton.AWE_MB_LEFT ); + _view.update(); } } - /** - * Draw UI view - */ - void draw() - { - Graphics.addUI( this ); - } - /** * Cleanup UI memory */ @@ -166,11 +161,14 @@ public: class AwesomiumView : TextureAsset { private: - version( Windows ) - awe_webview* webView; - ubyte[] glBuffer; + const(awe_renderbuffer)* renderBuffer; public: +//package(dash): + awe_webview* webView; + version( Windows ) + ubyte[] glBuffer; + this( uint w, uint h, string filePath, GameObject owner, bool localFilePath = true ) { _width = w; @@ -210,12 +208,12 @@ public: version( Windows ) if ( webView && webView.awe_webview_is_dirty() ) { - const(awe_renderbuffer)* buffer = webView.awe_webview_render(); + renderBuffer = webView.awe_webview_render(); // Ensure the buffer exists - if ( buffer !is null ) { + if ( renderBuffer !is null ) { - buffer.awe_renderbuffer_copy_to( glBuffer.ptr, awe_renderbuffer_get_rowspan( buffer ), 4, false, true ); + renderBuffer.awe_renderbuffer_copy_to( glBuffer.ptr, awe_renderbuffer_get_rowspan( renderBuffer ), 4, false, true ); updateBuffer( glBuffer.ptr ); } diff --git a/source/dash/core/dgame.d b/source/dash/core/dgame.d index 4ee0ce8d..5111390e 100644 --- a/source/dash/core/dgame.d +++ b/source/dash/core/dgame.d @@ -88,8 +88,6 @@ public: */ final void run() { - // Init tasks - //TaskManager.initialize(); start(); GC.collect(); diff --git a/source/dash/core/scene.d b/source/dash/core/scene.d index 7d589b8f..6ad6fb92 100644 --- a/source/dash/core/scene.d +++ b/source/dash/core/scene.d @@ -25,6 +25,7 @@ public: /// The camera to render with. Camera camera; Listener listener; + UserInterface ui; /// The root object of the scene. mixin( Getter!_root ); @@ -64,6 +65,11 @@ public: _root.shutdown(); destroy( _root ); _root = new GameObject; + + ui.shutdown(); + destroy( ui ); + // TODO: Can be built automatically by config + ui = null; } /** @@ -71,6 +77,7 @@ public: */ final void update() { + ui.update(); _root.update(); } diff --git a/source/dash/graphics/adapters/adapter.d b/source/dash/graphics/adapters/adapter.d index 0c16fdc5..ad831c21 100644 --- a/source/dash/graphics/adapters/adapter.d +++ b/source/dash/graphics/adapters/adapter.d @@ -18,10 +18,6 @@ private: uint _height, _screenHeight; bool _fullscreen, _backfaceCulling, _vsync; -protected: - // Do not add properties for: - UserInterface[] uis; - public: /// Pixel width of the rendering area mixin( Property!_width ); @@ -90,15 +86,6 @@ public: /// TODO: Remove in favor of pipelines abstract void initializeDeferredRendering(); - /* - * Adds a UI to be drawn over the objects in the scene - * UIs will be drawn ( and overlap ) in the order they are added - */ - final void addUI( UserInterface ui ) - { - uis ~= ui; - } - protected: /** * Loads rendering properties from Config diff --git a/source/dash/graphics/adapters/gl.d b/source/dash/graphics/adapters/gl.d index a2b7f79c..a87ea23e 100644 --- a/source/dash/graphics/adapters/gl.d +++ b/source/dash/graphics/adapters/gl.d @@ -390,13 +390,11 @@ public: glUseProgram( shader.programID ); glBindVertexArray( Assets.unitSquare.glVertexArray ); - foreach( ui; uis ) - { - shader.bindUniformMatrix4fv( shader.WorldProj, - scene.camera.orthogonalMatrix * ui.scaleMat ); - shader.bindUI( ui ); - glDrawElements( GL_TRIANGLES, Assets.unitSquare.numVertices, GL_UNSIGNED_INT, null ); - } + auto ui = scene.ui; + shader.bindUniformMatrix4fv( shader.WorldProj, + scene.camera.orthogonalMatrix * ui.scaleMat ); + shader.bindUI( ui ); + glDrawElements( GL_TRIANGLES, Assets.unitSquare.numVertices, GL_UNSIGNED_INT, null ); glBindVertexArray(0); } @@ -435,7 +433,7 @@ public: //TODO: Repair the UI on Linux systems version(linux){} else - uiPass(); + uiPass(); // put it on the screen swapBuffers(); @@ -443,6 +441,5 @@ public: // clean up glBindVertexArray(0); glUseProgram(0); - uis = []; } } diff --git a/source/dash/utility/input/inputsystem.d b/source/dash/utility/input/inputsystem.d index f0019935..d07d5049 100644 --- a/source/dash/utility/input/inputsystem.d +++ b/source/dash/utility/input/inputsystem.d @@ -175,7 +175,44 @@ public: */ void setButtonState( Buttons buttonCode, ButtonStorageType newState ) { - buttonStaging[ buttonCode ] = newState; + // HACK: Don't mind me. + import dash.utility.input.mouse, dash.core.dgame, dash.graphics.graphics; + import dash.utility.bindings.awesomium; + static if( is( Buttons == MouseButtons ) ) + { + if( buttonCode == MouseButtons.Left ) + { + auto ui = DGame.instance.activeScene.ui; + auto mousePos = Input.mousePos; + auto offset = ( Graphics.width * (mousePos.y - 1) + mousePos.x ) * 4; + auto transparency = ui.view.glBuffer[ offset + 3 ]; + + import dash.utility.output; + tracef( "Transparency at point %d, %d: %d", cast(int)mousePos.x, cast(int)( Graphics.height - mousePos.y ), transparency ); + + if( ui && newState && transparency > 0 ) + { + awe_webview_inject_mouse_down( ui.view.webView, awe_mousebutton.AWE_MB_LEFT ); + } + else + { + buttonStaging[ buttonCode ] = newState; + + if( !newState ) + { + awe_webview_inject_mouse_up( ui.view.webView, awe_mousebutton.AWE_MB_LEFT ); + } + } + } + else + { + buttonStaging[ buttonCode ] = newState; + } + } + else + { + buttonStaging[ buttonCode ] = newState; + } } private: From 55bce0d788f66dfeb7e53f104719cfbb3cb385df Mon Sep 17 00:00:00 2001 From: Brandon Littell Date: Sat, 15 Nov 2014 15:07:05 -0500 Subject: [PATCH 134/141] [Input] Implemented mousePos for SDL, fixed garbage default values --- source/dash/graphics/adapters/sdl.d | 3 ++- source/dash/utility/input/input.d | 23 +++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 1eb7c79c..4a43fdd2 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -11,11 +11,12 @@ import std.string, std.file; class Sdl : OpenGL { private: - SDL2 sdl; SDL2Window window; SDL2GLContext glContext; public: + SDL2 sdl; + static @property Sdl get() { return cast(Sdl)Graphics.adapter; } override void initialize() diff --git a/source/dash/utility/input/input.d b/source/dash/utility/input/input.d index bc3ab492..d8c193f3 100644 --- a/source/dash/utility/input/input.d +++ b/source/dash/utility/input/input.d @@ -306,10 +306,20 @@ public: */ vec2ui mousePos() { - version( Windows ) + version( DashUseSDL2 ) + { + import dash.graphics; + + if( !Sdl.get() ) + return vec2ui( 0, 0 ); + + auto mouse = Sdl.get().sdl.mouse; + return vec2ui( cast(uint)mouse.x, cast(uint)( Graphics.height - mouse.y ) ); + } + else version( Windows ) { if( !Win32GL.get() ) - return vec2ui(); + return vec2ui( 0, 0 ); import dash.graphics; import win32.windows; @@ -317,18 +327,11 @@ public: GetCursorPos( &i ); ScreenToClient( Win32GL.get().hWnd, &i ); - // Adjust for border - if( !Graphics.adapter.fullscreen ) - { - i.x -= GetSystemMetrics( SM_CXBORDER ); - i.y -= GetSystemMetrics( SM_CYBORDER ); - } - return vec2ui( i.x, Graphics.height - i.y ); } else { - return vec2ui(); + return vec2ui( 0, 0 ); } } From 033f4049a53d19348b57d7625f402f4b673bd00d Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 15 Nov 2014 15:51:45 -0500 Subject: [PATCH 135/141] [Editor] Improved loggging for invalid callback ids --- source/dash/editor/editor.d | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/dash/editor/editor.d b/source/dash/editor/editor.d index bded696f..6aa9c5f5 100644 --- a/source/dash/editor/editor.d +++ b/source/dash/editor/editor.d @@ -288,14 +288,18 @@ package: { // If it's a callback, dispatch it as such. UUID id = msg.callbackId.parseUUID(); - if( auto cb = id in callbacks ) + if( id.empty ) + { + error( "Callback received with empty id" ); + } + else if( auto cb = id in callbacks ) { (*cb)( msg ); callbacks.remove( id ); } else { - errorf( "Callback reference lost: %s", msg.callbackId ); + errorf( "Callback reference lost: %s", id ); } } From bfb1bc6784b12df2731e30788df08c642c6853d8 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 15 Nov 2014 17:01:24 -0500 Subject: [PATCH 136/141] [Transform] Fixed scale being 0 by default --- source/dash/core/gameobject.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dash/core/gameobject.d b/source/dash/core/gameobject.d index b5c69975..d9a041d0 100644 --- a/source/dash/core/gameobject.d +++ b/source/dash/core/gameobject.d @@ -579,7 +579,7 @@ public: /// The position of the object. @rename( "Scale" ) @optional - float[3] scale = [ 0.0f, 0.0f, 0.0f ]; + float[3] scale = [ 1.0f, 1.0f, 1.0f ]; } /** From 839247814be55cd00eaa95bbc61c0c42d3c06137 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 15 Nov 2014 18:09:47 -0500 Subject: [PATCH 137/141] [Assets] Fixed assets that aren't initially used being uninitialized --- source/dash/components/assets.d | 1 + 1 file changed, 1 insertion(+) diff --git a/source/dash/components/assets.d b/source/dash/components/assets.d index 1db04c1d..3cc5dd22 100644 --- a/source/dash/components/assets.d +++ b/source/dash/components/assets.d @@ -234,6 +234,7 @@ public: this( AssetType ass ) { asset = ass; + initialize(); } /// Is the asset null? From 6c658c70a7192929a78e7f14ed484a0483a5cf4a Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 15 Nov 2014 18:12:12 -0500 Subject: [PATCH 138/141] [Awesomium] Fixed Linux and OSX builds --- source/dash/components/userinterface.d | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/dash/components/userinterface.d b/source/dash/components/userinterface.d index 9cdffebc..34d067fe 100644 --- a/source/dash/components/userinterface.d +++ b/source/dash/components/userinterface.d @@ -161,13 +161,15 @@ public: class AwesomiumView : TextureAsset { private: - const(awe_renderbuffer)* renderBuffer; + version( Windows ) + const(awe_renderbuffer)* renderBuffer; public: //package(dash): - awe_webview* webView; - version( Windows ) - ubyte[] glBuffer; + version( Windows ) + awe_webview* webView; + version( Windows ) + ubyte[] glBuffer; this( uint w, uint h, string filePath, GameObject owner, bool localFilePath = true ) { From 5b6292b051f954ef43dea412d2c8e2a1172b1dec Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 15 Nov 2014 18:22:37 -0500 Subject: [PATCH 139/141] [Awesomium] Fixed the build for reals this time --- source/dash/components/userinterface.d | 1 - source/dash/utility/input/inputsystem.d | 82 +++++++++++++------------ 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/source/dash/components/userinterface.d b/source/dash/components/userinterface.d index 34d067fe..9858f44e 100644 --- a/source/dash/components/userinterface.d +++ b/source/dash/components/userinterface.d @@ -168,7 +168,6 @@ public: //package(dash): version( Windows ) awe_webview* webView; - version( Windows ) ubyte[] glBuffer; this( uint w, uint h, string filePath, GameObject owner, bool localFilePath = true ) diff --git a/source/dash/utility/input/inputsystem.d b/source/dash/utility/input/inputsystem.d index d07d5049..40050e5f 100644 --- a/source/dash/utility/input/inputsystem.d +++ b/source/dash/utility/input/inputsystem.d @@ -175,44 +175,50 @@ public: */ void setButtonState( Buttons buttonCode, ButtonStorageType newState ) { - // HACK: Don't mind me. - import dash.utility.input.mouse, dash.core.dgame, dash.graphics.graphics; - import dash.utility.bindings.awesomium; - static if( is( Buttons == MouseButtons ) ) - { - if( buttonCode == MouseButtons.Left ) - { - auto ui = DGame.instance.activeScene.ui; - auto mousePos = Input.mousePos; - auto offset = ( Graphics.width * (mousePos.y - 1) + mousePos.x ) * 4; - auto transparency = ui.view.glBuffer[ offset + 3 ]; - - import dash.utility.output; - tracef( "Transparency at point %d, %d: %d", cast(int)mousePos.x, cast(int)( Graphics.height - mousePos.y ), transparency ); - - if( ui && newState && transparency > 0 ) - { - awe_webview_inject_mouse_down( ui.view.webView, awe_mousebutton.AWE_MB_LEFT ); - } - else - { - buttonStaging[ buttonCode ] = newState; - - if( !newState ) - { - awe_webview_inject_mouse_up( ui.view.webView, awe_mousebutton.AWE_MB_LEFT ); - } - } - } - else - { - buttonStaging[ buttonCode ] = newState; - } - } - else - { - buttonStaging[ buttonCode ] = newState; - } + // HACK: Don't mind me. + import dash.utility.input.mouse, dash.core.dgame, dash.graphics.graphics; + import dash.utility.bindings.awesomium; + version( Windows ) { + static if( is( Buttons == MouseButtons ) ) + { + if( buttonCode == MouseButtons.Left ) + { + auto ui = DGame.instance.activeScene.ui; + auto mousePos = Input.mousePos; + auto offset = ( Graphics.width * (mousePos.y - 1) + mousePos.x ) * 4; + auto transparency = ui.view.glBuffer[ offset + 3 ]; + + import dash.utility.output; + tracef( "Transparency at point %d, %d: %d", cast(int)mousePos.x, cast(int)( Graphics.height - mousePos.y ), transparency ); + + if( ui && newState && transparency > 0 ) + { + awe_webview_inject_mouse_down( ui.view.webView, awe_mousebutton.AWE_MB_LEFT ); + } + else + { + buttonStaging[ buttonCode ] = newState; + + if( !newState ) + { + awe_webview_inject_mouse_up( ui.view.webView, awe_mousebutton.AWE_MB_LEFT ); + } + } + } + else + { + buttonStaging[ buttonCode ] = newState; + } + } + else + { + buttonStaging[ buttonCode ] = newState; + } + } + else + { + buttonStaging[ buttonCode ] = newState; + } } private: From c173b936e971d555acf0790d2d2760cb8adb410d Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 15 Nov 2014 18:23:53 -0500 Subject: [PATCH 140/141] [Scene] Added null checks to ui operations --- source/dash/core/scene.d | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/source/dash/core/scene.d b/source/dash/core/scene.d index 6ad6fb92..415ce4e2 100644 --- a/source/dash/core/scene.d +++ b/source/dash/core/scene.d @@ -66,10 +66,13 @@ public: destroy( _root ); _root = new GameObject; - ui.shutdown(); - destroy( ui ); - // TODO: Can be built automatically by config - ui = null; + if( ui ) + { + ui.shutdown(); + destroy( ui ); + // TODO: Can be built automatically by config + ui = null; + } } /** @@ -77,7 +80,8 @@ public: */ final void update() { - ui.update(); + if( ui ) + ui.update(); _root.update(); } From e3cb87f88507985c689034419ca06499fddcd36f Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 15 Nov 2014 18:34:34 -0500 Subject: [PATCH 141/141] [SDL] Fixed broken scrolling logic --- source/dash/graphics/adapters/sdl.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dash/graphics/adapters/sdl.d b/source/dash/graphics/adapters/sdl.d index 4a43fdd2..7e5d0925 100644 --- a/source/dash/graphics/adapters/sdl.d +++ b/source/dash/graphics/adapters/sdl.d @@ -174,7 +174,7 @@ public: break; case SDL_MOUSEWHEEL: - Mouse.setAxisState( Mouse.Axes.ScrollWheel, Mouse.getAxisState( Mouse.Axes.ScrollWheel ) + ( ( cast(int)event.wheel.y >> 16 ) / 120 ) ); + Mouse.setAxisState( Mouse.Axes.ScrollWheel, Mouse.getAxisState( Mouse.Axes.ScrollWheel ) + event.wheel.y ); break; case SDL_APP_TERMINATING: