<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for PaintSelector.xaml
    /// </summary>
    public partial class PaintSelector : Window
    {
        public static string PaintColor;
        
        public PaintSelector()
        {
            InitializeComponent();
            //this.window = window;
            //PaintColor = window.PaintColor;
        }
        private void button_Click(object sender, RoutedEventArgs e)
        {
            Button button = (Button)sender;
            Brush b = button.Background;
            textbox_color.Text = "#"+ (b as SolidColorBrush).Color.ToString().Substring(3);
        }

        private void textbox_color_TextChanged(object sender, TextChangedEventArgs e)
        {
            changeTextBoxColor();
        }

        private void changeTextBoxColor()
        {
            if(textbox_color.Text.Length==7)
            {
                try
                {
                    var bc = new BrushConverter();
                    string color = "#FF" + textbox_color.Text.Substring(1);
                    textbox_color.Background = (Brush)bc.ConvertFrom(color);
                }
                catch
                {
                    MessageBox.Show("Please use the right format\n \"#123abc\" where 1-9,a-f (hex)");
                }
            }
            else
            {
                var bc = new BrushConverter();
                textbox_color.Background = (Brush)bc.ConvertFrom("#eeeeee");
            }
            PaintColor = textbox_color.Text;
        }

        private void slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            string red = Convert.ToInt32(slider_red.Value).ToString("X");
            string green = Convert.ToInt32(slider_green.Value).ToString("X");
            string blue = Convert.ToInt32(slider_blue.Value).ToString("X");
            string color = "#" + red.PadLeft(2,'0') +""+ green.PadLeft(2,'0') +""+ blue.PadLeft(2,'0');
            textbox_color.Text = color;
        }
        
        private void textbox_color_MouseEnter(object sender, MouseEventArgs e)
        {
            changeTextBoxColor();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            textbox_color.Text = "#";
        }


        //onpaint change: this.window.paint = #iets;
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for ProgressWindow.xaml
    /// </summary>
    public partial class ProgressWindow : Window
    {
        BackgroundWorker BackgroundWorker;
        public ProgressWindow(BackgroundWorker backgroundworker, string doing )
        {
            this.BackgroundWorker = backgroundworker;
            InitializeComponent();
            doing_label.Content = doing;
        }

        public void Cancel_Click(object sender, RoutedEventArgs e)
        {
            if (BackgroundWorker != null)
                BackgroundWorker.CancelAsync();
        }

        public void UpdateProgress(int currentprogress)
        {
            progressbar.Value = currentprogress;
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Assimp;
using Assimp.Unmanaged;


namespace Advanced_Blueprint_Tools
{
    using System.Windows.Media;
    using System.Windows.Media.Media3D;
    using HelixToolkit.Wpf;
    using Assimp.Configs;
    using System.Net.Http;
    using System.Net;
    using Newtonsoft.Json.Linq;

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        
        public BP OpenedBlueprint { get; set; }
        public Model3DGroup Model { get; set; }
        public Model3DGroup Marker { get; set; }
        public Model3DGroup Marker2 { get; set; }
        public Model3DGroup Glass { get; set; }

        public Model3DGroup Wires { get; set; }

        OpenWindow openwindow;
        //public cuz need to update(); when new creation loaded: 
        public AdvancedConnections advancedconnections;
        public AdvancedColor advancedcolorwindow;
        public SwapBlocksWindow swapblockswindow;
        public BlockProperties blockProperties;
        public AreaProperties areaProperties;
        public BlockPropertiesRAW blockPropertiesRAW;

        Circle_generator circle_generator;
        Ellipsoid_Generator ellpisoid_generator;
        Cuboid_Generator cuboid_Generator;

        NotificationWindow notificationWindow;
        Settings settings;

        public MainWindow()
        {

            new Thread(() =>
            {
                MessageBox.Show("This version of the tool should work with scrap mechanic 0.4.5, if for any reason this breaks or you found a bug: contact Brent Batch#9261");
            }).Start();
            InitializeComponent();
            //LOAD RESOURCES:
            Database.findPaths();
            new Thread(() =>
            {
                try
                {
                    Database.LoadAllBlocks();
                }
                catch (Exception e)
                {
                    MessageBox.Show("Error: Could not load parts. Further program functions may fail.\n" + e.Message);
                }
            }).Start();
            new Thread(() =>
            {
                try
                { 
                    Database.LoadAllBlueprints();
                }
                    catch (Exception e)
                {
                    MessageBox.Show("Error: Could not load Blueprints. Further program functions may fail.\n" + e.Message);
                }
            }).Start();
            new Task(() =>
            {
                try
                { 
                    new Updater().CheckForUpdates();
                }
                    catch (Exception e)
                {
                    MessageBox.Show("Error: could not check for an updated version.\n" + e.Message);
                }
            }).Start();
            new Thread(() =>
            {
                try
                {
                    while (true)
                    {
                        this.Dispatcher.Invoke((Action)(() =>
                        {
                            if (Database.Notifications.Count > 0)
                            {
                                Notifications.Visibility = Visibility.Visible;
                                Notifications.Content = Database.Notifications.Count;
                            }
                            else
                            {
                                Notifications.Visibility = Visibility.Collapsed;
                            }
                        }));
                        Thread.Sleep(1500);
                    }
                }
                catch { }

            }).Start();
            helix.Camera = helix_wires.Camera;

        } 

        public void RenderBlueprint()
        {
            
            try
            {
                TextBox_Name.Text = BP.Description.name;
                TextBox_Description.Text = BP.Description.description;

                Tuple<Model3DGroup, Model3DGroup> renders = BP.RenderBlocks();//backgroundtask ?
                this.Model = renders.Item1;
                this.Glass = renders.Item2;
                this.Marker = null;
                CenterMass.Content = null;
                this.Marker2 = new Model3DGroup();

                RenderWires();
                if (listBox_parts.Visibility == Visibility.Visible)
                    fillparts();
                Image_blueprint.DataContext = null;
                Image_blueprint.DataContext = this;
                helix.ResetCamera();
                helix_wires.Camera = helix.Camera;
                //Model.Children[5].Transform = new ScaleTransform3D(2,2,2);

                if (connections.IsEnabled == false)
                {
                    connections.IsEnabled = true;
                    blockproperties.IsEnabled = true;
                    paint.IsEnabled = true;
                    fixcreation.IsEnabled = true;
                    areaproperties.IsEnabled = true;
                    swapblocks.IsEnabled = true;
                    paintpicker.IsEnabled = true;
                    mirrorcreation.IsEnabled = true;
                    requiredmods.IsEnabled = true;
                }
                if (!Properties.Settings.Default.safemode)
                    blockpropertiesRAW.IsEnabled = true;
                else
                    blockpropertiesRAW.IsEnabled = false;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message + "\nin most cases the creation should be fine, something just went wrong while rendering", "failed to render");
            }
            
        }

        public void RenderWires()
        {
            this.Wires = new Model3DGroup();
            if (Properties.Settings.Default.wires)
            {
                var wires = BP.GetWires();
                foreach (dynamic wire in wires.Values)
                {
                    Addblob(wire.pos, wire.color.ToString());
                    if (wire.connections != null)
                        foreach (dynamic connid in wire.connections)
                            if (wires.ContainsKey(Convert.ToInt32(connid.id.ToString())))
                            {
                                Addwire(wire.pos, wires[Convert.ToInt32(connid.id.ToString())].pos, wire.color.ToString());
                            }
                }
                Image_blueprint.DataContext = null;
                Image_blueprint.DataContext = this;
                }

        }
        private void ToggleWires_Click(object sender, RoutedEventArgs e)
        {
            if (BP.Blueprint != null)
            {
                Properties.Settings.Default.wires = !Properties.Settings.Default.wires;
                if (Properties.Settings.Default.wires)
                    RenderWires();
                else
                {
                    this.Wires = null;
                    Image_blueprint.DataContext = null;
                    Image_blueprint.DataContext = this;
                }

            }

        }


        private void CenterMass_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (CenterMass.Content == null)
                {
                    Point3D point = BP.GetCenterOffMass().Item1;

                    Material material = new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(255,230,30,30)));
                    var meshBuilder = new MeshBuilder(false, false);

                    meshBuilder.AddSphere(point, 0.3);
                    var Mesh = meshBuilder.ToMesh(true);
                    CenterMass.Content = new GeometryModel3D { Geometry = Mesh, Material = material };
                }
                else
                    CenterMass.Content = null;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        public void Addblob(dynamic pos, string color)
        {
            try
            {
                if (!Properties.Settings.Default.colorwires)
                    color = Properties.Settings.Default.blobcolor.Substring(1,6);

                Material material = new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(Properties.Settings.Default.coloropacity,
                            Convert.ToByte(color.Substring(0, 2), 16), Convert.ToByte(color.Substring(2, 2), 16), Convert.ToByte(color.Substring(4, 2), 16))));
                var meshBuilder = new MeshBuilder(false, false);

                meshBuilder.AddSphere(new Point3D(Convert.ToDouble(pos.x.ToString()) ,
                                                Convert.ToDouble(pos.y.ToString()) ,
                                                Convert.ToDouble(pos.z.ToString()) ), 0.25);
                var Mesh = meshBuilder.ToMesh(true);
                this.Wires.Children.Add(new GeometryModel3D { Geometry = Mesh, Material = material });
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "wire render failed");
            }
        }

        public void Addwire(dynamic pos1, dynamic pos2, string color)
        {
            try
            {
                if (!Properties.Settings.Default.colorwires)
                    color = Properties.Settings.Default.wirecolor.Substring(1, 6);
                Material material = new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(Properties.Settings.Default.coloropacity,
                        Convert.ToByte(color.Substring(0, 2), 16), Convert.ToByte(color.Substring(2, 2), 16), Convert.ToByte(color.Substring(4, 2), 16))));

                var meshBuilder = new MeshBuilder(false, false);

                meshBuilder.AddArrow(new Point3D(Convert.ToDouble(pos1.x.ToString()),
                                                Convert.ToDouble(pos1.y.ToString()) ,
                                                Convert.ToDouble(pos1.z.ToString()) ),
                                    new Point3D(Convert.ToDouble(pos2.x.ToString()) ,
                                                Convert.ToDouble(pos2.y.ToString()) ,
                                                Convert.ToDouble(pos2.z.ToString()) ),
                                    0.15, 4);
                var Mesh = meshBuilder.ToMesh(true);
                this.Wires.Children.Add(new GeometryModel3D { Geometry = Mesh, Material = material });
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "wire render failed");
            }
        }

        public void setMarker(double x, double y, double z)
        {//cross marker
            Model3DGroup marker = new Model3DGroup();
            Material material = new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(100, 51, 204, 51)));
            var meshBuilder = new MeshBuilder(false, false);
            meshBuilder.AddBox(new Point3D(x, y, z), 0.2, 0.2, 1000);
            meshBuilder.AddBox(new Point3D(x, y, z), 0.2, 1000, 0.2);
            meshBuilder.AddBox(new Point3D(x, y, z), 1000, 0.2, 0.2);
            // Create a mesh from the builder (and freeze it)
            var Mesh = meshBuilder.ToMesh(true);
            
            marker.Children.Add(new GeometryModel3D { Geometry = Mesh, Material = material });
            this.Marker = marker;
            
          
            Image_blueprint.DataContext = "";
            Image_blueprint.DataContext = this;
            helix_wires.Camera.LookAt(new Point3D(x, y, z), 1000);
            //helix.Camera = helix_wires.Camera;
        }
        public void setMarker2(double x, double y, double z, double boundsx, double boundsy, double boundsz)
        {//cuboid marker
            Model3DGroup marker = new Model3DGroup();
            Material material = new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(50, 20, 50, 50)));
            var meshBuilder = new MeshBuilder(false, false);
            meshBuilder.AddBox(new Point3D(x, y, z), boundsx+0.1, boundsy+0.1, boundsz+0.1);
            // Create a mesh from the builder (and freeze it)
            var Mesh = meshBuilder.ToMesh(true);
            marker.Children.Add(new GeometryModel3D { Geometry = Mesh, Material = material });
            this.Marker2 = marker;
            Image_blueprint.DataContext = "";
            Image_blueprint.DataContext = this;
        }

        private void OpenCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (openwindow != null && openwindow.IsLoaded)
            {
                openwindow.Focus();
            }
            else
            {
                openwindow = new OpenWindow(this);
                openwindow.Owner = this;
                openwindow.Show();
            }
            openwindow.TextBox_Search.Focus();
        }

        private void SaveCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)//possible to save/saveas?
        {
            e.CanExecute = false;
            if (BP.Blueprint != null) e.CanExecute = true;
        }

        private void SaveCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            button_overwrite_click(sender, e);
        }
        private void SaveAsCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            button_save_click(sender, e);
        }


        private void button_overwrite_click(object sender, RoutedEventArgs e)//save/overwrite
        {
            if (BP.Blueprint != null)
            {
                newtumbnail();
                BP.Description.name = TextBox_Name.Text;
                BP.Description.description = TextBox_Description.Text;
                BP.Save();
            }
        }
        private void button_save_click(object sender, RoutedEventArgs e)//save as
        {
            if (BP.Blueprint != null)
            {
                newtumbnail();
                BP.Description.name = TextBox_Name.Text;
                BP.Description.description = TextBox_Description.Text;
                Random r = new Random(); //GENERATE NEW UUID AND CHANGE DESCRIPTION LOCALID --todo
                BP.SaveAs("Blueprint" + r.Next() + "-" + r.Next());
            }
        }
        
        private void newtumbnail()
        {
            RenderTargetBitmap bmp = new RenderTargetBitmap(500, 500, 96, 96, PixelFormats.Pbgra32);
            bmp.Render(helix);
            Clipboard.SetImage(bmp);
            PngBitmapEncoder png = new PngBitmapEncoder();
            png.Frames.Add(BitmapFrame.Create(bmp));
            BP.Icon = png;
        }


        private void Click_advancedwiring(object sender, RoutedEventArgs e)
        {
            if (advancedconnections != null) advancedconnections.Close();
            advancedconnections = new AdvancedConnections(this);
            advancedconnections.Owner = this;
            advancedconnections.Show();
        }

        private void Click_blockproperties(object sender, RoutedEventArgs e)
        {
            if (blockProperties != null) blockProperties.Close();
            blockProperties = new BlockProperties(this);
            blockProperties.Owner = this;
            blockProperties.Show();
        }

        private void Click_areaproperties(object sender, RoutedEventArgs e)
        {
            if (areaProperties != null) areaProperties.Close();
            areaProperties = new AreaProperties(this);
            areaProperties.Owner = this;
            areaProperties.Show();
        }
        private void Click_blockpropertiesRAW(object sender, RoutedEventArgs e)
        {
            if (blockPropertiesRAW != null) blockPropertiesRAW.Close();
            blockPropertiesRAW = new BlockPropertiesRAW(this);
            blockPropertiesRAW.Owner = this;
            blockPropertiesRAW.Show();
        }

        private void Click_advancedcolor(object sender, RoutedEventArgs e)
        {//paint tool
            if (advancedcolorwindow != null) advancedcolorwindow.Close();
            advancedcolorwindow = new AdvancedColor(this);
            advancedcolorwindow.Owner = this;
            advancedcolorwindow.Show();
        }
        
        private void Click_fixcreation(object sender, RoutedEventArgs e)
        {
            dynamic blueprint = new JObject();

            blueprint.bodies = new JArray();
            blueprint.version = 1;
            blueprint.bodies.Add(new JObject());
            blueprint.bodies[0].childs = new JArray();

            //BP.Blueprint.joints = null;
            foreach (dynamic body in BP.Blueprint.bodies)
            {
                //remove bearings/springs/pistons
                foreach (dynamic child in body.childs)
                {
                    if (child.joints != null)
                        child.joints = null;
                    if (child.controller != null)
                    {
                        if (child.controller.joints != null)
                            child.controller.joints = null;
                        if (child.controller.controllers != null)
                            child.controller.controllers = null;
                    }
                    blueprint.bodies[0].childs.Add(child);
                }
            }
            BP.Description.description = BP.Description.description + "\n++ removed joints & glitchwelded";
            BP.setblueprint(blueprint);
            this.RenderBlueprint();
        }
        
        private void Click_swapblocks(object sender, RoutedEventArgs e)
        {
            if (swapblockswindow != null) swapblockswindow.Close();
            swapblockswindow = new SwapBlocksWindow(this);
            swapblockswindow.Owner = this;
            swapblockswindow.Show();
        }


        public static PaintSelector paintSelector;
        private void Click_paintpicker(object sender, RoutedEventArgs e) //paint picker
        {
            {
                paintSelector = new PaintSelector();
                paintSelector.Owner = this;
                paintSelector.Show();
                //MainWindow.openpainpicker();
            }
        }
        public void openpaintpicker()//opens the paintpicker if mainwindow doesn't have one open
        {
            
            if (paintSelector == null || !(paintSelector.IsActive || paintSelector.IsFocused || paintSelector.IsVisible))
            {
                paintSelector = new PaintSelector();
                paintSelector.Owner = this; //static function :(
                paintSelector.Show();
            }
        }
        

        private void Click_mirrormode(object sender, RoutedEventArgs e)//needs work
          {
            dynamic blueprint = BP.Blueprint;
            if (blueprint.joints == null)
            {
                foreach (dynamic body in blueprint.bodies)
                    foreach (dynamic block in body.childs)
                    {
                        {
                            dynamic realpos = BP.getposandbounds(block);
                            
                            int xaxis = Convert.ToInt32(block.xaxis);
                            int zaxis = Convert.ToInt32(block.zaxis);
                            if (!((xaxis == 1 && zaxis == -2) || (Math.Abs(xaxis) == 1 && Math.Abs(zaxis) == 3) || (xaxis == -1 && zaxis == 2)))
                            {
                                realpos.xaxis = -xaxis;
                                realpos.zaxis = Math.Abs( zaxis)==1? -zaxis : zaxis;

                            }
                            //Bounds bounds = Blockobject.BoundsByRotation(new Bounds(realpos.bounds),1,3);
                            realpos.pos.x = -Convert.ToInt32(block.pos.x) - ((realpos.pos.x == block.pos.x)? Convert.ToInt32(realpos.bounds.x) :0);
                            //realpos.pos.y = Convert.ToInt32(block.pos.y) - Convert.ToInt32(block.bounds.y);

                            block.pos = BP.calcbppos(realpos).pos;
                            block.xaxis = BP.calcbppos(realpos).xaxis;
                            block.zaxis = BP.calcbppos(realpos).zaxis;

                            //block.pos.x = -Convert.ToInt32(block.pos.x);
                            //works thus far for blocks, not parts tho

                            /*
                            if(Math.Abs(Convert.ToInt32(block.zaxis)) == 3 || Math.Abs(Convert.ToInt32(block.zaxis)) == 2)
                            {
                                block.xaxis = -Convert.ToInt32(block.xaxis);
                            }
                            if(Math.Abs(Convert.ToInt32(block.zaxis)) == 1)
                            {
                                block.zaxis = -Convert.ToInt32(block.zaxis);
                            }*/
                            /*block.pos.x = -Convert.ToInt32(block.pos.x);
                            if(Convert.ToInt32(block.xaxis) == 1 || Convert.ToInt32(block.xaxis) == -1)
                                block.xaxis = -Convert.ToInt32(block.xaxis);
                            else
                                block.zaxis = -Convert.ToInt32(block.zaxis);*/
                        }
                    }
                BP.setblueprint(blueprint);
                this.RenderBlueprint();
            }
            else
                MessageBox.Show("Mirror mode can't mirror blueprints with joints inside yet!");
            MessageBox.Show("Mirror mode did it's best to mirror things though there may be some parts that didn't turn out great.");

        }

        private void Click_ellipsoidgenerator(object sender, RoutedEventArgs e)
        {
            if (ellpisoid_generator != null) ellpisoid_generator.Close();
            ellpisoid_generator = new Ellipsoid_Generator(this);
            ellpisoid_generator.Owner = this;
            ellpisoid_generator.Show();

        }

        private void circlegenerator_Click(object sender, RoutedEventArgs e)
        {
            if (circle_generator != null) circle_generator.Close();
            circle_generator = new Circle_generator(this);
            circle_generator.Owner = this;
            circle_generator.Show();
        }

        private void Click_cuboidgenerator(object sender, RoutedEventArgs e)
        {
            if (cuboid_Generator != null) cuboid_Generator.Close();
            cuboid_Generator = new Cuboid_Generator(this);
            cuboid_Generator.Owner = this;
            cuboid_Generator.Show();
        }

        private void Click_requiredmods(object sender, RoutedEventArgs e)
        {
            
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://scrapmechanic.xesau.eu/uuidservice/get_mods");
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            string postData = "";
            foreach(string uuid in BP.GetUsedUuids())
            {
                postData+="&uuid[]=" + uuid;
            }
            postData = postData.Substring(1);

            byte[] bytes = Encoding.UTF8.GetBytes(postData);
            request.ContentLength = bytes.Length;

            Stream requestStream = request.GetRequestStream();
            requestStream.Write(bytes, 0, bytes.Length);

            WebResponse response = request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader reader = new StreamReader(stream);

            var result = reader.ReadToEnd();
            dynamic Mods = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(result);

            foreach (dynamic missingmod in Mods.missing)
            {
                if (Database.blocks.ContainsKey(missingmod.ToString()))
                {
                    string modid = System.IO.Path.GetFileName(Database.blocks[missingmod.ToString()].id.ToString());
                    dynamic mod = new JObject();
                    mod.name = Database.blocks[missingmod.ToString()].Mod;
                    mod.ok = "✔";
                    mod.author = "Unavailable, service couldn't find it";
                    mod.url = "http://steamcommunity.com/workshop/filedetails/?id=" + modid;

                    if(!((JArray)Mods.mods).Contains(mod))
                        Mods.mods.Add(mod);
                }
                else
                {
                    MessageBox.Show("couldn't find required mod for: " + missingmod.ToString());
                }
            }
            
            foreach (dynamic mod in Mods.mods)
            {
                string fileId = mod.url.ToString().Substring(51);
                if (Database.usedmods.ContainsKey(fileId))
                    mod.ok = "✔";
                else
                    if(mod.ok == null)
                        mod.ok = "X";
            }

            new required_mods(Mods).Show();

            stream.Dispose();
            reader.Dispose();
        }

        private void Notifications_Click(object sender, RoutedEventArgs e)
        {
            if (notificationWindow != null) notificationWindow.Close();
            notificationWindow = new NotificationWindow();
            notificationWindow.Owner = this;
            notificationWindow.Show();
        }

        private void Settings_Click(object sender, RoutedEventArgs e)
        {
            if (settings != null) settings.Close();
            settings = new Settings(this);
            settings.Owner = this;
            settings.Show();

        }

        private void Help_Click(object sender, RoutedEventArgs e)
        {
            MessageBoxResult result = MessageBox.Show("Need help?","",MessageBoxButton.YesNo);   
            if(result == MessageBoxResult.Yes)
            {
                System.Diagnostics.Process.Start("https://discord.gg/HXFqUqF");
            }
        }

        private void About_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("A tool that provides lots of awesome features for you to make blueprint editing fun and easy!\n" +
                "\nMade by <NAME> (youtube.com/c.brentbatch)\n'Required Mods'-feature: help by Xesau/Aaron\n\n" +
                "And a BIG thanks to all the testers: @GamerGuy, @iceboundGlaceon, @lmaster, @the_killerbanana, @ThePiGuy24Gaming, @Remynem, @xXTBR and @zOmbie1919nl.\n\n" +
                "Version: " + Properties.Settings.Default.version,"About");
        }

        private void Label_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if(TextBox_Description.Text == "Easter Egg")
            MessageBox.Show(@"                 /  \" + "\n" +
@"               / _ ^\" + "\n" +
@"              |  /  \  |" + "\n" +
@"              ||      ||  _______" + "\n" +
@"              ||      ||  |\          \" + "\n" +
@"              ||      ||  ||\          \" + "\n" +
@"              ||      ||  ||  \        |" + "\n" +
@"              ||      ||  ||    \__/" + "\n" +
@"              ||      ||  ||      ||" + "\n" +
@"                \\_/  \_/  \_//" + "\n" +
@"              /     _         _     \" + "\n" +
@"            /                           \" + "\n" +
@"            |       O         O      |" + "\n" +
@"            |      \    ___    /      |" + "\n" +
@"          /          \  \_/  /         \" + "\n" +
@"        /      -----    |    --\        \" + "\n" +
@"        |           \__/|\__/  \       |" + "\n" +
@"        \              |_|_|              /" + "\n" +
@"          \_____              _____/" + "\n" +
@"                      \          /" + "\n" +
@"                      |          |","Easter Egg!");
        }

        private void ObjToBlueprint_Click(object sender, RoutedEventArgs e)
        {
            new ObjToBlueprint(this) { Owner = this }.Show();
        }

        private void PixelArt_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("coming soon!","create 2d/3d pixelart, be able to import png");
        }

        private void Enable_Mode_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("coming soon!","Enable Mods, make certain mods invisible in features");
        }

        private void logicgenerator_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("coming soon!","Logic Diagram to Blueprint convertor");
        }

        private void midiconvertor_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("coming soon!", "import MIDI track, convert to blueprint");
        }

        private void mergecreation_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("coming soon!", "hold creation in ram, import new, merge");
        }

        private void gif3d_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("coming soon!", "import multiple blueprints, craft a 3dgif with them");
        }

        private void dupecreation_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("coming soon!", "stack/dupe creation in x/y/z");
        }

        private void listBox_parts_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }

        private void label_desc_Click(object sender, RoutedEventArgs e)
        {

            var bc = new BrushConverter();
            label_desc.Background = (Brush)bc.ConvertFrom("#FFFBD300");
            label_parts.Background = (Brush)bc.ConvertFrom("#FF61737C");
            TextBox_Description.Visibility = Visibility.Visible;
            listBox_parts.Visibility = Visibility.Hidden;
        }

        private void label_parts_Click(object sender, RoutedEventArgs e)
        {
            //thread:
            var bc = new BrushConverter();
            label_desc.Background = (Brush)bc.ConvertFrom("#FF61737C");
            label_parts.Background = (Brush)bc.ConvertFrom("#FFFBD300");
            TextBox_Description.Visibility = Visibility.Hidden;
            listBox_parts.Visibility = Visibility.Visible;
            fillparts();
        }
        Dictionary<string, Tuple<string, BitmapSource, int>> parts;
        public void fillparts()
        {
            var parts = BP.GetUsedPartsList();
            if (parts != null)
                if (!parts.Equals(this.parts) || true)
                {
                    new Thread(() =>
                    {
                        List<Part_listitem> part_Listitems = new List<Part_listitem>();
                        foreach (var uuid in parts.Keys)
                        {
                            part_Listitems.Add(new Part_listitem()
                            { name = parts[uuid].Item1, amount = parts[uuid].Item3.ToString(), uuid = uuid});
                        }
                        this.Dispatcher.Invoke((Action)(() =>
                        {
                            //listBox_parts.ItemsSource = null;
                            listBox_parts.ItemsSource = part_Listitems;
                        }));
                        ImageToBitmapSourceConverter converter = new ImageToBitmapSourceConverter();
                        foreach (Part_listitem item in part_Listitems)
                        {
                            var bmp = Database.blocks[item.uuid].GetIcon(item.uuid);
                            if(bmp != null)
                            {
                                item.icon = (BitmapSource)converter.Convert(bmp.Clone(),null, typeof(BitmapSource),null);
                                item.emptysurface = 0;
                                item.iconheight = 100;
                            }
                        }
                        this.Dispatcher.Invoke((Action)(() =>
                        {
                            listBox_parts.ItemsSource = null;
                            listBox_parts.ItemsSource = part_Listitems;
                        }));

                    }
                    ).Start();
                    this.parts = parts;
                }
        }

    }
    public class Part_listitem
    {
        public int emptysurface { get; set; } = 100;
        public int iconheight { get; set; } = 0;
        public BitmapSource icon { get; set; } = null;
        public string uuid { get; set; }
        public string name { get; set; } = "unnamed";
        public string amount { get; set; }
        public override string ToString()
        {
            return name + "\n" + amount;
        }
    }
}
<file_sep>﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for BlockPropertiesRAW.xaml
    /// </summary>
    public partial class BlockPropertiesRAW : Window
    {
        MainWindow mainwindow;
        HashSet<string> uuidsbackup = new HashSet<string>();
        dynamic blueprint;
        public BlockPropertiesRAW(MainWindow mainwindow)
        {
            this.mainwindow = mainwindow;
            InitializeComponent();
            Loadwindow w = new Loadwindow();
            w.Show();
            Update();

            w.Close();
        }
        private void button_help_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://discord.gg/HXFqUqF");
        }
        private void Filter_pos_TextChanged(object sender, RoutedEventArgs e)
        {
            TextBox t = (TextBox)sender;
            try
            {
                if (Convert.ToInt32(t.Text) >= 0) { }
            }
            catch
            {
                if (t.Text == "-")
                {
                    t.Text = "-0";
                    t.Select(1, 1);
                }
                else
                {
                    t.Text = "0";
                    t.Select(0, 1);
                }
            }
            if (this.IsLoaded)
                filterupdate();
        }
        private void filter_type_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.IsLoaded)
                filterupdate();
        }
        private void Filter_SET_Click(object sender, RoutedEventArgs e)
        {
            this.mainwindow.openpaintpicker();
            filter_color.Text = PaintSelector.PaintColor;
        }
        private void color_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox textbox_color = (TextBox)sender;
            if (textbox_color.Text.Length == 7)
            {
                try
                {
                    var bc = new BrushConverter();
                    string color = "#FF" + textbox_color.Text.Substring(1);
                    textbox_color.Background = (Brush)bc.ConvertFrom(color);
                    if (textbox_color.Name == "filter_color") filtercolor = textbox_color.Text.Substring(1, 6).ToLower();
                }
                catch
                {
                    //MessageBox.Show("Please use the right format\n \"#123abc\" where 1-9,a-f (hex)");
                    textbox_color.Text = "";
                }
            }
            else
            {
                var bc = new BrushConverter();
                textbox_color.Background = (Brush)bc.ConvertFrom("#eeeeee");
                if (textbox_color.Name == "filter_color") filtercolor = null;
            }
            if (textbox_color.Name == "filter_color")
                if (this.IsLoaded)
                    filterupdate();
        }
        public void Update()//new bp, items replaced, ... whatever
        {
            disableAll();
            blueprint = BP.Blueprint;
            if (filter_x1.Text == "" || uuidsbackup != BP.GetUsedUuids())
            {
                dynamic bounds = BP.GetBounds();
                filter_x1.Text = bounds.minx.ToString();
                filter_y1.Text = bounds.miny.ToString();
                filter_z1.Text = bounds.minz.ToString();
                filter_x2.Text = bounds.maxx.ToString();
                filter_y2.Text = bounds.maxy.ToString();
                filter_z2.Text = bounds.maxz.ToString();
            }
            if (uuidsbackup != BP.GetUsedUuids())//fill the combobox once
            {
                filter_type.Items.Clear();
                filter_type.Items.Add(new Item("any", "*"));
                foreach (string uuid in BP.GetUsedUuids())
                {
                    if (Database.blocks.ContainsKey(uuid))
                        filter_type.Items.Add(new Item(Database.blocks[uuid].Name.ToString(), uuid));
                }
                uuidsbackup.Clear();
                uuidsbackup.UnionWith(BP.GetUsedUuids());
                filter_type.SelectedIndex = 0;
            }
            filterupdate();
        }
        
        string filtercolor = null;

        Thread filter;
        private void filterupdate()
        {
            var l = new Loadwindow();
            l.Show();
            disableAll();
            filter_output.Items.Clear();
            if (Convert.ToInt32(filter_x1.Text) > Convert.ToInt32(filter_x2.Text))
            {
                string h = filter_x1.Text;
                filter_x1.Text = filter_x2.Text;
                filter_x2.Text = h;
            }
            if (Convert.ToInt32(filter_y1.Text) > Convert.ToInt32(filter_y2.Text))
            {
                string h = filter_y1.Text;
                filter_y1.Text = filter_y2.Text;
                filter_y2.Text = h;
            }
            if (Convert.ToInt32(filter_z1.Text) > Convert.ToInt32(filter_z2.Text))
            {
                string h = filter_z1.Text;
                filter_z1.Text = filter_z2.Text;
                filter_z2.Text = h;
            }
            int x1 = Convert.ToInt32(filter_x1.Text);
            int y1 = Convert.ToInt32(filter_y1.Text);
            int z1 = Convert.ToInt32(filter_z1.Text);
            int x2 = Convert.ToInt32(filter_x2.Text);
            int y2 = Convert.ToInt32(filter_y2.Text);
            int z2 = Convert.ToInt32(filter_z2.Text);
            this.mainwindow.setMarker2((x1 + x2 + 0.0f) / 2, (y1 + y2 + 0.0f) / 2, (z1 + z2 + 0.0f) / 2, (x2 - x1), (y2 - y1), (z2 - z1));
            string targetuuid = null;
            if (filter_type.SelectedIndex < 0) filter_type.SelectedIndex = 0;
            if (filter_type.SelectedIndex > 0)
                targetuuid = ((Item)filter_type.SelectedItem).UUID;


            //thread:
            if (filter != null && filter.IsAlive)
                filter.Abort();
            filter = new Thread(() =>
            {
                //filter correct blocks:
                int i = 0;
                foreach (dynamic body in blueprint.bodies)
                    foreach (dynamic child in body.childs)
                    {
                        if (child.color.ToString().StartsWith("#"))
                            child.color = child.color.ToString().Substring(1, 6).ToLower();
                        dynamic realpos = BP.getposandbounds(child);
                        if ((filtercolor == null || filtercolor == child.color.ToString()) &&
                            (targetuuid == null || targetuuid == child.shapeId.ToString()) &&
                            (x1 <= (int)realpos.pos.x && (int)realpos.pos.x + (int)realpos.bounds.x <= x2) &&
                            (y1 <= (int)realpos.pos.y && (int)realpos.pos.y + (int)realpos.bounds.y <= y2) &&
                            (z1 <= (int)realpos.pos.z && (int)realpos.pos.z + (int)realpos.bounds.z <= z2))
                        {
                            dynamic listitem = new JObject();
                            listitem.pos = new JObject();
                            listitem.pos.x = (int)realpos.pos.x;
                            listitem.pos.y = (int)realpos.pos.y;
                            listitem.pos.z = (int)realpos.pos.z;
                            listitem.bounds = new JObject();
                            listitem.bounds.x = (int)realpos.bounds.x;
                            listitem.bounds.y = (int)realpos.bounds.y;
                            listitem.bounds.z = (int)realpos.bounds.z;
                            listitem.blockname = "unnamed shape" + child.shapeId.ToString();
                            listitem.index = i;
                            if (Database.blocks.ContainsKey(child.shapeId.ToString()))
                                listitem.blockname = Database.blocks[child.shapeId.ToString()].Name;
                            listitem.color = child.color.ToString();
                            listitem.child = child.ToString();
                            this.Dispatcher.Invoke((Action)(() =>
                            {
                                filter_output.Items.Add(listitem);
                            }));
                        }
                        i++;
                    }
                if (blueprint.joints != null)
                    foreach (dynamic child in blueprint.joints)
                    {

                        if (child.color.ToString().StartsWith("#"))
                            child.color = child.color.ToString().Substring(1, 6).ToLower();
                        dynamic c = child;
                        c.pos = child.posA;
                        c.xaxis = child.xaxisA;
                        c.zaxis = child.zaxisA;
                        dynamic realpos = BP.getposandbounds(c);
                        realpos.pos = child.posA;
                        if (!(Convert.ToInt32(child.zaxis.ToString()) > 0 || !(realpos.bounds.x != 1 || realpos.bounds.y != 1 || realpos.bounds.z != 1)))
                        {
                            int zaxis = Convert.ToInt32(child.zaxis.ToString());
                            if (zaxis == -1)
                                realpos.pos.x -= realpos.bounds.x - 1;
                            if (zaxis == -2)
                                realpos.pos.y -= realpos.bounds.y - 1;
                            if (zaxis == -3)
                                realpos.pos.z -= realpos.bounds.z - 1;
                        }

                        if ((filtercolor == null || filtercolor == child.color.ToString()) &&
                            (targetuuid == null || targetuuid == child.shapeId.ToString()) &&
                            (x1 <= (int)realpos.pos.x && (int)realpos.pos.x + (int)realpos.bounds.x <= x2) &&
                            (y1 <= (int)realpos.pos.y && (int)realpos.pos.y + (int)realpos.bounds.y <= y2) &&
                            (z1 <= (int)realpos.pos.z && (int)realpos.pos.z + (int)realpos.bounds.z <= z2))
                        {
                            dynamic listitem = new JObject();
                            listitem.pos = new JObject();
                            listitem.pos.x = (int)realpos.pos.x;
                            listitem.pos.y = (int)realpos.pos.y;
                            listitem.pos.z = (int)realpos.pos.z;
                            listitem.bounds = new JObject();
                            listitem.bounds.x = (int)realpos.bounds.x;
                            listitem.bounds.y = (int)realpos.bounds.y;
                            listitem.bounds.z = (int)realpos.bounds.z;
                            listitem.blockname = "unnamed shape" + child.shapeId.ToString();
                            if (Database.blocks.ContainsKey(child.shapeId.ToString()))
                                listitem.blockname = Database.blocks[child.shapeId.ToString()].Name;
                            listitem.color = child.color.ToString();
                            listitem.child = child.ToString();
                            listitem.index = i;
                            this.Dispatcher.Invoke((Action)(() =>
                            {
                                filter_output.Items.Add(listitem);
                            }));
                        }
                        i++;
                    }
            });
            filter.IsBackground = true;
            filter.Start();
            l.Close();
        }
        private void filter_output_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if(filter_output.SelectedIndex>=0)
            {
                dynamic selected = ((dynamic)filter_output.SelectedItem);
                string child = selected.child.ToString();
                
                this.mainwindow.setMarker(Convert.ToInt32(selected.pos.x) + (Convert.ToDouble(selected.bounds.x) / 2), Convert.ToInt32(selected.pos.y) + (Convert.ToDouble(selected.bounds.y) / 2), Convert.ToDouble(selected.pos.z) + (Convert.ToDouble(selected.bounds.z) / 2));

                Edit_child.Text = child;

                button_render.IsEnabled = true;
            }
        }
        private void button_render_Click(object sender, RoutedEventArgs e)
        {
            //string blueprintstr = blueprint.ToString();
            //string child = ((dynamic)filter_output.SelectedItem).child.ToString();
            Loadwindow w = new Loadwindow();
            try
            {
                w.Show();
                dynamic child = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(Edit_child.Text);
                int i = 0;
                int index = ((dynamic)filter_output.SelectedItem).index;
                for (int j=0; j<blueprint.bodies.Count; j++)
                    for(int k=0; k<blueprint.bodies[j].childs.Count; k++)
                    {
                        if (index == i)
                        {
                            blueprint.bodies[j].childs[k] = child;
                            BP.setblueprint(blueprint);
                            BP.Description.description = BP.Description.description + "\n++Applied RAW changes";
                            mainwindow.RenderBlueprint();
                            //Update(); 
                            w.Close();
                            MessageBox.Show("edit successful");

                            filterupdate();
                            return;
                        }
                        i++;
                    }

                for (int j = 0; j < blueprint.joints.Count; j++)
                {
                    if (index == i)
                    {
                        blueprint.joints[j] = child;
                        BP.setblueprint(blueprint);
                        BP.Description.description = BP.Description.description + "\n++Applied RAW changes";
                        mainwindow.RenderBlueprint();
                        //Update();
                        w.Close();
                        MessageBox.Show("edit successful");
                        filterupdate();
                        return;
                    }
                    i++;
                }

                w.Close();
                MessageBox.Show("edit UNsuccessfull :(");
            }
            catch (Exception exc)
            {
                w.Close();
                MessageBox.Show(exc.Message);
            }
        }
        private void disableAll()
        {
            Edit_child.Text = "";
            button_render.IsEnabled = false;
            this.mainwindow.Marker = null;
            mainwindow.Image_blueprint.DataContext = "";
            mainwindow.Image_blueprint.DataContext = mainwindow;
        }
        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            base.OnClosing(e);
            this.mainwindow.Marker = null;
            this.mainwindow.Marker2 = null;
            mainwindow.Image_blueprint.DataContext = null;
            mainwindow.Image_blueprint.DataContext = mainwindow;
            this.mainwindow.helix.ResetCamera();
        }

    }
}
<file_sep>﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for SwapBlocksWindow.xaml
    /// </summary>
    public partial class SwapBlocksWindow : Window
    {
        MainWindow window;
        private dynamic uuidsbackup;
        private dynamic blockstoreplace;
        private dynamic replacebyblocks;
        public SwapBlocksWindow(MainWindow window)
        {
            this.window = window;
            InitializeComponent();
            Update();
        }


        public void Update()
        {
            if (uuidsbackup != BP.GetUsedUuids())
            {
                blockstoreplace = new JArray();
                replacebyblocks = new JArray();
                foreach (string uuid in BP.GetUsedUuids())
                {
                    if (Database.blocks.ContainsKey(uuid))
                    {
                        dynamic blok = new JObject();
                        blok.name = Database.blocks[uuid].Name;
                        blok.bounds = (Database.blocks[uuid] is Part)? ((Part)Database.blocks[uuid]).GetBoundsDynamic() : null;
                        blok.uuid = uuid;
                        blockstoreplace.Add(blok);
                    }
                }
                this.Dispatcher.Invoke((Action)(() =>
                {//this refer to form in WPF application 
                    comboBox_old.Items.Clear();
                    comboBox_new.Items.Clear();
                }));
                foreach (dynamic blok in blockstoreplace)
                {
                    this.Dispatcher.Invoke((Action)(() =>
                    {//this refer to form in WPF application 
                        comboBox_old.Items.Add(blok.name);
                    }));
                }
            }
            uuidsbackup = BP.GetUsedUuids();

        }

        private void textBox_color1_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox textbox_color = (TextBox)sender;
            if (textbox_color.Text.Length == 7)
            {
                try
                {
                    var bc = new BrushConverter();
                    string color = "#FF" + textbox_color.Text.Substring(1);
                    textbox_color.Background = (Brush)bc.ConvertFrom(color);
                }
                catch
                {
                    MessageBox.Show("Please use the right format\n \"#123abc\" where 1-9,a-f (hex)");
                }
            }
            else
            {
                var bc = new BrushConverter();
                textbox_color.Background = (Brush)bc.ConvertFrom("#eeeeee");
            }
        }

        private void comboBox_old_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            replacebyblocks = new JArray();
            comboBox_new.Items.Clear();
            if(comboBox_old.SelectedIndex>=0)
            {

                dynamic selectedblok = blockstoreplace[comboBox_old.SelectedIndex];

                var keys = Database.blocks.Keys;
                try
                {
                    foreach (string uuid in keys)
                    {
                        dynamic bounds = null;
                        if (Database.blocks[uuid] is Part)
                        {
                            bounds = ((Part)Database.blocks[uuid]).GetBoundsDynamic();
                        }

                        //if (bounds == null || (selectedblok.bounds != null && bounds == selectedblok.bounds))
                        {
                            dynamic block = new JObject();
                            block.name = Database.blocks[uuid].Name;
                            block.bounds = bounds;
                            block.uuid = uuid;
                            replacebyblocks.Add(block);
                            comboBox_new.Items.Add(block.name);
                        }

                    }
                }
                catch { }

            }
        }
        private void comboBox_new_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }

        private void button_set_Click(object sender, RoutedEventArgs e)
        {
            this.window.openpaintpicker();
            textBox_color1.Text = PaintSelector.PaintColor;
        }

        private void button_swap_Click(object sender, RoutedEventArgs e)
        {
            if(comboBox_new.SelectedIndex>-1&& comboBox_old.SelectedIndex > -1)
            {

                dynamic blocktoreplace = blockstoreplace[comboBox_old.SelectedIndex];
                dynamic replacebyblock = replacebyblocks[comboBox_new.SelectedIndex];
                int amountchanged = 0;
                dynamic blueprint = BP.Blueprint;
                foreach (dynamic body in blueprint.bodies)
                    foreach (dynamic child in body.childs)
                    {
                        if (child.shapeId == blocktoreplace.uuid && (textBox_color1.Text.ToString().ToLower() == child.color.ToString().ToLower() || textBox_color1.Text.ToString().ToLower() == "#"+child.color.ToString().ToLower() || textBox_color1.Text == "" || textBox_color1.Text =="#"))
                        {
                            if (child.bounds == null)
                            {
                                child.bounds = blocktoreplace.bounds;
                            }
                            child.shapeId = replacebyblock.uuid;
                            amountchanged++;
                        }
                    }

                string message = "++ " + amountchanged + " " + blocktoreplace.name + " are now changed to " + replacebyblock.name;
                MessageBox.Show(message);
                if (amountchanged > 0)
                {
                    BP.setblueprint(blueprint);
                    BP.Description.description = BP.Description.description + "\n" + message;
                    window.RenderBlueprint();
                }

            }
        }

        //get bounds from 
        private dynamic getbounds(dynamic part)
        {
            dynamic bounds = null;
            if (part.box != null)
            {
                return part.box;
            }
            if (part.hull != null)
            {
                bounds = new JObject();
                bounds.x = part.hull.x;
                bounds.y = part.hull.y;
                bounds.z = part.hull.z;
                return bounds;
            }
            if (part.cylinder != null)
            {
                if (part.cylinder.axis.ToString().ToLower() == "x")
                {
                    bounds = new JObject();
                    bounds.x = part.cylinder.depth;
                    bounds.y = part.cylinder.diameter * 2;
                    bounds.z = part.cylinder.diameter * 2;
                    return bounds;

                }
                else
                if (part.cylinder.axis.ToString().ToLower() == "y")
                {
                    bounds = new JObject();
                    bounds.x = part.cylinder.diameter * 2;
                    bounds.y = part.cylinder.depth;
                    bounds.z = part.cylinder.diameter * 2;
                    return bounds;

                }
                else
                if (part.cylinder.axis.ToString().ToLower() == "z")
                {
                    bounds = new JObject();
                    bounds.x = part.cylinder.diameter * 2;
                    bounds.y = part.cylinder.diameter * 2;
                    bounds.z = part.cylinder.depth;
                    return bounds;

                }
            }
            return bounds;
        }

    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for AdvancedConnections.xaml
    /// </summary>
    public partial class AdvancedConnections : Window
    {
        
        MainWindow mainwindow;
        private dynamic uuidsbackup;

        HashSet<Connectable> connectable_UUIDS = new HashSet<Connectable>();
        //List<Item> ItemList;
        public AdvancedConnections(MainWindow window)
        {
            this.mainwindow = window;
            InitializeComponent();
            this.Update();
        }

        public void Update()
        {
            if(uuidsbackup != BP.GetUsedUuids())
            {
                connectable_UUIDS.Clear();
                foreach (string uuid in BP.GetUsedUuids())
                {
                    if (Database.blocks.ContainsKey(uuid) && Database.blocks[uuid] is Part && (Database.blocks[uuid] as Part).IsConnectable)
                    {
                        connectable_UUIDS.Add(new Connectable(uuid.ToString(), ((Part)Database.blocks[uuid]).GetBoundsDynamic(), Database.blocks[uuid].Name));

                    }
                }
                this.Dispatcher.Invoke((Action)(() =>
                {//this refer to form in WPF application 
                    comboBox_items1.Items.Clear();
                    comboBox_items2.Items.Clear();
                }));
                foreach (Connectable i in connectable_UUIDS)
                {
                    this.Dispatcher.Invoke((Action)(() =>
                    {//this refer to form in WPF application 
                        comboBox_items1.Items.Add(i);
                        comboBox_items2.Items.Add(i);
                    }));
                }
            }
            uuidsbackup = BP.GetUsedUuids(); 
        }

        

        private void TextBox_color_TextChanged(object sender, TextChangedEventArgs e)
        {
            this.Update();
            TextBox textbox_color = (TextBox)sender;
            if (textbox_color.Text.Length == 7)
            {
                try
                {
                    var bc = new BrushConverter();
                    string color = "#FF" + textbox_color.Text.Substring(1);
                    textbox_color.Background = (Brush)bc.ConvertFrom(color);
                }
                catch
                {
                    MessageBox.Show("Please use the right format\n \"#123abc\" where 1-9,a-f (hex)");
                }
            }
            else
            {
                var bc = new BrushConverter();
                textbox_color.Background = (Brush)bc.ConvertFrom("#eeeeee");
            }
        }

        private void Button3_Click(object sender, RoutedEventArgs e)
        {
            this.mainwindow.openpaintpicker();
            textBox_color1.Text = PaintSelector.PaintColor;
        }

        private void Button3_Copy_Click(object sender, RoutedEventArgs e)
        {
            this.mainwindow.openpaintpicker();
            textBox_color2.Text = PaintSelector.PaintColor;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.Update();
            PaintSelector p = new PaintSelector
            {
                Owner = this.mainwindow
            };
            p.Show();
        }
        
        public struct Controller
        {
            public int id;
            public int x;
            public int y;
            public int z;
            public string color;
            public string uuid;
            public List<int> connections;
        }

        private void WireIt(dynamic a, string sourcecolor, string destinationcolor, string sourcetype, string destinationtype, int offsetx, int offsety, int offsetz, string offsetcolor )
        {
            
            Dictionary<int,Controller> controllers = new Dictionary<int, Controller>();
            bool dirx = checkBox_X.IsChecked == true;
            bool diry = checkBox_Y.IsChecked == true;
            bool dirz = checkBox_Z.IsChecked == true;
            bool self = checkBox_0.IsChecked == true;
            bool matchoffset = MatchOffset.IsChecked == true; //safemode enable?

            Dictionary<string, List<int>> filtercrap = new Dictionary<string, List<int>>();//can be glitchwelded
            //x.y.z = int

            foreach (dynamic body in BP.Blueprint.bodies)
                foreach (dynamic child in body.childs)
                    if (child.controller != null)
                    {
                        dynamic rpos = BP.getposandbounds(child);
                        int x = Convert.ToInt32(rpos.pos.x.ToString());
                        int y = Convert.ToInt32(rpos.pos.y.ToString());
                        int z = Convert.ToInt32(rpos.pos.z.ToString());
                        string color = child.color.ToString().ToLower();
                        if (color.StartsWith("#"))
                            color = color.Substring(1, 6);
                        int id = Convert.ToInt32(child.controller.id.ToString());
                        controllers.Add(id,new Controller {id= id, x = x, y = y, z = z, color = color, uuid = child.shapeId.ToString(), connections = new List<int>() });

                        string key = x.ToString() + "." + y.ToString() + "." + z.ToString();
                        if (!filtercrap.ContainsKey(key))
                            filtercrap.Add(key, new List<int> { id });
                        else
                            filtercrap[key].Add(id);
                    }

            if(matchoffset)
            {//filter only the block with color,type,offset from source
                foreach (Controller source in controllers.Values)
                    if ((sourcecolor == null || sourcecolor == source.color) && (sourcetype == source.uuid))
                        foreach (Controller destination in controllers.Values)
                            if((destinationcolor == null || destinationcolor == destination.color) && ( destinationtype == null || destinationtype == destination.uuid) && 
                                (self || !source.Equals(destination)) &&
                                (dirx || source.x+offsetx == destination.x) && (diry || source.y + offsety == destination.y) && (dirz || source.z + offsetz == destination.z))
                            {
                                source.connections.Add(destination.id);
                            }
            }
            else//filter all blocks no offset with col&type, then get the ones offset from them (any color, any type)
                foreach (Controller source in controllers.Values)
                    if ((sourcecolor == null || sourcecolor == source.color) && (sourcetype == source.uuid))
                        foreach (Controller destination in controllers.Values)
                            if ((destinationcolor == null || destinationcolor == destination.color) && (destinationtype == null || destinationtype == destination.uuid) &&
                                (self || !source.Equals(destination)) &&
                                (dirx || source.x == destination.x) && (diry || source.y == destination.y) && (dirz || source.z == destination.z))
                            {
                                string key = (offsetx+ destination.x).ToString() + "." + (offsety + destination.y).ToString() + "." + (offsetz + destination.z).ToString();
                                //get block offset from destination 
                                if (filtercrap.ContainsKey(key))
                                    source.connections.AddRange(filtercrap[key]);
                                //source.connections.Add(destination.id);
                            }

            //apply controllers to bp:

            int amountwired = 0;
            foreach (dynamic body in BP.Blueprint.bodies)
                foreach (dynamic child in body.childs)
                    if (child.controller != null && controllers.ContainsKey(Convert.ToInt32(child.controller.id.ToString())))
                    {
                        int id = Convert.ToInt32(child.controller.id.ToString());
                        if (child.controller.controllers == null)
                            child.controller.controllers = new JArray();
                        if(controllers[id].connections != null)
                            foreach (int destid in controllers[id].connections)
                            {
                                child.controller.controllers.Add(new JObject { ["id"] = destid });
                                amountwired++;
                            }
                    }

            new System.Threading.Thread(new System.Threading.ThreadStart(() => {
                    MessageBox.Show("Successfully made " + amountwired + " connections! :D");
            })).Start();

            if (amountwired > 0)
            {
                mainwindow.TextBox_Description.Text += "\n--> " + amountwired + " connections made\n";
                BP.Description.description = BP.Description.description + "\n--> " + amountwired + " connections made\n";
            }

            mainwindow.RenderWires();
            #region somecode
            /*
            dynamic controllersold = new JObject();

            dynamic sources = new JObject();

            foreach (dynamic body in blueprint.bodies)
                foreach (dynamic child in body.childs)
                {
                    if (child.controller != null)
                    {
                        dynamic rpos = BP.getposandbounds(child);
                        string x = rpos.pos.x.ToString();
                        string y = rpos.pos.y.ToString();
                        string z = rpos.pos.z.ToString();
                        string color = child.color.ToString();
                        if (color.StartsWith("#"))
                            color = color.Substring(1, 6);
                        //child.shapeId.ToString()
                        // Convert.ToInt32(child.controller.id.ToString())
                        dynamic controller = new JObject { [x] = new JObject { [y] = new JObject { [z] = new JObject { [child.color.ToString()] = new JObject { [child.shapeId.ToString()] = new JObject { [color] = Convert.ToInt32(child.controller.id.ToString()) } } } } } };
                        controllersold.Merge(controller);
                        if ((sourcecolor == null || sourcecolor == color) && (sourcetype == null || sourcetype == child.shapeId.ToString()))
                            sources.Merge(controller);
                    }
                }


            dynamic result = new JObject();//result.DeepClone();
            //Newtonsoft.Json.Linq.JProperty // keypair

            if (matchoffset) //ON
            {//filter only the block with color,type,offset from source
                dynamic searchfrom = controllersold.DeepClone();
                if (dirx)
                {
                    result = searchfrom;
                }
                else
                {
                    foreach(JProperty Jprop in sources) //Jprop.Name = "X"
                    {
                        string coord = (Convert.ToInt32(Jprop.Name) + offsetx).ToString();
                        if (searchfrom[coord] != null)
                        {
                            result.Merge(new JObject { [coord] = searchfrom[coord] });
                        }
                    }
                }

                searchfrom = result.DeepClone();
                result = new JObject();
                if (diry)
                {
                    result = searchfrom;
                }
                else
                {
                    foreach (JProperty JpropSource in sources) 
                    {
                        string coord = (Convert.ToInt32(JpropSource.Name) + offsetx).ToString();
                        if (searchfrom[coord] != null)
                        {
                            result.Merge(new JObject { [coord] = searchfrom[coord] });
                        }
                    }
                }
            }
            else
            {//filter all blocks no offset with col&type, then get the ones offset from them (any color, any type)

            }


            foreach (dynamic body in blueprint.bodies)
                foreach(dynamic child in body.childs)
                {
                    if(child.controller != null && (sourcetype == null || sourcetype == child.shapeId.ToString()))
                    {
                        string color = child.color.ToString(); if (color.StartsWith("#")) color = color.Substring(1, 6);
                        if(sourcecolor == null || color == sourcecolor)
                        {
                            dynamic rpos = BP.getposandbounds(child);
                            int x = Convert.ToInt32(rpos.pos.x.ToString());
                            int y = Convert.ToInt32(rpos.pos.y.ToString());
                            int z = Convert.ToInt32(rpos.pos.z.ToString());



                        }
                    }
                }




            if (blueprint == "")//false
            using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.scrapshitConnectionString))
            {
                //conn.ConnectionString = "MyDB";c
                int i = 0;
                conn.Open();
                using (SqlCommand insertCommand = new SqlCommand("DELETE FROM Connections", conn))
                {
                    insertCommand.ExecuteNonQuery();
                }
                foreach (dynamic body in blueprint.bodies)
                    foreach (dynamic child in body.childs)
                    {
                        if(child.controller != null)
                        {
                            dynamic rpos = BP.getposandbounds(child);
                            string x = rpos.pos.x.ToString();
                            string y = rpos.pos.y.ToString();
                            string z = rpos.pos.z.ToString();
                            string color = child.color.ToString();
                            if (color.StartsWith("#"))
                                color = color.Substring(1, 6);

                            using (SqlCommand insertCommand = new SqlCommand("INSERT INTO Connections (Controller_Id, posx, posy, posz, color, uuid) VALUES (@controllerid, @x, @y, @z, @color, @uuid)", conn))
                            {
                                insertCommand.Parameters.AddWithValue("@controllerid", Convert.ToInt32(child.controller.id.ToString()));
                                insertCommand.Parameters.AddWithValue("@x", x);
                                insertCommand.Parameters.AddWithValue("@y", y);
                                insertCommand.Parameters.AddWithValue("@z", z);
                                insertCommand.Parameters.AddWithValue("@color", color);
                                insertCommand.Parameters.AddWithValue("@uuid", child.shapeId.ToString());
                                try
                                {
                                    i+= insertCommand.ExecuteNonQuery();
                                }
                                catch (Exception e)
                                {
                                    MessageBox.Show(e.Message);
                                }

                            }
                        }
                    }



                //SqlCommand cmd = new SqlCommand("SELECT * FROM Connections WHERE login = @login", conn);

                //find all sources  "SELECT * AS 'Sources' FROM Connections" + "WHERE color = @sourcecolor AND uuid = @sourceuuid"
                //find all dests?


                //string cmd = "SELECT * FROM Description"
                //cmd+= "Where uuid = @uuid"
                //cmd+= @"AND color = @color"

                //all with uuid x / other / all other (match offset block color)
                //all with color / all other  / all other (match offset block color)
                //all with x + offsetx / other(all in this dir) /x
                //all with y + offsety / other / y
                //all with z + offsetz /other / z
                //exclude self wire?
                //if match offset block color search offset from  x y z found blocks (from all, check all current found + offset with color x and type x)

            }



            //<x, y, z, color, shapeId>, controllerid
            Dictionary<Tuple<int, int, int, string, string>, int> dict = new Dictionary<Tuple<int, int, int, string, string>, int>();

            Dictionary<int, Dictionary<int, Dictionary<int, int>>> testdict = new Dictionary<int, Dictionary<int, Dictionary<int, int>>>();
            //testdict[5][2][3] = 5;

            */
            #endregion
        }



        //Wire it!
        private void Button1_Click(object sender, RoutedEventArgs e)
        {//WIRE IT!
            if(comboBox_items1.SelectedIndex!=-1 && comboBox_items2.SelectedIndex != -1 && BP.Blueprint != null)
            {
                dynamic backupbp = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(BP.Blueprint.ToString());
                string sourcecolor = textBox_color1.Text.ToLower();
                string destinationcolor = textBox_color2.Text.ToLower();
                Connectable sourceblock = (Connectable) comboBox_items1.SelectedItem;
                Connectable destinationblock = (Connectable) comboBox_items2.SelectedItem;

                int offsetx = Convert.ToInt32(textBox_X.Text);
                int offsety = Convert.ToInt32(textBox_Y.Text);
                int offsetz = Convert.ToInt32(textBox_Z.Text);

                if (sourcecolor.Length == 7)
                    sourcecolor = sourcecolor.Substring(1, 6);
                else
                    sourcecolor = null;
                if (destinationcolor.Length == 7)
                    destinationcolor = destinationcolor.Substring(1, 6);
                else
                    destinationcolor = null;
                //try
                {
                    WireIt(null, sourcecolor, destinationcolor, sourceblock.UUID, destinationblock.UUID, offsetx, offsety, offsetz, destinationcolor);
                }
                //catch (Exception ex)
                {
                  //  MessageBox.Show(ex.Message + "\n\n Blueprint connections abrupted\nrestoring blueprint", "ERROR");
                    //BP.setblueprint(backupbp);
                }
                
                if(false)
                {

                #region oldcode
                //list all destionationblocks and their ID's
                dynamic destids = new JObject();
                int minx = 10000, maxx = -10000, miny = 10000, maxy = -10000, minz = 10000, maxz = -10000;
                //loop over all blocks:
                foreach (dynamic body in BP.Blueprint.bodies)
                {
                    foreach(dynamic child in body.childs)
                    {
                        if(child.shapeId.Value.ToLower() == destinationblock.UUID.ToLower() /*&& (child.color.Value.ToLower() == destinationcolor.ToLower() || "#"+child.color.Value.ToLower() == destinationcolor.ToLower() || destinationcolor == "" || destinationcolor == "#")*/)
                        {
                            dynamic dest = BP.getposandbounds(child);//outputs corrected child (default rotation, correct position)

                            string x = dest.pos.x.ToString();
                            string y = dest.pos.y.ToString();
                            string z = dest.pos.z.ToString();

                            if (destids[x] == null)
                                destids[x] = new JObject();
                            if (destids[x][y] == null)
                                destids[x][y] = new JObject();
                            if (destids[x][y][z] == null)
                                destids[x][y][z] = new JObject();
                            if (destids[x][y][z].ids == null)
                                destids[x][y][z].ids = new JArray();
                            dynamic id = new JObject();
                            id.id = child.controller.id;
                            destids[x][y][z].ids.Add(id);
                            destids[x][y][z].color = child.color;

                            //get whole creation bounds:
                            if (dest.pos.x < minx) minx = dest.pos.x;
                            if (dest.pos.x > maxx) maxx = dest.pos.x;
                            if (dest.pos.y < miny) miny = dest.pos.y;
                            if (dest.pos.y > maxy) maxy = dest.pos.y;
                            if (dest.pos.z < minz) minz = dest.pos.z;
                            if (dest.pos.z > maxz) maxz = dest.pos.z;
                           /* {//test
                                if (destids[x + "." + y + "." + z] == null) destids[x + "." + y + "." + z] = new JArray();
                                dynamic blockproperties = new JObject();
                                blockproperties.id = new JObject();
                                blockproperties.id.id = child.controller.id;
                                blockproperties.uuid = child.shapeId;
                                if (child.color.ToString().StartsWith("#")) child.color = child.color.ToString().subString(1);
                                blockproperties.color = child.color;
                                destids[x + "." + y + "." + z].Add(blockproperties);
                            }*/
                        }
                    }
                }
                if(BP.Blueprint.joints != null)
                foreach(dynamic child in BP.Blueprint.joints)
                {
                    if (child.shapeId.Value.ToLower() == destinationblock.UUID.ToLower() /*&& (child.color.Value.ToLower() == destinationcolor.ToLower() || "#"+child.color.Value.ToLower() == destinationcolor.ToLower() || destinationcolor == "" || destinationcolor == "#")*/)
                    {
                        dynamic dest = (child);//outputs corrected child (default rotation, correct position)

                        string x = dest.pos.x.ToString();
                        string y = dest.pos.y.ToString();
                        string z = dest.pos.z.ToString();

                        if (destids[x] == null)
                            destids[x] = new JObject();
                        if (destids[x][y] == null)
                            destids[x][y] = new JObject();
                        if (destids[x][y][z] == null)
                            destids[x][y][z] = new JObject();
                        if (destids[x][y][z].ids == null)
                            destids[x][y][z].ids = new JArray();
                        dynamic id = new JObject();
                        id.id = child.controller.id;
                        destids[x][y][z].ids.Add(id);
                        destids[x][y][z].color = child.color;

                        //get whole creation bounds:
                        if (dest.pos.x < minx) minx = dest.pos.x;
                        if (dest.pos.x > maxx) maxx = dest.pos.x;
                        if (dest.pos.y < miny) miny = dest.pos.y;
                        if (dest.pos.y > maxy) maxy = dest.pos.y;
                        if (dest.pos.z < minz) minz = dest.pos.z;
                        if (dest.pos.z > maxz) maxz = dest.pos.z;
                    }

                }

                int amountwired=0;
                try
                {
                    //can be improved!

                    foreach(dynamic body in BP.Blueprint.bodies)
                        foreach(dynamic child in body.childs)
                            if (child.shapeId.Value.ToLower() == sourceblock.UUID.ToLower() && (child.color.Value.ToLower() == sourcecolor.ToLower() || "#" + child.color.Value.ToLower() == sourcecolor.ToLower() || sourcecolor == "" || sourcecolor == "#"))
                            {//COLOR AND UUID CORRECT, FURTHER WIRING PROCESS:
                                dynamic source = BP.getposandbounds(child);//outputs corrected child (default rotation, correct position)

                                string x = source.pos.x.ToString();
                                string y = source.pos.y.ToString();
                                string z = source.pos.z.ToString();

                                if (checkBox_X.IsChecked == false)
                                {
                                    minx = source.pos.x;
                                    maxx = source.pos.x;//bounds?
                                }
                                if (checkBox_Y.IsChecked == false)
                                {
                                    miny = source.pos.y;
                                    maxy = source.pos.y;
                                }
                                if (checkBox_Z.IsChecked == false)
                                {
                                    minz = source.pos.z;
                                    maxz = source.pos.z;
                                }

                                string color = child.color.ToString();
                                if (color.StartsWith("#"))
                                    color.Substring(1, 6);
                                for (int i = minx; i <= maxx; i++)
                                    if (destids[i.ToString()] != null)
                                        for (int j = miny; j <= maxy; j++)
                                            if (destids[i.ToString()][j.ToString()] != null)
                                                for (int k = minz; k <= maxz; k++)
                                                    if (destids[i.ToString()][j.ToString()][k.ToString()] != null)
                                                        if (destids[i.ToString()][j.ToString()][k.ToString()].color.ToString().ToLower() == destinationcolor.ToLower() || "#" + destids[i.ToString()][j.ToString()][k.ToString()].color.ToString().ToLower() == destinationcolor.ToLower() || destinationcolor == "" || destinationcolor == "#")
                                                            if (destids[(i+ Convert.ToInt32(textBox_X.Text)).ToString()] !=null && destids[(i + Convert.ToInt32(textBox_X.Text)).ToString()][(j + Convert.ToInt32(textBox_Y.Text)).ToString()] != null && destids[(i + Convert.ToInt32(textBox_X.Text)).ToString()][(j + Convert.ToInt32(textBox_Y.Text)).ToString()][(k + Convert.ToInt32(textBox_Z.Text)).ToString()] != null)
                                                                foreach (dynamic id in destids[(i + Convert.ToInt32(textBox_X.Text)).ToString()][(j + Convert.ToInt32(textBox_Y.Text)).ToString()][(k + Convert.ToInt32(textBox_Z.Text)).ToString()].ids)
                                                                    if (!(checkBox_0.IsChecked == false && child.controller.id == id.id))
                                                                    {
                                                                        if (child.controller.controllers == null)
                                                                            child.controller.controllers = new JArray();
                                                                        child.controller.controllers.Add(id);
                                                                        amountwired++;
                                                                    }

                                /*
                                for (int i = minx; i <= maxx; i++)
                                    for (int j = miny; j <= maxy; j++)
                                        for (int k = minz; k <= maxz; k++)
                                            if (
                                                destids[i.ToString() + "." + j.ToString() + "." + k.ToString()] != null &&
                                                destids[(i + Convert.ToInt32(textBox_X.Text)).ToString() + "." +
                                                        (j + Convert.ToInt32(textBox_Y.Text)).ToString() + "." +
                                                        (k + Convert.ToInt32(textBox_Z.Text)).ToString()] != null
                                                )
                                                foreach ( dynamic destblocknooffset in destids[i.ToString() + "." + j.ToString() + "." + k.ToString()])
                                                    if((destblocknooffset.color.ToLower() == destinationcolor.ToLower() || destinationcolor == "" || destinationcolor == "#"))
                                                        foreach(dynamic blockoffset in destids[(i + Convert.ToInt32(textBox_X.Text)).ToString() + "." + (j + Convert.ToInt32(textBox_Y.Text)).ToString() + "." + (k + Convert.ToInt32(textBox_Z.Text)).ToString()])
                                                            if(!(checkBox_0.IsChecked == false && child.controller.id == blockoffset.id.id))
                                                            {
                                                                if (child.controller.controllers == null)
                                                                    child.controller.controllers = new JArray();
                                                                child.controller.controllers.Add(blockoffset.id);
                                                                amountwired++;
                                                            }
                                */

                                mainwindow.Image_blueprint.DataContext = null;
                                mainwindow.Image_blueprint.DataContext = mainwindow;
                            }

                    new System.Threading.Thread(new System.Threading.ThreadStart(() => {
                        if(Properties.Settings.Default.wires)
                            MessageBox.Show("Successfully made " + amountwired + " connections! :D\n\n'Wires'-feature will render wires upon load from openwindow->needs work");
                        else
                            MessageBox.Show("Successfully made " + amountwired + " connections! :D");
                    })).Start();
                    
                    //window.UpdateOpenedBlueprint();
                    if (amountwired>0)
                        BP.Description.description = BP.Description.description + "\n--> " + amountwired + " connections made between " + sourcecolor + " " + sourceblock.name + " and " + destinationcolor + " " + destinationblock.name;
                   
                }
                catch(Exception exception)
                {
                    MessageBox.Show(exception.Message+"\n\n Blueprint connections abrupted\nrestoring blueprint","ERROR");
                    BP.setblueprint(backupbp);
                }
                    #endregion

                }
            }
            else
            {
                MessageBox.Show("Something went wrong!\nno harm done");
            }




        }

        

        private void Button2_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://youtu.be/glLgQemUS2I?t=270");
        }//help

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox t = (TextBox)sender;
            try
            {
                if (Convert.ToInt32(t.Text) >= 0) { }
            }
            catch
            {
                if (t.Text == "-")
                {
                    t.Text = "-0";
                    t.Select(1, 1);
                }
                else
                {
                    t.Text = "0";
                    t.Select(0, 1);
                }
            }
        }


        //
    }
    public class Connectable
    {
        public string name = "unnamed block";
        public string UUID;
        public dynamic bounds;

        public Connectable(string UUID, dynamic bounds)
        {
            this.UUID = UUID;
            this.bounds = bounds;
        }
        public Connectable(string UUID, dynamic bounds, string name)
        {
            this.UUID = UUID;
            this.bounds = bounds;
            this.name = name;
        }

        public override string ToString()
        {
            return name;
        }
    }
    

}
<file_sep>﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using static Advanced_Blueprint_Tools.Part;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for AreaProperties.xaml
    /// </summary>
    public partial class AreaProperties : Window
    {
        MainWindow mainwindow; 
        HashSet<string> uuidsbackup = new HashSet<string>();
        public AreaProperties(MainWindow mainwindow)
        {
            this.mainwindow = mainwindow;
            InitializeComponent();
            Loadwindow w = new Loadwindow();
            w.Show();
            Update();

            w.Close();
        }

        private void Button_Help_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://discord.gg/HXFqUqF"); 
        }

        private void Filter_pos_TextChanged(object sender, RoutedEventArgs e)
        {
            TextBox t = (TextBox)sender;
            try
            {
                if (Convert.ToInt32(t.Text) >= 0) { }
            }
            catch
            {
                if (t.Text == "-")
                {
                    t.Text = "-0";
                    t.Select(1, 1);
                }
                else
                {
                    t.Text = "0";
                    t.Select(0, 1);
                }
            }
            if (this.IsLoaded)
            {
                int x1 = Convert.ToInt32(filter_x1.Text);
                int y1 = Convert.ToInt32(filter_y1.Text);
                int z1 = Convert.ToInt32(filter_z1.Text);
                int x2 = Convert.ToInt32(filter_x2.Text);
                int y2 = Convert.ToInt32(filter_y2.Text);
                int z2 = Convert.ToInt32(filter_z2.Text);
                this.mainwindow.setMarker2((x1 + x2 + 0.0f) / 2, (y1 + y2 + 0.0f) / 2, (z1 + z2 + 0.0f) / 2, (x2 - x1), (y2 - y1), (z2 - z1));
            }
        }
        private void filter_type_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.IsLoaded)
                filterupdate();
        }
        private void Filter_SET_Click(object sender, RoutedEventArgs e)
        {
            this.mainwindow.openpaintpicker();
            filter_color.Text = PaintSelector.PaintColor;
        }
        private void color_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox textbox_color = (TextBox)sender;
            if (textbox_color.Text.Length == 7)
            {
                try
                {
                    var bc = new BrushConverter();
                    string color = "#FF" + textbox_color.Text.Substring(1);
                    textbox_color.Background = (Brush)bc.ConvertFrom(color);
                    if (textbox_color.Name == "filter_color") filtercolor = textbox_color.Text;
                }
                catch
                {
                    //MessageBox.Show("Please use the right format\n \"#123abc\" where 1-9,a-f (hex)");
                    textbox_color.Text = "";
                }
            }
            else
            {
                var bc = new BrushConverter();
                textbox_color.Background = (Brush)bc.ConvertFrom("#eeeeee");
                if (textbox_color.Name == "filter_color") filtercolor = null;
            }
            if (textbox_color.Name == "filter_color")
                if (this.IsLoaded)
                    filterupdate();
        }

        public void Update()//new bp, items replaced, ... whatever
        {
            disableAll();
            if (filter_x1.Text == "" || uuidsbackup != BP.GetUsedUuids())
            {
                dynamic bounds = BP.GetBounds();
                filter_x1.Text = bounds.minx.ToString();
                filter_y1.Text = bounds.miny.ToString();
                filter_z1.Text = bounds.minz.ToString();
                filter_x2.Text = bounds.maxx.ToString();
                filter_y2.Text = bounds.maxy.ToString();
                filter_z2.Text = bounds.maxz.ToString();
            }
            if (uuidsbackup != BP.GetUsedUuids() | true)//fill the combobox once
            {
                filter_type.Items.Clear();
                filter_type.Items.Add(new Item("any","*"));
                foreach (string uuid in BP.GetUsedUuids())
                {
                    if (Database.blocks.ContainsKey(uuid))
                        filter_type.Items.Add(new Item(Database.blocks[uuid].Name.ToString(), uuid));
                }
                uuidsbackup.Clear();
                uuidsbackup.UnionWith(BP.GetUsedUuids());
                filter_type.SelectedIndex = 0;
            }
            filterupdate();
        }

        private string filtercolor = null;
        private void filterupdate() // enable specific boxes
        {
            disableAll();
            if (filter_type.SelectedIndex>0)
            {
                string uuid = ((Item)filter_type.SelectedItem).UUID.ToString();
                if(Database.blocks.ContainsKey(uuid) && Database.blocks[uuid] is Part)
                {
                    properties property = ((Part)Database.blocks[uuid]).GetProperty();
                    if (property == properties.sensor)
                        Edit_sensor.Visibility = Visibility.Visible;
                    if (property == properties.spotlight)
                        Edit_lamp.Visibility = Visibility.Visible;
                    if (property == properties.logic)
                        Edit_gate.Visibility = Visibility.Visible;
                    if (property == properties.timer)
                        Edit_Timer.Visibility = Visibility.Visible;
                }

            }
            Edit_general.Visibility = Visibility.Visible;
            int x1 = Convert.ToInt32(filter_x1.Text);
            int y1 = Convert.ToInt32(filter_y1.Text);
            int z1 = Convert.ToInt32(filter_z1.Text);
            int x2 = Convert.ToInt32(filter_x2.Text);
            int y2 = Convert.ToInt32(filter_y2.Text);
            int z2 = Convert.ToInt32(filter_z2.Text);
            this.mainwindow.setMarker2((x1 + x2 + 0.0f) / 2, (y1 + y2 + 0.0f) / 2, (z1 + z2 + 0.0f) / 2, (x2 - x1), (y2 - y1), (z2 - z1));

            button_render.IsEnabled = true;
        }

        private void button_render_Click(object sender, RoutedEventArgs e)
        {
            //apply changes
            if (Convert.ToInt32(filter_x1.Text) > Convert.ToInt32(filter_x2.Text))
            {
                string h = filter_x1.Text;
                filter_x1.Text = filter_x2.Text;
                filter_x2.Text = h;
            }
            if (Convert.ToInt32(filter_y1.Text) > Convert.ToInt32(filter_y2.Text))
            {
                string h = filter_y1.Text;
                filter_y1.Text = filter_y2.Text;
                filter_y2.Text = h;
            }
            if (Convert.ToInt32(filter_z1.Text) > Convert.ToInt32(filter_z2.Text))
            {
                string h = filter_z1.Text;
                filter_z1.Text = filter_z2.Text;
                filter_z2.Text = h;
            }
            int x1 = Convert.ToInt32(filter_x1.Text);
            int y1 = Convert.ToInt32(filter_y1.Text);
            int z1 = Convert.ToInt32(filter_z1.Text);
            int x2 = Convert.ToInt32(filter_x2.Text);
            int y2 = Convert.ToInt32(filter_y2.Text);
            int z2 = Convert.ToInt32(filter_z2.Text);
            string targetuuid = null;
            if (filter_type.SelectedIndex < 0) filter_type.SelectedIndex = 0;
            if (filter_type.SelectedIndex > 0)
                targetuuid = ((Item)filter_type.SelectedItem).UUID;


            dynamic blueprint = BP.Blueprint;
            if (filtercolor != null&& filtercolor.StartsWith("#"))
                filtercolor = filtercolor.Substring(1, 6).ToLower();

            foreach(dynamic body in blueprint.bodies)
                foreach(dynamic child in body.childs)
                {
                    if (child.color.ToString().StartsWith("#"))
                        child.color = child.color.ToString().Substring(1, 6).ToLower();
                    dynamic realpos = BP.getposandbounds(child);
                    if((filtercolor == null || filtercolor == child.color.ToString()) &&
                        (targetuuid == null || targetuuid == child.shapeId.ToString()) &&
                        (x1 <= (int)realpos.pos.x && (int)realpos.pos.x + (int)realpos.bounds.x <= x2) &&
                        (y1 <= (int)realpos.pos.y && (int)realpos.pos.y + (int)realpos.bounds.y <= y2) &&
                        (z1 <= (int)realpos.pos.z && (int)realpos.pos.z + (int)realpos.bounds.z <= z2) )
                    {
                        child.pos.x = child.pos.x + Convert.ToInt32(new_x.Text);
                        child.pos.y = child.pos.y + Convert.ToInt32(new_y.Text);
                        child.pos.z = child.pos.z + Convert.ToInt32(new_z.Text);

                        if (new_color.Text != "")
                            child.color = new_color.Text.ToString().Substring(1, 6);
                        if (Edit_gate.IsVisible && new_gatemode.SelectedIndex > 0)
                            child.controller.mode = new_gatemode.SelectedIndex - 1;
                        if(Edit_lamp.IsVisible)
                        {
                            if (new_luminance.Text != "") child.controller.luminance = Convert.ToInt32(new_luminance.Text);
                            if (new_coneangle.Text != "") child.controller.coneAngle = Convert.ToInt32(new_coneangle.Text);
                            if (new_lampcolor.Text != "") child.controller.color = new_lampcolor.Text;
                        }
                        if(Edit_sensor.IsVisible && (new_sensorrange.Text != "" || new_sensorcolormode.IsChecked==true))
                        {
                            if (new_sensorrange.Text != "")
                                child.controller.range = Convert.ToInt32(new_sensorrange.Text);

                            child.controller.colorMode = new_sensorcolormode.IsChecked==true?true:false;
                            child.controller.color = new_sensorcolor.Text;
                        }
                        if(Edit_Timer.IsVisible && new_timerseconds.Text != null)
                        {
                            child.controller.seconds = Convert.ToInt32(new_timerseconds.Text);
                            child.controller.ticks = Convert.ToInt32(new_timerticks.Text);
                        }

                    }
                }
            if(blueprint.joints != null)
            foreach (dynamic child in blueprint.joints)
            {

                if (child.color.ToString().StartsWith("#"))
                    child.color = child.color.ToString().Substring(1, 6);
                dynamic c = child;
                c.pos = child.posA;
                c.xaxis = child.xaxisA;
                c.zaxis = child.zaxisA;
                dynamic realpos = BP.getposandbounds(c);
                realpos.pos = child.posA;
                if (!(Convert.ToInt32(child.zaxis.ToString())>0 || !(realpos.bounds.x != 1 || realpos.bounds.y != 1 || realpos.bounds.z != 1)))
                {
                    int zaxis = Convert.ToInt32(child.zaxis.ToString());
                    if (zaxis == -1)
                        realpos.pos.x -= realpos.bounds.x - 1;
                    if (zaxis == -2)
                        realpos.pos.y -= realpos.bounds.y - 1;
                    if (zaxis == -3)
                        realpos.pos.z -= realpos.bounds.z - 1;
                }

                if ((filtercolor == null || filtercolor == child.color.ToString()) &&
                    (targetuuid == null || targetuuid == child.shapeId.ToString()) &&
                    (x1 <= (int)realpos.pos.x && (int)realpos.pos.x + (int)realpos.bounds.x <= x2) &&
                    (y1 <= (int)realpos.pos.y && (int)realpos.pos.y + (int)realpos.bounds.y <= y2) &&
                    (z1 <= (int)realpos.pos.z && (int)realpos.pos.z + (int)realpos.bounds.z <= z2))
                {
                    child.posA.x = child.posA.x + Convert.ToInt32(new_x.Text);
                    child.posA.y = child.posA.y + Convert.ToInt32(new_y.Text);
                    child.posA.z = child.posA.z + Convert.ToInt32(new_z.Text);
                    if (new_color.Text != "")
                        child.color = new_color.Text.ToString().Substring(1, 6);


                }
            }


            Loadwindow w = new Loadwindow();
            w.Show();
            BP.Description.description = BP.Description.description += "++ Applied some area property changes ";
            BP.setblueprint(BP.Blueprint);
            this.mainwindow.RenderBlueprint();
            //Update();
            filterupdate();
            w.Close();
        }



        private void SET_Copy_Click(object sender, RoutedEventArgs e)
        {

            this.mainwindow.openpaintpicker();
            new_sensorcolor.Text = PaintSelector.PaintColor;

        }
        private void SET_Copy1_Click(object sender, RoutedEventArgs e)
        {
            this.mainwindow.openpaintpicker();
            new_lampcolor.Text = PaintSelector.PaintColor;
        }
        private void SET_Copy2_Click(object sender, RoutedEventArgs e)
        {
            this.mainwindow.openpaintpicker();
            new_color.Text = PaintSelector.PaintColor;
        }

        private void disableAll()
        {
            Edit_gate.Visibility = Visibility.Collapsed;
            Edit_general.Visibility = Visibility.Collapsed;
            Edit_lamp.Visibility = Visibility.Collapsed;
            Edit_sensor.Visibility = Visibility.Collapsed;
            Edit_Timer.Visibility = Visibility.Collapsed;
            button_render.IsEnabled = false;
            this.mainwindow.Marker = null;
            mainwindow.Image_blueprint.DataContext = "";
            mainwindow.Image_blueprint.DataContext = mainwindow;

        }
        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            base.OnClosing(e);
            this.mainwindow.Marker = null;
            this.mainwindow.setMarker2(0, 0, 0, 0, 0, 0);
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using System.Windows;
using System.IO;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;

namespace Advanced_Blueprint_Tools
{
    public class BP
    {
        public static string Blueprintpath { get; private set; } 

        public static dynamic Blueprint { get; private set; }

        public static dynamic Description { get; private set; }

        public static PngBitmapEncoder Icon { get; set; }

        private static Dictionary<int, dynamic> Wires { get; set; }

        private static HashSet<string> Useduuids = new HashSet<string>();
        
        public static bool missingmod = false;
        public static bool brokenrotation = false;

        public static void setblueprint(dynamic bp)
        {
            Blueprint = bp;
            missingmod = false;
            brokenrotation = false;
            Useduuids.Clear();
            GetUsedUuids();
            Wires = new Dictionary<int, dynamic>();
        }

        public BP(string bppath, dynamic bp, dynamic desc)
        {
            Blueprintpath = bppath;
            Blueprint = bp;
            Description = desc;
            setblueprint(bp);
        }

        public BP(string bppath)
        {
            Blueprint = null;
            Description = null;

            Blueprintpath = bppath;
            //load directory of blueprints
            try
            {
                Blueprint = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(System.IO.File.ReadAllText(Blueprintpath + @"\blueprint.json"));
                Description = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(System.IO.File.ReadAllText(Blueprintpath + @"\description.json"));

                setblueprint(Blueprint);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                
            }
        }

        public static HashSet<string> GetUsedUuids()
        {
            if (Useduuids.Count > 0) return Useduuids;

            Useduuids = new HashSet<string>();

            if (Blueprint.bodies != null)
                foreach (dynamic body in Blueprint.bodies)
                    foreach (dynamic child in body.childs)
                            Useduuids.Add(child.shapeId.ToString());
            if (Blueprint.joints != null)
                foreach(dynamic joint in Blueprint.joints)
                        Useduuids.Add(joint.shapeId.ToString());
            return Useduuids;
        }

        public static Dictionary<string, Tuple<string, BitmapSource, int>> GetUsedPartsList()
        {
            Dictionary<string, int> uuidamounts = new Dictionary<string, int>();
            try
            {

                if (Blueprint.bodies != null)
                    foreach (dynamic body in Blueprint.bodies)
                        foreach (dynamic child in body.childs)
                        {
                            int modifier = 1;
                            if (child.bounds != null)
                                modifier = Convert.ToInt32(child.bounds.x.ToString()) * Convert.ToInt32(child.bounds.y.ToString()) * Convert.ToInt32(child.bounds.z.ToString());
                            string uuid = child.shapeId.ToString();
                            if (!uuidamounts.ContainsKey(uuid))
                                uuidamounts.Add(uuid, modifier);
                            else
                                uuidamounts[uuid]+=modifier;
                        }
                if (Blueprint.joints != null)
                    foreach (dynamic joint in Blueprint.joints)
                    {
                        string uuid = joint.shapeId.ToString();
                        if (!uuidamounts.ContainsKey(uuid))
                            uuidamounts.Add(uuid, 1);
                        else
                            uuidamounts[uuid]++;
                    }
                Dictionary<string, Tuple<string, BitmapSource, int>> list = new Dictionary<string, Tuple<string, BitmapSource, int>>();
                foreach (string uuid in uuidamounts.Keys)
                {
                    if (Database.blocks.ContainsKey(uuid))
                    {
                        list.Add(uuid, new Tuple<string, BitmapSource, int>(Database.blocks[uuid].Name, null, uuidamounts[uuid]));
                    }
                }

                return list;
            }
            catch { return null; }
        }

        public static Dictionary<int, dynamic> GetWires()
        {
            Wires = new Dictionary<int, dynamic>();

            if (Blueprint.bodies != null)
                foreach (dynamic body in Blueprint.bodies)
                    foreach (dynamic child in body.childs)
                        if (child.controller != null && child.controller.id != null)
                        {
                            dynamic correctedchild = getposandbounds(child);
                            dynamic wire = new JObject();
                            wire.pos = new JObject()
                            {
                                ["x"]= Convert.ToInt32(correctedchild.pos.x.ToString()) + Convert.ToInt32(correctedchild.bounds.x.ToString()) / 2.0,
                                ["y"]= Convert.ToInt32(correctedchild.pos.y.ToString()) + Convert.ToInt32(correctedchild.bounds.y.ToString()) / 2.0,
                                ["z"]= Convert.ToInt32(correctedchild.pos.z.ToString()) + Convert.ToInt32(correctedchild.bounds.z.ToString()) / 2.0
                            };
                            string color = child.color.ToString();
                            if (color.StartsWith("#"))
                                color = color.Substring(1);
                            wire.color = color;
                            wire.connections = child.controller.controllers;
                            Wires.Add(Convert.ToInt32(child.controller.id.ToString()), wire);
                        }

            if (Blueprint.joints != null)
                foreach (dynamic joint in Blueprint.joints)
                    if (joint.controller != null && joint.controller.id != null)
                    {
                        dynamic correctedchild = getposandbounds(joint);
                        dynamic wire = new JObject();
                        wire.pos = new JObject()
                        {
                            ["x"] = Convert.ToInt32(correctedchild.pos.x.ToString()) + Convert.ToInt32(correctedchild.bounds.x.ToString()) / 2.0,
                            ["y"] = Convert.ToInt32(correctedchild.pos.y.ToString()) + Convert.ToInt32(correctedchild.bounds.y.ToString()) / 2.0,
                            ["z"] = Convert.ToInt32(correctedchild.pos.z.ToString()) + Convert.ToInt32(correctedchild.bounds.z.ToString()) / 2.0
                        };
                        string color = joint.color.ToString();
                        if (color.StartsWith("#"))
                            color = color.Substring(1);
                        wire.color = color;
                        wire.connections = joint.controller.controllers;
                        Wires.Add(Convert.ToInt32(joint.controller.id.ToString()), wire);
                    }

            return Wires;
        }

        public static dynamic GetBounds()
        {
            int minx = 10000, maxx = -10000, miny = 10000, maxy = -10000, minz = 10000, maxz = -10000;
            foreach(dynamic body in Blueprint.bodies)
                foreach(dynamic child in body.childs)
                {
                    dynamic correctedchild = getposandbounds(child);
                    if (correctedchild.pos.x < minx) minx = correctedchild.pos.x;
                    else
                    if (correctedchild.pos.x + correctedchild.bounds.x > maxx) maxx = correctedchild.pos.x + correctedchild.bounds.x;
                    if (correctedchild.pos.y < miny) miny = correctedchild.pos.y;
                    else
                    if (correctedchild.pos.y + correctedchild.bounds.y > maxy) maxy = correctedchild.pos.y + correctedchild.bounds.y;
                    if (correctedchild.pos.z < minz) minz = correctedchild.pos.z;
                    else
                    if (correctedchild.pos.z + correctedchild.bounds.z > maxz) maxz = correctedchild.pos.z + correctedchild.bounds.z;
                }
            if (Blueprint.joints != null)
                foreach (dynamic joint in Blueprint.joints)
                {
                    dynamic correctedchild = getposandbounds(joint);
                    if (correctedchild.pos.x < minx) minx = correctedchild.pos.x;
                    else
                    if (correctedchild.pos.x + correctedchild.bounds.x > maxx) maxx = correctedchild.pos.x + correctedchild.bounds.x;
                    if (correctedchild.pos.y < miny) miny = correctedchild.pos.y;
                    else
                    if (correctedchild.pos.y + correctedchild.bounds.y > maxy) maxy = correctedchild.pos.y + correctedchild.bounds.y;
                    if (correctedchild.pos.z < minz) minz = correctedchild.pos.z;
                    else
                    if (correctedchild.pos.z + correctedchild.bounds.z > maxz) maxz = correctedchild.pos.z + correctedchild.bounds.z;
                }
            return new JObject() { ["minx"] = minx, ["maxx"] = maxx, ["miny"] = miny, ["maxy"] = maxy, ["minz"] = minz, ["maxz"] = maxz };
        }

        public static Tuple<Point3D,int> GetCenterOffMass()
        {
            Point3D center = new Point3D(0, 0, 0);
            int totalweight = 0;
            
            foreach(dynamic body in Blueprint.bodies)
                foreach(dynamic child in body.childs)
                    if(Database.blocks.ContainsKey(child.shapeId.ToString()))
                    {
                        dynamic realpos = getposandbounds(child);
                        int weight = Database.blocks[child.shapeId.ToString()].GetWeight(realpos.bounds);

                        var point = new Point3D((int)realpos.pos.x + (int)realpos.bounds.x/ 2.0, (int)realpos.pos.y + (int)realpos.bounds.y / 2.0, (int)realpos.pos.z + (int)realpos.bounds.z / 2.0);

                        int tot = totalweight + weight;
                        center = new Point3D((center.X * totalweight + point.X * weight) / tot, (center.Y * totalweight + point.Y * weight) / tot, (center.Z * totalweight + point.Z * weight) / tot);
                        totalweight = tot;
                    }
            return new Tuple<Point3D, int>(center, totalweight);
        }

        public static Tuple<Model3DGroup, Model3DGroup> RenderBlocks()
        {
            Model3DGroup blocks = new Model3DGroup();
            Model3DGroup glass = new Model3DGroup();

            Block block = new Block(null, "unknown", "unknown", null, null);

            if (Blueprint.bodies != null)
                foreach (dynamic body in Blueprint.bodies)
                    foreach (dynamic child in body.childs)
                    {
                        dynamic realpos = getposandbounds(child);
                        int x = realpos.pos.x;
                        int y = realpos.pos.y;
                        int z = realpos.pos.z;

                        if (Database.blocks.ContainsKey(child.shapeId.ToString()))
                        {
                            Blockobject blockobject = Database.blocks[child.shapeId.ToString()];
                            if (blockobject is Block)
                            {
                                Model3D model = (blockobject as Block).Render(x, y, z, realpos.bounds, child.color.ToString(), Convert.ToInt32(realpos.xaxis), Convert.ToInt32(realpos.zaxis));
                                if (!blockobject.glass)
                                    blocks.Children.Add(model);
                                else
                                    glass.Children.Add(model);
                            }
                            else//part
                            {
                                Model3D model = (blockobject as Part).Render(x , y, z, child.color.ToString(), Convert.ToInt32(realpos.xaxis), Convert.ToInt32(realpos.zaxis));
                                if (!blockobject.glass)
                                    blocks.Children.Add(model);
                                else
                                    glass.Children.Add(model);
                                
                            }
                        }
                        else//not in database
                        {
                            dynamic bounds = new JObject() { ["x"] = 1, ["y"] = 1, ["z"] = 1 };
                            if (realpos.bounds != null)
                                bounds = realpos.bounds;

                            Model3D model = block.Render(x, y, z, bounds, child.color.ToString(), Convert.ToInt32(realpos.xaxis), Convert.ToInt32(realpos.zaxis));

                            blocks.Children.Add(model);

                        }
                    }
            if(Blueprint.joints != null)
                foreach(dynamic joint in Blueprint.joints)
                {
                    dynamic realpos = getposandbounds(joint);
                    int x = realpos.pos.x;
                    int y = realpos.pos.y;
                    int z = realpos.pos.z;

                    if (Database.blocks.ContainsKey(joint.shapeId.ToString()))
                    {
                        Blockobject blockobject = Database.blocks[joint.shapeId.ToString()];
                        if (blockobject is Block)
                        {
                            Model3D model = (blockobject as Block).Render(x, y, z, realpos.bounds, joint.color.ToString(), Convert.ToInt32(realpos.xaxis), Convert.ToInt32(realpos.zaxis));
                            if (!blockobject.glass)
                                blocks.Children.Add(model);
                            else
                                glass.Children.Add(model);
                        }
                        else//part
                        {
                            Model3D model = (blockobject as Part).Render(x, y, z, joint.color.ToString(), Convert.ToInt32(realpos.xaxis), Convert.ToInt32(realpos.zaxis));
                            if (!blockobject.glass)
                                blocks.Children.Add(model);
                            else
                                glass.Children.Add(model);
                        }
                    }
                    else//not in database
                    {
                        dynamic bounds = new JObject() { ["x"] = 1, ["y"] = 1, ["z"] = 1 };
                        if (realpos.bounds != null)
                            bounds = realpos.bounds;

                        Model3D model = block.Render(x, y, z, bounds, joint.color.ToString(), Convert.ToInt32(realpos.xaxis), Convert.ToInt32(realpos.zaxis));

                        blocks.Children.Add(model);

                    }

                }
            new Task(() =>
            {
                if (BP.missingmod) MessageBox.Show("Missing mod for this blueprint! \nPlease download the required mod!\n\nwill work for now tho wiring/moving blocks not recommended!");
            }).Start();
            new Task(() =>
            {
                if (BP.brokenrotation) MessageBox.Show("Broken Rotation in this blueprint!\n\nTools 'mirror tool', [] ,.. will BREAK your blueprint!");
            }).Start();
            return new Tuple<Model3DGroup, Model3DGroup>(blocks,glass);
        }

        

        public static void Save()
        {

            string blueprinttext = Convert.ToString(Blueprint);
            string descriptiontext = Newtonsoft.Json.JsonConvert.SerializeObject(Description);
            
            if(!Directory.Exists(Blueprintpath))
                System.IO.Directory.CreateDirectory(Blueprintpath);

            backup();
            System.IO.File.WriteAllText(Blueprintpath + "\\blueprint.json", blueprinttext); //save blueprint
            System.IO.File.WriteAllText(Blueprintpath + "\\description.json", descriptiontext); //save description

            using (Stream stm = File.Create(Blueprintpath + "\\icon.png"))
            {
                Icon.Save(stm);
            }
            Database.LoadBpsIn(Database.User_ + "\\blueprints");//refresh icon
            Database.bprefresh = true;
            new System.Threading.Thread(new System.Threading.ThreadStart(()=> { MessageBox.Show("Blueprint saved!"); })).Start();
            

        }
        public static void backup()
        {
            if(File.Exists(Blueprintpath + "\\blueprint.json"))
            {
                for(int i = 1; i<30; i++)
                {
                    if (!File.Exists(Blueprintpath + "\\blueprint_backup_" + i.ToString() + ".json"))
                    {
                        System.IO.File.Copy(Blueprintpath + "\\blueprint.json", Blueprintpath + "\\blueprint_backup_" + i.ToString() + ".json");
                        break;
                    }
                }
            }
        }
        public static void SaveAs(string name)//in scrapdata dir
        {
            string newbp = Database.User_ + @"\Blueprints\" + name;
            System.IO.Directory.CreateDirectory(newbp);

            string blueprinttext = Convert.ToString(Blueprint);
            Description.localId = System.Guid.NewGuid();
            string descriptiontext = Newtonsoft.Json.JsonConvert.SerializeObject(Description);

            System.IO.File.WriteAllText(newbp + "\\blueprint.json", blueprinttext); //save blueprint
            System.IO.File.WriteAllText(newbp + "\\description.json", descriptiontext); //save description
            using (Stream stm = File.Create(newbp+"\\icon.png"))
            {
                Icon.Save(stm);
            }
            Database.LoadBpsIn(Database.User_ + "\\blueprints");
            Database.bprefresh = true;
            
            
            new System.Threading.Thread(() => { MessageBox.Show("Saved as new blueprint!\nwill require game restart to be able to find it in-game!\n(blame axolot)"); }).Start();

        }



        //get bounds from 
        private static dynamic getbounds(dynamic part)
        {
            dynamic bounds = new Newtonsoft.Json.Linq.JObject();
            if (part.box != null)
            {
                return part.box;
            }
            if (part.hull != null)
            {
                bounds.x = part.hull.x;
                bounds.y = part.hull.y;
                bounds.z = part.hull.z;
                return bounds;
            }
            if (part.cylinder != null)
            {
                if (part.cylinder.axis.ToString().ToLower() == "x")
                {
                    bounds.x = part.cylinder.depth;
                    bounds.y = part.cylinder.diameter;
                    bounds.z = part.cylinder.diameter;
                    return bounds;
                }
                else
                if (part.cylinder.axis.ToString().ToLower() == "y")
                {
                    bounds.x = part.cylinder.diameter;
                    bounds.y = part.cylinder.depth;
                    bounds.z = part.cylinder.diameter;
                    return bounds;
                }
                else
                if (part.cylinder.axis.ToString().ToLower() == "z")
                {
                    bounds.x = part.cylinder.diameter;
                    bounds.y = part.cylinder.diameter;
                    bounds.z = part.cylinder.depth;
                    return bounds;
                }
            }
            bounds.X = 1;
            bounds.Y = 1;
            bounds.Z = 1;
            MessageBox.Show("no bounds\n\nImpossible senario. please report");
            return bounds;
        }

        //Reorganize bounds according to rotation:
        private static dynamic flip(dynamic child, string neworder)
        {
            int x = child.bounds.x;
            int y = child.bounds.y;
            int z = child.bounds.z;
            if (neworder == "zxy") //shift
            {
                child.bounds.x = z;
                child.bounds.y = x;
                child.bounds.z = y;
            }
            if (neworder == "yzx") //"
            {
                child.bounds.x = y;
                child.bounds.y = z;
                child.bounds.z = x;
            }
            if (neworder == "xzy") //switch
            {
                child.bounds.x = x;
                child.bounds.y = z;
                child.bounds.z = y;
            }
            if (neworder == "zyx")
            {
                child.bounds.x = z;
                child.bounds.y = y;
                child.bounds.z = x;
            }
            if (neworder == "yxz")
            {
                child.bounds.x = y;
                child.bounds.y = x;
                child.bounds.z = z;
            }
            return child;
        }

        //get new pos and correct ingame bounds for child
        public static dynamic getposandbounds(dynamic whatever)
        {
            dynamic child = Newtonsoft.Json.JsonConvert.DeserializeObject(Convert.ToString(whatever));
            string uuid = child.shapeId;
            //if (child.bounds == null) //add bounds to parts (blocks do not get affected)
            {
                if (Database.blocks.ContainsKey(uuid))
                {
                    Blockobject b = Database.blocks[uuid];
                    if (b is Part)
                    {
                        child.bounds = ((Part)b).GetBoundsDynamic();
                    }
                }
                else
                {
                    missingmod = true;
                }
                if (child.bounds == null)
                {
                    child.bounds = new JObject { ["x"] = 1, ["y"] = 1, ["z"] = 1 };
                }
            }
            bool IsJoint = false;
            if (child.posA != null)
            {
                IsJoint = true;
                child.pos = child.posA;
                child.xaxis = child.xaxisA;
                child.zaxis = child.zaxisA;
            }
            try
            {
                int xaxis = Convert.ToInt32(child.xaxis);
                int zaxis = Convert.ToInt32(child.zaxis);
                int xaxisabs = Math.Abs(xaxis);
                int zaxisabs = Math.Abs(zaxis);
                //switch bounds here
                if (Math.Abs(Convert.ToInt32(child.xaxis)) == 3)
                {
                    if (Math.Abs(Convert.ToInt32(child.zaxis)) == 2)
                    {
                        flip(child, "yzx");
                    }
                    if (Math.Abs(Convert.ToInt32(child.zaxis)) == 1)
                    {
                        flip(child, "zyx");
                    }
                }
                if (Math.Abs(Convert.ToInt32(child.xaxis)) == 2)
                {
                    if (Math.Abs(Convert.ToInt32(child.zaxis)) == 3)
                    {
                        flip(child, "yxz");
                    }
                    if (Math.Abs(Convert.ToInt32(child.zaxis)) == 1)
                    {
                        flip(child, "zxy");
                    }
                }
                if (Math.Abs(Convert.ToInt32(child.xaxis)) == 1)
                {
                    if (Math.Abs(Convert.ToInt32(child.zaxis)) == 2)
                    {
                        flip(child, "xzy");
                    }
                }
                //this updating pos only applies to parts, blocks do not get affected as they always have xaxis 1 zaxis 3
                if (!IsJoint)
                {  //
                   //if (xaxis == -1 | zaxis == -1 | (xaxis == 2 && zaxis == 3) | (xaxis == 3 && zaxis == -2) | (xaxis == -2 && zaxis == -3) | (xaxis == -3 && zaxis == 2))
                   //    child.pos.x -= child.bounds.x;
                   //if (xaxis == -2 | zaxis == -2 | (xaxis == -1 && zaxis == 3) | (xaxis == -3 && zaxis == -1) | (xaxis == 1 && zaxis == -3) | (xaxis == 3 && zaxis == 1))
                   //    child.pos.y -= child.bounds.y;
                   //if (xaxis == -3 | zaxis == -3 | (xaxis == -2 && zaxis == 1) | (xaxis == -1 && zaxis == -2) | (xaxis == 1 && zaxis == 2) | (xaxis == 2 && zaxis == -1))
                   //    child.pos.z -= child.bounds.z;
                    if (child.xaxis == -1 | child.zaxis == -1 | (child.xaxis == 2 && child.zaxis == 3) | (child.xaxis == 3 && child.zaxis == -2) | (child.xaxis == -2 && child.zaxis == -3) | (child.xaxis == -3 && child.zaxis == 2))
                        child.pos.x -= child.bounds.x;
                    if (child.xaxis == -2 | child.zaxis == -2 | (child.xaxis == -1 && child.zaxis == 3) | (child.xaxis == -3 && child.zaxis == -1) | (child.xaxis == 1 && child.zaxis == -3) | (child.xaxis == 3 && child.zaxis == 1))
                        child.pos.y -= child.bounds.y;
                    if (child.xaxis == -3 | child.zaxis == -3 | (child.xaxis == -2 && child.zaxis == 1) | (child.xaxis == -1 && child.zaxis == -2) | (child.xaxis == 1 && child.zaxis == 2) | (child.xaxis == 2 && child.zaxis == -1))
                        child.pos.z -= child.bounds.z;
                }
                else
                {
                    if (!(zaxis > 0 || !(child.bounds.x != 1 || child.bounds.y != 1 || child.bounds.z != 1)))
                    {
                        //correctedchild.pos = Blueprint.joints[i].posB;
                        if (zaxis == -1)
                            child.pos.x -= child.bounds.x - 1;
                        if (zaxis == -2)
                            child.pos.y -= child.bounds.y - 1;
                        if (zaxis == -3)
                            child.pos.z -= child.bounds.z - 1;
                    }
                }
            }
            catch
            {
            }
            return child;
        }
        public static dynamic calcbppos(dynamic whatever)
        {
            dynamic child = Newtonsoft.Json.JsonConvert.DeserializeObject(Convert.ToString(whatever));
            //this updating pos only applies to parts, blocks do not get affected as they always have xaxis 1 zaxis 3
            if (child.xaxis == -1 | child.zaxis == -1 | (child.xaxis == 2 && child.zaxis == 3) | (child.xaxis == 3 && child.zaxis == -2) | (child.xaxis == -2 && child.zaxis == -3) | (child.xaxis == -3 && child.zaxis == 2))
                child.pos.x += child.bounds.x;
            if (child.xaxis == -2 | child.zaxis == -2 | (child.xaxis == -1 && child.zaxis == 3) | (child.xaxis == -3 && child.zaxis == -1) | (child.xaxis == 1 && child.zaxis == -3) | (child.xaxis == 3 && child.zaxis == 1))
                child.pos.y += child.bounds.y;
            if (child.xaxis == -3 | child.zaxis == -3 | (child.xaxis == -2 && child.zaxis == 1) | (child.xaxis == -1 && child.zaxis == -2) | (child.xaxis == 1 && child.zaxis == 2) | (child.xaxis == 2 && child.zaxis == -1))
                child.pos.z += child.bounds.z;
            return child;
        }
    }
}
<file_sep>﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for Sphere_generator.xaml
    /// </summary>
    public partial class Ellipsoid_Generator : Window
    {
        private MainWindow mainwindow;
        public Ellipsoid_Generator(MainWindow window)
        {
            this.mainwindow = window;
            InitializeComponent();
        }

        private void Button_Help_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://youtu.be/glLgQemUS2I?t=1479");
        }

        private void Button_Create_Click(object sender, RoutedEventArgs e)
        {
            float X = Convert.ToInt32(TextBox_X.Text);
            float Y = Convert.ToInt32(TextBox_Y.Text);
            float Z = Convert.ToInt32(TextBox_Z.Text);
            float t = Convert.ToInt32(TextBox_thickness.Text);

            dynamic Sphere = new JObject();
            Sphere.bodies = new JArray();
            Sphere.bodies.Add(new JObject() as dynamic);
            Sphere.bodies[0].childs = new JArray();

            dynamic blocksXYZ = new JObject();
            int amountgenerated=0;
            for (float x = -X; x < X; x++)
                for (float y = -Y; y < Y; y++)
                    for (float z = -Z; z < Z; z++)
                    {

                        if ((Math.Pow(x / X, 2) + Math.Pow(y / Y, 2) + Math.Pow(z / Z, 2)) < 0.95 &&
                            (Math.Pow(x  / (X-t), 2) + Math.Pow((y ) / (Y-t), 2) + Math.Pow(z / (Z-t), 2)) > 0.95)
                        {
                            if (blocksXYZ[x.ToString()] == null)
                                blocksXYZ[x.ToString()] = new JObject();
                            if (blocksXYZ[x.ToString()][y.ToString()] == null)
                                blocksXYZ[x.ToString()][y.ToString()] = new JObject();
                            if (blocksXYZ[x.ToString()][y.ToString()][z.ToString()] == null)
                                blocksXYZ[x.ToString()][y.ToString()][z.ToString()] = new JObject();
                            dynamic bounds = new JObject();
                            bounds.x = 1;
                            bounds.y = 1;
                            bounds.z = 1;
                            blocksXYZ[x.ToString()][y.ToString()][z.ToString()].bounds = bounds;
                            amountgenerated++;
                        }
                    }

            foreach (dynamic x in blocksXYZ)
                foreach (dynamic y in x.Value)
                    foreach (dynamic z in y.Value)
                    {
                        dynamic bounds = z.Value.bounds;
                        if (bounds != null)
                        {
                            for (int i = Convert.ToInt32(z.Name) + 1; i < 64; i++)
                            {
                                if (blocksXYZ[x.Name][y.Name][i.ToString()] != null && blocksXYZ[x.Name][y.Name][i.ToString()].bounds != null)
                                {
                                    blocksXYZ[x.Name][y.Name][i.ToString()].bounds = null;

                                    blocksXYZ[x.Name][y.Name][z.Name].bounds.z = Convert.ToInt32(blocksXYZ[x.Name][y.Name][z.Name].bounds.z) + 1;
                                }
                                else
                                    break;
                            }
                        }
                    }

            foreach (dynamic x in blocksXYZ)
                foreach (dynamic y in x.Value)
                    foreach (dynamic z in y.Value)
                    {
                        dynamic bounds = z.Value.bounds;
                        if (bounds != null)
                        {
                            for (int i = Convert.ToInt32(y.Name) + 1; i < 64; i++)
                            {
                                if (blocksXYZ[x.Name][i.ToString()] != null && blocksXYZ[x.Name][i.ToString()][z.Name] != null &&
                                    blocksXYZ[x.Name][i.ToString()][z.Name].bounds != null &&
                                    blocksXYZ[x.Name][i.ToString()][z.Name].bounds.z == blocksXYZ[x.Name][y.Name][z.Name].bounds.z)
                                {
                                    blocksXYZ[x.Name][i.ToString()][z.Name].bounds = null;

                                    blocksXYZ[x.Name][y.Name][z.Name].bounds.y = Convert.ToInt32(blocksXYZ[x.Name][y.Name][z.Name].bounds.y) + 1;
                                }
                                else
                                    break;
                            }
                        }
                    }
            foreach (dynamic x in blocksXYZ)
                foreach (dynamic y in x.Value)
                    foreach (dynamic z in y.Value)
                    {
                        dynamic bounds = z.Value.bounds;
                        if (bounds != null)
                        {
                            for (int i = Convert.ToInt32(x.Name) + 1; i < 64; i++)
                            {
                                if (blocksXYZ[i.ToString()] != null && blocksXYZ[i.ToString()][y.Name] != null && blocksXYZ[i.ToString()][y.Name][z.Name] != null &&
                                    blocksXYZ[i.ToString()][y.Name][z.Name].bounds != null &&
                                    blocksXYZ[i.ToString()][y.Name][z.Name].bounds.z == blocksXYZ[x.Name][y.Name][z.Name].bounds.z &&
                                    blocksXYZ[i.ToString()][y.Name][z.Name].bounds.y == blocksXYZ[x.Name][y.Name][z.Name].bounds.y)
                                {
                                    blocksXYZ[i.ToString()][y.Name][z.Name].bounds = null;

                                    blocksXYZ[x.Name][y.Name][z.Name].bounds.x = Convert.ToInt32(blocksXYZ[x.Name][y.Name][z.Name].bounds.x) + 1;
                                }
                                else
                                    break;
                            }
                        }
                    }


            foreach (dynamic x in blocksXYZ)
                foreach (dynamic y in x.Value)
                    foreach (dynamic z in y.Value)
                        if(z.Value.bounds != null)
                            Sphere.bodies[0].childs.Add(block(Convert.ToInt32(x.Name), Convert.ToInt32(y.Name), Convert.ToInt32(z.Name), z.Value.bounds));

            if (amountgenerated > 0)
            {
                string message = "++ An ellipsoid with " + amountgenerated + " blocks has been generated!";
                //MessageBox.Show(message+"\n\nOptimized to: "+count+" shapes");
                Random r = new Random();
                string blueprintpath = Database.User_ + "\\Blueprints\\GeneratedEllipsoid-"+r.Next()+r.Next();
                dynamic description = new JObject();
                description.description = "generated ellipsoid";
                description.name = "generated sphere" + r.Next();
                description.type = "Blueprint";
                description.version = 0;

                if (BP.Blueprintpath== null)
                {//no blueprint exists, initialize new one
                    new BP(blueprintpath, Sphere, description);
                }
                else
                {//overwrite current blueprint
                    BP.setblueprint(Sphere);
                    BP.Description.description += message;
                }
                mainwindow.RenderBlueprint();
            }
            else
            {
                MessageBox.Show("no ellipsoid has been generated");
            }

        }
        private dynamic block(int x, int y, int z, dynamic bounds)
        {
            dynamic block = new JObject();
            block.color = "5DB7E7";
            block.pos = new JObject();
            block.pos.x = x;
            block.pos.y = y;
            block.pos.z = z;
            block.bounds = new JObject();
            block.bounds.x = bounds.x;
            block.bounds.y = bounds.y;
            block.bounds.z = bounds.z;
            block.shapeId = "a6c6ce30-dd47-4587-b475-085d55c6a3b4";
            block.xaxis = 1;
            block.zaxis = 3;
            return block;
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox t = (TextBox)sender;
            try
            {
                if (Convert.ToInt32(t.Text) >= 0 || Convert.ToInt32(t.Text) <= 0) { }
            }
            catch
            {
                t.Text = "0";
            }
        }
    }
}
<file_sep>﻿using Assimp;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Threading;
using System.IO;
using System.Drawing;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for ObjToBlueprint.xaml
    /// </summary>
    public partial class ObjToBlueprint : Window
    {
        MainWindow mainWindow;
        string file;
        string texture;
        Dictionary<Point3D, Point3D> coloredpoints;
        double scale=1;
        Assimp.Vector3D bounds = new Assimp.Vector3D(1, 1, 1);
        BackgroundWorker backgroundWorker = new BackgroundWorker();
        ProgressWindow progressWindow;
        HashSet<Point3D> pointlist = new HashSet<Point3D>();//Tuple<Point3D,color>
        bool flipyz = false;
        bool flipxz = false;
        int flipz = 1;
        bool texturepossible = false;
        public ObjToBlueprint(MainWindow mainWindow)
        {
            this.mainWindow = mainWindow;
            InitializeComponent();
        }
        

        private void objPath_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.DefaultExt = ".obj";
            openFileDialog.Filter = "Obj files (*.obj)|*.obj|Mesh files (*.mesh)|*.mesh|Fbx Files(*.fbx)|*.fbx|stl files(*.stl)|*.stl|All Files(*.*)|*.*";
            openFileDialog.InitialDirectory = Database.ScrapData;

            openFileDialog.ShowDialog();

            string file = openFileDialog.FileName;
            if (file != null && file != "")
            {
                objPath.Text = file;
            }

        }
        private void objPath_TextChanged(object sender, TextChangedEventArgs e)
        {
            string file = objPath.Text;
            if (file != null && file != "" && File.Exists(file))
            {
                this.file = file;
                //objPath.Text = file;

                new Thread(() =>
                {
                    try
                    {
                        this.texturepossible = false;
                        int minx = 1000000, maxx = -1000000, miny = 1000000, maxy = -1000000, minz = 1000000, maxz = -1000000;
                        Scene scene = new AssimpImporter().ImportFile(file);
                        foreach (Mesh m in scene.Meshes)
                        {
                            if (m.TextureCoordsChannelCount>0) this.texturepossible = true;
                            foreach (Assimp.Vector3D p in m.Vertices)
                            {
                                if (p.X < minx) minx = (int)p.X;
                                else if (p.X > maxx) maxx = (int)p.X;
                                if (p.Y < miny) miny = (int)p.Y;
                                else if (p.Y > maxy) maxy = (int)p.Y;
                                if (p.Z < minz) minz = (int)p.Z;
                                else if (p.Z > maxz) maxz = (int)p.Z;
                            }
                        }
                        this.Dispatcher.Invoke((Action)(() =>
                        {
                            BoundsBox.Content = @"(" + (maxx - minx) + "x" + (maxy - miny) + "x" + (maxz - minz) + ")";
                        }));
                    }
                    catch (Exception ex)
                    {
                        System.Windows.MessageBox.Show(ex.Message, "Couldn't load mesh file");
                        this.file = null;
                    }
                }).Start();
            }
        }
        private void TexturePath_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.DefaultExt = ".png";
            openFileDialog.Filter = "png files (*.png)|*.png|jpg files (*.jpg)|*.jpg|All Files(*.*)|*.*";
            openFileDialog.InitialDirectory = Database.ScrapData;

            openFileDialog.ShowDialog();

            string file = openFileDialog.FileName;
            if (file != null && file != "")
            {
                TexturePath.Text = file;
            }
            

        }
        private void TexturePath_TextChanged(object sender, TextChangedEventArgs e)
        {
            string file = TexturePath.Text;
            if (file != null && file != "" && File.Exists(file))
            {
                this.texture = file;
            }
            else this.texture = null;

        }


        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if(this.file != null)
            {
                flipyz = flipYZ.IsChecked == true;
                flipxz = flipXZ.IsChecked == true;
                flipz = flipZ.IsChecked == true ? -1 : 1;

                backgroundWorker = new BackgroundWorker();
                backgroundWorker.WorkerSupportsCancellation = true;
                backgroundWorker.WorkerReportsProgress = true;
                progressWindow = new ProgressWindow(backgroundWorker, "Converting OBJ to Pointlist");
                progressWindow.Show();

                if(this.texture != null && this.texturepossible)
                    backgroundWorker.DoWork += new DoWorkEventHandler(Convertobjwtexture);
                else
                    backgroundWorker.DoWork += new DoWorkEventHandler(Convertobj);
                backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(conversioncompleted);
                backgroundWorker.ProgressChanged += BackgroundWorker1_ProgressChanged;
                    
                backgroundWorker.RunWorkerAsync();
                
            }
        }
        private void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressWindow.UpdateProgress(e.ProgressPercentage);
        }
        private void Convertobjwtexture(object sender, DoWorkEventArgs e)
        {
            try
            {
                Scene scene = new AssimpImporter().ImportFile(file, PostProcessSteps.Triangulate);

                coloredpoints = new Dictionary<Point3D, Point3D>();
                //List<Triangle> splittriangles = new List<Triangle>();
                //pointlist = new HashSet<Point3D>();


                //pointlist.ToDictionary<>
                int progress = 0;
                int total = 0;

                foreach (Mesh m in scene.Meshes)
                    foreach (Face face in m.Faces)
                        total++;
                foreach (Mesh m in scene.Meshes)
                {
                    var texturecoords = m.GetTextureCoords(0);

                    foreach (Face face in m.Faces)
                    {
                        
                        IList<Point3D> vertices = new List<Point3D>();
                        IList<Point3D> texturepoints = new List<Point3D>();
                        foreach (uint i in face.Indices)
                        {
                            double x = m.Vertices[i].X * scale;
                            double y = m.Vertices[i].Y * scale;
                            double z = m.Vertices[i].Z * scale;
                            Point3D point;
                            Assimp.Vector3D texturep = texturecoords[i];
                            Point3D texturepoint = new Point3D(texturep.X,1-texturep.Y,texturep.Z);
                            if (flipyz)
                            {
                                if (flipxz)
                                {
                                    point = new Point3D(y, z, flipz * x);
                                }
                                else
                                {
                                    point = new Point3D(x, z, flipz * y);
                                }
                            }
                            else
                            {
                                if (flipxz)
                                {
                                    point = new Point3D(z, y, flipz * x);
                                }
                                else
                                    point = new Point3D(x, y, flipz * z);
                            }
                            vertices.Add(point);
                            texturepoints.Add(texturepoint);
                            Point3D flooredpoint = new Point3D((int)Math.Floor(point.X), (int)Math.Floor(point.Y), (int)Math.Floor(point.Z));
                            if (!coloredpoints.ContainsKey(flooredpoint))
                                coloredpoints.Add(flooredpoint, texturepoint);
                        }
                        if (vertices.Count == 3)
                        {
                            ColorTriangle triangle = new ColorTriangle(vertices,texturepoints);
                            if (!triangle.BoundsSmallerThan(bounds))
                                Splitcolortriangles(triangle);
                        }
                        else
                        { }
                        progress++;
                        backgroundWorker.ReportProgress((progress * 100) / total);
                        if (backgroundWorker.CancellationPending)
                            e.Cancel = true;
                    }

                }
            }
            catch (Exception ex)
            {
                if (!(ex is OperationCanceledException))
                    System.Windows.MessageBox.Show(ex.Message, "Something went wrong converting the obj+texture");
                else
                    e.Cancel = true;
            }
            
            try
            {
                if (backgroundWorker.CancellationPending)
                    throw new OperationCanceledException();

                dynamic blueprint = new JObject();
                try
                {
                    Bitmap texturemap = new Bitmap(this.texture);
                    HashSet<Tuple<Point3D, string>> pointswithcolor = new HashSet<Tuple<Point3D, string>>();
                    int width = texturemap.Width;
                    int height = texturemap.Height;
                    foreach (var pair in coloredpoints)
                    {
                        int x = (int)(pair.Value.X * width);
                        int y = (int)(pair.Value.Y * height);
                        if (pair.Value.Y > 1)
                        {

                        }
                        while (y < 0)
                            y ++;
                        while (x < 0)
                            x ++;
                        if(Math.Abs(x)>width/2)
                        {

                        }
                        while (x >= width)
                            x -= width;
                        while (y>= height)
                            y -= height;
                        System.Drawing.Color color = texturemap.GetPixel(x , y);
                        string c = color.Name.Substring(2);
                        pointswithcolor.Add(new Tuple<Point3D, string>(pair.Key, c));
                    }
                    coloredpoints.Clear();
                    blueprint = BlueprintOptimizer.CreateBlueprintFromPointsAndColor(pointswithcolor);
                }
                catch (Exception bpex)
                {
                    System.Windows.MessageBox.Show(bpex.Message, "Something went wrong building the blueprint");
                }
                int amountgenerated = blueprint.bodies[0].childs.Count;
                string message = "converted obj to blueprint with " + amountgenerated + " blocks !";
                //MessageBox.Show(message+"\n\nOptimized to: "+count+" shapes");
                Random r = new Random();
                string blueprintpath = Database.User_ + "\\Blueprints\\Generatedblueprintobj-" + r.Next() + r.Next();
                dynamic description = new JObject();
                description.description = "generated obj blueprint with " + amountgenerated + " block";
                description.name = "generated blueprint" + r.Next();
                description.type = "Blueprint";
                description.version = 0;
                new Task(() =>
                {
                    System.Windows.MessageBox.Show(message + "\nPLEASE WAIT for the rendering to complete");
                }).Start();
                if (BP.Blueprintpath == null)
                {//no blueprint exists, initialize new one
                    new BP(blueprintpath, blueprint, description);
                }
                else
                {//overwrite current blueprint
                    BP.setblueprint(blueprint);
                    BP.Description.description += message;
                }
            }
            catch (Exception exc)
            {
                System.Windows.MessageBox.Show(exc.Message, "error");
            }


        }
        private void Splitcolortriangles(ColorTriangle triangle)
        {
            if (backgroundWorker.CancellationPending)
                throw new OperationCanceledException();
            //split triangle in 4 triangles:
            Point3D mid1 = Average(triangle.vertices[0], triangle.vertices[1]);
            Point3D mid2 = Average(triangle.vertices[1], triangle.vertices[2]);
            Point3D mid3 = Average(triangle.vertices[0], triangle.vertices[2]);
            Point3D tmid1 = Average(triangle.texturecoords[0], triangle.texturecoords[1]);
            Point3D tmid2 = Average(triangle.texturecoords[1], triangle.texturecoords[2]);
            Point3D tmid3 = Average(triangle.texturecoords[0], triangle.texturecoords[2]);
            List<ColorTriangle> triangles = new List<ColorTriangle>
            {
                new ColorTriangle(new List<Point3D> { mid1, mid2, mid3 }, new List<Point3D>{ tmid1, tmid2, tmid3 }),
                new ColorTriangle(new List<Point3D> { mid1, mid3, triangle.vertices[0] },new List<Point3D> { tmid1, tmid3, triangle.texturecoords[0] }),
                new ColorTriangle(new List<Point3D> { mid1, mid2, triangle.vertices[1] },new List<Point3D> { tmid1, tmid2, triangle.texturecoords[1] }),
                new ColorTriangle(new List<Point3D> { mid2, mid3, triangle.vertices[2] },new List<Point3D> { tmid2, tmid3, triangle.texturecoords[2] })
            };

            Point3D flooredpoint1 = new Point3D((int)Math.Floor(mid1.X), (int)Math.Floor(mid1.Y), (int)Math.Floor(mid1.Z));
            if (!coloredpoints.ContainsKey(flooredpoint1))
                coloredpoints.Add(flooredpoint1, tmid1);
            Point3D flooredpoint2 = new Point3D((int)Math.Floor(mid2.X), (int)Math.Floor(mid2.Y), (int)Math.Floor(mid2.Z));
            if (!coloredpoints.ContainsKey(flooredpoint2))
                coloredpoints.Add(flooredpoint2, tmid2);
            Point3D flooredpoint3 = new Point3D((int)Math.Floor(mid3.X), (int)Math.Floor(mid3.Y), (int)Math.Floor(mid3.Z));
            if (!coloredpoints.ContainsKey(flooredpoint3))
                coloredpoints.Add(flooredpoint3, tmid3);
           // coloredpoints.Add(new Tuple<Point3D,Point3D>( new Point3D((int)Math.Floor(mid1.X), (int)Math.Floor(mid1.Y), (int)Math.Floor(mid1.Z)),tmid1));
           // coloredpoints.Add(new Tuple<Point3D,Point3D>( new Point3D((int)Math.Floor(mid2.X), (int)Math.Floor(mid2.Y), (int)Math.Floor(mid2.Z)),tmid2));
           // coloredpoints.Add(new Tuple<Point3D,Point3D>( new Point3D((int)Math.Floor(mid3.X), (int)Math.Floor(mid3.Y), (int)Math.Floor(mid3.Z)),tmid3));
            //triangles.Add(new Triangle(new List<Point3D> { mid1, mid2, mid3 }));
            //triangles.Add(new Triangle(new List<Point3D> { mid1, mid3, triangle.vertices[0] }));
            //triangles.Add(new Triangle(new List<Point3D> { mid1, mid2, triangle.vertices[1] }));
            //triangles.Add(new Triangle(new List<Point3D> { mid2, mid3, triangle.vertices[2] }));
            //check for each triangle if bounds are smaller than 1x1x1, if not, split each again:
            foreach (ColorTriangle splittriangle in triangles)
            {
                // foreach(Point3D point in splittriangle.vertices)
                //   pointlist.Add(new Point3D((int)Math.Floor(point.X), (int)Math.Floor(point.Y), (int)Math.Floor(point.Z)));

                if (!splittriangle.BoundsSmallerThan(bounds))
                    Splitcolortriangles(splittriangle);
            }
            //return splittriangles;
        }

        private void Convertobj(object sender, DoWorkEventArgs e)
        {

            Scene scene = new AssimpImporter().ImportFile(file, PostProcessSteps.Triangulate);

            //List<Triangle> splittriangles = new List<Triangle>();
            pointlist = new HashSet<Point3D>();
            //pointlist.ToDictionary<>
            int progress = 0;
            int total = 0;
            try
            {
                

                foreach (Mesh m in scene.Meshes)
                    foreach (Face face in m.Faces)
                        total++;
                foreach (Mesh m in scene.Meshes)
                {

                    foreach (Face face in m.Faces)
                    {
                        IList<Point3D> vertices = new List<Point3D>();
                        foreach (uint i in face.Indices)
                        {
                            double x = m.Vertices[i].X * scale;
                            double y = m.Vertices[i].Y * scale;
                            double z = m.Vertices[i].Z * scale;
                            Point3D point;
                            if (flipyz)
                            {
                                if(flipxz)
                                {
                                    point = new Point3D(y,z, flipz * x);
                                }
                                else
                                {
                                    point = new Point3D(x,z, flipz * y);
                                }
                            }
                            else
                            {
                                if (flipxz)
                                {
                                    point = new Point3D(z,y, flipz * x);
                                }
                                else
                                    point = new Point3D(x,y, flipz * z);
                            }
                            vertices.Add(point);
                            pointlist.Add(new Point3D((int)Math.Floor(point.X), (int)Math.Floor(point.Y), (int)Math.Floor(point.Z)));
                        }
                        if (vertices.Count == 3)
                        {
                            Triangle triangle = new Triangle(vertices);
                            if (!triangle.BoundsSmallerThan(bounds))
                                Splittriangles(triangle);
                        }
                        else
                        { }
                        progress++;
                        backgroundWorker.ReportProgress((progress * 100) / total);
                        if (backgroundWorker.CancellationPending)
                            e.Cancel = true;
                    }

                }
            }
            catch(Exception ex)
            {
                if(!(ex is OperationCanceledException))
                    System.Windows.MessageBox.Show(ex.Message, "Something went wrong converting the obj");
                else
                    e.Cancel = true;
            }

            try
            {
                if (backgroundWorker.CancellationPending)
                    throw new OperationCanceledException();

                dynamic blueprint = new JObject();
                try
                {
                    blueprint = BlueprintOptimizer.CreateBlueprintFromPoints(pointlist);
                }
                catch(Exception bpex)
                {
                    System.Windows.MessageBox.Show(bpex.Message, "Something went wrong building the blueprint");
                }
                int amountgenerated = blueprint.bodies[0].childs.Count;
                string message = "converted obj to blueprint with " + amountgenerated + " blocks !";
                //MessageBox.Show(message+"\n\nOptimized to: "+count+" shapes");
                Random r = new Random();
                string blueprintpath = Database.User_ + "\\Blueprints\\Generatedblueprintobj-" + r.Next() + r.Next();
                dynamic description = new JObject();
                description.description = "generated obj blueprint with "+amountgenerated+" block";
                description.name = "generated blueprint" + r.Next();
                description.type = "Blueprint";
                description.version = 0;
                new Task(() =>
                {
                    System.Windows.MessageBox.Show(message + "\nPLEASE WAIT for the rendering to complete");
                }).Start();
                if (BP.Blueprintpath == null)
                {//no blueprint exists, initialize new one
                    new BP(blueprintpath, blueprint, description);
                }
                else
                {//overwrite current blueprint
                    BP.setblueprint(blueprint);
                    BP.Description.description += message;
                }
            }
            catch (Exception exc)
            {
                System.Windows.MessageBox.Show(exc.Message, "error");
            }

        }

        
        private void Splittriangles(Triangle triangle)
        {
            if (backgroundWorker.CancellationPending)
                throw new OperationCanceledException();
            //split triangle in 4 triangles:
            Point3D mid1 = Average(triangle.vertices[0], triangle.vertices[1]); 
            Point3D mid2 = Average(triangle.vertices[1], triangle.vertices[2]);
            Point3D mid3 = Average(triangle.vertices[0], triangle.vertices[2]);
            List<Triangle> triangles = new List<Triangle>
            {
                new Triangle(new List<Point3D> { mid1, mid2, mid3 }),
                new Triangle(new List<Point3D> { mid1, mid3, triangle.vertices[0] }),
                new Triangle(new List<Point3D> { mid1, mid2, triangle.vertices[1] }),
                new Triangle(new List<Point3D> { mid2, mid3, triangle.vertices[2] })
            };
            pointlist.Add(new Point3D((int)Math.Floor(mid1.X), (int)Math.Floor(mid1.Y), (int)Math.Floor(mid1.Z)));
            pointlist.Add(new Point3D((int)Math.Floor(mid2.X), (int)Math.Floor(mid2.Y), (int)Math.Floor(mid2.Z)));
            pointlist.Add(new Point3D((int)Math.Floor(mid3.X), (int)Math.Floor(mid3.Y), (int)Math.Floor(mid3.Z)));
            //triangles.Add(new Triangle(new List<Point3D> { mid1, mid2, mid3 }));
            //triangles.Add(new Triangle(new List<Point3D> { mid1, mid3, triangle.vertices[0] }));
            //triangles.Add(new Triangle(new List<Point3D> { mid1, mid2, triangle.vertices[1] }));
            //triangles.Add(new Triangle(new List<Point3D> { mid2, mid3, triangle.vertices[2] }));
            //check for each triangle if bounds are smaller than 1x1x1, if not, split each again:
            foreach (Triangle splittriangle in triangles)
            {
               // foreach(Point3D point in splittriangle.vertices)
                 //   pointlist.Add(new Point3D((int)Math.Floor(point.X), (int)Math.Floor(point.Y), (int)Math.Floor(point.Z)));

                if (!splittriangle.BoundsSmallerThan(bounds))
                    Splittriangles(splittriangle);
            }
            //return splittriangles;
        }

        private Point3D Average(Point3D point1, Point3D point2)
        {
            return new Point3D((point1.X + point2.X) / 2.0, (point1.Y + point2.Y) / 2.0, (point1.Z + point2.Z) / 2.0);
        }

        private void conversioncompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressWindow.Close();
            pointlist.Clear();
            if (!e.Cancelled)
            {
                mainWindow.RenderBlueprint();
            }
            backgroundWorker.Dispose();
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {

            System.Windows.Controls.TextBox t = (System.Windows.Controls.TextBox)sender;
            try
            {
                if (Convert.ToDouble(t.Text) >= 0) { }
            }
            catch
            {
                if (t.Text == "-")
                {
                    t.Text = "-0";
                    t.Select(1, 1);
                }
                else
                {
                    t.Text = "0";
                    t.Select(0, 1);
                }
            }
            this.scale = Convert.ToDouble(t.Text);
        }


    }



    public class Triangle
    {
        public IList<Point3D> vertices;

        public Triangle(IList<Point3D> vertices)
        {
            this.vertices = vertices;
        }
        public bool BoundsSmallerThan(Assimp.Vector3D bounds)
        {
            return (Math.Abs(vertices[0].X - vertices[1].X) < bounds.X && Math.Abs(vertices[0].X - vertices[2].X) < bounds.X && Math.Abs(vertices[2].X - vertices[1].X) < bounds.X &&
                    Math.Abs(vertices[0].Y - vertices[1].Y) < bounds.Y && Math.Abs(vertices[0].Y - vertices[2].Y) < bounds.Y && Math.Abs(vertices[2].Y - vertices[1].Y) < bounds.Y &&
                    Math.Abs(vertices[0].Z - vertices[1].Z) < bounds.Z && Math.Abs(vertices[0].Z - vertices[2].Z) < bounds.Z && Math.Abs(vertices[2].Z - vertices[1].Z) < bounds.Z);
        }
    }

    public class ColorTriangle : Triangle
    {
        public IList<Point3D> texturecoords;

        public ColorTriangle(IList<Point3D> vertices, IList<Point3D> texturecoords) : base(vertices)
        {
            this.texturecoords = texturecoords;
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for Settings.xaml
    /// </summary>
    public partial class Settings : Window
    {
        MainWindow mainWindow;
        public Settings(MainWindow mainWindow)
        {
            this.mainWindow = mainWindow;
            InitializeComponent();
            color_wire.Text = Properties.Settings.Default.wirecolor;
            color_blob.Text = Properties.Settings.Default.blobcolor;
            Update();
            
        }
        void Update()
        {
            Button_Branch.Content = "Branch: \t\t" + Properties.Settings.Default.branch.ToString();
            Button_SafeMode.Content = "Safe mode: \t" + (Properties.Settings.Default.safemode ? "ON" : "OFF");
            Button_Debug.Content = "Debug Mode: \tNot Available";
            Text_Path.Text = Properties.Settings.Default.steamapps;
            Text_Version.Content = "Version: \tV" + Properties.Settings.Default.version.ToString();
            Button_wires.Content = "Wires: \t\t" + (Properties.Settings.Default.wires == true ? "ON" : "OFF");
            Button_colorwires.Content = "ColorWires:\t" + (Properties.Settings.Default.colorwires == true ? "ON" : "OFF");
            WiresOpacity.Text = Properties.Settings.Default.coloropacity.ToString();
        }

        private void Button_Branch_Click(object sender, RoutedEventArgs e)
        {
            if(Properties.Settings.Default.branch.ToString() == "Test")
            {
                Properties.Settings.Default.branch = "Public";
            }
            else
            {
                Properties.Settings.Default.branch = "Test";
            }
            Update();
        }

        private void Button_SafeMode_Click(object sender, RoutedEventArgs e)
        {
            Properties.Settings.Default.safemode = !Properties.Settings.Default.safemode;

            //MessageBox.Show("this doesn't affect anything yet\nWill allow you to swap any blocks with any blocks, can possibly brick your blueprint");
            
            Update();
        }

        private void Button_Debug_Click(object sender, RoutedEventArgs e)
        {

        }

        private void Text_Path_TextChanged(object sender, TextChangedEventArgs e)
        {
            var bc = new BrushConverter();
            if (System.IO.Directory.Exists(Text_Path.Text))
            {
                Text_Path.Background = (Brush)bc.ConvertFrom("#61937C");
                Properties.Settings.Default.steamapps = Text_Path.Text;
            }
            else
            {
                Text_Path.Background = (Brush)bc.ConvertFrom("#81737C");
            }
        }

        private void Button_update_Click(object sender, RoutedEventArgs e)
        {
            if(new Updater().CheckForUpdates())
            {
                MessageBox.Show("updates available!");
            }
            else
            {
                MessageBox.Show("up to date!");
            }
        }
        private void Button_wires_Click(object sender, RoutedEventArgs e)
        {

            Properties.Settings.Default.wires = !Properties.Settings.Default.wires;
            Update();
        }

        private void Save_settings_Click(object sender, RoutedEventArgs e)
        {
            if (!System.IO.Directory.Exists(Text_Path.Text))
            {
                var bc = new BrushConverter();
                Text_Path.Background = (Brush)bc.ConvertFrom("#ff0000");

            }
            Properties.Settings.Default.Save();
            this.Close();
            MessageBox.Show("Settings saved!");

        }

        private void Button_colorwires_Click(object sender, RoutedEventArgs e)
        {
            Properties.Settings.Default.colorwires = !Properties.Settings.Default.colorwires;
            Update();
        }

        private void color_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox textbox_color = (TextBox)sender;
            if (textbox_color.Text.Length == 7)
            {
                try
                {
                    var bc = new BrushConverter();
                    string color = "#FF" + textbox_color.Text.Substring(1);
                    textbox_color.Background = (Brush)bc.ConvertFrom(color);
                }
                catch
                {
                    //MessageBox.Show("Please use the right format\n \"#123abc\" where 1-9,a-f (hex)");
                    textbox_color.Text = "";
                }
            }
            else
            {
                var bc = new BrushConverter();
                textbox_color.Text = "#2CE6E6";
                textbox_color.Background = (Brush)bc.ConvertFrom("#2CE6E6");
            }
        }

        private void color_SET_Click(object sender, RoutedEventArgs e)
        {

            this.mainWindow.openpaintpicker();
            color_wire.Text = PaintSelector.PaintColor;
            Properties.Settings.Default.wirecolor = color_wire.Text;
        }

        private void color_SET2_Click(object sender, RoutedEventArgs e)
        {

            this.mainWindow.openpaintpicker();
            color_blob.Text = PaintSelector.PaintColor;
            Properties.Settings.Default.blobcolor = color_blob.Text;
        }

        private void Opacity_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox t = (TextBox)sender;
            try
            {
                if (Convert.ToInt32(t.Text) < 0) t.Text = "0";
                if (Convert.ToInt32(t.Text) >255) t.Text = "255";
            }
            catch
            {
                t.Text = "0";
                t.Select(0, 1);
            }
            Properties.Settings.Default.coloropacity = Convert.ToByte(t.Text);
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Newtonsoft.Json.Linq;
using System.Threading;
using System.Drawing;
namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for OpenWindow.xaml
    /// </summary>
    public partial class OpenWindow : Window
    {
        MainWindow mainwindow;
        Thread loadbp;
        public OpenWindow(MainWindow mainWindow)
        {
            this.mainwindow = mainWindow;
            InitializeComponent();

            //load mainwindow.blueprints in list
            loadbp = new Thread(new ThreadStart(Loadblueprints));
            loadbp.SetApartmentState(ApartmentState.STA);
            loadbp.IsBackground = true;
            loadbp.Start();
            //Loadblueprints(""); 
        }
        
        public void Loadblueprints()//threaded
        {
            string searchby = "";
            int totalbps = 0;
            while (true)
            {
                while(totalbps != Database.blueprints.Count())
                {
                    this.Dispatcher.Invoke((Action)(() =>
                    {
                        searchby = TextBox_Search.Text;
                    }));

                    //filter:
                    //if()
                    try
                    {
                        List<Blueprint> items = new List<Blueprint>();
                        foreach (string path in Database.blueprints.Keys)
                        {
                            Blueprint blueprint = new Blueprint(path, Database.blueprints[path]);
                            string name = blueprint.getname();
                            if ((searchby == "" || blueprint.getname().ToLower().Contains(searchby.ToLower()))&& Directory.Exists(path))
                            {
                                items.Add(blueprint);
                            }
                        }
                        this.Dispatcher.Invoke((Action)(() =>
                        {
                            listBox_blueprints.ItemsSource = null;
                            listBox_blueprints.Items.Clear();
                            listBox_blueprints.ItemsSource = items;
                        }));
                    }
                    catch { }
                    totalbps = Database.blueprints.Count();
                }
                try
                {

                    this.Dispatcher.Invoke((Action)(() =>
                    {
                        if (Database.bprefresh == true)
                        {
                            Database.bprefresh = false;
                            button_refresh_Copy_Click(null, null);
                        }
                    }));
                }
                catch
                {
                    break;
                }
                Thread.Sleep(1000);
            }


        }
        private void button_refresh_Copy_Click(object sender, RoutedEventArgs e)
        {
            Label_name.Content = "/";
            loadbp.Abort();
            loadbp = new Thread(new ThreadStart(Loadblueprints));
            loadbp.Start();
        }

        private void ListBox_Selectionchanged(object sender, RoutedEventArgs e)
        {
            if(listBox_blueprints.SelectedIndex!=-1)
            {
                try
                {
                    string bp = ((Blueprint)listBox_blueprints.SelectedItem).blueprintpath.ToString();
                    dynamic desc = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(System.IO.File.ReadAllText(bp + @"\description.json"));
                    Label_name.Content = desc.name;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

        }


        private void button_LOAD_Click(object sender, RoutedEventArgs e)
        {
            Load();
        }

        public void Load()
        {
            Loadwindow l = new Loadwindow();
            string bppath = "";
            try
            {
                bppath = ((Blueprint)listBox_blueprints.SelectedItem).blueprintpath.ToString();

                l.Show();
                new BP(bppath);
                mainwindow.RenderBlueprint();


                if (mainwindow.advancedconnections != null && mainwindow.advancedconnections.IsLoaded) mainwindow.advancedconnections.Update();
                if (mainwindow.advancedcolorwindow != null && mainwindow.advancedcolorwindow.IsLoaded) mainwindow.advancedcolorwindow.Update();
                if (mainwindow.swapblockswindow != null && mainwindow.swapblockswindow.IsLoaded) mainwindow.swapblockswindow.Update();
                if (mainwindow.blockProperties != null && mainwindow.blockProperties.IsLoaded) mainwindow.blockProperties.Update();
                if (mainwindow.areaProperties != null && mainwindow.areaProperties.IsLoaded) mainwindow.areaProperties.Update();
                if (mainwindow.blockPropertiesRAW != null && mainwindow.blockPropertiesRAW.IsLoaded) mainwindow.blockPropertiesRAW.Update();

                l.Close();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                l.Close();
            }
        }

        private void button_DELETE_Click(object sender, RoutedEventArgs e)
        {
            //messagebox YES/NO
            MessageBoxResult result = MessageBox.Show("Are you sure you want to remove this blueprint?"," ",MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Question, MessageBoxResult.No, MessageBoxOptions.DefaultDesktopOnly);
            if(result == MessageBoxResult.Yes)
            {
                try
                {
                    if(((Blueprint)listBox_blueprints.SelectedItem).blueprintpath.Contains(Database.steamapps))
                    {
                        MessageBoxResult res2 = MessageBox.Show("Removing a workshop blueprint will result in the game complaining:\n'failed to find blahblah, verify integrity'!\n\nAre you sure you want to continue?\nYou will have to 'verify integrity' through steam", "WORKSHOP BLUEPRINT!", MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Question, MessageBoxResult.No, MessageBoxOptions.DefaultDesktopOnly);
                        if (res2 == MessageBoxResult.No)
                            throw new OperationCanceledException("Canceled removing workshop blueprint");

                    }
                    Directory.Delete(((Blueprint)listBox_blueprints.SelectedItem).blueprintpath, true);
                    //Database.LoadBpsIn(Database.User_ + "\\blueprints");
                    Database.blueprints.Remove(((Blueprint)listBox_blueprints.SelectedItem).blueprintpath);
                    button_refresh_Copy_Click(null, null);

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message,"failed to remove");
                }
            }
        }
    }
    public class Blueprint
    {
        public string image { get; set; }
        

        public string blueprintpath { get; private set; }
        public BitmapSource imsource { get; private set; }
        //public string name { get; private set; }

        public Blueprint(string blueprintpath, BitmapSource src)
        {
            this.blueprintpath = blueprintpath;
            this.imsource = src;
            this.image = blueprintpath + "\\icon.png";
            //name = getname();
        }

        public string getname()
        {
            try
            {
                dynamic desc = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(System.IO.File.ReadAllText(blueprintpath + @"\description.json"));
                return desc.name.ToString().ToLower();
            }
            catch
            {
                return null;
            }
        }

    }
    
}
<file_sep>﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for AdvancedColor.xaml
    /// </summary>
    public partial class AdvancedColor : Window
    {
        MainWindow window;
        List<Item> ItemList;
        dynamic uuidsbackup;

        public AdvancedColor(MainWindow window)
        {
            this.window = window;
            InitializeComponent();
            this.Update();
        }


        public void Update()
        {
            if (uuidsbackup != BP.GetUsedUuids())
            {
                ItemList = new List<Item>
                {
                    new Item("any", "*")
                };
                foreach (string uuid in BP.GetUsedUuids())
                {
                    if (Database.blocks.ContainsKey(uuid))
                    {
                        ItemList.Add(new Item(Database.blocks[uuid].Name, uuid));
                    }
                }
                dynamic colorlist = new JObject();
                foreach (dynamic body in BP.Blueprint.bodies)
                    foreach(dynamic child in body.childs)
                    {
                        if (child.color.ToString().StartsWith("#")) child.color = child.color.ToString().Substring(1);
                        if (colorlist[child.color.ToString().ToLower()] == null)
                        {
                            colorlist[child.color.ToString().ToLower()] = true;
                            string c = child.color.ToString();

                            Button b = new Button();
                            var bc = new BrushConverter();
                            b.Background = (Brush)bc.ConvertFrom("#"+c);
                            color_list.Items.Add(b);
                        }

                    }

                this.Dispatcher.Invoke((Action)(() =>
                {//this refer to form in WPF application 
                    comboBox_old.Items.Clear();
                }));
                foreach (Item item in ItemList)
                {
                    this.Dispatcher.Invoke((Action)(() =>
                    {//this refer to form in WPF application 
                        comboBox_old.Items.Add(item);
                    }));
                }
            }
            uuidsbackup = BP.GetUsedUuids(); 
        }



        private void TextBox_color_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox textbox_color = (TextBox)sender;
            if (textbox_color.Text.Length == 7)
            {
                try
                {
                    var bc = new BrushConverter();
                    string color = "#FF" + textbox_color.Text.Substring(1);
                    textbox_color.Background = (Brush)bc.ConvertFrom(color);
                }
                catch
                {
                    MessageBox.Show("Please use the right format\n \"#123abc\" where 1-9,a-f (hex)");
                }
            }
            else
            {
                var bc = new BrushConverter();
                textbox_color.Background = (Brush)bc.ConvertFrom("#eeeeee");
            }
        }

        private void Button3_Click(object sender, RoutedEventArgs e)
        {
            window.openpaintpicker();
            textBox_color1.Text = PaintSelector.PaintColor;
        }

        private void Button3_Copy_Click(object sender, RoutedEventArgs e)
        {
            window.openpaintpicker();
            textBox_color2.Text = PaintSelector.PaintColor;
        }

        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://youtu.be/glLgQemUS2I?t=677");
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            TextBox t1 = (TextBox)textBox_color1;
            Brush b = t1.Background;
            string oldcolor = "#" + (b as SolidColorBrush).Color.ToString().Substring(3);

            TextBox t2 = (TextBox)textBox_color2;
            Brush b1 = t2.Background;
            string newcolor = "#" + (b1 as SolidColorBrush).Color.ToString().Substring(3);

            int amountcolored = 0;
            foreach (dynamic body in BP.Blueprint.bodies)
            {
                foreach (dynamic child in body.childs)
                {
                    string token = "#";
                    string color = child.color.ToString();
                    if (color[0] == '#') token = "";
                    if ((token + child.color.ToString().ToLower() == oldcolor.ToLower() || textBox_color1.Text == "#" || textBox_color1.Text == "") && ((comboBox_old.SelectedIndex <= 0) || child.shapeId.ToString() == ((Item)comboBox_old.SelectedItem).UUID.ToLower()))
                    {
                        amountcolored++;
                        child.color = newcolor;
                    }
                }
            }
            if(BP.Blueprint.joints != null)
                foreach (dynamic child in BP.Blueprint.joints)
                {
                    string token = "#";
                    string color = child.color.ToString();
                    if (color[0] == '#') token = "";
                    if ((token + child.color.ToString().ToLower() == oldcolor.ToLower() || textBox_color1.Text == "#" || textBox_color1.Text == "") && ((comboBox_old.SelectedIndex <= 0) || child.shapeId.ToString() == ((Item)comboBox_old.SelectedItem).UUID.ToLower()))
                    {
                        amountcolored++;
                        child.color = newcolor.Substring(1); 
                    }
                }
            if (comboBox_old.SelectedIndex < 0) comboBox_old.SelectedIndex = 0;
            string message = "++ " + amountcolored + " " + oldcolor + " " + ((Item)comboBox_old.SelectedItem).Name + " are now painted " + newcolor + " color";
            if (textBox_color1.Text == "#" || textBox_color1.Text == "")
                message = "++ " + amountcolored + ((Item)comboBox_old.SelectedItem).Name + " are now painted " + newcolor + " color";
            
            new System.Threading.Thread(new System.Threading.ThreadStart(() => { MessageBox.Show(message); })).Start();

            if (amountcolored > 0)
            {
                BP.setblueprint(BP.Blueprint);

                BP.Description.description = BP.Description.description + "\n" + message;
                window.RenderBlueprint();
            }


        }

        private void Color_list_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.window.openpaintpicker();
            PaintSelector.PaintColor = "#" + ((string)((dynamic)color_list.SelectedItem).Background.ToString()).Substring(3,6);
            if (MainWindow.paintSelector.IsLoaded)
                MainWindow.paintSelector.textbox_color.Text = PaintSelector.PaintColor;
        }
    }

    public class Item
    {
        public string Name { get; set; }
        public string UUID { get; set; }

        public Item(string Name, string UUID)
        {
            this.Name = Name;
            this.UUID = UUID;
        }

        public override string ToString()
        {
            return Name;
        }
    }
}
<file_sep>﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ComponentModel;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for Properties.xaml
    /// </summary>
    public partial class BlockProperties : Window
    {
        MainWindow mainwindow;
        List<Item> usedblocks;
        HashSet<string> uuidsbackup;
        dynamic backuplist;
        public BlockProperties(MainWindow mainwindow)
        {
            this.mainwindow = mainwindow;
            InitializeComponent();
            //new Loadwindow(this).Show();
            Loadwindow w = new Loadwindow();
            w.Show();

            Update();

            w.Close();

        }

        public void Update()
        {

            if (uuidsbackup != BP.GetUsedUuids())
            {
                usedblocks = new List<Item>
                {
                    new Item("any", "*")
                };
                foreach (string uuid in BP.GetUsedUuids())
                {
                    if (Database.blocks.ContainsKey(uuid))
                    {
                        usedblocks.Add(new Item(Database.blocks[uuid].Name.ToString(), uuid)); // fill the combobox!   only runs once!
                    }
                }
                filter_type.Items.Clear();
                foreach (Item useditem in usedblocks)
                        filter_type.Items.Add(useditem);

            }
            uuidsbackup = BP.GetUsedUuids(); 
            filter_type.SelectedIndex = 0;
            int i = 0;
            {
                backuplist = new JObject(); //fill 'backup'list with all childs!

                foreach (dynamic body in BP.Blueprint.bodies)
                    foreach (dynamic child in body.childs)
                    {
                        if (child.color.ToString().StartsWith("#"))
                            child.color = child.color.ToString().Substring(1);
                        child.blueprintIndex = i;
                        child.blockname = Database.blocks.ContainsKey(child.shapeId.ToString()) ? Database.blocks[child.shapeId.ToString()].Name : "unknown part";
                        dynamic realpos = BP.getposandbounds(child);

                        if (backuplist[realpos.pos.x.ToString()] == null) backuplist[realpos.pos.x.ToString()] = new JObject();
                        if (backuplist[realpos.pos.x.ToString()][realpos.pos.y.ToString()] == null) backuplist[realpos.pos.x.ToString()][realpos.pos.y.ToString()] = new JObject();
                        if (backuplist[realpos.pos.x.ToString()][realpos.pos.y.ToString()][realpos.pos.z.ToString()] == null) backuplist[realpos.pos.x.ToString()][realpos.pos.y.ToString()][realpos.pos.z.ToString()] = new JObject();
                        if (backuplist[realpos.pos.x.ToString()][realpos.pos.y.ToString()][realpos.pos.z.ToString()][realpos.color.ToString().ToLower()] == null)
                            backuplist[realpos.pos.x.ToString()][realpos.pos.y.ToString()][realpos.pos.z.ToString()][realpos.color.ToString().ToLower()] = new JObject();
                        if (backuplist[realpos.pos.x.ToString()][realpos.pos.y.ToString()][realpos.pos.z.ToString()][realpos.color.ToString().ToLower()][realpos.shapeId.ToString().ToLower()] == null)
                            backuplist[realpos.pos.x.ToString()][realpos.pos.y.ToString()][realpos.pos.z.ToString()][realpos.color.ToString().ToLower()][realpos.shapeId.ToString().ToLower()] = new JObject();
                        backuplist[realpos.pos.x.ToString()][realpos.pos.y.ToString()][realpos.pos.z.ToString()][realpos.color.ToString().ToLower()][realpos.shapeId.ToString().ToLower()][i.ToString()] = child;

                        i++;
                    }
            }

            //fill xyz:
            dynamic bounds = BP.GetBounds();
            filter_x1.Text = bounds.minx.ToString();
            filter_y1.Text = bounds.miny.ToString();
            filter_z1.Text = bounds.minz.ToString();
            filter_x2.Text = bounds.maxx.ToString();
            filter_y2.Text = bounds.maxy.ToString();
            filter_z2.Text = bounds.maxz.ToString();

            filterupdate();
        }

        private void Button_Help_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("find help here: \nhttp://youtube.com/c/brentbatch");
        }

        private void Filter_SET_Click(object sender, RoutedEventArgs e)
        {
            this.mainwindow.openpaintpicker();
            filter_color.Text = PaintSelector.PaintColor;
        }
        private void Filter_pos_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox t = (TextBox)sender;
            try
            {
                if (Convert.ToInt32(t.Text) >= 0) { }
            }
            catch
            {
                if (t.Text == "-")
                {
                    t.Text = "-0";
                    t.Select(1, 1);
                }
                else
                {
                    t.Text = "0";
                    t.Select(0, 1);
                }
            }
            if (this.IsLoaded)
                filterupdate();
        }
        private void filter_type_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.IsLoaded)
                filterupdate();
        }
        private string filtercolor = null;
        private void filter_color_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox textbox_color = (TextBox)sender;
            if (textbox_color.Text.Length == 7)
            {
                try
                {
                    var bc = new BrushConverter();
                    string color = "#FF" + textbox_color.Text.Substring(1);
                    textbox_color.Background = (Brush)bc.ConvertFrom(color);
                    if (textbox_color.Name == "filter_color") filtercolor = textbox_color.Text;
                }
                catch
                {
                    //MessageBox.Show("Please use the right format\n \"#123abc\" where 1-9,a-f (hex)");
                    textbox_color.Text = "";
                }
            }
            else
            {
                var bc = new BrushConverter();
                textbox_color.Background = (Brush)bc.ConvertFrom("#eeeeee");
                if (textbox_color.Name == "filter_color") filtercolor = null;
            }

            if (this.IsLoaded)
                filterupdate();
        }
        private void color_TextChanged(Object sender , TextChangedEventArgs e)
        {
            TextBox textbox_color = (TextBox)sender;
            if (textbox_color.Text.Length == 7)
            {
                try
                {
                    var bc = new BrushConverter();
                    string color = "#FF" + textbox_color.Text.Substring(1);
                    textbox_color.Background = (Brush)bc.ConvertFrom(color);
                }
                catch
                {
                    //MessageBox.Show("Please use the right format\n \"#123abc\" where 1-9,a-f (hex)");
                    textbox_color.Text = "";
                }
            }
            else
            {
                var bc = new BrushConverter();
                textbox_color.Background = (Brush)bc.ConvertFrom("#eeeeee");
            }

        }


        private void filterupdate()
        {
            // if (filter != null && filter.IsAlive) filter.Abort();
            // filter = new Thread(new ThreadStart(filter_output_update));
            // filter.SetApartmentState(ApartmentState.STA);
            // filter.Start();
            Loadwindow l = new Loadwindow();
            l.Show();
            filter_output_update();
            l.Close();
        }
        //Thread filter;

        private void filter_output_update()
        {

            {

                dynamic bounds = BP.GetBounds();
                int x1 = bounds.minx, y1 = bounds.maxx, z1 = bounds.miny, x2 = bounds.maxy, y2 = bounds.minz, z2 = bounds.maxz;
                string type = "*";//nullable! = any

                this.Dispatcher.Invoke((Action)(() =>
                {//this refer to form in WPF application 

                    if (filter_output.Items.Count > 0) filter_output.Items.Clear();
                    if (filter_x1.Text != "") x1 = Convert.ToInt32(filter_x1.Text);
                    if (filter_y1.Text != "") y1 = Convert.ToInt32(filter_y1.Text);
                    if (filter_z1.Text != "") z1 = Convert.ToInt32(filter_z1.Text);
                    if (filter_x2.Text != "") x2 = Convert.ToInt32(filter_x2.Text);
                    if (filter_y2.Text != "") y2 = Convert.ToInt32(filter_y2.Text);
                    if (filter_z2.Text != "") z2 = Convert.ToInt32(filter_z2.Text);//0.1! = any
                    if (filter_type.SelectedIndex < 0) filter_type.SelectedIndex = 0;
                    if (filter_type.SelectedIndex >= 0)
                        type = ((Item) filter_type.SelectedItem).UUID;
                    this.mainwindow.setMarker2((x1 + x2+0.0f) / 2, (y1 + y2 + 0.0f) / 2, (z1 + z2 + 0.0f) / 2, (x2 - x1), (y2 - y1), (z2 - z1));
                }));
                string color = filtercolor;//nullable! = any


                for (int x = x1; x <= x2; x++)
                    if (backuplist[x.ToString()] != null)
                        for (int y = y1; y < y2; y++)
                            if (backuplist[x.ToString()][y.ToString()] != null)
                                for (int z = z1; z < z2; z++)
                                    if (backuplist[x.ToString()][y.ToString()][z.ToString()] != null)
                                    {
                                        if (color == null)
                                        {
                                            foreach (dynamic xyzcolor in backuplist[x.ToString()][y.ToString()][z.ToString()])
                                                if (type == "*")
                                                {
                                                    foreach (dynamic childuuid in xyzcolor.Value)
                                                    {
                                                        foreach (dynamic child in childuuid.Value)
                                                            this.Dispatcher.Invoke((Action)(() =>
                                                            {//this refer to form in WPF application 
                                                                filter_output.Items.Add(child.Value);  //any color any type
                                                            }));
                                                    }
                                                }
                                                else
                                                {
                                                    if (xyzcolor.Value[type.ToLower()] != null)
                                                        foreach (dynamic child in xyzcolor.Value[type.ToLower()])
                                                            this.Dispatcher.Invoke((Action)(() =>
                                                            {//this refer to form in WPF application 
                                                                filter_output.Items.Add(child.Value); //any color , one type
                                                            }));
                                                }
                                        }
                                        else
                                        {
                                            if (color.StartsWith("#"))
                                                color = color.Substring(1).ToLower();
                                            if (backuplist[x.ToString()][y.ToString()][z.ToString()][color] != null)
                                            {
                                                if (type == "*")
                                                {
                                                    foreach (dynamic childuuid in backuplist[x.ToString()][y.ToString()][z.ToString()][color])
                                                    {
                                                        foreach (dynamic child in childuuid.Value)
                                                            this.Dispatcher.Invoke((Action)(() =>
                                                            {//this refer to form in WPF application 
                                                                filter_output.Items.Add(child.Value); //one color , any type
                                                            }));
                                                    }
                                                }
                                                else
                                                {
                                                    if (backuplist[x.ToString()][y.ToString()][z.ToString()][color][type] != null)
                                                        foreach (dynamic child in backuplist[x.ToString()][y.ToString()][z.ToString()][color][type])
                                                            this.Dispatcher.Invoke((Action)(() =>
                                                            {//this refer to form in WPF application 
                                                                filter_output.Items.Add(child.Value);  //one color, one type
                                                            }));
                                                }
                                            }
                                        }
                                    }

                try
                {
                    this.Dispatcher.Invoke((Action)(() =>
                    {//this refer to form in WPF application 
                        disableAll();
                    }));
                }
                catch { }
            }
        }
        int selectedchildindex=-1;
        private void filter_output_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            disableAll();
            if (filter_output.SelectedIndex != -1)
            {

                var bc = new BrushConverter();
                string selectedcolor = ((dynamic)filter_output.SelectedItem).color;
                string color = "#FF" + (selectedcolor.StartsWith("#")==true? selectedcolor.Substring(1): selectedcolor);
                //filter_output_color.Fill = (Brush)bc.ConvertFrom(color);
                //clear other options, enable/disable several

                dynamic selectedblock = ((dynamic)filter_output.SelectedItem);

                dynamic realpos = BP.getposandbounds(selectedblock);
                this.mainwindow.setMarker(Convert.ToInt32(realpos.pos.x) + (Convert.ToDouble(realpos.bounds.x)/2), Convert.ToInt32(realpos.pos.y) + (Convert.ToDouble(realpos.bounds.y) / 2), Convert.ToDouble(realpos.pos.z) + (Convert.ToDouble(realpos.bounds.z) / 2));

                selectedchildindex = selectedblock.blueprintIndex;
                Edit_general.Visibility = Visibility.Visible;
                new_x.Text = selectedblock.pos.x;
                new_y.Text = selectedblock.pos.y;
                new_z.Text = selectedblock.pos.z;
                new_color.Text = "#" + selectedblock.color;
                new_xaxis.Text = selectedblock.xaxis;
                new_zaxis.Text = selectedblock.zaxis;
                if(selectedblock.controller != null) //
                {
                    if(selectedblock.controller.mode != null) //logic gate!
                    {
                        
                        new_gatemode.SelectedIndex = selectedblock.controller.mode;
                        Edit_gate.Visibility = Visibility.Visible;
                        //mode 0-5
                    }
                    if(selectedblock.controller.buttonMode != null)//sensor!
                    {
                        // colorMode & range & color
                        new_sensorcolormode.IsChecked = selectedblock.controller.colorMode;
                        if (selectedblock.controller.colorMode == null) new_sensorcolormode.IsChecked = false;
                        new_sensorrange.Text = selectedblock.controller.range;
                        new_sensorcolor.Text = "#"+selectedblock.controller.color;
                        if (selectedblock.controller.color == null) new_sensorcolor.Text = "#eeeeee";
                        Edit_sensor.Visibility = Visibility.Visible;
                    }
                    if (selectedblock.controller.luminance != null)//light!
                    {
                        //coneAngle  & luminance
                        new_coneangle.Text = selectedblock.controller.coneAngle;
                        new_luminance.Text = selectedblock.controller.luminance;
                        Edit_lamp.Visibility = Visibility.Visible;
                    }
                    if(selectedblock.controller.seconds != null)//timer
                    {
                        //seconds ticks
                        new_timerseconds.Text = selectedblock.controller.seconds;
                        new_timerticks.Text = selectedblock.controller.ticks;
                        Edit_Timer.Visibility = Visibility.Visible;
                    }

                    if (selectedblock.controller.timePerFrame != null)//controller!
                    {
                        //playMode timePerFrame joints
                        new_controllerloopmode.IsChecked = selectedblock.controller.playMode;
                        new_controllertimeperframe.Text = selectedblock.controller.timePerFrame;
                        new_controllercontrolls.Items.Clear();
                        if (selectedblock.controller.joints != null)
                            foreach (dynamic joint in selectedblock.controller.joints)
                            {

                                joint.controller0 = joint.frames[0].targetAngle.ToString();
                                joint.controller1 = joint.frames[1].targetAngle.ToString();
                                joint.controller2 = joint.frames[2].targetAngle.ToString();
                                joint.controller3 = joint.frames[3].targetAngle.ToString();
                                joint.controller4 = joint.frames[4].targetAngle.ToString();
                                joint.controller5 = joint.frames[5].targetAngle.ToString();
                                joint.controller6 = joint.frames[6].targetAngle.ToString();
                                joint.controller7 = joint.frames[7].targetAngle.ToString();
                                joint.controller8 = joint.frames[8].targetAngle.ToString();
                                joint.controller9 = joint.frames[9].targetAngle.ToString();
                                new_controllercontrolls.Items.Add(joint);

                            }
                        /*
                        if (selectedblock.controller.controllers != null)
                            foreach (dynamic joint in selectedblock.controller.frames)
                            {
                                joint.controller0 = joint.frames[0].targetAngle.ToString();
                                joint.controller1 = joint.frames[1].targetAngle.ToString();
                                joint.controller2 = joint.frames[2].targetAngle.ToString();
                                joint.controller3 = joint.frames[3].targetAngle.ToString();
                                joint.controller4 = joint.frames[4].targetAngle.ToString();
                                joint.controller5 = joint.frames[5].targetAngle.ToString();
                                joint.controller6 = joint.frames[6].targetAngle.ToString();
                                joint.controller7 = joint.frames[7].targetAngle.ToString();
                                joint.controller8 = joint.frames[8].targetAngle.ToString();
                                joint.controller9 = joint.frames[9].targetAngle.ToString();
                                new_controllercontrolls.Items.Add(joint);

                            }*/

                        Edit_controller.Visibility = Visibility.Visible;
                    }
                }
                button_render.IsEnabled = true;



            }
        }

        private void disableAll()
        {
            Edit_controller.Visibility = Visibility.Collapsed;
            Edit_gate.Visibility = Visibility.Collapsed;
            Edit_general.Visibility = Visibility.Collapsed;
            Edit_lamp.Visibility = Visibility.Collapsed;
            Edit_sensor.Visibility = Visibility.Collapsed;
            Edit_Timer.Visibility = Visibility.Collapsed;
            button_render.IsEnabled = false;
            this.mainwindow.Marker = null;
            mainwindow.Image_blueprint.DataContext = "";
            mainwindow.Image_blueprint.DataContext = mainwindow;

        }

        private void SET_Copy_Click(object sender, RoutedEventArgs e)
        {

            this.mainwindow.openpaintpicker();
            new_sensorcolor.Text = PaintSelector.PaintColor;

        }
        private void SET_Copy1_Click(object sender, RoutedEventArgs e)
        {
            this.mainwindow.openpaintpicker();
            new_lampcolor.Text = PaintSelector.PaintColor;
        }
        private void SET_Copy2_Click(object sender, RoutedEventArgs e)
        {
            this.mainwindow.openpaintpicker();
            new_color.Text = PaintSelector.PaintColor;
        }


        private void new_controllercontrolls_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            new_selectedcontroller.DataContext = (dynamic)new_controllercontrolls.SelectedItem;
            if (new_controllercontrolls.SelectedItem != null && ((dynamic)new_controllercontrolls.SelectedItem).reverse == true)
                new_controllerreverse.IsChecked = true;
        }

        private void new_controller_joint_Changed(object sender, TextChangedEventArgs e)
        {
            dynamic test = (dynamic)new_selectedcontroller.DataContext;
        }

        private void new_controllerreverse_Click(object sender, RoutedEventArgs e)
        {
            new_controller_joint_Changed(null, null);
        }

        private void button_help_Click_1(object sender, RoutedEventArgs e)
        {
            System.Windows.MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("Watch this video on how to use: \nhttps://www.youtube.com/c/brentbatch", "Tutorial?", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Asterisk);
            if (messageBoxResult.ToString() == "Yes")
            { System.Diagnostics.Process.Start("https://youtu.be/glLgQemUS2I?t=799"); }
        }

        private void button_render_Click(object sender, RoutedEventArgs e)
        {
            //blueprintIndex
            foreach(dynamic body in BP.Blueprint.bodies)
                foreach(dynamic child in body.childs)
                    if (Convert.ToInt32(child.blueprintIndex) == selectedchildindex)
                    {

                        if (Edit_controller.IsVisible)
                        {
                            child.controller.joints.Clear();
                            foreach (dynamic item in (dynamic)new_controllercontrolls.Items)
                            {
                                item.startAngle = Convert.ToInt32(item.startAngle);
                                item.frames[0].targetAngle = Convert.ToInt32(item.controller0);
                                item.frames[1].targetAngle = Convert.ToInt32(item.controller1);
                                item.frames[2].targetAngle = Convert.ToInt32(item.controller2);
                                item.frames[3].targetAngle = Convert.ToInt32(item.controller3);
                                item.frames[4].targetAngle = Convert.ToInt32(item.controller4);
                                item.frames[5].targetAngle = Convert.ToInt32(item.controller5);
                                item.frames[6].targetAngle = Convert.ToInt32(item.controller6);
                                item.frames[7].targetAngle = Convert.ToInt32(item.controller7);
                                item.frames[8].targetAngle = Convert.ToInt32(item.controller8);
                                item.frames[9].targetAngle = Convert.ToInt32(item.controller9);
                                child.controller.joints.Add(item);
                            }
                        }
                        if(Edit_gate.IsVisible)
                        {
                            child.controller.mode = new_gatemode.SelectedIndex;
                        }
                        if(Edit_general.IsVisible)
                        {
                            child.pos.x = Convert.ToInt32(new_x.Text);
                            child.pos.y = Convert.ToInt32(new_y.Text);
                            child.pos.z = Convert.ToInt32(new_z.Text);
                            child.color = new_color.Text;
                            child.xaxis = Convert.ToInt32(new_xaxis.Text);
                            child.zaxis = Convert.ToInt32(new_zaxis.Text);

                            dynamic selectedblock = ((dynamic)filter_output.SelectedItem);
                            selectedblock.pos.x = child.pos.x;
                            selectedblock.pos.y = child.pos.y;
                            selectedblock.pos.z = child.pos.z;
                            selectedblock.xaxis = child.xaxis;
                            selectedblock.zaxis = child.zaxis;
                        }
                        if(Edit_sensor.IsVisible)
                        {
                            child.controller.colorMode = new_sensorcolormode.IsChecked;
                            child.controller.range = Convert.ToInt32(new_sensorrange.Text);
                            child.controller.color = new_sensorcolor.Text;
                        }
                        if(Edit_lamp.IsVisible)
                        {
                            child.controller.coneAngle = Convert.ToInt32(new_coneangle.Text);
                            child.controller.luminance = Convert.ToInt32(new_luminance.Text);
                        }
                        if(Edit_Timer.IsVisible)
                        {
                            child.controller.seconds = Convert.ToInt32(new_timerseconds.Text);
                            child.controller.ticks = Convert.ToInt32(new_timerticks.Text);
                        }
                }


            Loadwindow w = new Loadwindow();
            w.Show();

            BP.Description.description = BP.Description.description += "++ Applied some block property changes ";
            BP.setblueprint(BP.Blueprint);
            this.mainwindow.RenderBlueprint();
            //Update();
            dynamic bounds = BP.GetBounds();
            int x1 = bounds.minx, y1 = bounds.maxx, z1 = bounds.miny, x2 = bounds.maxy, y2 = bounds.minz, z2 = bounds.maxz;
            this.Dispatcher.Invoke((Action)(() =>
            {//this refer to form in WPF application 
                if (filter_x1.Text != "") x1 = Convert.ToInt32(filter_x1.Text);
                if (filter_y1.Text != "") y1 = Convert.ToInt32(filter_y1.Text);
                if (filter_z1.Text != "") z1 = Convert.ToInt32(filter_z1.Text);
                if (filter_x2.Text != "") x2 = Convert.ToInt32(filter_x2.Text);
                if (filter_y2.Text != "") y2 = Convert.ToInt32(filter_y2.Text);
                if (filter_z2.Text != "") z2 = Convert.ToInt32(filter_z2.Text);//0.1! = any
                this.mainwindow.setMarker2((x1 + x2 + 0.0f) / 2, (y1 + y2 + 0.0f) / 2, (z1 + z2 + 0.0f) / 2, (x2 - x1), (y2 - y1), (z2 - z1));
            }));
            w.Close();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            this.mainwindow.Marker = null;
            this.mainwindow.setMarker2(0, 0, 0, 0, 0, 0);
            this.mainwindow.Marker2 = new System.Windows.Media.Media3D.Model3DGroup();
        }

    }
}
<file_sep>﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Text;
using Assimp;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;
using HelixToolkit.Wpf;
using System.Windows.Media;
using System.Drawing;
using System.Windows.Threading;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using System.Runtime.InteropServices;
using System.Xml;
using System.Text.RegularExpressions;
using Newtonsoft.Json;

namespace Advanced_Blueprint_Tools
{
    public static class Database
    {
        public static string steamapps { get; private set; }
        public static string User_ { get; private set; } //path
        public static string ScrapData { get; private set; } = "";
        public static string SurvivalData { get; private set; } = "";
        private static string ModDatabase = "";

        public static long UserID { get; private set; }

        public static Dictionary<string, Blockobject> blocks = new Dictionary<string, Blockobject>();//uuid, block
        public static Dictionary<string, string> usedmods = new Dictionary<string, string>();//id, name
        public static Dictionary<string, BitmapSource> blueprints = new Dictionary<string, BitmapSource>();//path, img
        public static List<Notification> Notifications = new List<Notification>();

        public static bool bprefresh;

        public static void LoadAllBlocks()
        {
            LoadVanillaObjects();
            LoadModObjects();
        }
        public static string findPaths()
        {
            string userdir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Axolot Games\\Scrap Mechanic\\User";

            DateTime lasthigh = new DateTime(1900, 1, 1);
            string dir = "";
            foreach (string subdir in Directory.GetDirectories(userdir)) //get user_numbers folder that is last used
            {
                DirectoryInfo fi1 = new DirectoryInfo(subdir + @"\blueprints");
                DateTime created = fi1.LastWriteTime;
                fi1 = new DirectoryInfo(subdir);

                if (created > lasthigh)
                {
                    dir = subdir;
                    lasthigh = created;
                }
            }
            User_ = dir;
            

            steamapps = Properties.Settings.Default.steamapps;
            /*
            {//not yet
                if(Properties.Settings.Default.times == 3)
                    System.Diagnostics.Process.Start("http://www.youtube.com/c/brentbatch?sub_confirmation=1");
            }*/

            if (File.Exists("steamapps") && !File.Exists("config"))
                File.Copy("steamapps", "config");

            dynamic config = new JObject();
            if (File.Exists("config") && !System.IO.Directory.Exists(steamapps + @"\common\Scrap Mechanic\Data\Objects\Database\ShapeSets"))
            {
                try
                {
                    config = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(File.ReadAllText("steamapps"));
                }
                catch {

                }
                if (config.steamapps != null)
                {
                    steamapps = config.steamapps.ToString();
                    Properties.Settings.Default.steamapps = config.steamapps.ToString();
                }
                if (config.times != null)
                    Properties.Settings.Default.times = Convert.ToInt32(config.times.ToString());
                if (config.safemode == true)
                    Properties.Settings.Default.safemode = config.safemode == true ? true : false;
                if (config.wires == true)
                    Properties.Settings.Default.wires = config.wires == true ? true : false;
                if (config.colorwires == true)
                    Properties.Settings.Default.colorwires = config.colorwires == true ? true : false;
                if (config.wirecolor != null)
                    Properties.Settings.Default.wirecolor = config.wirecolor;
                if (config.blobcolor != null)
                    Properties.Settings.Default.blobcolor = config.blobcolor;
                if (config.coloropacity != null)
                    Properties.Settings.Default.coloropacity = Convert.ToByte(config.coloropacity.ToString());

            }
            Properties.Settings.Default.times++;

            if (steamapps == null)
            {
                steamapps = "";
            }

            if (System.IO.Directory.Exists(Environment.GetEnvironmentVariable("ProgramFiles(x86)") + @"\Steam\SteamApps\common\Scrap Mechanic\Data\Objects\Database\ShapeSets"))
            {
                steamapps = Environment.GetEnvironmentVariable("ProgramFiles(x86)") + "\\steam\\SteamApps";
            }
            else if (System.IO.Directory.Exists(@"C:\Program Files (x86)\Steam\SteamApps\common\Scrap Mechanic\Data\Objects\Database\ShapeSets"))
            {
                steamapps = @"C:\Program Files (x86)\Steam\SteamApps";
            }
            else if (System.IO.Directory.Exists(@"D:\Program Files (x86)\Steam\SteamApps\common\Scrap Mechanic\Data\Objects\Database\ShapeSets"))
            {
                steamapps = @"D:\Program Files (x86)\Steam\SteamApps";
            }
            else if (System.IO.Directory.Exists(steamapps + @"\common\Scrap Mechanic\Data\Objects\Database\ShapeSets"))
            {
                //i already know steamapps!
            }
            else
            {
                while (!System.IO.Directory.Exists(ScrapData + @"\Objects\Database\ShapeSets"))
                {
                    MessageBoxResult result = MessageBox.Show("could not find the gamefiles folder which is needed to get the block properties\nPlease select the Scrap Mechanic folder, It contains: Cache,Data,Logs,Release,...\n\nSteam Library > Right click scrap mechanic > properties > Local Files > browse local files > Copy path from the folder", "Unusual folder location!", MessageBoxButton.OKCancel);
                    if (result != MessageBoxResult.OK)
                    {
                        MessageBox.Show("continuing without loading resources.\nWorking processes: \n- Loading blueprints -although a bit broken\n- sphere generator\n- mirror mode");
                    }

                    System.Windows.Forms.FolderBrowserDialog fbD = new System.Windows.Forms.FolderBrowserDialog();
                    fbD.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);

                    fbD.ShowDialog();
                    string scrap = fbD.SelectedPath;
                    try
                    {
                        steamapps = System.IO.Path.GetDirectoryName(System.IO.Path.GetDirectoryName(scrap));
                    }
                    catch { steamapps = ""; }
                    ScrapData = scrap + "\\Data";
                }
            }

            if (ScrapData == "")
                ScrapData = steamapps + @"\common\Scrap Mechanic\Data";

            if (SurvivalData == "")
                SurvivalData = steamapps + @"\common\Scrap Mechanic\Survival";
            
            if (steamapps != "")
                ModDatabase = steamapps + @"\workshop\content\387990";

            Properties.Settings.Default.steamapps = steamapps;
            Properties.Settings.Default.Save();
            return steamapps;
        }

        public static void LoadAllBlueprints()
        {
            string blueprintdir = User_ + "\\blueprints";
            UserID = Convert.ToInt64(Path.GetFileName(User_).ToString().Substring(5));
            LoadBpsIn(blueprintdir);
            if (Directory.Exists(steamapps + @"\workshop\content\387990"))
                LoadBpsIn(steamapps + @"\workshop\content\387990");

            Thread updatebps = new Thread(new ThreadStart(() =>
            {
                while(true)
                {
                    if (Directory.GetLastWriteTime(blueprintdir) > DateTime.Now.AddSeconds(-2))
                        LoadBpsIn(blueprintdir);
                    if (Directory.Exists(steamapps + @"\workshop\content\387990") &&
                    Directory.GetLastWriteTime(steamapps + @"\workshop\content\387990") > DateTime.Now.AddSeconds(-2))
                        LoadBpsIn(Database.steamapps + @"\workshop\content\387990");

                    Thread.Sleep(1500);
                }
            }));
            updatebps.IsBackground = true;
            updatebps.Start();

        }

        public static void LoadBpsIn(string directory)
        {
            ImageToBitmapSourceConverter converter = new ImageToBitmapSourceConverter();
            foreach (string blueprint in Directory.GetDirectories(directory))
            {
                if (File.Exists(blueprint + @"\blueprint.json") /*&& File.Exists(blueprint + @"\icon.png") && File.Exists(blueprint + @"\description.json")*/)
                {
                    if (!File.Exists(blueprint + @"\description.json"))
                    {
                        dynamic desc = new JObject();
                        desc.name = "unnamed blueprint";
                        desc.description = "has no name";
                        //create new description
                        File.WriteAllText(blueprint + @"\description.json", desc.ToString());
                    }

                    if (File.Exists(blueprint + @"\icon.png"))
                    {
                        Image image = Image.FromFile(blueprint + @"\icon.png");
                        if (!blueprints.ContainsKey(blueprint))
                            blueprints.Add(blueprint, (BitmapSource)converter.Convert((Image)image.Clone(),null,null,null));
                        else
                        {
                            if (!blueprints[blueprint].Equals((Image)image.Clone()))
                            {
                                //blueprints[blueprint].;
                                blueprints[blueprint] = (BitmapSource)converter.Convert((Image)image.Clone(), null, null, null);
                            }
                        }
                        image.Dispose();
                        
                    }
                    else
                    {
                        //load with 'missing icon' or sth
                        Image image = Image.FromFile("missingicon.bmp");
                        if (!blueprints.ContainsKey(blueprint))
                            blueprints.Add(blueprint, (BitmapSource)converter.Convert((Image)image.Clone(), null, null, null));
                        else
                        {
                            if (!blueprints[blueprint].Equals((Image)image.Clone()))
                            {
                                //blueprints[blueprint].;
                                blueprints[blueprint] = (BitmapSource)converter.Convert((Image)image.Clone(), null, null, null);
                            }
                        }
                        image.Dispose();
                    }
                }
                else if(File.Exists(blueprint + @"\icon.png"))
                {
                    //go over all files, if no .txt files or directories, remove folder

                    bool dirs = false;
                    foreach (string subdir in Directory.GetDirectories(blueprint))
                    {
                        if (Directory.Exists(subdir)) dirs = true;
                    }
                    if(!dirs)
                    {
                        bool hasTxtFile = false;
                        foreach (string subfile in Directory.GetFiles(blueprint))
                        {
                            string ext = Path.GetExtension(subfile);
                            if (ext == ".txt")
                                hasTxtFile = true;
                        }
                        if (!hasTxtFile)
                            Directory.Delete(blueprint, true);
                    }
                }
            }
        }
        

        private static void LoadVanillaObjects()
        {
            string inventorydecpath = ScrapData + @"\Gui\Language\English\InventoryItemDescriptions.json";
            JObject inventoryitemdesc = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(System.IO.File.ReadAllText(inventorydecpath)) as dynamic;
            
            //VANILLA BLOCKS: 
            dynamic blockz = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(
                System.IO.File.ReadAllText(ScrapData + @"\Objects\Database\ShapeSets\blocks.json"));

            foreach (dynamic prop in blockz)
            {
                foreach (dynamic part in blockz[prop.Name])
                {
                    string name = "unnamed shape " + part.uuid.ToString();
                    if (inventoryitemdesc[part.uuid.ToString()] != null)
                        name = inventoryitemdesc[part.uuid.ToString()].title.ToString();
                    
                    blocks.Add(
                        part.uuid.ToString(),
                        new Block(ScrapData, name, "vanilla", part,null)
                        );

                }
            }

            //VANILLA PARTS:
            string ScrapShapeSets = ScrapData + @"\Objects\Database\ShapeSets";
            foreach (string file in System.IO.Directory.GetFiles(ScrapShapeSets))
            {
                dynamic parts = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(System.IO.File.ReadAllText(file));
                foreach (dynamic prop in parts)
                {
                    foreach (dynamic part in parts[prop.Name])
                    {
                        try
                        {
                            string name = "unnamed shape " + part.uuid.ToString();
                            if (inventoryitemdesc[part.uuid.ToString()] != null)
                                name = inventoryitemdesc[part.uuid.ToString()].title.ToString();

                            if (part.renderable != null)//only adding parts here, modded shit not allowed
                                blocks.Add(
                                    part.uuid.ToString(),
                                    new Part(ScrapData, name, "vanilla", part, null, true)
                                    );
                        }
                        catch (Exception e)
                        {
                            Notifications.Add(new Notification(
                                "unloadable file",
                                new Task(() =>
                                {
                                    System.Windows.MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show(e.Message+"\n\nopen file?", "error in vanilla files!", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly);
                                    if (messageBoxResult == MessageBoxResult.Yes)
                                    {
                                        System.Diagnostics.Process.Start(file);
                                    }
                                })
                            ));
                        }
                    }
                }
            }
        }
        

        private static void LoadModObjects()
        {
            List<String> workshoppages = new List<string>();

            if (ModDatabase != "")
                foreach (string folder in System.IO.Directory.GetDirectories(ModDatabase))
                {
                    //modded blocks:
                    if (System.IO.Directory.Exists(folder + @"\Objects\Database\ShapeSets"))//its a mod, not a blueprint (workshop dir contains blueprints too)
                    {
                        dynamic inventoryitemdesc = new JObject();
                        try
                        {
                            inventoryitemdesc = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(System.IO.File.ReadAllText(folder + @"\Gui\Language\English\inventoryDescriptions.json"));
                            if (inventoryitemdesc == null)
                                inventoryitemdesc = new JObject();
                        }
                        catch
                        {//not parseable
                            if (!workshoppages.Contains("http://steamcommunity.com/sharedfiles/filedetails/?id=" + System.IO.Path.GetFileName(folder)))
                                workshoppages.Add("http://steamcommunity.com/sharedfiles/filedetails/?id=" + System.IO.Path.GetFileName(folder));
                            Notifications.Add(new Notification(
                                "unloadable file",
                                new Task(() =>
                                {
                                    System.Windows.MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("item desc not parseable, open location?", "unparseable file!", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly);
                                    if (messageBoxResult == MessageBoxResult.Yes)
                                    {
                                            System.Diagnostics.Process.Start(folder +@"\Gui\Language\");
                                    }
                                })
                            ));
                        }

                        int conflictusemod = 0; //(1 use old, 2 use new

                        foreach (string file in System.IO.Directory.GetFiles(folder + @"\Objects\Database\ShapeSets"))
                            if (System.IO.Path.GetExtension(file).ToLower() == ".json")
                            {
                                dynamic parts = null;
                                try
                                {
                                    //try to parse the usual way
                                    string text = System.IO.File.ReadAllText(file); 
                                    parts = Newtonsoft.Json.Linq.JObject.Parse(text);
                                }
                                catch (Exception e)
                                {//not parseable, add to naughty list
                                    if (!workshoppages.Contains("http://steamcommunity.com/sharedfiles/filedetails/?id=" + System.IO.Path.GetFileName(folder)))
                                        workshoppages.Add("http://steamcommunity.com/sharedfiles/filedetails/?id=" + System.IO.Path.GetFileName(folder));

                                    Notifications.Add(new Notification(
                                        "unparseable file",
                                        new Task(() =>
                                        {
                                            System.Windows.MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("unparseable file found:\n" + file, "unparseable file!\nError:\n" + e.Message, System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly);
                                            if (messageBoxResult == MessageBoxResult.Yes)
                                            {
                                                System.Diagnostics.Process.Start(file);
                                            }
                                        })
                                    ));
                                }


                                dynamic moddesc = Newtonsoft.Json.Linq.JObject.Parse(System.IO.File.ReadAllText(folder + @"\description.json"));

                                if (parts != null)
                                    foreach (dynamic prop in parts)
                                    {
                                        foreach (dynamic part in parts[prop.Name])
                                        {
                                            try
                                            {

                                                if (!(part is JObject))
                                                {
                                                    continue;
                                                }

                                                if (moddesc.name != null)
                                                {
                                                    if (conflictusemod == 0 && blocks.ContainsKey(part.uuid.ToString()) && blocks[part.uuid.ToString()].Path != folder)
                                                    {
                                                        conflictusemod = 1;//keep mod1

                                                        string uuid = part.uuid.ToString();
                                                        string mod1 = blocks[part.uuid.ToString()].Mod;
                                                        string mod2 = moddesc.name;

                                                        if (mod1.ToString() == "vanilla")
                                                        {
                                                            conflictusemod = 2;//overwrite, people have old installed mods in vanilla files!
                                                        }
                                                        else
                                                        {
                                                            MessageBoxResult messageBoxResult = MessageBox.Show
                                                                ("\"" + mod1 + "\" is using some(or all) uuid's of mod \"" + mod2 + "\"\n\nOverwrite blocks from \"" + mod1 + "\" with the blocks from \"" + mod2 + "\" ?\n\n" + file, "Conflicting mods!!", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly);
                                                            if (messageBoxResult == MessageBoxResult.Yes)
                                                            {
                                                                conflictusemod = 2;//overwrite!
                                                            }
                                                        }

                                                        //System.Diagnostics.Process.Start(blocks[part.uuid.ToString()].Modfolder.ToString());
                                                        //System.Diagnostics.Process.Start(folder);
                                                    }

                                                    if (conflictusemod != 1)//OVERWRITE if 2 , 0=no conflict
                                                    {
                                                        usedmods[moddesc.fileId.ToString()] = moddesc.name.ToString();

                                                        string name = "unnamed shape " + part.uuid.ToString();
                                                        if (inventoryitemdesc[part.uuid.ToString()] != null)
                                                            name = inventoryitemdesc[part.uuid.ToString()].title.ToString();

                                                        if (part.renderable != null)//part
                                                        {
                                                            if(blocks.ContainsKey(part.uuid.ToString()))
                                                            { //OVERWRITE
                                                                blocks[part.uuid.ToString()] =
                                                                    new Part(folder, name, moddesc.name.ToString(), part, moddesc);
                                                            }
                                                            else
                                                            blocks.Add(
                                                                part.uuid.ToString(),
                                                                new Part(folder, name, moddesc.name.ToString(), part, moddesc)
                                                                );
                                                        }
                                                        else //block!
                                                        {
                                                            if (blocks.ContainsKey(part.uuid.ToString()))
                                                            { //OVERWRITE
                                                                blocks[part.uuid.ToString()] =
                                                                    new Block(folder, name, moddesc.name.ToString(), part, moddesc);
                                                            }
                                                            else
                                                                blocks.Add(
                                                                    part.uuid.ToString(),
                                                                    new Block(folder, name, moddesc.name.ToString(), part, moddesc)
                                                                );
                                                            //part.dif asg nor
                                                        }
                                                    }
                                                }
                                                else
                                                {

                                                    Notifications.Add(new Notification(
                                                        "broken appdata mod",
                                                        new Task(() =>
                                                        {
                                                            MessageBox.Show("broken mod description!\nfolder: " + folder);

                                                        })
                                                    ));
                                                    }

                                            }
                                            catch
                                            {
                                                if(!workshoppages.Contains("http://steamcommunity.com/sharedfiles/filedetails/?id=" + System.IO.Path.GetFileName(folder)))
                                                    workshoppages.Add("http://steamcommunity.com/sharedfiles/filedetails/?id=" + System.IO.Path.GetFileName(folder));
                                            }
                                        }
                                    }
                            }
                    }
                    
                }


            try //appdata mods
            {
                string appdatamods = User_ + "\\Mods";
                
                foreach (string folder in System.IO.Directory.GetDirectories(appdatamods))
                {
                    if (System.IO.Directory.Exists(folder + @"\Objects\Database\ShapeSets"))
                    {
                        dynamic inventoryitemdesc = new JObject();
                        try
                        {
                            inventoryitemdesc = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(System.IO.File.ReadAllText(folder + @"\Gui\Language\English\inventoryDescriptions.json"));
                            if (inventoryitemdesc == null)
                                inventoryitemdesc = new JObject();
                        }
                        catch (Exception e)
                        {

                            Notifications.Add(new Notification(
                                "broken appdata mod",
                                new Task(() =>
                                {
                                    MessageBox.Show(e.Message + "\n\n" + folder+ @"\Gui\Language\English\inventoryDescriptions.json", "broken appdata mod!", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly);

                                })
                            ));
                        }

                        foreach (string file in System.IO.Directory.GetFiles(folder + @"\Objects\Database\ShapeSets"))
                            if (System.IO.Path.GetExtension(file).ToLower() == ".json")
                            {
                                dynamic parts = null;
                                try
                                {
                                    parts = Newtonsoft.Json.Linq.JObject.Parse(System.IO.File.ReadAllText(file));
                                }
                                catch (Exception e)
                                {

                                    Notifications.Add(new Notification(
                                        "broken appdata mod",
                                        new Task(() =>
                                        {
                                            MessageBox.Show(e.Message + "\n\n" + file, "broken appdata mod!", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly);

                                        })
                                    ));
                                }

                                dynamic moddesc = Newtonsoft.Json.Linq.JObject.Parse(System.IO.File.ReadAllText(folder + @"\description.json"));

                                if (parts != null)
                                    foreach (dynamic prop in parts)
                                    {
                                        foreach (dynamic part in parts[prop.Name])
                                        {

                                            try
                                            {

                                                if (!(part is JObject))
                                                {
                                                    continue;
                                                }

                                                if (moddesc.name != null)
                                                {
                                                    if (moddesc.fileId == null)
                                                    {
                                                        Random r = new Random();//fucking jank fix
                                                        moddesc.fileId = r.Next().ToString();
                                                    }
                                                    usedmods[moddesc.fileId.ToString()] = moddesc.name.ToString();

                                                    string name = "unnamed shape " + part.uuid.ToString();
                                                    if (inventoryitemdesc[part.uuid.ToString()] != null)
                                                        name = inventoryitemdesc[part.uuid.ToString()].title.ToString();


                                                    if (part.renderable != null)//part
                                                    {

                                                        if (blocks.ContainsKey(part.uuid.ToString()))
                                                        {
                                                            blocks[part.uuid.ToString()] =
                                                                new Part(folder,name, moddesc.name.ToString(),part, moddesc);
                                                        }
                                                        else
                                                            blocks.Add(
                                                                part.uuid.ToString(),
                                                                new Part(folder, name, moddesc.name.ToString(), part, moddesc)
                                                            );
                                                    }
                                                    else //block!
                                                    {
                                                        if (blocks.ContainsKey(part.uuid.ToString()))
                                                        {
                                                            blocks[part.uuid.ToString()] =
                                                                new Block(folder, name, moddesc.name.ToString(), part, moddesc);
                                                        }
                                                        else
                                                            blocks.Add(
                                                                part.uuid.ToString(),
                                                                new Block(folder, name, moddesc.name.ToString(), part, moddesc)
                                                            );
                                                    }
                                                }
                                                else
                                                {

                                                    MessageBox.Show("broken mod description!\nFile: " + folder);
                                                    //MessageBox.Show("you have a broken mod!\nFile: " + file,"", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly);
                                                }

                                            }
                                            catch (Exception e)
                                            {
                                                MessageBox.Show(e.Message + "\n" + file, "\nSomething wrong with a self-made mod", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly);
                                            }
                                        }
                                    }
                            }
                    }
                    
                }


            }
            catch (Exception e)
            { MessageBox.Show(e.Message, "Error while loading appdata mods", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly); }


            if (workshoppages.Count != 0)
            {
                Notifications.Add(new Notification(
                    "unloadable mods --workshop pages",
                    new Task(() =>
                    {
                        System.Windows.MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("Mods: " + usedmods.Count() + "\nBlocks loaded: " + blocks.Count() + "\n\nFound mods that weren't able to be loaded\nEither broken or made by a lazy modder\n\npls Remove or Unsub\n\nOpen Workshop pages?", "Found unloadable mods!", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly);
                        if (messageBoxResult == MessageBoxResult.Yes)
                        {
                            foreach (string page in workshoppages)
                            {
                                System.Diagnostics.Process.Start(page);
                            }
                        }
                    })
                ));
            }
        }
        
    }

    public abstract class Blockobject
    {
        public string Path { get; private set; }//path to mod
        public string Mod { get; private set; } = "";//modname
        public string Name { get; private set; } = "unnamed shape";//block name
        public int id { get; private set; }//mod id
        private Bitmap icon;
        

        public bool glass { get; protected set; } = false;

        public Blockobject(string path, string Name, string Modname, dynamic desc)
        {
            this.Path = path;
            this.Name = Name;
            this.Mod = Modname;
            if(desc != null)
            {
                this.id = desc.fileId;
            }
        }

        public Bitmap GetIcon(string uuid)
        {
            if (icon != null) return icon;
            if(File.Exists(this.Path + @"\Gui\IconMap.png") && File.Exists(this.Path + @"\Gui\IconMap.xml"))
            {
                Bitmap IconMap = new Bitmap(this.Path + @"\Gui\IconMap.png");
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(File.ReadAllText(this.Path + @"\Gui\IconMap.xml"));
                string iconstring = Newtonsoft.Json.JsonConvert.SerializeXmlNode(doc).Replace("@", "");
                dynamic icons = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(iconstring);

                string[] size = icons.MyGUI.Resource.Group.size.ToString().Split(' ');

                foreach (dynamic icon in icons.MyGUI.Resource.Group.Index)
                {
                    if(icon.@name.ToString() == uuid)
                    {
                        string[] point = icon.Frame.point.ToString().Split(' ');
                        Bitmap bmp = IconMap.Clone(new System.Drawing.Rectangle(Convert.ToInt32(point[0]), Convert.ToInt32(point[1]), Convert.ToInt32(size[0]), Convert.ToInt32(size[1])), IconMap.PixelFormat);
                        IconMap.Dispose();
                        this.icon = bmp;
                        return bmp;
                    }
                }
            }
            return null;
        }

        public abstract int GetWeight(dynamic bounds = null);

        public xyzpair BoundsByRotation(xyzpair bounds, int xaxis, int zaxis)
        {
            if (Math.Abs(xaxis) == 3)
            {
                if (Math.Abs(zaxis) == 2)
                {
                    return new xyzpair(bounds.y, bounds.z, bounds.x);
                }
                else
                if (Math.Abs(zaxis) == 1)
                {
                    return new xyzpair(bounds.z, bounds.y, bounds.x);
                }
            }
            if (Math.Abs(xaxis) == 2)
            {
                if (Math.Abs(zaxis) == 3)
                {
                    return new xyzpair(bounds.y, bounds.x, bounds.z);
                }
                else
                if (Math.Abs(zaxis) == 1)
                {
                    return new xyzpair(bounds.z, bounds.x, bounds.y);
                }
            }
            if (Math.Abs(xaxis) == 1)
            {
                if (Math.Abs(zaxis) == 2)
                {
                    return new xyzpair(bounds.x, bounds.z, bounds.y);
                }
            }
            return bounds;
        }
        
        protected Model3D Render(double x, double y, double z, Geometry3D geometry3D, xyzpair bounds, string color, int xaxis, int zaxis)
        {
            //x => x - centerx;
            if (color.StartsWith("#"))
                color = color.Substring(1);
            System.Windows.Media.Color c = System.Windows.Media.Color.FromRgb(Convert.ToByte(color.Substring(0, 2), 16), Convert.ToByte(color.Substring(2, 2), 16), Convert.ToByte(color.Substring(4, 2), 16));
            if (glass == true)
                c.A = 120;
            System.Windows.Media.Media3D.Material material = new DiffuseMaterial(new SolidColorBrush(c));

            //for textures: prob need to switch to: https://www.nuget.org/packages/HelixToolkit.Wpf.SharpDX/
            //https://github.com/helix-toolkit/helix-toolkit/issues/471
            

            Model3D renderedblock = new GeometryModel3D { Geometry = geometry3D, Material = material };

            #region Rotation and Translation

            renderedblock.Transform = new MatrixTransform3D(new Matrix3D());
            Transform3DGroup baseLinkMove = new Transform3DGroup();
            TranslateTransform3D baseLinkTranslate = new TranslateTransform3D();
            RotateTransform3D baseLinkRotatex = new RotateTransform3D();
            RotateTransform3D baseLinkRotatez = new RotateTransform3D();
            bool xpos = xaxis > 0;
            bool zpos = zaxis > 0;
            switch (Math.Abs(xaxis))
            {
                case 1:
                    baseLinkRotatex.Rotation = new AxisAngleRotation3D(new System.Windows.Media.Media3D.Vector3D(0, 0, xpos ? 0 : 1), 180);
                    baseLinkMove.Children.Add(baseLinkRotatex);
                    switch (Math.Abs(zaxis))
                    {
                        case 1:
                            MessageBox.Show("Incorrect rotationset found !");
                            break;
                        case 2:
                            baseLinkRotatez.Rotation = new AxisAngleRotation3D(new System.Windows.Media.Media3D.Vector3D(zpos ? -1 : 1, 0, 0), 90);
                            break;
                        case 3:
                            baseLinkRotatez.Rotation = new AxisAngleRotation3D(new System.Windows.Media.Media3D.Vector3D(zpos ? 0 : 1, 0, 0), 180);
                            break;
                    }
                    baseLinkMove.Children.Add(baseLinkRotatez);
                    break;
                case 2:
                    baseLinkRotatex.Rotation = new AxisAngleRotation3D(new System.Windows.Media.Media3D.Vector3D(0, 0, xpos ? 1 : -1), 90);
                    baseLinkMove.Children.Add(baseLinkRotatex);
                    switch (Math.Abs(zaxis))
                    {
                        case 1:
                            baseLinkRotatez.Rotation = new AxisAngleRotation3D(new System.Windows.Media.Media3D.Vector3D(0, zpos ? 1 : -1, 0), 90);
                            break;
                        case 2:
                            MessageBox.Show("Incorrect rotationset found !");
                            break;
                        case 3:
                            baseLinkRotatez.Rotation = new AxisAngleRotation3D(new System.Windows.Media.Media3D.Vector3D(0, zpos ? 0 : 1, 0), 180);
                            break;
                    }
                    baseLinkMove.Children.Add(baseLinkRotatez);
                    break;
                case 3:
                    baseLinkRotatex.Rotation = new AxisAngleRotation3D(new System.Windows.Media.Media3D.Vector3D(0, xpos ? -1 : 1, 0), 90);
                    baseLinkMove.Children.Add(baseLinkRotatex);
                    switch (Math.Abs(zaxis))
                    {
                        case 1:
                            baseLinkRotatez.Rotation = new AxisAngleRotation3D(new System.Windows.Media.Media3D.Vector3D(0, 0, (zpos == xpos) ? 1 : 0), 180);
                            break;
                        case 2:
                            baseLinkRotatez.Rotation = new AxisAngleRotation3D(new System.Windows.Media.Media3D.Vector3D(0, 0, (zpos == xpos) ? -1 : 1), 90);
                            break;
                        case 3:
                            MessageBox.Show("Incorrect rotationset found !");
                            break;
                    }
                    baseLinkMove.Children.Add(baseLinkRotatez);
                    break;
            } //rotations translate!



            baseLinkTranslate.OffsetX = x + (float)(bounds.x) / 2;
            baseLinkTranslate.OffsetY = y + (float)(bounds.y) / 2;
            baseLinkTranslate.OffsetZ = z + (float)(bounds.z) / 2;

            baseLinkMove.Children.Add(baseLinkTranslate);
            renderedblock.Transform = baseLinkMove;
            #endregion

            return renderedblock;
        }

    }

    public class Block : Blockobject
    {
        private dynamic block;
        //private static Dictionary<dynamic,Geometry3D> previousGeometries;
        private int weight = -1;


        public Block(string path, string Name, string Modname, JObject block, JObject desc) :base( path,  Name,  Modname, desc)
        {
            this.block = block;
            if (this.block != null && this.block.glass != null && this.block.glass == true)
                base.glass = true;
        }

        public override int GetWeight(dynamic bounds)
        {
            if (this.weight != -1) return this.weight;
            double density = 500;
            if (this.block.density != null) density = this.block.density;
            int weight = (int)(density * (int)bounds.x + density * (int)bounds.y + density * (int)bounds.z);
            return weight;
        }

        public Model3D Render(double x, double y, double z, dynamic bounds, string color, int xaxis, int zaxis)
        {
            var meshBuilder = new MeshBuilder(false, false);
            int bx = Convert.ToInt32(bounds.x);
            int by = Convert.ToInt32(bounds.y);
            int bz = Convert.ToInt32(bounds.z);
            meshBuilder.AddBox(new Point3D(0, 0, 0), bx, by, bz);

            Geometry3D geometry3D = meshBuilder.ToMesh(true);

            return base.Render(x, y, z, geometry3D, BoundsByRotation(new xyzpair(bx, by, bz), xaxis, zaxis), color, xaxis, zaxis);
        }
    }

    public class Part : Blockobject
    {
        public string uuid { get; private set; }
        private dynamic part;
        private Geometry3D geometry3D;
        private xyzpair bounds;
        private int weight = -1;
        public enum properties
        {
            unknown,
            noninteractive,
            spotlight,
            engine,
            thruster,
            steering,
            seat,
            timedjoint,
            lever,
            button,
            sensor,
            logic,
            timer,
            piston,
            simpleInteractive,
            bearing,
            spring,
            radio,
            horn,
            tone,
            scripted
        }
        private properties property = properties.unknown;

        public bool IsConnectable {
            get { return (GetProperty() != properties.noninteractive) && (this.property != properties.bearing) && (this.property != properties.spring); }
            private set { }
        }

        public properties GetProperty()
        {
            if (property == properties.unknown)
            {
                if (part.spotlight != null)
                    this.property = properties.spotlight;
                else
                if (part.engine != null)
                    this.property = properties.engine;
                else
                if (part.thruster != null)
                    this.property = properties.thruster;
                else
                if (part.steering != null)
                    this.property = properties.steering;
                else
                if (part.seat != null)
                    this.property = properties.seat;
                else
                if (part.timedjoint != null)
                    this.property = properties.timedjoint;
                else
                if (part.lever != null)
                    this.property = properties.lever;
                else
                if (part.button != null)
                    this.property = properties.button;
                else
                if (part.sensor != null)
                    this.property = properties.sensor;
                else
                if (part.logic != null)
                    this.property = properties.logic;
                else
                if (part.timer != null)
                    this.property = properties.timer;
                else
                if (part.piston != null)
                    this.property = properties.piston;
                else
                if (part.simpleInteractive != null)
                    this.property = properties.simpleInteractive;
                else
                if (part.bearing != null)
                    this.property = properties.bearing;
                else
                if (part.spring != null)
                    this.property = properties.spring;
                else
                if (part.radio != null)
                    this.property = properties.radio;
                else
                if (part.horn != null)
                    this.property = properties.horn;
                else
                if (part.tone != null)
                    this.property = properties.tone;
                else
                if (part.scripted != null)
                    this.property = properties.scripted;
                else
                    this.property = properties.noninteractive;
            }
            return property;
        }
        
        public Part(string path, string Name, string Modname, JObject part, JObject desc, bool prerender = false ) : base(path, Name, Modname, desc)
        {
            this.part = part;

            if (!(this.part.renderable is JObject))
            {
                String render = this.part.renderable.ToString().Replace(@"/", @"\");
                String renderablePath = render;// = this.Path + r.Substring(r.IndexOf('/')).Replace(@"/", @"\");
                if (render.ToLower().StartsWith("$game_data"))
                {
                    renderablePath = Database.ScrapData + render.Substring(10);
                }
                if (render.ToLower().StartsWith("$mod_data"))
                {
                    renderablePath = base.Path + render.Substring(9);
                }
                if (render.ToLower().StartsWith("$survival_data"))
                {
                    renderablePath = Database.SurvivalData + render.Substring(14);
                }
                if (render.ToLower().StartsWith("../data"))
                {
                    renderablePath = base.Path + render.Substring(7);
                }
                String json = System.IO.File.ReadAllText(renderablePath);
                // FIX THE FUCKING SHIT JSON BY DEVS:
                String reverseJson = new string(json.Reverse().ToArray());
                int curlyOpenBracketCount = reverseJson.Count<char>(f => f == '{');
                int curlyCloseBracketCount = reverseJson.Count<char>(f => f == '}');
                while (curlyCloseBracketCount > curlyOpenBracketCount)
                {
                    reverseJson = reverseJson.Substring(reverseJson.IndexOf('}')+1);
                    curlyOpenBracketCount = reverseJson.Count<char>(f => f == '{');
                    curlyCloseBracketCount = reverseJson.Count<char>(f => f == '}');
                }
                int blockyOpenBracketCount = reverseJson.Count<char>(f => f == '[');
                int blockyCloseBracketCount = reverseJson.Count<char>(f => f == ']');
                while (blockyCloseBracketCount > blockyOpenBracketCount)
                {
                    reverseJson = reverseJson.Substring(reverseJson.IndexOf(']') + 1);
                    blockyOpenBracketCount = reverseJson.Count<char>(f => f == '[');
                    blockyCloseBracketCount = reverseJson.Count<char>(f => f == ']');
                }
                json = new string(reverseJson.Reverse().ToArray());
                dynamic renderable = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json) as dynamic;
                this.part.renderable = renderable;
            }

            this.uuid = this.part.uuid;
            if (prerender == true)
            {
                new Thread(new ThreadStart(() => { this.GetGeometry(); })).Start();
                this.GetProperty(); 
                this.GetBounds();
            }
        }

        public xyzpair GetBounds()
        {
            if(this.bounds == null)
                this.bounds = xyzpair.getPartBounds(part);
            return this.bounds;
        }

        public override int GetWeight(dynamic bounds)
        {
            if (this.weight != -1) return this.weight;
            double density = 500;
            if (this.part.density != null) density = this.part.density;
            int weight = (int)(density * (int)bounds.x + density* (int)bounds.y + density * (int)bounds.z);
            return weight;
        }

        public dynamic GetBoundsDynamic()
        {
            this.GetBounds();
            dynamic bounds = new JObject();
            bounds.x = this.bounds.x;
            bounds.y = this.bounds.y;
            bounds.z = this.bounds.z;
            return bounds;
        }


        public Model3D Render(double x, double y, double z, string color, int xaxis,int zaxis)
        {
            return base.Render(x, y, z, GetGeometry(), BoundsByRotation(GetBounds(), xaxis,zaxis), color, xaxis, zaxis);
        }

        public Geometry3D GetGeometry()
        {
            if(geometry3D != null)
                return geometry3D;
            
           //if (part.renderable.lodList[0].subMeshList != null)
           //    foreach (dynamic submesh in part.renderable.lodList[0].subMeshList)
           //        if (submesh.material.ToString() == "Glass")
           //            base.glass = true;

            //part.renderable.lodList[].subMeshList[].textureList[]
            //part.renderable.lodList[].subMeshMap.Shark.textureList[]

            string meshlocation = part.renderable.lodList[0].mesh.ToString();


            this.geometry3D = LoadMesh(meshlocation);

            return geometry3D;

        }


        private Geometry3D LoadMesh(string meshlocation)
        {
            Geometry3D geometry = null;
            try
            {
                bool game = false;
                if (meshlocation.ToLower().StartsWith("$game_data"))
                {
                    meshlocation = meshlocation.Substring(10);
                    meshlocation = Database.ScrapData + meshlocation;
                    game = true;
                }
                if (meshlocation.ToLower().StartsWith("$mod_data"))
                {
                    meshlocation = meshlocation.Substring(9);
                    meshlocation = base.Path + meshlocation;
                }
                if (meshlocation.ToLower().StartsWith("$survival_data"))
                {
                    meshlocation = meshlocation.Substring(14);
                    meshlocation = Database.SurvivalData + meshlocation;
                }
                if (meshlocation.ToLower().StartsWith("../data"))
                {
                    meshlocation = meshlocation.Substring(7);
                    meshlocation = base.Path + meshlocation;
                    game = true;
                }
                string location = meshlocation;

                if (System.IO.Path.GetExtension(meshlocation) != ".obj")
                {
                    string obj = System.IO.Path.GetDirectoryName(meshlocation) + "\\" + System.IO.Path.GetFileNameWithoutExtension(meshlocation) + ".obj";
                    if (File.Exists(obj))
                        location = obj;//loading obj is prefered

                    string meshes = obj.Replace(System.IO.Path.GetDirectoryName(Path), "Meshes");
                    if (game == true)
                        meshes = obj.Replace(System.IO.Path.GetDirectoryName(Database.ScrapData), "Meshes");
                    if (File.Exists(meshes))
                    {
                        location = meshes;//if converted obj in install files exists, use it
                    }
                }


                Scene a = new AssimpImporter().ImportFile(location);

                var meshBuilder = new MeshBuilder(false, false);
                foreach(Mesh m in a.Meshes)
                {
                    
                    foreach (Face face in m.Faces)
                    {

                        IList<Point3D> vertices = new List<Point3D>();
                        foreach (uint i in face.Indices)
                        {
                            vertices.Add(new Point3D(m.Vertices[i].X, m.Vertices[i].Y, m.Vertices[i].Z));
                        }
                        meshBuilder.AddPolygon(vertices);
                        vertices = new List<Point3D>();
                    }
                    if (false)
                    {
                        try
                        {
                            var texturecoords = m.GetTextureCoords(0);
                            meshBuilder.TextureCoordinates = new PointCollection();
                            foreach (Assimp.Vector3D vec in m.GetTextureCoords(0))
                            {
                                meshBuilder.TextureCoordinates.Add(new System.Windows.Point(Convert.ToDouble(vec.X), Convert.ToDouble(vec.Y)));
                            }
                        }
                        catch (Exception edd)
                        {
                            MessageBox.Show(edd.Message);
                        }
                    }
                }

                //meshBuilder.Normals = m.Normals;
                //meshBuilder.Tangents = m.Tangents;
                //meshBuilder.BiTangents = m.BiTangents;
                geometry = meshBuilder.ToMesh(true);

            }
            catch (Exception e)
            {
                bool devmode = false;

                if(devmode)//create meshes structure inside tool folder
                {
                    string toolmesh = meshlocation.Replace(System.IO.Path.GetDirectoryName(Path), "Meshes");
                    System.IO.Directory.CreateDirectory(System.IO.Directory.GetParent(toolmesh).ToString());
                    if(!File.Exists(toolmesh))
                        File.Copy(meshlocation, toolmesh);
                }


                //failed to load .fbx/mesh file
                //construct geometry out of pointlist

                var meshBuilder = new MeshBuilder(false, false);
                if (part.box != null)
                {
                    meshBuilder.AddBox(new Point3D(0, 0, 0),Convert.ToDouble(part.box.x), Convert.ToDouble(part.box.y), Convert.ToDouble(part.box.z));
                    return meshBuilder.ToMesh(true);
                }
                if (part.cylinder != null)
                {
                    Point3D p1 = new Point3D(0, 0, 0);
                    Point3D p2 = new Point3D(0, 0, 0);
                    double margin = Convert.ToDouble(part.cylinder.margin);
                    double depth = Convert.ToDouble(part.cylinder.depth);
                    if (part.cylinder.axis.ToString().ToLower() == "x")
                    {
                        p1.X -= depth / 2;
                        p2.X += depth / 2;
                    }
                    if (part.cylinder.axis.ToString().ToLower() == "y")
                    {
                        p1.Y -= depth / 2;
                        p2.Y += depth / 2;
                    }
                    if (part.cylinder.axis.ToString().ToLower() == "z")
                    {
                        p1.Z -= depth / 2;
                        p2.Z += depth / 2;
                    }
                    meshBuilder.AddCylinder(p1, p2, Convert.ToDouble(part.cylinder.diameter) * margin, (Convert.ToInt32(part.cylinder.diameter) + 5 ) * 2);
                    return meshBuilder.ToMesh(true);
                }
                if(part.hull != null)
                {
                    if(part.hull.pointList != null && part.hull.pointList.Count > 5)
                    {
                        List<Point3D> points = new List<Point3D>();
                        foreach(dynamic point in part.hull.pointList)
                        {
                            points.Add(new Point3D(
                                Convert.ToDouble(point.x) * Convert.ToInt32(part.hull.x),
                                Convert.ToDouble(point.y) * Convert.ToInt32(part.hull.y),
                                Convert.ToDouble(point.z) * Convert.ToInt32(part.hull.z)));
                        }
                        meshBuilder.AddPolygon(points);
                        return meshBuilder.ToMesh(true);
                    }
                    else
                    {
                        meshBuilder.AddBox(new Point3D(0, 0, 0), Convert.ToInt32(part.hull.x), Convert.ToInt32(part.hull.y), Convert.ToInt32(part.hull.z));
                        return meshBuilder.ToMesh(true);
                    }
                }

                MessageBox.Show("error building mesh", "", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly);
                //shouldn't be able to get to this line.
            }
            return geometry;
        }
    }
    
    public class xyzpair
    {
        public int x;
        public int y;
        public int z;

        public xyzpair(int x, int y, int z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public static xyzpair getPartBounds(dynamic part)
        {
            dynamic bounds = getDynamicPartBounds(part);
            xyzpair b = new xyzpair(1,1,1);
            b.x = bounds.x;
            b.y = bounds.y;
            b.z = bounds.z;
            return b;
        }

        private static dynamic getDynamicPartBounds(dynamic part)
        {
            dynamic bounds = new JObject();
            if (part.box != null)
            {
                return part.box;
            }
            if (part.hull != null)
            {
                bounds.x = part.hull.x;
                bounds.y = part.hull.y;
                bounds.z = part.hull.z;
                return bounds;
            }
            if (part.cylinder != null)
            {
                if (part.cylinder.axis.ToString().ToLower() == "x")
                {
                    bounds.x = part.cylinder.depth;
                    bounds.y = part.cylinder.diameter;
                    bounds.z = part.cylinder.diameter;
                    return bounds;
                }
                else
                if (part.cylinder.axis.ToString().ToLower() == "y")
                {
                    bounds.x = part.cylinder.diameter;
                    bounds.y = part.cylinder.depth;
                    bounds.z = part.cylinder.diameter;
                    return bounds;

                }
                else
                if (part.cylinder.axis.ToString().ToLower() == "z")
                {
                    bounds.x = part.cylinder.diameter;
                    bounds.y = part.cylinder.diameter;
                    bounds.z = part.cylinder.depth;
                    return bounds;

                }
            }
            bounds.X = 1;
            bounds.Y = 1;
            bounds.Z = 1;
            MessageBox.Show("no bounds\n\nImpossible senario. please report");
            return bounds;
        }
    }

    [ValueConversion(typeof(Image), typeof(BitmapSource))]
    public class ImageToBitmapSourceConverter : IValueConverter
    {
        [DllImport("gdi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool DeleteObject(IntPtr value);

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Image myImage = (Image)value;

            var bitmap = new Bitmap(myImage);
            IntPtr bmpPt = bitmap.GetHbitmap();
            BitmapSource bitmapSource =
             System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                   bmpPt,
                   IntPtr.Zero,
                   Int32Rect.Empty,
                   BitmapSizeOptions.FromEmptyOptions());

            //freeze bitmapSource and clear memory to avoid memory leaks
            bitmapSource.Freeze();
            DeleteObject(bmpPt);

            return bitmapSource;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;
using Newtonsoft.Json.Linq;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for Circle_generator.xaml
    /// </summary>
    public partial class Circle_generator : Window
    {

        private MainWindow mainwindow;
        public Circle_generator(MainWindow window)
        {
            this.mainwindow = window;
            InitializeComponent();
        }

        private void Button_Help_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://youtu.be/glLgQemUS2I?t=1479");
        }

        private void Button_Create_Click(object sender, RoutedEventArgs e)
        {
            float X = Convert.ToInt32(TextBox_X.Text);
            float Y = Convert.ToInt32(TextBox_Y.Text);
            //float Z = Convert.ToInt32(TextBox_Z.Text);
            float t = 0.4f + (float)Convert.ToDouble(TextBox_thickness.Text);

            dynamic circle = new JObject();

            HashSet<Point3D> points = new HashSet<Point3D>();

            double precision = 0.95;
            double pp = 0;

            for (float x = -X; x < X; x++)
                for (float y = -Y; y < Y; y++)
                    if ((Math.Pow(x / X, 2) + Math.Pow(y / Y, 2)) < precision &&
                        (Math.Pow((x ) / (X - t), 2) + Math.Pow((y ) / (Y - t), 2)) > (precision-pp))
                    {
                        points.Add(new Point3D(x, y, 1));
                    }


            circle = BlueprintOptimizer.CreateBlueprintFromPoints(points);


            if (circle.bodies[0].childs.Count > 0)
            {
                string message = "++ An ellipse/circle with " + circle.bodies[0].childs.Count + " shapes has been generated!";
                Random r = new Random();
                string blueprintpath = Database.User_ + "\\Blueprints\\Generatedellipse-" + r.Next() + r.Next();
                dynamic description = new JObject();
                description.description = "generated ellipsoid";
                description.name = "generated ellipse/circle" + r.Next();
                description.type = "Blueprint";
                description.version = 0;

                if (BP.Blueprintpath == null)
                {//no blueprint exists, initialize new one
                    new BP(blueprintpath, circle, description);
                }
                else
                {//overwrite current blueprint
                    BP.setblueprint(circle);
                    BP.Description.description += message;
                }
                mainwindow.RenderBlueprint();
            }
            else
            {
                MessageBox.Show("no circle has been generated");
            }

        }
        private dynamic block(int x, int y, int z, dynamic bounds)
        {
            dynamic block = new JObject();
            block.color = "5DB7E7";
            block.pos = new JObject();
            block.pos.x = x;
            block.pos.y = y;
            block.pos.z = z;
            block.bounds = new JObject();
            block.bounds.x = bounds.x;
            block.bounds.y = bounds.y;
            block.bounds.z = bounds.z;
            block.shapeId = "a6c6ce30-dd47-4587-b475-085d55c6a3b4";
            block.xaxis = 1;
            block.zaxis = 3;
            return block;
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox t = (TextBox)sender;
            try
            {
                if (Convert.ToDouble(t.Text) < 0 ){ t.Text = "0"; }
            }
            catch
            {
                t.Text = "0";
            }
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for NotificationWindow.xaml
    /// </summary>
    public partial class NotificationWindow : Window
    {
        
        public NotificationWindow()
        {
            InitializeComponent();
            fill_listbox();
            listBox_notis.MouseDoubleClick += new MouseButtonEventHandler(Notification_Click);
            new Task(() =>
            {
                try
                {
                    int amountnotis = 0;
                    while (true)
                    {
                        this.Dispatcher.Invoke((Action)(() =>
                        {
                            if (amountnotis != Database.Notifications.Count)
                                this.fill_listbox();
                            amountnotis = Database.Notifications.Count;
                            if (amountnotis == 0)
                                this.Close();
                        }));
                        Thread.Sleep(2000);
                    }
                }
                catch { }
            }).Start();
        }

        private void fill_listbox()
        {
            listBox_notis.Items.Clear();
            foreach (Notification notification in Database.Notifications)
            {
                listBox_notis.Items.Add(notification);
            }

        }

        private void Notification_Click(object sender, RoutedEventArgs e)
        {
            if(listBox_notis.SelectedIndex>-1)
            {
                Notification currentnoti = ((Notification)listBox_notis.SelectedItem);
                currentnoti.performTask();
                Database.Notifications.Remove(((Notification)listBox_notis.SelectedItem));

                fill_listbox();//refresh
            }
        }
    }



    public class Notification
    {
        
        public string description { get; private set; }

        private Task task;
        //public string tag{get; private set;}
        public void performTask()
        {
            
            try
            {
                if (task != null)
                    task.Start();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "\nerror while showing notification");
            }
        }
        public Notification(string description, Task task)
        {
            this.description = description;
            this.task = task;
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Advanced_Blueprint_Tools
{
    using System.Windows.Media;
    using System.Windows.Media.Media3D;
    using HelixToolkit.Wpf;
    using System.Threading;

    public class MainViewModel
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="MainViewModel"/> class.
        /// </summary>
        public MainViewModel()
        {



            // Create a model group
            var modelGroup = new Model3DGroup();

            // Create a mesh builder and add a box to it
            var meshBuilder = new MeshBuilder(false, false);
            meshBuilder.AddBox(new Point3D(0, 5, 5), 2, 2, 5);
            meshBuilder.AddBox(new Rect3D(0, 0, 1.2, 1, 5, 0.4));
            MeshGeometry3D g = new MeshGeometry3D();

            // Create a mesh from the builder (and freeze it)
            var mesh = meshBuilder.ToMesh(true);

            // Create some materials
            var greenMaterial = MaterialHelper.CreateMaterial(Colors.Green);
            var redMaterial = MaterialHelper.CreateMaterial(Colors.Red);
            var blueMaterial = MaterialHelper.CreateMaterial(Colors.Blue);
            var insideMaterial = MaterialHelper.CreateMaterial(Colors.Yellow);



            //The Importer to load .obj files
            ModelImporter importer = new ModelImporter();

            //The Material (Color) that is applyed to the importet objects
            Material material = new DiffuseMaterial(new SolidColorBrush(Colors.White));
            importer.DefaultMaterial = material;
            Model3D block = importer.Load(@"D:\Program Files (x86)\Steam\SteamApps\workshop\content\387990\877698157\Objects\Mesh\Seat.obj");

            //modelGroup.Children.Add(block);

            // Add 3 models to the group (using the same mesh, that's why we had to freeze it)
            modelGroup.Children.Add(new GeometryModel3D { Geometry = mesh, Material = greenMaterial, BackMaterial = insideMaterial });
            //modelGroup.Children.Add(new GeometryModel3D { Geometry = mesh, Transform = new TranslateTransform3D(-2, 0, 0), Material = redMaterial, BackMaterial = insideMaterial });
            //modelGroup.Children.Add(new GeometryModel3D { Geometry = mesh, Transform = new TranslateTransform3D(2, 0, 0), Material = blueMaterial, BackMaterial = insideMaterial });

            // Set the property, which will be bound to the Content property of the ModelVisual3D (see MainWindow.xaml)
            this.Model = modelGroup;
        }
        

        /// <summary>
        /// Gets or sets the model.
        /// </summary>
        /// <value>The model.</value>
        public Model3D Model { get; set; }
    }
}
<file_sep>﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Threading;
using System.Diagnostics;


namespace Advanced_Blueprint_Tools
{
    class Updater
    {

        public bool CheckForUpdates() //for current branch & version: 'properties.settings'
        {
            try
            {
                
                var request = (HttpWebRequest)WebRequest.Create("https://raw.githubusercontent.com/brentbatch/blueprinttool/master/version.json");
                
                request.UserAgent = "VSTS-Get";
                request.ContentType = "application/json";
                request.Method = "GET";

                WebResponse response = request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);

                var result = reader.ReadToEnd();
                dynamic json = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(result);
                int gotoversion = Convert.ToInt32(json.Public.version.ToString());
                if (Properties.Settings.Default.branch == "Test")
                {
                    gotoversion = Convert.ToInt32(json.Test.version.ToString());
                }

                /*
                if (Properties.Settings.Default.version > gotoversion && Properties.Settings.Default.branch != "Test")
                {//going from high version to public branch(lower version)
                    Database.Notifications.Add(new Notification("manual update required",
                    new Task(() =>
                    {
                        System.Windows.MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("going from Test version to public version requires a manual re-install\nYou'll need to remove the current version and install public version yourself\n\nOpen download link of 'public' branch in browser?", "Update", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly);
                        if (messageBoxResult == MessageBoxResult.Yes)
                        {
                            System.Diagnostics.Process.Start("https://github.com/brentbatch/blueprinttool/archive/master.zip");//public
                        } //manual update
                    })
                    ));
                    return true;
                }*/
                if (Properties.Settings.Default.version < gotoversion || (Properties.Settings.Default.version > gotoversion && Properties.Settings.Default.branch != "Test"))
                {//normal update
                    Database.Notifications.Add(new Notification("Update Available!",
                    new Task(() =>
                    {
                        System.Windows.MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("Found a new update for branch: "+ Properties.Settings.Default.branch +"\n\nDo you want to update to this version?\ncurrent:"+ Properties.Settings.Default.version+ "\nbranch version:"+gotoversion.ToString()+"\n\nWould you like to download this version?", "Update Available!", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Asterisk, MessageBoxResult.Yes, MessageBoxOptions.DefaultDesktopOnly);
                        if (messageBoxResult == MessageBoxResult.Yes)
                        {
                            string root = Directory.GetDirectoryRoot("Meshes") + "bptools\\";
                            if (File.Exists(root + "update.zip"))
                                File.Delete(root + "update.zip");
                            string applicationfiles = "";
                            if (!Directory.Exists(root))
                                Directory.CreateDirectory(root);
                            if (Properties.Settings.Default.branch == "Test")
                            {
                                //System.Diagnostics.Process.Start("https://github.com/brentbatch/Blueprinttool_test/archive/master.zip");
                                try
                                {
                                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                                    using (WebClient webClient = new WebClient())
                                    {
                                        webClient.DownloadFile("https://github.com/brentbatch/Blueprinttool_test/archive/master.zip", root+"update.zip");
                                    }
                                    //create new desktop shortcuts
                                    applicationfiles = root + "Update\\Blueprinttool_test-master\\Application Files";
                                }
                                catch (Exception e)
                                {
                                    MessageBox.Show(e.Message);
                                }

                            }
                            else
                            {//public
                                //System.Diagnostics.Process.Start("https://github.com/brentbatch/Blueprinttool/archive/master.zip");
                                try
                                {
                                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                                    using (WebClient webClient = new WebClient())
                                    {
                                        webClient.DownloadFile("https://github.com/brentbatch/Blueprinttool/archive/master.zip", @"update.zip");
                                    }
                                    applicationfiles = root + "Update\\Blueprinttool-master\\Application Files";
                                }
                                catch (Exception e)
                                {
                                    MessageBox.Show(e.Message);
                                }
                            }
                            String ZipPath = root + @"update.zip";
                            String extractPath = root + @"Update";
                            string startPath = root + @"start";
                            //System.IO.Compression.ZipFile.CreateFromDirectory(startPath, ZipPath);
                            string master = Path.GetDirectoryName(applicationfiles);
                            if (File.Exists(master + "\\Advanced Blueprint Tools.application"))
                                File.Delete(master + "\\Advanced Blueprint Tools.application");
                            if (File.Exists(master + "\\README.md"))
                                File.Delete(master + "\\README.md");
                            if (File.Exists(master + "\\version.json"))
                                File.Delete(master + "\\version.json");
                            if (File.Exists(master + "\\setup.exe"))
                                File.Delete(master + "\\setup.exe");
                            try
                            {
                                System.IO.Compression.ZipFile.ExtractToDirectory(ZipPath, extractPath);
                            }
                            catch { }

                            dynamic config = new JObject();
                            config.steamapps = Properties.Settings.Default.steamapps;
                            config.times = Properties.Settings.Default.times;
                            config.branch = Properties.Settings.Default.branch;
                            config.wires = Properties.Settings.Default.wires;
                            config.safemode = Properties.Settings.Default.safemode;
                            config.colorwires = Properties.Settings.Default.colorwires;
                            config.wirecolor = Properties.Settings.Default.wirecolor;
                            config.blobcolor = Properties.Settings.Default.blobcolor;
                            config.coloropacity = Properties.Settings.Default.coloropacity;

                            DateTime lasthigh = new DateTime(1900, 1, 1);
                            string findlastversionname = "";
                            foreach (string subdir in Directory.GetDirectories(applicationfiles)) //get user_numbers folder that is last used
                            {
                                DirectoryInfo fi1 = new DirectoryInfo(subdir);
                                DateTime created = fi1.LastWriteTime;
                                fi1 = new DirectoryInfo(subdir);

                                if (created > lasthigh)
                                {
                                    findlastversionname = subdir;
                                    lasthigh = created;
                                }
                            }

                            File.WriteAllText(findlastversionname + "\\config", config.ToString());

                            object shDesktop = (object)"Desktop";
                            IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell();
                            string shortcutAddress = (string)shell.SpecialFolders.Item(ref shDesktop) + @"\Advanced Blueprint Tools.lnk";
                            IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(shortcutAddress);
                            shortcut.Description = "Shortcut for blueprint tool "+gotoversion;
                            shortcut.TargetPath = findlastversionname + "\\Advanced Blueprint Tools.exe";
                            shortcut.WorkingDirectory = findlastversionname;
                            shortcut.Save();
                            Process.Start(shortcutAddress);
                            Environment.Exit(0);
                        }
                    })
                    ));
                    return true;
                }
            }
            catch
            {
                Database.Notifications.Add(new Notification("unable to check for updates",null));
            }

            return false;
        }
    }
}
<file_sep>﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;

namespace Advanced_Blueprint_Tools
{
    class BlueprintOptimizer
    {
        public static dynamic optimizeblueprint(dynamic blueprint)
        {
            dynamic optimizedblueprint = new JObject();

            //code





            return blueprint;
        }

        public static dynamic CreateBlueprintFromPoints(HashSet<Point3D> pointlist)
        {
            

            Dictionary<Point3D, Bounds> mergex = new Dictionary<Point3D, Bounds>();
            int i = 0;
            foreach(Point3D point in pointlist)
                if(!pointlist.Contains(new Point3D(point.X-1,point.Y, point.Z)))
                {
                    while (pointlist.Contains(new Point3D(point.X + i, point.Y, point.Z)))
                    {
                        //pointlist.Remove(new Point3D(point.X + i, point.Y, point.Z));
                        if (!mergex.ContainsKey(point))
                            mergex.Add(point, new Bounds { x = 1, y = 1, z = 1 });
                        else
                            mergex[point].x++;
                        i++;
                    }
                    i = 0;
                }
            pointlist.Clear();
            
            Dictionary<Point3D, Bounds> mergey = new Dictionary<Point3D, Bounds>();

            foreach(Point3D point in mergex.Keys)
                if(!(mergex.ContainsKey(new Point3D(point.X, point.Y-1, point.Z)) && mergex[new Point3D(point.X, point.Y, point.Z)].x == mergex[new Point3D(point.X, point.Y - 1, point.Z)].x))
                {
                    while (mergex.ContainsKey(new Point3D(point.X, point.Y + i, point.Z)) && 
                           mergex[new Point3D(point.X, point.Y + i, point.Z)].x == mergex[point].x)//x bound need to be same to merge
                    {
                        //mergex.Remove(neighbourkey);
                        if (!mergey.ContainsKey(point))
                            mergey.Add(point, mergex[point]);
                        else
                            mergey[point].y++;
                        i++;
                    }
                    i = 0;
                }
            mergex.Clear();
            

            Dictionary<Point3D, Bounds> mergez = new Dictionary<Point3D, Bounds>();

            foreach (Point3D point in mergey.Keys)
                if (!(mergey.ContainsKey(new Point3D(point.X, point.Y , point.Z-1)) && 
                    mergey[new Point3D(point.X, point.Y, point.Z)].x == mergey[new Point3D(point.X, point.Y, point.Z - 1)].x && 
                    mergey[new Point3D(point.X, point.Y, point.Z)].y == mergey[new Point3D(point.X, point.Y, point.Z - 1)].y))
                {
                    while (mergey.ContainsKey(new Point3D(point.X, point.Y, point.Z + i)) && 
                        mergey[new Point3D(point.X, point.Y, point.Z + i)].x == mergey[point].x && 
                        mergey[new Point3D(point.X, point.Y, point.Z + i)].y == mergey[point].y)
                    {
                        //mergex.Remove(neighbourkey);
                        if (!mergez.ContainsKey(point))
                            mergez.Add(point, mergey[point]);
                        else
                            mergez[point].z++;
                        i++;
                    }
                    i = 0;
                }
            
            mergey.Clear();



            dynamic blueprint = new JObject();
            blueprint.version = 1;
            blueprint.bodies = new JArray();
            blueprint.bodies.Add(new JObject());
            blueprint.bodies[0].childs = new JArray();

            int amountgenerated = 0;
            int negz = 1;//-1/1
            foreach(var keypair in mergez)
            {
                dynamic child = new JObject();
                child.color = "5DB7E7";
                child.pos = new JObject();
                child.pos.x = (int)Math.Floor(keypair.Key.X);
                child.pos.y = (int)Math.Floor(keypair.Key.Y);
                child.pos.z = (int)Math.Floor(keypair.Key.Z);
                child.bounds = new JObject();
                child.bounds.x = keypair.Value.x;
                child.bounds.y = keypair.Value.y;
                child.bounds.z = keypair.Value.z;
                child.shapeId = "a6c6ce30-dd47-4587-b475-085d55c6a3b4";
                child.xaxis = 1;
                child.zaxis = negz*3;
                blueprint.bodies[0].childs.Add(child);
                amountgenerated++;
            }

            return blueprint;
        }
        public static dynamic CreateBlueprintFromPointsAndColor(HashSet<Tuple<Point3D, string>> colorpoints)
        {


            Dictionary<Point3D, Bounds> mergex = new Dictionary<Point3D, Bounds>();
            int i = 0;
            int j = 0;
            foreach (var point in colorpoints)
                if (!colorpoints.Contains(new Tuple<Point3D, string>( new Point3D(point.Item1.X - 1, point.Item1.Y, point.Item1.Z), point.Item2)))
                {
                    while (colorpoints.Contains(new Tuple<Point3D, string>(new Point3D(point.Item1.X + i, point.Item1.Y, point.Item1.Z), point.Item2)))
                    {
                        //pointlist.Remove(new Point3D(point.X + i, point.Y, point.Z));

                        if (!mergex.ContainsKey(point.Item1))
                            mergex.Add(point.Item1, new Bounds { x = 1, y = 1, z = 1, color = point.Item2 });
                        else
                            mergex[point.Item1].x++;
                        i++;
                    }
                    i = 0;
                    j++;
                }
            colorpoints.Clear();

            Dictionary<Point3D, Bounds> mergey = new Dictionary<Point3D, Bounds>();

            foreach (Point3D point in mergex.Keys)
                if (!(mergex.ContainsKey(new Point3D(point.X, point.Y - 1, point.Z)) &&
                    mergex[new Point3D(point.X, point.Y, point.Z)].x == mergex[new Point3D(point.X, point.Y - 1, point.Z)].x &&
                    mergex[new Point3D(point.X, point.Y, point.Z)].color == mergex[new Point3D(point.X, point.Y - 1, point.Z)].color))
                {
                    while (mergex.ContainsKey(new Point3D(point.X, point.Y + i, point.Z)) &&
                           mergex[new Point3D(point.X, point.Y + i, point.Z)].x == mergex[point].x &&
                           mergex[new Point3D(point.X, point.Y + i, point.Z)].color == mergex[point].color)//x bound need to be same to merge
                    {
                        //mergex.Remove(neighbourkey);
                        if (!mergey.ContainsKey(point))
                            mergey.Add(point, mergex[point]);
                        else
                            mergey[point].y++;
                        i++;
                    }
                    i = 0;
                }
            mergex.Clear();


            Dictionary<Point3D, Bounds> mergez = new Dictionary<Point3D, Bounds>();

            foreach (Point3D point in mergey.Keys)
                if (!(mergey.ContainsKey(new Point3D(point.X, point.Y, point.Z - 1)) &&
                    mergey[new Point3D(point.X, point.Y, point.Z)].x == mergey[new Point3D(point.X, point.Y, point.Z - 1)].x &&
                    mergey[new Point3D(point.X, point.Y, point.Z)].y == mergey[new Point3D(point.X, point.Y, point.Z - 1)].y &&
                    mergey[new Point3D(point.X, point.Y, point.Z)].color == mergey[new Point3D(point.X, point.Y, point.Z - 1)].color))
                {
                    while (mergey.ContainsKey(new Point3D(point.X, point.Y, point.Z + i)) &&
                        mergey[new Point3D(point.X, point.Y, point.Z + i)].x == mergey[point].x &&
                        mergey[new Point3D(point.X, point.Y, point.Z + i)].y == mergey[point].y &&
                        mergey[new Point3D(point.X, point.Y, point.Z + i)].color == mergey[point].color)
                    {
                        //mergex.Remove(neighbourkey);
                        if (!mergez.ContainsKey(point))
                            mergez.Add(point, mergey[point]);
                        else
                            mergez[point].z++;
                        i++;
                    }
                    i = 0;
                }

            mergey.Clear();



            dynamic blueprint = new JObject();
            blueprint.version = 1;
            blueprint.bodies = new JArray();
            blueprint.bodies.Add(new JObject());
            blueprint.bodies[0].childs = new JArray();

            int amountgenerated = 0;
            int negz = 1;//-1/1
            foreach (var keypair in mergez)
            {
                dynamic child = new JObject();
                child.color = keypair.Value.color;
                child.pos = new JObject();
                child.pos.x = (int)Math.Floor(keypair.Key.X);
                child.pos.y = (int)Math.Floor(keypair.Key.Y);
                child.pos.z = (int)Math.Floor(keypair.Key.Z);
                child.bounds = new JObject();
                child.bounds.x = keypair.Value.x;
                child.bounds.y = keypair.Value.y;
                child.bounds.z = keypair.Value.z;
                child.shapeId = "a6c6ce30-dd47-4587-b475-085d55c6a3b4";
                child.xaxis = 1;
                child.zaxis = negz * 3;
                blueprint.bodies[0].childs.Add(child);
                amountgenerated++;
            }

            return blueprint;
        }
        public class Bounds
        {
            public string color;
           public int y;
           public int z;
           public int x;
        }
    }

}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for required_mods.xaml
    /// </summary>
    public partial class required_mods : Window
    {
        private dynamic Mods;
        public required_mods(dynamic Mods)
        {

            this.Mods = Mods.mods;
            InitializeComponent();
            foreach (dynamic mod in this.Mods)
            {
                listBox_mods.Items.Add(mod);//new mod(mod.name.ToString(), mod.author.ToString(), mod.url.ToString(), true)
            }
            listBox_mods.MouseDoubleClick += new MouseButtonEventHandler(Mod_Click);
            listBox_mods.SelectionChanged += new SelectionChangedEventHandler(Mod_Click);
            
        }
        

        private void Mod_Click(object sender, RoutedEventArgs e)
        {
            ListBox b = (ListBox)sender;
            dynamic mod = (b.SelectedItem);
            MessageBoxResult messageBoxResult = MessageBox.Show
                ("Name: "+mod.name+"\nAuthor: "+mod.author+"\nUrl: "+mod.url+"\n\nWould you like to go to this mod page?", "Selected Mod   -provided by http://scrapmechanic.xesau.eu/uuidservice/", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Asterisk);
            if (messageBoxResult == MessageBoxResult.Yes)
            {
                System.Diagnostics.Process.Start(@"steam://openurl/"+mod.url);
            }

        }
        


    }
    public class mod
    {
        public string name;
        public string author;
        public string url;

        public Brush Background;

        public mod(string name, string author, string url, bool hasit)
        {
            this.name = name;
            this.author = author;
            this.url = url;
            if(hasit)
            {
                var bc = new BrushConverter();
                this.Background = (Brush)bc.ConvertFrom("#5522ff22");
            }
            else
            {
                var bc = new BrushConverter();
                this.Background = (Brush)bc.ConvertFrom("#55ff2222");
            }
        }
    }
}
<file_sep>﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Advanced_Blueprint_Tools
{
    /// <summary>
    /// Interaction logic for Cuboid_Generator.xaml
    /// </summary>
    public partial class Cuboid_Generator : Window
    {
        MainWindow mainWindow;
        public Cuboid_Generator(MainWindow mainWindow)
        {
            this.mainWindow = mainWindow;
            InitializeComponent();
        }

        private void Button_Help_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://youtu.be/glLgQemUS2I?t=1627");
        }

        private void Button_Create_Click(object sender, RoutedEventArgs e)
        {
            int thickness = Convert.ToInt32(TextBox_thickness.Text);
            int sizeX = Convert.ToInt32(TextBox_X.Text);
            int sizeY = Convert.ToInt32(TextBox_Y.Text);
            int sizeZ = Convert.ToInt32(TextBox_Z.Text) - thickness;


            dynamic Cuboid = new JObject();
            Cuboid.bodies = new JArray();
            Cuboid.bodies.Add(new JObject());
            Cuboid.bodies[0].childs = new JArray();

            Cuboid.bodies[0].childs.Add(block(0, 0, 0, sizeX, sizeY, thickness));
            Cuboid.bodies[0].childs.Add(block(0, 0, thickness, sizeX, thickness, sizeZ));
            Cuboid.bodies[0].childs.Add(block(0, 0, thickness, thickness, sizeY, sizeZ));
            Cuboid.bodies[0].childs.Add(block(sizeX - thickness, thickness, thickness, thickness, sizeY - thickness, sizeZ - thickness));
            Cuboid.bodies[0].childs.Add(block(thickness, sizeY - thickness , thickness, sizeX - thickness, thickness, sizeZ - thickness));
            Cuboid.bodies[0].childs.Add(block(thickness, thickness, sizeZ, sizeX - thickness, sizeY - thickness, thickness));

            string message = "++ A Cuboid has been generated!";
            Random r = new Random();
            string blueprintdir = Database.User_ + "\\Blueprints" + "\\GeneratedCuboid-" + r.Next() + r.Next();
            dynamic description = new JObject();
            description.description = "generated cuboid";
            description.name = "generated cuboid" + r.Next();
            description.type = "Blueprint";
            description.version = 0;

            if (BP.Blueprintpath == null)
            {//no blueprint exists, initialize new one
                new BP(blueprintdir, Cuboid, description);
            }
            else
            {//a blueprint exists, overwrite it
                BP.setblueprint(Cuboid);
                BP.Description.description += message;
            }
            mainWindow.RenderBlueprint();
        }

        private dynamic block(int x, int y, int z, int bx, int by, int bz)
        {
            dynamic block = new JObject();
            block.color = "5DB7E7";
            block.pos = new JObject();
            block.pos.x = x;
            block.pos.y = y;
            block.pos.z = z;
            block.bounds = new JObject();
            block.bounds.x = bx;
            block.bounds.y = by;
            block.bounds.z = bz;
            block.shapeId = "a6c6ce30-dd47-4587-b475-085d55c6a3b4";
            block.xaxis = 1;
            block.zaxis = 3;
            return block;
        }
        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox t = (TextBox)sender;
            try
            {
                if (Convert.ToInt32(t.Text) >= 0) { }
            }
            catch
            {
                if (t.Text == "-")
                {
                    t.Text = "-0";
                    t.Select(1, 1);
                }
                else
                {
                    t.Text = "0";
                    t.Select(0, 1);
                }
            }
        }
    }
}
