This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/editors/gpencil/gpencil_undo.c

203 lines
4.7 KiB
C
Raw Normal View History

/*
* ***** 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 *****
*/
/** \file blender/editors/gpencil/gpencil_undo.c
* \ingroup edgpencil
*/
2014-12-26 20:00:52 +01: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"
#include "BKE_blender_undo.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_main.h"
#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
char name[BKE_UNDO_STR_MAX];
struct bGPdata *gpd;
} bGPundonode;
static ListBase undo_nodes = {NULL, NULL};
static bGPundonode *cur_node = NULL;
int ED_gpencil_session_active(void)
{
return (BLI_listbase_is_empty(&undo_nodes) == false);
}
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
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 */
//printf("\t\tGP - undo step\n");
if (cur_node->prev) {
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;
}
}
}
2012-05-08 18:29:02 +00:00
else if (step == -1) {
//printf("\t\tGP - redo step\n");
if (cur_node->next) {
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;
}
}
}
2014-12-27 12:09:29 +13:00
if (new_gpd) {
if (gpd_ptr) {
if (*gpd_ptr) {
2012-05-08 18:29:02 +00:00
bGPdata *gpd = *gpd_ptr;
bGPDlayer *gpl, *gpld;
2014-12-27 12:09:29 +13:00
BKE_gpencil_free_layers(&gpd->layers);
2014-12-27 12:09:29 +13:00
/* copy layers */
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) {
/* make a copy of source layer and its data */
gpld = BKE_gpencil_layer_duplicate(gpl);
BLI_addtail(&gpd->layers, gpld);
}
}
}
}
2014-12-27 12:09:29 +13:00
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
2014-12-27 12:09:29 +13:00
return OPERATOR_FINISHED;
}
void gpencil_undo_init(bGPdata *gpd)
{
gpencil_undo_push(gpd);
}
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);
}
void gpencil_undo_push(bGPdata *gpd)
{
bGPundonode *undo_node;
2014-12-27 12:09:29 +13:00
//printf("\t\tGP - undo push\n");
2014-12-27 12:09:29 +13:00
if (cur_node) {
/* 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
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
gpencil_undo_free_node(undo_node);
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;
}
}
2014-12-27 12:09:29 +13: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;
}
}
/* create new undo node */
2012-05-08 18:29:02 +00:00
undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node");
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
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
while (undo_node) {
gpencil_undo_free_node(undo_node);
2012-05-08 18:29:02 +00:00
undo_node = undo_node->next;
}
2014-12-27 12:09:29 +13:00
BLI_freelistN(&undo_nodes);
2014-12-27 12:09:29 +13:00
2012-05-08 18:29:02 +00:00
cur_node = NULL;
}