private void OnTriggerStay2D(Collider2D collision) { //First enusre this plot is not growing something already. if (state != GROWSTATE.None) { return; } //Then make sure the object is a seed Seed seed = collision.gameObject.GetComponent <Seed>(); if (seed) { //Then get its shadow object property to make sure its on the ground. ShadowObject shadowObject = seed.gameObject.GetComponent <ShadowObject>(); if (shadowObject.Elevation <= 0.1f) { //Only consume the seed if you are the first plot to do so. if (!seed.consumed) { seed.consumed = true; PlantSeed(seed.plant); Destroy(collision.gameObject); } } } }
private void OnObjectDeserialized(int i, object newObject) { if (objectReferences != null && newObject != null) { var previousObject = objectReferences[i]; //// If the object is an attached reference, there is no need to copy the shadow object //if (AttachedReferenceManager.GetAttachedReference(previousObject) != null) //{ // return; //} ShadowObject.Copy(previousObject, newObject); // NOTE: we don't use Add because of strings that might be duplicated clonedObjectMapping[previousObject] = newObject; if ((flags & AssetClonerFlags.RemoveItemIds) != AssetClonerFlags.RemoveItemIds) { CollectionItemIdentifiers sourceIds; if (CollectionItemIdHelper.TryGetCollectionItemIds(previousObject, out sourceIds)) { var newIds = CollectionItemIdHelper.GetCollectionItemIds(newObject); sourceIds.CloneInto(newIds, clonedObjectMapping); } } } }
private static Dictionary<UFile, ObjectId> TryGet(Asset asset, ShadowObjectPropertyKey key) { var shadow = ShadowObject.GetOrCreate(asset); object obj; if (shadow.TryGetValue(key, out obj)) { return (Dictionary<UFile, ObjectId>)obj; } return null; }
private static Dictionary<UFile, ObjectId> GetOrCreate(Asset asset, ShadowObjectPropertyKey key) { var shadow = ShadowObject.GetOrCreate(asset); object obj; if (shadow.TryGetValue(key, out obj)) { return (Dictionary<UFile, ObjectId>)obj; } var hashes = new Dictionary<UFile, ObjectId>(); shadow[key] = hashes; return hashes; }
private void OnObjectDeserialized(int i, object newObject) { if (objectReferences != null && newObject != null) { var previousObject = objectReferences[i]; ShadowObject.CopyDynamicProperties(previousObject, newObject); if ((flags & AssetClonerFlags.RemoveOverrides) != 0) { Override.RemoveFrom(newObject); } } }
public static CollectionItemIdentifiers GetCollectionItemIds(object instance) { var shadow = ShadowObject.GetOrCreate(instance); object result; if (shadow.TryGetValue(CollectionItemIdKey, out result)) { return((CollectionItemIdentifiers)result); } var itemIds = new CollectionItemIdentifiers(); shadow.Add(CollectionItemIdKey, itemIds); return(itemIds); }
public static bool TryGetCollectionItemIds(object instance, out CollectionItemIdentifiers itemIds) { var shadow = ShadowObject.Get(instance); if (shadow == null) { itemIds = null; return(false); } object result; itemIds = shadow.TryGetValue(CollectionItemIdKey, out result) ? (CollectionItemIdentifiers)result : null; return(result != null); }
public void TestGetAndGetOrCreate() { ShadowObject.Enable = true; var obj = new object(); var shadowObject = ShadowObject.Get(obj); Assert.Null(shadowObject); shadowObject = ShadowObject.GetOrCreate(obj); Assert.NotNull(shadowObject); var shadowObject2 = ShadowObject.GetOrCreate(obj); Assert.AreEqual(shadowObject, shadowObject2); }
void OnEnable() { if (shadowParent == null) { shadowParent = new GameObject("Shadows"); } if (!shadowInstance) { shadowInstance = Instantiate(shadowPrefab, transform.position, shadowPrefab.transform.rotation).GetComponent <ShadowObject>(); shadowInstance.transform.parent = shadowParent.transform; } shadowInstance.scale = shadowScale; shadowInstance.isVisible = true; }
private void Awake() { shadowObject = GetComponent <ShadowObject>(); sprite = GetComponent <SpriteObject>(); needObject = GetComponent <NeedObject>(); // Sets up the audio to be 3D audioSource = gameObject.AddComponent <AudioSource>(); audioSource.spatialBlend = 1.0F; audioSource.rolloffMode = AudioRolloffMode.Linear; // Loads the audio clips liftingAudio = Resources.Load <AudioClip>("bloop"); landingAudios = new AudioClip[3]; landingAudios[0] = Resources.Load <AudioClip>("grass_1"); landingAudios[1] = Resources.Load <AudioClip>("grass_2"); landingAudios[2] = Resources.Load <AudioClip>("grass_3"); }
public void TestCopy() { ShadowObject.Enable = true; var obj = new object(); var obj1 = new object(); var shadowObject = ShadowObject.GetOrCreate(obj); shadowObject.IsSelected = true; ShadowObject.Copy(obj, obj1); var shadowObject1 = ShadowObject.Get(obj1); Assert.NotNull(shadowObject1); Assert.True(shadowObject1.IsSelected); }
private void OnObjectDeserialized(int i, object newObject) { if (objectReferences != null && newObject != null) { var previousObject = objectReferences[i]; //// If the object is an attached reference, there is no need to copy the shadow object //if (AttachedReferenceManager.GetAttachedReference(previousObject) != null) //{ // return; //} ShadowObject.Copy(previousObject, newObject); if ((flags & AssetClonerFlags.RemoveOverrides) != 0) { Override.RemoveFrom(newObject); } } }
/// <summary> /// Clones the current value of this cloner with the specified new shadow registry (optional) /// </summary> /// <returns>A clone of the value associated with this cloner.</returns> private object Clone() { var stream = streamOrValueType as Stream; if (stream != null) { stream.Position = 0; var reader = new BinarySerializationReader(stream); reader.Context.SerializerSelector = ClonerSelector; var refFlag = (flags & AssetClonerFlags.ReferenceAsNull) != 0 ? ContentSerializerContext.AttachedReferenceSerialization.AsNull : ContentSerializerContext.AttachedReferenceSerialization.AsSerializableVersion; reader.Context.Set(InvariantObjectListProperty, invariantObjects); reader.Context.Set(ContentSerializerContext.SerializeAttachedReferenceProperty, refFlag); object newObject = null; reader.SerializeExtended(ref newObject, ArchiveMode.Deserialize); // If there are any references, we would like to copy all dynamic properties from ShadowObject to the new instances if (objectReferences != null) { var newObjectReferences = reader.Context.Get(MemberSerializer.ObjectDeserializeReferences); foreach (var objRef in objectReferences) { var innerObject = objRef.Key; var newInnerObject = newObjectReferences[objRef.Value]; // Copy only when objects are non-null if (innerObject != null && newInnerObject != null) { ShadowObject.CopyDynamicProperties(innerObject, newInnerObject); if ((flags & AssetClonerFlags.RemoveOverrides) != 0) { Override.RemoveFrom(newInnerObject); } } } } return(newObject); } // Else this is a value type, so it is cloned automatically return(streamOrValueType); }
private void OnTriggerEnter2D(Collider2D collision) { ShadowObject shadowObject = collision.gameObject.GetComponent <ShadowObject>(); if (shadowObject) { if (!shadowObject.GravityEnabled) { DropIt(shadowObject.gameObject); } if (type == WALLTYPE.Horizontal) { shadowObject.HitHorizontal(); } else if (type == WALLTYPE.Vertical) { shadowObject.HitVertical(); } } }
private void OnObjectDeserialized(int i, object newObject) { if (objectReferences != null && newObject != null) { var previousObject = objectReferences[i]; //// If the object is an attached reference, there is no need to copy the shadow object //if (AttachedReferenceManager.GetAttachedReference(previousObject) != null) //{ // return; //} ShadowObject.Copy(previousObject, newObject); // NOTE: we don't use Add because of strings that might be duplicated clonedObjectMapping[previousObject] = newObject; if ((flags & AssetClonerFlags.RemoveItemIds) != AssetClonerFlags.RemoveItemIds) { CollectionItemIdentifiers sourceIds; if (CollectionItemIdHelper.TryGetCollectionItemIds(previousObject, out sourceIds)) { var newIds = CollectionItemIdHelper.GetCollectionItemIds(newObject); sourceIds.CloneInto(newIds, clonedObjectMapping); } } if ((flags & AssetClonerFlags.GenerateNewIdsForIdentifiableObjects) == AssetClonerFlags.GenerateNewIdsForIdentifiableObjects) { var identifiable = newObject as IIdentifiable; if (identifiable != null) { cloningIdRemapping = cloningIdRemapping ?? new Dictionary <Guid, Guid>(); var newId = Guid.NewGuid(); cloningIdRemapping[identifiable.Id] = newId; identifiable.Id = newId; } } } }
private ObjectId GetHashId() { // This methods use the stream that is already filled-up by the standard binary serialization of the object // Here we add ids and overrides metadata informations to the stream in order to calculate an accurate id var stream = streamOrValueType as MemoryStream; if (stream != null) { // ------------------------------------------------------ // Un-comment the following code to debug the ObjectId of the serialized version without taking into account overrides // ------------------------------------------------------ //var savedPosition = stream.Position; //stream.Position = 0; //var intermediateHashId = ObjectId.FromBytes(stream.ToArray()); //stream.Position = savedPosition; var writer = new BinarySerializationWriter(stream); Dictionary <string, OverrideType> overrides = null; List <string> orderedNames = null; foreach (var objectRef in objectReferences) { //// If the object is actually a reference to another asset, we can skip it as their won't be any overrides //if (AttachedReferenceManager.GetAttachedReference(objectRef) != null) //{ // continue; //} // Else gets the id if there are any (including shadows that are not part of the standard serialization) var shadowObject = ShadowObject.GetOrCreate(objectRef); if (shadowObject.IsIdentifiable) { // Get the shadow id (may be a non-shadow, so we may duplicate it in the stream (e.g Entity) // but it should not be a big deal var id = shadowObject.GetId(objectRef); writer.Write(id); } // Dump all members with overrides informations foreach (var item in shadowObject) { if (item.Key.Item2 == Override.OverrideKey) { // Use the member name to ensure a stable id var memberName = ((IMemberDescriptor)item.Key.Item1).Name; // Only creates the overrides dictionary if needed if (overrides == null) { overrides = new Dictionary <string, OverrideType>(); } overrides.Add(memberName, (OverrideType)item.Value); } } // Write any overrides information to the stream if (overrides != null) { // Collect names and order them by alphabetical order in order to make sure that we will get a stable id // (Dictionary doesn't ensure order) if (orderedNames == null) { orderedNames = new List <string>(); } orderedNames.Clear(); foreach (var entry in overrides) { orderedNames.Add(entry.Key); } orderedNames.Sort(); // Write all overrides for the current object reference foreach (var name in orderedNames) { writer.Write(name); // Write the override as an int writer.Write((int)overrides[name]); } // Clear overrides for next entry overrides.Clear(); } } writer.Flush(); stream.Position = 0; return(ObjectId.FromBytes(stream.ToArray())); } return(ObjectId.Empty); }
protected override void DrawCore(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex) { var viewParameters = context.Parameters; var device = context.GraphicsDevice; var viewInverse = Matrix.Invert(viewParameters.Get(TransformationKeys.View)); var viewProjection = viewParameters.Get(TransformationKeys.ViewProjection); BlendState previousBlendState = null; DepthStencilState previousDepthStencilState = null; Effect previousEffect = null; var isPicking = context.IsPicking(); bool hasBegin = false; for (var i = fromIndex; i <= toIndex; i++) { var renderItem = renderItems[i]; var spriteState = (SpriteProcessor.SpriteComponentState)renderItem.DrawContext; var spriteComp = spriteState.SpriteComponent; var transfoComp = spriteState.TransformComponent; var depthStencilState = spriteState.SpriteComponent.IgnoreDepth ? device.DepthStencilStates.None : device.DepthStencilStates.Default; var sprite = spriteComp.CurrentSprite; if (sprite == null) { continue; } // Update the sprite batch var blendState = isPicking ? device.BlendStates.Opaque : renderItems.HasTransparency ? (spriteComp.PremultipliedAlpha ? device.BlendStates.AlphaBlend : device.BlendStates.NonPremultiplied) : device.BlendStates.Opaque; var currentEffect = isPicking? GetOrCreatePickingSpriteEffect(): ShadowObject.IsObjectSelected(spriteComp) ? GetOrCreateSelectedSpriteEffect(): null; // TODO remove this code when material are available if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState) { if (hasBegin) { sprite3DBatch.End(); } sprite3DBatch.Begin(viewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, device.RasterizerStates.CullNone, currentEffect); hasBegin = true; } previousEffect = currentEffect; previousBlendState = blendState; previousDepthStencilState = depthStencilState; var sourceRegion = sprite.Region; var texture = sprite.Texture; var color = spriteComp.Color; if (isPicking) // TODO move this code corresponding to picking out of the runtime code. { color = new Color4(RuntimeIdHelper.ToRuntimeId(spriteComp)); } // skip the sprite if no texture is set. if (texture == null) { continue; } // determine the element world matrix depending on the type of sprite var worldMatrix = transfoComp.WorldMatrix; if (spriteComp.SpriteType == SpriteType.Billboard) { worldMatrix = viewInverse; // remove scale of the camera worldMatrix.Row1 /= ((Vector3)viewInverse.Row1).Length(); worldMatrix.Row2 /= ((Vector3)viewInverse.Row2).Length(); // set the scale of the object worldMatrix.Row1 *= ((Vector3)transfoComp.WorldMatrix.Row1).Length(); worldMatrix.Row2 *= ((Vector3)transfoComp.WorldMatrix.Row2).Length(); // set the position worldMatrix.TranslationVector = transfoComp.WorldMatrix.TranslationVector; } // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image) var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height); if (sprite.Orientation == ImageOrientation.Rotated90) { var oldCenterX = normalizedCenter.X; normalizedCenter.X = -normalizedCenter.Y; normalizedCenter.Y = oldCenterX; } // apply the offset due to the center of the sprite var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal); worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21; worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22; worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23; // draw the sprite sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, SwizzleMode.None, renderItem.Depth); } sprite3DBatch.End(); }
private static void SetDictionary(Asset asset, ShadowObjectPropertyKey key, Dictionary <UFile, ObjectId> dictionary) { var shadow = ShadowObject.GetOrCreate(asset); shadow[key] = dictionary; }
private void LateUpdate() { //grabs any object in a radius and adds it to the array hitObjects = Physics2D.OverlapCircleAll(lightCaster.transform.position, shadowCastRadius, isWall); lastPos = lightCaster.transform.position; tempPath = new List <Vector2>(); // this is the main loop this throws rays at all the objects shadow object points and then offsets it by a tiny margin // so everything is accounted for. for (int i = 0; i < hitObjects.Length; i++) { if (hitObjects[i].gameObject.GetComponent <ShadowObject>() != null) { ShadowObject tmp = hitObjects[i].gameObject.GetComponent <ShadowObject>(); for (int j = 0; j < tmp.objectVerts.Count; j++) { Vector2 angleVector = (tmp.objectVerts[j] - new Vector2(lightCaster.transform.position.x, lightCaster.transform.position.y)); RaycastHit2D ray2 = Physics2D.Raycast(lightCaster.transform.position, angleVector, shadowCastRadius, isWall); //at the exact pos of the verticy of the object if (ray2) { tempPath.Add(ray2.point); } Debug.DrawLine(lightCaster.transform.position, ray2.point); RaycastHit2D ray = Physics2D.Raycast(lightCaster.transform.position, new Vector2(angleVector.x - 0.1f, angleVector.y - 0.1f), shadowCastRadius, isWall); //at the exact pos of the verticy of the object if (ray) { tempPath.Add(ray.point); } Debug.DrawLine(lightCaster.transform.position, ray.point); RaycastHit2D ray3 = Physics2D.Raycast(lightCaster.transform.position, new Vector2(angleVector.x + 0.1f, angleVector.y + 0.1f), shadowCastRadius, isWall); //at the exact pos of the verticy of the object if (ray3) { tempPath.Add(ray3.point); } Debug.DrawLine(lightCaster.transform.position, ray3.point); } } } tempPath.Sort(new ClockwiseComparer(lightCaster.transform.position)); Debug.Log(tempPath.Count); //poly.SetPath(0, tempPath); // this is dumb IDK Y. IT HAS ALL THE RIGHT POINTS BUT IT ADDS A BUNCH OF ZEROOSSSS HELOOOO int pointCount = 0; pointCount = tempPath.Count; MeshFilter mf = GetComponent <MeshFilter>(); Mesh mesh = new Mesh(); Vector2[] points = tempPath.ToArray(); Vector3[] vertices = new Vector3[pointCount]; Vector2[] uv = new Vector2[pointCount]; for (int j = 0; j < pointCount; j++) { Vector2 actual = points[j]; vertices[j] = new Vector3(actual.x, actual.y, 0); uv[j] = actual; } Triangulator tr = new Triangulator(points); triangles = tr.Triangulate(); mesh.vertices = vertices; mesh.triangles = triangles; mesh.uv = uv; mf.mesh = mesh; }
protected override void DrawCore(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex) { var viewParameters = context.Parameters; var device = context.GraphicsDevice; var viewProjection = viewParameters.Get(TransformationKeys.ViewProjection); BlendState previousBlendState = null; DepthStencilState previousDepthStencilState = null; Effect previousEffect = null; var isPicking = context.IsPicking(); bool hasBegin = false; for (var i = fromIndex; i <= toIndex; i++) { var renderItem = renderItems[i]; var spriteState = (SpriteStudioProcessor.Data)renderItem.DrawContext; var transfoComp = spriteState.TransformComponent; var depthStencilState = device.DepthStencilStates.None; foreach (var node in spriteState.SpriteStudioComponent.SortedNodes) { if (node.Sprite?.Texture == null || node.Sprite.Region.Width <= 0 || node.Sprite.Region.Height <= 0f || node.Hide != 0) { continue; } // Update the sprite batch BlendState spriteBlending; switch (node.BaseNode.AlphaBlending) { case SpriteStudioBlending.Mix: spriteBlending = device.BlendStates.AlphaBlend; break; case SpriteStudioBlending.Multiplication: spriteBlending = MultBlendState; break; case SpriteStudioBlending.Addition: spriteBlending = device.BlendStates.Additive; break; case SpriteStudioBlending.Subtraction: spriteBlending = SubBlendState; break; default: throw new ArgumentOutOfRangeException(); } var blendState = isPicking ? device.BlendStates.Opaque : renderItems.HasTransparency ? spriteBlending : device.BlendStates.Opaque; var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : ShadowObject.IsObjectSelected(spriteState.SpriteStudioComponent) ? GetOrCreateSelectedSpriteEffect() : null; // TODO remove this code when material are available if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState) { if (hasBegin) { sprite3DBatch.End(); } sprite3DBatch.Begin(viewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, device.RasterizerStates.CullNone, currentEffect); hasBegin = true; } previousEffect = currentEffect; previousBlendState = blendState; previousDepthStencilState = depthStencilState; var sourceRegion = node.Sprite.Region; var texture = node.Sprite.Texture; // skip the sprite if no texture is set. if (texture == null) { continue; } var color4 = Color4.White; if (isPicking) { // TODO move this code corresponding to picking out of the runtime code. color4 = new Color4(RuntimeIdHelper.ToRuntimeId(spriteState.SpriteStudioComponent)); } else { if (node.BlendFactor > 0.0f) { switch (node.BlendType) //todo this should be done in a shader { case SpriteStudioBlending.Mix: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; case SpriteStudioBlending.Multiplication: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; case SpriteStudioBlending.Addition: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; case SpriteStudioBlending.Subtraction: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; default: throw new ArgumentOutOfRangeException(); } } else { color4 *= node.FinalTransparency; } } var worldMatrix = node.ModelTransform * transfoComp.WorldMatrix; // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image) var normalizedCenter = new Vector2(node.Sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - node.Sprite.Center.Y / sourceRegion.Height); if (node.Sprite.Orientation == ImageOrientation.Rotated90) { var oldCenterX = normalizedCenter.X; normalizedCenter.X = -normalizedCenter.Y; normalizedCenter.Y = oldCenterX; } // apply the offset due to the center of the sprite var size = node.Sprite.Size; var centerOffset = Vector2.Modulate(normalizedCenter, size); worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21; worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22; // draw the sprite sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref size, ref color4, node.Sprite.Orientation, SwizzleMode.None, renderItem.Depth); } } sprite3DBatch.End(); }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); BlendStateDescription? previousBlendState = null; DepthStencilStateDescription?previousDepthStencilState = null; EffectInstance previousEffect = null; //TODO string comparison ...? var isPicking = renderViewStage.RenderStage.Name == "Picking"; var device = RenderSystem.GraphicsDevice; var hasBegin = false; for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var spriteState = (RenderSpriteStudio)renderNode.RenderObject; var transfoComp = spriteState.TransformComponent; var depthStencilState = DepthStencilStates.DepthRead; foreach (var node in spriteState.SpriteStudioComponent.SortedNodes) { if (node.Sprite?.Texture == null || node.Sprite.Region.Width <= 0 || node.Sprite.Region.Height <= 0f || node.Hide != 0) { continue; } // Update the sprite batch BlendStateDescription spriteBlending; switch (node.BaseNode.AlphaBlending) { case SpriteStudioBlending.Mix: spriteBlending = BlendStates.AlphaBlend; break; case SpriteStudioBlending.Multiplication: spriteBlending = MultBlendState; break; case SpriteStudioBlending.Addition: spriteBlending = BlendStates.Additive; break; case SpriteStudioBlending.Subtraction: spriteBlending = SubBlendState; break; default: throw new ArgumentOutOfRangeException(); } // TODO: this should probably be moved to Prepare() // Project the position // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object var worldPosition = new Vector4(transfoComp.WorldMatrix.TranslationVector, 1.0f); Vector4 projectedPosition; Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition); var projectedZ = projectedPosition.Z / projectedPosition.W; var blendState = isPicking ? BlendStates.Default : spriteBlending; var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : ShadowObject.IsObjectSelected(spriteState.SpriteStudioComponent) ? GetOrCreateSelectedSpriteEffect() : null; // TODO remove this code when material are available if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState) { if (hasBegin) { sprite3DBatch.End(); } sprite3DBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, RasterizerStates.CullNone, currentEffect); hasBegin = true; } previousEffect = currentEffect; previousBlendState = blendState; previousDepthStencilState = depthStencilState; var sourceRegion = node.Sprite.Region; var texture = node.Sprite.Texture; // skip the sprite if no texture is set. if (texture == null) { continue; } var color4 = Color4.White; if (isPicking) { // TODO move this code corresponding to picking out of the runtime code. color4 = new Color4(RuntimeIdHelper.ToRuntimeId(spriteState.SpriteStudioComponent)); } else { if (node.BlendFactor > 0.0f) { switch (node.BlendType) //todo this should be done in a shader { case SpriteStudioBlending.Mix: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; case SpriteStudioBlending.Multiplication: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; case SpriteStudioBlending.Addition: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; case SpriteStudioBlending.Subtraction: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; default: throw new ArgumentOutOfRangeException(); } } else { color4 *= node.FinalTransparency; } } var worldMatrix = node.ModelTransform * transfoComp.WorldMatrix; // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image) var normalizedCenter = new Vector2(node.Sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - node.Sprite.Center.Y / sourceRegion.Height); if (node.Sprite.Orientation == ImageOrientation.Rotated90) { var oldCenterX = normalizedCenter.X; normalizedCenter.X = -normalizedCenter.Y; normalizedCenter.Y = oldCenterX; } // apply the offset due to the center of the sprite var size = node.Sprite.Size; var centerOffset = Vector2.Modulate(normalizedCenter, size); worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21; worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22; // draw the sprite sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref size, ref color4, node.Sprite.Orientation, SwizzleMode.None, projectedZ); } } if (hasBegin) { sprite3DBatch.End(); } }