diff --git a/SEToolbox/Models/StructureCubeGridModel.cs b/SEToolbox/Models/StructureCubeGridModel.cs index 0ddaffc8..35f409f6 100644 --- a/SEToolbox/Models/StructureCubeGridModel.cs +++ b/SEToolbox/Models/StructureCubeGridModel.cs @@ -1057,6 +1057,48 @@ public bool ConvertToRoundArmor() return count > 0; } + public bool SetPivotPntHere(ViewModels.CubeItemViewModel selectedCubeItem) + { + // Is the selectedCubeItem the pivot point? + var definitionS = SpaceEngineersApi.GetCubeDefinition(selectedCubeItem.TypeId, CubeGrid.GridSizeEnum, selectedCubeItem.SubtypeId); + SerializableBlockOrientation blockOrientation = selectedCubeItem.Cube.BlockOrientation; + var cubePos = selectedCubeItem.Cube.Min.ToVector3I(); + if (definitionS.Size.X == 1 && definitionS.Size.Y == 1 && definitionS.Size.Z == 1) + { + } + else + { + var orientCenter = definitionS.Center.Transform(blockOrientation).Abs(); + cubePos = selectedCubeItem.Cube.Min.ToVector3I() + orientCenter; + } + if(cubePos.X == 0 && cubePos.Y == 0 && cubePos.Z == 0) + { + return false; + } + + //Update the position of each cube to be relative to the selected cube. + var position = selectedCubeItem.Position; + foreach (var cube in CubeGrid.CubeBlocks) + { + // Offset the cube's position by the passed position. + cube.Min = new SerializableVector3I(cube.Min.X - cubePos.X, cube.Min.Y - cubePos.Y, cube.Min.Z - cubePos.Z); + } + + //Offset the ship's position by the passed position. + var pivot = CubeGrid.PositionAndOrientation.Value.Position; + var scaledPosition = new VRageMath.Vector3D(cubePos.X, cubePos.Y, cubePos.Z); + scaledPosition *= CubeGrid.GridSizeEnum == MyCubeSize.Large ? 2.5 : 1.0; + CubeGrid.PositionAndOrientation = new MyPositionAndOrientation + { + Position = new VRageMath.Vector3D(pivot.X + scaledPosition.X, pivot.Y + scaledPosition.Y, pivot.Z + scaledPosition.Z), + Forward = CubeGrid.PositionAndOrientation.Value.Forward, + Up = CubeGrid.PositionAndOrientation.Value.Up + }; + + + return true; + } + #region Mirror public bool MirrorModel(bool usePlane, bool oddMirror) diff --git a/SEToolbox/Properties/Resources.resx b/SEToolbox/Properties/Resources.resx index 7b99118e..df500b35 100644 --- a/SEToolbox/Properties/Resources.resx +++ b/SEToolbox/Properties/Resources.resx @@ -3085,4 +3085,22 @@ Reason: {1} Can not find update + + Export CAD + + + Export model to SECAD ldr file. + + + Set Pivot Point + + + Use as Pivot Point + + + Set the pivot point to the selected cube item + + + ..\Resources\PivotPnt.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/SEToolbox/Resources/PivotPnt.png b/SEToolbox/Resources/PivotPnt.png new file mode 100644 index 00000000..78e27b33 Binary files /dev/null and b/SEToolbox/Resources/PivotPnt.png differ diff --git a/SEToolbox/ViewModels/ExplorerViewModel.cs b/SEToolbox/ViewModels/ExplorerViewModel.cs index b4f40b37..f43b39ee 100644 --- a/SEToolbox/ViewModels/ExplorerViewModel.cs +++ b/SEToolbox/ViewModels/ExplorerViewModel.cs @@ -1,6 +1,7 @@ namespace SEToolbox.ViewModels { using Sandbox.Common.ObjectBuilders; + using Sandbox.Definitions; using SEToolbox.Interfaces; using SEToolbox.Interop; using SEToolbox.Interop.Asteroids; @@ -142,6 +143,8 @@ public ExplorerViewModel(ExplorerModel dataModel, IDialogService dialogService, public ICommand ExportBlueprintCommand => new DelegateCommand(ExportBlueprintExecuted, ExportBlueprintCanExecute); + public ICommand ExportCADCommand => new DelegateCommand(ExportCADExecuted, ExportCADCanExecute); + public ICommand CreateFloatingItemCommand => new DelegateCommand(CreateFloatingItemExecuted, CreateFloatingItemCanExecute); public ICommand GenerateVoxelFieldCommand => new DelegateCommand(GenerateVoxelFieldExecuted, GenerateVoxelFieldCanExecute); @@ -430,7 +433,7 @@ public void OpenExecuted() public bool SaveCanExecute() { - return _dataModel.ActiveWorld != null && _dataModel.ActiveWorld.IsValid && + return _dataModel.ActiveWorld != null && _dataModel.ActiveWorld.IsValid && ((_dataModel.ActiveWorld.SaveType != SaveWorldType.DedicatedServerService && _dataModel.ActiveWorld.SaveType != SaveWorldType.CustomAdminRequired) || ((_dataModel.ActiveWorld.SaveType == SaveWorldType.DedicatedServerService || _dataModel.ActiveWorld.SaveType == SaveWorldType.CustomAdminRequired) && ToolboxUpdater.IsRuningElevated())); @@ -774,6 +777,17 @@ public void ExportBlueprintExecuted() ExportBlueprintToFile(Selections.ToArray()); } + public bool ExportCADCanExecute() + { + return _dataModel.ActiveWorld != null && _dataModel.ActiveWorld.IsValid && Selections.Count > 0 && + Selections.Any(e => e is StructureCubeGridViewModel); + } + + public void ExportCADExecuted() + { + ExportCADToFile(Selections.ToArray()); + } + public bool CreateFloatingItemCanExecute() { return _dataModel.ActiveWorld != null && _dataModel.ActiveWorld.IsValid; @@ -1205,10 +1219,10 @@ public void InertiaTensorExecuted(bool state) int count = SetInertiaTensor(Selections, true); IsBusy = false; - _dialogService.ShowMessageBox(this, - string.Format(Res.ClsExplorerGridChangesMade, count), - Res.ClsExplorerTitleChangesMade, - System.Windows.MessageBoxButton.OK, + _dialogService.ShowMessageBox(this, + string.Format(Res.ClsExplorerGridChangesMade, count), + Res.ClsExplorerTitleChangesMade, + System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information); } @@ -2036,6 +2050,186 @@ public void ExportBlueprintToFile(params IStructureViewBase[] viewModels) } } + public void ExportCADToFile(params IStructureViewBase[] viewModels) + { + string localBlueprintsFolder = null; + if (string.IsNullOrEmpty(_dataModel.ActiveWorld.DataPath.BlueprintsPath)) + { + // There is no blueprints under Dedicated Server, so cannot find the blueprint folder to save to. + _dialogService.ShowMessageBox(this, Res.ErrorNoBlueprintPath, Res.ErrorNoBlueprintPathTitle, System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + return; + } + localBlueprintsFolder = Path.Combine(_dataModel.ActiveWorld.DataPath.BlueprintsPath, SpaceEngineersConsts.LocalBlueprintsSubFolder); + + var saveFileDialog = _saveFileDialogFactory(); + saveFileDialog.Filter = "SECAD Model File|*.ldr";//AppConstants.CADExportFilter; + saveFileDialog.Title = "Export to SECAD";//Res.DialogExportCADTitle; + saveFileDialog.FileName = "export cad.ldr"; + saveFileDialog.OverwritePrompt = true; + + if (_dialogService.ShowSaveFileDialog(this, saveFileDialog) == DialogResult.OK) + { + // open the file for writing + using (StreamWriter sw = new StreamWriter(saveFileDialog.FileName, false, Encoding.ASCII)) + { + // write the header + sw.WriteLine("0 SECAD Model File"); + sw.WriteLine("0 Name: " + Path.GetFileNameWithoutExtension(saveFileDialog.FileName)); + sw.WriteLine("0 Author: SEToolbox"); + sw.WriteLine("0 Unofficial Model"); + sw.WriteLine("0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt"); + sw.WriteLine("0 Forward UP"); + sw.WriteLine(""); + + // Rotation matrix around X axis + Matrix matrix = Matrix.CreateFromAxisAngle(Vector3.UnitX, MathHelper.ToRadians(0)); + + // write the model + foreach (var viewModel in viewModels) + { + if (viewModel is StructureCubeGridViewModel model) + { + foreach (CubeItemViewModel block in model.CubeList) + { + MyCubeBlockDefinition definition = SpaceEngineersApi.GetCubeDefinition(block.TypeId, block.CubeSize, block.SubtypeId); + System.Windows.Media.Brush clr = block.Color; + BindablePoint3DIModel pos = block.Position; + Vector3I sz = definition.Size; + SerializableBlockOrientation blockOrientation = block.Cube.BlockOrientation; + + MatrixI mt = new MatrixI(blockOrientation); + Vector3I posT = Vector3.Transform(pos.ToVector3I(), matrix).RoundToVector3I(); + mt.ForwardVector = new Vector3I(mt.ForwardVector.X, mt.ForwardVector.Y, mt.ForwardVector.Z); + + // mt.Translation = pos.ToVector3I(); + // Matrix mtF = mt.GetFloatMatrix(); + + // Matrix mtPO = new SerializableBlockOrientation(Base6Directions.Direction.Up, Base6Directions.Direction.Forward).ToQuaternion().ToMatrix(); // model.DataModel.PositionAndOrientation.Value.ToMatrix(); + // mtPO = Matrix.Invert(mtPO); + // Matrix mtX = Matrix.Multiply(mtPO, mtF); + // mtX = Matrix.Round(ref mtX); + + // format for output is 1 < colour > x y z a b c d e f g h i < file > + sw.WriteLine(string.Format("0 TypeId: {0} SubTypeId: {1}", block.TypeId.ToString(), block.SubtypeId)); + sw.WriteLine(string.Format("0 {0}|Size:{1,3},{2,3},{3,3}|Orientation:{4,3} {5,3}|Pos:{6,3} {7,3} {8,3}", block.FriendlyName, sz.X, sz.Y, sz.Z, + blockOrientation.Forward.ToString(), blockOrientation.Up.ToString(), pos.X, pos.Y, pos.Z)); + + //Matrix m0 = mt.GetFloatMatrix(); + //Matrix m1 = new Matrix(1,0,0,0,1,0,0,0,-1); + //Matrix.Invert(ref m1, out m1); + + //Matrix m2 = Matrix.Multiply(m0, m1); + string posStr = string.Format("{0,3} {1,3} {2,3}", posT.X * 10, posT.Z * 10, posT.Y * 10); + + sw.WriteLine("0 RIGHT UP FORWARD"); + sw.WriteLine("0 _X_ _Y_ _Z_ _X_ _Y_ _Z_ _X_ _Y_ _Z_"); + string vecStr = string.Format("{0,3} {1,3} {2,3} {3,3} {4,3} {5,3} {6,3} {7,3} {8,3}", + mt.RightVector.X, mt.RightVector.Y, mt.RightVector.Z, + mt.UpVector.X, mt.UpVector.Y, mt.UpVector.Z, + mt.ForwardVector.X, mt.ForwardVector.Y, mt.ForwardVector.Z); + + sw.WriteLine("0 blockOrientation: {0}", vecStr); + sw.WriteLine("0"); + sw.WriteLine("0 RIGHT UP FORWARD"); + sw.WriteLine("0 CLR _X_ _Y_ _Z_ _X_ _Y_ _Z_ _X_ _Y_ _Z_ _X_ _Y_ _Z_"); + + MatrixI localMatrix = new MatrixI(Base6Directions.Direction.Forward, Base6Directions.Direction.Up); + Vector3I normal = definition.Center; + Vector3I normal2 = definition.Size - 1; + Vector3I.TransformNormal(ref normal2, ref localMatrix, out Vector3I result); + Vector3I.TransformNormal(ref normal, ref localMatrix, out Vector3I result2); + Vector3I vector3I = Vector3I.Abs(result); + Vector3I result3 = result2 + block.Cube.Min; + + if (result.X != vector3I.X) + { + result3.X += vector3I.X; + } + if (result.Y != vector3I.Y) + { + result3.Y += vector3I.Y; + } + if (result.Z != vector3I.Z) + { + result3.Z += vector3I.Z; + } + + + string line; + switch (block.TypeId.ToString()) + { + case "MyObjectBuilder_Thrust": + line = string.Format("1 9 {1} {2} Thruster.dat", 9, posStr, " 1 0 0 0 1 0 0 0 1"); + break; + case "MyObjectBuilder_Reactor": + line = string.Format("1 17 {1} {2} Lrg1x1x1.dat", 17, posStr, vecStr); + break; + case "MyObjectBuilder_LandingGear": + line = string.Format("1 73 {1} {2} LandingGear.dat", 73, posStr, vecStr); + break; + case "MyObjectBuilder_Beacon": + line = string.Format("1 25 {1} {2} Beacon.dat", 25, posStr, vecStr); + break; + case "MyObjectBuilder_Refinery": + line = string.Format("1 70 {1} {2} Refinery.dat", 70, posStr, vecStr); + break; + case "MyObjectBuilder_Assembler": + line = string.Format("1 {0,3} {1} {2} Assembler.dat", 15, posStr, vecStr); + break; + case "MyObjectBuilder_CargoContainer": + line = string.Format("1 19 {1} {2} Lrg1x1x1.dat", 19, posStr, vecStr); + break; + case "MyObjectBuilder_Gyro": + line = string.Format("1 74 {1} {2} Lrg1x1x1.dat", 74, posStr, vecStr); + break; + case "MyObjectBuilder_CubeBlock": + if (block.SubtypeId == "LargeHeavyBlockArmorBlock") + { + line = string.Format("1 8 {1} {2} LightArmour.dat", 8, posStr, vecStr); + } + else + { + line = string.Format("1 {0,-3} {1} {2} LightArmour.dat", 7, posStr, vecStr); + } + break; + case "MyObjectBuilder_ConveyorConnector": + line = string.Format("1 27 {1} {2} Lrg1x1x1.dat", 27, posStr, vecStr); + break; + case "MyObjectBuilder_ShipConnector": + line = string.Format("1 27 {1} {2} Lrg1x1x1.dat", 27, posStr, vecStr); + break; + case "MyObjectBuilder_Cockpit": + line = string.Format("1 2 {1} {2} Cockpit.dat", 2, posStr, vecStr); + break; + case "MyObjectBuilder_ShipWelder": + line = string.Format("1 29 {1} {2} Lrg1x1x2.dat", 29, posStr, vecStr); + break; + case "MyObjectBuilder_OxygenTank": + line = string.Format("1 14 {1} {2} OxygenTank.dat", 14, posStr, vecStr); + break; + case "MyObjectBuilder_OreDetector": + line = string.Format("1 15 {1} {2} OreDetector.dat", 15, posStr, vecStr); + break; + default: + if (block.SubtypeId == "") + { + line = string.Format("1 0 {1} {2} {5}.dat", 0, posStr, vecStr, block.TypeId.ToString()); + } + else + { + line = string.Format("1 0 {1} {2} {5}.dat", 0, posStr, vecStr, block.SubtypeId); + } + break; + } + sw.WriteLine(line); + sw.WriteLine(""); + } + } + } + } + } + } + public void TestCalcCubesModel(params IStructureViewBase[] viewModels) { var bld = new StringBuilder(); diff --git a/SEToolbox/ViewModels/StructureCubeGridViewModel.cs b/SEToolbox/ViewModels/StructureCubeGridViewModel.cs index 0a737658..550c3a5a 100644 --- a/SEToolbox/ViewModels/StructureCubeGridViewModel.cs +++ b/SEToolbox/ViewModels/StructureCubeGridViewModel.cs @@ -156,6 +156,8 @@ public StructureCubeGridViewModel(BaseViewModel parentViewModel, StructureCubeGr public ICommand ConvertCubeToFrameworkCommand => new DelegateCommand(ConvertCubeToFrameworkExecuted, ConvertCubeToFrameworkCanExecute); + public ICommand ConvertCubeSetPivotPntHere => new DelegateCommand(ConvertCubeSetPivotPointHereExecuted, ConvertCubeSetPivotPointHereCanExecute); + public ICommand ReplaceCubesCommand => new DelegateCommand(ReplaceCubesExecuted, ReplaceCubesCanExecute); public ICommand ColorCubesCommand => new DelegateCommand(ColorCubesExecuted, ColorCubesCanExecute); @@ -576,6 +578,20 @@ public bool ConvertCubeToFrameworkCanExecute(double value) return SelectedCubeItem != null; } + public void ConvertCubeSetPivotPointHereExecuted() + { + DataModel.SetPivotPntHere(SelectedCubeItem); + MainViewModel.IsModified = true; + MainViewModel.CalcDistances(); + IsSubsSystemNotReady = true; + DataModel.InitializeAsync(); + } + + public bool ConvertCubeSetPivotPointHereCanExecute() + { + return Selections.Count == 1; + } + public void ConvertCubeToFrameworkExecuted(double value) { MainViewModel.IsBusy = true; diff --git a/SEToolbox/Views/ControlCubeGrid.xaml b/SEToolbox/Views/ControlCubeGrid.xaml index a842297e..ea3b6900 100644 --- a/SEToolbox/Views/ControlCubeGrid.xaml +++ b/SEToolbox/Views/ControlCubeGrid.xaml @@ -15,786 +15,794 @@ mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="600" commands:DialogService.IsRegisteredView="True"> - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0.005 - - - - - 0.25 - - - - - 0.50 - - - - - 0.75 - - - - - 1.00 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0.005 - - - - - 0.25 - - - - - 0.50 - - - - - 0.75 - - - - - 1.00 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.005 + + + + + 0.25 + + + + + 0.50 + + + + + 0.75 + + + + + 1.00 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/SEToolbox/Views/WindowExplorer.xaml b/SEToolbox/Views/WindowExplorer.xaml index 9b04ce34..f6623b16 100644 --- a/SEToolbox/Views/WindowExplorer.xaml +++ b/SEToolbox/Views/WindowExplorer.xaml @@ -17,531 +17,536 @@ WindowStartupLocation="CenterScreen" Icon="/SEToolbox;component/app.ico" commands:DialogCloser.DialogResult="{Binding CloseResult}" commands:DialogService.IsRegisteredView="True"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -