-
Notifications
You must be signed in to change notification settings - Fork 4
/
archive_3d_models.py
executable file
·157 lines (135 loc) · 7.13 KB
/
archive_3d_models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import os
import os.path
import logging
import shutil
import re
logger = logging.getLogger(__name__)
def get_variable(env_var):
path = os.getenv(env_var)
if path is None and (env_var == "KISYS3DMOD" or re.match("KICAD.*_3DMODEL_DIR", env_var)):
path = os.getenv("KICAD7_3DMODEL_DIR")
if path is None:
path = os.getenv("KICAD6_3DMODEL_DIR")
return path
class Archiver():
def __init__(self, model_local_path="/packages3D"):
self.model_local_path = model_local_path
def archive_3d_models(self, board, remap_missing_models=False):
logger.info("Starting to archive 3D models")
logger.debug("All defined environment variables: " + repr(os.environ))
# prepare folder for 3D models
prj_path = os.path.dirname(os.path.abspath(board.GetFileName()))
model_folder_path = os.path.normpath(prj_path + self.model_local_path)
# go to project folder
os.chdir(prj_path)
if not os.path.exists(model_folder_path):
os.makedirs(model_folder_path)
# get all footprints
footprints = board.GetFootprints()
# go through all footprints
not_copied = []
for fp in footprints:
fp_ref = fp.GetReference()
logger.info("Getting 3D models for footprint of: " + fp_ref)
# find all 3D models linked to footprint
models = fp.Models()
# go through all models bound to footprint
# bad python API
nr_models = len(models)
models_to_push_back = []
for index in range(nr_models):
# pop one 3D model from the list
model = models.pop()
# copy 3D model
model_path = model.m_Filename
logger.info("Trying to copy: " + model_path)
# check if model path includes environment variable
abs_model_path = None
if "${" in model_path:
start_index = model_path.find("${")+2
end_index = model_path.find("}")
env_var = model_path[start_index:end_index]
path = get_variable(env_var)
# if variable is defined, find proper model path
if path is not None:
abs_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:
logger.info("Can not find model defined with enviroment variable:\n" + model_path)
abs_model_path = None
elif "$(" in model_path:
start_index = model_path.find("$(")+2
end_index = model_path.find(")")
env_var = model_path[start_index:end_index]
path = get_variable(env_var)
# if variable is defined, find proper model path
if path is not None:
abs_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:
logger.info("Can not find model defined with enviroment variable:\n" + model_path)
abs_model_path = None
# check if there is no path (model is local to project)
elif prj_path == os.path.dirname(os.path.abspath(model_path)):
abs_model_path = os.path.abspath(model_path)
# check if model is given with absolute path
elif os.path.exists(model_path):
abs_model_path = os.path.abspath(model_path)
# otherwise we don't know how to parse the path
else:
logger.info("Ambiguous path for the model: " + model_path)
# test default 3D_library location if defined
if os.getenv("KICAD6_3DMODEL_DIR"):
if os.path.exists(os.path.normpath(os.path.join(os.getenv("KICAD6_3DMODEL_DIR"), model_path))):
abs_model_path = os.path.normpath(os.path.join(os.getenv("KICAD6_3DMODEL_DIR"), model_path))
logger.info("Going with: " + abs_model_path)
# test default 3D_library location if defined
elif os.getenv("KICAD7_3DMODEL_DIR"):
if os.path.exists(os.path.normpath(os.path.join(os.getenv("KICAD7_3DMODEL_DIR"), model_path))):
abs_model_path = os.path.normpath(os.path.join(os.getenv("KICAD7_3DMODEL_DIR"), model_path))
logger.info("Going with: " + abs_model_path)
# testing project folder location
elif os.path.exists(os.path.normpath(os.path.join(prj_path, model_path))):
abs_model_path = os.path.normpath(os.path.join(prj_path, model_path))
logger.info("Going with: " + abs_model_path)
else:
abs_model_path = None
logger.info("Can not find model defined with: " + model_path)
# copy model
model_missing = True
if abs_model_path:
model_without_extension = abs_model_path.rsplit('.', 1)[0]
for ext in ['.wrl', '.stp', '.step', '.igs', '.WRL', '.STP', '.STEP', '.IGS']:
try:
shutil.copy2(model_without_extension + ext, model_folder_path)
model_missing = False
# src and dst are the same
except shutil.Error:
model_missing = False
# file not found
except (OSError, IOError):
pass
# correct abs_model path for logging
else:
abs_model_path = model_path
if model_missing:
logger.info("Did not copy: " + model.m_Filename)
not_copied.append((fp_ref, model.m_Filename))
if not model_missing or remap_missing_models:
logger.info("Remapping: " + model.m_Filename)
filename = os.path.basename(abs_model_path)
new_path = "${KIPRJMOD}" + self.model_local_path + "/" + filename
model.m_Filename = new_path
# and push it to the back of the list (changed or unchaged)
models_to_push_back.append(model)
# push all the models back
for m in models_to_push_back:
models.push_back(m)
if not_copied:
not_copied_pretty = [(x[0], os.path.normpath(x[1])) for x in not_copied]
str_list = [repr(x) for x in not_copied_pretty]
logger.info("Did not succeed to copy 3D models!\n"
+ "\n".join(str_list))
return not_copied
else:
return []