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">
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+