Skip to content

Commit c126f74

Browse files
committed
Working Beta
Issue for testing.
1 parent 8d2c9f1 commit c126f74

File tree

8 files changed

+379
-7
lines changed

8 files changed

+379
-7
lines changed

DataStructures/data.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ class Data(EventDispatcher):
4747
gcodeShift = ObjectProperty([0.0,0.0]) #the amount that the gcode has been shifted
4848
logger = Logger() #the module which records the machines behavior to review later
4949

50+
# Background image stuff, persist but not saved
51+
backgroundFile = None
52+
backgroundTexture = None
53+
backgroundManualReg = []
54+
backgroundRedraw = BooleanProperty(False)
55+
5056
'''
5157
Flags
5258
'''

Settings/maslowSettings.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,23 @@
572572
"key": "distPerRotRightChainTolerance",
573573
"firmwareKey": 41
574574
}
575+
],
576+
"Background Settings":
577+
[
578+
{
579+
"type": "string",
580+
"title": "Background File or Directory",
581+
"desc": "Current background file",
582+
"key": "backgroundFile",
583+
"default": ""
584+
},
585+
{
586+
"type": "list",
587+
"title": "Manual Registration",
588+
"desc": "Relative corner coords for image correction",
589+
"key": "manualReg",
590+
"default": []
591+
},
575592
]
576593
}
577594

UIElements/backgroundMenu.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import os
2+
from kivy.uix.gridlayout import GridLayout
3+
from UIElements.fileBrowser import FileBrowser
4+
from kivy.uix.popup import Popup
5+
from DataStructures.makesmithInitFuncs import MakesmithInitFuncs
6+
from UIElements.backgroundPickDlg import BackgroundPickDlg
7+
from kivy.core.image import Image as CoreImage
8+
from PIL import Image as PILImage
9+
from io import BytesIO
10+
import json
11+
12+
graphicsExtensions = (".jpg", ".png", ".jp2",".webp",".pbm",".ppm",".pgm")
13+
14+
15+
class BackgroundMenu(GridLayout, MakesmithInitFuncs):
16+
17+
def __init__(self, data, **kwargs):
18+
super(BackgroundMenu, self).__init__(**kwargs)
19+
self.data = data
20+
21+
def updateAlignmentInConfig(self):
22+
self.data.config.set('Background Settings', 'manualReg',
23+
self.data.backgroundManualReg)
24+
self.data.config.write()
25+
26+
def openBackground(self):
27+
'''
28+
Open The Pop-up To Load A File
29+
Creates a new pop-up which can be used to open a file.
30+
'''
31+
# Starting path is either where the last opened file was
32+
# or the users home directory
33+
if not os.path.isdir(self.data.backgroundFile):
34+
startingPath = os.path.dirname(self.data.backgroundFile)
35+
else:
36+
# Don't go up a dir if the "backgroundFile" is a directory!
37+
startingPath = self.data.backgroundFile
38+
if startingPath is "":
39+
startingPath = os.path.expanduser('~')
40+
# We want to filter to show only files that ground control can open
41+
validFileTypes = graphicsExtensions
42+
validFileTypes = ['*{0}'.format(fileType) for fileType in validFileTypes]
43+
44+
content = FileBrowser(select_string='Select',
45+
favorites=[(startingPath, 'Last Location')],
46+
path=startingPath,
47+
filters=validFileTypes, dirselect=False)
48+
content.bind(on_success=self.load, on_canceled=self.dismiss_popup,
49+
on_submit=self.load)
50+
self._popup = Popup(title="Select a file...", content=content,
51+
size_hint=(0.9, 0.9))
52+
self._popup.open()
53+
54+
def reloadBackground(self):
55+
self.processBackground()
56+
self.close()
57+
58+
def processBackground(self):
59+
if self.data.backgroundFile == "" or os.path.isdir(
60+
self.data.backgroundFile):
61+
self.data.backgroundTexture = None
62+
self.data.backgroundManualReg = []
63+
self.updateAlignmentInConfig()
64+
self.data.backgroundRedraw = True
65+
return
66+
else:
67+
img = PILImage.open(self.data.backgroundFile)
68+
img.thumbnail((1920, 1080), PILImage.ANTIALIAS)
69+
img = img.transpose(PILImage.FLIP_TOP_BOTTOM)
70+
imgBytes = BytesIO()
71+
img.save(imgBytes, format="png")
72+
imgBytes.seek(0)
73+
texture = CoreImage(imgBytes, ext="png").texture
74+
self.data.backgroundTexture = texture
75+
if self.data.backgroundManualReg:
76+
# Already have centers to use; just go on to warp_image
77+
self.warp_image()
78+
else:
79+
# Start the manual alignment process
80+
self.realignBackground()
81+
82+
def realignBackground(self):
83+
content = BackgroundPickDlg(self.data)
84+
content.setUpData(self.data)
85+
content.close = self.close_PickDlg
86+
self._popup = Popup(title="Background PointPicker", content=content,
87+
size_hint=(0.9, 0.9))
88+
self._popup.open()
89+
90+
def close_PickDlg(self, instance):
91+
if instance.accepted:
92+
# Update manual image registration marks
93+
self.data.backgroundManualReg = instance.tex_coords
94+
# Save the data from the popup
95+
self.updateAlignmentInConfig()
96+
self.warp_image()
97+
self.dismiss_popup()
98+
self.close()
99+
100+
def warp_image(self):
101+
self.data.backgroundRedraw = True
102+
103+
def clear_background(self):
104+
'''
105+
Clear background
106+
'''
107+
self.data.backgroundFile = ""
108+
self.processBackground()
109+
self.close()
110+
111+
def load(self, instance):
112+
'''
113+
Load A Background Image File from the file dialog
114+
Takes in a file path (from the pop-up filepicker
115+
or directory, if no file was picked) and processes it.
116+
'''
117+
if len(instance.selection) == 1:
118+
filename = instance.selection[0]
119+
else:
120+
# User pressed Submit without picking a file
121+
filename = instance.path
122+
# Save the file in the config...
123+
self.data.backgroundFile = filename
124+
self.data.config.set('Background Settings',
125+
'backgroundfile', str(self.data.backgroundFile))
126+
self.data.config.write()
127+
# close the open file popup
128+
self.dismiss_popup()
129+
# new image loaded so clear manual alignment centers
130+
self.data.backgroundManualReg = []
131+
# process it
132+
self.processBackground()
133+
# Close the menu, going back to the main page.
134+
self.close()
135+
136+
def dismiss_popup(self, *args):
137+
'''
138+
Close The File Picker (cancel was pressed instead of OK).
139+
'''
140+
self._popup.dismiss()
141+
pass

UIElements/backgroundPickDlg.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
from kivy.uix.gridlayout import GridLayout
2+
from kivy.properties import StringProperty, ListProperty, ObjectProperty
3+
from DataStructures.makesmithInitFuncs import MakesmithInitFuncs
4+
from kivy.vector import Vector
5+
6+
7+
class BackgroundPickDlg(GridLayout, MakesmithInitFuncs):
8+
instructionText = StringProperty("Drag bounding box to frame edges")
9+
texture = ObjectProperty(None)
10+
tex_coords = ListProperty([0, 0, 1, 0, 1, 1, 0, 1])
11+
tex_selection = ListProperty([0, 0, 100, 0, 100, 100, 0, 100])
12+
13+
def __init__(self, data, **kwargs):
14+
super(BackgroundPickDlg, self).__init__(**kwargs)
15+
self.data = data
16+
# Load the texture
17+
self.texture = self.data.backgroundTexture
18+
# Window is not set up yet, wait for size.update
19+
self.imWidg.bind(size=self.update)
20+
self.update()
21+
22+
def update(self, *args):
23+
if self.imWidg.size[0] is not 100 and self.imWidg.size[1] is not 100:
24+
# Widget is stable, update the textures bounds
25+
self.w, self.h = self.imWidg.size
26+
self.coeff_size = [self.w, self.h, self.w, self.h,
27+
self.w, self.h, self.w, self.h]
28+
# Place selection box
29+
self.tex_selection = [self.w * 0.2, self.h * 0.3,
30+
self.w * 0.9, self.h * 0.3,
31+
self.w * 0.9, self.h * 0.9,
32+
self.w * 0.2, self.h * 0.9]
33+
# Why??!!...
34+
self.resize_texture()
35+
self.reset_image()
36+
else:
37+
pass # Wait for widget to resize properly
38+
39+
def reset_image(self):
40+
self.tex_coords = [0, 0, 1, 0, 1, 1, 0, 1]
41+
42+
def resize_texture(self):
43+
coeffs = []
44+
padOffx, padOffy = self.imWidg.pos
45+
i = 0
46+
for (p, s) in zip(self.coeff_size, self.tex_selection):
47+
if i % 2: # y coord
48+
if p is not 0:
49+
coeffs.append(float(s - padOffy) / float(p))
50+
else:
51+
coeffs.append(0.0 - padOffy)
52+
else: # x coord
53+
if p is not 0:
54+
coeffs.append(float(s - padOffx) / float(p))
55+
else:
56+
coeffs.append(0.0 - padOffx)
57+
i += 1
58+
self.tex_coords = coeffs
59+
60+
def accept_texture(self):
61+
self.accepted = True
62+
self.close(self)
63+
64+
def on_touch_down(self, touch):
65+
for i in range(4):
66+
x, y = self.tex_selection[i*2:i*2+2]
67+
if Vector(x - touch.x, y - touch.y).length() < 10:
68+
touch.grab(self)
69+
touch.ud['tex'] = i
70+
return True
71+
72+
return super(BackgroundPickDlg, self).on_touch_down(touch)
73+
74+
def on_touch_move(self, touch):
75+
if touch.grab_current is not self:
76+
return super(BackgroundPickDlg, self).on_touch_move(touch)
77+
78+
tex = touch.ud.get('tex')
79+
80+
if tex is not None:
81+
self.tex_selection[tex * 2] = touch.x
82+
self.tex_selection[tex * 2 + 1] = touch.y
83+
84+
def on_touch_up(self, touch):
85+
if touch.grab_current is self:
86+
touch.ungrab(self)
87+
else:
88+
return super(BackgroundPickDlg, self).on_touch_up(touch)

UIElements/gcodeCanvas.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
from kivy.core.window import Window
1717
from UIElements.modernMenu import ModernMenu
1818
from kivy.metrics import dp
19+
from kivy.graphics.texture import Texture
20+
from kivy.graphics import Rectangle
1921

2022
import re
2123
import math
@@ -53,7 +55,8 @@ def initialize(self):
5355
Window.bind(on_resize = self.centerCanvas)
5456

5557
self.data.bind(gcode = self.updateGcode)
56-
self.data.bind(gcodeShift = self.reloadGcode)
58+
self.data.bind(backgroundRedraw = self.updateGcode)
59+
self.data.bind(gcodeShift = self.reloadGcode) #No need to reload if the origin is changed, just clear and redraw
5760
self.data.bind(gcodeFile = self.centerCanvasAndReloadGcode)
5861

5962
global_variables._keyboard = Window.request_keyboard(self._keyboard_closed, self)
@@ -215,6 +218,12 @@ def drawWorkspace(self, *args):
215218
Line(points = (-width/2,0,width/2,0), dash_offset = 5, group='workspace')
216219
Line(points = (0, -height/2,0,height/2), dash_offset = 5, group='workspace')
217220

221+
texture = self.data.backgroundTexture
222+
if texture is not None:
223+
Rectangle(texture=texture, pos=(-width/2, -height/2),
224+
size=(width, height),
225+
tex_coords=self.data.backgroundManualReg)
226+
218227
def drawLine(self,gCodeLine,command):
219228
'''
220229
@@ -565,6 +574,7 @@ def updateGcode(self, *args):
565574
'''
566575

567576
#reset variables
577+
self.data.backgroundRedraw = False
568578
self.xPosition = self.data.gcodeShift[0]*self.canvasScaleFactor
569579
self.yPosition = self.data.gcodeShift[1]*self.canvasScaleFactor
570580
self.zPosition = 0

UIElements/screenControls.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from DataStructures.makesmithInitFuncs import MakesmithInitFuncs
55
from UIElements.buttonTemplate import ButtonTemplate
66
from kivy.app import App
7+
from UIElements.backgroundMenu import BackgroundMenu
78

89

910
class ScreenControls(FloatLayout, MakesmithInitFuncs):
@@ -15,10 +16,12 @@ def setButtonAppearance(self):
1516
Called on creation to set up links to button background textures
1617
1718
'''
18-
self.actionsBtn.btnBackground = self.data.iconPath + 'Generic.png'
19-
self.actionsBtn.textColor = self.data.fontColor
20-
self.settingsBtn.btnBackground = self.data.iconPath + 'Generic.png'
21-
self.settingsBtn.textColor = self.data.fontColor
19+
self.actionsBtn.btnBackground = self.data.iconPath + 'Generic.png'
20+
self.actionsBtn.textColor = self.data.fontColor
21+
self.settingsBtn.btnBackground = self.data.iconPath + 'Generic.png'
22+
self.settingsBtn.textColor = self.data.fontColor
23+
self.backgroundBtn.btnBackground = self.data.iconPath + 'Generic.png'
24+
self.backgroundBtn.textColor = self.data.fontColor
2225

2326
def openSettings(self):
2427
'''
@@ -52,4 +55,15 @@ def close_actions(self):
5255
'''
5356
Close pop-up
5457
'''
55-
self._popup.dismiss()
58+
self._popup.dismiss()
59+
60+
def open_background(self):
61+
'''
62+
Open A Pop-up To Manage the Canvas Background
63+
'''
64+
content = BackgroundMenu(self.data)
65+
content.setUpData(self.data)
66+
content.close = self.close_actions
67+
self._popup = Popup(title="Background Picture", content=content,
68+
size_hint=(0.5, 0.5))
69+
self._popup.open()

0 commit comments

Comments
 (0)