- Improved tweening support
[yamf.git] / yamf / model / frame.cpp
blob82c2ab7b85a1f6d0bac0e8e28ed2265053faa2b0
1 /***************************************************************************
2 * Copyright (C) 2005 by David Cuadrado *
3 * krawek@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "frame.h"
22 #include "layer.h"
24 #include <dcore/debug.h>
26 #include <QGraphicsItem>
28 #include "object.h"
29 #include "scene.h"
30 #include "item/builder.h"
31 #include "model/command/manager.h"
32 #include "model/command/addobject.h"
33 #include "model/command/removeobject.h"
34 #include "model/command/lockframe.h"
35 #include "model/command/changeframevisibility.h"
36 #include "model/command/renameframe.h"
38 #include "model/library.h"
39 #include "model/object.h"
40 #include "model/objectgroup.h"
42 #include "item/group.h"
43 #include "item/tweener.h"
45 #define INVALID_Z -10000
48 namespace YAMF {
49 namespace Model {
51 struct Frame::Private
53 Private() : objectCount(0)
57 QString name;
58 bool isLocked;
59 bool isVisible;
60 GraphicObjects graphics;
61 int repeat;
63 int objectCount;
65 ObjectGroup *createObjectGroup(Frame *frame , QGraphicsItem *item)
67 ObjectGroup *oGroup = new ObjectGroup(frame);
68 if(Item::Group *group = static_cast<Item::Group * >(item))
70 foreach(QGraphicsItem *child, group->childs())
72 if(child->type() == Item::Group::Type)
74 ObjectGroup *ocGroup = createObjectGroup(frame, child);
75 oGroup->addToGroup(ocGroup);
78 else
80 Object *object = new Object(child, frame);
81 oGroup->addToGroup(object);
85 return oGroup;
88 void fixZValue( Object *object )
90 if( QGraphicsItem *item = object->item() )
92 if( item->zValue() == INVALID_Z )
94 double zMax = 0;
95 foreach(Object *graphic, graphics.values() )
97 if( zMax < graphic->item()->zValue() )
99 zMax = graphic->item()->zValue();
102 item->setZValue(zMax+0.1);
111 * @~spanish
112 * Constructor por defecto
114 Frame::Frame(Layer *parent, const QString& name ) : QObject(parent), d(new Private)
116 d->name = name;
117 d->isLocked = false;
118 d->isVisible = true;
119 d->repeat = 1;
123 * @~spanish
124 * Destructor
126 Frame::~Frame()
128 d->graphics.clear(true);
129 delete d;
133 * @~spanish
134 * Limpia el marco.
136 void Frame::clean()
138 d->graphics.clear(true);
142 * @~spanish
143 * Pone el nombre del frame
145 void Frame::setFrameName(const QString &name)
147 if(name != d->name)
149 Command::RenameFrame *cmd = new Command::RenameFrame(this, name, &d->name);
150 project()->commandManager()->addCommand(cmd);
155 * @~spanish
156 * Retorna el nombre del frame
158 QString Frame::frameName() const
160 return d->name;
164 * @~spanish
165 * Si isLocked es verdadero bloquea el frame, de lo contrario lo desbloquea.
167 void Frame::setLocked(bool isLocked)
169 if(isLocked != d->isLocked)
171 Command::LockFrame *command = new Command::LockFrame(this, isLocked, &d->isLocked);
172 project()->commandManager()->addCommand(command);
178 * @~spanish
179 * Returna verdadero cuando el frame esta bloqueado
181 bool Frame::isLocked() const
183 return d->isLocked;
187 * @~spanish
188 * Cambia la visibilidad del marco.
189 * Si @p isVisible es verdadero permite la visualización del marco de lo contrario lo oculta.
191 void Frame::setVisible(bool isVisible)
193 if(d->isVisible != isVisible)
195 Command::ChangeFrameVisibility *command = new Command::ChangeFrameVisibility(this, isVisible, &d->isVisible);
196 project()->commandManager()->addCommand(command);
201 * @~spanish
202 * Retorna verdadero si el marco es visible, de lo contrario retorna falso.
204 bool Frame::isVisible() const
206 return d->isVisible;
210 * @~spanish
211 * Añade un objeto grafico al marco.
213 void Frame::addObject(Object *object)
215 Command::Manager *commandManager = project()->commandManager();
217 object->setParent(this);
219 d->fixZValue(object);
221 if( object->objectName().isEmpty() )
223 object->setObjectName(tr("Object %1").arg(d->objectCount++));
226 Command::AddObject *command = new Command::AddObject(object, &d->graphics);
227 commandManager->addCommand(command);
231 * @~spanish
232 * Remueve el objeto grafico @p object del marco.
234 void Frame::removeObject(Object *object)
236 Command::RemoveObject *cmd = new Command::RemoveObject(object, &d->graphics, this);
237 project()->commandManager()->addCommand(cmd);
239 this->scene()->removeTweeningObject(object);
243 * @~spanish
244 * Remueve los objetos graficos @p objects del marco.
246 void Frame::removeObjects(const QList<Object *> &objects)
248 Command::RemoveObject *cmd = new Command::RemoveObject(objects, &d->graphics, this);
249 project()->commandManager()->addCommand(cmd);
251 foreach(Object *object, objects)
253 this->scene()->removeTweeningObject(object);
258 * @~spanish
259 * Remueve los objetos graficos que contiene el ítem @p item del marco.
261 void Frame::removeItem(QGraphicsItem *item)
263 int index = visualIndexOf(item);
264 if( index >= 0 )
266 removeObject(graphic(index));
271 * @~spanish
272 * Remueve los objetos graficos que contiene los ítems @p items del marco.
274 void Frame::removeItems(const QList<QGraphicsItem *> &items)
276 QList<Object *> objects;
277 foreach(QGraphicsItem *item, items)
279 int index = visualIndexOf(item);
280 if( index >= 0 )
282 objects << graphic(index);
286 if(!objects.isEmpty())
287 removeObjects(objects);
291 * @~spanish
292 * Añade el item grafico @p item al marco, retornando el objeto grafico que lo contiene.
294 Object *Frame::addItem(QGraphicsItem *item)
296 Object *object = new Object(item, this);
297 object->setObjectName(tr("Object %1").arg(d->objectCount++));
298 item->setZValue(INVALID_Z);
300 addObject(object);
302 return object;
306 * @~spanish
307 * Reemplaza el item que contien el objeto grafico de la posición @p logicalIndex por el ítem @p item..
309 void Frame::replaceItem(int logicalIndex, QGraphicsItem *item)
311 Object *toReplace = this->graphic(logicalIndex);
313 if ( toReplace )
315 toReplace->setItem( item );
320 * @~spanish
321 * Remueve el objeto grafico que esta en la posición @p logicalIndex del marco.
323 void Frame::removeObjectAt(int logicalIndex)
325 if ( !d->graphics.contains(logicalIndex) )
327 return;
330 Object *object = graphic(logicalIndex);
331 removeObject(object);
334 void Frame::detach(Model::Object *object)
336 d->graphics.remove(object);
338 QGraphicsItem *item = object->item();
340 if ( item )
342 QGraphicsScene *scene = item->scene();
344 if(scene)
346 scene->removeItem(item);
351 void Frame::attach(Model::Object *object)
353 d->graphics.add(object);
357 * @~spanish
358 * Cambia la posición del objeto grafico de la posición @p currentPosition a la posición @p newPosition.
360 bool Frame::moveItem(int currentPosition, int newPosition)
362 D_FUNCINFO << "current "<< currentPosition << " new " << newPosition;
363 if(currentPosition == newPosition || currentPosition < 0 || currentPosition >= d->graphics.count() || newPosition < 0 || newPosition >= d->graphics.count())
365 return false;
368 if(currentPosition < newPosition)
370 for( int i = currentPosition; i < newPosition; i++)
372 double tmp = d->graphics.visualValue(i)->item()->zValue();
373 d->graphics.visualValue(i)->item()->setZValue(d->graphics.visualValue(i+1)->item()->zValue());
374 d->graphics.visualValue(i+1)->item()->setZValue(tmp);
375 d->graphics.moveVisual(i, i+1);
378 else
380 for( int i = currentPosition; i > newPosition; i--)
382 double tmp = d->graphics.visualValue(i)->item()->zValue();
383 d->graphics.visualValue(i)->item()->setZValue(d->graphics.visualValue(i-1)->item()->zValue());
384 d->graphics.visualValue(i-1)->item()->setZValue(tmp);
385 d->graphics.moveVisual(i, i-1);
388 return true;
394 * @~spanish
395 * Retorna los objetos graficos que contiene el marco.
397 GraphicObjects Frame::graphics() const
399 return d->graphics;
403 * @~spanish
404 * Retorna el objeto grafico de la posición @p visualIndex.
406 Object *Frame::graphic(int visualIndex) const
408 if ( !d->graphics.containsVisual(visualIndex) )
410 D_FUNCINFO << " FATAL ERROR: index out of bound " << visualIndex << " FRAME: " << this->visualIndex() << " LAYER: " << layer()->visualIndex();
411 return 0;
414 return d->graphics.visualValue(visualIndex);
418 * @~spanish
419 * Retorna el objecto grafico que contiene al item @p item.
421 Object *Frame::graphic(QGraphicsItem *item) const
423 if( item )
425 foreach(Object *object, d->graphics.values() )
427 if (object->item() == item )
429 return object;
433 return 0;
436 Object *Frame::findGraphic(QGraphicsItem *item) const
438 Object *object = graphic(item);
440 if( ! object )
442 object = scene()->tweeningObject(item);
445 return object;
449 * @~spanish
450 * Retorna el item que contiene el objeto grafico de la posición @p visualIndex.
452 QGraphicsItem *Frame::item(int visualIndex) const
454 Object *object = graphic(visualIndex);
456 if ( object )
458 return object->item();
461 return 0;
465 * @~spanish
466 * Obtiene la posición visual del objeto grafico @p object.
468 int Frame::visualIndexOf(Object *object) const
470 return d->graphics.visualIndex(object);
474 * @~spanish
475 * Obtiene la posición logica del objeto grafico @p object.
477 int Frame::logicalIndexOf(Object *object) const
479 return d->graphics.logicalIndex(object);
483 * @~spanish
484 * Obtiene la posición visual del objeto grafico que contiene al ítem @p item.
486 int Frame::visualIndexOf(QGraphicsItem *item) const
488 foreach(Object *object, d->graphics.values() )
490 if (object->item() == item )
492 return d->graphics.visualIndex(object);
495 return -1;
499 * @~spanish
500 * Obtiene la posición logica del objeto grafico que contiene al ítem @p item.
502 int Frame::logicalIndexOf(QGraphicsItem *item) const
504 foreach(Object *object, d->graphics.values())
506 if (object->item() == item )
508 return d->graphics.logicalIndex(object);
512 return -1;
517 * @~spanish
518 * Retorna la posición visual del marco.
520 int Frame::visualIndex() const
522 return layer()->visualIndexOf(const_cast<Frame *>(this));
527 * @~spanish
528 * Retorna la posición logica del marco.
530 int Frame::logicalIndex() const
532 return layer()->logicalIndexOf(const_cast<Frame *>(this));
535 Model::Location Frame::location() const
537 Model::Location loc;
538 loc.setValue(Location::Scene, scene()->visualIndex() );
539 loc.setValue(Location::Layer, layer()->visualIndex() );
540 loc.setValue(Location::Frame, this->visualIndex() );
542 return loc;
547 * @~spanish
548 * Retorna la capa en la que esta el marco.
550 Layer *Frame::layer() const
552 return static_cast<Layer *>(parent());
556 * @~spanish
557 * Retorna la escena en la que esta el marco.
559 Scene *Frame::scene() const
561 return layer()->scene();
566 * @~spanish
567 * Retorna el proyecto en el que esta el marco.
569 Project *Frame::project() const
571 return layer()->project();
576 * @~spanish
577 * Construye el marco a partir del xml.
579 void Frame::fromXml(const QString &xml )
581 QDomDocument document;
583 if (! document.setContent(xml) )
585 return;
588 QDomElement root = document.documentElement();
590 setFrameName( root.attribute( "name", frameName() ) );
592 QDomNode n = root.firstChild();
594 while( !n.isNull() )
596 QDomElement e = n.toElement();
598 if(!e.isNull())
600 if( e.tagName() == "object" )
602 QString objectXml;
603 QTextStream ts(&objectXml);
604 ts << e;
606 Object *last = new Object(this);
607 last->fromXml(objectXml);
609 if( last->item() )
611 if(last->item()->type() == Item::Group::Type)
613 ObjectGroup *oGroup = d->createObjectGroup(this, last->item());
614 addObject(oGroup);
616 else
618 addObject(last);
621 else
623 delete last;
628 n = n.nextSibling();
633 * @~spanish
634 * Convierte el marco a un documento xml.
636 QDomElement Frame::toXml(QDomDocument &doc) const
638 QDomElement root = doc.createElement("frame");
639 root.setAttribute("name", d->name );
640 root.setAttribute("index", visualIndex());
641 int nclones = layer()->clones(const_cast<Frame *>(this));
642 if(nclones > 0)
644 root.setAttribute("clones", nclones);
647 doc.appendChild(root);
649 foreach(Object *object, d->graphics.visualValues() )
651 if( dynamic_cast<Common::AbstractSerializable *>(object->item()) )
653 root.appendChild( object->toXml(doc) );
657 return root;