Skip to content

Commit d5ff98e

Browse files
committed
No geometry changed - add "stl fixing" and selection from parts list to customizer.
1 parent c4ab3a6 commit d5ff98e

7 files changed

Lines changed: 51 additions & 18 deletions

File tree

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y openscad
33
ADD . /case
44
RUN pip3 install -e /case/customizer/
55
ENV LOG_LEVEL=info
6+
ENV CUSTOMIZER_THREADS=6
67
ENV MODULE_NAME=obs_case_customizer.app

customizer/src/obs_case_customizer/app.py

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from websockets.exceptions import ConnectionClosed
2525

2626
THREADS = int(os.environ.get('CUSTOMIZER_THREADS', 1))
27-
TIMEOUT = int(os.environ.get('CUSTOMIZER_JOB_TIMEOUT', 1200))
27+
TIMEOUT = int(os.environ.get('CUSTOMIZER_JOB_TIMEOUT', 2400))
2828
QUEUESIZE = int(os.environ.get('CUSTOMIZER_QUEUE_LENGTH', 20))
2929
TEMPLATEDIR = pkg_resources.resource_filename(__name__, 'templates')
3030

@@ -71,10 +71,19 @@ def field_type(entry, default_value):
7171
return "file"
7272
elif isinstance(default_value, bool):
7373
return "bool"
74+
if entry == "parts_list":
75+
return "parts_list"
7476
else:
7577
return "string"
7678

7779

80+
def all_parts():
81+
return [*ALL_PARTS, *[f"logo/CustomLogo/MainCase{l}-{inv}-{mn}"
82+
for l in ["", "Lid"]
83+
for inv in ["inverted", "normal"]
84+
for mn in ["main", "highlight"]]]
85+
86+
7887
templates.env.filters['field_type'] = field_type
7988

8089

@@ -90,9 +99,9 @@ def models(root):
9099

91100
async def queue_runner():
92101
while True:
93-
fun, arg = await queue.get()
94-
logging.info(f"running {arg}")
95-
await fun(arg)
102+
fun, kwargs = await queue.get()
103+
logging.info(f"running {kwargs}")
104+
await fun(**kwargs)
96105

97106

98107
@app.on_event('startup')
@@ -175,12 +184,10 @@ def package_to_zip(source: Path, target: Path):
175184
zf.write(name, zipped_name)
176185

177186

178-
async def run_job(uid, parts=None):
187+
async def run_job(uid=None, parts=None):
179188
global job_durations
180189
starttime = datetime.datetime.now()
181190

182-
if parts == None:
183-
parts = ALL_PARTS
184191
dir_to_work = Path(tempfile.gettempdir()) / uid
185192
logfile = dir_to_work / "log.txt"
186193
variables_file = dir_to_work / "variables.json"
@@ -192,6 +199,16 @@ async def run_job(uid, parts=None):
192199
"parts": parts,
193200
"status": "working",
194201
}
202+
203+
if parts == None:
204+
parts = ALL_PARTS
205+
if job_config.use_custom_logo:
206+
parts.extend([f"logo/CustomLogo/MainCase{l}-{inv}-{mn}"
207+
for l in ["", "Lid"]
208+
for inv in ["inverted", "normal"]
209+
for mn in ["main", "highlight"]])
210+
info["parts"] = parts
211+
195212
write_info_json = lambda: json.dump(info, info_file.open("wt"))
196213

197214
with tempfile.TemporaryDirectory() as temp:
@@ -202,13 +219,6 @@ async def run_job(uid, parts=None):
202219
await copy_build_files_to_build_dir(dir_to_work, temp, job_config.use_custom_logo)
203220

204221
try:
205-
if job_config.use_custom_logo:
206-
parts.extend([f"logo/CustomLogo/MainCase{l}-{inv}-{mn}"
207-
for l in ["", "Lid"]
208-
for inv in ["inverted", "normal"]
209-
for mn in ["main", "highlight"]])
210-
info["parts"] = parts
211-
write_info_json()
212222

213223
make_targets = [f'export/{name}.stl' for name in parts]
214224

@@ -282,6 +292,7 @@ async def _as_form(**data):
282292
@as_form
283293
class CustomVariables(BaseModel):
284294
use_custom_logo: bool = True
295+
fix_svg: bool = False
285296
MainCase_back_rider: bool = True
286297
MainCase_top_rider: bool = True
287298
MainCase_back_rider_cable: bool = True
@@ -313,7 +324,8 @@ class RunningJob(CustomVariables):
313324
def form_get(request: Request):
314325
# TODO: Switch to CustomVariables.schema for the generation of the <form>
315326
variables = CustomVariables()
316-
fields = [("main_case_logo_svg", ""), ("main_case_lid_logo_svg", ""), *variables.dict().items()]
327+
fields = [("main_case_logo_svg", ""), ("main_case_lid_logo_svg", ""), ("parts_list", all_parts()),
328+
*variables.dict().items()]
317329
return templates.TemplateResponse('customizer.html', context={'request': request, 'fields': fields})
318330

319331

@@ -367,7 +379,10 @@ async def jobstate(websocket: WebSocket, uid: uuid.UUID):
367379
async def form_post(request: Request,
368380
main_case_logo_svg: Optional[bytes] = File(None),
369381
main_case_lid_logo_svg: Optional[bytes] = File(None),
382+
parts_list: Optional[list] = None,
370383
variables: CustomVariables = Depends(CustomVariables.as_form)):
384+
if set(parts_list) - set(all_parts()):
385+
raise HTTPException(status_code=400, detail="Only valid parts can be generated")
371386
uid = str(uuid.uuid4())
372387
work_dir = Path(tempfile.gettempdir()) / uid
373388
logging.info(work_dir)
@@ -391,7 +406,7 @@ async def form_post(request: Request,
391406
variables_json_file.open("w").write(variables.json())
392407

393408
try:
394-
queue.put_nowait((run_job, uid))
409+
queue.put_nowait((run_job, dict(uid=uid, parts=parts_list)))
395410
except asyncio.QueueFull:
396411
return HTTPException(status_code=503, detail="Queue is full, please try again later")
397412

customizer/src/obs_case_customizer/templates/customizer.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@
3434
<input type="checkbox" {{'checked="checked"' if value else ''}} name="{{entry}}" id="{{entry}}" />
3535
{% elif ft == "file" %}
3636
<input type="file" name="{{entry}}" id="{{entry}}" accept="image/svg+xml"/>
37+
{% elif ft == "parts_list" %}
38+
<select name="parts_list" size="{{ value|length }}"multiple>
39+
{% for part in value %}
40+
<option value="{{part}}" selected>{{part}}</option>
41+
{% endfor %}
42+
</select>
3743
{% else %}
3844
<input type="text" title="{{entry}}" name="{{entry}}" id="{{entry}}" value="{{value}}"/>
3945
{% endif %}

lib/utils.scad

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,13 @@ module ScrewHoleM3(depth, head_depth=0, elongation=0) {
131131
elongation=elongation
132132
);
133133
}
134+
135+
module load_svg(filename) {
136+
// some SVG produce strange geometry. This is a bit slower but fixes the issues.
137+
if (fix_svg) {
138+
offset(delta = epsilon) import(filename);
139+
}
140+
else {
141+
import(filename);
142+
}
143+
}

src/MainCase/MainCase.scad

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ if (logo_generate_templates) {
586586
mirror([0, 1, 0])
587587
rotate([0, 0, -90])
588588
translate([0, -72-72, 0])
589-
import(str("../../logo/", logo_name, "/MainCase.svg"));
589+
load_svg(str("../../logo/", logo_name, "/MainCase.svg"));
590590
}
591591
}
592592

src/MainCase/MainCaseLid.scad

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ if (logo_generate_templates) {
146146
}
147147
mirror([1, 0, 0])
148148
translate([-104, -72-72, 0])
149-
import(str("../../logo/", logo_name, "/MainCaseLid.svg"));
149+
load_svg(str("../../logo/", logo_name, "/MainCaseLid.svg"));
150150
}
151151
}
152152
// When changing MainCase outer dimensions, check that the rim does still fit by removing the asterisk

variables.scad

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ extrude_width = 0.46;
1414
// Simplifies printing by adding smart bridges to remove need for supports.
1515
enable_easy_print = true;
1616
enable_text = true;
17+
fix_svg = false;
1718

1819
// Used e.g. by easy print algorithms.
1920
layer_height = 0.2;

0 commit comments

Comments
 (0)