/* * Copyright (c) 2005-2007 Hypertriton, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "animview.h" #include "icons.h" RG_Animview * RG_AnimviewNew(void *parent) { RG_Animview *av; av = Malloc(sizeof(RG_Animview)); AG_ObjectInit(av, &rgAnimviewClass); AG_ObjectAttach(parent, av); return (av); } static void Play(AG_Event *event) { RG_Animview *av = AG_PTR(1); AG_ScheduleTimeout(av, &av->timer, 1); AG_ButtonDisable(av->btns.play); AG_ButtonEnable(av->btns.pause); AG_ButtonEnable(av->btns.stop); } static void Pause(AG_Event *event) { RG_Animview *av = AG_PTR(1); AG_DelTimeout(av, &av->timer); AG_ButtonEnable(av->btns.play); AG_ButtonDisable(av->btns.pause); AG_ButtonDisable(av->btns.stop); } static void Stop(AG_Event *event) { RG_Animview *av = AG_PTR(1); AG_DelTimeout(av, &av->timer); av->frame = 0; AG_ButtonEnable(av->btns.play); AG_ButtonDisable(av->btns.pause); AG_ButtonDisable(av->btns.stop); } static Uint32 TickFrame(void *p, Uint32 ival, void *arg) { RG_Animview *av = p; if (av->anim->nframes == 0) return (0); if (++av->frame < av->anim->nframes) { RG_AnimFrame *fr = &av->anim->frames[av->frame]; return (fr->delay > 0 ? fr->delay*100/av->speed : 1); } else { RG_AnimFrame *fr = &av->anim->frames[0]; av->frame = 0; return (fr->delay > 0 ? fr->delay*100/av->speed: 1); } } static void CloseMenu(RG_Animview *av) { AG_MenuCollapse(av->menu, av->menu_item); AG_ObjectDestroy(av->menu); av->menu = NULL; av->menu_win = NULL; av->menu_item = NULL; } static void SetSpeed(AG_Event *event) { RG_Animview *av = AG_PTR(1); Uint factor = AG_INT(2); av->speed = factor; } static void OpenMenu(RG_Animview *av, int x, int y) { if (av->menu != NULL) CloseMenu(av); av->menu = AG_MenuNew(NULL, 0); av->menu_item = av->menu->itemSel = AG_MenuAddItem(av->menu, NULL); { AG_MenuItem *m_speed; AG_MenuAction(av->menu_item, _("Play"), rgIconPlay.s, Play, "%p", av); AG_MenuAction(av->menu_item, _("Pause"), rgIconPause.s, Pause, "%p", av); AG_MenuAction(av->menu_item, _("Stop"), rgIconStop.s, Stop, "%p", av); AG_MenuSeparator(av->menu_item); m_speed = AG_MenuAction(av->menu_item, _("Playback speed"), NULL, NULL, NULL); { AG_MenuAction(m_speed, _("Quadruple"), NULL, SetSpeed, "%p, %i", av, 400); AG_MenuAction(m_speed, _("Triple"), NULL, SetSpeed, "%p, %i", av, 300); AG_MenuAction(m_speed, _("Double"), NULL, SetSpeed, "%p, %i", av, 200); AG_MenuAction(m_speed, _("Normal"), NULL, SetSpeed, "%p, %i", av, 100); AG_MenuAction(m_speed, _("Half"), NULL, SetSpeed, "%p, %i", av, 50); AG_MenuAction(m_speed, _("One third"), NULL, SetSpeed, "%p, %i", av, 33); AG_MenuAction(m_speed, _("One quarter"), NULL, SetSpeed, "%p, %i", av, 25); } } av->menu_win = AG_MenuExpand(av->menu, av->menu_item, x, y); } static void MouseButtonDown(AG_Event *event) { RG_Animview *av = AG_SELF(); int button = AG_INT(1); int x = AG_INT(2); int y = AG_INT(3); if (button == SDL_BUTTON_RIGHT && y < WIDGET(av)->h - WIDGET(av->btns.play)->h) OpenMenu(av, WIDGET(av)->rView.x1 + x, WIDGET(av)->rView.y1 + y); } static void Init(void *obj) { RG_Animview *av = obj; WIDGET(av)->flags |= AG_WIDGET_EXPAND; av->pre_w = 64; av->pre_h = 64; av->ranim.x = 0; av->ranim.y = 0; av->ranim.w = av->pre_w; av->ranim.h = av->pre_h; av->speed = 100; av->menu = NULL; av->menu_win = NULL; AG_SetTimeout(&av->timer, TickFrame, av, 0); av->btns.play = AG_ButtonNew(av, 0, NULL); AG_ButtonSurfaceNODUP(av->btns.play, rgIconPlay.s); AG_SetEvent(av->btns.play, "button-pushed", Play, "%p", av); av->btns.pause = AG_ButtonNew(av, 0, NULL); AG_ButtonSurfaceNODUP(av->btns.pause, rgIconPause.s); AG_SetEvent(av->btns.pause, "button-pushed", Pause, "%p", av); av->btns.stop = AG_ButtonNew(av, 0, NULL); AG_ButtonSurfaceNODUP(av->btns.stop, rgIconStop.s); AG_SetEvent(av->btns.stop, "button-pushed", Stop, "%p", av); AG_ButtonEnable(av->btns.play); AG_ButtonDisable(av->btns.pause); AG_ButtonDisable(av->btns.stop); AG_SetEvent(av, "window-mousebuttondown", MouseButtonDown, NULL); } void RG_AnimviewSizeHint(RG_Animview *av, int w, int h) { av->pre_w = w; av->pre_h = h; } static void SizeRequest(void *p, AG_SizeReq *r) { RG_Animview *av = p; AG_SizeReq rPlay, rPause, rStop; AG_WidgetSizeReq(av->btns.play, &rPlay); AG_WidgetSizeReq(av->btns.pause, &rPause); AG_WidgetSizeReq(av->btns.stop, &rStop); r->w = MAX(av->pre_w, rPlay.w+rPause.w+rStop.w); r->h = av->pre_h + MAX3(rPlay.h, rPause.h, rStop.h); } static int SizeAllocate(void *p, const AG_SizeAlloc *a) { RG_Animview *av = p; AG_SizeReq rBtn; AG_SizeAlloc aBtn; int hBtn = 0; AG_WidgetSizeReq(av->btns.play, &rBtn); if (hBtn < rBtn.h) { hBtn = rBtn.h; } AG_WidgetSizeReq(av->btns.pause, &rBtn); if (hBtn < rBtn.h) { hBtn = rBtn.h; } AG_WidgetSizeReq(av->btns.stop, &rBtn); if (hBtn < rBtn.h) { hBtn = rBtn.h; } aBtn.x = 0; aBtn.y = a->h - hBtn; aBtn.w = a->w/3; aBtn.h = hBtn; AG_WidgetSizeAlloc(av->btns.play, &aBtn); aBtn.x += aBtn.w; AG_WidgetSizeAlloc(av->btns.pause, &aBtn); aBtn.x += aBtn.w; if ((aBtn.x + aBtn.w) < a->w) { aBtn.w++; } /* For rounding */ AG_WidgetSizeAlloc(av->btns.stop, &aBtn); av->ranim.x = a->w/2 - av->ranim.w/2; av->ranim.y = (a->h - hBtn)/2 - av->ranim.h/2; return (0); } static void Draw(void *p) { RG_Animview *av = p; RG_AnimFrame *fr; if (av->anim == NULL || av->anim->nframes < 1) { return; } fr = &av->anim->frames[av->frame]; if (fr->su != NULL) { AG_PushClipRect(av, AG_RECT(0, 0, WIDTH(av), HEIGHT(av))); AG_WidgetBlit(av, fr->su, av->ranim.x, av->ranim.y); AG_PopClipRect(); } } void RG_AnimviewSetAnimation(RG_Animview *av, RG_Anim *anim) { AG_DelTimeout(av, &av->timer); av->anim = anim; av->frame = 0; av->ranim.x = WIDGET(av)->w/2 - anim->w/2; av->ranim.y = (WIDGET(av)->h - WIDGET(av->btns.play)->h)/2 - anim->h/2; av->ranim.w = anim->w; av->ranim.h = anim->h; } AG_WidgetClass rgAnimviewClass = { { "Agar(Widget):RG(Animview)", sizeof(RG_Animview), { 0,0 }, Init, NULL, /* free */ NULL, /* destroy */ NULL, /* load */ NULL, /* save */ NULL /* edit */ }, Draw, SizeRequest, SizeAllocate };