Spaces:
Sleeping
Sleeping
# Ported from the win32 and MFC OpenGL Samples. | |
import sys | |
from pywin.mfc import docview | |
try: | |
from OpenGL.GL import * # nopycln: import | |
from OpenGL.GLU import * # nopycln: import | |
except ImportError: | |
print("The OpenGL extensions do not appear to be installed.") | |
print("This Pythonwin demo can not run") | |
sys.exit(1) | |
import timer | |
import win32api | |
import win32con | |
import win32ui | |
PFD_TYPE_RGBA = 0 | |
PFD_TYPE_COLORINDEX = 1 | |
PFD_MAIN_PLANE = 0 | |
PFD_OVERLAY_PLANE = 1 | |
PFD_UNDERLAY_PLANE = -1 | |
PFD_DOUBLEBUFFER = 0x00000001 | |
PFD_STEREO = 0x00000002 | |
PFD_DRAW_TO_WINDOW = 0x00000004 | |
PFD_DRAW_TO_BITMAP = 0x00000008 | |
PFD_SUPPORT_GDI = 0x00000010 | |
PFD_SUPPORT_OPENGL = 0x00000020 | |
PFD_GENERIC_FORMAT = 0x00000040 | |
PFD_NEED_PALETTE = 0x00000080 | |
PFD_NEED_SYSTEM_PALETTE = 0x00000100 | |
PFD_SWAP_EXCHANGE = 0x00000200 | |
PFD_SWAP_COPY = 0x00000400 | |
PFD_SWAP_LAYER_BUFFERS = 0x00000800 | |
PFD_GENERIC_ACCELERATED = 0x00001000 | |
PFD_DEPTH_DONTCARE = 0x20000000 | |
PFD_DOUBLEBUFFER_DONTCARE = 0x40000000 | |
PFD_STEREO_DONTCARE = 0x80000000 | |
# threeto8 = [0, 0o111>>1, 0o222>>1, 0o333>>1, 0o444>>1, 0o555>>1, 0o666>>1, 0o377] | |
threeto8 = [0, 73 >> 1, 146 >> 1, 219 >> 1, 292 >> 1, 365 >> 1, 438 >> 1, 255] | |
twoto8 = [0, 0x55, 0xAA, 0xFF] | |
oneto8 = [0, 255] | |
def ComponentFromIndex(i, nbits, shift): | |
# val = (unsigned char) (i >> shift); | |
val = (i >> shift) & 0xF | |
if nbits == 1: | |
val = val & 0x1 | |
return oneto8[val] | |
elif nbits == 2: | |
val = val & 0x3 | |
return twoto8[val] | |
elif nbits == 3: | |
val = val & 0x7 | |
return threeto8[val] | |
else: | |
return 0 | |
OpenGLViewParent = docview.ScrollView | |
class OpenGLView(OpenGLViewParent): | |
def PreCreateWindow(self, cc): | |
self.HookMessage(self.OnSize, win32con.WM_SIZE) | |
# An OpenGL window must be created with the following flags and must not | |
# include CS_PARENTDC for the class style. Refer to SetPixelFormat | |
# documentation in the "Comments" section for further information. | |
style = cc[5] | |
style = style | win32con.WS_CLIPSIBLINGS | win32con.WS_CLIPCHILDREN | |
cc = cc[0], cc[1], cc[2], cc[3], cc[4], style, cc[6], cc[7], cc[8] | |
cc = self._obj_.PreCreateWindow(cc) | |
return cc | |
def OnSize(self, params): | |
lParam = params[3] | |
cx = win32api.LOWORD(lParam) | |
cy = win32api.HIWORD(lParam) | |
glViewport(0, 0, cx, cy) | |
if self.oldrect[2] > cx or self.oldrect[3] > cy: | |
self.RedrawWindow() | |
self.OnSizeChange(cx, cy) | |
self.oldrect = self.oldrect[0], self.oldrect[1], cx, cy | |
def OnInitialUpdate(self): | |
self.SetScaleToFitSize( | |
(100, 100) | |
) # or SetScrollSizes() - A Pythonwin requirement | |
return self._obj_.OnInitialUpdate() | |
# return rc | |
def OnCreate(self, cs): | |
self.oldrect = self.GetClientRect() | |
self._InitContexts() | |
self.Init() | |
def OnDestroy(self, msg): | |
self.Term() | |
self._DestroyContexts() | |
return OpenGLViewParent.OnDestroy(self, msg) | |
def OnDraw(self, dc): | |
self.DrawScene() | |
def OnEraseBkgnd(self, dc): | |
return 1 | |
# The OpenGL helpers | |
def _SetupPixelFormat(self): | |
dc = self.dc.GetSafeHdc() | |
pfd = CreatePIXELFORMATDESCRIPTOR() | |
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | |
pfd.iPixelType = PFD_TYPE_RGBA | |
pfd.cColorBits = 24 | |
pfd.cDepthBits = 32 | |
pfd.iLayerType = PFD_MAIN_PLANE | |
pixelformat = ChoosePixelFormat(dc, pfd) | |
SetPixelFormat(dc, pixelformat, pfd) | |
self._CreateRGBPalette() | |
def _CreateRGBPalette(self): | |
dc = self.dc.GetSafeHdc() | |
n = GetPixelFormat(dc) | |
pfd = DescribePixelFormat(dc, n) | |
if pfd.dwFlags & PFD_NEED_PALETTE: | |
n = 1 << pfd.cColorBits | |
pal = [] | |
for i in range(n): | |
this = ( | |
ComponentFromIndex(i, pfd.cRedBits, pfd.cRedShift), | |
ComponentFromIndex(i, pfd.cGreenBits, pfd.cGreenShift), | |
ComponentFromIndex(i, pfd.cBlueBits, pfd.cBlueShift), | |
0, | |
) | |
pal.append(this) | |
hpal = win32ui.CreatePalette(pal) | |
self.dc.SelectPalette(hpal, 0) | |
self.dc.RealizePalette() | |
def _InitContexts(self): | |
self.dc = self.GetDC() | |
self._SetupPixelFormat() | |
hrc = wglCreateContext(self.dc.GetSafeHdc()) | |
wglMakeCurrent(self.dc.GetSafeHdc(), hrc) | |
def _DestroyContexts(self): | |
hrc = wglGetCurrentContext() | |
wglMakeCurrent(0, 0) | |
if hrc: | |
wglDeleteContext(hrc) | |
# The methods to support OpenGL | |
def DrawScene(self): | |
assert 0, "You must override this method" | |
def Init(self): | |
assert 0, "You must override this method" | |
def OnSizeChange(self, cx, cy): | |
pass | |
def Term(self): | |
pass | |
class TestView(OpenGLView): | |
def OnSizeChange(self, right, bottom): | |
glClearColor(0.0, 0.0, 0.0, 1.0) | |
glClearDepth(1.0) | |
glEnable(GL_DEPTH_TEST) | |
glMatrixMode(GL_PROJECTION) | |
if bottom: | |
aspect = right / bottom | |
else: | |
aspect = 0 # When window created! | |
glLoadIdentity() | |
gluPerspective(45.0, aspect, 3.0, 7.0) | |
glMatrixMode(GL_MODELVIEW) | |
near_plane = 3.0 | |
far_plane = 7.0 | |
maxObjectSize = 3.0 | |
self.radius = near_plane + maxObjectSize / 2.0 | |
def Init(self): | |
pass | |
def DrawScene(self): | |
glClearColor(0.0, 0.0, 0.0, 1.0) | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) | |
glPushMatrix() | |
glTranslatef(0.0, 0.0, -self.radius) | |
self._DrawCone() | |
self._DrawPyramid() | |
glPopMatrix() | |
glFinish() | |
SwapBuffers(wglGetCurrentDC()) | |
def _DrawCone(self): | |
glColor3f(0.0, 1.0, 0.0) | |
glPushMatrix() | |
glTranslatef(-1.0, 0.0, 0.0) | |
quadObj = gluNewQuadric() | |
gluQuadricDrawStyle(quadObj, GLU_FILL) | |
gluQuadricNormals(quadObj, GLU_SMOOTH) | |
gluCylinder(quadObj, 1.0, 0.0, 1.0, 20, 10) | |
# gluDeleteQuadric(quadObj); | |
glPopMatrix() | |
def _DrawPyramid(self): | |
glPushMatrix() | |
glTranslatef(1.0, 0.0, 0.0) | |
glBegin(GL_TRIANGLE_FAN) | |
glColor3f(1.0, 0.0, 0.0) | |
glVertex3f(0.0, 1.0, 0.0) | |
glColor3f(0.0, 1.0, 0.0) | |
glVertex3f(-1.0, 0.0, 0.0) | |
glColor3f(0.0, 0.0, 1.0) | |
glVertex3f(0.0, 0.0, 1.0) | |
glColor3f(0.0, 1.0, 0.0) | |
glVertex3f(1.0, 0.0, 0.0) | |
glEnd() | |
glPopMatrix() | |
class CubeView(OpenGLView): | |
def OnSizeChange(self, right, bottom): | |
glClearColor(0.0, 0.0, 0.0, 1.0) | |
glClearDepth(1.0) | |
glEnable(GL_DEPTH_TEST) | |
glMatrixMode(GL_PROJECTION) | |
if bottom: | |
aspect = right / bottom | |
else: | |
aspect = 0 # When window created! | |
glLoadIdentity() | |
gluPerspective(45.0, aspect, 3.0, 7.0) | |
glMatrixMode(GL_MODELVIEW) | |
near_plane = 3.0 | |
far_plane = 7.0 | |
maxObjectSize = 3.0 | |
self.radius = near_plane + maxObjectSize / 2.0 | |
def Init(self): | |
self.busy = 0 | |
self.wAngleY = 10.0 | |
self.wAngleX = 1.0 | |
self.wAngleZ = 5.0 | |
self.timerid = timer.set_timer(150, self.OnTimer) | |
def OnTimer(self, id, timeVal): | |
self.DrawScene() | |
def Term(self): | |
timer.kill_timer(self.timerid) | |
def DrawScene(self): | |
if self.busy: | |
return | |
self.busy = 1 | |
glClearColor(0.0, 0.0, 0.0, 1.0) | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) | |
glPushMatrix() | |
glTranslatef(0.0, 0.0, -self.radius) | |
glRotatef(self.wAngleX, 1.0, 0.0, 0.0) | |
glRotatef(self.wAngleY, 0.0, 1.0, 0.0) | |
glRotatef(self.wAngleZ, 0.0, 0.0, 1.0) | |
self.wAngleX = self.wAngleX + 1.0 | |
self.wAngleY = self.wAngleY + 10.0 | |
self.wAngleZ = self.wAngleZ + 5.0 | |
glBegin(GL_QUAD_STRIP) | |
glColor3f(1.0, 0.0, 1.0) | |
glVertex3f(-0.5, 0.5, 0.5) | |
glColor3f(1.0, 0.0, 0.0) | |
glVertex3f(-0.5, -0.5, 0.5) | |
glColor3f(1.0, 1.0, 1.0) | |
glVertex3f(0.5, 0.5, 0.5) | |
glColor3f(1.0, 1.0, 0.0) | |
glVertex3f(0.5, -0.5, 0.5) | |
glColor3f(0.0, 1.0, 1.0) | |
glVertex3f(0.5, 0.5, -0.5) | |
glColor3f(0.0, 1.0, 0.0) | |
glVertex3f(0.5, -0.5, -0.5) | |
glColor3f(0.0, 0.0, 1.0) | |
glVertex3f(-0.5, 0.5, -0.5) | |
glColor3f(0.0, 0.0, 0.0) | |
glVertex3f(-0.5, -0.5, -0.5) | |
glColor3f(1.0, 0.0, 1.0) | |
glVertex3f(-0.5, 0.5, 0.5) | |
glColor3f(1.0, 0.0, 0.0) | |
glVertex3f(-0.5, -0.5, 0.5) | |
glEnd() | |
glBegin(GL_QUADS) | |
glColor3f(1.0, 0.0, 1.0) | |
glVertex3f(-0.5, 0.5, 0.5) | |
glColor3f(1.0, 1.0, 1.0) | |
glVertex3f(0.5, 0.5, 0.5) | |
glColor3f(0.0, 1.0, 1.0) | |
glVertex3f(0.5, 0.5, -0.5) | |
glColor3f(0.0, 0.0, 1.0) | |
glVertex3f(-0.5, 0.5, -0.5) | |
glEnd() | |
glBegin(GL_QUADS) | |
glColor3f(1.0, 0.0, 0.0) | |
glVertex3f(-0.5, -0.5, 0.5) | |
glColor3f(1.0, 1.0, 0.0) | |
glVertex3f(0.5, -0.5, 0.5) | |
glColor3f(0.0, 1.0, 0.0) | |
glVertex3f(0.5, -0.5, -0.5) | |
glColor3f(0.0, 0.0, 0.0) | |
glVertex3f(-0.5, -0.5, -0.5) | |
glEnd() | |
glPopMatrix() | |
glFinish() | |
SwapBuffers(wglGetCurrentDC()) | |
self.busy = 0 | |
def test(): | |
template = docview.DocTemplate(None, None, None, CubeView) | |
# template = docview.DocTemplate(None, None, None, TestView ) | |
template.OpenDocumentFile(None) | |
if __name__ == "__main__": | |
test() | |