Animating text?

edited April 2012 in Help request
Just a few days into using Orx but so far everything's been a joy!

Well, almost everything... I'm prototyping a menu where I have text labels (an object with a graphic with a text) and I'd like it to change color when I hover over it with the mouse cursor. I followed a tutorial where using animations I toggle between an active/inactive image and that works fine, but when I have two graphics that instead of images have text like this it just doesn't change colour:

[OptionActive]
Text = OptionText
Color = (0, 0, 0)

[OptionInactive]
Text = OptionText
Color = (0, 0, 255)

I've also tried setting the colour programmatically with orxObject_SetColor but that makes the text disappear (!)

Just wanted to ask if there's a best practice for this type of thing - I've not spent too much time debugging it yet, thought I might try asking here first in case I'm just missing something completely obvious - which wouldn't surprise me :-P

Comments

  • edited April 2012
    Are you setting the alpha value with the orxObject_SetColor call? It sounds like you might be setting alpha to 0 or something.

    My first (off the top of my head) suggestion is to have two FX that operate on the color: One for on hover and one for off hover. On mouse over, remove the off hover FX (to ensure it's not still active, or they'll cancel each other out or cause other unintended behavior) and add the on hover FX. Do the opposite for when the mouse leaves the object.

    Using FX can also enable you to do things like fade the color, and affect a lot more than just the color (4 FX can be defined on one object, after all). It's probably the most flexible way to achieve what you want.
  • edited April 2012
    Hey boxjar, glad you're enjoying it so far! :)

    As sonicbhoc mentioned, don't forget about the alpha when setting a color programmatically and also that orxCOLOR should have normalized components (0 - 1, not 0 - 255) when applied.

    I'd also go with his FX solution, however I simply wanted to precise that if you're using relative FXs instead of absolute ones, you shouldn't need to have to remove the former FX manually. Something like:
    In config:
    
    [OnHoverFX]
    SlotList = OnHoverSlot
    
    [OnHoverSlot]
    Type = color
    Curve = smooth
    Absolute = false
    StartTime = 0
    EndTime = 0.2 ; Or whichever duration you'd like
    StartValue = (0, 0, 0) ; Starting with current value, whichever it is
    EndValue = (0, 0, 255) ; Adding 255 to the blue channel, if we start with black we'll get bright blue
    
    [OffHoverFX]
    SlotList = OffHoverSlot
    
    [OffHoverSlot@OnHoverSlot]
    EndValue = (0, 0, -255) ; This time we assume we start with blue and that we'll remove 255 from this channel
    
    In code:
    
    void OnHover(orxOBJECT *_pstObject)
    {
      orxObject_AddFX(_pstObject, "OnHoverFX");
    }
    
    void OffHover(orxOBJECT *_pstObject)
    {
      orxObject_AddFX(_pstObject, "OffHoverFX");
    }
    

    If you'd rather do transition from less "pure" colors, you can do them in other color spaces (like hsl or hsv) by using Type = hsl or Type = hsv instead of Type = color, and using normalized values. Note that those are only available in the SVN version, not the 1.3rc0. :)
  • edited April 2012
    Cool, thanks very much indeed for your detailed answers! I'll try something along those lines later today and let you know how it goes.
  • edited April 2012
    So I tried doing this using FX and have it working (and with the nice fading in/out effect as a bonus) - it looks really nice, and the code+config is very neat! Thanks again for your replies, it really helped me out and I now see why FX will be very useful.

    One thing I ought to mention though: I couldn't get it to work using a relative colour value when fading out. Trying different RGB EndValues it seems any negative number is ignored...

    It isn't important to me, just thought I'd let you know. I instead changed it to an absolute effect which works perfectly for my purposes:


    In config:

    [OnHoverFX]
    SlotList = OnHoverSlot

    [OnHoverSlot]
    Type = color
    Curve = smooth
    Absolute = true
    StartTime = 0
    EndTime = 0.2 ; Or whichever duration you'd like
    StartValue = (0, 0, 0) ; Starting with current value, whichever it is
    EndValue = (0, 0, 255) ; Go to blue

    [OffHoverFX]
    SlotList = OffHoverSlot

    [OffHoverSlot@OnHoverSlot]
    EndValue = (0, 0, 0) ; Go back to black

    In code:

    void OnHover(orxOBJECT *_pstObject)
    {
    orxObject_AddFX[strike]FromConfig[/strike](_pstObject, "OnHoverFX");
    }

    void OffHover(orxOBJECT *_pstObject)
    {
    orxObject_AddFX[strike]FromConfig[/strike](_pstObject, "OffHoverFX");
    }
  • edited April 2012
    Woops, thanks for the channel/function name corrections, that's probably why I shouldn't be posting code (and even less writing new features) at 4:00AM, especially after a 2h long night. ^^

    I'll check why the negative value isn't working correctly. Maybe I missed something obvious myself and will give it a try tomorrow after some rest! :)

    Also, in your case, you have a fade only with OnHoverFX as both values now are absolute (0, 0, 0) for OffHoverFX. Here's to fix it:
    [OffHoverSlot@OnHoverSlot]
    StartValue = (0, 0, 255)
    EndValue = (0, 0, 0)
    
  • edited April 2012
    Hi,

    I think there's a problem in your absolute FX.

    As I understand in you code, in the "On" effect, you're going from black to blue.

    But, Because you did't override "StartValue" in your "Off" effect, the start value in the "Off" is black (because the FX is absolute), and the end value is black too (you've override this one and set it to 0).

    So, I think you're Off effect doesn't work (black => black).

    No, when you want to add an FX to cancel another one, I really suggest you to use relative FX. It doesn't work with absolute when the 2 Fx are mixed in the same time (if you run "On" and "Off" very quickly).

    To use a relative color FX, you have to thing about "what's the initial color of my object?".

    If the object is initialy black, then to go to blue, it's like that :
    [On]
    StartValue = (0,0,0)
    EndValue = (0,0,255) <= here, you add some blue
    
    And to go back to black:
    [Off]
    StartValue = (0,0,0)
    EndValue = (0,0,-255) <= remove the blue and return to black
    
    Now, if your object is initially white, and you want to go to blue:
    [On]
    StartValue = (0,0,0)
    EndValue = (-255,-255,0) ; <= remove all color from white, except blue channel
    
    And to go back to white:
    [Off]
    StartValue = (0,0,0)
    EndValue = (255,255,0) ; <= restore all removed colors
    

    I hope there's no mistake I what I said here ^^

    Hope this help !
  • edited April 2012
    I should know myself better: so I just tried locally and it worked just fine for me.

    Here's what I tried:
    [Ball]
    Alpha   = 1.0
    Color   = (0, 0, 0)
    FXList  = Fade
    
    [Fade]
    SlotList    = in # out
    KeepInCache = true
    
    [in]
    Type = color
    Curve = smooth
    StartTime = 0
    EndTime = 2
    StartValue = (0, 0, 0)
    EndValue = (0, 0, 255)
    Absolute = false
    
    [out@in]
    StartTime = 3
    EndTime = 5
    EndValue = (0, 0, -255)
    

    And I got nice slowly glowing blue objects. Could it have been a typo in your test?

    EDIT: Didn't see that faistoiplaisir was quicker than me and posted in the meantime, sorry for the redundancy! :)
  • edited April 2012
    Ah yes, sorry that's absolutely right - I forgot to copy the StartValue line in my OffHover FX.

    It's strange that it's working for you... well not strange exactly, I'd be more surprised if it was working for me but not you :-) Let me dig into this some more and see if I can find out why using the relative method isn't working for me.
  • edited April 2012
    Mystery solved, I have the relative method working now so that's fantastic! Thanks again for all your help.

    Essentially, I was being stupid on the code side. There was a bug that meant that I didn't just apply the HoverOn FX once when the cursor entered the object, but repeatedly while it was hovering over it. When I then wanted to apply the HoverOff FX there was no free slot for that FX (which I did spot a message for in the logs when I started digging through them).

    Not entirely sure why I had the absolute version working with the same bug in the code, but who cares about that now. :cheer:
  • edited April 2012
    Oh great, that's a bug less to investigate! ;)

    I have a theory why it'd work for absolute and not for relative.
    Even if you spam On FXs, at some point there's bound to get a Off FXs that will be triggered, and as the values are absolute it'll set everything straight. Whereas if you have 10 On relative FXs that have been executed, you'll need 10 Off relative FXs to counter that effect.

    Color values actually go out of bound to allow accurate relative effects. Internally all channel values are normalized, after 10 On FXs, your blue value will be 10.0, and if only 1 Off FX is executed, it'll go down to 9.0. Which, when rendered, will be clamped at 1.0, ie. still bright blue.
  • edited April 2012
    Ah ok, I see, that does make sense.
  • edited April 2012
    Sort of a related question: hypothetically, should the following work? I have a structure like this:
    [Container]
    ChildList = Child1 # Child2
    FXList = FadeToTransparentFX
    
    [Child1]
    Alpha = $Container
    Graphic = ...
    
    [Child2]
    Alpha = $Container
    Graphic = ...
    
    [FadeToTransparentFX]
    SlotList = FadeToTransparentFXSlot
    
    [FadeToTransparentFXSlot]
    Type = alpha
    Curve = smooth
    Absolute = true
    StartTime = 0
    EndTime = 1
    StartValue = 1
    EndValue = 0
    

    I would expect this to make Child1 and Child2 go from opaque to transparent when they're created - is that right? Or is there some other way to do this that would be better?

    Reason I'm asking is I'm not getting it to work at the moment, but there could definitely be another problem in my code - just wanted to check that I'm not going about this the wrong way...
  • edited April 2012
    Hi !

    There's some errors in your code.

    First, as I know, you can't do that :
    [Child1]
    Alpha = $Container
    
    I think you want to initialize the alpha child from its parent right ? In that case, it should be "@ instead of $" :
    [Child1]
    Alpha = @Container
    

    Be carefull, ini file are used to initialise only the object. When the Alpha change (at runtime) in the parent, the Child's Alpha remain unchanged.

    Second, FX applied to an object are no't applied to it's childs. In a lot of case, you don't want that (for example, an fx position, you don't want child to be moved when you move it's parent with a FX position).

    So, If you want to apply this fx to child at creation, do like that :
    [Container]
    ChildList = Child1 # Child2
    [Child1]
    Alpha = @Container
    FXList = FadeToTransparentFX
    Graphic = ...
    [Child2@Child1] ; With that, child 2 will have the same parameters as Child1
    Graphic = ...
    

    The last problem I think is the curve for your fx, "smooth" doesn't exist I think. You can use "sine" instead.
    [FadeToTransparentFXSlot]
    Type = alpha
    Curve = sine
    Absolute = true
    StartTime = 0
    EndTime = 1
    Period = 2 ; If you omit that (because the curve type is sine), your object will do 1 => 0 => 1 for it's alpha. Using the period, you can have 1 => 0 for the alpha.
    StartValue = 1
    EndValue = 0
    


    Hope that helps !!
  • edited April 2012
    "smooth" does exist, as does "smoother" if you are using recent code from subversion.
    Also, if you do Alpha = @Container and container has no alpha value, you're not doing much of anything. You don't need that line at all, since Alpha defaults to 1 and you are just going to immediately change it with an FX anyway.
  • edited April 2012
    Ok for the smooth properties, I didn't know them !

    But before my answer, I have checked the tutorial/bin/CreationTemplate.ini and apparently it's not updated in svn so ;)
  • edited April 2012
    Ah yes, the $ should have been a @ - typo in the post, have an @ in my ini file. D'oh!

    I guess I half-expected a reference like that to update in runtime, just as when using inheritance:

    http://orx-project.org/wiki/en/orx/config/syntax
    When using inheritance, when the parent key's value change, even at runtime, the child value will also be changed.

    But I can understand why it would be different with proper inheritance.

    Problem is, I want to be able to apply the FX as the result of an event as well, but I guess I can just iterate through the children in code and set the FX on each of them. Just wanted to check so I don't miss out on any of the Orx automation goodness I keep finding. :-)

    The CreationTemplate.ini I've been using as a reference is the one in trunk/code/bin, that seems to be up to date.
  • edited April 2012
    And so does the one in tutorial/bin! ;)
    Curve = linear|triangle|square|sine|smooth|smoother;
    

    As for the inheritance it's only valid for config data but doesn't translate to anything that has been created out of those data. :)
    config:
    [Parent]
    
    [Child]
    Value = @Parent
    
    code:
    
    orxConfig_PushSection("Parent");
    orxConfig_SetU32("Value", 5);
    orxConfig_PopSection();
    orxConfig_PushSection("Child");
    orxLOG("Value = %ld", orxConfig_GetU32("Value"));
    orxConfig_PopSection()
    

    This will print Value = 5, even if the Value entry wasn't defined in the Parent section at first.

    And for object->children automation, you'll have to write it manually I'm afraid. Or use Scroll where I wrapped those to optionally propagate to children. ;)
  • edited April 2012
    Think I'm starting to find my way around the API now - thanks for all the help!

    Don't be surprised if I'm back later today with another question though. ;-)
  • edited April 2012
    Great! There's a bunch of non-obvious things to discover there, the config system, of course, but also localization, inputs, profiler or memory banks are worth a glance, for example. ;)

    Don't hesitate with questions, hopefully it'll be useful not only to you but also to other people that might come with the same ones later on. :)
Sign In or Register to comment.