sdl_elm.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. #!/usr/bin/python3
  2. import pygame
  3. import pygame.gfxdraw
  4. import pygame.font
  5. from lib.xcolor import *
  6. font0 = pygame.font.SysFont("freesans",10)
  7. font0b = pygame.font.SysFont("freesansbold",10)
  8. font = pygame.font.SysFont("freemonobold",22)
  9. font10 = pygame.font.SysFont("freemonobold",10)
  10. font12 = pygame.font.SysFont("freemonobold",12)
  11. font15 = pygame.font.SysFont("freemonobold",15)
  12. font22 = pygame.font.SysFont("FreeSans",22)
  13. #font = pygame.font.SysFont(None,30)
  14. def check_rgb(rgb):
  15. rgb_out = [127,127,127,127]
  16. try:
  17. for i,v in enumerate(rgb):
  18. if v > 255:
  19. v = 255
  20. if v < 0:
  21. v = 0
  22. rgb_out[i] = v
  23. except Exception as e:
  24. print("rgb exception ",e)
  25. return rgb_out
  26. class VALUE():
  27. def __init__(self,v=0,_min=0,_max=255):
  28. self._val = v
  29. self._max = _max
  30. self._min = _min
  31. def _check(self):
  32. if self._val > self._max:
  33. self._val = self._max
  34. if self._val < self._min:
  35. self._val = self._min
  36. def get(self):
  37. self._check()
  38. return self._val
  39. def set(self,val):
  40. if val <= self._max and val >= self._min:
  41. self._val = val
  42. def inc(self,v):
  43. self._val += v
  44. self._check()
  45. class ELEM_KILLGROUP():
  46. def __init__(self):
  47. self.data = []
  48. def insert(self,elm):
  49. if elm not in self.data:
  50. self.data.append(elm)
  51. return 1
  52. return 0
  53. def clean(self,elm):
  54. v = elm.val
  55. for i in self.data:
  56. i.clear()
  57. #elm.set(v)
  58. return v
  59. class CALLBACK():
  60. def __init__(self):
  61. self._cb = self.dummy
  62. self.ok = 0
  63. def cb(self,*args):
  64. if self.ok:
  65. print("CALLBACK.cb",args)
  66. #try:
  67. self._cb(args)
  68. #except Exception as e:
  69. # print(" Exception CALLBACK.cb",args)
  70. def dummy(self,arg):
  71. print("CALLBACK.dummy",arg)
  72. def set(self,cb):
  73. self._cb = cb
  74. self.ok = 1
  75. print("CALLBACK",cb)
  76. class ELEM_BUF():
  77. def __init__(self,kill=None,name="ELEM_BUF"):
  78. self.val = VALUE() #0
  79. self.increment = 10
  80. self.name = name
  81. self.cb_on = CALLBACK()
  82. self.cb_off = CALLBACK()
  83. self.nr_on = [0]
  84. self.nr_off = [0]
  85. self.color = [0,255,0]
  86. self.color_on = [255,255,0]
  87. self.type="flash" #"toggle" #"flash",fade
  88. self.killgroup = kill
  89. self.events = []
  90. def _rep__(self):
  91. x="<ELEM_BUF name:{} val:{} id:{}>".format(self.name,self.val.get(), id(self))
  92. def get_event(self):
  93. out = self.events[:]
  94. self.events = []
  95. return out
  96. def get(self):
  97. return self.val.get()
  98. def get_color(self):
  99. if self.val.get():
  100. return self.color_on
  101. return self.color
  102. def clean(self):
  103. self.val.set(0)
  104. def press(self):
  105. #print("ELEM_BUF.press",[self.name,self.type,self.val.get()])
  106. if self.type == "fader":
  107. self.inc(self.increment)
  108. if self.type == "toggle":
  109. if self.val.get():
  110. self.val.set(0)
  111. else:
  112. self.val.set(1)
  113. if self.type == "flash":
  114. self.val.set(1)
  115. self.events.append("press")
  116. self.cb_on.cb("ho")
  117. def release(self):
  118. if self.type == "fader":
  119. self.inc(-self.increment)
  120. if self.type == "flash":
  121. self.val.set(0)
  122. self.events.append("release")
  123. def inc(self,v):
  124. self.val.inc(v)
  125. class Layout():
  126. def __init__(self,master):
  127. self.master = master
  128. def pack(self,**args):
  129. pass
  130. def grid(self,**args):
  131. pass
  132. def bind(self,**args):
  133. pass
  134. def get_font_hight(font):
  135. fr = font.render("test_font_hight" ,1, (0,0,0))
  136. r = fr.get_rect()
  137. h = r[3]
  138. return h
  139. def draw_bd(pos=[0,0,10,10],delta=0):
  140. d = delta
  141. xpos = (
  142. (pos[0]-d ,pos[1]-d),
  143. (pos[0]+pos[2]+d-1 ,pos[1]-d),
  144. (pos[0]+pos[2]+d-1 ,pos[1]+pos[3]+d-1),
  145. (pos[0]-d ,pos[1]+pos[3]+d-1)
  146. )
  147. i_old = None
  148. ypos = []
  149. for i in xpos:
  150. if i_old:
  151. ypos.append( (i_old,i) )
  152. i_old = i
  153. ypos.append( (i_old,xpos[0]) )
  154. return ypos
  155. def check_area_v(v1,v2,event_v):#elm_pos,event_pos):
  156. if event_v < v1+1:
  157. return 0
  158. if event_v > v2-1:
  159. return 0
  160. return 1
  161. def check_area(pos,event_pos):
  162. v2 = pos[0]+pos[2]
  163. x = check_area_v(pos[0],v2,event_pos[0])
  164. v2 = pos[1]+pos[3]
  165. y = check_area_v(pos[1],v2,event_pos[1])
  166. if x and y:
  167. return 1
  168. def check_area2_dir(R1,R2):
  169. r2 = R2[:] #mouse_box
  170. xd = 1
  171. yd = 1
  172. if r2[0] > r2[2]:
  173. r2[0],r2[2] = r2[2],r2[0]
  174. xd=-1
  175. if r2[1] > r2[3]:
  176. r2[1],r2[3] = r2[3],r2[1]
  177. yd=-1
  178. #print("check_area2_dir",xd,yd)
  179. return xd,yd,r2
  180. def check_area2(R1,R2): #pos,mouse_box
  181. xd,yd,r2 = check_area2_dir(R1,R2)
  182. btn_box = R1[:] #btn_box
  183. w=btn_box[2]
  184. h=btn_box[3]
  185. p1 = [btn_box[0],btn_box[1]]
  186. p4 = [btn_box[0]+w,btn_box[1]+h]
  187. x=0
  188. if r2[2] > p1[0] and r2[0] < p4[0]:
  189. x+=1
  190. y=0
  191. if r2[3] > p1[1] and r2[1] < p4[1]:
  192. y+=1
  193. if x and y:#> 4:
  194. #print("btn",R1,"mouse",R2)
  195. #print("btn",btn_box,"mouse",r2)
  196. #print("area2",x,y)
  197. return 1
  198. class Button():
  199. def __init__(self,window,pos):
  200. self.window = window
  201. self.event_pos = [0,0]
  202. self.font0 = pygame.font.SysFont("freesans-bold",16)
  203. self.w = 20
  204. self.h = 10
  205. self.pos = pos
  206. self.rel_pos = [0,0]
  207. self.fader = "h" #v
  208. self.ATTR = "XX"
  209. self.ID = "0"
  210. self.btn1 = ELEM_BUF()
  211. self.btn1.name = "BUTTON"
  212. self.btn1.nr_on = [1,3]
  213. self.btn1.nr_off = [1,3]
  214. #self.btn1.color = LIGHTGRAY
  215. self.btn1.color = GRAY
  216. self.btn1.color_on = RED
  217. self.btn2 = ELEM_BUF() # sel elem
  218. self.btn2.name = "SELECT BUF"
  219. self.btn2.nr_on = [2]
  220. self.btn2.nr_off = [0]
  221. self.btn2.color = GRAY
  222. self.btn2.color_on = YELLOW
  223. self.btn2.type = "toggle"
  224. self.btn3 = ELEM_BUF()
  225. self.btn3.name = "MOUSE FOCUS"
  226. self.btn3.color = GRAY
  227. self.btn3.color_on = WHITHE
  228. self.btn4 = ELEM_BUF()
  229. self.btn4.name = "MOUSE ENCODER"
  230. self.btn4.increment = 4.4
  231. self.btn4.type = "fader"
  232. self.btn4.nr_on = [4]
  233. self.btn4.nr_off = [5]
  234. self.btn4.color = GRAY
  235. self.btn4.color_on = WHITHE
  236. self.btns = []
  237. self.btns.append(self.btn1)
  238. self.btns.append(self.btn2)
  239. self.btns.append(self.btn3)
  240. self.btns.append(self.btn4)
  241. self.__layout = Layout(self)
  242. self.pack = self.__layout.pack
  243. self.grid = self.__layout.grid
  244. self.bind = self.__layout.bind
  245. self.text = "line1\nline2"
  246. self.type = "toggle" # flash, kill
  247. self.dbg = 0
  248. self.text2 = []
  249. def __repr__(self):
  250. x="<sdl.BUTTON name:{} ID:{}-{:8} btn1:{:03} val2:{:03} id at {}>"
  251. x=x.format(self.btn1.name,self.ID,self.ATTR,self.btn1.val.get(),self.btn4.val.get(), id(self))
  252. return x
  253. def check(self):
  254. if self.dbg:
  255. self.text2 = []
  256. #self.text2.append(self.val)
  257. b = []
  258. for btn in self.btns:
  259. b.append(btn.get())
  260. self.text2.append(b)
  261. self.text2.append(self.btn1.type)
  262. self._check_event()
  263. self._check_min_hight()
  264. def draw(self,text="GOBO1"):
  265. self.check()
  266. self.window.set_alpha(128)
  267. self._draw_bg()
  268. self._draw_fader()
  269. self._draw_font(text="")
  270. rgb = self.btn2.get_color()
  271. self._draw_bd(color=rgb)
  272. self._draw_bd(delta=-1)
  273. rgb = self.btn3.get_color()
  274. self._draw_bd(delta=-2,color=rgb)
  275. def get_rect(self):
  276. self.check()
  277. return self.pos[:]
  278. def _check_min_hight(self):
  279. c = 1+ self.text.count("\n") #+1
  280. c += len(self.text2)
  281. fh = get_font_hight(self.font0)
  282. h = (fh+1)*c +6#8 #+8
  283. if self.pos[3] < h:
  284. self.pos[3] = h #ah+20
  285. def _draw_bg(self):
  286. pos = self.pos
  287. rgb = self.btn1.get_color()
  288. rgb = check_rgb(rgb)
  289. pygame.draw.rect(self.window,rgb,pos)
  290. def _draw_fader(self):
  291. rgb = [0,200,0]
  292. rgb = self.btn4.color_on
  293. pos2 = self.pos[:]
  294. hight = pos2[3]
  295. v = self.btn4.val.get() #self.val.get()
  296. fh = get_font_hight(self.font0)
  297. _max_val = self.btn4.val._max
  298. if self.fader == "h":
  299. pos2[1] += 2 #fh+2
  300. pos2[3] = 4 #fh+2
  301. if v > 0:
  302. pos2[2] = int(pos2[2]* v/_max_val)
  303. else:
  304. pos2[2] = 4
  305. pygame.draw.rect(self.window,rgb,pos2)
  306. elif self.fader == "v":
  307. if v > 0:
  308. pos2[1] += int((hight-20)* v/_max_val)
  309. pos2[3] = 20
  310. else:
  311. pos2[3] = 20
  312. pos2[0] += 6
  313. pos2[2] -= 12
  314. pygame.draw.rect(self.window,rgb,pos2)
  315. def _draw_font(self,text=""):
  316. pos = self.pos
  317. a = pos[0]+4
  318. r = pos[1]+4
  319. v = "{:4.02f}".format(self.btn4.val.get())
  320. lines = self.text.split("\n")
  321. lines.extend(self.text2)
  322. for i in lines:
  323. i = str(i)
  324. if "<ival%>" in i:
  325. v=float(v)
  326. v=v/self.btn4.val._max*100
  327. v=int(v)
  328. i = i.replace("<ival%>",str(v))
  329. if "<ival>" in i:
  330. i = i.replace("<ival>",str(int(float(v))))
  331. if "<val>" in i:
  332. i = i.replace("<val>",v)
  333. fr = self.font0.render(i ,1, (0,0,0))
  334. fr_r=fr.get_rect()
  335. p2 = [pos[0]+4,r,fr_r[2],fr_r[3]]
  336. if 0:# dbg # bg highlight
  337. pygame.draw.rect(self.window,[0,0,255],p2)
  338. self.window.blit(fr,(a,r))
  339. r+=fr_r[3]+1
  340. def _set_mouse_focus(self,state):
  341. if state:
  342. self.btn3.press() # mouse focus on
  343. else:
  344. self.btn3.release()
  345. def _check_event(self):
  346. pass
  347. def _draw_bd(self,delta=0,color=GRAY):#BLACK):
  348. l_pos = draw_bd(pos=self.pos,delta=delta)
  349. for i in l_pos:
  350. pygame.draw.aaline(self.window,color,i[0],i[1],1)
  351. def event(self,event=None):
  352. r_event = {}
  353. if "pos" in event.dict:
  354. self.event_pos = event.pos[:]
  355. update_rel_pos = 0
  356. if "buttons" in event.dict:
  357. if event.dict["buttons"][0]:
  358. update_rel_pos = 1
  359. if "button" in event.dict:
  360. if event.dict["button"] == 1:
  361. update_rel_pos = 1
  362. if update_rel_pos:
  363. rel = [0,0]
  364. rel[0] = self.event_pos[0] -self.pos[0]-4
  365. rel[0] = rel[0]/(self.pos[2]-8)
  366. rel[1] = self.event_pos[1] -self.pos[1]-4
  367. rel[1] = rel[1]/(self.pos[3]-8)
  368. if rel[0] < 0:
  369. rel[0] = 0
  370. if rel[0] > 1:
  371. rel[0] = 1
  372. if rel[1] < 0:
  373. rel[1] = 0
  374. if rel[1] > 1:
  375. rel[1] = 1
  376. #print("RELPOS",rel)
  377. self.rel_pos = rel
  378. self._check_event()
  379. self._set_mouse_focus(0)
  380. if check_area(self.pos,self.event_pos):
  381. self._set_mouse_focus(1)
  382. if "button" in event.dict:
  383. mode = ""
  384. if event.type in [5,pygame.MOUSEBUTTONDOWN]:
  385. mode = "press"
  386. if event.type in [6,pygame.MOUSEBUTTONUP]:
  387. mode = "release"
  388. e = [event.button,mode]
  389. #print("e",e)
  390. #print()
  391. for btn in self.btns:
  392. if e[0] in btn.nr_on and e[1] == "press":
  393. btn.press()
  394. if e[0] in btn.nr_off and e[1] == "release":
  395. btn.release()
  396. re = btn.get_event()
  397. if re and btn.name not in ['MOUSE FOCUS']:
  398. #print("----------------",btn.name,re)
  399. r_event[btn.name] = re
  400. return r_event
  401. def draw_mouse_box(window,pos1,pos2,color=[128,128,128],text=1):
  402. color = [200,0,0,127]
  403. if text:
  404. fr = font15.render("A" ,1, (200,200,200))
  405. window.blit(fr,pos1)
  406. fr = font15.render("B" ,1, (200,200,200))
  407. window.blit(fr,[pos2[0]-10,pos2[1]-10])
  408. # h unten
  409. _pos1 = [pos1[0],pos2[1]]
  410. _pos2 = [pos2[0],pos2[1]]
  411. pygame.draw.aaline(window,color,_pos1,_pos2,1)
  412. color = [255,255,0,127]
  413. # h rechts
  414. _pos1 = [pos2[0],pos1[1]]
  415. _pos2 = [pos2[0],pos2[1]]
  416. pygame.draw.aaline(window,color,_pos1,_pos2,1)
  417. color = [0,200,0,127]
  418. # h links
  419. _pos1 = [pos1[0],pos1[1]]
  420. _pos2 = [pos1[0],pos2[1]]
  421. pygame.draw.aaline(window,color,_pos1,_pos2,1)
  422. color = [0,0,200,127]
  423. # h oben
  424. _pos1 = [pos1[0],pos1[1]]
  425. _pos2 = [pos2[0],pos1[1]]
  426. pygame.draw.aaline(window,color,_pos1,_pos2,1)