Guest User

Untitled

a guest
Apr 11th, 2012
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.06 KB | None | 0 0
  1. #-------->
  2. # BLB Editor
  3. # by Zack "Zack0Wack0" Corr
  4. # Updated: 04/02/11
  5. #--------
  6. import sys,os,wx
  7. from time import strftime
  8. import wx.stc
  9. from wx import glcanvas
  10. from OpenGL.GL import *
  11. from OpenGL.GLU import gluBuild2DMipmaps
  12. from PIL import Image
  13.  
  14. name = "BLB Editor"
  15. version = 0.25
  16. title = name + " v" + str(version)
  17. description = "BLB Editor is an application for editing Blockland brick files (.blb). \nIt includes a 3D canvas for rendering your current brick model,\n a styled text editor and a range of other features."
  18. author = "Zack0Wack0"
  19. website = "http://www.zack0wack0.com"
  20. #-------->
  21. # Cross OS Compatibility
  22. #--------
  23. if wx.Platform == '__WXMSW__':
  24. runningOS = "WINDOWS"
  25. faces = { 'times': 'Times New Roman',
  26. 'mono' : 'Courier New',
  27. 'helv' : 'Arial',
  28. 'other': 'Comic Sans MS',
  29. 'size' : 10,
  30. 'size2': 8,
  31. }
  32. elif wx.Platform == '__WXMAC__':
  33. runningOS = "MAC"
  34. faces = { 'times': 'Times New Roman',
  35. 'mono' : 'Monaco',
  36. 'helv' : 'Arial',
  37. 'other': 'Comic Sans MS',
  38. 'size' : 12,
  39. 'size2': 10,
  40. }
  41. else:
  42. runningOS = "OTHER" #it's probably linux or something
  43. faces = { 'times': 'Times',
  44. 'mono' : 'Courier',
  45. 'helv' : 'Helvetica',
  46. 'other': 'new century schoolbook',
  47. 'size' : 12,
  48. 'size2': 10,
  49. }
  50. #-------->
  51. # BLB Handling
  52. #--------
  53. class Handler:
  54. """Handles all the BLB parsing and writing.""" #lol I never got around to it
  55. def __init__(self):
  56. pass
  57. #-------->
  58. # GUI
  59. #--------
  60. id_file_new = 0
  61. id_file_open = 1
  62. id_file_import = 2
  63. id_file_save = 3
  64. id_file_saveas = 4
  65. id_file_exit = 10
  66. id_view_zoomin = 5
  67. id_view_zoomout = 6
  68. id_view_refresh = 7
  69. id_view_axii = 8
  70. id_view_grid = 9
  71. id_help_about = 11
  72. class Application(wx.App):
  73. """Controls everything."""
  74. def __init__(self,title,version):
  75. self.saved = False
  76. self.text = ""
  77. self.file = ""
  78. self.directory = ""
  79. self.title = title
  80. self.handler = Handler()
  81. wipe = open("log.txt","w")
  82. wipe.write(strftime("%d/%m/%Y %H:%M:%S") + "\n")
  83. wipe.close()
  84. wx.App.__init__(self,redirect=True,filename="log.txt")
  85. def OnInit(self):
  86. print self.title + " by Zack \"Zack0Wack0\" Corr"
  87.  
  88. self.frame = wx.Frame(None,-1,self.title,pos=(50,50),size=(640,480),style=wx.DEFAULT_FRAME_STYLE)
  89. try:
  90. self.icon = wx.Icon("icon.ico",wx.BITMAP_TYPE_ICO)
  91. self.frame.SetIcon(self.icon)
  92. except:
  93. pass
  94. self.frame.app = self
  95. self.statusbar = self.frame.CreateStatusBar()
  96. self.menubar = wx.MenuBar()
  97.  
  98. self.fileMenu = wx.Menu()
  99. self.fileMenuNew = self.fileMenu.Append(id_file_new,"&New\tCtrl+N")
  100. self.Bind(wx.EVT_MENU,self.onNew,id=id_file_new)
  101. self.fileMenuOpen = self.fileMenu.Append(id_file_open,"&Open...\tCtrl+O")
  102. self.Bind(wx.EVT_MENU,self.onOpen,id=id_file_open)
  103. self.fileMenuImport = self.fileMenu.Append(id_file_import,"&Import...\tCtrl+I")
  104. self.Bind(wx.EVT_MENU,self.onImport,id=id_file_import)
  105. self.fileMenuSave = self.fileMenu.Append(id_file_save,"&Save\tCtrl+S")
  106. self.Bind(wx.EVT_MENU,self.onQuickSave,id=id_file_save)
  107. self.fileMenuSaveAs = self.fileMenu.Append(id_file_saveas,"Save &As...")
  108. self.Bind(wx.EVT_MENU,self.onSave,id=id_file_saveas)
  109. self.fileMenu.AppendSeparator()
  110. self.fileMenuExit = self.fileMenu.Append(id_file_exit,"Exit")
  111. self.Bind(wx.EVT_MENU,self.onExit,id=id_file_exit)
  112.  
  113. self.viewMenu = wx.Menu()
  114. self.viewMenuZoomIn = self.viewMenu.Append(id_view_zoomin,"Zoom &In\tCtrl+=")
  115. self.Bind(wx.EVT_MENU,self.onZoomIn,id=id_view_zoomin)
  116. self.viewMenuZoomOut = self.viewMenu.Append(id_view_zoomout,"Zoom &Out\tCtrl+-")
  117. self.Bind(wx.EVT_MENU,self.onZoomOut,id=id_view_zoomout)
  118. self.viewMenuRefresh = self.viewMenu.Append(id_view_refresh,"&Refresh\tCtrl+R")
  119. self.Bind(wx.EVT_MENU,self.onRefresh,id=id_view_refresh)
  120. self.viewMenuAxii = self.viewMenu.Append(id_view_axii,"&Toggle Axii\tCtrl+M")
  121. self.Bind(wx.EVT_MENU,self.onToggleAxii,id=id_view_axii)
  122. self.viewMenuGrid = self.viewMenu.Append(id_view_grid,"&Toggle Grid\tCtrl+G")
  123. self.Bind(wx.EVT_MENU,self.onToggleGrid,id=id_view_grid)
  124.  
  125. self.helpMenu = wx.Menu()
  126. self.helpMenuAbout = self.helpMenu.Append(id_help_about,"&About")
  127. self.Bind(wx.EVT_MENU,self.onAbout,id=id_help_about)
  128.  
  129. self.menubar.Append(self.fileMenu,"File")
  130. self.menubar.Append(self.viewMenu,"View")
  131. self.menubar.Append(self.helpMenu,"Help")
  132. self.frame.SetMenuBar(self.menubar)
  133.  
  134. self.frame.Bind(wx.EVT_CLOSE,self.onExit)
  135. self.frame.Show(True)
  136. self.frame.SetSize((640, 480))
  137. self.frame.Centre()
  138. self.panel = MainPanel(self.frame,app=self)
  139. self.SetTopWindow(self.frame)
  140. self.newFile(True)
  141.  
  142. print "Successfully started up."
  143. return True
  144. def openFile(self):
  145. doOpen = True
  146. if self.file != "" and self.saved != True:
  147. doOpen = False
  148. dialog = wx.MessageDialog(self.frame,"You haven't saved your current file. Do you want to save it before opening a new file?","Opening a file",wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION)
  149. result = dialog.ShowModal()
  150. dialog.Destroy()
  151. if result == wx.ID_YES:
  152. self.saveFile()
  153. doOpen = True
  154. elif result == wx.ID_NO:
  155. doOpen = True
  156. if not doOpen:
  157. return
  158. dialog = wx.FileDialog(self.frame,"Open",self.directory,self.file,"Blockland Brick Files (*.blb)|*.blb",wx.OPEN)
  159. if dialog.ShowModal() == wx.ID_OK:
  160. self.file = dialog.GetFilename()
  161. self.directory = dialog.GetDirectory()
  162. try:
  163. reader = open(os.path.join(self.directory,self.file),"r")
  164. text = ""
  165. for line in reader:
  166. text = text + line
  167. self.panel.text.SetText(text)
  168. reader.close()
  169. self.frame.SetStatusText("Opened " + self.file + " at " + strftime("%H:%M:%S") + ".")
  170. self.saved = True
  171. self.frame.SetTitle(self.title + " - " + self.file)
  172. self.refresh(True)
  173. except:
  174. self.frame.SetStatusText("Failed to open.")
  175. dialog.Destroy()
  176. def importFile(self):
  177. pass
  178. def newFile(self,forced=False):
  179. doNewFile = True
  180. if not self.saved and not forced:
  181. doNewFile = False
  182. dialog = wx.MessageDialog(self.frame,"You haven't saved your current file. Do you want to save it now?","New file",wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION)
  183. result = dialog.ShowModal()
  184. dialog.Destroy()
  185. if result == wx.ID_YES:
  186. self.saveFile()
  187. doNewFile = True
  188. elif result == wx.ID_NO:
  189. doNewFile = True
  190. if doNewFile:
  191. self.file = ""
  192. self.directory = ""
  193. self.text = ""
  194. self.saved = True
  195. self.panel.text.SetText("")
  196. self.frame.SetTitle(self.title)
  197. def saveFileAs(self):
  198. dialog = wx.FileDialog(self.frame,"Save As",self.directory,self.file,"Blockland Brick Files (*.blb)|*.blb",wx.SAVE | wx.OVERWRITE_PROMPT)
  199. if dialog.ShowModal() == wx.ID_OK:
  200. self.file = dialog.GetFilename()
  201. self.directory = dialog.GetDirectory()
  202. dialog.Destroy()
  203. self.saveFile()
  204. return
  205. dialog.Destroy()
  206. def saveFile(self):
  207. if self.saved:
  208. return
  209. if self.file != "":
  210. try:
  211. writer = open(os.path.join(self.directory,self.file),"w")
  212. writer.write(self.panel.text.GetText())
  213. writer.close()
  214. self.frame.SetStatusText("Saved " + self.file + " at " + strftime("%H:%M:%S") + ".")
  215. self.saved = True
  216. self.frame.SetTitle(self.title + " - " + self.file)
  217. except:
  218. self.frame.SetStatusText("Failed to save.")
  219. else:
  220. self.saveFileAs()
  221. def exit(self):
  222. self.frame.Destroy()
  223. def about(self):
  224. info = wx.AboutDialogInfo()
  225. try:
  226. info.SetIcon(self.icon)
  227. except:
  228. pass
  229. info.SetName(name)
  230. info.SetVersion(str(version))
  231. info.SetDescription(description)
  232. info.SetWebSite(website)
  233. info.AddDeveloper(author)
  234. wx.AboutBox(info)
  235. def refresh(self,reset=False):
  236. lines = self.panel.text.GetText()
  237. if lines == "":
  238. return
  239. lines = lines.split("\n")
  240. try:
  241. size = lines[0]
  242. size = size.strip().split()
  243. modelSize = [int(size[0]),int(size[1]),int(size[2])]
  244. type = lines[1]
  245. if type == "BRICK":
  246. #doesn't support normal bricks "yet"
  247. return
  248. lines = lines[2:]
  249. except:
  250. return
  251. linecount = -1
  252. polygons = []
  253. for line in lines:
  254. linecount = linecount + 1
  255. if len(line) >= 4:
  256. if line[0:4] == "TEX:" and len(lines)-linecount >= 15:
  257. successes = 0
  258. texture = line[4:]
  259. colour = []
  260. if lines[linecount+1][0:9].strip() == "POSITION:":
  261. pos1 = lines[linecount+2].strip().split()
  262. pos2 = lines[linecount+3].strip().split()
  263. pos3 = lines[linecount+4].strip().split()
  264. pos4 = lines[linecount+5].strip().split()
  265. try:
  266. pos1X = float(pos1[0])
  267. pos1Y = float(pos1[1])
  268. pos1Z = float(pos1[2])
  269. pos1 = [pos1X,pos1Y,pos1Z]
  270. pos2X = float(pos2[0])
  271. pos2Y = float(pos2[1])
  272. pos2Z = float(pos2[2])
  273. pos2 = [pos2X,pos2Y,pos2Z]
  274. pos3X = float(pos3[0])
  275. pos3Y = float(pos3[1])
  276. pos3Z = float(pos3[2])
  277. pos3 = [pos3X,pos3Y,pos3Z]
  278. pos4X = float(pos4[0])
  279. pos4Y = float(pos4[1])
  280. pos4Z = float(pos4[2])
  281. pos4 = [pos4X,pos4Y,pos4Z]
  282. successes = successes + 1
  283. except:
  284. continue
  285. if lines[linecount+6][0:10].strip() == "UV COORDS:":
  286. uv1 = lines[linecount+7].strip().split()
  287. uv2 = lines[linecount+8].strip().split()
  288. uv3 = lines[linecount+9].strip().split()
  289. uv4 = lines[linecount+10].strip().split()
  290. try:
  291. uv1X = float(uv1[0])
  292. uv1Y = float(uv1[1])
  293. uv1 = [uv1X,uv1Y]
  294. uv2X = float(uv2[0])
  295. uv2Y = float(uv2[1])
  296. uv2 = [uv2X,uv2Y]
  297. uv3X = float(uv3[0])
  298. uv3Y = float(uv3[1])
  299. uv3 = [uv3X,uv3Y]
  300. uv4X = float(uv4[0])
  301. uv4Y = float(uv4[1])
  302. uv4 = [uv4X,uv4Y]
  303. successes = successes + 1
  304. except:
  305. continue
  306. if lines[linecount+11][0:7].strip() == "COLORS:" and len(lines)-linecount >= 20:
  307. colour1 = lines[linecount+12].strip().split()
  308. colour2 = lines[linecount+13].strip().split()
  309. colour3 = lines[linecount+14].strip().split()
  310. colour4 = lines[linecount+15].strip().split()
  311. try:
  312. colour1R = float(colour1[0])
  313. colour1G = float(colour1[1])
  314. colour1B = float(colour1[2])
  315. colour1A = float(colour1[3])
  316. colour1 = [colour1R,colour1G,colour1B,colour1A]
  317. colour2R = float(colour2[0])
  318. colour2G = float(colour2[1])
  319. colour2B = float(colour2[2])
  320. colour2A = float(colour2[3])
  321. colour2 = [colour2R,colour2G,colour2B,colour2A]
  322. colour3R = float(colour3[0])
  323. colour3G = float(colour3[1])
  324. colour3B = float(colour3[2])
  325. colour3A = float(colour3[3])
  326. colour3 = [colour3R,colour3G,colour3B,colour3A]
  327. colour4R = float(colour4[0])
  328. colour4G = float(colour4[1])
  329. colour4B = float(colour4[2])
  330. colour4A = float(colour4[3])
  331. colour4 = [colour4R,colour4G,colour4B,colour4A]
  332. colour = [colour1,colour2,colour3,colour4]
  333. successes = successes + 1
  334. except:
  335. continue
  336. if lines[linecount+16][0:8].strip() == "NORMALS:":
  337. normal1 = lines[linecount+17].strip().split()
  338. normal2 = lines[linecount+18].strip().split()
  339. normal3 = lines[linecount+19].strip().split()
  340. normal4 = lines[linecount+20].strip().split()
  341. try:
  342. normal1X = float(normal1[0])
  343. normal1Y = float(normal1[1])
  344. normal1Z = float(normal1[2])
  345. normal1 = [normal1X,normal1Y,normal1Z]
  346. normal2X = float(normal2[0])
  347. normal2Y = float(normal2[1])
  348. normal2Z = float(normal2[2])
  349. normal2 = [normal2X,normal2Y,normal2Z]
  350. normal3X = float(normal3[0])
  351. normal3Y = float(normal3[1])
  352. normal3Z = float(normal3[2])
  353. normal3 = [normal3X,normal3Y,normal3Z]
  354. normal4X = float(normal4[0])
  355. normal4Y = float(normal4[1])
  356. normal4Z = float(normal4[2])
  357. normal4 = [normal4X,normal4Y,normal4Z]
  358. successes = successes + 1
  359. except:
  360. continue
  361. if lines[linecount+11][0:8].strip() == "NORMALS:":
  362. normal1 = lines[linecount+12].strip().split()
  363. normal2 = lines[linecount+13].strip().split()
  364. normal3 = lines[linecount+14].strip().split()
  365. normal4 = lines[linecount+15].strip().split()
  366. try:
  367. normal1X = float(normal1[0])
  368. normal1Y = float(normal1[1])
  369. normal1Z = float(normal1[2])
  370. normal1 = [normal1X,normal1Y,normal1Z]
  371. normal2X = float(normal2[0])
  372. normal2Y = float(normal2[1])
  373. normal2Z = float(normal2[2])
  374. normal2 = [normal2X,normal2Y,normal2Z]
  375. normal3X = float(normal3[0])
  376. normal3Y = float(normal3[1])
  377. normal3Z = float(normal3[2])
  378. normal3 = [normal3X,normal3Y,normal3Z]
  379. normal4X = float(normal4[0])
  380. normal4Y = float(normal4[1])
  381. normal4Z = float(normal4[2])
  382. normal4 = [normal4X,normal4Y,normal4Z]
  383. successes = successes + 1
  384. except:
  385. continue
  386. if successes > 2:
  387. poly = [texture,[pos1,pos2,pos3,pos4],[normal1,normal2,normal3,normal4],[uv1,uv2,uv3,uv4],colour]
  388. polygons.append(poly)
  389. self.panel.canvas.updateModel(polygons,modelSize,reset)
  390. self.panel.canvas.Refresh(False)
  391. if len(polygons) > 0:
  392. self.frame.SetStatusText("Refreshed " + str(len(polygons)) + " polygons at " + strftime("%H:%M:%S") + ".")
  393. def zoomIn(self):
  394. self.panel.canvas.zoomIn()
  395. self.panel.canvas.Refresh(False)
  396. def zoomOut(self):
  397. self.panel.canvas.zoomOut()
  398. self.panel.canvas.Refresh(False)
  399. def toggleGrid(self):
  400. self.panel.canvas.toggleGrid()
  401. self.panel.canvas.Refresh(False)
  402. def toggleAxii(self):
  403. self.panel.canvas.toggleAxii()
  404. self.panel.canvas.Refresh(False)
  405. def onNew(self,event):
  406. self.newFile()
  407. def onOpen(self,event):
  408. self.openFile()
  409. def onImport(self,event):
  410. self.importFile()
  411. def onSave(self,event):
  412. self.saveFileAs()
  413. def onQuickSave(self,event):
  414. self.saveFile()
  415. def onZoomIn(self,event):
  416. self.zoomIn()
  417. def onZoomOut(self,event):
  418. self.zoomOut()
  419. def onToggleGrid(self,event):
  420. self.toggleGrid()
  421. def onToggleAxii(self,event):
  422. self.toggleAxii()
  423. def onRefresh(self,event):
  424. self.refresh()
  425. def onAbout(self,event):
  426. self.about()
  427. def onExit(self,event):
  428. if not self.saved:
  429. close = False
  430. dialog = wx.MessageDialog(self.frame,"You haven't saved your current file. Do you want to save it now?","Exiting program",wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION)
  431. result = dialog.ShowModal()
  432. dialog.Destroy()
  433. if result == wx.ID_YES:
  434. self.saveFile()
  435. close = True
  436. elif result == wx.ID_NO:
  437. close = True
  438. if close:
  439. self.exit()
  440. else:
  441. self.exit()
  442. class MainPanel(wx.Panel):
  443. """The main GUI."""
  444. def __init__(self,parent,app=None):
  445. wx.Panel.__init__(self,parent,-1)
  446. self.parent = parent
  447.  
  448. self.box = wx.BoxSizer(wx.HORIZONTAL)
  449.  
  450. self.canvas = CanvasPanel(self)
  451. self.canvas.SetSize((400,400))
  452. self.box.Add(self.canvas,6,wx.EXPAND)
  453.  
  454. self.text = TextPanel(self)
  455. self.box.Add(self.text,4,wx.EXPAND)
  456. self.text.EmptyUndoBuffer()
  457. self.text.Colourise(0,-1)
  458. self.text.SetMarginType(1,wx.stc.STC_MARGIN_NUMBER)
  459. self.text.SetMarginWidth(1,25)
  460.  
  461. self.SetAutoLayout(True)
  462. self.SetSizer(self.box)
  463. class TextPanel(wx.stc.StyledTextCtrl):
  464. def __init__(self,parent,id=-1,pos=wx.DefaultPosition,size=wx.DefaultSize,style=0):
  465. self.keywords = "TEX POSITION UV COORDS NORMALS COVERAGE SPECIAL BRICK"
  466. wx.stc.StyledTextCtrl.__init__(self,parent,id,pos,size,style)
  467. self.parent = parent
  468. self.SetKeyWords(0,self.keywords)
  469.  
  470. self.SetProperty("fold","1")
  471. self.SetProperty("tab.timmy.whinge.level","1")
  472. self.SetMargins(0,0)
  473.  
  474. self.SetViewWhiteSpace(False)
  475.  
  476. self.SetMarginWidth(2,8)
  477.  
  478. self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT,"face:%(helv)s,size:%(size)d" % faces)
  479. self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,"back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
  480. self.StyleSetSpec(wx.stc.STC_STYLE_CONTROLCHAR,"face:%(other)s" % faces)
  481. self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,"fore:#FFFFFF,back:#0000FF,bold")
  482. self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,"fore:#000000,back:#FF0000,bold")
  483.  
  484. self.StyleSetSpec(1,"fore:#00AAFF,face:%(helv)s,size:%(size)d" % faces)
  485.  
  486. self.SetLexer(wx.stc.STC_LEX_CONTAINER)
  487. self.Bind(wx.EVT_KEY_DOWN,self.onKeyPressed)
  488. self.Bind(wx.stc.EVT_STC_STYLENEEDED,self.onStyleNeeded)
  489. def onKeyPressed(self,event):
  490. event.Skip()
  491. newText = self.GetText()
  492. if self.parent.parent.app.text != newText:
  493. if self.parent.parent.app.saved:
  494. if self.parent.parent.app.file != "":
  495. self.parent.parent.SetTitle(self.parent.parent.app.title + " - *" + self.parent.parent.app.file)
  496. self.parent.parent.app.saved = False
  497. self.parent.parent.app.text = newText
  498. def onStyleNeeded(self,event):
  499. end = event.GetPosition()
  500. start = self.GetEndStyled()
  501. self.StartStyling(start,0x1f)
  502. for i in range(start,end + 1):
  503. c = self.GetCharAt(i)
  504. if 48 <= c <= 57:
  505. self.SetStyling(1,1)
  506. else:
  507. self.SetStyling(1,0)
  508. class CanvasPanel(glcanvas.GLCanvas):
  509. """The 3D canvas."""
  510. def __init__(self,parent):
  511. glcanvas.GLCanvas.__init__(self,parent,-1)
  512. self.polygons = []
  513. self.parent = parent
  514. self.init = False
  515. self.lastx = self.x = 0
  516. self.lasty = self.y = 0
  517. self.size = None
  518. self.scale = 0.1
  519. self.noRotateFix = False
  520. self.axii = True
  521. self.grid = False
  522. self.gridList = None
  523. self.maxScale = 0.1
  524. self.minScale = 0.05
  525. self.Bind(wx.EVT_ERASE_BACKGROUND,self.onEraseBackground)
  526. self.Bind(wx.EVT_SIZE,self.onSize)
  527. self.Bind(wx.EVT_PAINT,self.onPaint)
  528. self.Bind(wx.EVT_LEFT_DOWN,self.onMouseDown)
  529. self.Bind(wx.EVT_LEFT_UP,self.onMouseUp)
  530. self.Bind(wx.EVT_MOTION,self.onMouseMotion)
  531. self.Bind(wx.EVT_KEY_DOWN,self.onKeyPressed)
  532. def updateModel(self,polygons,modelSize,reset=False):
  533. self.polygons = polygons
  534. self.modelSize = modelSize
  535. volume = self.modelSize[0] * self.modelSize[1]
  536. self.maxScale = (pow(volume,2.1) / pow(volume,2.5)) * 0.75
  537. self.minScale = 0.01
  538. if reset:
  539. glScale(self.maxScale,self.maxScale,self.maxScale)
  540. self.scale = self.maxScale
  541. def loadImage(self,imageFile,sWrap=GL_REPEAT,tWrap=GL_REPEAT,rWrap=GL_REPEAT):
  542. im = Image.open(imageFile)
  543. width = im.size[0]
  544. height = im.size[1]
  545. image = im.tostring("raw","RGBX",0,-1)
  546. id = glGenTextures(1)
  547. glPixelStorei(GL_UNPACK_ALIGNMENT,1)
  548. glBindTexture(GL_TEXTURE_2D,id)
  549. glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,image)
  550. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,sWrap)
  551. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,tWrap)
  552. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_R,rWrap)
  553. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
  554. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
  555. glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE)
  556. return id
  557. def zoomIn(self):
  558. glScale(1.03,1.03,1.03)
  559. self.noRotateFix = True
  560. def zoomOut(self):
  561. glScale(0.97,0.97,0.97)
  562. self.noRotateFix = True
  563. def toggleAxii(self):
  564. if self.axii:
  565. self.axii = False
  566. else:
  567. self.axii = True
  568. def toggleGrid(self):
  569. if self.grid:
  570. self.grid = False
  571. else:
  572. self.grid = True
  573. def onEraseBackground(self,event):
  574. pass
  575. def onSize(self,event):
  576. size = self.size = self.GetClientSize()
  577. if self.GetContext():
  578. self.SetCurrent()
  579. glViewport(0,0,size.width,size.height)
  580. event.Skip()
  581. def onPaint(self,event):
  582. dc = wx.PaintDC(self)
  583. self.SetCurrent()
  584. if not self.init:
  585. self.initCanvas()
  586. self.init = True
  587. self.onDraw()
  588. def onMouseDown(self,event):
  589. self.CaptureMouse()
  590. self.x, self.y = self.lastx, self.lasty = event.GetPosition()
  591. def onMouseUp(self,event):
  592. if self and self.HasCapture():
  593. self.ReleaseMouse()
  594. def onMouseMotion(self,event):
  595. if event.Dragging() and event.LeftIsDown():
  596. self.lastx, self.lasty = self.x, self.y
  597. self.x, self.y = event.GetPosition()
  598. self.Refresh(False)
  599. if event.MiddleIsDown():
  600. wheelRot = event.GetWheelRotation()
  601. if wheelrot != 0:
  602. if wheelrot > 0:
  603. self.zoomIn()
  604. else:
  605. self.zoomOut()
  606. self.Refresh(False)
  607. def onKeyPressed(self,event):
  608. if event.GetKeyCode() == wx.WXK_UP:
  609. if self.zoom >= 6:
  610. return
  611. self.zoom = self.zoom + 1
  612. if event.GetKeyCode() == wx.WXK_DOWN:
  613. if self.zoom <= 0:
  614. return
  615. self.zoom = self.zoom - 1
  616. event.Skip()
  617. def initCanvas(self):
  618. try:
  619. self.texture = {
  620. "TOP": self.loadImage("brickTOP.bmp"),
  621. "SIDE": self.loadImage("brickSIDE.bmp"),
  622. "RAMP": self.loadImage("brickRAMP.bmp"),
  623. "BOTTOMEDGE": self.loadImage("brickBOTTOMEDGE.bmp",GL_CLAMP,GL_CLAMP),
  624. "BOTTOMLOOP": self.loadImage("brickBOTTOMLOOP.bmp"),
  625. "PRINT": self.loadImage("brickPRINT.bmp")
  626. }
  627. self.usesTextures = True
  628. print "Textures loaded successfully."
  629. except Exception as exception:
  630. self.usesTextures = False
  631. print "Textures failed to load. (" + str(exception) + ")"
  632. glEnable(GL_LIGHTING)
  633. glEnable(GL_LIGHT0)
  634.  
  635. glMatrixMode(GL_PROJECTION)
  636. glFrustum(-0.5,0.5,-0.5,0.5,1,3)
  637.  
  638. glMatrixMode(GL_MODELVIEW)
  639. glTranslatef(0,0,-2)
  640.  
  641. glRotatef(self.y,1.0,0.0,0.0)
  642. glRotatef(self.x,0.0,1.0,0.0)
  643.  
  644. glEnable(GL_DEPTH_TEST)
  645. def onDraw(self):
  646. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
  647. glDisable(GL_LIGHTING)
  648. useColour = False
  649. glEnable(GL_COLOR_MATERIAL)
  650. faceID = -1
  651. for poly in self.polygons:
  652. faceID += 1
  653. texture = poly[0]
  654. pos1 = poly[1][0]
  655. pos2 = poly[1][1]
  656. pos3 = poly[1][2]
  657. pos4 = poly[1][3]
  658. normal1 = poly[2][0]
  659. normal2 = poly[2][1]
  660. normal3 = poly[2][2]
  661. normal4 = poly[2][3]
  662. uv1 = poly[3][0]
  663. uv2 = poly[3][1]
  664. uv3 = poly[3][2]
  665. uv4 = poly[3][3]
  666. colour = poly[4]
  667. useColour = False
  668. if len(colour) > 0:
  669. colour1 = colour[0]
  670. colour2 = colour[1]
  671. colour3 = colour[2]
  672. colour4 = colour[3]
  673. #due to openGL lamos you can't enable and disable blend during drawing, so sucks for you if you need each vertex a different transparency
  674. if colour1[3] < 1.0:
  675. glEnable(GL_BLEND)
  676. glBlendFunc(GL_ONE_MINUS_SRC_ALPHA,GL_ONE_MINUS_DST_ALPHA)
  677. useColour = True
  678. else:
  679. glColor4f(1,1,1,1)
  680. glEnable(GL_TEXTURE_2D)
  681. if self.usesTextures and not useColour:
  682. glBindTexture(GL_TEXTURE_2D,self.texture[texture])
  683. glBegin(GL_QUADS)
  684. if useColour:
  685. glColor4f(colour1[0],colour1[1],colour1[2],colour1[3])
  686. else:
  687. glTexCoord2f(uv1[0],uv1[1])
  688. glNormal3f(normal1[0],normal1[1],normal1[2])
  689. glVertex3f(pos1[0],pos1[1],(pos1[2]) / 3)
  690. if useColour:
  691. glColor4f(colour2[0],colour2[1],colour2[2],colour2[3])
  692. else:
  693. glTexCoord2f(uv2[0],uv2[1])
  694. glNormal3f(normal2[0],normal2[1],normal2[2])
  695. glVertex3f(pos2[0],pos2[1],(pos2[2]) / 3)
  696. if useColour:
  697. glColor4f(colour3[0],colour3[1],colour3[2],colour3[3])
  698. else:
  699. glTexCoord2f(uv3[0],uv3[1])
  700. glNormal3f(normal3[0],normal3[1],normal3[2])
  701. glVertex3f(pos3[0],pos3[1],(pos3[2]) / 3)
  702. if useColour:
  703. glColor4f(colour4[0],colour4[1],colour4[2],colour4[3])
  704. else:
  705. glTexCoord2f(uv4[0],uv4[1])
  706. glNormal3f(normal4[0],normal4[1],normal4[2])
  707. glVertex3f(pos4[0],pos4[1],(pos4[2]) / 3)
  708. glEnd()
  709. glFlush()
  710. if not useColour:
  711. glDisable(GL_TEXTURE_2D)
  712. else:
  713. glDisable(GL_BLEND)
  714. glDisable(GL_COLOR_MATERIAL)
  715. if self.axii:
  716. glLineWidth(2)
  717. glDisable(GL_LIGHTING)
  718. glBegin(GL_LINES)
  719. glColor4f(1,0,0,1)
  720. glVertex3f(0,0,0)
  721. glVertex3f(10000,0,0)
  722. glColor4f(0,1,0,1)
  723. glVertex3f(0,0,0)
  724. glVertex3f(0,10000,0)
  725. glColor4f(0,0,1,1)
  726. glVertex3f(0,0,0)
  727. glVertex3f(0,0,10000)
  728. glEnd()
  729. glEnable(GL_LIGHTING)
  730. if self.grid:
  731. if self.gridList == None:
  732. self.parent.parent.SetStatusText("Compiling the grid. This could take a while.")
  733. self.gridList = glGenLists(1)
  734. glNewList(self.gridList,GL_COMPILE)
  735. glLineWidth(1)
  736. glBegin(GL_LINES)
  737. for x in range(64):
  738. for y in range(64):
  739. x = float(x)
  740. y = float(y)
  741. glColor4f(0.5,0.5,0.5,1)
  742. a = (x - 32) - 0.5
  743. b = (y - 32) - 0.5
  744. c = x - 0.5
  745. d = y - 0.5
  746. glVertex3f(a,b,0)
  747. glVertex3f(a,d,0)
  748. glVertex3f(a,b,0)
  749. glVertex3f(c,b,0)
  750. glEnd()
  751. glEndList()
  752. glDisable(GL_LIGHTING)
  753. glCallList(self.gridList)
  754. glEnable(GL_LIGHTING)
  755. self.parent.parent.SetStatusText("Finished compiling the grid.")
  756. else:
  757. glDisable(GL_LIGHTING)
  758. glCallList(self.gridList)
  759. glEnable(GL_LIGHTING)
  760. if self.size is None:
  761. self.size = self.GetClientSize()
  762. w, h = self.size
  763. w = max(w,1.0)
  764. h = max(h,1.0)
  765. xScale = 180.0 / w
  766. yScale = 180.0 / h
  767. if not self.noRotateFix:
  768. glRotate((self.y - self.lasty) * yScale,1,0,0)
  769. glRotate((self.x - self.lastx) * xScale,0,1,0)
  770. else:
  771. self.noRotateFix = False
  772. self.SwapBuffers()
  773. #-------->
  774. # Run
  775. #--------
  776. BLBEditor = Application(title,version)
  777. BLBEditor.MainLoop()
Advertisement
Add Comment
Please, Sign In to add comment