;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasLight::toggle ;toggles a light on or off depending upon its state if self.on eq 1 then begin self.on = 0 ;turn it off self.oPoly->setProperty,hide=1 endif else begin self.on = 1 ;turn it on self.oPoly->setProperty,hide=0 endelse return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| function christmasLight::init ;initialization for the individual light on the tree ;initialize the super class if (self->IDLgrModel::init(_extra=extra) ne 1) then return, 0 ;y goes from -0.5 to +0.75 so height = 1.25 and is offset by -0.5 ;radius goes from 0 to 0.5, theta from 0 to 2pi ;choose random y, radius and theta height = 1.25 y = (randomu(seed,1) * 1.25) radius = 0.5 theta = randomu(seed,1) * 2. * !pi ;now we can determine x and z so that light will fit on surface of the "tree" x = ((height-y)/height) * radius * cos(theta) z = ((height-y)/height) * radius * sin(theta) mesh_obj,4,verts, conn, Replicate(0.03 ,20,20) ;.03 is the size of the light verts[0,*] = verts[0,*] + x[0] verts[1,*] = verts[1,*] + y[0] - 0.5 verts[2,*] = verts[2,*] + z[0] color = [randomu(seed,1)*256,randomu(seed,1)*256,randomu(seed,1)*256] self.oPoly = obj_new('IDLgrPolygon',data=verts,polygons=conn,color=color,shading=0) self->add,self.oPoly ;light is created on self.on = 1 return,1 end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasLight::cleanup ;cleanup routine obj_destroy,self.oPoly return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasLight__define ;definition of the christmasLight object void = {christmasLight, $ inherits IDLgrModel, $ oPoly : obj_new(), $ ;object holder on : 0 } ;on or off flag return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| ; CHRISTMAS TREE CODE FROM HERE DOWN ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasTreeExit,event ;called from the pull down menu widget_control,event.top,/destroy return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasCleanup, base ;called no matter how the GUI is destroyed widget_control,base,get_uvalue=object obj_destroy,object return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasTree_event,event ;event handler for the top base widget_control,event.top, get_uvalue=object eventType = tag_names(event, /struct) ;find out what it is case eventType of ;resize events go here and keep the window square 'WIDGET_BASE' : object->resize, newSize = (event.x + event.y)/2 'WIDGET_TIMER':begin ;this timer rotates the tree object->turnTheTree widget_control,event.top,timer=1 ;set the timer again end else: end return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro blinkTheLights,event ;handles the timer events for the lights widget_control,event.top, get_uvalue=object object->blinkTheLights widget_control,event.id,timer=0.1 ;set the light timer return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasTree::blinkTheLights ;picks a random light to toggle on or off ranIndex = long(randomu(seed,1) * self.nLights) (*self.oLightArrayPtr)[ranIndex[0]]->toggle self.oWindow->Draw, self.oView return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasTree::resize, newSize=newSize ;resizes the draw widget and redraws the view widget_control,self.drawId,draw_xsize=newSize,draw_ysize=newSize self.oWindow->Draw, self.oView return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasTree::turnTheTree ;rotates the tree by 10 degrees each time around the y axis self.oRotateModel->rotate,[0,1,0],10 self.oWindow->Draw, self.oView return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| function christmasTree::init, nlights=nlights ;initialization routine for the christmas tree if not keyword_set(nlights) then nlights=50 ;initialize the super class if (self->IDLgrModel::init(_extra=extra) ne 1) then return, 0 ;Get the screen size. device, get_screen_size = screenSize xdim = screenSize[0]*.50 ;about 50 percent of the screen size ydim=xdim ;keep isotropic base=widget_base(title='Christmas Tree',column=1,/tlb_size_events,mbar=barBase) ;pull down menu next fileId = widget_button(barBase, value='File', /menu) void = widget_button(fileId, /separator, value='Exit', $ event_pro='christmasTreeExit') self.drawId=widget_draw(base, xsize=xdim, ysize=ydim, event_pro='blinkTheLights',$ graphics_level=2, retain=0, /expose_events) widget_control, base, /realize widget_control, hourglass=1 widget_control, self.drawId, get_value=oWindow self.oWindow=oWindow ;create view object. self.oView = obj_new('IDLgrView', projection=1, eye=1.1, $ color=[0,0,0], view=[-1,-1,2,2], zclip=[1,-1]) self.oRotateModel = obj_new('IDLgrModel') ;need a model to rotate ;outside of tree first array1 = [[0.5,-0.5,0.0],[0.0,0.75,0.0]] p1=36 p2=[0.0, 0.0, 0.0] p3=[0,1,0] mesh_obj, 6, verts, conn, array1,p1=p1, p2=p2, p3=p3 oPoly1 = obj_new('IDLgrPolygon',data=verts,polygons=conn,color=[0,255,0],shading=0,hide=0) ;trunk now array2 = [[0.15,-0.75,0],[0.15,0.15,0]] mesh_obj,6,tverts,tconn,array2,p1=p1, p2=p2, p3=p3 oPoly2 = obj_new('IDLgrPolygon',data=tverts,polygons=tconn,color=[105,58,42],shading=1,hide=0) ;add the objects to the model self.oRotateModel->add, oPoly1 self.oRotateModel->add, oPoly2 ;add the rotating model to the view self.oView -> add, self.oRotateModel ;don't want light sources to rotate so give them a separate model oLightModel = obj_new('IDLgrModel') oLight1 = obj_new('IDLgrLight',direction=[0,0,0],location=[0,0,1],type=2, $ color=[255,255,255],hide=0) oLight2 = obj_new('IDLgrLight', direction=[1,0,0],location=[-1,1,0],type=1, $ color=[255,255,255],intensity=0.5) oLightModel->add,oLight1 oLightModel->add,oLight2 ;add some text that will not rotate displayText = ['M','E','R','R','Y','C','H','R','I','S','T','M','A','S'] numDisplay = n_elements(displayText) xPos = ((findgen(numDisplay)/(numDisplay-1.))*1.5) - 0.75 ;from -.25 to .75 yPos = (sin((findgen(numDisplay)/(numDisplay-1.))*!pi)*(-0.5)) - 0.5 ;-.5 to -1 zPos = fltarr(numDisplay) + 0.5 oText = obj_new('IDLgrText',string=displayText,location=transpose([[xPos],[yPos],[zPos]]), $ color=[255,0,0],char_dim=[.15,.15]) oLightModel->add,oText self.oView-> add, oLightModel ;add the blinking lights oLightArray = objarr(nLights) for i=0,nLights-1 do begin oLightArray[i] = obj_new('christmasLight') self.oRotateModel->add,oLightArray[i] endfor self.nLights = nLights self.oLightArrayPtr = ptr_new(oLightArray,/no_copy) self.oWindow->Draw, self.oView ;store objects for cleanup self.oContainer = obj_new('IDL_Container') self.oContainer -> add, oPoly1 self.oContainer -> add, oPoly2 self.oContainer-> add,oLight1 self.oContainer-> add,oLight2 self.oContainer-> add,oText self.oContainer-> add, oLightModel ;store the object reference in the base widget_control, base,set_uvalue=self widget_control,self.drawId, timer=0.1 ;start the timer event for the lights widget_control,base,timer=1.0 ;timer for rotating the tree xmanager,'christmasTree',base,/no_block,cleanup='christmasCleanup' return,1 end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasTree::cleanup ;cleanup routine for the christmas tree object if obj_valid(self.oContainer) then obj_destroy,self.oContainer if ptr_valid(self.oLightArrayPtr) then begin obj_destroy,*self.oLightArrayPtr ptr_free,self.oLightArrayPtr endif if obj_valid(self.oWindow) then obj_destroy,self.oWindow if obj_valid(self.oView) then obj_destroy,self.oView if obj_valid(self.oRotateModel) then obj_destroy, self.oRotateModel return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasTree__define ;defintion routine for the christmas tree object void = {christmasTree, $ inherits IDLgrmodel, $ oLightArrayPtr : ptr_new(), $ nLights : 0, $ drawId : 0L, $ oRotateModel : obj_new(), $ oWindow : obj_new(), $ oView : obj_new(), $ oContainer : obj_new()} return end ;{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:|{{:| pro christmasTree, nlights=nlights ;driver program for the christmas tree object oTree = obj_new('christmastree',nlights=nlights) return end