/// <summary> /// Randomly emit particles sprite. /// </summary> /// <param name="emitCount">Number of particles to emit</param> public void Emit(int emitCount) { Sprite sprite = spriteRenderer.sprite; if (!sprite) { if (verboseDebug) { Debug.LogError("Unable to emit. Sprite is null in game object " + name); } return; } float colorR = EmitFromColor.r; float colorG = EmitFromColor.g; float colorB = EmitFromColor.b; Vector3 transformPos = spriteRenderer.gameObject.transform.position; Quaternion transformRot = spriteRenderer.gameObject.transform.rotation; Vector3 transformScale = spriteRenderer.gameObject.transform.lossyScale; //if Particle system is using Local Space discard transform modifiers. if (SimulationSpace == ParticleSystemSimulationSpace.Local) { transformPos = Vector3.zero; transformScale = Vector3.one; transformRot = Quaternion.identity; } bool flipX = spriteRenderer.flipX; bool flipY = spriteRenderer.flipY; float PixelsPerUnit = sprite.pixelsPerUnit; float width = (int)sprite.rect.size.x; float height = (int)sprite.rect.size.y; int intWidth = (int)width; //set particle size based on sprite Pixels per unit and particle system prefered size float halfPixelSize = 1 / PixelsPerUnit / 2; #if UNITY_5_5_OR_NEWER float startSize = 1 / (PixelsPerUnit); startSize *= mainModule.startSize.constant; //TODO ability to process different sizes coming in next update #else float startSize = 1 / (PixelsPerUnit); startSize *= particlesSystem.startSize; #endif //calculate sprite offset position in texture float offsetX = sprite.pivot.x / PixelsPerUnit; float offsetY = sprite.pivot.y / PixelsPerUnit; //if the sprite raw data is cached use that one, if not ask for it to the texture. Color[] pix; if (useSpritesSharingCache && Application.isPlaying) { pix = SpritesDataPool.GetSpriteColors(sprite, (int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); } else if (CacheSprites) { if (spritesSoFar.ContainsKey(sprite)) { pix = spritesSoFar[sprite]; } else { pix = sprite.texture.GetPixels((int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); spritesSoFar.Add(sprite, pix); } } else { pix = sprite.texture.GetPixels((int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); } float toleranceR = RedTolerance; float toleranceG = GreenTolerance; float toleranceB = BlueTolerance; float widthByHeight = width * height; Color[] cCache = colorCache; int[] iCache = indexCache; if (cCache.Length < widthByHeight) { colorCache = new Color[(int)widthByHeight]; indexCache = new int[(int)widthByHeight]; cCache = colorCache; iCache = indexCache; } bool UseEmissionFromColorLocal = UseEmissionFromColor; int matchesCount = 0; bool borderEmissionLocal = borderEmission == BorderEmission.Fast || borderEmission == BorderEmission.Precise; #region BLA if (borderEmissionLocal) { bool lastVisible = false; Color lastColor = pix[0]; int widthInt = (int)width; bool borderEmissionPreciseLocal = borderEmission == BorderEmission.Precise; for (int i = 0; i < widthByHeight; i++) { Color c = pix[i]; //skip pixels with alpha 0 bool currentVisible = c.a > 0; if (borderEmissionPreciseLocal) { int prevYindex = i - widthInt; if (prevYindex > 0) { Color cPrev = pix[prevYindex]; bool prevVisibleInY = cPrev.a > 0; if (currentVisible) { if (!prevVisibleInY) { //Skip unwanted colors when using Emission from color. if (UseEmissionFromColorLocal) { if (!FloatComparer.AreEqual(colorR, c.r, toleranceR) || !FloatComparer.AreEqual(colorG, c.g, toleranceG) || !FloatComparer.AreEqual(colorB, c.b, toleranceB)) { continue; } } cCache[matchesCount] = c; iCache[matchesCount] = i; matchesCount++; lastColor = c; lastVisible = true; continue; } } else { if (prevVisibleInY) { //Skip unwanted colors when using Emission from color. if (UseEmissionFromColorLocal) { if (!FloatComparer.AreEqual(colorR, cPrev.r, toleranceR) || !FloatComparer.AreEqual(colorG, cPrev.g, toleranceG) || !FloatComparer.AreEqual(colorB, cPrev.b, toleranceB)) { continue; } } cCache[matchesCount] = cPrev; iCache[matchesCount] = prevYindex; matchesCount++; } } } } if (borderEmissionLocal && !currentVisible && lastVisible) { //Skip unwanted colors when using Emission from color. if (UseEmissionFromColorLocal) { if (!FloatComparer.AreEqual(colorR, lastColor.r, toleranceR) || !FloatComparer.AreEqual(colorG, lastColor.g, toleranceG) || !FloatComparer.AreEqual(colorB, lastColor.b, toleranceB)) { continue; } } cCache[matchesCount] = lastColor; iCache[matchesCount] = i - 1; matchesCount++; lastVisible = true; } lastColor = c; if (!currentVisible) { lastVisible = false; continue; } if (!borderEmissionLocal || (currentVisible && !lastVisible)) { //Skip unwanted colors when using Emission from color. if (UseEmissionFromColorLocal) { if (!FloatComparer.AreEqual(colorR, c.r, toleranceR) || !FloatComparer.AreEqual(colorG, c.g, toleranceG) || !FloatComparer.AreEqual(colorB, c.b, toleranceB)) { continue; } } cCache[matchesCount] = c; iCache[matchesCount] = i; matchesCount++; lastVisible = true; } } } else { //find available pixels to emit from for (int i = 0; i < widthByHeight; i++) { Color c = pix[i]; //skip pixels with alpha 0 if (c.a <= 0) { continue; } //Skip unwanted colors when using Emission from color. if (UseEmissionFromColorLocal) { if (!FloatComparer.AreEqual(colorR, c.r, toleranceR) || !FloatComparer.AreEqual(colorG, c.g, toleranceG) || !FloatComparer.AreEqual(colorB, c.b, toleranceB)) { continue; } } cCache[matchesCount] = c; iCache[matchesCount] = i; matchesCount++; } } #endregion //Profiler.EndSample(); //no colors were matched, stop if (matchesCount <= 0) { return; } Vector3 tempV = Vector3.zero; //Profiler.BeginSample("Part Two"); //emit needed particle count for (int k = 0; k < emitCount; k++) { int index = Random.Range(0, matchesCount - 1); int i = iCache[index]; //get pixel position in texture float posX = ((i % width) / PixelsPerUnit) - offsetX; float posY = ((i / intWidth) / PixelsPerUnit) - offsetY; //handle sprite renderer fliping if (flipX) { posX = width / PixelsPerUnit - posX - offsetX * 2; } if (flipY) { posY = height / PixelsPerUnit - posY - offsetY * 2; } tempV.x = posX * transformScale.x - halfPixelSize; tempV.y = posY * transformScale.y + halfPixelSize; ParticleSystem.EmitParams em = new ParticleSystem.EmitParams(); // define new particle start position based on Sprite pixel position in texture, this game object's rotation and position. em.position = transformRot * tempV + transformPos; if (UsePixelSourceColor) { em.startColor = cCache[index]; } em.startSize = startSize; particlesSystem.Emit(em, 1); } //Profiler.EndSample(); }
public void Emit(int emitCount) { Sprite sprite1 = this.spriteRenderer.get_sprite(); if (!Object.op_Implicit((Object)sprite1)) { if (!this.verboseDebug) { return; } Debug.LogError((object)("Unable to emit. Sprite is null in game object " + ((Object)this).get_name())); } else { float r = (float)this.EmitFromColor.r; float g = (float)this.EmitFromColor.g; float b = (float)this.EmitFromColor.b; Vector3 vector3_1 = ((Component)this.spriteRenderer).get_gameObject().get_transform().get_position(); Quaternion quaternion = ((Component)this.spriteRenderer).get_gameObject().get_transform().get_rotation(); Vector3 vector3_2 = ((Component)this.spriteRenderer).get_gameObject().get_transform().get_lossyScale(); if (this.SimulationSpace == null) { vector3_1 = Vector3.get_zero(); vector3_2 = Vector3.get_one(); quaternion = Quaternion.get_identity(); } bool flipX = this.spriteRenderer.get_flipX(); bool flipY = this.spriteRenderer.get_flipY(); float pixelsPerUnit = sprite1.get_pixelsPerUnit(); Rect rect1 = sprite1.get_rect(); float x1 = (float)(int)((Rect) ref rect1).get_size().x; Rect rect2 = sprite1.get_rect(); float y1 = (float)(int)((Rect) ref rect2).get_size().y; int num1 = (int)x1; float num2 = (float)(1.0 / (double)pixelsPerUnit / 2.0); double num3 = (double)(1f / pixelsPerUnit); ParticleSystem.MinMaxCurve startSize = ((ParticleSystem.MainModule) ref this.mainModule).get_startSize(); double constant = (double)((ParticleSystem.MinMaxCurve) ref startSize).get_constant(); float num4 = (float)(num3 * constant); float num5 = (float)sprite1.get_pivot().x / pixelsPerUnit; float num6 = (float)sprite1.get_pivot().y / pixelsPerUnit; Color[] colorArray; if (this.useSpritesSharingCache && Application.get_isPlaying()) { Sprite sprite2 = sprite1; Rect rect3 = sprite1.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = sprite1.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int blockWidth = (int)x1; int blockHeight = (int)y1; colorArray = SpritesDataPool.GetSpriteColors(sprite2, x2, y2, blockWidth, blockHeight); } else if (this.CacheSprites) { if (this.spritesSoFar.ContainsKey(sprite1)) { colorArray = this.spritesSoFar[sprite1]; } else { Texture2D texture = sprite1.get_texture(); Rect rect3 = sprite1.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = sprite1.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int num7 = (int)x1; int num8 = (int)y1; colorArray = texture.GetPixels(x2, y2, num7, num8); this.spritesSoFar.Add(sprite1, colorArray); } } else { Texture2D texture = sprite1.get_texture(); Rect rect3 = sprite1.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = sprite1.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int num7 = (int)x1; int num8 = (int)y1; colorArray = texture.GetPixels(x2, y2, num7, num8); } float redTolerance = this.RedTolerance; float greenTolerance = this.GreenTolerance; float blueTolerance = this.BlueTolerance; float num9 = x1 * y1; Color[] colorCache = this.colorCache; int[] indexCache = this.indexCache; if ((double)colorCache.Length < (double)num9) { this.colorCache = new Color[(int)num9]; this.indexCache = new int[(int)num9]; colorCache = this.colorCache; indexCache = this.indexCache; } bool emissionFromColor = this.UseEmissionFromColor; int index1 = 0; bool flag1 = this.borderEmission == EmitterBase.BorderEmission.Fast || this.borderEmission == EmitterBase.BorderEmission.Precise; if (flag1) { bool flag2 = false; Color color1 = colorArray[0]; int num7 = (int)x1; bool flag3 = this.borderEmission == EmitterBase.BorderEmission.Precise; for (int index2 = 0; (double)index2 < (double)num9; ++index2) { Color color2 = colorArray[index2]; bool flag4 = color2.a > 0.0; if (flag3) { int index3 = index2 - num7; if (index3 > 0) { Color color3 = colorArray[index3]; bool flag5 = color3.a > 0.0; if (flag4) { if (!flag5) { if (!emissionFromColor || FloatComparer.AreEqual(r, (float)color2.r, redTolerance) && FloatComparer.AreEqual(g, (float)color2.g, greenTolerance) && FloatComparer.AreEqual(b, (float)color2.b, blueTolerance)) { colorCache[index1] = color2; indexCache[index1] = index2; ++index1; color1 = color2; flag2 = true; continue; } continue; } } else if (flag5) { if (!emissionFromColor || FloatComparer.AreEqual(r, (float)color3.r, redTolerance) && FloatComparer.AreEqual(g, (float)color3.g, greenTolerance) && FloatComparer.AreEqual(b, (float)color3.b, blueTolerance)) { colorCache[index1] = color3; indexCache[index1] = index3; ++index1; } else { continue; } } } } if (flag1 && !flag4 && flag2) { if (!emissionFromColor || FloatComparer.AreEqual(r, (float)color1.r, redTolerance) && FloatComparer.AreEqual(g, (float)color1.g, greenTolerance) && FloatComparer.AreEqual(b, (float)color1.b, blueTolerance)) { colorCache[index1] = color1; indexCache[index1] = index2 - 1; ++index1; flag2 = true; } else { continue; } } color1 = color2; if (!flag4) { flag2 = false; } else if ((!flag1 || flag4 && !flag2) && (!emissionFromColor || FloatComparer.AreEqual(r, (float)color2.r, redTolerance) && FloatComparer.AreEqual(g, (float)color2.g, greenTolerance) && FloatComparer.AreEqual(b, (float)color2.b, blueTolerance))) { colorCache[index1] = color2; indexCache[index1] = index2; ++index1; flag2 = true; } } } else { for (int index2 = 0; (double)index2 < (double)num9; ++index2) { Color color = colorArray[index2]; if (color.a > 0.0 && (!emissionFromColor || FloatComparer.AreEqual(r, (float)color.r, redTolerance) && FloatComparer.AreEqual(g, (float)color.g, greenTolerance) && FloatComparer.AreEqual(b, (float)color.b, blueTolerance))) { colorCache[index1] = color; indexCache[index1] = index2; ++index1; } } } if (index1 <= 0) { return; } Vector3 zero = Vector3.get_zero(); for (int index2 = 0; index2 < emitCount; ++index2) { int index3 = Random.Range(0, index1 - 1); int num7 = indexCache[index3]; float num8 = (float)num7 % x1 / pixelsPerUnit - num5; float num10 = (float)(num7 / num1) / pixelsPerUnit - num6; if (flipX) { num8 = (float)((double)x1 / (double)pixelsPerUnit - (double)num8 - (double)num5 * 2.0); } if (flipY) { num10 = (float)((double)y1 / (double)pixelsPerUnit - (double)num10 - (double)num6 * 2.0); } zero.x = (__Null)((double)num8 * vector3_2.x - (double)num2); zero.y = (__Null)((double)num10 * vector3_2.y + (double)num2); ParticleSystem.EmitParams emitParams = (ParticleSystem.EmitParams)null; ((ParticleSystem.EmitParams) ref emitParams).set_position(Vector3.op_Addition(Quaternion.op_Multiply(quaternion, zero), vector3_1)); if (this.UsePixelSourceColor) { ((ParticleSystem.EmitParams) ref emitParams).set_startColor(Color32.op_Implicit(colorCache[index3])); } ((ParticleSystem.EmitParams) ref emitParams).set_startSize(num4); this.particlesSystem.Emit(emitParams, 1); } } }
/// <summary> /// Will emit one particle from every pixel in the sprite, or from every pixel in the found color if UseEmissionFromColor is set to true /// </summary> /// <param name="hideSprite">Must it disable referenced spriteRenderer</param> public void EmitAll(bool hideSprite = true) { if (hideSprite) { spriteRenderer.enabled = false; } Sprite sprite = spriteRenderer.sprite; if (!sprite) { if (verboseDebug) { Debug.LogError("Unable to emit. Sprite is null in game object " + name); } return; } float colorR = EmitFromColor.r; float colorG = EmitFromColor.g; float colorB = EmitFromColor.b; Vector3 transformPos = spriteRenderer.gameObject.transform.position; Quaternion transformRot = spriteRenderer.gameObject.transform.rotation; Vector3 transformScale = spriteRenderer.gameObject.transform.lossyScale; //if Particle system is using Local Space discard transform modifiers. if (SimulationSpace == ParticleSystemSimulationSpace.Local) { transformPos = Vector3.zero; transformScale = Vector3.one; transformRot = Quaternion.identity; } bool flipX = spriteRenderer.flipX; bool flipY = spriteRenderer.flipY; float PixelsPerUnit = sprite.pixelsPerUnit; float width = (int)sprite.rect.size.x; float height = (int)sprite.rect.size.y; //set particle size based on sprite Pixels per unit and particle system prefered size #if UNITY_5_5_OR_NEWER float startSize = 1 / (PixelsPerUnit); startSize *= mainModule.startSize.constant; //TODO ability to process different sizes coming in next update #else float startSize = 1 / (PixelsPerUnit); startSize *= particlesSystem.startSize; #endif //calculate sprite offset position in texture float offsetX = sprite.pivot.x / PixelsPerUnit; float offsetY = sprite.pivot.y / PixelsPerUnit; //if the sprite raw data is cached use that one, if not ask for it to the texture. Color[] pix; if (useSpritesSharingCache && Application.isPlaying) { pix = SpritesDataPool.GetSpriteColors(sprite, (int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); } else if (CacheSprites) { if (spritesSoFar.ContainsKey(sprite)) { pix = spritesSoFar[sprite]; } else { pix = sprite.texture.GetPixels((int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); spritesSoFar.Add(sprite, pix); } } else { pix = sprite.texture.GetPixels((int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); } float toleranceR = RedTolerance; float toleranceG = GreenTolerance; float toleranceB = BlueTolerance; float widthByHeight = width * height; Vector3 tempV = Vector3.zero; for (int i = 0; i < widthByHeight; i++) { Color c = pix[i]; //skip pixels with alpha 0 if (c.a <= 0) { continue; } //Skip unwanted colors when using Emission from color. if (UseEmissionFromColor) { if (!FloatComparer.AreEqual(colorR, c.r, toleranceR) || !FloatComparer.AreEqual(colorG, c.g, toleranceG) || !FloatComparer.AreEqual(colorB, c.b, toleranceB)) { continue; } } //get pixel position in texture float posX = ((i % width) / PixelsPerUnit) - offsetX; float posY = ((i / width) / PixelsPerUnit) - offsetY; //handle sprite renderer fliping if (flipX) { posX = width / PixelsPerUnit - posX - offsetX * 2; } if (flipY) { posY = height / PixelsPerUnit - posY - offsetY * 2; } tempV.x = posX * transformScale.x; tempV.y = posY * transformScale.y; ParticleSystem.EmitParams em = new ParticleSystem.EmitParams(); // define new particle start position based on Sprite pixel position in texture, this game object's rotation and position. em.position = transformRot * tempV + transformPos; if (UsePixelSourceColor) { em.startColor = c; } em.startSize = startSize; particlesSystem.Emit(em, 1); } }
/// <summary> /// Will emit one particle from every pixel in the sprite, or from every pixel in the found color if UseEmissionFromColor is set to true /// </summary> /// <param name="hideSprite">Must it disable referenced spriteRenderer</param> public void EmitAll(bool hideSprite = true) { if (hideSprite) { imageRenderer.enabled = false; } Sprite sprite = imageRenderer.sprite; if (!sprite) { if (verboseDebug) { Debug.LogError("Unable to emit. Sprite is null in game object " + name); } return; } float colorR = EmitFromColor.r; float colorG = EmitFromColor.g; float colorB = EmitFromColor.b; float PixelsPerUnit = sprite.pixelsPerUnit; float width = (int)sprite.rect.size.x; float height = (int)sprite.rect.size.y; //set particle size based on sprite Pixels per unit and particle system prefered size #if UNITY_5_5_OR_NEWER var startSize = mainModule.startSize.constant; //TODO ability to process different sizes coming in next update #else var startSize = particlesSystem.startSize; #endif //calculate sprite offset position in texture float offsetX = sprite.pivot.x / PixelsPerUnit; float offsetY = sprite.pivot.y / PixelsPerUnit; //if the sprite raw data is cached use that one, if not ask for it to the texture. Color[] pix; if (useSpritesSharingCache && Application.isPlaying) { pix = SpritesDataPool.GetSpriteColors(sprite, (int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); } else if (CacheSprites) { if (spritesSoFar.ContainsKey(sprite)) { pix = spritesSoFar[sprite]; } else { pix = sprite.texture.GetPixels((int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); spritesSoFar.Add(sprite, pix); } } else { pix = sprite.texture.GetPixels((int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); } float toleranceR = RedTolerance; float toleranceG = GreenTolerance; float toleranceB = BlueTolerance; float widthByHeight = width * height; Vector3 tempV = Vector3.zero; for (int i = 0; i < widthByHeight; i++) { Color c = pix[i]; //skip pixels with alpha 0 if (c.a <= 0) { continue; } //Skip unwanted colors when using Emission from color. if (UseEmissionFromColor) { if (!FloatComparer.AreEqual(colorR, c.r, toleranceR) || !FloatComparer.AreEqual(colorG, c.g, toleranceG) || !FloatComparer.AreEqual(colorB, c.b, toleranceB)) { continue; } } //get pixel position in texture float posX = ((i % width) / PixelsPerUnit) - offsetX; float posY = ((i / width) / PixelsPerUnit) - offsetY; ParticleSystem.EmitParams em = new ParticleSystem.EmitParams(); // define new particle start position based on Sprite pixel position in texture, this game object's rotation and position. tempV.x = posX * wMult + offsetXY.x; tempV.y = posY * hMult - offsetXY.y; em.position = tempV; if (UsePixelSourceColor) { em.startColor = c; } em.startSize = startSize; particlesSystem.Emit(em, 1); } }
public void EmitAll(bool hideSprite = true) { if (hideSprite) { ((Renderer)this.spriteRenderer).set_enabled(false); } Sprite sprite1 = this.spriteRenderer.get_sprite(); if (!Object.op_Implicit((Object)sprite1)) { if (!this.verboseDebug) { return; } Debug.LogError((object)("Unable to emit. Sprite is null in game object " + ((Object)this).get_name())); } else { float r = (float)this.EmitFromColor.r; float g = (float)this.EmitFromColor.g; float b = (float)this.EmitFromColor.b; Vector3 vector3_1 = ((Component)this.spriteRenderer).get_gameObject().get_transform().get_position(); Quaternion quaternion = ((Component)this.spriteRenderer).get_gameObject().get_transform().get_rotation(); Vector3 vector3_2 = ((Component)this.spriteRenderer).get_gameObject().get_transform().get_lossyScale(); if (this.SimulationSpace == null) { vector3_1 = Vector3.get_zero(); vector3_2 = Vector3.get_one(); quaternion = Quaternion.get_identity(); } bool flipX = this.spriteRenderer.get_flipX(); bool flipY = this.spriteRenderer.get_flipY(); float pixelsPerUnit = sprite1.get_pixelsPerUnit(); Rect rect1 = sprite1.get_rect(); float x1 = (float)(int)((Rect) ref rect1).get_size().x; Rect rect2 = sprite1.get_rect(); float y1 = (float)(int)((Rect) ref rect2).get_size().y; double num1 = (double)(1f / pixelsPerUnit); ParticleSystem.MinMaxCurve startSize = ((ParticleSystem.MainModule) ref this.mainModule).get_startSize(); double constant = (double)((ParticleSystem.MinMaxCurve) ref startSize).get_constant(); float num2 = (float)(num1 * constant); float num3 = (float)sprite1.get_pivot().x / pixelsPerUnit; float num4 = (float)sprite1.get_pivot().y / pixelsPerUnit; Color[] colorArray; if (this.useSpritesSharingCache && Application.get_isPlaying()) { Sprite sprite2 = sprite1; Rect rect3 = sprite1.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = sprite1.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int blockWidth = (int)x1; int blockHeight = (int)y1; colorArray = SpritesDataPool.GetSpriteColors(sprite2, x2, y2, blockWidth, blockHeight); } else if (this.CacheSprites) { if (this.spritesSoFar.ContainsKey(sprite1)) { colorArray = this.spritesSoFar[sprite1]; } else { Texture2D texture = sprite1.get_texture(); Rect rect3 = sprite1.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = sprite1.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int num5 = (int)x1; int num6 = (int)y1; colorArray = texture.GetPixels(x2, y2, num5, num6); this.spritesSoFar.Add(sprite1, colorArray); } } else { Texture2D texture = sprite1.get_texture(); Rect rect3 = sprite1.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = sprite1.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int num5 = (int)x1; int num6 = (int)y1; colorArray = texture.GetPixels(x2, y2, num5, num6); } float redTolerance = this.RedTolerance; float greenTolerance = this.GreenTolerance; float blueTolerance = this.BlueTolerance; float num7 = x1 * y1; Vector3 zero = Vector3.get_zero(); for (int index = 0; (double)index < (double)num7; ++index) { Color color = colorArray[index]; if (color.a > 0.0 && (!this.UseEmissionFromColor || FloatComparer.AreEqual(r, (float)color.r, redTolerance) && FloatComparer.AreEqual(g, (float)color.g, greenTolerance) && FloatComparer.AreEqual(b, (float)color.b, blueTolerance))) { float num5 = (float)index % x1 / pixelsPerUnit - num3; float num6 = (float)index / x1 / pixelsPerUnit - num4; if (flipX) { num5 = (float)((double)x1 / (double)pixelsPerUnit - (double)num5 - (double)num3 * 2.0); } if (flipY) { num6 = (float)((double)y1 / (double)pixelsPerUnit - (double)num6 - (double)num4 * 2.0); } zero.x = (__Null)((double)num5 * vector3_2.x); zero.y = (__Null)((double)num6 * vector3_2.y); ParticleSystem.EmitParams emitParams = (ParticleSystem.EmitParams)null; ((ParticleSystem.EmitParams) ref emitParams).set_position(Vector3.op_Addition(Quaternion.op_Multiply(quaternion, zero), vector3_1)); if (this.UsePixelSourceColor) { ((ParticleSystem.EmitParams) ref emitParams).set_startColor(Color32.op_Implicit(color)); } ((ParticleSystem.EmitParams) ref emitParams).set_startSize(num2); this.particlesSystem.Emit(emitParams, 1); } } } }
/// <summary> /// Randomly emit particles in sprite. /// </summary> /// <param name="emitCount">Number of particles to emit</param> public void Emit(int emitCount) { Sprite sprite = imageRenderer.sprite; if (imageRenderer.overrideSprite) { sprite = imageRenderer.overrideSprite; //Debug.Log(sprite.rect.size.x); } if (!sprite) { if (verboseDebug) { Debug.LogError("Unable to emit. Sprite is null in game object " + name); } return; } float colorR = EmitFromColor.r; float colorG = EmitFromColor.g; float colorB = EmitFromColor.b; float PixelsPerUnit = sprite.pixelsPerUnit; float width = (int)sprite.rect.size.x; float height = (int)sprite.rect.size.y; //set particle size based on sprite Pixels per unit and particle system prefered size #if UNITY_5_5_OR_NEWER ParticleSystem.MinMaxCurve startSize = mainModule.startSize; #else var startSize = particlesSystem.startSize; #endif //calculate sprite offset position in texture float offsetX = sprite.pivot.x / PixelsPerUnit; float offsetY = sprite.pivot.y / PixelsPerUnit; //if the sprite raw data is cached use that one, if not ask for it to the texture. Color[] pix; if (useSpritesSharingCache && Application.isPlaying) { pix = SpritesDataPool.GetSpriteColors(sprite, (int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); } else if (CacheSprites) { if (spritesSoFar.ContainsKey(sprite)) { pix = spritesSoFar[sprite]; } else { pix = sprite.texture.GetPixels((int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); spritesSoFar.Add(sprite, pix); } } else { pix = sprite.texture.GetPixels((int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); } float toleranceR = RedTolerance; float toleranceG = GreenTolerance; float toleranceB = BlueTolerance; float widthByHeight = width * height; Color[] cCache = colorCache; int[] iCache = indexCache; if (cCache.Length < widthByHeight) { colorCache = new Color[(int)widthByHeight]; indexCache = new int[(int)widthByHeight]; cCache = colorCache; iCache = indexCache; } //TODO XXX this next "for" is the bottleneck for performance in big images. (optimization could be made, separating this for in 2 or more frames) //find available pixels to emit from int matchesCount = 0; for (int i = 0; i < widthByHeight; i++) { Color c = pix[i]; //skip pixels with alpha 0 if (c.a > 0) { //Skip unwanted colors when using Emission from color. if (UseEmissionFromColor) { if (!FloatComparer.AreEqual(colorR, c.r, toleranceR) || !FloatComparer.AreEqual(colorG, c.g, toleranceG) || !FloatComparer.AreEqual(colorB, c.b, toleranceB)) { continue; } } cCache[matchesCount] = c; iCache[matchesCount] = i; matchesCount++; } } //no colors were matched, stop if (matchesCount <= 0) { return; } Vector3 tempV = Vector3.zero; //emit needed particle count for (int k = 0; k < emitCount; k++) { int index = Random.Range(0, matchesCount - 1); int i = iCache[index]; //get pixel position in texture float posX = ((i % width) / PixelsPerUnit) - offsetX; float posY = ((i / width) / PixelsPerUnit) - offsetY; ParticleSystem.EmitParams em = new ParticleSystem.EmitParams(); // define new particle start position based on Sprite pixel position in texture, this game object's rotation and position. tempV.x = posX * wMult + offsetXY.x; tempV.y = posY * hMult - offsetXY.y; em.position = tempV; if (UsePixelSourceColor) { em.startColor = cCache[index]; } #if UNITY_5_5_OR_NEWER em.startSize = startSize.constant;//TODO ability to process different sizes coming in next update #else em.startSize = startSize; #endif particlesSystem.Emit(em, 1); } }
/// <summary> /// Will cache sprite data needed to emit later. /// Static emitter needs to cache sprite coords data first before emitting. /// A lot of variables are saved as local for fast access. /// </summary> public virtual void CacheSprite(bool relativeToParent = false) { #if MEM_DEBUG Debug.Log("<color=black>CacheSprite</color> " + gameObject.name); long mem = System.GC.GetTotalMemory(false); Debug.Log("<color=red>F00 = </color>" + mem / 1024 / 1024); #endif hasCachingEnded = false; particlesCacheCount = 0; Sprite sprite = spriteRenderer.sprite; if (!sprite) { if (verboseDebug) { Debug.LogError("Unable to cache. Sprite is null in game object " + name); } return; } float colorR = EmitFromColor.r; float colorG = EmitFromColor.g; float colorB = EmitFromColor.b; //getting sprite source as gameobject for pos rot and scale Vector3 transformPos = spriteRenderer.gameObject.transform.position; Quaternion transformRot = spriteRenderer.gameObject.transform.rotation; Vector3 transformScale = spriteRenderer.gameObject.transform.lossyScale; bool flipX = spriteRenderer.flipX; bool flipY = spriteRenderer.flipY; float PixelsPerUnit = sprite.pixelsPerUnit; if (spriteRenderer == null || spriteRenderer.sprite == null) { if (verboseDebug) { Debug.LogError("Sprite reference missing"); } } float width = (int)sprite.rect.size.x; float height = (int)sprite.rect.size.y; //set particle size based on sprite Pixels per unit and particle system prefered size #if UNITY_5_5_OR_NEWER particleStartSize = 1 / PixelsPerUnit; particleStartSize *= mainModule.startSize.constant; //TODO ability to process different sizes coming in next update #else particleStartSize = 1 / PixelsPerUnit; particleStartSize *= particlesSystem.startSize; #endif //calculate sprite offset position in texture float offsetX = sprite.pivot.x / PixelsPerUnit; float offsetY = sprite.pivot.y / PixelsPerUnit; //ask texture for wanted sprite Color[] pix; if (useSpritesSharingCache && Application.isPlaying) { pix = SpritesDataPool.GetSpriteColors(sprite, (int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); } else { pix = sprite.texture.GetPixels((int)sprite.rect.position.x, (int)sprite.rect.position.y, (int)width, (int)height); } float toleranceR = RedTolerance; float toleranceG = GreenTolerance; float toleranceB = BlueTolerance; float widthByHeight = width * height; // Create lists for fast insertion List <Color> colorsCache = new List <Color>(); List <Vector3> positionsCache = new List <Vector3>(); for (int i = 0; i < widthByHeight; i++) { Color c = pix[i]; //skip pixels with alpha 0 if (c.a <= 0) { continue; } //Skip unwanted colors when using Emission from color. if (UseEmissionFromColor && (!FloatComparer.AreEqual(colorR, c.r, toleranceR) || !FloatComparer.AreEqual(colorG, c.g, toleranceG) || !FloatComparer.AreEqual(colorB, c.b, toleranceB))) { continue; } //get pixel position in texture float posX = ((i % width) / PixelsPerUnit) - offsetX; float posY = ((i / width) / PixelsPerUnit) - offsetY; //handle sprite renderer fliping if (flipX) { posX = width / PixelsPerUnit - posX - offsetX * 2; } if (flipY) { posY = height / PixelsPerUnit - posY - offsetY * 2; } Vector3 vTemp; // define new particle start position based on Sprite pixel position in texture, this game object's rotation and position. if (relativeToParent) { vTemp = transformRot * new Vector3(posX * transformScale.x, posY * transformScale.y, 0) + transformPos; } else { vTemp = new Vector3(posX, posY, 0); } positionsCache.Add(vTemp); colorsCache.Add(c); particlesCacheCount++; } //Duplicate data as an array for better performance when accessing later //particlesCacheArray = particlesCache.ToArray(); particleInitPositionsCache = positionsCache.ToArray(); particleInitColorCache = colorsCache.ToArray(); if (particlesCacheCount <= 0) { if (verboseDebug) { Debug.LogWarning("Caching particle emission went wrong. This is most probably because couldn't find wanted color in sprite"); } return; } #if MEM_DEBUG Debug.Log("<color=green>F01 = </color>" + System.GC.GetTotalMemory(false) / 1024 / 1024 + " | delta: " + (System.GC.GetTotalMemory(false) - mem) / 1024 / 1024); #endif //clear unwanted allocation pix = null; positionsCache.Clear(); positionsCache = null; colorsCache.Clear(); colorsCache = null; System.GC.Collect(); hasCachingEnded = true; #if MEM_DEBUG Debug.Log("<color=blue>F02 = </color> = " + System.GC.GetTotalMemory(false) / 1024 / 1024 + " | final delta: " + (System.GC.GetTotalMemory(false) - mem) / 1024 / 1024); #endif #if UNITY_EDITOR cachedSprite = sprite; #endif //finally call event to warn we've finished if (OnCacheEnded != null) { OnCacheEnded(); } }
public void EmitAll(bool hideSprite = true) { if (hideSprite) { ((Behaviour)this.imageRenderer).set_enabled(false); } Sprite sprite1 = this.imageRenderer.get_sprite(); if (!Object.op_Implicit((Object)sprite1)) { if (!this.verboseDebug) { return; } Debug.LogError((object)("Unable to emit. Sprite is null in game object " + ((Object)this).get_name())); } else { float r = (float)this.EmitFromColor.r; float g = (float)this.EmitFromColor.g; float b = (float)this.EmitFromColor.b; float pixelsPerUnit = sprite1.get_pixelsPerUnit(); Rect rect1 = sprite1.get_rect(); float x1 = (float)(int)((Rect) ref rect1).get_size().x; Rect rect2 = sprite1.get_rect(); float y1 = (float)(int)((Rect) ref rect2).get_size().y; ParticleSystem.MinMaxCurve startSize = ((ParticleSystem.MainModule) ref this.mainModule).get_startSize(); float constant = ((ParticleSystem.MinMaxCurve) ref startSize).get_constant(); float num1 = (float)sprite1.get_pivot().x / pixelsPerUnit; float num2 = (float)sprite1.get_pivot().y / pixelsPerUnit; Color[] colorArray; if (this.useSpritesSharingCache && Application.get_isPlaying()) { Sprite sprite2 = sprite1; Rect rect3 = sprite1.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = sprite1.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int blockWidth = (int)x1; int blockHeight = (int)y1; colorArray = SpritesDataPool.GetSpriteColors(sprite2, x2, y2, blockWidth, blockHeight); } else if (this.CacheSprites) { if (this.spritesSoFar.ContainsKey(sprite1)) { colorArray = this.spritesSoFar[sprite1]; } else { Texture2D texture = sprite1.get_texture(); Rect rect3 = sprite1.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = sprite1.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int num3 = (int)x1; int num4 = (int)y1; colorArray = texture.GetPixels(x2, y2, num3, num4); this.spritesSoFar.Add(sprite1, colorArray); } } else { Texture2D texture = sprite1.get_texture(); Rect rect3 = sprite1.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = sprite1.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int num3 = (int)x1; int num4 = (int)y1; colorArray = texture.GetPixels(x2, y2, num3, num4); } float redTolerance = this.RedTolerance; float greenTolerance = this.GreenTolerance; float blueTolerance = this.BlueTolerance; float num5 = x1 * y1; Vector3 zero = Vector3.get_zero(); for (int index = 0; (double)index < (double)num5; ++index) { Color color = colorArray[index]; if (color.a > 0.0 && (!this.UseEmissionFromColor || FloatComparer.AreEqual(r, (float)color.r, redTolerance) && FloatComparer.AreEqual(g, (float)color.g, greenTolerance) && FloatComparer.AreEqual(b, (float)color.b, blueTolerance))) { float num3 = (float)index % x1 / pixelsPerUnit - num1; float num4 = (float)index / x1 / pixelsPerUnit - num2; ParticleSystem.EmitParams emitParams = (ParticleSystem.EmitParams)null; zero.x = (__Null)((double)num3 * (double)this.wMult + this.offsetXY.x); zero.y = (__Null)((double)num4 * (double)this.hMult - this.offsetXY.y); ((ParticleSystem.EmitParams) ref emitParams).set_position(zero); if (this.UsePixelSourceColor) { ((ParticleSystem.EmitParams) ref emitParams).set_startColor(Color32.op_Implicit(color)); } ((ParticleSystem.EmitParams) ref emitParams).set_startSize(constant); this.particlesSystem.Emit(emitParams, 1); } } } }
public void Emit(int emitCount) { Sprite key = this.imageRenderer.get_sprite(); if (Object.op_Implicit((Object)this.imageRenderer.get_overrideSprite())) { key = this.imageRenderer.get_overrideSprite(); } if (!Object.op_Implicit((Object)key)) { if (!this.verboseDebug) { return; } Debug.LogError((object)("Unable to emit. Sprite is null in game object " + ((Object)this).get_name())); } else { float r = (float)this.EmitFromColor.r; float g = (float)this.EmitFromColor.g; float b = (float)this.EmitFromColor.b; float pixelsPerUnit = key.get_pixelsPerUnit(); Rect rect1 = key.get_rect(); float x1 = (float)(int)((Rect) ref rect1).get_size().x; Rect rect2 = key.get_rect(); float y1 = (float)(int)((Rect) ref rect2).get_size().y; ParticleSystem.MinMaxCurve startSize = ((ParticleSystem.MainModule) ref this.mainModule).get_startSize(); float num1 = (float)key.get_pivot().x / pixelsPerUnit; float num2 = (float)key.get_pivot().y / pixelsPerUnit; Color[] colorArray; if (this.useSpritesSharingCache && Application.get_isPlaying()) { Sprite sprite = key; Rect rect3 = key.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = key.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int blockWidth = (int)x1; int blockHeight = (int)y1; colorArray = SpritesDataPool.GetSpriteColors(sprite, x2, y2, blockWidth, blockHeight); } else if (this.CacheSprites) { if (this.spritesSoFar.ContainsKey(key)) { colorArray = this.spritesSoFar[key]; } else { Texture2D texture = key.get_texture(); Rect rect3 = key.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = key.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int num3 = (int)x1; int num4 = (int)y1; colorArray = texture.GetPixels(x2, y2, num3, num4); this.spritesSoFar.Add(key, colorArray); } } else { Texture2D texture = key.get_texture(); Rect rect3 = key.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = key.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int num3 = (int)x1; int num4 = (int)y1; colorArray = texture.GetPixels(x2, y2, num3, num4); } float redTolerance = this.RedTolerance; float greenTolerance = this.GreenTolerance; float blueTolerance = this.BlueTolerance; float num5 = x1 * y1; Color[] colorCache = this.colorCache; int[] indexCache = this.indexCache; if ((double)colorCache.Length < (double)num5) { this.colorCache = new Color[(int)num5]; this.indexCache = new int[(int)num5]; colorCache = this.colorCache; indexCache = this.indexCache; } int index1 = 0; for (int index2 = 0; (double)index2 < (double)num5; ++index2) { Color color = colorArray[index2]; if (color.a > 0.0 && (!this.UseEmissionFromColor || FloatComparer.AreEqual(r, (float)color.r, redTolerance) && FloatComparer.AreEqual(g, (float)color.g, greenTolerance) && FloatComparer.AreEqual(b, (float)color.b, blueTolerance))) { colorCache[index1] = color; indexCache[index1] = index2; ++index1; } } if (index1 <= 0) { return; } Vector3 zero = Vector3.get_zero(); for (int index2 = 0; index2 < emitCount; ++index2) { int index3 = Random.Range(0, index1 - 1); int num3 = indexCache[index3]; float num4 = (float)num3 % x1 / pixelsPerUnit - num1; float num6 = (float)num3 / x1 / pixelsPerUnit - num2; ParticleSystem.EmitParams emitParams = (ParticleSystem.EmitParams)null; zero.x = (__Null)((double)num4 * (double)this.wMult + this.offsetXY.x); zero.y = (__Null)((double)num6 * (double)this.hMult - this.offsetXY.y); ((ParticleSystem.EmitParams) ref emitParams).set_position(zero); if (this.UsePixelSourceColor) { ((ParticleSystem.EmitParams) ref emitParams).set_startColor(Color32.op_Implicit(colorCache[index3])); } ((ParticleSystem.EmitParams) ref emitParams).set_startSize(((ParticleSystem.MinMaxCurve) ref startSize).get_constant()); this.particlesSystem.Emit(emitParams, 1); } } }
public virtual void CacheSprite(bool relativeToParent = false) { this.hasCachingEnded = false; this.particlesCacheCount = 0; Sprite sprite1 = this.imageRenderer.get_sprite(); if (!Object.op_Implicit((Object)sprite1)) { if (!this.verboseDebug) { return; } Debug.LogError((object)("Unable to cache. Sprite is null in game object " + ((Object)this).get_name())); } else { float r = (float)this.EmitFromColor.r; float g = (float)this.EmitFromColor.g; float b = (float)this.EmitFromColor.b; float pixelsPerUnit = sprite1.get_pixelsPerUnit(); if ((Object.op_Equality((Object)this.imageRenderer, (Object)null) || Object.op_Equality((Object)this.imageRenderer.get_sprite(), (Object)null)) && this.verboseDebug) { Debug.LogError((object)"Image UI reference missing"); } Rect rect1 = sprite1.get_rect(); float x1 = (float)(int)((Rect) ref rect1).get_size().x; Rect rect2 = sprite1.get_rect(); float y1 = (float)(int)((Rect) ref rect2).get_size().y; ParticleSystem.MinMaxCurve startSize = ((ParticleSystem.MainModule) ref this.mainModule).get_startSize(); this.particleStartSize = ((ParticleSystem.MinMaxCurve) ref startSize).get_constant(); float num1 = (float)sprite1.get_pivot().x / pixelsPerUnit; float num2 = (float)sprite1.get_pivot().y / pixelsPerUnit; Color[] colorArray; if (this.useSpritesSharingCache && Application.get_isPlaying()) { Sprite sprite2 = sprite1; Rect rect3 = sprite1.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = sprite1.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int blockWidth = (int)x1; int blockHeight = (int)y1; colorArray = SpritesDataPool.GetSpriteColors(sprite2, x2, y2, blockWidth, blockHeight); } else { Texture2D texture = sprite1.get_texture(); Rect rect3 = sprite1.get_rect(); int x2 = (int)((Rect) ref rect3).get_position().x; Rect rect4 = sprite1.get_rect(); int y2 = (int)((Rect) ref rect4).get_position().y; int num3 = (int)x1; int num4 = (int)y1; colorArray = texture.GetPixels(x2, y2, num3, num4); } float redTolerance = this.RedTolerance; float greenTolerance = this.GreenTolerance; float blueTolerance = this.BlueTolerance; float num5 = x1 * y1; List <Color> colorList = new List <Color>(); List <Vector3> vector3List = new List <Vector3>(); for (int index = 0; (double)index < (double)num5; ++index) { Color color = colorArray[index]; if (color.a > 0.0 && (!this.UseEmissionFromColor || FloatComparer.AreEqual(r, (float)color.r, redTolerance) && FloatComparer.AreEqual(g, (float)color.g, greenTolerance) && FloatComparer.AreEqual(b, (float)color.b, blueTolerance))) { float num3 = (float)index % x1 / pixelsPerUnit - num1; float num4 = (float)index / x1 / pixelsPerUnit - num2; Vector3 vector3; ((Vector3) ref vector3).\u002Ector(num3, num4, 0.0f); vector3List.Add(vector3); colorList.Add(color); ++this.particlesCacheCount; } } this.particleInitPositionsCache = vector3List.ToArray(); this.particleInitColorCache = colorList.ToArray(); if (this.particlesCacheCount <= 0) { if (!this.verboseDebug) { return; } Debug.LogWarning((object)"Caching particle emission went wrong. This is most probably because couldn't find wanted color in sprite"); } else { vector3List.Clear(); colorList.Clear(); GC.Collect(); this.hasCachingEnded = true; if (this.OnCacheEnded == null) { return; } this.OnCacheEnded(); } } }