//ツリーの深さと幅の探索
        private void Material_Level(material material, int level)
        {
            if (level == 0)
            {
                material_levels.Add(1);
            }

            if (material_levels.Count - 1 < level + 2)
            {
                material_levels.Add(0);
            }

            //material_levels[level] +=  material.material_op.Count;
            material_levels[level + 1] += material.material_childs.Count;

            foreach (material m in material.material_childs)
            {
                Material_Level(m, level + 1);
            }

            if (material.material_childs.Count == 0)
            {
                if (material_levels.Count < level + 2)
                {
                    material_levels.Add(0);
                }

                material_levels[level + 1] += material.material_op.Count;
            }
        }
        //--------------------------------------
        //新マテリアルツリーコード
        //--------------------------------------

        //boxの上真ん中のxy座標を返す
        private (OP_MaterialBox, double, double) ShowMaterialTree2(material m, int all_material, int shift = 0, int level = 0)
        {
            double width_fix = Width - (Width_margin * 2);
            int    nodecount = tools.CountMaterial(m);
            double wn        = ((double)nodecount / (double)(2 * all_material)) * width_fix;

            wn -= BoxWidth / 2;

            double x_shift = ((double)shift / (double)all_material) * width_fix;
            double windowX = wn + x_shift + Width_margin;
            double windowY = CalcShowPointY(level, BoxHeight);

            //OP_MaterialBox matBox = ShowMaterial(m.Recipes, windowX, windowY);
            OP_MaterialBox matBox = ShowMaterial(m.Recipes, windowX, windowY);

            int shift2 = shift;

            foreach (material mx in m.material_childs)
            {
                int nodecount_c = tools.CountMaterial(mx);
                (OP_MaterialBox childBox, double childX, double childY) = ShowMaterialTree2(mx, all_material, shift2, level + 1);
                shift2 += nodecount_c;

                //線を引く
                Path p = new Path();
                p.Stroke          = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
                p.StrokeThickness = 2;
                string geoStr = string.Format("M{0},{1} L{2},{3}", windowX + BoxWidth / 2, windowY + BoxHeight, childX, childY);
                p.Data        = Geometry.Parse(geoStr);
                childBox.path = p;
                main_grid.Children.Add(p);
            }

            if (m.material_childs.Count == 0)
            {
                double dw = width_fix / all_material;
                double x  = Width_margin + (dw * shift);

                double y = CalcShowPointY(level + 1, BoxHeight);

                foreach (List <op_stct2> ops in m.material_op)
                {
                    Material_StartBox opBox =  ShowMaterial(ops, x, y);

                    //線を引く
                    Path p = new Path();
                    p.Stroke          = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
                    p.StrokeThickness = 2;
                    string geoStr = string.Format("M{0},{1} L{2},{3}", windowX + BoxWidth / 2, windowY + BoxHeight, x + BoxWidth / 2, y);
                    p.Data     = Geometry.Parse(geoStr);
                    opBox.path = p;
                    main_grid.Children.Add(p);

                    x += dw;
                }
            }


            return(matBox, windowX + BoxWidth / 2, windowY);
        }
        //materialの一番根の数を数える
        public static int CountMaterial(material material)
        {
            int sum = 0;

            foreach (material m in material.material_childs)
            {
                sum += CountMaterial(m);
            }

            if (material.material_childs.Count == 0)
            {
                return(material.material_op.Count);
            }

            return(sum);
        }
        private void StartButton_Click(object sender, RoutedEventArgs e)
        {
            material m         = OP_CompositionEngine.SerchOP(ContextData.targetOPList.ToArray());
            var      tree_page = TreeFrame.Content;

            if (tree_page is OP_TreePage)
            {
                var page = (OP_TreePage)tree_page;
                page.ShowMaterialTree(m);
                //Console.WriteLine("FrameViewBox Width:{0}, Height:{1}", TreeFrame_ViewBox.Width, TreeFrame_ViewBox.Height);

                double edge_X = Width - (TreeFrameBoader.Margin.Left + TreeFrameBoader.Margin.Right);
                double edge_Y = Height - (TreeFrameBoader.Margin.Top + TreeFrameBoader.Margin.Bottom);
                TreeFrame_ViewBox.Width  = edge_X;
                TreeFrame_ViewBox.Height = edge_Y;
            }
        }
        //ツリーを表示(外部からアクセス用)
        public void ShowMaterialTree(material m)
        {
            ClearDisplay();

            material_slot = m.Recipes.Count;
            Material_Level(m, 0);

            //var box = ShowMaterialTree(m, 0);

            int ChildCout = tools.CountMaterial(m);

            (this.Width, this.Height) = PageWidthHeight(m.Recipes.Count, ChildCout);
            ShowMaterialTree2(m, ChildCout);

            //EventBox.ForEach(x => x.forceEvent());
            //EventBox.Clear();

            Console.WriteLine("Material:{0}", tools.CountMaterial(m));
        }
        static public material SerchOP(op_stct2[] target, int percent_plus = 0)
        {
            material output_mat = SerchOP_materialBodys(target, percent_plus);

            List <string> target_names = target.Select(x => x.op_name).ToList();
            List <string> flatten_mat  = new List <string>();
            int           max_slot     = 1;

            //次の再帰に入るか判定
            foreach (List <op_stct2> x in output_mat.material_op)
            {
                foreach (op_stct2 y in x)
                {
                    flatten_mat.Add(y.op_name);
                }

                if (max_slot < x.Count())
                {
                    max_slot = x.Count();
                }
            }

            //目的のOPと素材のOPの差集合
            List <string> exist = tools.SubList(target_names, flatten_mat);


            if ((max_slot == 1 && exist.Count() == 0) == false)
            {
                foreach (List <op_stct2> o in output_mat.material_op)
                {
                    material m = SerchOP(o.ToArray(), percent_plus);
                    output_mat.material_childs.Add(m);
                }
            }

            return(output_mat);
        }