Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Tint multiple targets with single button

Discussion in 'UGUI & TextMesh Pro' started by mimminito, Nov 13, 2014.

  1. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Hi,

    How would I go about tinting multiple targets with a single click? For example if I have an Image (background) with a button component attached to it, and as a child of this image I have another image which displays an icon for the button. When I click on the button only the background will tint its color, not the icon.

    Is there a way I can achieve this effect? I know this is not NGUI, but for reference I could add multiple button components to a single GameObject in NGUI and change the targets to achieve the effect.

    Adam
     
  2. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Anyone got any suggestions on this? Still looking for an elegant solution
     
  3. holyjewsus

    holyjewsus

    Joined:
    Mar 7, 2011
    Posts:
    624
    I would just create a new type of button that inherits from button, and Override DoStateTransition, then you can find all images in the parent or something, and loop through each of them on the transition

    something like this

    Code (CSharp):
    1.     protected virtual IEnumerator TweenColorFromCurrent (Color ToColor, float duration)
    2.                 {
    3.                         for (float f = 0; f <= duration; f = f + Time.deltaTime) {
    4.  
    5.                                 obUI.ForEach(x=>x.material.color = Color.Lerp (x.material.color, ToColor, f));
    6.                                 yield return null;
    7.  
    8.                         }
    9.                         obUI.ForEach(x=>x.material.color = ToColor);
    10.                 }
    11.  
    12.  
    13.                 protected override void DoStateTransition (Selectable.SelectionState state, bool instant)
    14.                 {
    15.                     obUI = this.GetComponentsInChildren<Renderer>().ToList();
    16.                         Debug.Log ("inside state transition");
    17.  
    18.                         if (state == SelectionState.Pressed) {
    19.                                 StopAllCoroutines ();
    20.                                 StartCoroutine (TweenColorFromCurrent (this.colors.pressedColor, this.colors.fadeDuration));
    21.                         }
    22.          
    23.                         if (state == Selectable.SelectionState.Highlighted) {
    24.                                 Debug.Log ("state was highlight");
    25.                                 //StopAllCoroutines();
    26.                                 StartCoroutine (TweenColorFromCurrent (this.colors.highlightedColor, this.colors.fadeDuration));
    27.                         }
    28.                         if (state == Selectable.SelectionState.Normal) {
    29.                                 Debug.Log ("state was normal");
    30.                                 StopAllCoroutines ();
    31.                                 StartCoroutine (TweenColorFromCurrent (this.colors.normalColor, this.colors.fadeDuration));
    32.                         }
    33.            
    34.                 }
    35.         }
    36. }
     
    Augenpulver likes this.
  4. holyjewsus

    holyjewsus

    Joined:
    Mar 7, 2011
    Posts:
    624
  5. mimminito

    mimminito

    Joined:
    Feb 10, 2010
    Posts:
    780
    Thanks for the help! I did not know that the UI had gone open source already, I knew they was planning to but didnt see that post! Ill be checking it out for sure, thanks again!
     
  6. toomanydisplays

    toomanydisplays

    Joined:
    Jul 27, 2018
    Posts:
    2
    I know this is an old Post but since google directed me here, probably others will come here aswell.

    I found a simple solution the the scenario miminito describes.

    1. Create a Button and add your own button sprite as Source Image.
    2. Create another Button and use your background sprite (in my case a glowing outline) as Source Image for this one.
    3. Put the background as child of the first button

    Both Buttons will detect if the mouse is hovering over it or if they are clicked.
    Nonetheless when you are assigning your script to the "On Click ()" function:

    4. Put it on the last child in the hirachy

    I'm not exactly sure why it can't be on the parent, but somehow it then gets blocked by the child.
    Guess the last child is on top of the others, even if they all have the same coords.

    In case your button keeps highlighted after you clicked it:

    5. Put navigation on "None"
     
    Last edited: Aug 31, 2018
    Braza likes this.
  7. mauro_c8

    mauro_c8

    Joined:
    Oct 22, 2019
    Posts:
    1
    Based on @holyjewsus's answer and the source of UI's selectable I've came with a working solution.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. public class MultiImageButton : Button
    5. {
    6.     protected override void DoStateTransition(SelectionState state, bool instant)
    7.     {
    8.         var targetColor =
    9.             state == SelectionState.Disabled ? colors.disabledColor :
    10.             state == SelectionState.Highlighted ? colors.highlightedColor :
    11.             state == SelectionState.Normal ? colors.normalColor :
    12.             state == SelectionState.Pressed ? colors.pressedColor :
    13.             state == SelectionState.Selected ? colors.selectedColor : Color.white;
    14.  
    15.         foreach (var graphic in GetComponentsInChildren<Graphic>())
    16.         {
    17.             graphic.CrossFadeColor(targetColor, instant ? 0f : colors.fadeDuration, true, true);
    18.         }
    19.     }
    20. }
     
    NICK_HOM, maewionn, esbenrb and 7 others like this.
  8. cdauphin

    cdauphin

    Joined:
    Mar 16, 2018
    Posts:
    17
    Using
    Code (CSharp):
    1. [SerializeField] Graphic[] _sourceImages;
    works, you just have to activate the inspector debug view to access the field (top right of the inspector panel, click on the three dot and check debug). You also can create a custom editor for this class to handle it without having to switch from normal to debug mode.
     
    Last edited: Oct 12, 2020
    eraban likes this.
  9. dotsquid

    dotsquid

    Joined:
    Aug 11, 2016
    Posts:
    224
    There is an Animation transition type which allows to animate any objects for different states of the button (or any other control which supports transitions)
     
  10. the1whom0x

    the1whom0x

    Joined:
    Dec 14, 2015
    Posts:
    3
    For anyone still interested, I reworked it so it's a tad bit more user friendly inspector wise:

    This is the MultiImageButton.cs

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5. [RequireComponent(typeof(MultiImageTargetGraphics))]
    6. public class MultiImageButton : Button
    7. {
    8.     private Image[] targetImages;
    9.  
    10.     private MultiImageTargetGraphics targetGraphics;
    11.  
    12.     protected override void Start()
    13.     {
    14.         targetGraphics = GetComponent<MultiImageTargetGraphics>();
    15.  
    16.         targetImages = targetGraphics.GetTargetImages;
    17.  
    18.         base.Start();
    19.     }
    20.  
    21.     protected override void DoStateTransition(SelectionState state, bool instant)
    22.     {
    23.         if (!targetGraphics) return;
    24.  
    25.         var targetColor =
    26.             state == SelectionState.Disabled ? colors.disabledColor :
    27.             state == SelectionState.Highlighted ? colors.highlightedColor :
    28.             state == SelectionState.Normal ? colors.normalColor :
    29.             state == SelectionState.Pressed ? colors.pressedColor :
    30.             state == SelectionState.Selected ? colors.selectedColor : Color.white;
    31.  
    32.         foreach (var image in targetImages)
    33.             image.CrossFadeColor(targetColor, instant ? 0 : colors.fadeDuration, true, true);
    34.     }
    35. }
    Accompanied by MultiImageTargetGraphics
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5. public class MultiImageTargetGraphics : MonoBehaviour
    6. {
    7.     [SerializeField] private Image[] targetImages;
    8.  
    9.     public Image[] GetTargetImages => targetImages;
    10. }
    All you do is add MultiImageButton, replacing the standard button, and just add the target images on the MultiImageTargetGraphics that will be added with it. TargetGraphic of MultiImageButton is unused.
     
    CleverAI likes this.
  11. CleverAI

    CleverAI

    Joined:
    Jun 4, 2017
    Posts:
    32
    @the1whom0x
    I have rewritten your code a little bit, so that it works for all kinds of graphics and not only images.


    This is the MultiImageButton.cs

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5. [RequireComponent(typeof(MultiImageTargetGraphics))]
    6. public class MultiImageButton : Button
    7. {
    8.     private Graphic[] graphics;
    9.  
    10.     private MultiImageTargetGraphics targetGraphics;
    11.  
    12.     protected override void Start()
    13.     {
    14.         base.Start();
    15.     }
    16.  
    17.     protected override void DoStateTransition(SelectionState state, bool instant)
    18.     {
    19.         //get the graphics, if it could not get the graphics, return here
    20.         if (!GetGraphics())
    21.             return;
    22.  
    23.         var targetColor =
    24.             state == SelectionState.Disabled ? colors.disabledColor :
    25.             state == SelectionState.Highlighted ? colors.highlightedColor :
    26.             state == SelectionState.Normal ? colors.normalColor :
    27.             state == SelectionState.Pressed ? colors.pressedColor :
    28.             state == SelectionState.Selected ? colors.selectedColor : Color.white;
    29.  
    30.         foreach (var graphic in graphics)
    31.             graphic.CrossFadeColor(targetColor, instant ? 0 : colors.fadeDuration, true, true);
    32.     }
    33.  
    34.     private bool GetGraphics()
    35.     {
    36.         if(!targetGraphics) targetGraphics = GetComponent<MultiImageTargetGraphics>();
    37.         graphics = targetGraphics?.GetTargetGraphics;
    38.         return graphics != null && graphics.Length > 0;
    39.     }
    40. }
    41.  
    This is the MultiImageTargetGraphics.cs
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. public class MultiImageTargetGraphics : MonoBehaviour
    5. {
    6.     [SerializeField] private Graphic[] targetGraphics;
    7.  
    8.     public Graphic[] GetTargetGraphics => targetGraphics;
    9. }
    Also fixed a tiny error. Enjoy!
     
    Last edited: Apr 10, 2021
  12. AkamaruDesign

    AkamaruDesign

    Joined:
    Dec 17, 2016
    Posts:
    11
    It does not work with TMpro text, any fix/idea?
     
  13. dotsquid

    dotsquid

    Joined:
    Aug 11, 2016
    Posts:
    224
    It should if you are using TextMeshProUGUI which inherits UnityEngine.UI.Graphic
     
  14. UrbanNuke

    UrbanNuke

    Joined:
    Jun 11, 2019
    Posts:
    14
    Anybody knows how colors are being interpolated?
    Becuse I'm getting weird result, which doesn't match to setup colors (normal, highlighted etc)