/**********************************************************************
 *<
	FILE: edmrest.cpp

	DESCRIPTION:  Edit Mesh OSM	Restore objects

	CREATED BY: Rolf Berteig

	HISTORY: created 1 September, 1995

 *>	Copyright (c) 1994, All Rights Reserved.
 **********************************************************************/
#include "mods.h"
#include "editmesh.h"

VertexEditRestore::VertexEditRestore(EditMeshData* md, EditMeshMod* mod)
	{	
	meshData  = md;
	this->mod = mod;
	deltas = md->vdelta;	
	t = mod->iObjParams->GetTime();
	Mesh *mesh = meshData->TempData(mod)->GetMesh(t);
	verts.SetCount(mesh->getNumVerts());
	for ( int i = 0; i < mesh->getNumVerts(); i++ ) {
		verts[i] = mesh->verts[i];
		}
	}

void VertexEditRestore::Restore(int isUndo)
	{
	// So we can redo...	
	rdeltas = meshData->vdelta;		
	meshData->vdelta = deltas;		
	
	if (meshData->tempData && meshData->TempData(mod)->MeshCached(t)) {
		Mesh *mesh = meshData->TempData(mod)->GetMesh(t);
		mesh->setNumVerts(verts.Count());
		for (int i = 0; i < verts.Count(); i++) {
			mesh->verts[i] = verts[i];
			}
		mesh->vertHide = deltas.hide;
		meshData->TempData(mod)->Invalidate(PART_GEOM);
	} else 
	if (meshData->tempData) {
		meshData->TempData(mod)->Invalidate(PART_GEOM,FALSE);
		}
	if (isUndo) mod->NotifyDependents(FOREVER, PART_GEOM, REFMSG_CHANGE);	
	}

void VertexEditRestore::Redo()
	{
	deltas = meshData->vdelta;
	meshData->vdelta = rdeltas;		
 	rdeltas.SetSize(0);
	
	if (meshData->tempData) {
		meshData->TempData(mod)->Invalidate(PART_GEOM,FALSE);
		}
	mod->NotifyDependents(FOREVER, PART_GEOM, REFMSG_CHANGE);
	}

/*-------------------------------------------------------------------*/

TopoEditRestore::TopoEditRestore(EditMeshData* md, EditMeshMod* mod)
		: VertexEditRestore(md,mod)
	{	
	tdelta = md->tdelta;
	vsel   = md->vsel;
	fsel   = md->fsel;
	esel   = md->esel;

	Mesh *mesh = meshData->TempData(mod)->GetMesh(t);	
	faces.SetCount(mesh->getNumFaces());
	for (int i = 0; i<mesh->getNumFaces(); i++) {
		faces[i] = mesh->faces[i];
		}
	}

void TopoEditRestore::Restore(int isUndo)
	{
	if (isUndo && rvsel.GetSize()!=meshData->vsel.GetSize()) {
		rtdelta = meshData->tdelta;
		rvsel   = meshData->vsel;
		rfsel   = meshData->fsel;
		resel   = meshData->esel;
		}
	meshData->tdelta = tdelta;
	meshData->vsel   = vsel;
	meshData->fsel   = fsel;
	meshData->esel   = esel;
		
	// RB 3-21-96: Instead of undoing the cache, invalidate it
	if (0/*meshData->tempData && meshData->TempData(mod)->MeshCached(t)*/) {
		Mesh *mesh = meshData->TempData(mod)->GetMesh(t);
		mesh->setNumFaces(faces.Count());
		for (int i = 0; i < faces.Count(); i++) {
			mesh->faces[i] = faces[i];
			}
		mesh->faceSel = fsel;
		mesh->edgeSel = esel;
		meshData->TempData(mod)->Invalidate(PART_TOPO);
	} else 
	if (meshData->tempData) {
		meshData->TempData(mod)->Invalidate(PART_TOPO,FALSE);
		}
	
	VertexEditRestore::Restore(isUndo);	
	}

void TopoEditRestore::Redo()
	{	
	meshData->tdelta = rtdelta; 	
	meshData->vsel   = rvsel;
	meshData->fsel   = rfsel;
	meshData->esel   = resel;

	if (meshData->tempData) {
		meshData->TempData(mod)->Invalidate(PART_TOPO,FALSE);
		}
	
	VertexEditRestore::Redo();
	}

/*-------------------------------------------------------------------*/

VertexSelRestore::VertexSelRestore(EditMeshData* md, EditMeshMod* mod)
	{
	sel = md->vsel;
	meshData = md;
	this->mod = mod;
	t = mod->iObjParams->GetTime();
	}

void VertexSelRestore::Restore(int isUndo)
	{
	rsel = meshData->vsel;
	meshData->vsel = sel;
	if ( meshData->tempData && meshData->TempData(mod)->MeshCached(t) ) {
		Mesh *mesh = meshData->TempData(mod)->GetMesh(t);
		mesh->vertSel = sel;
		meshData->TempData(mod)->Invalidate(PART_SELECT);
		}
	mod->NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
	}

void VertexSelRestore::Redo()
	{
	meshData->vsel = rsel;
	if ( meshData->tempData && meshData->TempData(mod)->MeshCached(t) ) {
		Mesh *mesh = meshData->TempData(mod)->GetMesh(t);
		mesh->vertSel = rsel;
		meshData->TempData(mod)->Invalidate(PART_SELECT);
		}
	mod->NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
	}

/*-------------------------------------------------------------------*/

VertexHideRestore::VertexHideRestore(EditMeshData* md, EditMeshMod* mod)
	{
	hide = md->vdelta.hide;
	meshData = md;
	this->mod = mod;
	t = mod->iObjParams->GetTime();
	}

void VertexHideRestore::Restore(int isUndo)
	{
	rhide = meshData->vdelta.hide;
	meshData->vdelta.hide = hide;
	if (meshData->tempData && meshData->TempData(mod)->MeshCached(t)) {
		Mesh *mesh = meshData->TempData(mod)->GetMesh(t);
		mesh->vertHide = hide;		
		}
	mod->NotifyDependents(FOREVER, PART_TOPO, REFMSG_CHANGE);
	}

void VertexHideRestore::Redo()
	{
	meshData->vdelta.hide = rhide;
	if (meshData->tempData && meshData->TempData(mod)->MeshCached(t)) {
		Mesh *mesh = meshData->TempData(mod)->GetMesh(t);
		mesh->vertHide = rhide;		
		}
	mod->NotifyDependents(FOREVER, PART_TOPO, REFMSG_CHANGE);
	}

/*-------------------------------------------------------------------*/

FaceSelRestore::FaceSelRestore(EditMeshData* md, EditMeshMod* mod)
	{
	sel = md->fsel;
	meshData = md;
	this->mod = mod;
	t = mod->iObjParams->GetTime();
	}

void FaceSelRestore::Restore(int isUndo)
	{
	rsel = meshData->fsel;
	meshData->fsel = sel;
	if ( meshData->tempData && meshData->TempData(mod)->MeshCached(t) ) {
		Mesh *mesh = meshData->TempData(mod)->GetMesh(t);
		mesh->faceSel = sel;
		meshData->TempData(mod)->Invalidate(PART_SELECT);
		}
	mod->NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
	}

void FaceSelRestore::Redo()
	{
	meshData->fsel = rsel;
	if ( meshData->tempData && meshData->TempData(mod)->MeshCached(t) ) {
		Mesh *mesh = meshData->TempData(mod)->GetMesh(t);
		mesh->faceSel = rsel;
		meshData->TempData(mod)->Invalidate(PART_SELECT);
		}
	mod->NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
	}

/*-------------------------------------------------------------------*/

EdgeSelRestore::EdgeSelRestore(EditMeshData* md, EditMeshMod* mod)
	{
	sel = md->esel;
	meshData = md;
	this->mod = mod;
	t = mod->iObjParams->GetTime();
	}

void EdgeSelRestore::Restore(int isUndo)
	{
	rsel = meshData->esel;
	meshData->esel = sel;
	if ( meshData->tempData && meshData->TempData(mod)->MeshCached(t) ) {
		Mesh *mesh = meshData->TempData(mod)->GetMesh(t);
		mesh->edgeSel = sel;
		meshData->TempData(mod)->Invalidate(PART_SELECT);
		}
	mod->NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
	}

void EdgeSelRestore::Redo()
	{
	meshData->esel = rsel;
	if ( meshData->tempData && meshData->TempData(mod)->MeshCached(t) ) {
		Mesh *mesh = meshData->TempData(mod)->GetMesh(t);
		mesh->edgeSel = rsel;
		meshData->TempData(mod)->Invalidate(PART_DISPLAY);
		}
	mod->NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
	}

/*-------------------------------------------------------------------*/

FaceAttribRestore::FaceAttribRestore(EditMeshData* md, EditMeshMod* mod)
	{
	attribs = md->tdelta.attribs;
	
	meshData = md;
	this->mod = mod;	
	}

void FaceAttribRestore::Restore(int isUndo)
	{	
	if (isUndo) {
		rattribs = meshData->tdelta.attribs;
		}
	meshData->tdelta.attribs = attribs;	
	if (meshData->tempData) {
		meshData->TempData(mod)->Invalidate(PART_TOPO,FALSE);
		}

	mod->InvalidateSurfaceUI();
	mod->NotifyDependents(FOREVER, PART_TOPO, REFMSG_CHANGE);
	}

void FaceAttribRestore::Redo()
	{	
	meshData->tdelta.attribs = rattribs;	
	if (meshData->tempData) {
		meshData->TempData(mod)->Invalidate(PART_TOPO,FALSE);	
		}
	mod->InvalidateSurfaceUI();
	mod->NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
	}

/*-------------------------------------------------------------------*/

FaceSmoothGroupRestore::FaceSmoothGroupRestore(EditMeshData* md, EditMeshMod* mod)
	{
	smgroups = md->tdelta.smgroups;
	
	meshData = md;
	this->mod = mod;	
	}

void FaceSmoothGroupRestore::Restore(int isUndo)
	{	
	if (isUndo) {
		rsmgroups = meshData->tdelta.smgroups;
		}
	meshData->tdelta.smgroups = smgroups;	
	if (meshData->tempData) {
		meshData->TempData(mod)->Invalidate(PART_TOPO,FALSE);
		}

	mod->InvalidateSurfaceUI();
	mod->NotifyDependents(FOREVER, PART_TOPO, REFMSG_CHANGE);
	}

void FaceSmoothGroupRestore::Redo()
	{	
	meshData->tdelta.smgroups = rsmgroups;	
	if (meshData->tempData) {
		meshData->TempData(mod)->Invalidate(PART_TOPO,FALSE);	
		}
	mod->InvalidateSurfaceUI();
	mod->NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
	}

/*-------------------------------------------------------------------*/

ExtrudeRestore::ExtrudeRestore(EditMeshData* md, EditMeshMod* mod)
	{
	meshData  = md;
	this->mod = mod;	
	}

void ExtrudeRestore::Restore(int isUndo)
	{	
	int ct;

	// Go through selected faces and put back selected faces to
	// their original mapping.
	int sel = 0;	
	for ( int i = 0; i < meshData->fsel.GetSize(); i++ ) {
		if ( meshData->fsel[i] ) {
			// Save for the redo
			FaceMap fm = meshData->tdelta.GetFaceMap(i);
			ivmap.Append(1,&fm.v[0],20);
			ivmap.Append(1,&fm.v[1],20);
			ivmap.Append(1,&fm.v[2],20);
			
			// Undo
			meshData->tdelta.ModifyFace(i,&vmap[sel]);
			sel+=3;
			}
		}
	ivmap.Shrink();

	// Pull the verts out of tdelta
	ct = meshData->tdelta.cverts.Count();
	if (!cverts.Count()) {
		cverts.Resize(nv);
		for (i = 1; i <= nv; i++) {
			DWORD v = meshData->tdelta.cverts[ct-i];
			cverts.Append(1,&v);
			}
		}
	meshData->tdelta.cverts.Delete(ct-nv,nv);

	// Pull the faces out of tdelta
	ct = meshData->tdelta.nfaces.Count();
	if ( !nfaces.Count() ) {		
		nfaces.Resize(nf);
		for ( i = 1; i <= nf; i++ ) {
			Face f = meshData->tdelta.nfaces[ct-i];
			nfaces.Append(1,&f);
			}
		}
	meshData->tdelta.nfaces.Delete(ct-nf,nf);
	
	meshData->Invalidate(PART_TOPO|PART_GEOM,FALSE);
	mod->NotifyDependents(FOREVER, PART_TOPO|PART_GEOM, REFMSG_CHANGE);
	}

void ExtrudeRestore::Redo()
	{
	// Go through selected faces and put back selected faces to
	// their original mapping.
	int sel = 0;
	for ( int i = 0; i < meshData->fsel.GetSize(); i++ ) {
		if ( meshData->fsel[i] ) {
			// Redo
			meshData->tdelta.ModifyFace(i,&ivmap[sel]);
			sel+=3;
			}
		}
	
	// Put the verts back into tdelta			
	meshData->tdelta.cverts.Resize(meshData->tdelta.cverts.Count()+nv);
	for ( i = 0; i < nv; i++ ) {
		meshData->tdelta.cverts.Append(1,&cverts[i]);		
		}

	// Put the faces back into tdelta		
	meshData->tdelta.nfaces.Resize(meshData->tdelta.nfaces.Count()+nf);
	for ( i = 0; i < nf; i++ ) {
		meshData->tdelta.nfaces.Append(1,&nfaces[i]);		
		}	
	
	meshData->Invalidate(PART_TOPO|PART_GEOM,FALSE);
	mod->NotifyDependents(FOREVER, PART_TOPO|PART_GEOM, REFMSG_CHANGE);	
	}

/*--------------------------------------------------------------------*/

