2011-09-06 07:59:18 +00:00
|
|
|
/*
|
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*
|
|
|
|
|
* The Original Code is Copyright (C) 2011 Blender Foundation.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* Contributor(s): Blender Foundation,
|
|
|
|
|
* Sergey Sharybin
|
|
|
|
|
*
|
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
|
*/
|
|
|
|
|
|
2012-09-10 01:55:58 +00:00
|
|
|
/** \file blender/editors/gpencil/gpencil_undo.c
|
|
|
|
|
* \ingroup edgpencil
|
|
|
|
|
*/
|
|
|
|
|
|
2014-12-26 20:00:52 +01:00
|
|
|
|
2011-09-06 07:59:18 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "DNA_gpencil_types.h"
|
|
|
|
|
#include "DNA_listBase.h"
|
|
|
|
|
#include "DNA_windowmanager_types.h"
|
|
|
|
|
|
2013-04-05 17:56:54 +00:00
|
|
|
#include "BLI_listbase.h"
|
|
|
|
|
|
2016-04-24 22:42:41 +10:00
|
|
|
#include "BKE_blender_undo.h"
|
2011-09-06 07:59:18 +00:00
|
|
|
#include "BKE_context.h"
|
2016-07-10 14:52:00 +02:00
|
|
|
#include "BKE_global.h"
|
2011-09-06 07:59:18 +00:00
|
|
|
#include "BKE_gpencil.h"
|
2016-07-10 14:52:00 +02:00
|
|
|
#include "BKE_main.h"
|
2011-09-06 07:59:18 +00:00
|
|
|
|
|
|
|
|
#include "ED_gpencil.h"
|
|
|
|
|
|
|
|
|
|
#include "WM_api.h"
|
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
|
|
|
|
|
#include "gpencil_intern.h"
|
|
|
|
|
|
|
|
|
|
typedef struct bGPundonode {
|
|
|
|
|
struct bGPundonode *next, *prev;
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2012-09-10 01:55:58 +00:00
|
|
|
char name[BKE_UNDO_STR_MAX];
|
2011-09-06 07:59:18 +00:00
|
|
|
struct bGPdata *gpd;
|
|
|
|
|
} bGPundonode;
|
|
|
|
|
|
|
|
|
|
static ListBase undo_nodes = {NULL, NULL};
|
|
|
|
|
static bGPundonode *cur_node = NULL;
|
|
|
|
|
|
|
|
|
|
int ED_gpencil_session_active(void)
|
|
|
|
|
{
|
2014-02-08 06:07:10 +11:00
|
|
|
return (BLI_listbase_is_empty(&undo_nodes) == false);
|
2011-09-06 07:59:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ED_undo_gpencil_step(bContext *C, int step, const char *name)
|
|
|
|
|
{
|
2012-05-08 18:29:02 +00:00
|
|
|
bGPdata **gpd_ptr = NULL, *new_gpd = NULL;
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2014-06-14 02:54:17 +10:00
|
|
|
gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
if (step == 1) { /* undo */
|
2011-09-06 07:59:18 +00:00
|
|
|
//printf("\t\tGP - undo step\n");
|
2012-03-24 06:38:07 +00:00
|
|
|
if (cur_node->prev) {
|
2015-01-26 16:03:11 +01:00
|
|
|
if (!name || STREQ(cur_node->name, name)) {
|
2012-05-08 18:29:02 +00:00
|
|
|
cur_node = cur_node->prev;
|
|
|
|
|
new_gpd = cur_node->gpd;
|
2011-09-06 07:59:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-08 18:29:02 +00:00
|
|
|
else if (step == -1) {
|
2011-09-06 07:59:18 +00:00
|
|
|
//printf("\t\tGP - redo step\n");
|
2012-03-24 06:38:07 +00:00
|
|
|
if (cur_node->next) {
|
2015-01-26 16:03:11 +01:00
|
|
|
if (!name || STREQ(cur_node->name, name)) {
|
2012-05-08 18:29:02 +00:00
|
|
|
cur_node = cur_node->next;
|
|
|
|
|
new_gpd = cur_node->gpd;
|
2011-09-06 07:59:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (new_gpd) {
|
|
|
|
|
if (gpd_ptr) {
|
|
|
|
|
if (*gpd_ptr) {
|
2012-05-08 18:29:02 +00:00
|
|
|
bGPdata *gpd = *gpd_ptr;
|
2011-09-06 07:59:18 +00:00
|
|
|
bGPDlayer *gpl, *gpld;
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2016-08-04 15:03:18 +02:00
|
|
|
BKE_gpencil_free_layers(&gpd->layers);
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2011-09-06 07:59:18 +00:00
|
|
|
/* copy layers */
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&gpd->layers);
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
for (gpl = new_gpd->layers.first; gpl; gpl = gpl->next) {
|
2011-09-06 07:59:18 +00:00
|
|
|
/* make a copy of source layer and its data */
|
2016-08-04 15:03:18 +02:00
|
|
|
gpld = BKE_gpencil_layer_duplicate(gpl);
|
2011-09-06 07:59:18 +00:00
|
|
|
BLI_addtail(&gpd->layers, gpld);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2012-10-05 19:51:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2011-09-06 07:59:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void gpencil_undo_init(bGPdata *gpd)
|
|
|
|
|
{
|
|
|
|
|
gpencil_undo_push(gpd);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-07 23:53:13 +12:00
|
|
|
static void gpencil_undo_free_node(bGPundonode *undo_node)
|
|
|
|
|
{
|
|
|
|
|
/* HACK: animdata wasn't duplicated, so it shouldn't be freed here,
|
|
|
|
|
* or else the real copy will segfault when accessed
|
|
|
|
|
*/
|
|
|
|
|
undo_node->gpd->adt = NULL;
|
|
|
|
|
|
|
|
|
|
BKE_gpencil_free(undo_node->gpd, false);
|
|
|
|
|
MEM_freeN(undo_node->gpd);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-06 07:59:18 +00:00
|
|
|
void gpencil_undo_push(bGPdata *gpd)
|
|
|
|
|
{
|
|
|
|
|
bGPundonode *undo_node;
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2011-09-06 07:59:18 +00:00
|
|
|
//printf("\t\tGP - undo push\n");
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (cur_node) {
|
2011-09-06 07:59:18 +00:00
|
|
|
/* remove all un-done nodes from stack */
|
2012-05-08 18:29:02 +00:00
|
|
|
undo_node = cur_node->next;
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
while (undo_node) {
|
2012-05-08 18:29:02 +00:00
|
|
|
bGPundonode *next_node = undo_node->next;
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2016-09-07 23:53:13 +12:00
|
|
|
gpencil_undo_free_node(undo_node);
|
2011-09-06 07:59:18 +00:00
|
|
|
BLI_freelinkN(&undo_nodes, undo_node);
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
undo_node = next_node;
|
2011-09-06 07:59:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2016-09-08 01:09:55 +12:00
|
|
|
/* limit number of undo steps to the maximum undo steps
|
|
|
|
|
* - to prevent running out of memory during **really**
|
|
|
|
|
* long drawing sessions (triggering swapping)
|
|
|
|
|
*/
|
|
|
|
|
/* TODO: Undo-memory constraint is not respected yet, but can be added if we have any need for it */
|
|
|
|
|
if (U.undosteps && !BLI_listbase_is_empty(&undo_nodes)) {
|
|
|
|
|
/* remove anything older than n-steps before cur_node */
|
|
|
|
|
int steps = 0;
|
|
|
|
|
|
|
|
|
|
undo_node = (cur_node) ? cur_node : undo_nodes.last;
|
|
|
|
|
while (undo_node) {
|
|
|
|
|
bGPundonode *prev_node = undo_node->prev;
|
|
|
|
|
|
|
|
|
|
if (steps >= U.undosteps) {
|
|
|
|
|
gpencil_undo_free_node(undo_node);
|
|
|
|
|
BLI_freelinkN(&undo_nodes, undo_node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
steps++;
|
|
|
|
|
undo_node = prev_node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-06 07:59:18 +00:00
|
|
|
/* create new undo node */
|
2012-05-08 18:29:02 +00:00
|
|
|
undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node");
|
2016-08-04 15:03:18 +02:00
|
|
|
undo_node->gpd = BKE_gpencil_data_duplicate(G.main, gpd, true);
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
cur_node = undo_node;
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2011-09-06 07:59:18 +00:00
|
|
|
BLI_addtail(&undo_nodes, undo_node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void gpencil_undo_finish(void)
|
|
|
|
|
{
|
2012-05-08 18:29:02 +00:00
|
|
|
bGPundonode *undo_node = undo_nodes.first;
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
while (undo_node) {
|
2016-09-07 23:53:13 +12:00
|
|
|
gpencil_undo_free_node(undo_node);
|
2012-05-08 18:29:02 +00:00
|
|
|
undo_node = undo_node->next;
|
2011-09-06 07:59:18 +00:00
|
|
|
}
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2011-09-06 07:59:18 +00:00
|
|
|
BLI_freelistN(&undo_nodes);
|
2014-12-27 12:09:29 +13:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
cur_node = NULL;
|
2011-09-06 07:59:18 +00:00
|
|
|
}
|