■変更前 ```csharp #region 追加関数等 private AbstractData convert_from_layer_type(AbstractVoid baseObj, string layerType) { // 塗り図形、領域オブジェクトの変換処理 // 省略 } private void _set_layer_and_layer_type(Quadcept.Interface.Manager.IPCBDataCore window, int layer, string layerType, int[] ids, bool isMoveLayerType) { // 層間移動処理 // 省略 } #endregion /// <summary> /// 層間移動モードへ切り替え /// </summary> /// <param name="window">対象DataCore</param> /// <param name="layer">層</param> /// <param name="layerType">層種類</param> /// <param name="isCopy">コピー</param> /// <param name="mgr">モードマネージャ</param> /// <returns>結果</returns> public OperationResult Execute(Quadcept.Interface.Manager.IPCBDataCore window, int layer, string layerType, bool isCopy, Quadcept.Command.PCB.CommandMode.DetailCommandModeManager mgr) { #region if (window.TempDataManager.SelectedObjects.Keys.Count == 0 || window.TempDataManager.Objects.Keys.Count() != 0) return OperationResult.Invalid; var targets = new List<Data.PCB.AbstractData>(); var isMoveLayerType = true; var selectCannotMoveItemTypeList = new HashSet<PCBItemType>(); // 層間移動チェックと移動 or コピー対象(clone)を抽出する。 foreach (var id in window.TempDataManager.SelectedObjects.Keys.ToArray()) { var tmp = window.TempDataManager.SelectedObjects[id]; if (tmp.ItemType.EqualsAny(PCBItemType.FootPrint, PCBItemType.Cutout, PCBItemType.Rat, PCBItemType.PadStack, PCBItemType.ViaStack, PCBItemType.Panel)) { selectCannotMoveItemTypeList.Add(tmp.ItemType); // 層間移動できないオブジェクトリスト continue; } if (!window.DataManager.Objects.AllObjectsContainsKey(id)) continue; var obj = window.DataManager.Objects[id]; if (obj.SharedLayer < 0) // システム層オブジェクトは他の層(物理層)に移動しない。 continue; // コピーモード で コピー不可なら対象にしない。 if (isCopy && !CopySelectedObjectsCommand.IsCanCopy(window, obj)) continue; if (window.TempDataManager.Objects.NetObjects.ContainsKey(obj.SharedNetName) && window.TempDataManager.Objects.NetObjects[obj.SharedNetName].Contains(obj)) isMoveLayerType = false; // 層種類変更フラグを落とす if (obj.ItemType.EqualsAny(PCBItemType.ArcRoute, PCBItemType.PolyRoute, PCBItemType.Route, PCBItemType.ConnectionPoint, PCBItemType.DynamicCopper, PCBItemType.StaticCopper, PCBItemType.FillingShape, PCBItemType.ThermalLine, PCBItemType.AssemblyArea)) isMoveLayerType = false; // 層種類変更フラグを落とす if (isCopy) targets.Add(obj.Clone(true)); else targets.Add(obj); } if (targets.Count != window.TempDataManager.SelectedObjects.Keys.Count) { // 移動(コピー)できないオブジェクトがあれば再選択メッセージ表示 var itemtypeMessage = new StringBuilder(); foreach (var type in selectCannotMoveItemTypeList) { itemtypeMessage.AppendLine(type.ToDescription()); } Quadcept.Interface.QuadceptModule.UIDialog.MessageDialog_Show(LM.GetResource(LM.Message.Mes_SelectedFailedToLayerMoveObject).F(itemtypeMessage.ToString()), Quadcept.Interface.UI.Dialog.Type.MessageDialog_CaptionType.Error); return OperationResult.Invalid; } using (Data.PCB.AbstractVoid.GeometriesCaches.Instance.CreateSection_Cache()) using (window.CreateSection_SheetMultiEntryCommand()) { var newDummyNet = OptimizeDummyNetCommand.GetNewDummyNet(window); var layerSetting = window.Environment.LayerSetting; if (!isCopy) { var targetIDs = new List<int>(); // 作業層変更 foreach (var obj in targets) targetIDs.Add(obj.ID); OptimizeDummyNetCommand.SetDummyNetToFixedMoveObjects(window.Environment.IsFixNet, newDummyNet, targets); _set_layer_and_layer_type(window, layer, layerType, targetIDs.ToArray(), isMoveLayerType); } else { var layerMovedIds = new HashSet<int>(); // 層移動、再選択するオブジェクトのID var clones = new List<Data.PCB.AbstractData>(); var newCopperIDs = new List<int>(); window.TempDataManager.Clear(); // cloneしたコピー対象オブジェクトの作業層、層種類更新する foreach (var obj in targets) { var cloneLayerType = isMoveLayerType ? layerType : obj.SharedLayerType; obj.SharedLayer = layer; switch (obj.ItemTypeBit) { // #14753 塗りオブジェクトの変換機能のミニマムとして実装(ベタ、部品領域には非対応) case PCBItemType.BitType.Polygon: case PCBItemType.BitType.PatternRestrictedArea: case PCBItemType.BitType.DrillRestrictedArea: case PCBItemType.BitType.ComponentRestrictedArea: case PCBItemType.BitType.HeightLimitArea: case PCBItemType.BitType.DesignRuleArea: clones.Add(convert_from_layer_type(obj as AbstractVoid, cloneLayerType)); break; default: obj.SharedLayerType = cloneLayerType; // 作業層、層種類が変更できないオブジェクトなら対象から除く(フェールセーフ) if (window.Environment.LayerSetting.GetLayer(obj.SharedLayer, obj.SharedLayerType) == null) continue; clones.Add(obj); break; } } // 層間移動のコピーは元オブジェクトと接触しない&フットプリント、パッドは移動対象外なので元と同じダミーネットが渡されても問題なかった。 // 「ネット固定しない」設定の対象となったので、相対移動、回転移動と同じチェックを追加( OptimizeDummyNetCommand.SetDummyNetToFixedCopyObjects(window.Environment.IsFixNet, newDummyNet, clones); foreach (var obj in clones) { if (obj.ItemType.Equals(PCBItemType.PadStack)) { obj.SharedPinNo = GetIncrementedUniqePadNumberCommand.Instance.Execute(window, obj.SharedPinNo, 1); } var fixedId = FixTempObjectsCommand.Instance.FixObject(window, -1, obj); layerMovedIds.Add(fixedId); //ベタ更新リストに追加 if (obj.ItemTypeBit == PCBItemType.BitType.DynamicCopper) { newCopperIDs.Add(fixedId); } } using (DetailCommand.DummyNet.Section.CreateSectionOldNetMerge(window)) // 旧ネットマージ // ダミーネット更新、ベタ更新、ラッツ更新 NetLogic.Instance.OptimizeCopperObject(window, newCopperIDs); // 移動(コピー)後のオブジェクトを最選択(複数コピーできないので「最後の」を考慮する必要なし) window.CommandManager.Commands.SelectObjects.Exucecute(layerMovedIds.ToArray()); } } window.CommandManager.Commands.Refresh.Exucecute(); return OperationResult.Invalid; #endregion } ``` ■変更後 ```csharp #region 追加関数等 PCBItemType[] _cant_move_layer_list = new PCBItemType[] { PCBItemType.FootPrint, PCBItemType.Cutout, PCBItemType.Rat, PCBItemType.PadStack, PCBItemType.ViaStack, PCBItemType.Panel }; PCBItemType[] _cant_move_layerType_list = new PCBItemType[] { PCBItemType.ArcRoute, PCBItemType.PolyRoute, PCBItemType.Route, PCBItemType.ConnectionPoint, PCBItemType.DynamicCopper, PCBItemType.StaticCopper, PCBItemType.FillingShape, PCBItemType.ThermalLine, PCBItemType.AssemblyArea }; PCBItemType[] _is_convert_ItemType = new PCBItemType[] { PCBItemType.Polygon, PCBItemType.PatternRestrictedArea, PCBItemType.DrillRestrictedArea, PCBItemType.ComponentRestrictedArea, PCBItemType.HeightLimitArea, PCBItemType.DesignRuleArea, }; private AbstractData convert_from_layer_type(AbstractVoid baseObj, string layerType) { // 塗り図形、領域オブジェクトの変換処理 // 省略 } private void _set_layer_and_layer_type(Quadcept.Interface.Manager.IPCBDataCore window, int layer, string layerType, int[] ids, bool isMoveLayerType) { // 層間移動処理 // 省略 } private static void _set_layer_and_layer_type(IPCBDataCore window, List<AbstractData> clones) { // パッドに新しい番号をセット _set_number_pad(window, clones); var layerMovedIds = new HashSet<int>(); // 層移動、再選択するオブジェクトのID var newCopperIDs = new List<int>(); foreach (var obj in clones) { var fixedId = FixTempObjectsCommand.Instance.FixObject(window, -1, obj); layerMovedIds.Add(fixedId); //ベタ更新リストに追加 if (obj.ItemTypeBit == PCBItemType.BitType.DynamicCopper) { newCopperIDs.Add(fixedId); } } using (DetailCommand.DummyNet.Section.CreateSectionOldNetMerge(window)) // 旧ネットマージ // ダミーネット更新、ベタ更新、ラッツ更新 NetLogic.Instance.OptimizeCopperObject(window, newCopperIDs); // 移動(コピー)後のオブジェクトを最選択(複数コピーできないので「最後の」を考慮する必要なし) window.CommandManager.Commands.SelectObjects.Exucecute(layerMovedIds.ToArray()); } private static void _set_number_pad(IPCBDataCore window, List<AbstractData> clones) { foreach (var obj in clones.Where(obj => obj.ItemType.Equals(PCBItemType.PadStack))) { obj.SharedPinNo = GetIncrementedUniqePadNumberCommand.Instance.Execute(window, obj.SharedPinNo, 1); } } private List<AbstractData> _create_clones(IPCBDataCore window, int layer, string layerType, List<AbstractData> targets, bool isMoveLayerType) { var clones = new List<Data.PCB.AbstractData>(); foreach (var obj in targets) { var clone = obj.Clone(true); var cloneLayerType = isMoveLayerType ? layerType : clone.SharedLayerType; clone.SharedLayer = layer; if (_is_convert_ItemType.Contains(clone.ItemType)) { clones.Add(_convert_from_layer_type(clone as AbstractVoid, cloneLayerType)); } else { clone.SharedLayerType = cloneLayerType; // 作業層、層種類が変更できないオブジェクトなら対象から除く(フェールセーフ) if (window.Environment.LayerSetting.GetLayer(clone.SharedLayer, clone.SharedLayerType) != null) clones.Add(clone); } } return clones; } private bool _checkMoveLayerType(IPCBDataCore window, List<AbstractData> targets) { foreach (var obj in targets) { if (window.TempDataManager.Objects.NetObjects.ContainsKey(obj.SharedNetName) && window.TempDataManager.Objects.NetObjects[obj.SharedNetName].Contains(obj)) return false; // 層種類変更フラグを落とす if (_cant_move_layerType_list.Contains(obj.ItemType)) return false; // 層種類変更フラグを落とす } return true; } private List<AbstractData> _create_copy_targetList(IPCBDataCore window) { var targets = new List<Data.PCB.AbstractData>(); foreach (var id in window.TempDataManager.SelectedObjects.Keys) { var tmp = window.TempDataManager.SelectedObjects[id]; if (!_cant_move_layer_list.Contains(tmp.ItemType)) { if (window.DataManager.Objects.AllObjectsContainsKey(id)) { var obj = window.DataManager.Objects[id]; if (obj.SharedLayer >= 0) // システム層オブジェクトは他の層(物理層)に移動しない。 { // コピー不可なら対象にしない。 if (CopySelectedObjectsCommand.IsCanCopy(window, obj)) targets.Add(obj); } } } } return targets; } private List<AbstractData> _create_move_targetList(IPCBDataCore window) { var targets = new List<Data.PCB.AbstractData>(); foreach (var id in window.TempDataManager.SelectedObjects.Keys) { var tmp = window.TempDataManager.SelectedObjects[id]; if (!_cant_move_layer_list.Contains(tmp.ItemType)) { if (window.DataManager.Objects.AllObjectsContainsKey(id)) { var obj = window.DataManager.Objects[id]; if (obj.SharedLayer >= 0) // システム層オブジェクトは他の層(物理層)に移動しない。 { targets.Add(obj); } } } } return targets; } private HashSet<PCBItemType> _create_selectCannotMoveItemTypeList(IPCBDataCore window) { var selectCannotMoveItemTypeList = new HashSet<PCBItemType>(); foreach (var id in window.TempDataManager.SelectedObjects.Keys) { var tmp = window.TempDataManager.SelectedObjects[id]; if (_cant_move_layer_list.Contains(tmp.ItemType)) selectCannotMoveItemTypeList.Add(tmp.ItemType); } return selectCannotMoveItemTypeList; } #endregion public OperationResult Execute(Quadcept.Interface.Manager.IPCBDataCore window, int layer, string layerType, bool isCopy, Quadcept.Command.PCB.CommandMode.DetailCommandModeManager mgr) { #region if (window.TempDataManager.SelectedObjects.Keys.Count == 0 || window.TempDataManager.Objects.Keys.Count() != 0) return OperationResult.Invalid; // 層間移動できないオブジェクト種類リスト HashSet<PCBItemType> selectCannotMoveItemTypeList = _create_selectCannotMoveItemTypeList(window); // 移動 or コピー対象(clone)となるオブジェクトリスト List<AbstractData> targets = isCopy? _create_copy_targetList(window): _create_move_targetList(window); // 層間移動チェック bool isMoveLayerType = _checkMoveLayerType(window, targets); if (targets.Count != window.TempDataManager.SelectedObjects.Keys.Count) { // 移動(コピー)できないオブジェクトがあれば再選択メッセージ表示 var itemtypeMessage = new StringBuilder(); foreach (var type in selectCannotMoveItemTypeList) { itemtypeMessage.AppendLine(type.ToDescription()); } Quadcept.Interface.QuadceptModule.UIDialog.MessageDialog_Show(LM.GetResource(LM.Message.Mes_SelectedFailedToLayerMoveObject).F(itemtypeMessage.ToString()), Quadcept.Interface.UI.Dialog.Type.MessageDialog_CaptionType.Error); return OperationResult.Invalid; } using (Data.PCB.AbstractVoid.GeometriesCaches.Instance.CreateSection_Cache()) using (window.CreateSection_SheetMultiEntryCommand()) { var newDummyNet = OptimizeDummyNetCommand.GetNewDummyNet(window); var layerSetting = window.Environment.LayerSetting; if (!isCopy) { var targetIDs = new List<int>(); // 作業層変更 foreach (var obj in targets) targetIDs.Add(obj.ID); OptimizeDummyNetCommand.SetDummyNetToFixedMoveObjects(window.Environment.IsFixNet, newDummyNet, targets); _set_layer_and_layer_type(window, layer, layerType, targetIDs.ToArray(), isMoveLayerType); } else { window.TempDataManager.Clear(); // cloneしたコピー対象オブジェクトの作業層、層種類更新する List<AbstractData> clones = _create_clones(window, layer, layerType, targets, isMoveLayerType); // 層間移動のコピーは元オブジェクトと接触しない&フットプリント、パッドは移動対象外なので元と同じダミーネットが渡されても問題なかった。 // 「ネット固定しない」設定の対象となったので、相対移動、回転移動と同じチェックを追加( OptimizeDummyNetCommand.SetDummyNetToFixedCopyObjects(window.Environment.IsFixNet, newDummyNet, clones); _set_layer_and_layer_type(window, clones); } } window.CommandManager.Commands.Refresh.Exucecute(); return OperationResult.Invalid; #endregion } ```