import os
import time
import math
import d3d11
import d3d11x
from d3d11c import *
try:
import wx
import wx.lib.anchors as anchors
except:
d3d11.messageBox(None, "wxPython is not available.\n\nThis sample will not work without it.", "wxPython sample", MB_OK)
raise
#Most code is from 'Tutorial2.py', refer to it for more explanation.
#Vertex layout description.
vertexDesc = [
("POSITION", 0, FORMAT_R32G32B32_FLOAT),
("COLOR", 0, FORMAT_R32G32B32A32_FLOAT),
]
triangle = [
(-5, 0, 0) + (1, 0, 0, 1), #Red vertex.
(0, 10, 0) + (0, 1, 0, 1), #Green vertex.
(5, 0, 0) + (0, 0, 1, 1), #Blue vertex.
]
class MainFrame(wx.Frame):
def __init__(self, parent, id, title, pos, size=(800, 600)):
wx.Frame.__init__(self, parent, id, title, pos, size)
self.mainpanel = wx.Panel(self, -1, size=(800, 600))
self.mainpanel.SetAutoLayout(True)
self.leftwindow = wx.Panel(self.mainpanel, -1, (10, 10), (380, 450))
self.leftwindow.SetBackgroundColour(wx.WHITE)
self.leftwindow.SetConstraints(anchors.LayoutAnchors(self.leftwindow, True, True, True, True))
self.rightwindow = wx.Panel(self.mainpanel, -1, (400, 10), (380, 450))
self.rightwindow.SetBackgroundColour(wx.WHITE)
self.rightwindow.SetConstraints(anchors.LayoutAnchors(self.rightwindow, False, True, True, True))
playvideo = wx.Button(self.mainpanel, -1, "Play media on this window...", (500, 500))
playvideo.SetConstraints(anchors.LayoutAnchors(playvideo, False, False, True, True))
self.Bind(wx.EVT_BUTTON, self.playVideo, playvideo)
#Create a DirectPython window from an existing wxPython window.
tempWindow = d3d11.Window(handle=self.leftwindow.GetHandle())
#Create our resources. Note that if the size of the window
#changes, you should call self.device.reset().
self.device = d3d11.Device(tempWindow, DRIVER_TYPE_WARP)
self.effect = d3d11.Effect(d3d11x.getResourceDir("Effects", "Tutorial2.fx"))
self.inputLayout = d3d11.InputLayout(vertexDesc, self.effect, 0, 0)
self.vertexBuffer = d3d11.Buffer(vertexDesc, triangle, BIND_VERTEX_BUFFER)
#We need to detach() the window. This means that it is up to
#us (or wxPython) to mange the window from now on.
tempWindow.detach()
self.media = None
self.Bind(wx.EVT_PAINT, self.onPaint)
self.Bind(wx.EVT_TIMER, self.onTimer)
self.Bind(wx.EVT_IDLE, self.onIdle)
self.leftwindow.Bind(wx.EVT_SIZE, self.onSize)
#Use a timer for rendering. It is not a very smooth
#solution, you might want to tweak the time interval
#or do something else, now it is jerky.
self.timer = wx.Timer(self)
self.timer.Start(10)
def renderAndPresent(self):
self.device.setRenderTargetsDefault()
self.device.setVertexBuffers([self.vertexBuffer])
self.device.setInputLayout(self.inputLayout)
self.device.setPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLELIST)
#View matrix.
viewMatrix = d3d11.Matrix()
viewMatrix.lookAt((0, 5, -15), (0, 5, 0), (0, 1, 0))
#Projection matrix.
screenDesc = self.device.getScreenDesc()
fieldOfView = math.radians(60.0)
aspectRatio = float(screenDesc.width) / screenDesc.height
projMatrix = d3d11.Matrix()
projMatrix.perspectiveFov(fieldOfView, aspectRatio, 0.1, 100.0)
#World matrix.
yRot = time.clock()
worldMatrix = d3d11.Matrix()
worldMatrix.rotate((0, yRot, 0))
#Combined matrix.
wordViewProj = worldMatrix * viewMatrix * projMatrix
#Update effect variable(s).
self.effect.set("worldViewProjection", wordViewProj)
self.effect.apply(0, 0)
#Draw all three vertices using the currently bound vertex buffer
#and other settings (Effect, input layout, topology etc.).
self.device.draw(len(self.vertexBuffer), 0)
#Present our rendering.
self.device.present(0)
def onSize(self, evt):
#Our rendering window has been resized, so reset
#the device.
self.device.reset()
def onIdle(self, evt):
if self.media:
#Check media messages manually. We don't
#need to do anything, but for more complex
#applications you might want to observe
#what is going on. You could (and maybe should)
#use a timer for this.
for message in self.media.getEvents():
pass
def onTimer(self, evt):
self.renderAndPresent()
def onPaint(self, evt):
dc = wx.PaintDC(self)
self.renderAndPresent()
def playVideo(self, evt):
dlg = wx.FileDialog(self, message="Choose a media file", defaultDir=os.getcwd(),
defaultFile="", style=wx.OPEN | wx.CHANGE_DIR)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
tempWindow = d3d11.Window(handle=self.rightwindow.GetHandle())
try:
#Load the media and play. onIdle() pumps messages. If the media
#does not have any video a window is not actually needed.
self.media = d3d11.Media(path, tempWindow)
self.media.play()
finally:
#Make sure window always gets detached, otherwise it
#closes 'rightwindow'.
tempWindow.detach()
class MainApp(wx.App):
def OnInit(self):
frame = MainFrame(None, -1, "DirectPython 11 with wxPython", (10, 10), (800, 600))
frame.CenterOnScreen()
frame.Show()
return True
if __name__ == "__main__":
app = MainApp(False)
app.MainLoop()