1 /***************************************************************************
2 * Copyright (C) 2006 by David Cuadrado *
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. *
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. *
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 "photogram.h"
23 #include <QGraphicsItem>
24 #include <QGraphicsView>
25 #include <QStyleOptionGraphicsItem>
26 #include <QGraphicsSceneMouseEvent>
30 #include <model/scene.h>
31 #include <model/layer.h>
32 #include <model/frame.h>
33 #include <model/object.h>
35 #include "item/group.h"
38 #include <drawing/abstracttool.h>
39 #include <drawing/brushmanager.h>
40 #include <drawing/paintarea.h>
42 #include "item/tweener.h"
44 #include <dcore/debug.h>
46 #include <private/guide.h>
51 struct Photogram::Private
53 Private() : tool(0), scene(0), position(0), isDrawing(false) {}
61 QHash
<QGraphicsItem
*, double> opacityMap
;
67 BrushManager
*brushManager
;
70 QList
<YAMF::Drawing::Private::Guide
*> guides
;
75 * Construye un fotograma.
77 Photogram::Photogram(PaintArea
*parent
) : QGraphicsScene(parent
), d(new Private
)
79 d
->paintArea
= parent
;
81 setItemIndexMethod(QGraphicsScene::NoIndex
);
83 d
->onionSkin
.next
= 0;
84 d
->onionSkin
.previous
= 0;
87 setBackgroundBrush(Qt::gray
);
89 d
->brushManager
= new BrushManager(this);
96 Photogram::~Photogram()
103 foreach( QGraphicsView
*view
, this->views() )
108 foreach(QGraphicsItem
*item
, items())
119 * Asigna @p pos como la posición del fotograma.
121 void Photogram::setCurrent(int pos
)
128 * Dibuja el fotograma actual.
130 void Photogram::drawCurrentPhotogram()
132 drawPhotogram( d
->position
);
139 * Función reimplementada para proveer la funcionalidad de papel cebolla.
141 void Photogram::drawItems(QPainter
*painter
, int numItems
, QGraphicsItem
*items
[], const QStyleOptionGraphicsItem options
[], QWidget
*widget
)
143 for (int i
= 0; i
< numItems
; ++i
)
145 QGraphicsItem
*item
= items
[i
];
147 painter
->setMatrix(item
->sceneMatrix(), true);
149 if ( d
->onionSkin
.opacityMap
.contains(item
) )
151 painter
->setOpacity( d
->onionSkin
.opacityMap
[item
] );
154 item
->paint(painter
, &options
[i
], widget
);
163 * Dibuja el fotograma de la posición @p photogram.
165 void Photogram::drawPhotogram(int photogram
)
167 if ( photogram
< 0 || !d
->scene
) return;
171 d
->tool
->aboutToChangePhotogram(this);
177 foreach(Model::Layer
*layer
, d
->scene
->layers().values())
179 if ( layer
->isVisible() )
181 if( d
->onionSkin
.previous
> 0 )
183 double opacityFactor
= 0.5 / (double)qMin(layer
->frames().count(),d
->onionSkin
.previous
);
185 double opacity
= 0.6;
187 for(int frameIndex
= photogram
-1; frameIndex
> photogram
-d
->onionSkin
.previous
-1; frameIndex
-- )
189 Model::Frame
* frame
= layer
->frame(frameIndex
);
192 addFrame( frame
, opacity
);
194 opacity
-= opacityFactor
;
198 if ( d
->onionSkin
.next
> 0 )
200 double opacityFactor
= 0.5 / (double)qMin(layer
->frames().count(), d
->onionSkin
.next
);
201 double opacity
= 0.6;
203 for(int frameIndex
= photogram
+1; frameIndex
< photogram
+d
->onionSkin
.next
+1; frameIndex
++ )
205 Model::Frame
* frame
= layer
->frame(frameIndex
);
208 addFrame( frame
, opacity
);
210 opacity
-= opacityFactor
;
214 Model::Frame
*frame
= layer
->frame( photogram
);
226 foreach(Model::Object
*obj
, d
->scene
->alwaysVisible() )
228 if( obj
->frame()->isVisible() )
230 addItem(obj
->item());
234 foreach(Model::Object
*object
, d
->scene
->tweeningObjects())
236 if(object
->frame()->layer()->isVisible() )
238 int origin
= object
->frame()->visualIndex();
240 if( Item::Tweener
*tweener
= object
->tweener() )
242 if( origin
< photogram
&& photogram
<= origin
+tweener
->frames() )
245 int step
= photogram
- origin
;
247 tweener
->setStep(step
);
249 addGraphicObject(object
);
260 d
->tool
->photogramChanged(this);
266 * Añade el frame al fotograma,si este es visible.
268 void Photogram::addFrame(Model::Frame
*frame
, double opacity
)
270 if ( frame
->isVisible() )
272 foreach(Model::Object
*object
, frame
->graphics().values() )
274 addGraphicObject(object
, opacity
);
281 * Añade el objeto grafico @p object al fotograma, con un factor de opacidad @p opacity.
283 void Photogram::addGraphicObject(Model::Object
*object
, double opacity
)
285 QGraphicsItem
*item
= object
->item();
289 d
->onionSkin
.opacityMap
.insert(item
, opacity
);
291 if ( Item::Group
*group
= qgraphicsitem_cast
<Item::Group
*>(item
) )
293 group
->recoverChilds();
296 if( ! qgraphicsitem_cast
<Item::Group
*>(item
->parentItem()))
305 * Limpia el fotograma.
307 void Photogram::clean()
309 d
->onionSkin
.opacityMap
.clear();
311 foreach(QGraphicsItem
*item
, items() )
313 if ( item
->scene() == this )
319 foreach(YAMF::Drawing::Private::Guide
*guide
, d
->guides
)
327 * Asigna los papel cebolla hacia adelante del fotograma.
329 void Photogram::setNextOnionSkinCount(int n
)
331 d
->onionSkin
.next
= n
;
332 drawCurrentPhotogram();
337 * Asigna los papel cebolla hacia atras del fotograma.
339 void Photogram::setPreviousOnionSkinCount(int n
)
341 d
->onionSkin
.previous
= n
;
343 drawCurrentPhotogram();
348 * Asigna la scena actual del fotograma.
350 void Photogram::setCurrentScene(Model::Scene
*scene
)
352 qDeleteAll(d
->guides
);
358 drawCurrentPhotogram();
363 * Asigna la visibilidad del layer que esta en la posición @p layerIndex a @p visible.
365 void Photogram::setLayerVisible(int layerIndex
, bool visible
)
367 if( !d
->scene
) return;
369 if( Model::Layer
*layer
= d
->scene
->layer(layerIndex
) )
371 layer
->setVisible(visible
);
377 * Retorna la escena del fotograma.
379 Model::Scene
*Photogram::scene() const
386 * Asigna @p tool como la herramienta actual.
388 void Photogram::setTool(AbstractTool
*tool
)
390 drawCurrentPhotogram();
393 if(d
->tool
->type() == AbstractTool::Selection
)
395 foreach(YAMF::Drawing::Private::Guide
*guide
, d
->guides
)
397 guide
->setFlag( QGraphicsItem::ItemIsMovable
, false );
398 guide
->setEnabledSyncCursor(true);
401 d
->tool
->aboutToChangeTool();
405 if(tool
->type() == AbstractTool::Selection
)
407 foreach(YAMF::Drawing::Private::Guide
*guide
, d
->guides
)
409 guide
->setFlag( QGraphicsItem::ItemIsMovable
, true );
410 guide
->setEnabledSyncCursor(false);
419 * Retorna la herramienta actual.
421 AbstractTool
*Photogram::currentTool() const
429 * Función reimplementada para informar a la herramienta actual del evento de presionado de un boton del mouse.
431 void Photogram::mousePressEvent(QGraphicsSceneMouseEvent
*event
)
433 QGraphicsScene::mousePressEvent(event
);
435 d
->isDrawing
= false;
437 if( event
->buttons() == Qt::LeftButton
&& (event
->modifiers () == (Qt::ShiftModifier
| Qt::ControlModifier
)))
442 // if( d->tool->type() == AbstractTool::Brush && event->isAccepted() ) return;
444 if( d
->position
> -1 )
446 if ( event
->buttons() == Qt::LeftButton
)
449 d
->tool
->press(event
);
457 * Función reimplementada para informar a la herramienta actual del evento de movimiento del mouse.
459 void Photogram::mouseMoveEvent(QGraphicsSceneMouseEvent
*event
)
461 QGraphicsScene::mouseMoveEvent(event
);
466 * Función que informa a la herramienta actual del movimiento del mouse.
468 void Photogram::mouseMoved(QGraphicsSceneMouseEvent
*event
)
470 // d->inputInformation->updateFromMouseEvent( event );
472 if (d
->tool
/*&& d->isDrawing*/ )
474 d
->tool
->move(event
);
480 * Función reimplementada para informar a la herramienta actual del evento de liberación de un boton del mouse.
482 void Photogram::mouseReleaseEvent(QGraphicsSceneMouseEvent
*event
)
484 QGraphicsScene::mouseReleaseEvent(event
);
485 mouseReleased(event
);
490 * Función que informa a la herramienta actual de liberación de un boton del mouse.
492 void Photogram::mouseReleased(QGraphicsSceneMouseEvent
*event
)
494 // d->inputInformation->updateFromMouseEvent( event );
496 if ( d
->tool
&& d
->isDrawing
)
498 d
->tool
->release(event
);
499 // drawCurrentPhotogram(); FIXME esto borra los nodos
502 d
->isDrawing
= false;
507 * Función reimplementada para informar a la herramienta actual del evento de doble click.
509 void Photogram::mouseDoubleClickEvent(QGraphicsSceneMouseEvent
*event
)
511 QGraphicsScene::mouseDoubleClickEvent(event
);
513 // d->inputInformation->updateFromMouseEvent( event );
517 d
->tool
->doubleClick( event
);
523 * Función reimplementada para informar a la herramienta actual del evento de preción de una tecla.
525 void Photogram::keyPressEvent(QKeyEvent
*event
)
529 d
->tool
->keyPressEvent(event
);
531 if ( event
->isAccepted() )
537 QGraphicsScene::keyPressEvent(event
);
543 * Función reimplementada para la creación de lineas guias.
545 void Photogram::dragEnterEvent ( QGraphicsSceneDragDropEvent
* event
)
547 if (event
->mimeData()->hasFormat("yamf-ruler"))
549 event
->acceptProposedAction();
550 YAMF::Drawing::Private::Guide
*guide
= 0;
551 if(event
->mimeData()->data("yamf-ruler") == "verticalLine")
553 guide
= new YAMF::Drawing::Private::Guide(Qt::Vertical
, this);
554 guide
->setPos(event
->scenePos());
558 guide
= new YAMF::Drawing::Private::Guide(Qt::Horizontal
, this);
559 guide
->setPos(event
->scenePos());
571 * Función reimplementada para la creación de lineas guias.
573 void Photogram::dragLeaveEvent ( QGraphicsSceneDragDropEvent
* event
)
575 if (event
->mimeData()->hasFormat("yamf-ruler"))
577 removeItem(d
->guides
.last());
578 delete d
->guides
.takeLast();
584 * Función reimplementada para la creación de lineas guias.
586 void Photogram::dragMoveEvent ( QGraphicsSceneDragDropEvent
* event
)
588 if (event
->mimeData()->hasFormat("yamf-ruler"))
590 if(!d
->guides
.isEmpty())
592 d
->guides
.last()->setPos(event
->scenePos());
599 * Función reimplementada para la creación de lineas guias.
601 void Photogram::dropEvent ( QGraphicsSceneDragDropEvent
* event
)
606 if(d
->tool
->type() == AbstractTool::Selection
)
608 d
->guides
.last()->setEnabledSyncCursor(false);
609 d
->guides
.last()->setFlag( QGraphicsItem::ItemIsMovable
, true );
615 bool Photogram::event(QEvent
*e
)
617 return QGraphicsScene::event(e
);
622 * Retorna verdadero si se esta dibujando.
624 bool Photogram::isDrawing() const
632 * Retorna el manejador de brochas del photograma.
634 BrushManager
*Photogram::brushManager() const
636 return d
->brushManager
;
641 * Evita la selección de elementos que estan en el papel cebolla.
643 void Photogram::aboutToMousePress()
645 QHash
<QGraphicsItem
*, double>::iterator it
= d
->onionSkin
.opacityMap
.begin();
647 while(it
!= d
->onionSkin
.opacityMap
.end() )
649 if( it
.value() != 1.0 )
651 it
.key()->setAcceptedMouseButtons(Qt::NoButton
);
652 it
.key()->setFlag(QGraphicsItem::ItemIsSelectable
, false);
656 it
.key()->setAcceptedMouseButtons( Qt::LeftButton
| Qt::RightButton
| Qt::MidButton
| Qt::XButton1
| Qt::XButton2
);