diff --git a/__init__.py b/__init__.py index 8a147a8..77f2ce7 100644 --- a/__init__.py +++ b/__init__.py @@ -1,14 +1,16 @@ -# pcbnew loads this folder as a package using import -# thus __init__.py (this file) is executed -# We import the plugin class here and register it to pcbnew - -from . import AnnularChecker - -from . import FabricationPositions - -from . import MoveToLayer - -from . import PcbToDxf - -from . import Snap2Grid - +# pcbnew loads this folder as a package using import +# thus __init__.py (this file) is executed +# We import the plugin class here and register it to pcbnew + +from . import AnnularChecker + +from . import FabricationPositions + +from . import MoveToLayer + +from . import PcbToDxf + +from . import Snap2Grid + +from . import checking3Dmodels + diff --git a/checking3Dmodels/__init__.py b/checking3Dmodels/__init__.py new file mode 100644 index 0000000..f0087d7 --- /dev/null +++ b/checking3Dmodels/__init__.py @@ -0,0 +1,2 @@ +from .model3d_list import checkMissing3Dmodels +checkMissing3Dmodels().register() diff --git a/checking3Dmodels/missing3dmodels.png b/checking3Dmodels/missing3dmodels.png new file mode 100644 index 0000000..dd7603d Binary files /dev/null and b/checking3Dmodels/missing3dmodels.png differ diff --git a/checking3Dmodels/missing3dmodels.svg b/checking3Dmodels/missing3dmodels.svg new file mode 100644 index 0000000..511648e --- /dev/null +++ b/checking3Dmodels/missing3dmodels.svg @@ -0,0 +1,296 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/checking3Dmodels/model3d_list.py b/checking3Dmodels/model3d_list.py new file mode 100644 index 0000000..4a15a02 --- /dev/null +++ b/checking3Dmodels/model3d_list.py @@ -0,0 +1,215 @@ +# -*- coding: utf-8 -*- +# +# A script to checking 3D models in kicad_pcb +# requirements: KiCAD pcbnew >= 4.0 +# release "1.0.0" +# copyright https://github.com/MitjaNemec +# copyright Maurice easyw +# +# main script from https://forum.kicad.info/t/report-that-lists-step-models/29594/5 +# +# + +### plugins errors +#import pcbnew +#pcbnew.GetWizardsBackTrace() + + +___version___="1.0.0" +#wx.LogMessage("My message") +#mm_ius = 1000000.0 + +import sys, os +import pcbnew +import datetime +import wx +from pcbnew import * +import base64 +from wx.lib.embeddedimage import PyEmbeddedImage +from sys import platform as _platform + +""" +execfile (r"C:\Users\userC\AppData\Roaming\kicad\scripting\plugins\model3d-list.py") +""" + +import pcbnew +import os.path + +def check3D(): + import os + + + # board = pcbnew.LoadBoard(r'C:\Cad\Project_K\testboard.kicad_pcb') + my_board = pcbnew.GetBoard() + fileName = pcbnew.GetBoard().GetFileName() + + dirpath = os.path.abspath(os.path.expanduser(fileName)) + path, fname = os.path.split(dirpath) + ext = os.path.splitext(os.path.basename(fileName))[1] + name = os.path.splitext(os.path.basename(fileName))[0] + #wx.LogMessage(dir) + #lsep=os.linesep + lsep='\n' + + # if running standalone (outside of pcbnew) + if os.getenv("KISYS3DMOD") is None: + pt_lnx = False;pt_osx = False;pt_win = False; + if _platform == "linux" or _platform == "linux2": + # linux + pt_lnx = True + default_prefix3d = '/usr/share/kicad/modules/packages3d' + #'/usr/share/kicad/modules/packages3d' + elif _platform == "darwin": + #osx + pt_osx = True + default_prefix3d = '/Library/Application Support/kicad/packages3d' + #/Library/Application Support/kicad/modules/packages3d/' wrong location + else: + # Windows + pt_win = True + #default_prefix3d = os.path.join(os.environ["ProgramFiles"],u'\\KiCad\\share\\kicad\\modules\\packages3d') + default_prefix3d = (os.environ["ProgramFiles"]+u'\\KiCad\\share\\kicad\\modules\\packages3d') + #print (default_prefix3d) + default_prefix3d = re.sub("\\\\", "/", default_prefix3d) #default_prefix3d.replace('\\','/') + #print (default_prefix3d) + + os.environ["KISYS3DMOD"] = os.path.normpath(default_prefix3d) + if os.getenv("KIPRJMOD") is None: + os.environ["KIPRJMOD"] = os.path.abspath(os.path.dirname(my_board.GetFileName())) + + # prepare folder for 3Dmodels + proj_path = os.path.dirname(os.path.abspath(my_board.GetFileName())) + out_filename_missing_3D_models=proj_path+os.sep+name+"_missing3Dmodels.txt" + + # get all footprints + footprints = my_board.GetModules() + fp_without_models = [] + + # go through all the footprints + for fp in footprints: + fp_ref = fp.GetReference() + + # for each footprint get all 3D models + fp_models = fp.Models() + + # for each 3D model find it's path + for model in fp_models: + model_path = model.m_Filename + + # check if path is encoded with variables + if "${" in model_path or "$(" in model_path: + # get environment variable name + start_index = model_path.find("${") + 2 or model_path.find("$(") + 2 + end_index = model_path.find("}") or model_path.find(")") + env_var = model_path[start_index:end_index] + + # check if variable is defined + path = os.getenv(env_var) + + # if variable is defined, get absolute path + if path is not None: + clean_model_path = os.path.normpath(path + model_path[end_index + 1:]) + # if variable is not defined, we can not find the model. Thus don't put it on the list + else: + print("Can not find model defined with enviroment variable:\n" + model_path) + fp_without_models.append((fp_ref, model_path)) + continue + # check if path is absolute or relative + elif model_path == os.path.basename(model_path): + clean_model_path = os.path.normpath(proj_path + "//" + model_path) + # check if model is given with absolute path + elif os.path.exists(model_path): + clean_model_path = model_path + # otherwise we don't know how to parse the path + else: + print("Ambiguios path for the model: " + model_path) + # test default 3D_library location "KISYS3DMOD" + if os.path.exists(os.path.normpath(os.path.join(os.getenv("KISYS3DMOD"), model_path))): + clean_model_path = os.path.normpath(os.path.join(os.getenv("KISYS3DMOD"), model_path)) + print("Going with: " + clean_model_path) + # test in project folder location + elif os.path.exists(os.path.normpath(os.path.join(proj_path, model_path))): + clean_model_path = os.path.normpath(os.path.join(proj_path, model_path)) + print("Going with: " + clean_model_path) + else: + print("Can not find model defined with path:\n" + model_path) + fp_without_models.append((fp_ref, model_path)) + clean_model_path = None + continue + + model_path_without_extension = clean_model_path.rsplit('.', 1)[0] + + found_at_least_one = False + if clean_model_path: + model_without_extension = clean_model_path.rsplit('.', 1)[0] + for ext in ['.stp', '.step', '.stpZ']: + if os.path.exists(model_without_extension + ext): + found_at_least_one = True + if not found_at_least_one: + fp_without_models.append((fp.GetReference(), clean_model_path)) + + pass + pass + print(repr(fp_without_models)) + Header_1="### Missing 3D models - created on " + datetime.datetime.now().strftime("%Y-%m-%d %H:%M")+lsep + Header_1+="### Printed by checking_3D_models plugin"+lsep + #LogMsg+="## Side : All"+lsep + Header_2="Board file: " + str(fileName)+lsep + Header_2+="3D missing models written to:" + lsep + out_filename_missing_3D_models + lsep + Header_2+="-------" + lsep + content=Header_1+Header_2 + for fp in fp_without_models: + content+=str(fp)+lsep + content += "-------" + lsep + "NBR of 3D missing models:" + str(len(fp_without_models)) + lsep + content += "checked extensions ['.stp', '.step', '.stpZ']" + Header_2+="NBR of 3D missing models:" + str(len(fp_without_models))+ lsep + # new_content = "\n".join(content) + with open(out_filename_missing_3D_models,'w') as f_out: + f_out.write(content) + return Header_2 + +class checkMissing3Dmodels( pcbnew.ActionPlugin ): + """ + A script to checking 3D models in kicad_pcb + requirements: KiCAD pcbnew >= 4.0 + release "1.0.0" + """ + + def defaults( self ): + """ + Method defaults must be redefined + self.name should be the menu label to use + self.category should be the category (not yet used) + self.description should be a comprehensive description + of the plugin + """ + self.name = "Missing 3D models \nversion "+___version___ + self.category = "Missing 3D models" + self.description = "Missing 3D models\non kicad_pcb file" + #self.SetIcon(PyEmbeddedImage(getPos_ico_b64_data).GetIcon()) + self.icon_file_name = os.path.join(os.path.dirname(__file__), "./missing3dmodels.png") + self.show_toolbar_button = True + + def Run( self ): + _pcbnew_frame = [x for x in wx.GetTopLevelWindows() if x.GetTitle().lower().startswith('pcbnew')][0] + check3DMissing() + +def check3DMissing(): + + board = pcbnew.GetBoard() + + #fileName = GetBoard().GetFileName() + fileName = pcbnew.GetBoard().GetFileName() + if len(fileName)==0: + wx.MessageBox("a board needs to be saved/loaded!") + else: + LogMsg='' + # msg="'get_pos.py'"+os.linesep + msg="Missing 3D models \nversion "+___version___+os.linesep + + #print(msg) + LogMsg+=msg + reply=check3D() + LogMsg+=reply + wx.LogMessage(LogMsg) +