---
# System prepended metadata

title: HairModel CreateHair4
tags: [Structure]

---

# HairModel CreateHair4
###### tags: `Structure`
finished : undo redo clear.

### goal:
if StackExistHair!=0, undo can always be excuted.
redo need to be excuted after undo, but not after clear function.
if clear excuted, rerecord the undo count. (till next clear)

### test example:
(u) = undo  //undo function include Pop and push, depends on clear functions excuted or not.
(r) = redo 
(c) = clear
(d) = draw a new one

### script:

```c#

//別忘記PosGenerate.cs要改 Point Pos
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateHair4 : MonoBehaviour
{
    int TriggerDown = 0;  //沒被按下
    int HairCounter = 0; //Hair片數
    int HairWidth = 1; //Hair寬度

    float length = 0.5f; //點距離

    Vector3 NewPos, OldPos; //抓新舊點

    public static List<Vector3> PointPos = new List<Vector3>(); //Pos座標存取
    public List<GameObject> HairModel = new List<GameObject>(); //髮片Gameobj存取

    public MeshGenerate MeshCreater; //呼叫 MeshGenerate.cs 中的東西給 MeshCreater 用
    public PosGenerate PosCreater; //呼叫 PosGenerate.cs 中的東西給 PosCreater 用

    public List<GameObject> ListExistHair = new List<GameObject>(); //給Undo用
    Stack<GameObject> StackExistHair = new Stack<GameObject>(); //給Redo用
    GameObject PushObj, PopObj;
    GameObject ExistHair;
    int u_Freq = 0, c_Freq = 0;
    int TempListExistHair = 0;

    private void Start()
    {
        PosCreater = gameObject.AddComponent<PosGenerate>(); //加入PosGenerate
    }

    void Update()
    {
        if (TriggerDown == 0) //沒被按下
        {
            if (Input.GetMouseButtonDown(0)) //偵測被按下的瞬間
            {
                GameObject Model = new GameObject(); //創建model gameobj
                HairModel.Add(Model); //加入list
                HairModel[HairCounter].name = "HairModel" + HairCounter; //設定名字
                ResetPos();
                TriggerDown = 1;
            }
        }
        if (TriggerDown == 1) //被按下
        {
            NewPos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10f));
            float dist = Vector3.Distance(OldPos, NewPos); //計算舊點到新點，位置的距離

            if (dist > length) //距離大於設定的長度
            {
                PosCreater = gameObject.GetComponent<PosGenerate>(); //加入PosGenerate
                PosCreater.GetPosition(OldPos, NewPos, HairWidth);
                ResetPos();
            }

            if (PointPos.Count >= (3 + (HairWidth - 1) * 2) * 2)
            {
                if (HairModel[HairCounter].GetComponent<MeshGenerate>() == null)
                    MeshCreater = HairModel[HairCounter].AddComponent<MeshGenerate>();
                else MeshCreater = HairModel[HairCounter].GetComponent<MeshGenerate>();
                MeshCreater.GenerateMesh(PointPos, HairWidth);
            }

            if (Input.GetMouseButtonUp(0))
            {
                if (PointPos.Count >= (3 + (HairWidth - 1) * 2) * 2)
                {
                    HairCounter++; 
                    ExistHair = GameObject.Find("HairModel" + (HairCounter - 1)); //找到相應的hairmodel名稱丟給 ExistHair GameObj
                    ListExistHair.Add(ExistHair);
                    c_Freq = 0;
                }

                else //清除不夠長所以沒加到程式碼的的髮片gameobj
                {                   
                    int least = HairModel.Count - 1;
                    Destroy(HairModel[least]);
                    HairModel.RemoveAt(least);
                }
                PointPos.Clear();
                TriggerDown = 0;
            }
        }

        //if StackExistHair!=0, undo can always be excuted.
        if (Input.GetKeyDown("u") && c_Freq == 0) //clear had not be excuted, undo use PushStaff.
        {
            u_Freq += 1;
            PushStuff();
            Debug.Log("uF:" + u_Freq + "cF:" + c_Freq);
        }
        if (Input.GetKeyDown("u") && c_Freq == 1) //clear had been excuted, undo use PopStaff.
        {
            u_Freq = 1; // after clear function excuted, undo can be excuted once.
            for (int i = 0; i < TempListExistHair; i++) 
            {
                PopStuff();
            }
            Debug.Log("uF:" + u_Freq + "cF:" + c_Freq);
        }

        //redo need to be excuted after undo, but not after clear function.
        if (Input.GetKeyDown("r") && u_Freq != 0 && c_Freq == 0)
        {
            PopStuff();
            u_Freq -= 1;
            Debug.Log("uF:" + u_Freq + "cF:" + c_Freq);
        }
        if (Input.GetKeyDown("r") && u_Freq != 0 && c_Freq == 1)
        {
            for (int i = 0; i < TempListExistHair; i++)
            {
                PushStuff();
            }
            u_Freq = 0; 
            Debug.Log("uF:" + u_Freq + "cF:" + c_Freq);
        }

        //if clear excuted, rerecord the undo count. (till next clear)
        if (Input.GetKeyDown("c"))
        {
            u_Freq = 0; // Undo count return to zero.
            StackExistHair.Clear();
            TempListExistHair = ListExistHair.Count; 
            for (int i = 0; i < TempListExistHair; i++)  //All in.
            {
                PushStuff();
            }
            c_Freq = 1; //clear functions had been excuted. (for undo)
            Debug.Log("uF:" + u_Freq + "cF:" + c_Freq);
        }

    }
    //= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
    void ResetPos()
    {
        OldPos = NewPos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10f));
    }

    void PushStuff() //push staff into 
    {
        PushObj = Instantiate(ListExistHair[ListExistHair.Count - 1]); //生成ListExitstHair中count-1的物件
        StackExistHair.Push(PushObj); //生成的物件(pushobj)push進stack存，之後要redo要用
        PushObj.SetActive(false); //場景上不再看得見
        Destroy(ListExistHair[ListExistHair.Count - 1]); //刪除ListExitstHair中count-1的物件
        ListExistHair.RemoveAt(ListExistHair.Count - 1); //從ListExistHair中移除count-1的物件
        Debug.Log("Push");
    }

    void PopStuff()
    {
        PopObj = StackExistHair.Pop(); //從stack中pop東西出來
        ListExistHair.Add(PopObj); //加回ListExitstsHair中
        PopObj.SetActive(true); //場景上要看得見
        Debug.Log("Pop");
    } 
}


```