Path: blob/main/tools/contributed/sumopy/agilepy/lib_wx/test_glcanvas.py
169689 views
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo1# Copyright (C) 2016-2025 German Aerospace Center (DLR) and others.2# SUMOPy module3# Copyright (C) 2012-2021 University of Bologna - DICAM4# This program and the accompanying materials are made available under the5# terms of the Eclipse Public License 2.0 which is available at6# https://www.eclipse.org/legal/epl-2.0/7# This Source Code may also be made available under the following Secondary8# Licenses when the conditions for such availability set forth in the Eclipse9# Public License 2.0 are satisfied: GNU General Public License, version 210# or later which is available at11# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html12# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later1314# @file test_glcanvas.py15# @author Joerg Schweizer16# @date 20121718'''19@author: Stou Sandalski ([email protected])20@license: Public Domain21'''2223# Uncomment if you have multiple wxWidgets versions24#import wxversion25# wxversion.select('2.8')2627import wxmisc28import objpanel29from wxmisc import *30import classman as cm31import math32import wx3334from wx import glcanvas35from wx.lib.buttons import GenBitmapTextButton, GenBitmapButton36try:37from OpenGL.GL import *38from OpenGL.GLU import *39from OpenGL.GLUT import *40from OpenGL.raw.GL.ARB.vertex_array_object import glGenVertexArrays, \41glBindVertexArray4243from OpenGL.arrays import vbo44import numpy as np4546except ImportError:47raise ImportError, "Required dependency OpenGL not present"4849import sys50import os51import types52APPDIR = os.path.join(os.path.dirname(__file__), "..")53sys.path.append(os.path.join(APPDIR, "lib_base"))54IMAGEDIR = os.path.join(os.path.dirname(__file__), "images")5556# wx gui stuff575859stockIDs = [60wx.ID_ABOUT,61wx.ID_ADD,62wx.ID_APPLY,63wx.ID_BOLD,64wx.ID_CANCEL,65wx.ID_CLEAR,66wx.ID_CLOSE,67wx.ID_COPY,68wx.ID_CUT,69wx.ID_DELETE,70wx.ID_EDIT,71wx.ID_FIND,72wx.ID_FILE,73wx.ID_REPLACE,74wx.ID_BACKWARD,75wx.ID_DOWN,76wx.ID_FORWARD,77wx.ID_UP,78wx.ID_HELP,79wx.ID_HOME,80wx.ID_INDENT,81wx.ID_INDEX,82wx.ID_ITALIC,83wx.ID_JUSTIFY_CENTER,84wx.ID_JUSTIFY_FILL,85wx.ID_JUSTIFY_LEFT,86wx.ID_JUSTIFY_RIGHT,87wx.ID_NEW,88wx.ID_NO,89wx.ID_OK,90wx.ID_OPEN,91wx.ID_PASTE,92wx.ID_PREFERENCES,93wx.ID_PRINT,94wx.ID_PREVIEW,95wx.ID_PROPERTIES,96wx.ID_EXIT,97wx.ID_REDO,98wx.ID_REFRESH,99wx.ID_REMOVE,100wx.ID_REVERT_TO_SAVED,101wx.ID_SAVE,102wx.ID_SAVEAS,103wx.ID_SELECTALL,104wx.ID_STOP,105wx.ID_UNDELETE,106wx.ID_UNDERLINE,107wx.ID_UNDO,108wx.ID_UNINDENT,109wx.ID_YES,110wx.ID_ZOOM_100,111wx.ID_ZOOM_FIT,112wx.ID_ZOOM_IN,113wx.ID_ZOOM_OUT,114115]116117118class BaseTool(cm.BaseObjman):119"""120This is a base tool class for Agilecanvas.121It must handle all mouse or keyboard events,122must create and draw helplines and finally123modify the state of client which are graphically124represented on the canvas.125"""126127def __init__(self, parent, mainframe=None):128"""129To be overridden by specific tool.130"""131self.init_common('select', parent, 'Selection tool', mainframe, info='Select objects in canvas')132133def set_button_info(self, bsize=(32, 32)):134# print 'set_button_info select tool'135self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'selectIcon.bmp'), wx.BITMAP_TYPE_BMP)136self._bitmap_sel = wx.Bitmap(os.path.join(IMAGEDIR, 'selectIconSel.bmp'), wx.BITMAP_TYPE_BMP)137138def get_button(self, parent, bottonsize=(32, 32), bottonborder=10):139140# simple stockbuttons141#b=wx.Button(parent, wx.ID_DELETE)142143id = wx.NewId()144bitmap = self._bitmap145146#b=GenBitmapTextToggleButton(parent, id, bitmap,tool.name,name = self.get_name())147b = GenBitmapToggleButton(parent, id, bitmap, (bitmap.GetWidth()+bottonborder,148bitmap.GetHeight()+bottonborder), name=self.get_name())149#b=GenBitmapToggleButton(self, wx.ID_DELETE)150#b = GenBitmapTextToggleButton(self, id, None, tool.get('name',''), size = (200, 45))151152if bitmap is not None:153#mask = wx.Mask(bitmap, wx.BLUE)154# bitmap.SetMask(mask)155b.SetBitmapLabel(bitmap)156# bmp=wx.NullBitmap157158bitmap_sel = self._bitmap_sel159if bitmap_sel is not None:160#mask = wx.Mask(bmp, wx.BLUE)161# bmp.SetMask(mask)162b.SetBitmapSelected(bitmap_sel)163164b.SetUseFocusIndicator(False)165166b.SetUseFocusIndicator(False)167# b.SetSize((36,140))168# b.SetBestSize()169tt = wx.ToolTip(self.get_info())170b.SetToolTip(tt) # .SetTip(tool.tooltip)171return b172173def init_common(self, ident, parent, name, mainframe=None, info=None):174# print 'Agiletool.__init__',ident,name175self.name = name176self.metacanvas = None177# FSMnamed.__init__(self,ident,parent,name)178self._init_objman(ident, parent=parent, name=name.title(), info=info)179attrsman = self.set_attrsman(cm.Attrsman(self))180181self.access = attrsman.add(cm.AttrConf('access', ['bus', 'bike', 'tram'],182groupnames=['options'],183perm='rw',184is_save=True,185name='Access list',186info='List with vehicle classes that have access',187))188189self.emissiontype = attrsman.add(cm.AttrConf('emissiontype', 'Euro 0',190groupnames=['options'],191perm='rw',192is_save=True,193name='Emission type',194info='Emission type of vehicle',195))196# dictionary of drawobjects that will be created during197# the application of the tool.198# ident is the number in chronological order of creation,199# starting with one. Value is the ad hoc instance of a drawing200# object.201self.drawobjs = {}202self.helpobjs = {}203204self.mainframe = mainframe205# print ' call set_button',self.ident206self.set_button_info()207self.targetsets = {}208# self.optionspanel=None209210def append_drawobj(self, drawobj):211"""212Append new drawobject213"""214n = len(self.drawobjs)+1215self.drawobjs[n] = drawobj216217def pop_drawobj(self):218"""219Returns most recent drawobject, removing it from the list.220If there are no more drwobjects in the list None is returned.221"""222223n = len(self.drawobjs)224if n > 0:225drawobj = self.drawobjs[n]226del self.drawobjs[n]227return drawobj228else:229return None230231def get_last_drawobj(self):232"""233Returns most recent drawobject, without changing the list.234If there are no more drwobjects in the list None is returned.235"""236n = len(self.drawobjs)237if n > 0:238drawobj = self.drawobjs[n]239return drawobj240else:241return None242243def clear_drawobjs(self):244"""245Clear list of drawobjects, while maintaining them on metacanvas.246"""247self.drawobjs = {}248249def del_drawobjs(self):250"""251Remove all drawobjects from metacanvas.252"""253while len(self.drawobjs) > 0:254drawobj = self.pop_drawobj()255self.metacanvas.del_obj(drawobj)256257def make_targetsets(self, setnames=None, layer=None):258"""259Returns a dictionary with instances of targetsets as values260and setnames as key.261This allows the tool to select a list of sets from the a specific262layer to which it can directly communicate.263264If no setnames are given then all sets of the specific layer265are returned.266267Can be used for example to change handle settings268"""269if setnames is not None:270objsets = {}271for name in setnames:272objsets[name] = self.metacanvas.get_objset_from_layer(layer, name)273self.targetsets = objsets274else:275self.targetsets = self.metacanvas.get_objset_from_layer(layer)276277def set_handles(self):278"""279Set handles to selected object sets which can be connected.280"""281# put handles on all section objects282for name_set in self.targetsets.keys():283self.metacanvas.set_handles(name_set=name_set)284285def get_bitmap_from_file(self, name_bitmap):286# print 'get_bitmap_from_file :'+"gui/bitmaps/" + name_bitmap + ".bmp"287return wx.Bitmap("gui/bitmaps/" + name_bitmap + ".bmp",288wx.BITMAP_TYPE_BMP)289290# def make_optionpanel(self,panel):291292def get_optionpanel(self, parent):293"""294Return tool option widgets on given parent295"""296# print 'get_optionpanel',self297#button = wx.Button(parent, wx.NewId(), self.name+' Options')298#button.Bind(wx.EVT_BUTTON, self.set_options)299# return button300301self.optionspanel = ObjPanel(parent, self, groups=['options'],302standartbuttons=[],303immediate_apply=True,304panelstyle='instrumental')305return self.optionspanel306307def set_options(self, event):308"""309Called from options panel.310"""311print 'set_options', self.ident312print ' event=', event313pass314315def set_statusbar(self, key, info):316pass317318def activate_metacanvas(self, metacanvas):319"""320This call by metacanvas signals that the tool has been321activated and can now interact with metacanvas.322"""323# print 'activate_metacanvas',self.ident324self.metacanvas = metacanvas325self.metacanvas.del_handles()326self.activate()327328def get_metacanvas(self):329return self.metacanvas330331# def get_pentable(self):332# if self.metacanvas:333# return self.metacanvas.get_pentable()334335def deactivate_metacanvas(self):336"""337This call by metacanvas signals that the tool has been338deactivated and can now interact with metacanvas.339"""340341self.deactivate()342self.optionspanel = None343self.metacanvas = None344345346class DelTool(BaseTool):347def __init__(self, parent, mainframe=None):348"""349To be overridden by specific tool.350"""351self.init_common('delete', parent, 'Delete', mainframe, info='Delete objects in canvas')352353def set_button_info(self, bsize=(32, 32)):354# print 'set_button_info select tool'355self._bitmap = None356self._bitmap_sel = None357358def get_button(self, parent, bottonsize=(32, 32), bottonborder=10):359360# simple stockbuttons361b = wx.Button(parent, wx.ID_DELETE, name=self.get_name())362363b.SetSize(bottonsize)364# b.SetBestSize()365tt = wx.ToolTip(self.get_info())366b.SetToolTip(tt) # .SetTip(tool.tooltip)367# print 'DelTool.get_button',dir(b)368return b369370371class ToolPalett(wx.Panel):372"""373This is a panel where tools are represented by images and/or text.374The tools are selected in a radio-button-fashion.375376Each tool has a string as key. Each time the status changes,377a callback function is called with new and old tool key as argument.378"""379380def __init__(self, parent, tools=[], callback=None, n_buttoncolumns=4):381"""382callback is a function that is called when a tool has been selected.383The function is called as:384callback(tool)385386"""387# the metacanvas object with which the pallet should apply th tools388self._callback = callback389390# wx.Window.__init__(self,parent,wx.ID_ANY,wx.DefaultPosition,wx.DefaultSize,wx.SUNKEN_BORDER|wx.WANTS_CHARS)391# wx.Panel.__init__(self,parent,wx.ID_ANY,wx.DefaultPosition,size,wx.RAISED_BORDER|wx.WANTS_CHARS)392wx.Panel.__init__(self, parent, -1, wx.DefaultPosition, wx.DefaultSize)393# wx.Panel.__init__(self,parent,wx.ID_ANY,wx.DefaultPosition,(300,600),wx.RAISED_BORDER|wx.WANTS_CHARS)394self.sizer = wx.GridSizer(0, n_buttoncolumns, 5, 5)395self.SetSizer(self.sizer)396self._id_to_tool = {}397self._id = -1398399for tool in tools:400self.add_tool(tool)401402self.sizer.Fit(self)403# self.SetMaxSize((300,300))404405def add_tool(self, tool):406"""407Add a tool to the pallet.408"""409bottonsize = (32, 32)410bottonborder = 10411toolbarborder = 1412413if tool is None:414self.sizer.Add()415return None416else:417b = tool.get_button(self, bottonsize=bottonsize, bottonborder=bottonborder)418self.Bind(wx.EVT_BUTTON, self.on_select, b)419420self._id_to_tool[b.GetId()] = (tool, b)421422#self.sizer.Add(b, 0, wx.GROW)423self.sizer.Add(b, 0, wx.EXPAND, border=toolbarborder)424# self.sizer.Add(b)425426return id427428def add_tool_old(self, tool):429"""430Add a tool to the pallet.431"""432bottonsize = (32, 32)433bottonborder = 10434toolbarborder = 1435436if tool is None:437self.sizer.Add()438return None439else:440id = wx.NewId()441bitmap = tool.get_buttonbitmap()442443# print '\n add_tool',key,bitmap444# print 'toolpallet.add_tool: key,name:',tool.key,tool.name445#b=GenBitmapTextToggleButton(self, id, bitmap,tool.name,name = tool.name)446b = GenBitmapToggleButton(self, id, bitmap, (bitmap.GetWidth() +447bottonborder, bitmap.GetHeight()+bottonborder))448#b=GenBitmapToggleButton(self, wx.ID_DELETE)449#b = GenBitmapTextToggleButton(self, id, None, tool.get('name',''), size = (200, 45))450self.Bind(wx.EVT_BUTTON, self.on_select, b)451452if bitmap:453#mask = wx.Mask(bitmap, wx.BLUE)454# bitmap.SetMask(mask)455b.SetBitmapLabel(bitmap)456# bmp=wx.NullBitmap457458bitmap_sel = tool.get_buttonbitmap_sel()459if bitmap_sel:460#mask = wx.Mask(bmp, wx.BLUE)461# bmp.SetMask(mask)462b.SetBitmapSelected(bitmap_sel)463464b.SetUseFocusIndicator(False)465# b.SetSize((36,140))466# b.SetBestSize()467tt = wx.ToolTip(tool.get_info())468b.SetToolTip(tt) # .SetTip(tool.tooltip)469470self._id_to_tool[id] = (tool, b)471472#self.sizer.Add(b, 0, wx.GROW)473474self.sizer.Add(b, 0, wx.EXPAND, border=toolbarborder)475# self.sizer.Add(b)476477return id478479def get_tools(self):480"""481Returns lins with all toll instances482"""483tools = []484for (tool, b) in self._id_to_tool.values():485tools.append(tool)486return tools487488def refresh(self):489"""490Reorganizes toolpallet after adding/removing tools.491Attention is not automatically called.492"""493self.sizer.Layout()494495def on_select(self, event):496497_id = event.GetEventObject().GetId()498print '\n on_select', _id, self._id # ,self._id_to_tool[_id]499if _id != self._id:500if self._id_to_tool.has_key(_id):501502(tool, button) = self._id_to_tool[_id]503print ' new tool', tool.get_name()504self.unselect()505self._id = _id506self.GetParent().set_options(tool)507if self._callback is not None:508self._callback(tool)509510def unselect(self):511"""512Unselect currently selected tool.513"""514if self._id_to_tool.has_key(self._id):515(tool, button) = self._id_to_tool[self._id]516if hasattr(button, 'SetToggle'):517button.SetToggle(False)518else:519# button.SetFocus()520# print 'button.SetFocus',button.SetFocus.__doc__521pass522523def select(self, id):524"""525Select explicitelt a tool.526"""527print '\n select', id, self._id, self._id_to_tool528529if id != self._id:530if self._id_to_tool.has_key(id):531# unselect previous532self.unselect()533534# select and activate new tool535(tool, button) = self._id_to_tool[id]536button.SetToggle(True)537self._id = id538if self._callback is not None:539self._callback(tool)540541542class __ToggleMixin:543def SetToggle(self, flag):544self.up = not flag545self.Refresh()546SetValue = SetToggle547548def GetToggle(self):549return not self.up550GetValue = GetToggle551552def OnLeftDown(self, event):553if not self.IsEnabled():554return555self.saveUp = self.up556self.up = False # not self.up557self.CaptureMouse()558self.SetFocus()559self.Refresh()560561def OnLeftUp(self, event):562if not self.IsEnabled() or not self.HasCapture():563return564if self.HasCapture():565if self.up != self.saveUp:566self.Notify()567self.ReleaseMouse()568self.Refresh()569570def OnKeyDown(self, event):571event.Skip()572573574class GenBitmapTextToggleButton(__ToggleMixin, GenBitmapTextButton):575"""A generic toggle bitmap button with text label"""576pass577578579class GenBitmapToggleButton(__ToggleMixin, GenBitmapButton):580"""A generic toggle bitmap button with text label"""581pass582583584class ToolsPanel(wx.Panel):585"""586587Interactively navigates through objects and displays attributes588on a panel.589"""590591def __init__(self, parent):592wx.Panel.__init__(self, parent, -1, wx.DefaultPosition, wx.DefaultSize)593594sizer = wx.BoxSizer(wx.VERTICAL)595596self._toolspalett = ToolPalett(self)597598# self._toolspalett.add_tool(BaseTool(self))599600# create initial option panel601self._optionspanel = wx.Window(self)602self._optionspanel.SetBackgroundColour("pink")603wx.StaticText(self._optionspanel, -1, "Tool Options", (300, -1))604605sizer.Add(self._toolspalett, 0, wx.ALL | wx.ALIGN_LEFT | wx.GROW, 4)606sizer.Add(self._optionspanel, 1, wx.GROW)607608# finish panel setup609self.SetSizer(sizer)610sizer.Fit(self)611612# self.SetSize(parent.GetSize())613614def add_tool(self, tool):615self._toolspalett.add_tool(tool)616617def set_options(self, tool):618#self._optionspanel.change_obj(tool,groupnames = ['options'])619# self._optionspanel.change_obj(tool)620sizer = self.GetSizer()621sizer.Remove(1)622self._optionspanel.Destroy()623624self._optionspanel = objpanel.ObjPanel(self, obj=tool,625attrconfigs=None,626#tables = None,627# table = None, id=None, ids=None,628groupnames=None,629func_change_obj=None,630show_groupnames=False, show_title=True, is_modal=False,631mainframe=None,632pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.MAXIMIZE_BOX | wx.RESIZE_BORDER,633immediate_apply=False, panelstyle='default',634standartbuttons=['apply', 'restore'])635# if id is not None:636# self.objpanel=ObjPanel(self,obj,id=id,func_change_obj=self.change_obj)637# else:638# self.objpanel=ObjPanel(self,obj,func_change_obj=self.change_obj)639sizer.Add(self._optionspanel, 1, wx.GROW)640641self.Refresh()642# sizer.Fit(self)643sizer.Layout()644645646def get_dist_point_to_segs(p, y1, x1, y2, x2, is_ending=True):647"""648Minimum Distance between a Point p = (x,y) and a Line segments ,649where vectors x1, y1 are the first points and x2,y2 are the second points650of the line segments.651Written by Paul Bourke, October 1988652http://astronomy.swin.edu.au/~pbourke/geometry/pointline/653654Rewritten in vectorial form by Joerg Schweizer655"""656657y3, x3 = p658659d = np.zeros(len(y1), dtype=np.float32)660661dx21 = (x2-x1)662dy21 = (y2-y1)663664lensq21 = dx21*dx21 + dy21*dy21665666# indexvector for all zero length lines667iz = (lensq21 == 0)668669dy = y3-y1[iz]670dx = x3-x1[iz]671672d[iz] = dx*dx + dy*dy673674lensq21[iz] = 1.0 # replace zeros with 1.0 to avoid div by zero error675676u = (x3-x1)*dx21 + (y3-y1)*dy21677u = u / lensq21678679x = x1 + u * dx21680y = y1 + u * dy21681682if is_ending:683ie = u < 0684x[ie] = x1[ie]685y[ie] = y1[ie]686ie = u > 1687x[ie] = x2[ie]688y[ie] = y2[ie]689690dx30 = x3-x691dy30 = y3-y692d[~iz] = (dx30*dx30 + dy30*dy30)[~iz]693return d694695696def is_inside_triangles(p, x1, y1, x2, y2, x3, y3):697"""698Returns a binary vector with True if point p is699inside a triangle.700x1,y1,x2,y2,x3,y3 are vectors with the 3 coordiantes of the triangles.701"""702alpha = ((y2 - y3)*(p[0] - x3) + (x3 - x2)*(p[1] - y3)) \703/ ((y2 - y3)*(x1 - x3) + (x3 - x2)*(y1 - y3))704705beta = ((y3 - y1)*(p[0] - x3) + (x1 - x3)*(p[1] - y3)) \706/ ((y2 - y3)*(x1 - x3) + (x3 - x2)*(y1 - y3))707708gamma = 1.0 - alpha - beta709return (alpha > 0) & (beta > 0) & (gamma > 0)710711712class WxGLTest_orig(glcanvas.GLCanvas):713def __init__(self, parent):714715glcanvas.GLCanvas.__init__(self, parent, -1, attribList=[glcanvas.WX_GL_DOUBLEBUFFER])716wx.EVT_PAINT(self, self.OnDraw)717wx.EVT_SIZE(self, self.OnSize)718wx.EVT_MOTION(self, self.OnMouseMotion)719wx.EVT_WINDOW_DESTROY(self, self.OnDestroy)720721self.init = True722723def OnDraw(self, event):724self.SetCurrent()725726if not self.init:727self.InitGL()728self.init = False729730glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)731glLoadIdentity()732733# Draw the spiral in 'immediate mode'734# WARNING: You should not be doing the spiral calculation inside the loop735# even if you are using glBegin/glEnd, sin/cos are fairly expensive functions736# I've left it here as is to make the code simpler.737radius = 1.0738x = radius*math.sin(0)739y = radius*math.cos(0)740glColor(0.0, 1.0, 0.0)741glBegin(GL_LINE_STRIP)742for deg in xrange(1000):743glVertex(x, y, 0.0)744rad = math.radians(deg)745radius -= 0.001746x = radius*math.sin(rad)747y = radius*math.cos(rad)748glEnd()749750glEnableClientState(GL_VERTEX_ARRAY)751752spiral_array = []753754# Second Spiral using "array immediate mode" (i.e. Vertex Arrays)755radius = 0.8756x = radius*math.sin(0)757y = radius*math.cos(0)758glColor(1.0, 0.0, 0.0)759for deg in xrange(820):760spiral_array.append([x, y])761rad = math.radians(deg)762radius -= 0.001763x = radius*math.sin(rad)764y = radius*math.cos(rad)765766glVertexPointerf(spiral_array)767glDrawArrays(GL_LINE_STRIP, 0, len(spiral_array))768glFlush()769self.SwapBuffers()770return771772def InitGL(self):773'''774Initialize GL775'''776777# # set viewing projection778# glClearColor(0.0, 0.0, 0.0, 1.0)779# glClearDepth(1.0)780#781# glMatrixMode(GL_PROJECTION)782# glLoadIdentity()783# gluPerspective(40.0, 1.0, 1.0, 30.0)784#785# glMatrixMode(GL_MODELVIEW)786# glLoadIdentity()787# gluLookAt(0.0, 0.0, 10.0,788# 0.0, 0.0, 0.0,789# 0.0, 1.0, 0.0)790791def OnSize(self, event):792793try:794width, height = event.GetSize()795except:796width = event.GetSize().width797height = event.GetSize().height798799self.Refresh()800self.Update()801802def OnMouseMotion(self, event):803x = event.GetX()804y = event.GetY()805806def OnDestroy(self, event):807print "Destroying Window"808809810class Lines:811"""Lines class."""812813def __init__(self, linewidth=3, vertices=None, colors=None):814self.name = 'Lines'815self.n_vert_per_elem = 2816self.linewidth = linewidth817self.c_highl = 0.3818self.detectwidth = 0.1 # m819self.set_attrs(vertices, colors)820821def set_attrs(self, vertices, colors):822823self.vertices = np.array(vertices, dtype=np.float32)824self._update_vertexvbo()825826self.colors = np.array(colors, dtype=np.float32)827self.colors_highl = np.zeros((len(colors), 4), dtype=np.float32)828self._update_colorvbo()829830def _update_vertexvbo(self):831self._vertexvbo = vbo.VBO(self.vertices.reshape((-1, 3)))832self._indexvbo = vbo.VBO(np.arange(self.n_vert_per_elem*len(self.vertices),833dtype=np.int32), target=GL_ELEMENT_ARRAY_BUFFER)834835def _update_colorvbo(self):836#self._colorvbo = vbo.VBO( np.resize( np.repeat(np.clip((self.colors+self.c_highl*self.colors_highl) ,0.0,1.0), self.n_vert_per_elem),(len(self.colors),4)) )837self._colorvbo = vbo.VBO(np.clip((self.colors+self.colors_highl)838[np.array(np.arange(0, len(self.colors), 1.0/self.n_vert_per_elem), int)], 0.0, 1.0))839840def pick(self, p):841"""842Returns a binary vector which is True values for lines that have been selected843by point p.844845In particular, an element of this vector is True if the minimum distance846between the respective line to point p is less than self.detectwidth847"""848x1 = self.vertices[:, 0, 0]849y1 = self.vertices[:, 0, 1]850851x2 = self.vertices[:, 1, 0]852y2 = self.vertices[:, 1, 1]853854return get_dist_point_to_segs(p, x1, y1, x2, y2, is_ending=True) < self.detectwidth**2855856def highlight(self, inds_highl):857self.colors_highl = np.repeat(self.c_highl*np.array(inds_highl, dtype=np.float32), 4).reshape(-1, 4)858self._update_colorvbo()859860def draw(self):861glLineWidth(self.linewidth)862863glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)864glEnable(GL_BLEND)865866glEnableClientState(GL_VERTEX_ARRAY)867glEnableClientState(GL_COLOR_ARRAY)868869self._colorvbo.bind()870glColorPointer(4, GL_FLOAT, 0, None)871872self._vertexvbo.bind()873self._indexvbo.bind()874glVertexPointer(3, GL_FLOAT, 0, None)875876glDrawElements(GL_LINES, self.n_vert_per_elem*len(self.vertices), GL_UNSIGNED_INT, None)877878glDisableClientState(GL_VERTEX_ARRAY)879glDisableClientState(GL_COLOR_ARRAY)880self._vertexvbo.unbind()881self._indexvbo.unbind()882self._colorvbo.unbind()883884885class Rectangles(Lines):886887def __init__(self, linewidth=3, vertices=None, colors=None):888self.name = 'Rectangles'889self.n_vert_per_elem = 4890self.c_highl = 0.3891self.detectwidth = 0.1 # m892self.linewidth = linewidth893894self.set_attrs(vertices, colors)895896def pick(self, p):897898x1 = self.vertices[:, 0, 0]899y1 = self.vertices[:, 0, 1]900901x2 = self.vertices[:, 1, 0]902y2 = self.vertices[:, 1, 1]903904x3 = self.vertices[:, 2, 0]905y3 = self.vertices[:, 2, 1]906907x4 = self.vertices[:, 3, 0]908y4 = self.vertices[:, 3, 1]909910return is_inside_triangles(p, x1, y1, x2, y2, x3, y3) | is_inside_triangles(p, x1, y1, x3, y3, x4, y4)911912def draw(self):913glLineWidth(self.linewidth)914915glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)916glEnable(GL_BLEND)917918glEnableClientState(GL_VERTEX_ARRAY)919glEnableClientState(GL_COLOR_ARRAY)920921self._colorvbo.bind()922glColorPointer(4, GL_FLOAT, 0, None)923924self._vertexvbo.bind()925self._indexvbo.bind()926glVertexPointer(3, GL_FLOAT, 0, None)927928glDrawElements(GL_QUADS, self.n_vert_per_elem*len(self.vertices), GL_UNSIGNED_INT, None)929930glDisableClientState(GL_VERTEX_ARRAY)931glDisableClientState(GL_COLOR_ARRAY)932self._vertexvbo.unbind()933self._indexvbo.unbind()934self._colorvbo.unbind()935936937class Triangles(Lines):938"""Triangles class."""939940def __init__(self, linewidth=3, vertices=None, colors=None):941self.name = 'Triangles' # ,self.__name__942self.n_vert_per_elem = 3943self.c_highl = 0.3944self.detectwidth = 0.1 # m945self.linewidth = linewidth946947self.set_attrs(vertices, colors)948949def pick(self, p):950return is_inside_triangles(p, self.vertices[:, 0, 0], self.vertices[:, 0, 1], self.vertices[:, 1, 0], self.vertices[:, 1, 1], self.vertices[:, 2, 0], self.vertices[:, 2, 1])951952def draw(self):953glLineWidth(self.linewidth)954955glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)956glEnable(GL_BLEND)957958glEnableClientState(GL_VERTEX_ARRAY)959glEnableClientState(GL_COLOR_ARRAY)960961self._colorvbo.bind()962glColorPointer(4, GL_FLOAT, 0, None)963964self._vertexvbo.bind()965self._indexvbo.bind()966glVertexPointer(3, GL_FLOAT, 0, None)967968glDrawElements(GL_TRIANGLES, self.n_vert_per_elem*len(self.vertices), GL_UNSIGNED_INT, None)969970glDisableClientState(GL_VERTEX_ARRAY)971glDisableClientState(GL_COLOR_ARRAY)972self._vertexvbo.unbind()973self._indexvbo.unbind()974self._colorvbo.unbind()975976977class GLFrame(wx.Frame):978"""A simple class for using OpenGL with wxPython."""979980def __init__(self, parent, id=-1, title='', pos=wx.DefaultPosition,981size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE,982name='frame', mainframe=None):983984print '\n\nGLFrame!!'985if mainframe is None:986self._mainframe = parent987else:988self._mainframe = mainframe989990self._elements = []991self.elements_selected = []992993self.eyex = 0.0994self.eyey = 0.0995self.eyez = -9.0996997self.centerx = 0.0998self.centery = 0.0999self.centerz = 0.010001001self.upx = -1.01002self.upy = 0.01003self.upz = 0.010041005self.g_Width = 6001006self.g_Height = 60010071008self.g_nearPlane = 1.1009self.g_farPlane = 1000.10101011self.action = ""1012self.xStart = self.yStart = 0.1013self.xStart1014self.zoom = 65.10151016self.xRotate = 0.1017self.yRotate = 0.1018self.zRotate = 0.10191020self.xTrans = 0.1021self.yTrans = 0.10221023#1024# Forcing a specific style on the window.1025# Should this include styles passed?1026style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE10271028super(GLFrame, self).__init__(parent, id, title, pos, size, style, name)1029#wx.Frame.__init__(self, parent, id, title, pos, size, style, name)10301031self.GLinitialized = False1032attribList = (glcanvas.WX_GL_RGBA, # RGBA1033glcanvas.WX_GL_DOUBLEBUFFER, # Double Buffered1034glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit10351036#1037# Create the canvas1038self.canvas = glcanvas.GLCanvas(self, attribList=attribList)10391040#1041# Set the event handlers.1042self.canvas.Bind(wx.EVT_ERASE_BACKGROUND, self.processEraseBackgroundEvent)1043self.canvas.Bind(wx.EVT_SIZE, self.processSizeEvent)1044self.canvas.Bind(wx.EVT_PAINT, self.processPaintEvent)10451046self.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)1047self.canvas.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)1048self.canvas.Bind(wx.EVT_MOTION, self.OnMotion)1049self.canvas.Bind(wx.EVT_MOUSEWHEEL, self.OnWheel)10501051self.Show()1052# this is needed to initialize GL projections for unproject1053wx.CallAfter(self.processSizeEvent)10541055def add_element(self, element):1056self._elements.append(element)1057self.OnDraw()10581059def resetView():1060self.zoom = 65.1061self.xRotate = 0.1062self.yRotate = 0.1063self.zRotate = 0.1064self.xTrans = 0.1065self.yTrans = 0.1066self.OnDraw()10671068def OnWheel(self, event):1069#EventType = FloatCanvas.EVT_FC_MOUSEWHEEL1070#1071Rot = event.GetWheelRotation()1072# print 'OnWheel!!',Rot,event.ControlDown(),event.ShiftDown()1073if event.ControlDown(): # event.ControlDown(): # zoom1074if Rot < 0:1075self.zoom *= 0.91076else:1077self.zoom *= 1.11078self.OnDraw()1079event.Skip()10801081def OnLeftDown(self, event):1082##1083if (event.ControlDown() & event.ShiftDown()) & (self.action == ''):1084self.action = 'drag'1085self.BeginGrap(event)1086event.Skip()10871088def OnLeftUp(self, event):1089if self.action == 'drag':1090self.EndGrap(event)1091self.action == ''1092event.Skip()10931094def get_intersection(self, v_near, v_far):1095# 1509181096# idea from http://www.bfilipek.com/2012/06/select-mouse-opengl.html1097# https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection1098d = -v_near + v_far10991100t = -v_near[2]/d[2]1101v_inter = v_near+t*d11021103return v_inter11041105def OnMotion(self, event):11061107p = self.unproject(event)[0:2]1108for element in self._elements:1109inds_pick = element.pick(p)1110element.highlight(inds_pick)11111112self.OnDraw()11131114if (event.ControlDown() & event.ShiftDown() & (self.action == 'drag')):1115self.MoveGrap(event)1116self.OnDraw()1117event.Skip()11181119elif (self.action == 'drag'):1120self.EndGrap(event)1121self.action == ''1122event.Skip()11231124def unproject(self, event):1125"""Get the world coordinates for viewCoordinate for the event1126"""1127mousex, mousey = event.GetPosition()1128x = mousex1129y = self.g_Height-mousey11301131modelviewmatrix = glGetDoublev(GL_MODELVIEW_MATRIX)1132projectionmatrix = glGetDoublev(GL_PROJECTION_MATRIX)1133viewport = glGetInteger(GL_VIEWPORT)1134z = 0.01135worldCoordinate_near = np.array(gluUnProject(1136x, y, z,1137modelviewmatrix,1138projectionmatrix,1139viewport,), dtype=np.float32)1140z = 1.01141worldCoordinate_far = np.array(gluUnProject(1142x, y, z,1143modelviewmatrix,1144projectionmatrix,1145viewport,), dtype=np.float32)11461147v_inter = self.get_intersection(worldCoordinate_near, worldCoordinate_far)1148return v_inter11491150def BeginGrap(self, event):11511152self.xStart, self.yStart = event.GetPosition()1153# print 'BeginGrap',self.xStart,self.yStart11541155def MoveGrap(self, event):1156x, y = event.GetPosition()11571158self.xTrans += x-self.xStart1159self.yTrans += y-self.yStart1160# print 'MoveGrap',self.xTrans,self.yTrans1161self.xStart, self.yStart = x, y11621163def EndGrap(self, event):1164# print 'EndGrap'1165self.canvas.SetCursor(wx.NullCursor)1166self.action = ''11671168#1169# Canvas Proxy Methods11701171def GetGLExtents(self):1172"""Get the extents of the OpenGL canvas."""1173return self.canvas.GetClientSize()11741175def SwapBuffers(self):1176"""Swap the OpenGL buffers."""1177self.canvas.SwapBuffers()11781179#1180# wxPython Window Handlers11811182def processEraseBackgroundEvent(self, event):1183"""Process the erase background event."""1184pass # Do nothing, to avoid flashing on MSWin11851186def processSizeEvent(self, event=None):1187"""Process the resize event."""1188if self.canvas.GetContext():1189# Make sure the frame is shown before calling SetCurrent.1190self.Show()1191self.canvas.SetCurrent()11921193size = self.GetGLExtents()1194self.OnReshape(size.width, size.height)1195self.canvas.Refresh(False)1196if event:1197event.Skip()11981199def processPaintEvent(self, event):1200"""Process the drawing event."""1201self.canvas.SetCurrent()12021203# This is a 'perfect' time to initialize OpenGL ... only if we need to1204if not self.GLinitialized:1205self.OnInitGL()1206self.GLinitialized = True12071208self.OnDraw()1209event.Skip()12101211#1212# GLFrame OpenGL Event Handlers12131214def OnInitGL(self):1215"""Initialize OpenGL for use in the window."""1216glClearColor(0, 0, 0, 1)12171218def OnReshape(self, width, height):1219"""Reshape the OpenGL viewport based on the dimensions of the window."""1220#global g_Width, g_Height1221self.g_Width = width1222self.g_Height = height1223glViewport(0, 0, self.g_Width, self.g_Height)12241225def OnDraw(self, *args, **kwargs):1226"""Draw the window."""1227# Clear frame buffer and depth buffer1228glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)1229# Set up viewing transformation, looking down -Z axis1230glLoadIdentity()1231gluLookAt(self.eyex, self.eyey, self.eyez, self.centerx, self.centery,1232self.centerz, self.upx, self.upy, self.upz) # -.1,0,012331234# Set perspective (also zoom)1235glMatrixMode(GL_PROJECTION)1236glLoadIdentity()1237# the window corner OpenGL coordinates are (-+1, -+1)1238glOrtho(-1, 1, 1, -1, -1, 1)12391240aspect = float(self.g_Width)/float(self.g_Height)12411242gluPerspective(self.zoom, aspect, self.g_nearPlane, self.g_farPlane)1243glMatrixMode(GL_MODELVIEW)1244self.polarView()12451246# draw actual scene1247for element in self._elements:1248element.draw()12491250self.SwapBuffers()12511252def polarView(self):1253glTranslatef(self.yTrans/100., 0.0, 0.0)1254glTranslatef(0.0, -self.xTrans/100., 0.0)1255glRotatef(-self.zRotate, 0.0, 0.0, 1.0)1256glRotatef(-self.xRotate, 1.0, 0.0, 0.0)1257glRotatef(-self.yRotate, .0, 1.0, 0.0)125812591260class WxGLTest2(glcanvas.GLCanvas):1261def __init__(self, parent, mainframe=None):1262if mainframe is None:1263self._mainframe = parent1264else:1265self._mainframe = mainframe12661267self._elements = []1268self.elements_selected = []12691270self.eyex = 0.01271self.eyey = 0.01272self.eyez = -9.012731274self.centerx = 0.01275self.centery = 0.01276self.centerz = 0.012771278self.upx = -1.01279self.upy = 0.01280self.upz = 0.012811282self.g_Width = 6001283self.g_Height = 60012841285self.g_nearPlane = 1.1286self.g_farPlane = 1000.12871288self.action = ""1289self.xStart = self.yStart = 0.1290self.xStart1291self.zoom = 65.12921293self.xRotate = 0.1294self.yRotate = 0.1295self.zRotate = 0.12961297self.xTrans = 0.1298self.yTrans = 0.12991300#1301# Forcing a specific style on the window.1302# Should this include styles passed?1303style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE13041305attribList = (glcanvas.WX_GL_RGBA, # RGBA1306glcanvas.WX_GL_DOUBLEBUFFER, # Double Buffered1307glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit13081309glcanvas.GLCanvas.__init__(self, parent, -1, attribList=attribList)1310#super(WxGLTest2, self).__init__(parent,-1, attribList=attribList)13111312self.GLinitialized = False13131314###1315# Forcing a specific style on the window.1316# Should this include styles passed?1317#style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE13181319#super(GLFrame, self).__init__(parent, id, title, pos, size, style, name)1320#wx.Frame.__init__(self, parent, id, title, pos, size, style, name)13211322#1323# Set the event handlers.1324self.Bind(wx.EVT_ERASE_BACKGROUND, self.processEraseBackgroundEvent)1325self.Bind(wx.EVT_SIZE, self.OnSize)1326self.Bind(wx.EVT_PAINT, self.processPaintEvent)13271328self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)1329self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)1330self.Bind(wx.EVT_MOTION, self.OnMotion)1331self.Bind(wx.EVT_MOUSEWHEEL, self.OnWheel)13321333# this is needed to initialize GL projections for unproject1334wx.CallAfter(self.OnSize)13351336def add_element(self, element):1337self._elements.append(element)1338self.OnDraw()13391340def resetView():1341self.zoom = 65.1342self.xRotate = 0.1343self.yRotate = 0.1344self.zRotate = 0.1345self.xTrans = 0.1346self.yTrans = 0.1347self.OnDraw()13481349def OnWheel(self, event):1350#EventType = FloatCanvas.EVT_FC_MOUSEWHEEL1351#1352Rot = event.GetWheelRotation()1353# print 'OnWheel!!',Rot,event.ControlDown(),event.ShiftDown()1354if event.ControlDown(): # event.ControlDown(): # zoom1355if Rot < 0:1356self.zoom *= 0.91357else:1358self.zoom *= 1.11359self.OnDraw()1360event.Skip()13611362def OnLeftDown(self, event):1363##1364if (event.ControlDown() & event.ShiftDown()) & (self.action == ''):1365self.action = 'drag'1366self.BeginGrap(event)1367event.Skip()13681369def OnLeftUp(self, event):1370if self.action == 'drag':1371self.EndGrap(event)1372self.action == ''1373event.Skip()13741375def get_intersection(self, v_near, v_far):1376# 1509181377# idea from http://www.bfilipek.com/2012/06/select-mouse-opengl.html1378# https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection1379d = -v_near + v_far13801381t = -v_near[2]/d[2]1382v_inter = v_near+t*d13831384return v_inter13851386def OnMotion(self, event):13871388p = self.unproject(event)[0:2]1389for element in self._elements:1390inds_pick = element.pick(p)1391element.highlight(inds_pick)13921393self.OnDraw()13941395if (event.ControlDown() & event.ShiftDown() & (self.action == 'drag')):1396self.MoveGrap(event)1397self.OnDraw()1398event.Skip()13991400elif (self.action == 'drag'):1401self.EndGrap(event)1402self.action == ''1403event.Skip()14041405def unproject(self, event):1406"""Get the world coordinates for viewCoordinate for the event1407"""1408mousex, mousey = event.GetPosition()1409x = mousex1410y = self.g_Height-mousey14111412modelviewmatrix = glGetDoublev(GL_MODELVIEW_MATRIX)1413projectionmatrix = glGetDoublev(GL_PROJECTION_MATRIX)1414viewport = glGetInteger(GL_VIEWPORT)1415z = 0.01416worldCoordinate_near = np.array(gluUnProject(1417x, y, z,1418modelviewmatrix,1419projectionmatrix,1420viewport,), dtype=np.float32)1421z = 1.01422worldCoordinate_far = np.array(gluUnProject(1423x, y, z,1424modelviewmatrix,1425projectionmatrix,1426viewport,), dtype=np.float32)14271428v_inter = self.get_intersection(worldCoordinate_near, worldCoordinate_far)1429return v_inter14301431def BeginGrap(self, event):14321433self.xStart, self.yStart = event.GetPosition()1434# print 'BeginGrap',self.xStart,self.yStart14351436def MoveGrap(self, event):1437x, y = event.GetPosition()14381439self.xTrans += x-self.xStart1440self.yTrans += y-self.yStart1441# print 'MoveGrap',self.xTrans,self.yTrans1442self.xStart, self.yStart = x, y14431444def EndGrap(self, event):1445# print 'EndGrap'1446self.SetCursor(wx.NullCursor)1447self.action = ''14481449#1450# Canvas Proxy Methods14511452def GetGLExtents(self):1453"""Get the extents of the OpenGL canvas."""1454return self.GetClientSize()14551456# def SwapBuffers(self):1457# """Swap the OpenGL buffers."""1458# self.SwapBuffers()14591460#1461# wxPython Window Handlers14621463def processEraseBackgroundEvent(self, event):1464"""Process the erase background event."""1465pass # Do nothing, to avoid flashing on MSWin14661467def OnSize(self, event=None, win=None):1468"""Process the resize event."""1469if self.GetContext():1470# Make sure the frame is shown before calling SetCurrent.1471self.Show()1472self.SetCurrent()14731474size = self.GetGLExtents()1475self.OnReshape(size.width, size.height)1476self.Refresh(False)1477if event:1478event.Skip()14791480def processPaintEvent(self, event):1481"""Process the drawing event."""1482self.SetCurrent()14831484# This is a 'perfect' time to initialize OpenGL ... only if we need to1485if not self.GLinitialized:1486self.OnInitGL()1487self.GLinitialized = True14881489self.OnDraw()1490event.Skip()14911492#1493# GLFrame OpenGL Event Handlers14941495def OnInitGL(self):1496"""Initialize OpenGL for use in the window."""1497glClearColor(0, 0, 0, 1)14981499def OnReshape(self, width, height):1500"""Reshape the OpenGL viewport based on the dimensions of the window."""1501#global g_Width, g_Height1502self.g_Width = width1503self.g_Height = height1504glViewport(0, 0, self.g_Width, self.g_Height)15051506def OnDraw(self, *args, **kwargs):1507"""Draw the window."""1508# Clear frame buffer and depth buffer1509glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)1510# Set up viewing transformation, looking down -Z axis1511glLoadIdentity()1512gluLookAt(self.eyex, self.eyey, self.eyez, self.centerx, self.centery,1513self.centerz, self.upx, self.upy, self.upz) # -.1,0,015141515# Set perspective (also zoom)1516glMatrixMode(GL_PROJECTION)1517glLoadIdentity()1518# the window corner OpenGL coordinates are (-+1, -+1)1519glOrtho(-1, 1, 1, -1, -1, 1)15201521aspect = float(self.g_Width)/float(self.g_Height)15221523gluPerspective(self.zoom, aspect, self.g_nearPlane, self.g_farPlane)1524glMatrixMode(GL_MODELVIEW)1525self.polarView()15261527# draw actual scene1528for element in self._elements:1529element.draw()1530# causes bad things :AttributeError: 'Implementation' object has no attribute 'glGenBuffers'15311532self.SwapBuffers()15331534def polarView(self):1535glTranslatef(self.yTrans/100., 0.0, 0.0)1536glTranslatef(0.0, -self.xTrans/100., 0.0)1537glRotatef(-self.zRotate, 0.0, 0.0, 1.0)1538glRotatef(-self.xRotate, 1.0, 0.0, 0.0)1539glRotatef(-self.yRotate, .0, 1.0, 0.0)154015411542class GlEditorSash(wx.SplitterWindow):15431544def __init__(self, parent,1545mainframe=None,1546size=wx.DefaultSize,1547is_menu=False, # create menu items1548Debug=0,1549):15501551wx.SplitterWindow.__init__(self, parent, wx.ID_ANY,1552style=wx.SP_LIVE_UPDATE,1553size=size)1554self.log = log15551556self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnSashChanged)1557self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGING, self.OnSashChanging)15581559# id=wx.ID_ANY1560# pixel_snap=10 # radius in pixels in which a point is selected1561# n_test=51562# wx.Window.__init__(self,parent,id,wx.DefaultPosition,wx.DefaultSize,wx.SUNKEN_BORDER|wx.WANTS_CHARS)1563# wx.Panel.__init__(self,parent,id,wx.DefaultPosition,size,wx.SUNKEN_BORDER|wx.WANTS_CHARS)1564# self.parent=parent1565self._mainframe = mainframe # mainframe1566#splitter = Splitter(self)15671568self._toolspanel = ToolPalett(self)1569self._toolspanel.add_tool(BaseTool(self))1570#sty = wx.BORDER_SUNKEN1571#self._toolspanel = wx.Window(self, style=sty)1572# self._toolspanel.SetBackgroundColour("pink")1573#wx.StaticText(self._toolspanel, -1, "Object", (50,50))15741575self._canvas = WxGLTest2(self)1576#p2 = wx.Window(self, style=sty)1577# p2.SetBackgroundColour("blue")1578#wx.StaticText(p2, -1, "GLeditor", (50,50))15791580#self.canvas = wx.Window(splitter, style=sty)1581# self.canvas.SetBackgroundColour("green")1582#wx.StaticText(self.canvas, -1, "Panel two", (50,50))15831584#self.canvas = WxGLTest2(splitter)1585#self.canvas = WxGLTest_orig(splitter)15861587#nbpanel = wx.Panel(splitter)1588#self._viewtabs = wx.Notebook(nbpanel,wx.ID_ANY, style=wx.CLIP_CHILDREN)1589#sizer = wx.BoxSizer(wx.VERTICAL)1590#sizer.Add(self._viewtabs, 1, wx.ALL|wx.EXPAND, 5)1591# nbpanel.SetSizer(sizer)1592# self.Layout()15931594# finally, put the notebook in a sizer for the panel to manage1595# the layout1596#sizer = wx.BoxSizer()1597#sizer.Add(self._viewtabs, 1, wx.EXPAND)1598# self.SetSizer(sizer)15991600self.SetMinimumPaneSize(20)1601#splitter.SplitVertically(p1, self.canvas, -100)1602self.SplitVertically(self._toolspanel, self._canvas, -100)16031604#wx.EVT_SIZE (self, self.on_size)1605self.SetSashPosition(500, True)1606# sizer=wx.BoxSizer(wx.VERTICAL)1607# sizer.Add(p1,0, wx.ALL | wx.ALIGN_LEFT | wx.GROW, 4)# from NaviPanelTest1608# sizer.Add(self.canvas,1,wx.GROW)# from NaviPanelTest16091610# finish panel setup1611# self.SetSizer(sizer)1612# sizer.Fit(self)1613# self.on_size()1614# self.Show()16151616def get_canvas(self):1617return self._canvas16181619def OnSashChanged(self, evt):1620#print("sash changed to %s\n" % str(evt.GetSashPosition()))1621pass16221623def OnSashChanging(self, evt):1624print("sash changing to %s\n" % str(evt.GetSashPosition()))1625# uncomment this to not allow the change1626# evt.SetSashPosition(-1)1627# evt.SetSashPosition(210)1628# self.canvas.OnSize()1629pass16301631def on_size(self, event=None):1632# self.tc.SetSize(self.GetSize())1633# self.tc.SetSize(self.GetSize())1634# self._viewtabs.SetSize(self.GetSize())1635# pass1636#wx.LayoutAlgorithm().LayoutWindow(self, self.p1)1637#wx.LayoutAlgorithm().LayoutWindow(self, self.p1)16381639# important:1640#wx.LayoutAlgorithm().LayoutWindow(self, self._viewtabs)16411642if event:1643event.Skip()164416451646class GlEditor(wx.Panel):16471648def __init__(self, parent,1649mainframe=None,1650size=wx.DefaultSize,1651is_menu=False, # create menu items1652Debug=0,1653):16541655wx.Panel.__init__(self, parent, wx.ID_ANY, size=size)1656sizer = wx.BoxSizer(wx.HORIZONTAL)16571658self._mainframe = mainframe16591660self._toolspanel = ToolsPanel(self)1661for i in range(5):1662self._toolspanel.add_tool(BaseTool(self))1663self._toolspanel.add_tool(DelTool(self))1664#sty = wx.BORDER_SUNKEN1665#self._toolspanel = wx.Window(self, style=sty)1666# self._toolspanel.SetBackgroundColour("pink")1667#wx.StaticText(self._toolspanel, -1, "Object", (50,50))16681669self._canvas = WxGLTest2(self)1670#p2 = wx.Window(self, style=sty)1671# p2.SetBackgroundColour("blue")1672#wx.StaticText(p2, -1, "GLeditor", (50,50))16731674sizer.Add(self._toolspanel, 0, wx.ALL | wx.ALIGN_LEFT | wx.GROW, 4) # from NaviPanelTest1675sizer.Add(self._canvas, 1, wx.GROW) # from NaviPanelTest16761677# finish panel setup1678self.SetSizer(sizer)1679sizer.Fit(self)16801681def get_canvas(self):1682return self._canvas16831684def on_size(self, event=None):1685# self.tc.SetSize(self.GetSize())1686# self.tc.SetSize(self.GetSize())1687# self._viewtabs.SetSize(self.GetSize())1688# pass1689#wx.LayoutAlgorithm().LayoutWindow(self, self.p1)1690#wx.LayoutAlgorithm().LayoutWindow(self, self.p1)16911692# important:1693#wx.LayoutAlgorithm().LayoutWindow(self, self._viewtabs)16941695if event:1696event.Skip()169716981699class MainSplitter(wx.SplitterWindow):1700def __init__(self, parent, ID=-1):1701wx.SplitterWindow.__init__(self, parent, ID,1702style=wx.SP_LIVE_UPDATE1703)17041705self.SetMinimumPaneSize(20)17061707#sty = wx.BORDER_SUNKEN17081709emptyobj = cm.BaseObjman('empty')1710self._objbrowser = objpanel.NaviPanel(self,1711emptyobj,1712#show_title = False1713#size = w.DefaultSize,1714#style = wx.DEFAULT_DIALOG_STYLE|wx.MAXIMIZE_BOX|wx.RESIZE_BORDER,1715# choose_id=False,choose_attr=False,1716# func_choose_id=None,1717# func_change_obj=None,1718#panelstyle = 'default',1719immediate_apply=False,1720buttons=[],1721standartbuttons=[],1722#defaultbutton = defaultbutton,1723)17241725#p1 = wx.Window(splitter, style=sty)1726# p1.SetBackgroundColour("pink")1727#wx.StaticText(p1, -1, "Object", (50,50))17281729#self.canvas = wx.Window(splitter, style=sty)1730# self.canvas.SetBackgroundColour("green")1731#wx.StaticText(self.canvas, -1, "Panel two", (50,50))1732#self.canvas = WxGLTest2(splitter)1733#self.canvas = WxGLTest_orig(splitter)17341735#self._viewtabs = wx.Notebook(self,wx.ID_ANY, style=wx.CLIP_CHILDREN)1736self._viewtabs = wx.Notebook(self, -1, size=(21, 21), style=wx.BK_DEFAULT1737# wx.BK_TOP1738# wx.BK_BOTTOM1739# wx.BK_LEFT1740# wx.BK_RIGHT1741# | wx.NB_MULTILINE1742)17431744#nbpanel = wx.Panel(splitter)1745#self._viewtabs = wx.Notebook(nbpanel,wx.ID_ANY, style=wx.CLIP_CHILDREN)1746#sizer = wx.BoxSizer(wx.VERTICAL)1747#sizer.Add(self._viewtabs, 1, wx.ALL|wx.EXPAND, 5)1748# nbpanel.SetSizer(sizer)1749# self.Layout()17501751# finally, put the notebook in a sizer for the panel to manage1752# the layout1753#sizer = wx.BoxSizer()1754#sizer.Add(self._viewtabs, 1, wx.EXPAND)1755# self.SetSizer(sizer)17561757#splitter.SplitVertically(self._objbrowser,self.canvas , -100)1758self.SplitVertically(self._objbrowser, self._viewtabs, -100)17591760self.SetSashPosition(500, True)1761self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnSashChanged)1762self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGING, self.OnSashChanging)17631764def add_view(self, name, ViewClass, **args):1765"""1766Add a new view to the notebook.1767"""1768# print 'context.add_view',ViewClass1769# print ' args',args1770view = ViewClass(self._viewtabs,1771mainframe=self.GetParent(),1772**args1773)17741775# Add network tab with editor1776p = self._viewtabs.AddPage(view, name.title())1777#self._views[name] = view1778# self._viewtabs.SetSelection(p)1779# self._viewtabs.Show(True)1780return view17811782def OnSashChanged(self, evt):1783#print("sash changed to %s\n" % str(evt.GetSashPosition()))1784pass17851786def OnSashChanging(self, evt):1787#print("sash changing to %s\n" % str(evt.GetSashPosition()))1788# uncomment this to not allow the change1789# evt.SetSashPosition(-1)1790# self.canvas.OnSize()1791pass179217931794class TestMainframe(AgileToolbarFrameMixin, wx.Frame):1795"""1796Simple wx frame with some special features.1797"""17981799def __init__(self, parent=None, id=-1, title='mainframe', pos=wx.DefaultPosition,1800size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE,1801name='frame'):18021803# Forcing a specific style on the window.1804# Should this include styles passed?1805style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE1806wx.Frame.__init__(self, parent, id, title, pos, size=size, style=style, name=name)1807#super(GLFrame, self).__init__(parent, id, title, pos, size, style, name)1808self._splitter = MainSplitter(self)1809self._views = {}1810#wx.EVT_SIZE (self, self.on_size)1811# sizer=wx.BoxSizer(wx.VERTICAL)1812# sizer.Add(p1,0, wx.ALL | wx.ALIGN_LEFT | wx.GROW, 4)# from NaviPanelTest1813# sizer.Add(self.canvas,1,wx.GROW)# from NaviPanelTest18141815# finish panel setup1816# self.SetSizer(sizer)1817# sizer.Fit(self)1818# self.Show()18191820# this is needed to initialize GL projections for unproject1821# wx.CallAfter(self.on_size)18221823#width,height = self.GetSize()1824#self._splitter.SetSashPosition(300, True)1825# maximize the frame1826self.Maximize()1827# self.CenterOnScreen()1828#################################################################1829# create statusbar1830#self.statusbar = AgileStatusbar(self)1831self.statusbar = AgileStatusbar(self)1832self.SetStatusBar(self.statusbar)1833# self.count=0.018341835#################################################################1836# create toolbar18371838tsize = (16, 16)1839self.init_toolbar(size=tsize)18401841#new_bmp = wx.ArtProvider.GetBitmap(wx.ART_NEW, wx.ART_TOOLBAR, tsize)1842#open_bmp = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, tsize)1843#save_bmp= wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR, tsize)1844#cut_bmp = wx.ArtProvider.GetBitmap(wx.ART_CUT, wx.ART_TOOLBAR, tsize)1845#copy_bmp = wx.ArtProvider.GetBitmap(wx.ART_COPY, wx.ART_TOOLBAR, tsize)1846#paste_bmp= wx.ArtProvider.GetBitmap(wx.ART_PASTE, wx.ART_TOOLBAR, tsize)18471848#self.add_tool('new',self.on_open,new_bmp,'create new doc')1849#self.add_tool('open',self.on_open,open_bmp,'Open doc')1850#self.add_tool('save',self.on_save,save_bmp,'Save doc')1851# self.toolbar.AddSeparator()1852# self.add_tool('cut',self.on_open,cut_bmp,'Cut')1853# self.add_tool('copy',self.on_open,copy_bmp,'Copy')1854# self.add_tool('paste',self.on_open,paste_bmp,'Paste')18551856# self.SetToolBar(self.toolbar)18571858#################################################################1859# create the menu bar18601861self.menubar = AgileMenubar(self)1862self.menubar.append_menu('file')1863self.menubar.append_menu('file/doc')18641865self.menubar.append_item('file/doc/open', self.on_open,1866shortkey='Ctrl+o', info='open it out')18671868self.menubar.append_item('file/doc/save', self.on_save,1869shortkey='Ctrl+s', info='save it out')18701871# self.menubar.append_menu('edit')1872# self.menubar.append_item('edit/cut',self.cut,\1873# shortkey='Ctrl+c',info='cut it out')18741875# self.menubar.append_item('edit/toggle',self.toggle_tools,\1876# shortkey='Ctrl+t',info='toggle tools')1877# self.menubar.append_menu('tools')1878self.SetMenuBar(self.menubar)1879# self.Show(True) #NO!!18801881def add_view(self, name, ViewClass, **args):1882"""1883Add a new view to the notebook.1884"""1885# print 'context.add_view',ViewClass1886# print ' args',args18871888view = self._splitter.add_view(name, ViewClass, **args)1889self._views[name] = view1890# self._viewtabs.SetSelection(p)1891# self._splitter._viewtabs.Show(True)1892return view18931894def on_size(self, event=None):1895print 'Mainframe.on_size'1896# self.tc.SetSize(self.GetSize())1897# self.tc.SetSize(self.GetSize())1898# self._viewtabs.SetSize(self.GetSize())1899# pass1900#wx.LayoutAlgorithm().LayoutWindow(self, self.p1)1901#wx.LayoutAlgorithm().LayoutWindow(self, self.p1)19021903# important:1904#wx.LayoutAlgorithm().LayoutWindow(self, self._viewtabs)1905wx.LayoutAlgorithm().LayoutWindow(self, self._splitter)1906if event:1907event.Skip()19081909def on_save(self, event):1910print 'save it!!'19111912def on_open(self, event):1913"""Open a document"""1914#wildcards = CreateWildCards() + "All files (*.*)|*.*"1915print 'open it!!'19161917def destroy(self):1918"""Destroy this object"""1919# self.theDocManager.theDestructor()1920#imgPreferences.saveXml(self.GetStartDirectory() + "/" + imgINI_FILE_NAME)1921##del self.thePrint1922self.Destroy()19231924def on_close(self, event):1925# self.Close(True)1926# pass1927self.destroy()19281929def on_exit(self, event):1930"""Called when the application is to be finished"""1931self.destroy()19321933def on_idle(self, event):1934pass1935#self.count = self.count + 11936# if self.count >= 100:1937# self.count = 019381939# self.statusbar.set_progress(self.count)19401941def on_about(self, event):1942"""Display the information about this application"""1943#dlg = imgDlgAbout(self, -1, "")1944# dlg.ShowModal()1945# dlg.Destroy()1946pass194719481949linewidth = 31950vertices = [1951[[0.0, 0.0, 0.0], [0.2, 0.0, 0.0]], # 0 green1952[[0.0, 0.0, 0.0], [0.0, 0.9, 0.0]], # 1 red1953]195419551956colors = [1957[0.0, 0.9, 0.0, 0.9], # 01958[0.9, 0.0, 0.0, 0.9], # 11959]1960lines = Lines(linewidth=linewidth, vertices=vertices, colors=colors)19611962linewidth2 = 31963vertices2 = [1964[[0.5, 0.5, 0.0], [0.7, 0.5, 0.0], [0.7, 1.0, 0.0]], # 0 green1965[[0.8, 0.5, 0.0], [0.9, 0.8, 0.0], [0.8, 0.2, 0.0]], # 1 orange1966]1967colors2 = [1968[0.0, 0.9, 0.3, 0.9], # 01969[0.9, 0.3, 0.0, 0.9], # 11970]1971triangles = Triangles(linewidth=linewidth2, vertices=vertices2, colors=colors2)19721973linewidth3 = 31974vertices3 = [1975[[0.5, 0.0, 0.0], [0.7, 0.0, 0.0], [0.7, 0.3, 0.0], [0.5, 0.3, 0.0], ], # 01976[[0.1, 0.0, 0.0], [0.3, 0.0, 0.0], [0.3, 0.2, 0.0], [0.1, 0.2, 0.0], ], # 11977]1978colors3 = [1979[0.8, 0.0, 0.8, 0.9], # 01980[0.0, 0.6, 0.6, 0.9], # 11981]1982rectangles = Rectangles(linewidth=linewidth3, vertices=vertices3, colors=colors3)19831984if __name__ == '__main__':19851986app = wx.PySimpleApp()19871988if 1:19891990frame = TestMainframe()1991gleditor = frame.add_view('GL Editor', GlEditor)1992#gleditor = frame._splitter.add_view('GL Editor',GlEditor)1993frame.Show()1994frame.on_size()1995canvas = gleditor.get_canvas()1996canvas.add_element(lines)1997canvas.add_element(triangles)1998canvas.add_element(rectangles)19992000app.SetTopWindow(frame)2001app.MainLoop()20022003app.Destroy()200420052006