static void AddWatermark(WordprocessingDocument doc, string textWatermark)
        {
            if (doc.MainDocumentPart.HeaderParts.Count() == 0)
            {
                doc.MainDocumentPart.DeleteParts(doc.MainDocumentPart.HeaderParts);
                var newHeaderPart = doc.MainDocumentPart.AddNewPart <HeaderPart>();
                var rId           = doc.MainDocumentPart.GetIdOfPart(newHeaderPart);
                var headerRef     = new HeaderReference();
                headerRef.Id = rId;
                var sectionProps = doc.MainDocumentPart.Document.Body.Elements <SectionProperties>().LastOrDefault();
                if (sectionProps == null)
                {
                    sectionProps = new SectionProperties();
                    doc.MainDocumentPart.Document.Body.Append(sectionProps);
                }
                sectionProps.RemoveAllChildren <HeaderReference>();
                sectionProps.Append(headerRef);

                newHeaderPart.Header = MakeHeader();
                newHeaderPart.Header.Save();
            }

            foreach (HeaderPart headerPart in doc.MainDocumentPart.HeaderParts)
            {
                var sdtBlock1      = new SdtBlock();
                var sdtProperties1 = new SdtProperties();
                var sdtId1         = new SdtId()
                {
                    Val = 87908844
                };
                var sdtContentDocPartObject1 = new SdtContentDocPartObject();
                var docPartGallery1          = new DocPartGallery()
                {
                    Val = "Watermarks"
                };
                var docPartUnique1 = new DocPartUnique();
                sdtContentDocPartObject1.Append(docPartGallery1);
                sdtContentDocPartObject1.Append(docPartUnique1);
                sdtProperties1.Append(sdtId1);
                sdtProperties1.Append(sdtContentDocPartObject1);

                var sdtContentBlock1 = new SdtContentBlock();
                var paragraph2       = new Paragraph()
                {
                    RsidParagraphAddition  = "00656E18",
                    RsidRunAdditionDefault = "00656E18"
                };
                var paragraphProperties2 = new ParagraphProperties();
                var paragraphStyleId2    = new ParagraphStyleId()
                {
                    Val = "Header"
                };
                paragraphProperties2.Append(paragraphStyleId2);
                var run1           = new Run();
                var runProperties1 = new RunProperties();
                var noProof1       = new NoProof();
                var languages1     = new Languages()
                {
                    EastAsia = "zh-TW"
                };
                runProperties1.Append(noProof1);
                runProperties1.Append(languages1);
                var picture1   = new Picture();
                var shapetype1 = new Shapetype()
                {
                    Id             = "_x0000_t136",
                    CoordinateSize = "21600,21600",
                    OptionalNumber = 136,
                    Adjustment     = "10800",
                    EdgePath       = "m@7,l@8,m@5,21600l@6,21600e"
                };
                var formulas1 = new Formulas();
                var formula1  = new Formula()
                {
                    Equation = "sum #0 0 10800"
                };
                var formula2 = new Formula()
                {
                    Equation = "prod #0 2 1"
                };
                var formula3 = new Formula()
                {
                    Equation = "sum 21600 0 @1"
                };
                var formula4 = new Formula()
                {
                    Equation = "sum 0 0 @2"
                };
                var formula5 = new Formula()
                {
                    Equation = "sum 21600 0 @3"
                };
                var formula6 = new Formula()
                {
                    Equation = "if @0 @3 0"
                };
                var formula7 = new Formula()
                {
                    Equation = "if @0 21600 @1"
                };
                var formula8 = new Formula()
                {
                    Equation = "if @0 0 @2"
                };
                var formula9 = new Formula()
                {
                    Equation = "if @0 @4 21600"
                };
                var formula10 = new Formula()
                {
                    Equation = "mid @5 @6"
                };
                var formula11 = new Formula()
                {
                    Equation = "mid @8 @5"
                };
                var formula12 = new Formula()
                {
                    Equation = "mid @7 @8"
                };
                var formula13 = new Formula()
                {
                    Equation = "mid @6 @7"
                };
                var formula14 = new Formula()
                {
                    Equation = "sum @6 0 @5"
                };

                formulas1.Append(formula1);
                formulas1.Append(formula2);
                formulas1.Append(formula3);
                formulas1.Append(formula4);
                formulas1.Append(formula5);
                formulas1.Append(formula6);
                formulas1.Append(formula7);
                formulas1.Append(formula8);
                formulas1.Append(formula9);
                formulas1.Append(formula10);
                formulas1.Append(formula11);
                formulas1.Append(formula12);
                formulas1.Append(formula13);
                formulas1.Append(formula14);
                var path1 = new Path()
                {
                    AllowTextPath       = TrueFalseValue.FromBoolean(true),
                    ConnectionPointType = ConnectValues.Custom,
                    ConnectionPoints    = "@9,0;@10,10800;@11,21600;@12,10800",
                    ConnectAngles       = "270,180,90,0"
                };
                var textPath1 = new TextPath()
                {
                    On       = TrueFalseValue.FromBoolean(true),
                    FitShape = TrueFalseValue.FromBoolean(true)
                };
                var shapeHandles1 = new ShapeHandles();

                var shapeHandle1 = new ShapeHandle()
                {
                    Position = "#0,bottomRight",
                    XRange   = "6629,14971"
                };

                shapeHandles1.Append(shapeHandle1);

                var lock1 = new Lock
                {
                    Extension = ExtensionHandlingBehaviorValues.Edit,
                    TextLock  = TrueFalseValue.FromBoolean(true),
                    ShapeType = TrueFalseValue.FromBoolean(true)
                };

                shapetype1.Append(formulas1);
                shapetype1.Append(path1);
                shapetype1.Append(textPath1);
                shapetype1.Append(shapeHandles1);
                shapetype1.Append(lock1);
                var shape1 = new Shape()
                {
                    Id             = "PowerPlusWaterMarkObject357922611",
                    Style          = "position:absolute;left:0;text-align:left;margin-left:0;margin-top:0;width:527.85pt;height:131.95pt;rotation:315;z-index:-251656192;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin",
                    OptionalString = "_x0000_s2049",
                    AllowInCell    = TrueFalseValue.FromBoolean(true),
                    FillColor      = "silver",
                    Stroked        = TrueFalseValue.FromBoolean(false),
                    Type           = "#_x0000_t136"
                };


                var fill1 = new Fill()
                {
                    Opacity = ".5"
                };
                TextPath textPath2 = new TextPath()
                {
                    Style  = "font-family:\"Calibri\";font-size:1pt",
                    String = textWatermark
                };

                var textWrap1 = new TextWrap()
                {
                    AnchorX = HorizontalAnchorValues.Margin,
                    AnchorY = VerticalAnchorValues.Margin
                };

                shape1.Append(fill1);
                shape1.Append(textPath2);
                shape1.Append(textWrap1);
                picture1.Append(shapetype1);
                picture1.Append(shape1);
                run1.Append(runProperties1);
                run1.Append(picture1);
                paragraph2.Append(paragraphProperties2);
                paragraph2.Append(run1);
                sdtContentBlock1.Append(paragraph2);
                sdtBlock1.Append(sdtProperties1);
                sdtBlock1.Append(sdtContentBlock1);
                headerPart.Header.Append(sdtBlock1);
                headerPart.Header.Save();
                //break;
            }
        }
    /*
     * Draw a collider gizmo for a specified part
     * */
    public static void DrawShapeHandle(BodyPart part, bool drawOpposite)
    {
        // early out if the part is null or the part has no shape
        if (part == null || part.shapeType == ShapeType.None || !part.isCollider)
        {
            return;
        }

        // store the current color
        Color oldColor = Handles.color;

        // set undo snapshot
        BodyPart[] parts = new BodyPart[1];
        if (isSymmetrical && part.oppositePart != null)
        {
            parts    = new BodyPart[2];
            parts[1] = part.oppositePart;
            parts[1].oppositePart = part;             // BUG: No idea why I need to do this
        }
        parts[0] = part;
        Undo.SetSnapshotTarget(parts, string.Format("Change Shape"));

        // create shape handles
        if (isShapeHandleEnabled)
        {
            // use radius if shape is capsule or sphere
            float radius = 0f;

            // compute the size to draw the shape handle based on the part's scale
            Vector3 shapeHandleSize = GetShapeHandleSize(part);

            // draw the correct handle based on shapeType
            switch (part.shapeType)
            {
            case ShapeType.Box:
                // create handles
                ShapeHandles.WireBox(ref shapeHandleSize, part.bone.TransformPoint(part.shapeCenter), part.bone.rotation, "");

                // apply the result
                DoShapeSizeThresholdTest(part, shapeHandleSize);

                // handle symmetry
                if (parts.Length > 1)
                {
                    part.PasteShapeSizeToOpposite(isScaleSymmetrical);
                    if (drawOpposite)
                    {
                        // get the opposite part's dimensions in case its local scale is different
                        shapeHandleSize = GetShapeHandleSize(parts[1]);

                        // ghost the opposite part
                        CustomHandleUtilities.SetHandleColor(oldColor, symmetryAlpha);
                        ShapeHandles.WireBox(ref shapeHandleSize, parts[1].bone.TransformPoint(parts[1].shapeCenter), parts[1].bone.rotation, "");

                        // apply the result
                        DoShapeSizeThresholdTest(parts[1], shapeHandleSize);
                        parts[1].PasteShapeSizeToOpposite(isScaleSymmetrical);
                    }
                }
                break;

            case ShapeType.Capsule:
                // get handle properties
                float      height             = 0f;
                Quaternion capsuleOrientation = Quaternion.identity;
                GetCapsuleProperties(part, ref height, ref radius, ref capsuleOrientation);

                // draw handle
                ShapeHandles.WireCapsule(ref radius, ref height, part.bone.TransformPoint(part.shapeCenter), part.bone.rotation * part.shapeRotation * capsuleOrientation, "");

                // apply result
                DoShapeSizeThresholdTest(part, CapsuleToSize(part, height, radius));

                // handle symmetry
                if (parts.Length > 1)
                {
                    part.PasteShapeSizeToOpposite(isScaleSymmetrical);
                    if (drawOpposite)
                    {
                        // get the opposite part's dimensions in case its local scale is different
                        GetCapsuleProperties(parts[1], ref height, ref radius, ref capsuleOrientation);

                        // ghost the opposite part
                        CustomHandleUtilities.SetHandleColor(oldColor, symmetryAlpha);
                        ShapeHandles.WireCapsule(ref radius, ref height, parts[1].bone.TransformPoint(parts[1].shapeCenter), parts[1].bone.rotation * parts[1].shapeRotation * capsuleOrientation, "");

                        // apply the result
                        DoShapeSizeThresholdTest(parts[1], CapsuleToSize(parts[1], height, radius));
                        parts[1].PasteShapeSizeToOpposite(isScaleSymmetrical);
                    }
                }
                break;

            case ShapeType.Sphere:
                // create a simple radius handle
                float oldRadius = Mathf.Max(
                    part.shapeSize.x * part.bone.lossyScale.x * 0.5f,
                    part.shapeSize.y * part.bone.lossyScale.y * 0.5f,
                    part.shapeSize.z * part.bone.lossyScale.z * 0.5f);
                radius = Handles.RadiusHandle(part.bone.rotation * part.shapeRotation, part.bone.TransformPoint(part.shapeCenter), oldRadius);
                if (Mathf.Abs(radius - oldRadius) > changeThreshold)
                {
                    float scaleFactor = 1f / VectorHelpers.MaxValue(part.bone.lossyScale);
                    part.shapeSize.x = 2f * radius * scaleFactor;
                    part.shapeSize.y = 2f * radius * scaleFactor;
                    part.shapeSize.z = 2f * radius * scaleFactor;
                    oldRadius        = radius;
                }

                // handle symmetry
                if (parts.Length > 1)
                {
                    part.PasteShapeSizeToOpposite(isScaleSymmetrical);
                    if (drawOpposite)
                    {
                        // ghost the opposite part
                        CustomHandleUtilities.SetHandleColor(oldColor, symmetryAlpha);
                        oldRadius = Mathf.Max(
                            parts[1].shapeSize.x * parts[1].bone.lossyScale.x * 0.5f,
                            parts[1].shapeSize.y * parts[1].bone.lossyScale.y * 0.5f,
                            parts[1].shapeSize.z * parts[1].bone.lossyScale.z * 0.5f);
                        radius = Handles.RadiusHandle(parts[1].bone.rotation * part.shapeRotation, parts[1].bone.TransformPoint(parts[1].shapeCenter), oldRadius);
                        if (Mathf.Abs(radius - oldRadius) > changeThreshold)
                        {
                            parts[1].shapeSize.x = 2f * radius;
                            parts[1].shapeSize.y = 2f * radius;
                            parts[1].shapeSize.z = 2f * radius;
                            parts[1].PasteShapeSizeToOpposite(isScaleSymmetrical);
                        }
                    }
                }
                break;
            }
        }

        // center handles
        if (isCenterHandleEnabled)
        {
            // position handle for the center
            Vector3 center = part.bone.InverseTransformPoint(Handles.PositionHandle(part.bone.TransformPoint(part.shapeCenter), part.bone.rotation * part.shapeRotation));

            // rotation handle
//			Quaternion rotation = Quaternion.Inverse(part.bone.rotation)*Handles.RotationHandle(part.bone.rotation*part.shapeRotation, part.bone.TransformPoint(part.shapeCenter));

            // handle symmetry
            if (parts.Length > 1)
            {
                center = part.TransformPointToOpposite(center, isScaleSymmetrical);
//				rotation = part.TransformRotationToOpposite(rotation);
                if (drawOpposite)
                {
                    center = parts[1].bone.InverseTransformPoint(Handles.PositionHandle(parts[1].bone.TransformPoint(center), parts[1].bone.rotation * part.shapeRotation));
//					rotation = Quaternion.Inverse(parts[1].bone.rotation)*Handles.RotationHandle(parts[1].bone.rotation*parts[1].shapeRotation, parts[1].bone.TransformPoint(parts[1].shapeCenter));
                }
                center = parts[1].TransformPointToOpposite(center, isScaleSymmetrical);
//				rotation = parts[1].TransformRotationToOpposite(rotation);
            }

            // apply results
            if ((part.shapeCenter - center).sqrMagnitude > changeThreshold * changeThreshold)
            {
                part.shapeCenter = center;
            }
//			if (Quaternion.Angle(part.shapeRotation, rotation)>changeThreshold) part.shapeRotation = rotation;
        }

        if (parts.Length > 1)
        {
            // update values
            parts[1].shapeType = part.shapeType;

            Vector3 oldValue = parts[1].shapeCenter;
            Vector3 newValue = part.TransformPointToOpposite(part.shapeCenter, isScaleSymmetrical);
            if ((oldValue - newValue).sqrMagnitude > changeThreshold * changeThreshold)
            {
                parts[1].shapeCenter = newValue;
            }

            oldValue = parts[1].shapeSize;
            part.PasteShapeSizeToOpposite(isScaleSymmetrical);
            if ((oldValue - parts[1].shapeSize).sqrMagnitude < changeThreshold * changeThreshold)
            {
                parts[1].shapeSize = oldValue;
            }

            // TODO: mirror rotation if/when collider rotation is implemented
        }

        CustomHandleUtilities.SetHandleColor(oldColor);

        foreach (BodyPart p in parts)
        {
            EditorUtility.SetDirty(p);
        }
    }