images can be placed on the working area, rotated and translated.
This commit is contained in:
parent
4879aafb72
commit
8adf72a4be
5 changed files with 141 additions and 12 deletions
|
|
@ -24,8 +24,10 @@ def full_extension_tree():
|
|||
result = dict(
|
||||
# extensions for 3d model files
|
||||
model=dict(
|
||||
stl=["svg"]
|
||||
stl=["svg"],
|
||||
image=['jpg', 'jpeg', 'png', 'gif', 'bmp', 'pcx', 'webp']
|
||||
),
|
||||
|
||||
# extensions for printable machine code
|
||||
machinecode=dict(
|
||||
gcode=["gcode", "gco", "g", "nc"]
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ $(function(){
|
|||
url: API_BASEURL + "printer/printhead",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
contentType: "application/json; charset=UTF-8",
|
||||
contentType: "application/json; charset=UTF8",
|
||||
data: JSON.stringify({"command": "position", x:x, y:y})
|
||||
});
|
||||
}
|
||||
|
|
@ -387,6 +387,49 @@ $(function(){
|
|||
|
||||
};
|
||||
|
||||
self.placeIMG = function (file) {
|
||||
var url = self._getIMGserveUrl(file);
|
||||
var img = new Image();
|
||||
img.onload = function () {
|
||||
|
||||
var wpx = this.width;
|
||||
var hpx = this.height;
|
||||
|
||||
var dimPT = self.getUsefulDimensions(wpx, hpx);
|
||||
var wPT = dimPT[0];
|
||||
var hPT = dimPT[1];
|
||||
|
||||
var y = self.mm2svgUnits(self.workingAreaHeightMM()) - hPT;
|
||||
var newImg = snap.image(url, 0, y, wPT, hPT);
|
||||
var id = self.getEntryId(file);
|
||||
var previewId = self.generateUniqueId(id); // appends # if multiple times the same design is placed.
|
||||
newImg.attr({id: previewId, filter: 'url(#grayscale_filter)'});
|
||||
snap.select("#userContent").append(newImg);
|
||||
newImg.transformable();
|
||||
newImg.ftRegisterCallback(self.svgTransformUpdate);
|
||||
file.id = previewId;
|
||||
file.previewId = previewId;
|
||||
file.url = url;
|
||||
file.subtype = "bitmap";
|
||||
self.placedDesigns.push(file);
|
||||
};
|
||||
img.src = url;
|
||||
};
|
||||
|
||||
self.removeIMG = function(file){
|
||||
self.removeSVG(file);
|
||||
};
|
||||
|
||||
self.getUsefulDimensions = function(wpx, hpx){
|
||||
var maxWidthMM = wpx * 0.25; // TODO parametrize
|
||||
var aspectRatio = wpx / hpx;
|
||||
var destWidthMM = Math.min(self.workingAreaWidthMM(), 100, maxWidthMM);
|
||||
var destHeightMM = destWidthMM / aspectRatio;
|
||||
var destWidthPT = self.mm2svgUnits(destWidthMM);
|
||||
var destHeightPT = self.mm2svgUnits(destHeightMM);
|
||||
return [destWidthPT, destHeightPT];
|
||||
};
|
||||
|
||||
self.getDocumentDimensionsInPt = function(doc_width, doc_height, doc_viewbox){
|
||||
if(doc_width === null){
|
||||
// assume defaults if not set
|
||||
|
|
@ -426,7 +469,7 @@ $(function(){
|
|||
};
|
||||
|
||||
self.getDocumentViewBoxMatrix = function(widthStr, heightStr, vbox){
|
||||
var dim = self.getDocumentDimensionsInPt(widthStr, heightStr, vbox)
|
||||
var dim = self.getDocumentDimensionsInPt(widthStr, heightStr, vbox);
|
||||
if(vbox !== null ){
|
||||
var widthPx = dim[0];
|
||||
var heightPx = dim[1];
|
||||
|
|
@ -489,12 +532,22 @@ $(function(){
|
|||
|
||||
};
|
||||
|
||||
self._getIMGserveUrl = function(file){
|
||||
return self._getSVGserveUrl(file);
|
||||
};
|
||||
|
||||
self.templateFor = function(data) {
|
||||
var extension = data.name.split('.').pop().toLowerCase();
|
||||
if (extension === "svg") {
|
||||
return "wa_template_" + data.type + "_svg";
|
||||
if(data.type === "model" || data.type === "machinecode"){
|
||||
var extension = data.name.split('.').pop().toLowerCase();
|
||||
if (extension === "svg") {
|
||||
return "wa_template_" + data.type + "_svg";
|
||||
} else if (_.contains(['jpg', 'jpeg', 'png', 'gif', 'bmp', 'pcx', 'webp'], extension)) {
|
||||
return "wa_template_" + data.type + "_img";
|
||||
} else {
|
||||
return "wa_template_" + data.type;
|
||||
}
|
||||
} else {
|
||||
return "wa_template_" + data.type;
|
||||
return "wa_template_dummy";
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -606,7 +606,7 @@ class Server():
|
|||
(r"/downloads/files/local/(.*)", util.tornado.LargeResponseHandler, dict(path=s.getBaseFolder("uploads"), as_attachment=True, path_validation=util.tornado.path_validation_factory(lambda path: not os.path.basename(path).startswith("."), status_code=404))),
|
||||
(r"/downloads/logs/([^/]*)", util.tornado.LargeResponseHandler, dict(path=s.getBaseFolder("logs"), as_attachment=True, access_validation=util.tornado.access_validation_factory(app, loginManager, util.flask.admin_validator))),
|
||||
# serve instead of downloads for preview // as_attachment=False
|
||||
(r"/serve/files/local/([^/]*\.(gco|gcode|g|nc|svg))", util.tornado.LargeResponseHandler, dict(path=s.getBaseFolder("uploads"), as_attachment=False)),
|
||||
(r"/serve/files/local/([^/]*\.(gco|gcode|g|nc|svg|jpg|jpeg|png|gif|bmp|pcx|webp))", util.tornado.LargeResponseHandler, dict(path=s.getBaseFolder("uploads"), as_attachment=False)),
|
||||
# camera snapshot
|
||||
(r"/downloads/camera/current", util.tornado.UrlForwardHandler, dict(url=s.get(["webcam", "snapshot"]), as_attachment=True, access_validation=util.tornado.access_validation_factory(app, loginManager, util.flask.user_validator))),
|
||||
# generated webassets
|
||||
|
|
|
|||
|
|
@ -245,12 +245,26 @@ $(function() {
|
|||
return data["prints"]["last"]["success"] ? "text-success" : "text-error";
|
||||
};
|
||||
|
||||
// self.templateFor = function(data) {
|
||||
// var extension = data.name.split('.').pop().toLowerCase();
|
||||
// if (extension === "svg") {
|
||||
// return "files_template_" + data.type + "_svg";
|
||||
// } else {
|
||||
// return "files_template_" + data.type;
|
||||
// }
|
||||
// };
|
||||
self.templateFor = function(data) {
|
||||
var extension = data.name.split('.').pop().toLowerCase();
|
||||
if (extension === "svg") {
|
||||
return "files_template_" + data.type + "_svg";
|
||||
if(data.type === "model" || data.type === "machinecode"){
|
||||
var extension = data.name.split('.').pop().toLowerCase();
|
||||
if (extension === "svg") {
|
||||
return "files_template_" + data.type + "_svg";
|
||||
} else if (_.contains(['jpg', 'jpeg', 'png', 'gif', 'bmp', 'pcx', 'webp'], extension)) {
|
||||
return "files_template_" + data.type + "_img";
|
||||
} else {
|
||||
return "files_template_" + data.type;
|
||||
}
|
||||
} else {
|
||||
return "files_template_" + data.type;
|
||||
return "files_template_dummy";
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -221,6 +221,31 @@
|
|||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="wa_template_model_img">
|
||||
<div class="file_list_entry">
|
||||
<div class="title muted pull-left" data-bind="text: name"></div>
|
||||
<div class="btn-group action-buttons pull-right">
|
||||
<div class="btn btn-mini" data-bind="click: function() { $root.toggleTransformHandles($data); }"><i class="icon-move" title="{{ _('Transform') }}"></i></div>
|
||||
<div class="btn btn-mini" data-bind="click: function() { $root.removeIMG($data); }"><i class="icon-remove" title="{{ _('Remove') }}"></i></div>
|
||||
</div>
|
||||
<div class="detail_information" >
|
||||
<div class="local_transformation muted">
|
||||
<i class="icon-move" title="{{ _('translation') }}"></i>
|
||||
<span class="translation" >0,0</span>
|
||||
<i class="icon-resize-full" title="{{ _('scale') }}"></i>
|
||||
<span class="scale" >100%</span>
|
||||
<i class="icon-repeat" title="{{ _('rotation') }}"></i>
|
||||
<span class="rotation" >0°</span>
|
||||
|
||||
</div>
|
||||
<div class="misfit_warning" >
|
||||
<i class="icon-exclamation-sign" style="color:red;" title="{{ _('exceeds working area') }}"> Design exceeds the working area.</i>
|
||||
<a href="#" data-bind="click: function(){ $root.fitSVG($data) } ">Make it fit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
|
@ -241,6 +266,9 @@
|
|||
height: workingAreaHeightPx()+'px'
|
||||
}
|
||||
">
|
||||
<filter id = "grayscale_filter">
|
||||
<feColorMatrix in = "SourceGraphic" type = "saturate" values = "0"/>
|
||||
</filter>
|
||||
<g id="scaleGroup" data-bind="attr: { transform: scaleMatrix() }">
|
||||
<rect data-bind="click: move_laser"
|
||||
id="coordGrid" x="0" y="0" width="0" height="0"
|
||||
|
|
@ -525,6 +553,38 @@
|
|||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="files_template_model_img">
|
||||
<div class="file_list_entry">
|
||||
<i class="icon-camera file_list_icon"></i>
|
||||
<div class="title muted dropdown" >
|
||||
<a type="button" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
|
||||
<span data-bind="text: name"></span>
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li>
|
||||
<a class="" data-bind="attr: {href: $root.downloadLink($data), css: {disabled: !$root.downloadLink($data)}}"><i class="icon-download-alt" title="{{ _('Download') }}"></i> {{ _('Download') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="" data-bind="click: function() { if ($root.enableRemove($data)) { $root.removeFile($data); } else { return; } }, css: {disabled: !$root.enableRemove($data)}"><i class="icon-trash" title="{{ _('Remove') }}"></i> {{ _('Remove') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="uploaded">{{ _('Uploaded') }}: <span data-bind="text: formatTimeAgo(date)"></span></div>
|
||||
<div class="size">{{ _('Size') }}: <span data-bind="text: formatSize(size)"></span></div>
|
||||
<div class="btn-group action-buttons">
|
||||
<!-- <a class="btn btn-mini" data-bind="attr: {href: $root.downloadLink($data), css: {disabled: !$root.downloadLink($data)}}"><i class="icon-download-alt" title="{{ _('Download') }}"></i></a>
|
||||
<div class="btn btn-mini" data-bind="click: function() { if ($root.enableRemove($data)) { $root.removeFile($data); } else { return; } }, css: {disabled: !$root.enableRemove($data)}"><i class="icon-trash" title="{{ _('Remove') }}"></i></div>-->
|
||||
<div class="btn" data-bind="click: function() { if(!$root.workingArea.isPlaced($data)){ $root.workingArea.placeIMG($data); } }, css: {disabled: $root.workingArea.isPlaced($data)}"><i class="icon-ok" title="{{ _('Use') }}">Add</i></div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="files_template_model_dummy">
|
||||
<div class="file_list_entry">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="files_template_folder">
|
||||
<div class="title" data-bind="text: name"></div>
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue