Ejemplo n.º 1
0
class HtmlView(DirectObject):
    notify = DirectNotifyGlobal.directNotify.newCategory('HtmlView')
    useHalfTexture = base.config.GetBool('news-half-texture', 0)

    def __init__(self, parent=aspect2d):
        global GlobalWebcore
        self.parent = parent
        self.mx = 0
        self.my = 0
        self.htmlFile = 'index.html'
        self.transparency = False
        if GlobalWebcore:
            pass
        else:
            GlobalWebcore = AwWebCore(AwWebCore.LOGVERBOSE, True,
                                      AwWebCore.PFBGRA)
            GlobalWebcore.setBaseDirectory('.')
            for errResponse in xrange(400, 600):
                GlobalWebcore.setCustomResponsePage(errResponse, 'error.html')

        self.webView = GlobalWebcore.createWebView(WEB_WIDTH, WEB_HEIGHT,
                                                   self.transparency, False,
                                                   70)
        frameName = ''
        inGameNewsUrl = self.getInGameNewsUrl()
        self.imgBuffer = array.array('B')
        for i in xrange(WEB_WIDTH * WEB_HEIGHT):
            self.imgBuffer.append(0)
            self.imgBuffer.append(0)
            self.imgBuffer.append(0)
            self.imgBuffer.append(255)

        if self.useHalfTexture:
            self.leftBuffer = array.array('B')
            for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT):
                self.leftBuffer.append(0)
                self.leftBuffer.append(0)
                self.leftBuffer.append(0)
                self.leftBuffer.append(255)

            self.rightBuffer = array.array('B')
            for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT):
                self.rightBuffer.append(0)
                self.rightBuffer.append(0)
                self.rightBuffer.append(0)
                self.rightBuffer.append(255)

        self.setupTexture()
        if self.useHalfTexture:
            self.setupHalfTextures()
        self.accept('mouse1', self.mouseDown, [AwWebView.LEFTMOUSEBTN])
        self.accept('mouse3', self.mouseDown, [AwWebView.RIGHTMOUSEBTN])
        self.accept('mouse1-up', self.mouseUp, [AwWebView.LEFTMOUSEBTN])
        self.accept('mouse3-up', self.mouseUp, [AwWebView.RIGHTMOUSEBTN])

    def getInGameNewsUrl(self):
        result = base.config.GetString(
            'fallback-news-url',
            'http://cdn.toontown.disney.go.com/toontown/en/gamenews/')
        override = base.config.GetString('in-game-news-url', '')
        if override:
            self.notify.info(
                'got an override url,  using %s for in a game news' % override)
            result = override
        else:
            try:
                launcherUrl = base.launcher.getValue('GAME_IN_GAME_NEWS_URL',
                                                     '')
                if launcherUrl:
                    result = launcherUrl
                    self.notify.info(
                        'got GAME_IN_GAME_NEWS_URL from launcher using %s' %
                        result)
                else:
                    self.notify.info(
                        'blank GAME_IN_GAME_NEWS_URL from launcher, using %s' %
                        result)
            except:
                self.notify.warning(
                    'got exception getting GAME_IN_GAME_NEWS_URL from launcher, using %s'
                    % result)

        return result

    def setupTexture(self):
        cm = CardMaker('quadMaker')
        cm.setColor(1.0, 1.0, 1.0, 1.0)
        aspect = base.camLens.getAspectRatio()
        htmlWidth = 2.0 * aspect * WEB_WIDTH_PIXELS / float(WIN_WIDTH)
        htmlHeight = 2.0 * float(WEB_HEIGHT_PIXELS) / float(WIN_HEIGHT)
        cm.setFrame(-htmlWidth / 2.0, htmlWidth / 2.0, -htmlHeight / 2.0,
                    htmlHeight / 2.0)
        bottomRightX = WEB_WIDTH_PIXELS / float(WEB_WIDTH + 1)
        bottomRightY = WEB_HEIGHT_PIXELS / float(WEB_HEIGHT + 1)
        cm.setUvRange(Point2(0, 1 - bottomRightY), Point2(bottomRightX, 1))
        card = cm.generate()
        self.quad = NodePath(card)
        self.quad.reparentTo(self.parent)
        self.guiTex = Texture('guiTex')
        self.guiTex.setupTexture(Texture.TT2dTexture, WEB_WIDTH, WEB_HEIGHT, 1,
                                 Texture.TUnsignedByte, Texture.FRgba)
        self.guiTex.setMinfilter(Texture.FTLinear)
        self.guiTex.setKeepRamImage(True)
        self.guiTex.makeRamImage()
        self.guiTex.setWrapU(Texture.WMRepeat)
        self.guiTex.setWrapV(Texture.WMRepeat)
        ts = TextureStage('webTS')
        self.quad.setTexture(ts, self.guiTex)
        self.quad.setTexScale(ts, 1.0, -1.0)
        self.quad.setTransparency(0)
        self.quad.setTwoSided(True)
        self.quad.setColor(1.0, 1.0, 1.0, 1.0)
        self.calcMouseLimits()

    def setupHalfTextures(self):
        self.setupLeftTexture()
        self.setupRightTexture()
        self.fullPnmImage = PNMImage(WEB_WIDTH, WEB_HEIGHT, 4)
        self.leftPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4)
        self.rightPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4)

    def setupLeftTexture(self):
        cm = CardMaker('quadMaker')
        cm.setColor(1.0, 1.0, 1.0, 1.0)
        aspect = base.camLens.getAspectRatio()
        htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH)
        htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT)
        cm.setFrame(-htmlWidth / 2.0, 0, -htmlHeight / 2.0, htmlHeight / 2.0)
        card = cm.generate()
        self.leftQuad = NodePath(card)
        self.leftQuad.reparentTo(self.parent)
        self.leftGuiTex = Texture('guiTex')
        self.leftGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH,
                                     WEB_HEIGHT, 1, Texture.TUnsignedByte,
                                     Texture.FRgba)
        self.leftGuiTex.setKeepRamImage(True)
        self.leftGuiTex.makeRamImage()
        self.leftGuiTex.setWrapU(Texture.WMClamp)
        self.leftGuiTex.setWrapV(Texture.WMClamp)
        ts = TextureStage('leftWebTS')
        self.leftQuad.setTexture(ts, self.leftGuiTex)
        self.leftQuad.setTexScale(ts, 1.0, -1.0)
        self.leftQuad.setTransparency(0)
        self.leftQuad.setTwoSided(True)
        self.leftQuad.setColor(1.0, 1.0, 1.0, 1.0)

    def setupRightTexture(self):
        cm = CardMaker('quadMaker')
        cm.setColor(1.0, 1.0, 1.0, 1.0)
        aspect = base.camLens.getAspectRatio()
        htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH)
        htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT)
        cm.setFrame(0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0)
        card = cm.generate()
        self.rightQuad = NodePath(card)
        self.rightQuad.reparentTo(self.parent)
        self.rightGuiTex = Texture('guiTex')
        self.rightGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH,
                                      WEB_HEIGHT, 1, Texture.TUnsignedByte,
                                      Texture.FRgba)
        self.rightGuiTex.setKeepRamImage(True)
        self.rightGuiTex.makeRamImage()
        self.rightGuiTex.setWrapU(Texture.WMClamp)
        self.rightGuiTex.setWrapV(Texture.WMClamp)
        ts = TextureStage('rightWebTS')
        self.rightQuad.setTexture(ts, self.rightGuiTex)
        self.rightQuad.setTexScale(ts, 1.0, -1.0)
        self.rightQuad.setTransparency(0)
        self.rightQuad.setTwoSided(True)
        self.rightQuad.setColor(1.0, 1.0, 1.0, 1.0)

    def calcMouseLimits(self):
        ll = Point3()
        ur = Point3()
        self.quad.calcTightBounds(ll, ur)
        self.notify.debug('ll=%s ur=%s' % (ll, ur))
        offset = self.quad.getPos(aspect2d)
        self.notify.debug('offset = %s ' % offset)
        ll.setZ(ll.getZ() + offset.getZ())
        ur.setZ(ur.getZ() + offset.getZ())
        self.notify.debug('new LL=%s, UR=%s' % (ll, ur))
        relPointll = self.quad.getRelativePoint(aspect2d, ll)
        self.notify.debug('relPoint = %s' % relPointll)
        self.mouseLL = (aspect2d.getScale()[0] * ll[0],
                        aspect2d.getScale()[2] * ll[2])
        self.mouseUR = (aspect2d.getScale()[0] * ur[0],
                        aspect2d.getScale()[2] * ur[2])
        self.notify.debug('original mouseLL=%s, mouseUR=%s' %
                          (self.mouseLL, self.mouseUR))

    def writeTex(self, filename='guiText.png'):
        self.notify.debug('writing texture')
        self.guiTex.generateRamMipmapImages()
        self.guiTex.write(filename)

    def toggleRotation(self):
        if self.interval.isPlaying():
            self.interval.finish()
        else:
            self.interval.loop()

    def mouseDown(self, button):
        messenger.send('wakeup')
        self.webView.injectMouseDown(button)

    def mouseUp(self, button):
        self.webView.injectMouseUp(button)

    def reload(self):
        pass

    def zoomIn(self):
        self.webView.zoomIn()

    def zoomOut(self):
        self.webView.zoomOut()

    def toggleTransparency(self):
        self.transparency = not self.transparency
        self.webView.setTransparent(self.transparency)

    def update(self, task):
        if base.mouseWatcherNode.hasMouse():
            x, y = self._translateRelativeCoordinates(
                base.mouseWatcherNode.getMouseX(),
                base.mouseWatcherNode.getMouseY())
            if self.mx - x != 0 or self.my - y != 0:
                self.webView.injectMouseMove(x, y)
                self.mx, self.my = x, y
            if self.webView.isDirty():
                self.webView.render(self.imgBuffer.buffer_info()[0],
                                    WEB_WIDTH * 4, 4)
                Texture.setTexturesPower2(2)
                textureBuffer = self.guiTex.modifyRamImage()
                textureBuffer.setData(self.imgBuffer.tostring())
                if self.useHalfTexture:
                    self.guiTex.store(self.fullPnmImage)
                    self.leftPnmImage.copySubImage(self.fullPnmImage, 0, 0, 0,
                                                   0, WEB_HALF_WIDTH,
                                                   WEB_HEIGHT)
                    self.rightPnmImage.copySubImage(self.fullPnmImage, 0, 0,
                                                    WEB_HALF_WIDTH, 0,
                                                    WEB_HALF_WIDTH, WEB_HEIGHT)
                    self.leftGuiTex.load(self.leftPnmImage)
                    self.rightGuiTex.load(self.rightPnmImage)
                    self.quad.hide()
                Texture.setTexturesPower2(1)
            GlobalWebcore.update()
        return Task.cont

    def _translateRelativeCoordinates(self, x, y):
        sx = int((x - self.mouseLL[0]) / (self.mouseUR[0] - self.mouseLL[0]) *
                 WEB_WIDTH_PIXELS)
        sy = WEB_HEIGHT_PIXELS - int(
            (y - self.mouseLL[1]) /
            (self.mouseUR[1] - self.mouseLL[1]) * WEB_HEIGHT_PIXELS)
        return (sx, sy)

    def unload(self):
        self.ignoreAll()
        self.webView.destroy()
        self.webView = None
        return

    def onCallback(self, name, args):
        if name == 'requestFPS':
            pass

    def onBeginNavigation(self, url, frameName):
        pass

    def onBeginLoading(self, url, frameName, statusCode, mimeType):
        pass

    def onFinishLoading(self):
        self.notify.debug('finished loading')

    def onReceiveTitle(self, title, frameName):
        pass

    def onChangeTooltip(self, tooltip):
        pass

    def onChangeCursor(self, cursor):
        pass

    def onChangeKeyboardFocus(self, isFocused):
        pass

    def onChangeTargetURL(self, url):
        pass
Ejemplo n.º 2
0
class HtmlView(DirectObject):
    notify = DirectNotifyGlobal.directNotify.newCategory('HtmlView')
    useHalfTexture = config.GetBool('news-half-texture', 0)

    def __init__(self, parent = aspect2d):
        global GlobalWebcore
        self.parent = parent
        self.mx = 0
        self.my = 0
        self.htmlFile = 'index.html'
        self.transparency = False
        if GlobalWebcore:
            pass
        else:
            GlobalWebcore = AwWebCore(AwWebCore.LOGVERBOSE, True, AwWebCore.PFBGRA)
            GlobalWebcore.setBaseDirectory('.')
            for errResponse in xrange(400, 600):
                GlobalWebcore.setCustomResponsePage(errResponse, 'error.html')

        self.webView = GlobalWebcore.createWebView(WEB_WIDTH, WEB_HEIGHT, self.transparency, False, 70)
        frameName = ''
        inGameNewsUrl = self.getInGameNewsUrl()
        self.imgBuffer = array.array('B')
        for i in xrange(WEB_WIDTH * WEB_HEIGHT):
            self.imgBuffer.append(0)
            self.imgBuffer.append(0)
            self.imgBuffer.append(0)
            self.imgBuffer.append(255)

        if self.useHalfTexture:
            self.leftBuffer = array.array('B')
            for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT):
                self.leftBuffer.append(0)
                self.leftBuffer.append(0)
                self.leftBuffer.append(0)
                self.leftBuffer.append(255)

            self.rightBuffer = array.array('B')
            for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT):
                self.rightBuffer.append(0)
                self.rightBuffer.append(0)
                self.rightBuffer.append(0)
                self.rightBuffer.append(255)

        self.setupTexture()
        if self.useHalfTexture:
            self.setupHalfTextures()
        self.accept('mouse1', self.mouseDown, [AwWebView.LEFTMOUSEBTN])
        self.accept('mouse3', self.mouseDown, [AwWebView.RIGHTMOUSEBTN])
        self.accept('mouse1-up', self.mouseUp, [AwWebView.LEFTMOUSEBTN])
        self.accept('mouse3-up', self.mouseUp, [AwWebView.RIGHTMOUSEBTN])

    def getInGameNewsUrl(self):
        result = config.GetString('fallback-news-url', 'http://cdn.toontown.disney.go.com/toontown/en/gamenews/')
        override = config.GetString('in-game-news-url', '')
        if override:
            self.notify.info('got an override url,  using %s for in a game news' % override)
            result = override
        else:
            try:
                launcherUrl = base.launcher.getValue('GAME_IN_GAME_NEWS_URL', '')
                if launcherUrl:
                    result = launcherUrl
                    self.notify.info('got GAME_IN_GAME_NEWS_URL from launcher using %s' % result)
                else:
                    self.notify.info('blank GAME_IN_GAME_NEWS_URL from launcher, using %s' % result)
            except:
                self.notify.warning('got exception getting GAME_IN_GAME_NEWS_URL from launcher, using %s' % result)

        return result

    def setupTexture(self):
        cm = CardMaker('quadMaker')
        cm.setColor(1.0, 1.0, 1.0, 1.0)
        aspect = base.camLens.getAspectRatio()
        htmlWidth = 2.0 * aspect * WEB_WIDTH_PIXELS / float(WIN_WIDTH)
        htmlHeight = 2.0 * float(WEB_HEIGHT_PIXELS) / float(WIN_HEIGHT)
        cm.setFrame(-htmlWidth / 2.0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0)
        bottomRightX = WEB_WIDTH_PIXELS / float(WEB_WIDTH + 1)
        bottomRightY = WEB_HEIGHT_PIXELS / float(WEB_HEIGHT + 1)
        cm.setUvRange(Point2(0, 1 - bottomRightY), Point2(bottomRightX, 1))
        card = cm.generate()
        self.quad = NodePath(card)
        self.quad.reparentTo(self.parent)
        self.guiTex = Texture('guiTex')
        self.guiTex.setupTexture(Texture.TT2dTexture, WEB_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba)
        self.guiTex.setMinfilter(Texture.FTLinear)
        self.guiTex.setKeepRamImage(True)
        self.guiTex.makeRamImage()
        self.guiTex.setWrapU(Texture.WMRepeat)
        self.guiTex.setWrapV(Texture.WMRepeat)
        ts = TextureStage('webTS')
        self.quad.setTexture(ts, self.guiTex)
        self.quad.setTexScale(ts, 1.0, -1.0)
        self.quad.setTransparency(0)
        self.quad.setTwoSided(True)
        self.quad.setColor(1.0, 1.0, 1.0, 1.0)
        self.calcMouseLimits()

    def setupHalfTextures(self):
        self.setupLeftTexture()
        self.setupRightTexture()
        self.fullPnmImage = PNMImage(WEB_WIDTH, WEB_HEIGHT, 4)
        self.leftPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4)
        self.rightPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4)

    def setupLeftTexture(self):
        cm = CardMaker('quadMaker')
        cm.setColor(1.0, 1.0, 1.0, 1.0)
        aspect = base.camLens.getAspectRatio()
        htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH)
        htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT)
        cm.setFrame(-htmlWidth / 2.0, 0, -htmlHeight / 2.0, htmlHeight / 2.0)
        card = cm.generate()
        self.leftQuad = NodePath(card)
        self.leftQuad.reparentTo(self.parent)
        self.leftGuiTex = Texture('guiTex')
        self.leftGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba)
        self.leftGuiTex.setKeepRamImage(True)
        self.leftGuiTex.makeRamImage()
        self.leftGuiTex.setWrapU(Texture.WMClamp)
        self.leftGuiTex.setWrapV(Texture.WMClamp)
        ts = TextureStage('leftWebTS')
        self.leftQuad.setTexture(ts, self.leftGuiTex)
        self.leftQuad.setTexScale(ts, 1.0, -1.0)
        self.leftQuad.setTransparency(0)
        self.leftQuad.setTwoSided(True)
        self.leftQuad.setColor(1.0, 1.0, 1.0, 1.0)

    def setupRightTexture(self):
        cm = CardMaker('quadMaker')
        cm.setColor(1.0, 1.0, 1.0, 1.0)
        aspect = base.camLens.getAspectRatio()
        htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH)
        htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT)
        cm.setFrame(0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0)
        card = cm.generate()
        self.rightQuad = NodePath(card)
        self.rightQuad.reparentTo(self.parent)
        self.rightGuiTex = Texture('guiTex')
        self.rightGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba)
        self.rightGuiTex.setKeepRamImage(True)
        self.rightGuiTex.makeRamImage()
        self.rightGuiTex.setWrapU(Texture.WMClamp)
        self.rightGuiTex.setWrapV(Texture.WMClamp)
        ts = TextureStage('rightWebTS')
        self.rightQuad.setTexture(ts, self.rightGuiTex)
        self.rightQuad.setTexScale(ts, 1.0, -1.0)
        self.rightQuad.setTransparency(0)
        self.rightQuad.setTwoSided(True)
        self.rightQuad.setColor(1.0, 1.0, 1.0, 1.0)

    def calcMouseLimits(self):
        ll = Point3()
        ur = Point3()
        self.quad.calcTightBounds(ll, ur)
        self.notify.debug('ll=%s ur=%s' % (ll, ur))
        offset = self.quad.getPos(aspect2d)
        self.notify.debug('offset = %s ' % offset)
        ll.setZ(ll.getZ() + offset.getZ())
        ur.setZ(ur.getZ() + offset.getZ())
        self.notify.debug('new LL=%s, UR=%s' % (ll, ur))
        relPointll = self.quad.getRelativePoint(aspect2d, ll)
        self.notify.debug('relPoint = %s' % relPointll)
        self.mouseLL = (aspect2d.getScale()[0] * ll[0], aspect2d.getScale()[2] * ll[2])
        self.mouseUR = (aspect2d.getScale()[0] * ur[0], aspect2d.getScale()[2] * ur[2])
        self.notify.debug('original mouseLL=%s, mouseUR=%s' % (self.mouseLL, self.mouseUR))

    def writeTex(self, filename = 'guiText.png'):
        self.notify.debug('writing texture')
        self.guiTex.generateRamMipmapImages()
        self.guiTex.write(filename)

    def toggleRotation(self):
        if self.interval.isPlaying():
            self.interval.finish()
        else:
            self.interval.loop()

    def mouseDown(self, button):
        messenger.send('wakeup')
        self.webView.injectMouseDown(button)

    def mouseUp(self, button):
        self.webView.injectMouseUp(button)

    def reload(self):
        pass

    def zoomIn(self):
        self.webView.zoomIn()

    def zoomOut(self):
        self.webView.zoomOut()

    def toggleTransparency(self):
        self.transparency = not self.transparency
        self.webView.setTransparent(self.transparency)

    def update(self, task):
        if base.mouseWatcherNode.hasMouse():
            x, y = self._translateRelativeCoordinates(base.mouseWatcherNode.getMouseX(), base.mouseWatcherNode.getMouseY())
            if self.mx - x != 0 or self.my - y != 0:
                self.webView.injectMouseMove(x, y)
                self.mx, self.my = x, y
            if self.webView.isDirty():
                self.webView.render(self.imgBuffer.buffer_info()[0], WEB_WIDTH * 4, 4)
                Texture.setTexturesPower2(2)
                textureBuffer = self.guiTex.modifyRamImage()
                textureBuffer.setData(self.imgBuffer.tostring())
                if self.useHalfTexture:
                    self.guiTex.store(self.fullPnmImage)
                    self.leftPnmImage.copySubImage(self.fullPnmImage, 0, 0, 0, 0, WEB_HALF_WIDTH, WEB_HEIGHT)
                    self.rightPnmImage.copySubImage(self.fullPnmImage, 0, 0, WEB_HALF_WIDTH, 0, WEB_HALF_WIDTH, WEB_HEIGHT)
                    self.leftGuiTex.load(self.leftPnmImage)
                    self.rightGuiTex.load(self.rightPnmImage)
                    self.quad.hide()
                Texture.setTexturesPower2(1)
            GlobalWebcore.update()
        return Task.cont

    def _translateRelativeCoordinates(self, x, y):
        sx = int((x - self.mouseLL[0]) / (self.mouseUR[0] - self.mouseLL[0]) * WEB_WIDTH_PIXELS)
        sy = WEB_HEIGHT_PIXELS - int((y - self.mouseLL[1]) / (self.mouseUR[1] - self.mouseLL[1]) * WEB_HEIGHT_PIXELS)
        return (sx, sy)

    def unload(self):
        self.ignoreAll()
        self.webView.destroy()
        self.webView = None
        return

    def onCallback(self, name, args):
        if name == 'requestFPS':
            pass

    def onBeginNavigation(self, url, frameName):
        pass

    def onBeginLoading(self, url, frameName, statusCode, mimeType):
        pass

    def onFinishLoading(self):
        self.notify.debug('finished loading')

    def onReceiveTitle(self, title, frameName):
        pass

    def onChangeTooltip(self, tooltip):
        pass

    def onChangeCursor(self, cursor):
        pass

    def onChangeKeyboardFocus(self, isFocused):
        pass

    def onChangeTargetURL(self, url):
        pass
Ejemplo n.º 3
0
Archivo: GXO.py Proyecto: crempp/psg
class GXOStar(GXOBase):
    def __init__(self, parent=render, pos=Vec3(50, 0, 0)):
        GXOBase.__init__(self, parent, pos)

        self._initializeFlare()

    def _initializeFlare(self):
        # Parameters
        self.distance = 130000.0
        self.threshold = 0.3
        self.radius = 0.8
        self.strength = 1.0
        self.suncolor = Vec4(1, 1, 1, 1)
        self.suncardcolor = Vec4(1, 1, 0, 0)

        # Initialize some values
        self.obscured = 0.0

        # flaredata will hold the rendered image
        self.flaredata = PNMImage()
        # flaretexture will store the rendered buffer
        self.flaretexture = Texture()

        # Create a 10x10 texture buffer for the flare
        self.flarebuffer = base.win.makeTextureBuffer("Flare Buffer", 10, 10)
        # Attach the texture to the buffer
        self.flarebuffer.addRenderTexture(self.flaretexture,
                                          GraphicsOutput.RTMCopyRam)
        self.flarebuffer.setSort(-100)

        # Camera that renders the flare buffer
        self.flarecamera = base.makeCamera(self.flarebuffer)
        #self.flarecamera.reparentTo(base.cam)
        #self.flarecamera.setPos(-50,0,0)
        self.ortlens = OrthographicLens()
        self.ortlens.setFilmSize(
            10, 10)  # or whatever is appropriate for your scene
        self.ortlens.setNearFar(1, self.distance)
        self.flarecamera.node().setLens(self.ortlens)
        self.flarecamera.node().setCameraMask(GXMgr.MASK_GXM_HIDDEN)

        # Create a light for the flare
        self.sunlight = self.baseNode.attachNewNode(
            PointLight("Sun:Point Light"))
        self.sunlight.node().setColor(self.suncolor)
        self.sunlight.node().setAttenuation(Vec3(0.1, 0.04, 0.0))

        # Load texture cards
        # Create a nodepath that'll hold the texture cards for the new lens-flare
        self.texcardNP = aspect2d.attachNewNode('Sun:flareNode1')
        self.texcardNP.attachNewNode('Sun:fakeHdr')
        self.texcardNP.attachNewNode('Sun:starburstNode')
        # Load a circle and assign it a color. This will be used to calculate
        # Flare occlusion
        self.starcard = loader.loadModel('../data/models/unitcircle.egg')
        self.starcard.reparentTo(self.baseNode)
        self.starcard.setColor(self.suncardcolor)
        self.starcard.setScale(1)
        #self.starcard.setTransparency(TransparencyAttrib.MAlpha)
        # This is necessary since a billboard always rotates the y-axis to the
        # target but we need the z-axis
        self.starcard.setP(-90)
        self.starcard.setBillboardPointEye(self.flarecamera, 0.0)
        # Don't let the main camera see the star card
        self.starcard.show(GXMgr.MASK_GXM_HIDDEN)
        self.starcard.hide(GXMgr.MASK_GXM_VISIBLE)

        #the models are really just texture cards create with egg-texture-cards
        # from the actual pictures
        self.hdr = loader.loadModel('../data/models/fx_flare.egg')
        self.hdr.reparentTo(self.texcardNP.find('**/Sun:fakeHdr'))

        # Flare specs
        self.starburst_0 = loader.loadModel(
            '../data/models/fx_starburst_01.egg')
        self.starburst_1 = loader.loadModel(
            '../data/models/fx_starburst_02.egg')
        self.starburst_2 = loader.loadModel(
            '../data/models/fx_starburst_03.egg')
        self.starburst_0.setPos(0.5, 0, 0.5)
        self.starburst_1.setPos(0.5, 0, 0.5)
        self.starburst_2.setPos(0.5, 0, 0.5)
        self.starburst_0.setScale(.2)
        self.starburst_1.setScale(.2)
        self.starburst_2.setScale(.2)
        self.starburst_0.reparentTo(
            self.texcardNP.find('**/Sun:starburstNode'))
        self.starburst_1.reparentTo(
            self.texcardNP.find('**/Sun:starburstNode'))
        self.starburst_2.reparentTo(
            self.texcardNP.find('**/Sun:starburstNode'))

        self.texcardNP.setTransparency(TransparencyAttrib.MAlpha)
        # Put the texture cards in the background bin
        self.texcardNP.setBin('background', 0)
        # The texture cards do not affect the depth buffer
        self.texcardNP.setDepthWrite(False)

        #attach a node to the screen middle, used for some math
        self.mid2d = aspect2d.attachNewNode('mid2d')

        #start the task that implements the lens-flare
        taskMgr.add(self._flareTask, 'Sun:flareTask')

    ## this function returns the aspect2d position of a light source, if it enters the cameras field of view
    def _get2D(self, nodePath):
        #get the position of the light source relative to the cam
        p3d = base.cam.getRelativePoint(nodePath, Point3(0, 0, 0))
        p2d = Point2()

        #project the light source into the viewing plane and return 2d coordinates, if it is in the visible area(read: not behind the cam)
        if base.cam.node().getLens().project(p3d, p2d):
            return p2d

        return None

    def _getObscured(self, color):
        # This originally looked for the radius of the light but that caused
        # assertion errors. Now I use the radius of the hdr model.
        bounds = self.starcard.getBounds()
        #print ("bounds=%s rad=%s"%(bounds,bounds.getRadius()))
        if not bounds.isEmpty():
            r = bounds.getRadius()
            # Setting the film size sets the field-of-view and the aspect ratio
            # Maybe this should be done with setAspectRation() and setFov()
            self.ortlens.setFilmSize(r * self.radius, r * self.radius)

            # Point the flarecamera at the sun so we can determine if anything
            # is obscurring the sun
            self.flarecamera.lookAt(self.baseNode)

            # Renders the next frame in all the registered windows, and flips
            # all of the frame buffers. This will populate flaretexture since
            # it's attached to the flarebuffer.
            # Save the rendered frame in flaredata
            base.graphicsEngine.renderFrame()
            self.flaretexture.store(self.flaredata)

            #print ("flaredata=%s | color=%s"%(self.flaredata.getXel(5,5), color))

            # Initialize the obscured factor
            obscured = 100.0
            color = VBase3D(color[0], color[1], color[2])
            for x in xrange(0, 9):
                for y in xrange(0, 9):
                    if color.almostEqual(self.flaredata.getXel(x, y),
                                         self.threshold):
                        obscured -= 1.0
        else:
            obscured = 0
        return obscured

    def _flareTask(self, task):
        #going through the list of lightNodePaths
        #for index in xrange(0, len(self.lightNodes)):

        pos2d = self._get2D(self.sunlight)
        #if the light source is visible from the cam's point of view,
        # display the lens-flare
        if pos2d:
            #print ("Flare visible")

            # The the obscured factor
            obscured = self._getObscured(self.suncardcolor)
            # Scale it to [0,1]
            self.obscured = obscured / 100
            ##print obscured

            # Length is the length of the vector that goes from the screen
            # middle to the pos of the light. The length gets smaller the
            # closer the light is to the screen middle, however, since
            # length is used to calculate the brightness of the effect we
            # actually need an inverse behaviour, since the brightness
            # will be greates when center of screen= pos of light
            length = math.sqrt(pos2d.getX() * pos2d.getX() +
                               pos2d.getY() * pos2d.getY())
            invLength = 1.0 - length * 2
            # Subtract the obscured factor from the inverted distence and
            # we have a value that simulates the power of the flare
            #brightness
            flarePower = invLength - self.obscured
            #print("light pos=%s | length=%s"%(pos2d,length))
            print("obs=%s | length=%s | inv=%s | pow=%s" %
                  (self.obscured, length, invLength, flarePower))

            # Clamp the flare power to some values
            if flarePower < 0 and self.obscured > 0: flarePower = 0.0
            if flarePower < 0 and self.obscured <= 0: flarePower = 0.3
            if flarePower > 1: flarePower = 1

            print("flarepower=%s" % (flarePower))

            #
            if self.obscured >= 0.8:
                self.texcardNP.find('**/Sun:starburstNode').hide()
            else:
                self.texcardNP.find('**/Sun:starburstNode').show()

                #drawing the lens-flare effect...
                r = self.suncolor.getX()
                g = self.suncolor.getY()
                b = self.suncolor.getZ()
                r = math.sqrt(r * r + length * length) * self.strength
                g = math.sqrt(g * g + length * length) * self.strength
                b = math.sqrt(b * b + length * length) * self.strength
                print("%s,%s,%s" % (r, g, b))

                #
                if self.obscured > 0.19:
                    a = self.obscured - 0.2
                else:
                    a = 0.4 - flarePower

                #
                if a < 0: a = 0
                if a > 0.8: a = 0.8

                #
                self.hdr.setColor(r, g, b, 0.8 - a)
                self.hdr.setR(90 * length)
                self.texcardNP.find('**/Sun:starburstNode').setColor(
                    r, g, b, 0.5 + length)
                self.hdr.setPos(pos2d.getX(), 0, pos2d.getY())
                self.hdr.setScale(8.5 + (5 * length))

                vecMid = Vec2(self.mid2d.getX(), self.mid2d.getZ())
                vec2d = Vec2(vecMid - pos2d)
                vec3d = Vec3(vec2d.getX(), 0, vec2d.getY())

                self.starburst_0.setPos(self.hdr.getPos() - (vec3d * 10))
                self.starburst_1.setPos(self.hdr.getPos() - (vec3d * 5))
                self.starburst_2.setPos(self.hdr.getPos() - (vec3d * 10))
                self.texcardNP.show()
                #print "a",a
        else:
            #hide the lens-flare effect for a light source, if it is not visible...
            self.texcardNP.hide()

        return Task.cont
class TexturePainter(DirectObject):
  def __init__(self):
    self.editTexture = None
    self.editModel = None
    
    self.texturePainterStatus = TEXTURE_PAINTER_STATUS_DISABLED
    
    self.paintColor = VBase4D(1,1,1,1)
    self.paintSize = 10
    self.paintEffect = PNMBrush.BEBlend
    self.paintSmooth = True
    self.paintMode = TEXTUREPAINTER_FUNCTION_PAINT_POINT
    
    self.painter = None
  
  # --- creation and destroying of the whole editor ---
  def enableEditor(self):
    ''' create the editor
    change from disabled to enabled'''
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_DISABLED:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_ENABLED
      self.__enableEditor()
    else:
      print "E: TexturePainter.enableEditor: not disabled", self.texturePainterStatus
  
  def disableEditor(self):
    ''' destroy the editor, automatically stop the editor and painting
    change from enabled to disabled'''
    # try stopping if more advanced mode
    #if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
    #  self.stopEditor()
    
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_ENABLED:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_DISABLED
      self.__disableEditor()
    else:
      print "E: TexturePainter.disableEditor: not enabled", self.texturePainterStatus
  
  # --- 
  def startEditor(self, editModel, editTexture, backgroundShader=MODEL_COLOR_SHADER):
    ''' prepare to paint
    change from enabled to initialized'''
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_ENABLED:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_INITIALIZED
      self.__startEditor(editModel, editTexture, backgroundShader)
    else:
      print "E: TexturePainter.startEditor: not enabled", self.texturePainterStatus
  
  def stopEditor(self):
    ''' stop painting, automatically stop painting
    change from initialized to enabled'''
    #if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
    #  self.stopPaint()
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_ENABLED
      return self.__stopEditor()
    else:
      print "E: TexturePainter.startEditor: not initialized", self.texturePainterStatus
  
  """ # this is not externally callable
  # ---
  def startPaint(self):
    ''' start painting on the model
    change from initialized to running '''
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_RUNNING
      self.__startPaint()
    else:
      print "E: TexturePainter.startPaint: not enabled", self.texturePainterStatus"""
  
  def stopPaint(self):
    ''' stop painting
    change from running to initialized '''
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_RUNNING:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_INITIALIZED
      self.__stopPaint()
    else:
      print "E: TexturePainter.stopPaint: not running", self.texturePainterStatus
  
  
  # --- brush settings for painting ---
  ''' changing brush settings is possible all the time '''
  def setBrushSettings(self, color, size, smooth, effect):
    #print "I: TexturePainter.setBrushSettings", color, size, smooth, effect
    self.paintColor = color
    self.paintSize = size
    self.paintEffect = effect
    self.paintSmooth = smooth
    if effect in [PNMBrush.BESet, PNMBrush.BEBlend, PNMBrush.BEDarken, PNMBrush.BELighten]:
      self.brush = PNMBrush.makeSpot(color, size, smooth, effect)
      #if self.paintModel:
      if self.painter:
        self.painter.setPen(self.brush)
  
  def getBrushSettings(self):
    return self.paintColor,self.paintSize,self.paintSmooth,self.paintEffect
  
  def setPaintMode(self, newMode):
    self.paintMode = newMode
    # clear last point if mode changed
    if newMode == TEXTUREPAINTER_FUNCTION_PAINT_POINT or \
       newMode == TEXTUREPAINTER_FUNCTION_READ:
      self.lastPoint = None
  
  def getPaintMode(self):
    return self.paintMode
  
  
  
  def __enableEditor(self):
    ''' create the background rendering etc., but the model is not yet defined '''
    print "I: TexturePainter.__enableEditor"
    # the buffer the model with the color texture is rendered into
    self.modelColorBuffer = None
    self.modelColorCam = None
    # the buffer the picked position color is rendered into
    self.colorPickerBuffer = None
    self.colorPickerCam = None
    # create the buffers
    self.__createBuffer()
    
    # when the window is resized, the background buffer etc must be updated.
    self.accept("window-event", self.__windowEvent)
    
    # some debugging stuff
    self.accept("v", base.bufferViewer.toggleEnable)
    self.accept("V", base.bufferViewer.toggleEnable)
  
  def __disableEditor(self):
    print "I: TexturePainter.__disableEditor"
    
    self.__destroyBuffer()
    
    # ignore window-event and debug
    self.ignoreAll()
  
  def __windowEvent(self, win=None):
    ''' when the editor is enabled, update the buffers etc. when the window
    is resized '''
    print "I: TexturePainter.windowEvent"
    
    # with a fixed backgroudn buffer size this is not needed anymore
    
    if False:
      #if self.texturePainterStatus != TEXTURE_PAINTER_STATUS_DISABLED:
      if self.modelColorBuffer:
        if WindowManager.activeWindow:
          # on window resize there seems to be never a active window
          win = WindowManager.activeWindow.win
        else:
          win = base.win
        if self.modelColorBuffer.getXSize() != win.getXSize() or self.modelColorBuffer.getYSize() != win.getYSize():
          '''print "  - window resized",\
              self.modelColorBuffer.getXSize(),\
              win.getXSize(),\
              self.modelColorBuffer.getYSize(),\
              win.getYSize()'''
          # if the buffer size doesnt match the window size (window has been resized)
          self.__destroyBuffer()
          self.__createBuffer()
          self.__updateModel()
      else:
        print "W: TexturePainter.__windowEvent: no buffer"
        self.__createBuffer()
  
  def __createBuffer(self):
    ''' create the buffer we render in the background into '''
    print "I: TexturePainter.__createBuffer"
    # the window has been modified
    if WindowManager.activeWindow:
      # on window resize there seems to be never a active window
      win = WindowManager.activeWindow.win
    else:
      win = base.win
    
    # get the window size
    self.windowSizeX = win.getXSize()
    self.windowSizeY = win.getYSize()
    
    # create a buffer in which we render the model using a shader
    self.paintMap = Texture()
    # 1.5.4 cant handle non power of 2 buffers
    self.modelColorBuffer = createOffscreenBuffer(-3, TEXTUREPAINTER_BACKGROUND_BUFFER_RENDERSIZE[0], TEXTUREPAINTER_BACKGROUND_BUFFER_RENDERSIZE[1]) #self.windowSizeX, self.windowSizeY)
    self.modelColorBuffer.addRenderTexture(self.paintMap, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPColor)
    self.modelColorCam = base.makeCamera(self.modelColorBuffer, lens=base.cam.node().getLens(), sort=1)
    
    # Create a small buffer for the shader program that will fetch the point from the texture made
    # by the self.modelColorBuffer
    self.colorPickerImage = PNMImage()
    self.colorPickerTex = Texture()
    self.colorPickerBuffer = base.win.makeTextureBuffer("color picker buffer", 2, 2, self.colorPickerTex, True)
    
    self.colorPickerScene = NodePath('color picker scene')
    
    self.colorPickerCam = base.makeCamera(self.colorPickerBuffer, lens=base.cam.node().getLens(), sort=2)
    self.colorPickerCam.reparentTo(self.colorPickerScene)
    self.colorPickerCam.setY(-2)
    
    cm = CardMaker('color picker scene card')
    cm.setFrameFullscreenQuad()
    pickerCard = self.colorPickerScene.attachNewNode(cm.generate())
    
    loadPicker = NodePath(PandaNode('pointnode'))
    loadPicker.setShader(Shader.make(COLOR_PICKER_SHADER), 10001)
    
    # Feed the paintmap from the paintBuffer to the shader and initial mouse positions
    self.colorPickerScene.setShaderInput('paintmap', self.paintMap)
    self.colorPickerScene.setShaderInput('mousepos', 0, 0, 0, 1)
    self.colorPickerCam.node().setInitialState(loadPicker.getState())
  
  def __destroyBuffer(self):
    print "I: TexturePainter.__destroyBuffer"
    if self.modelColorBuffer:
      
      # Destroy the buffer
      base.graphicsEngine.removeWindow(self.modelColorBuffer)
      self.modelColorBuffer = None
      # Remove the camera
      self.modelColorCam.removeNode()
      del self.modelColorCam
      
      self.colorPickerScene.removeNode()
      del self.colorPickerScene
      # remove cam
      self.colorPickerCam.removeNode()
      del self.colorPickerCam
      # Destroy the buffer
      base.graphicsEngine.removeWindow(self.colorPickerBuffer)
      self.colorPickerBuffer = None
      
      del self.colorPickerTex
      del self.colorPickerImage
  
  def __startEditor(self, editModel, editTexture, backgroundShader=MODEL_COLOR_SHADER):
    print "I: TexturePainter.__startEditor"
    
    # this is needed as on startup the editor may not have had a window etc.
    self.__windowEvent()
    
    if not editModel or not editTexture:
      print "W: TexturePainter.__startEditor: model or texture invalid", editModel, editTexture
      return False
    
    self.editModel = editModel
    self.editTexture = editTexture
    self.editImage = None
    self.backgroundShader = backgroundShader
    
    if type(self.editTexture) == Texture:
      # if the image to modify is a texture, create a pnmImage which we modify
      self.editImage = PNMImage()
      # copy the image from the texture to the working layer
      self.editTexture.store(self.editImage)
    else:
      self.editImage = self.editTexture
    
    # create the brush for painting
    self.painter = PNMPainter(self.editImage)
    self.setBrushSettings( *self.getBrushSettings() )
    
    self.__updateModel()
    
    # start edit
    messenger.send(EVENT_TEXTUREPAINTER_STARTEDIT)
    
    for startEvent in TEXTUREPAINTER_START_PAINT_EVENTS:
      self.accept(startEvent, self.__startPaint)
    for stopEvent in TEXTUREPAINTER_STOP_PAINT_EVENTS:
      self.accept(stopEvent, self.__stopPaint)
    
    self.modelColorCam.node().copyLens(WindowManager.activeWindow.camera.node().getLens())
    
    taskMgr.add(self.__paintTask, 'paintTask')
    
    #modelModificator.toggleEditmode(False)
    
    self.isPainting = False
  
  def __stopEditor(self):
    print "I: TexturePainter.__stopEditor"
    for startEvent in TEXTUREPAINTER_START_PAINT_EVENTS:
      self.ignore(startEvent)
    for stopEvent in TEXTUREPAINTER_STOP_PAINT_EVENTS:
      self.ignore(stopEvent)
    
    taskMgr.remove('paintTask')
    # stop edit end
    
    # must be reset before we loose the properties
    if self.editModel and self.editTexture and self.editImage:
      try:
        # hide the model from cam 2
        self.editModel.hide(BitMask32.bit(1))
        self.editModel = None
      except:
        print "E: TexturePainter.__stopEditor: the model has already been deleted"
    
    # stop edit
    messenger.send(EVENT_TEXTUREPAINTER_STOPEDIT)
    
    self.editImage = None
    self.editTexture = None
    self.painter = None
    self.brush = None
    
    #modelModificator.toggleEditmode(True)
    
  
  def __updateModel(self):
    if self.editModel:
      # create a image with the same size of the texture
      textureSize = (self.editTexture.getXSize(), self.editTexture.getYSize())
      
      # create a dummy node, where we setup the parameters for the background rendering
      loadPaintNode = NodePath(PandaNode('paintnode'))
      loadPaintNode.setShader(Shader.make(self.backgroundShader), 10001)
      loadPaintNode.setShaderInput('texsize', textureSize[0], textureSize[1], 0, 0)
      
      # copy the state onto the camera
      self.modelColorCam.node().setInitialState(loadPaintNode.getState())
      
      # the camera gets a special bitmask, to show/hide models from it
      self.modelColorCam.node().setCameraMask(BitMask32.bit(1))
      
      if False:
        # doesnt work, but would be nicer (not messing with the default render state)
        
        hiddenNode = NodePath(PandaNode('hiddennode'))
        hiddenNode.hide(BitMask32.bit(1))
        showTroughNode = NodePath(PandaNode('showtroughnode'))
        showTroughNode.showThrough(BitMask32.bit(1))
        
        self.modelColorCam.node().setTagStateKey('show-on-backrender-cam')
        self.modelColorCam.node().setTagState('False', hiddenNode.getState())
        self.modelColorCam.node().setTagState('True', showTroughNode.getState())
        
        render.setTag('show-on-backrender-cam', 'False')
        self.editModel.setTag('show-on-backrender-cam', 'True')
      else:
        # make only the model visible to the background camera
        render.hide(BitMask32.bit(1))
        self.editModel.showThrough(BitMask32.bit(1))
  
  # --- start the paint tasks ---
  def __startPaint(self):
    self.isPainting = True
  
  def __stopPaint(self):
    self.isPainting = False
  
  # --- modification tasks ---
  def __textureUpdateTask(self, task=None):
    ''' modify the texture using the edited image
    '''
    if type(self.editTexture) == Texture:
      self.editTexture.load(self.editImage)
    
    if task: # task may be None
      return task.again
  
  def __paintTask(self, task):
    #print "I: TexturePainter.__paintTask:"
    
    if not WindowManager.activeWindow or not WindowManager.activeWindow.mouseWatcherNode.hasMouse():
      '''print "  - abort:", WindowManager.activeWindow
      if WindowManager.activeWindow:
        print "  - mouse:", WindowManager.activeWindow.mouseWatcherNode.hasMouse()'''
      return task.cont
    
    
    # update the camera according to the active camera
    #self.modelColorCam.setMat(render, WindowManager.activeWindow.camera.getMat(render))
    
    mpos = base.mouseWatcherNode.getMouse()
    x_ratio = min( max( ((mpos.getX()+1)/2), 0), 1)
    y_ratio = min( max( ((mpos.getY()+1)/2), 0), 1)
    mx = int(x_ratio*self.windowSizeX)
    my = self.windowSizeY - int(y_ratio*self.windowSizeY)
    
    self.colorPickerScene.setShaderInput('mousepos', x_ratio, y_ratio, 0, 1)
    
    if self.colorPickerTex.hasRamImage():
      self.colorPickerTex.store(self.colorPickerImage)
      
      # get the color below the mousepick from the rendered frame
      r = self.colorPickerImage.getRedVal(0,0)
      g = self.colorPickerImage.getGreenVal(0,0)
      b = self.colorPickerImage.getBlueVal(0,0)
      # calculate uv-texture position from the color
      x = r + ((b%16)*256)
      y = g + ((b//16)*256)
      
      if self.isPainting:
        self.__paintPixel(x,y)
        self.__textureUpdateTask()
    else:
      # this might happen if no frame has been rendered yet since creation of the texture
      print "W: TexturePainter.__paintTask: colorPickerTex.hasRamMipmapImage() =", self.colorPickerTex.hasRamImage()
    
    return task.cont
  
  def __paintPixel(self, x, y):
    ''' paint at x/y with the defined settings '''
    
    imageMaxX = self.editImage.getXSize()
    imageMaxY = self.editImage.getYSize()
    def inImage(x,y):
      ''' is the given x/y position within the image '''
      return ((imageMaxX > x >= 0) and (imageMaxY > y >= 0))
    
    # how smooth should be painted
    if self.paintSmooth:
      # a smooth brush
      hardness = 1.0
    else:
      # a hard brush
      hardness = 0.1
    hardness = min(1.0, max(0.05, hardness))
    
    # the paint radius
    radius = int(round(self.paintSize/2.0))
    radiusSquare = float(radius*radius)
    
    # a function to get the brush color/strength, depending on the radius
    def getBrushColor(diffPosX, diffPosY):
      distance = diffPosX**2 + diffPosY**2
      brushStrength = (1 - (min(distance, radiusSquare) / radiusSquare)) / hardness
      return min(1.0, max(0.0, brushStrength))
    
    if inImage(x,y):
      if self.paintMode == TEXTUREPAINTER_FUNCTION_PAINT_POINT:
        if self.paintEffect in [PNMBrush.BESet, PNMBrush.BEBlend, PNMBrush.BEDarken, PNMBrush.BELighten]:
          # render a spot into the texture
          self.painter.drawPoint(x, y)
        
        elif self.paintEffect in [TEXTUREPAINTER_BRUSH_FLATTEN, TEXTUREPAINTER_BRUSH_SMOOTH, TEXTUREPAINTER_BRUSH_RANDOMIZE]:
          
          if self.paintEffect == TEXTUREPAINTER_BRUSH_SMOOTH:
            # calculate average values
            data = dict()
            smoothRadius = 2
            for dx in xrange(-radius, radius+1):
              for dy in xrange(-radius, radius+1):
                if inImage(x+dx,y+dy):
                  average = VBase4D(0)
                  dividor = 0
                  for px in xrange(-smoothRadius,smoothRadius+1):
                    for py in xrange(-smoothRadius,smoothRadius+1):
                      if inImage(x+dx+px,y+dy+py):
                        average += self.editImage.getXelA(x+dx+px,y+dy+py)
                        dividor += 1
                  average /= float(dividor)
                  data[(x+dx,y+dy)] = average
            
            # save to image
            for (px,py), newValue in data.items():
              currentValue = self.editImage.getXelA(px,py)
              diffValue = currentValue - newValue
              
              dx = px - x
              dy = py - y
              
              
              multiplier = getBrushColor(dx, dy)
              print dx, dy, multiplier
              '''if self.paintSmooth:
                multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
              else:
                # not sure if this is correct
                multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
              
              '''r = currentValue.getX() * (1-multiplier*self.paintColor.getX()) + diffValue.getX() * multiplier*self.paintColor.getX()
              g = currentValue.getY() * (1-multiplier*self.paintColor.getY()) + diffValue.getY() * multiplier*self.paintColor.getY()
              b = currentValue.getZ() * (1-multiplier*self.paintColor.getZ()) + diffValue.getZ() * multiplier*self.paintColor.getZ()
              a = currentValue.getW() * (1-multiplier*self.paintColor.getW()) + diffValue.getW() * multiplier*self.paintColor.getW()'''
              r = currentValue.getX() - multiplier * diffValue.getX()
              g = currentValue.getY() - multiplier * diffValue.getY()
              b = currentValue.getZ() - multiplier * diffValue.getZ()
              a = currentValue.getW() - multiplier * diffValue.getW()
              if self.editImage.hasAlpha():
                self.editImage.setXelA(px,py,VBase4D(r,g,b,a))
              else:
                self.editImage.setXel(px,py,VBase3D(r,g,b))
              
              #self.editImage.setXelA(x,y,value)
            
          if self.paintEffect == TEXTUREPAINTER_BRUSH_FLATTEN:
            dividor = 0
            average = VBase4D(0)
            for dx in xrange(-radius, radius+1):
              for dy in xrange(-radius, radius+1):
                if inImage(x+dx,y+dy):
                  multiplier = getBrushColor(dx, dy)
                  '''if self.paintSmooth:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
                  else:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
                  dividor += multiplier
                  average += self.editImage.getXelA(x+dx,y+dy) * multiplier
            average /= dividor
            for dx in xrange(-radius, radius+1):
              for dy in xrange(-radius, radius+1):
                if inImage(x+dx,y+dy):
                  multiplier = getBrushColor(dx, dy)
                  '''if self.paintSmooth:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
                  else:
                    # not sure if this is correct
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
                  currentValue = self.editImage.getXelA(x+dx,y+dy)
                  r = currentValue.getX() * (1-multiplier*self.paintColor.getX()) + average.getX() * multiplier*self.paintColor.getX()
                  g = currentValue.getY() * (1-multiplier*self.paintColor.getY()) + average.getY() * multiplier*self.paintColor.getY()
                  b = currentValue.getZ() * (1-multiplier*self.paintColor.getZ()) + average.getZ() * multiplier*self.paintColor.getZ()
                  a = currentValue.getW() * (1-multiplier*self.paintColor.getW()) + average.getW() * multiplier*self.paintColor.getW()
                  if self.editImage.hasAlpha():
                    self.editImage.setXelA(x+dx,y+dy,VBase4D(r,g,b,a))
                  else:
                    self.editImage.setXel(x+dx,y+dy,VBase3D(r,g,b))
          
          elif self.paintEffect == TEXTUREPAINTER_BRUSH_RANDOMIZE:
            for dx in xrange(-radius, radius+1):
              for dy in xrange(-radius, radius+1):
                if inImage(x+dx,y+dy):
                  r = VBase4D(random.random()*self.paintColor.getX()-self.paintColor.getX()/2.,
                             random.random()*self.paintColor.getY()-self.paintColor.getY()/2.,
                             random.random()*self.paintColor.getZ()-self.paintColor.getZ()/2.,
                             random.random()*self.paintColor.getW()-self.paintColor.getW()/2.)
                  multiplier = getBrushColor(dx, dy)
                  '''if self.paintSmooth:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
                  else:
                    # not sure if this is correct
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
                  currentValue = self.editImage.getXelA(x+dx,y+dy)
                  self.editImage.setXelA(x+dx,y+dy,currentValue+r*multiplier)
      
      elif self.paintMode == TEXTUREPAINTER_FUNCTION_READ:
        if inImage(x,y):
          col = self.editImage.getXelA(x,y)
          if self.editImage.hasAlpha():
            self.paintColor = VBase4D(col[0], col[1], col[2], col[3])
          else:
            self.paintColor = VBase4D(col[0], col[1], col[2], 1.0)
          messenger.send(EVENT_TEXTUREPAINTER_BRUSHCHANGED)
      
      elif self.paintMode == TEXTUREPAINTER_FUNCTION_PAINT_LINE:
        if self.lastPoint != None:
          self.painter.drawLine(x, y, self.lastPoint[0], self.lastPoint[1])
      
      elif self.paintMode == TEXTUREPAINTER_FUNCTION_PAINT_RECTANGLE:
        if self.lastPoint != None:
          self.painter.drawRectangle(x, y, self.lastPoint[0], self.lastPoint[1])
      
      self.lastPoint = (x,y)
Ejemplo n.º 5
0
class HtmlView(DirectObject):

    notify = DirectNotifyGlobal.directNotify.newCategory("HtmlView")
    useHalfTexture = base.config.GetBool("news-half-texture", 0)

    def __init__(self, parent=aspect2d):
        """Properly initialize ourself."""
        #AwWebViewListener.AwWebViewListener.__init__(self)
        self.parent = parent
        self.mx = 0
        self.my = 0
        self.htmlFile = "index.html"
        self.transparency = False  # this is important looks weird if it's true
        global GlobalWebcore
        if GlobalWebcore:
            # we get a C++ crash if we construct webcore a second time
            pass
        else:
            GlobalWebcore = AwWebCore(AwWebCore.LOGVERBOSE, True,
                                      AwWebCore.PFBGRA)
            GlobalWebcore.setBaseDirectory('.')
            for errResponse in xrange(400, 600):
                GlobalWebcore.setCustomResponsePage(errResponse, "error.html")

        self.webView = GlobalWebcore.createWebView(WEB_WIDTH, WEB_HEIGHT,
                                                   self.transparency, False,
                                                   70)
        #self.webView.setListener(self)
        #self.webView.setCallback("requestFPS");
        frameName = ''
        inGameNewsUrl = self.getInGameNewsUrl()
        #self.webView.loadURL2(inGameNewsUrl)

        self.imgBuffer = array.array('B')
        for i in xrange(WEB_WIDTH * WEB_HEIGHT):
            self.imgBuffer.append(0)
            self.imgBuffer.append(0)
            self.imgBuffer.append(0)
            self.imgBuffer.append(255)

        if self.useHalfTexture:
            self.leftBuffer = array.array('B')
            for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT):
                self.leftBuffer.append(0)
                self.leftBuffer.append(0)
                self.leftBuffer.append(0)
                self.leftBuffer.append(255)
            self.rightBuffer = array.array('B')
            for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT):
                self.rightBuffer.append(0)
                self.rightBuffer.append(0)
                self.rightBuffer.append(0)
                self.rightBuffer.append(255)

        self.setupTexture()
        if self.useHalfTexture:
            self.setupHalfTextures()

        #self.interval = LerpHprInterval(self.quad, 2, Vec3(360, 0, 0), Vec3(0, 0, 0))

        #self.accept("escape", sys.exit, [0])
        #self.accept("w", self.writeTex)

        self.accept("mouse1", self.mouseDown, [AwWebView.LEFTMOUSEBTN])
        self.accept("mouse3", self.mouseDown, [AwWebView.RIGHTMOUSEBTN])
        self.accept("mouse1-up", self.mouseUp, [AwWebView.LEFTMOUSEBTN])
        self.accept("mouse3-up", self.mouseUp, [AwWebView.RIGHTMOUSEBTN])

        #self.accept("f1", self.toggleRotation)
        #self.accept("f2", self.toggleTransparency)
        #self.accept("f3", self.reload)
        #self.accept("f4", self.zoomIn)
        #self.accept("f5", self.zoomOut)

        #taskMgr.doMethodLater(1.0, self.update, 'HtmlViewUpdateTask')
        # we get a problem if a mid-frame hearbeat fires of this task in conjunction with igLoop
        #taskMgr.add(self.update, 'HtmlViewUpdateTask',  priority = 51)
        #taskMgr.add(self.update, 'HtmlViewUpdateTask')
        #base.newsFrame = self

    def getInGameNewsUrl(self):
        """Get the appropriate URL to use if we are in test, qa, or live."""
        # First if all else fails, we hard code the live news url
        result = base.config.GetString(
            "fallback-news-url",
            "http://cdn.toontown.disney.go.com/toontown/en/gamenews/")
        # next check if we have an override, say they want to url to point to a file in their harddisk
        override = base.config.GetString("in-game-news-url", "")
        if override:
            self.notify.info(
                "got an override url,  using %s for in a game news" % override)
            result = override
        else:
            try:
                launcherUrl = base.launcher.getValue("GAME_IN_GAME_NEWS_URL",
                                                     "")
                if launcherUrl:
                    result = launcherUrl
                    self.notify.info(
                        "got GAME_IN_GAME_NEWS_URL from launcher using %s" %
                        result)
                else:
                    self.notify.info(
                        "blank GAME_IN_GAME_NEWS_URL from launcher, using %s" %
                        result)

            except:
                self.notify.warning(
                    "got exception getting GAME_IN_GAME_NEWS_URL from launcher, using %s"
                    % result)
        return result

    def setupTexture(self):
        cm = CardMaker('quadMaker')
        cm.setColor(1.0, 1.0, 1.0, 1.0)

        aspect = base.camLens.getAspectRatio()
        htmlWidth = 2.0 * aspect * WEB_WIDTH_PIXELS / float(WIN_WIDTH)
        htmlHeight = 2.0 * float(WEB_HEIGHT_PIXELS) / float(WIN_HEIGHT)

        # the html area will be center aligned and vertically top aligned
        #cm.setFrame(-htmlWidth/2.0, htmlWidth/2.0, 1.0 - htmlHeight, 1.0)
        cm.setFrame(-htmlWidth / 2.0, htmlWidth / 2.0, -htmlHeight / 2.0,
                    htmlHeight / 2.0)

        bottomRightX = (WEB_WIDTH_PIXELS) / float(WEB_WIDTH + 1)
        bottomRightY = WEB_HEIGHT_PIXELS / float(WEB_HEIGHT + 1)

        #cm.setUvRange(Point2(0,0), Point2(bottomRightX, bottomRightY))
        cm.setUvRange(Point2(0, 1 - bottomRightY), Point2(bottomRightX, 1))

        card = cm.generate()
        self.quad = NodePath(card)
        self.quad.reparentTo(self.parent)

        self.guiTex = Texture("guiTex")
        self.guiTex.setupTexture(Texture.TT2dTexture, WEB_WIDTH, WEB_HEIGHT, 1,
                                 Texture.TUnsignedByte, Texture.FRgba)
        self.guiTex.setMinfilter(Texture.FTLinear)
        self.guiTex.setKeepRamImage(True)
        self.guiTex.makeRamImage()
        self.guiTex.setWrapU(Texture.WMRepeat)
        self.guiTex.setWrapV(Texture.WMRepeat)

        ts = TextureStage('webTS')
        self.quad.setTexture(ts, self.guiTex)
        self.quad.setTexScale(ts, 1.0, -1.0)

        self.quad.setTransparency(0)
        self.quad.setTwoSided(True)
        self.quad.setColor(1.0, 1.0, 1.0, 1.0)
        #self.quad.setZ(0.1) # shtickerbook is moved up by 0.1

        self.calcMouseLimits()

    def setupHalfTextures(self):
        self.setupLeftTexture()
        self.setupRightTexture()
        self.fullPnmImage = PNMImage(WEB_WIDTH, WEB_HEIGHT, 4)
        self.leftPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4)
        self.rightPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4)

    def setupLeftTexture(self):
        cm = CardMaker('quadMaker')
        cm.setColor(1.0, 1.0, 1.0, 1.0)

        aspect = base.camLens.getAspectRatio()
        htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH)
        htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT)

        # the html area will be center aligned and vertically top aligned
        #cm.setFrame(-htmlWidth/2.0, htmlWidth/2.0, 1.0 - htmlHeight, 1.0)
        cm.setFrame(-htmlWidth / 2.0, 0, -htmlHeight / 2.0, htmlHeight / 2.0)
        card = cm.generate()
        self.leftQuad = NodePath(card)
        self.leftQuad.reparentTo(self.parent)

        self.leftGuiTex = Texture("guiTex")
        self.leftGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH,
                                     WEB_HEIGHT, 1, Texture.TUnsignedByte,
                                     Texture.FRgba)
        self.leftGuiTex.setKeepRamImage(True)
        self.leftGuiTex.makeRamImage()
        self.leftGuiTex.setWrapU(Texture.WMClamp)
        self.leftGuiTex.setWrapV(Texture.WMClamp)

        ts = TextureStage('leftWebTS')
        self.leftQuad.setTexture(ts, self.leftGuiTex)
        self.leftQuad.setTexScale(ts, 1.0, -1.0)

        self.leftQuad.setTransparency(0)
        self.leftQuad.setTwoSided(True)
        self.leftQuad.setColor(1.0, 1.0, 1.0, 1.0)
        #self.quad.setZ(0.1) # shtickerbook is moved up by 0.1

    def setupRightTexture(self):
        cm = CardMaker('quadMaker')
        cm.setColor(1.0, 1.0, 1.0, 1.0)

        aspect = base.camLens.getAspectRatio()
        htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH)
        htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT)

        # the html area will be center aligned and vertically top aligned
        #cm.setFrame(-htmlWidth/2.0, htmlWidth/2.0, 1.0 - htmlHeight, 1.0)
        cm.setFrame(0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0)
        card = cm.generate()
        self.rightQuad = NodePath(card)
        self.rightQuad.reparentTo(self.parent)

        self.rightGuiTex = Texture("guiTex")
        self.rightGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH,
                                      WEB_HEIGHT, 1, Texture.TUnsignedByte,
                                      Texture.FRgba)
        self.rightGuiTex.setKeepRamImage(True)
        self.rightGuiTex.makeRamImage()
        self.rightGuiTex.setWrapU(Texture.WMClamp)
        self.rightGuiTex.setWrapV(Texture.WMClamp)

        ts = TextureStage('rightWebTS')
        self.rightQuad.setTexture(ts, self.rightGuiTex)
        self.rightQuad.setTexScale(ts, 1.0, -1.0)

        self.rightQuad.setTransparency(0)
        self.rightQuad.setTwoSided(True)
        self.rightQuad.setColor(1.0, 1.0, 1.0, 1.0)
        #self.quad.setZ(0.1) # shtickerbook is moved up by 0.1

    def calcMouseLimits(self):
        ll = Point3()
        ur = Point3()
        self.quad.calcTightBounds(ll, ur)
        self.notify.debug("ll=%s ur=%s" % (ll, ur))

        # we need to get our relative position to aspect2d, since shtiker books is shifted
        offset = self.quad.getPos(aspect2d)
        self.notify.debug("offset = %s " % offset)
        ll.setZ(ll.getZ() + offset.getZ())
        ur.setZ(ur.getZ() + offset.getZ())

        self.notify.debug("new LL=%s, UR=%s" % (ll, ur))

        relPointll = self.quad.getRelativePoint(aspect2d, ll)
        self.notify.debug("relPoint = %s" % relPointll)
        self.mouseLL = (aspect2d.getScale()[0] * ll[0],
                        aspect2d.getScale()[2] * ll[2])
        self.mouseUR = (aspect2d.getScale()[0] * ur[0],
                        aspect2d.getScale()[2] * ur[2])
        self.notify.debug("original mouseLL=%s, mouseUR=%s" %
                          (self.mouseLL, self.mouseUR))

    def writeTex(self, filename="guiText.png"):
        self.notify.debug("writing texture")
        self.guiTex.generateRamMipmapImages()
        self.guiTex.write(filename)

    def toggleRotation(self):
        if self.interval.isPlaying():
            self.interval.finish()
        else:
            self.interval.loop()

    def mouseDown(self, button):
        messenger.send('wakeup')
        self.webView.injectMouseDown(button)

    def mouseUp(self, button):
        self.webView.injectMouseUp(button)

    def reload(self):
        pass
        #self.webView.loadFile(self.htmlFile, '')

    def zoomIn(self):
        self.webView.zoomIn()

    def zoomOut(self):
        self.webView.zoomOut()

    def toggleTransparency(self):
        self.transparency = not self.transparency
        self.webView.setTransparent(self.transparency)

    def update(self, task):
        global GlobalWebcore
        if base.mouseWatcherNode.hasMouse():
            x, y = self._translateRelativeCoordinates(
                base.mouseWatcherNode.getMouseX(),
                base.mouseWatcherNode.getMouseY())
            #self.notify.debug('got mouse move %d %d' % (x,y))
            #self.webView.injectMouseMove(x, y)

            if (self.mx - x) != 0 or (self.my - y) != 0:
                self.webView.injectMouseMove(x, y)
                #self.notify.debug('injecting mouse move %d %d' % (x,y))
                self.mx, self.my = x, y

            if self.webView.isDirty():
                #self.notify.debug("webview is dirty")
                self.webView.render(self.imgBuffer.buffer_info()[0],
                                    WEB_WIDTH * 4, 4)
                #Texture.setTexturesPower2(AutoTextureScale.ATSUp)
                Texture.setTexturesPower2(2)
                #self.notify.debug("about to modify ram image")
                textureBuffer = self.guiTex.modifyRamImage()
                #import pdb; pdb.set_trace()
                #self.notify.debug("about to call textureBuffer.setData")
                textureBuffer.setData(self.imgBuffer.tostring())
                #self.notify.debug("done calling setData")
                if self.useHalfTexture:
                    # TODO check with DRose, this feels inefficient
                    self.guiTex.store(self.fullPnmImage)
                    self.leftPnmImage.copySubImage(self.fullPnmImage, 0, 0, 0,
                                                   0, WEB_HALF_WIDTH,
                                                   WEB_HEIGHT)
                    self.rightPnmImage.copySubImage(self.fullPnmImage, 0, 0,
                                                    WEB_HALF_WIDTH, 0,
                                                    WEB_HALF_WIDTH, WEB_HEIGHT)
                    self.leftGuiTex.load(self.leftPnmImage)
                    self.rightGuiTex.load(self.rightPnmImage)
                    self.quad.hide()
                #Texture.setTexturesPower2(AutoTextureScale.ATSDown)
                Texture.setTexturesPower2(1)

            GlobalWebcore.update()
        return Task.cont

    def _translateRelativeCoordinates(self, x, y):
        sx = int((x - self.mouseLL[0]) / (self.mouseUR[0] - self.mouseLL[0]) *
                 WEB_WIDTH_PIXELS)
        sy = WEB_HEIGHT_PIXELS - int(
            (y - self.mouseLL[1]) /
            (self.mouseUR[1] - self.mouseLL[1]) * WEB_HEIGHT_PIXELS)
        return sx, sy

    def unload(self):
        """Clean up everything, especially the awesomium bits."""
        self.ignoreAll()
        self.webView.destroy()
        self.webView = None
        #global GlobalWebcore
        #GlobalWebcore = None
        pass

    # --------------------[ WebViewListener implementation ]--------------------------
    def onCallback(self, name, args):
        assert self.notify.debugStateCall(self)
        if name == "requestFPS":
            #self.webView.setProperty( "fps", JSValue("%.1f" % (1.0 / globalClock.getDt())) )
            #self.webView.executeJavascript("updateFPS()", "")
            pass

    def onBeginNavigation(self, url, frameName):
        assert self.notify.debugStateCall(self)
        pass

    def onBeginLoading(self, url, frameName, statusCode, mimeType):
        assert self.notify.debugStateCall(self)
        pass

    def onFinishLoading(self):
        assert self.notify.debugStateCall(self)
        self.notify.debug("finished loading")
        pass

    def onReceiveTitle(self, title, frameName):
        assert self.notify.debugStateCall(self)
        pass

    def onChangeTooltip(self, tooltip):
        assert self.notify.debugStateCall(self)
        pass

    def onChangeCursor(self, cursor):
        assert self.notify.debugStateCall(self)
        pass

    def onChangeKeyboardFocus(self, isFocused):
        assert self.notify.debugStateCall(self)
        pass

    def onChangeTargetURL(self, url):
        assert self.notify.debugStateCall(self)
        pass
Ejemplo n.º 6
0
Archivo: GXO.py Proyecto: crempp/psg
class GXOStar(GXOBase):
	def __init__(self, parent=render, pos=Vec3(50,0,0)):
		GXOBase.__init__(self, parent, pos)
				
		self._initializeFlare()
	
	def _initializeFlare(self):
		# Parameters
		self.distance     = 130000.0
		self.threshold    = 0.3
		self.radius       = 0.8
		self.strength     = 1.0
		self.suncolor     = Vec4( 1, 1, 1, 1 )
		self.suncardcolor = Vec4( 1, 1, 0, 0 )
		
		# Initialize some values
		self.obscured = 0.0
		
		# flaredata will hold the rendered image 
		self.flaredata = PNMImage()
		# flaretexture will store the rendered buffer
		self.flaretexture = Texture()
		
		# Create a 10x10 texture buffer for the flare
		self.flarebuffer = base.win.makeTextureBuffer("Flare Buffer", 10, 10)
		# Attach the texture to the buffer
		self.flarebuffer.addRenderTexture(self.flaretexture, GraphicsOutput.RTMCopyRam)
		self.flarebuffer.setSort(-100)
		
		# Camera that renders the flare buffer
		self.flarecamera = base.makeCamera(self.flarebuffer)
		#self.flarecamera.reparentTo(base.cam)
		#self.flarecamera.setPos(-50,0,0)
		self.ortlens = OrthographicLens()
		self.ortlens.setFilmSize(10, 10) # or whatever is appropriate for your scene
		self.ortlens.setNearFar(1,self.distance)
		self.flarecamera.node().setLens(self.ortlens)
		self.flarecamera.node().setCameraMask(GXMgr.MASK_GXM_HIDDEN)
		
		# Create a light for the flare
		self.sunlight = self.baseNode.attachNewNode(PointLight("Sun:Point Light"))
		self.sunlight.node().setColor(self.suncolor)
		self.sunlight.node().setAttenuation(Vec3( 0.1, 0.04, 0.0 ))
		
		# Load texture cards
		# Create a nodepath that'll hold the texture cards for the new lens-flare
		self.texcardNP = aspect2d.attachNewNode('Sun:flareNode1')
		self.texcardNP.attachNewNode('Sun:fakeHdr')
		self.texcardNP.attachNewNode('Sun:starburstNode')
		# Load a circle and assign it a color. This will be used to calculate
		# Flare occlusion
		self.starcard = loader.loadModel('../data/models/unitcircle.egg')
		self.starcard.reparentTo(self.baseNode)
		self.starcard.setColor(self.suncardcolor)
		self.starcard.setScale(1)
		#self.starcard.setTransparency(TransparencyAttrib.MAlpha)
		# This is necessary since a billboard always rotates the y-axis to the
		# target but we need the z-axis
		self.starcard.setP(-90)
		self.starcard.setBillboardPointEye(self.flarecamera, 0.0)
		# Don't let the main camera see the star card
		self.starcard.show(GXMgr.MASK_GXM_HIDDEN)
		self.starcard.hide(GXMgr.MASK_GXM_VISIBLE)
		
		#the models are really just texture cards create with egg-texture-cards
		# from the actual pictures
		self.hdr = loader.loadModel('../data/models/fx_flare.egg')
		self.hdr.reparentTo(self.texcardNP.find('**/Sun:fakeHdr'))
		
		# Flare specs
		self.starburst_0 = loader.loadModel('../data/models/fx_starburst_01.egg')
		self.starburst_1 = loader.loadModel('../data/models/fx_starburst_02.egg')
		self.starburst_2 = loader.loadModel('../data/models/fx_starburst_03.egg')
		self.starburst_0.setPos(0.5,0,0.5)
		self.starburst_1.setPos(0.5,0,0.5)
		self.starburst_2.setPos(0.5,0,0.5)
		self.starburst_0.setScale(.2)
		self.starburst_1.setScale(.2)
		self.starburst_2.setScale(.2)
		self.starburst_0.reparentTo(self.texcardNP.find('**/Sun:starburstNode'))
		self.starburst_1.reparentTo(self.texcardNP.find('**/Sun:starburstNode'))
		self.starburst_2.reparentTo(self.texcardNP.find('**/Sun:starburstNode'))
		
		self.texcardNP.setTransparency(TransparencyAttrib.MAlpha)
		# Put the texture cards in the background bin
		self.texcardNP.setBin('background', 0)
		# The texture cards do not affect the depth buffer
		self.texcardNP.setDepthWrite(False)
		
		#attach a node to the screen middle, used for some math
		self.mid2d = aspect2d.attachNewNode('mid2d')
		
		#start the task that implements the lens-flare
		taskMgr.add(self._flareTask, 'Sun:flareTask')
		
	## this function returns the aspect2d position of a light source, if it enters the cameras field of view
	def _get2D(self, nodePath):
		#get the position of the light source relative to the cam
		p3d = base.cam.getRelativePoint(nodePath, Point3(0,0,0))
		p2d = Point2()
		
		#project the light source into the viewing plane and return 2d coordinates, if it is in the visible area(read: not behind the cam)
		if base.cam.node().getLens().project(p3d, p2d):
			return p2d
		
		return None

	def _getObscured(self, color):
		# This originally looked for the radius of the light but that caused
		# assertion errors. Now I use the radius of the hdr model.
		bounds = self.starcard.getBounds()
		#print ("bounds=%s rad=%s"%(bounds,bounds.getRadius()))
		if not bounds.isEmpty():
			r = bounds.getRadius()
			# Setting the film size sets the field-of-view and the aspect ratio
			# Maybe this should be done with setAspectRation() and setFov()
			self.ortlens.setFilmSize(r * self.radius, r * self.radius)
			
			# Point the flarecamera at the sun so we can determine if anything
			# is obscurring the sun
			self.flarecamera.lookAt(self.baseNode)
			
			# Renders the next frame in all the registered windows, and flips
			# all of the frame buffers. This will populate flaretexture since
			# it's attached to the flarebuffer.
			# Save the rendered frame in flaredata
			base.graphicsEngine.renderFrame()
			self.flaretexture.store(self.flaredata)
			
			#print ("flaredata=%s | color=%s"%(self.flaredata.getXel(5,5), color))
			
			# Initialize the obscured factor
			obscured = 100.0
			color = VBase3D(color[0],color[1],color[2])
			for x in xrange(0,9):
				for y in xrange(0,9):
					if color.almostEqual(self.flaredata.getXel(x,y), self.threshold):
						obscured -=  1.0
		else:
			obscured = 0
		return obscured
	
	
	def _flareTask(self, task):
		#going through the list of lightNodePaths
		#for index in xrange(0, len(self.lightNodes)):
			
		pos2d = self._get2D(self.sunlight)
		#if the light source is visible from the cam's point of view,
		# display the lens-flare
		if pos2d:
			#print ("Flare visible")
			
			# The the obscured factor
			obscured = self._getObscured(self.suncardcolor)
			# Scale it to [0,1]
			self.obscured = obscured/100
			##print obscured
			
			# Length is the length of the vector that goes from the screen
			# middle to the pos of the light. The length gets smaller the
			# closer the light is to the screen middle, however, since
			# length is used to calculate the brightness of the effect we
			# actually need an inverse behaviour, since the brightness
			# will be greates when center of screen= pos of light
			length = math.sqrt(pos2d.getX()*pos2d.getX()+pos2d.getY()*pos2d.getY())
			invLength= 1.0-length*2
			# Subtract the obscured factor from the inverted distence and
			# we have a value that simulates the power of the flare
			#brightness
			flarePower=invLength-self.obscured
			#print("light pos=%s | length=%s"%(pos2d,length))
			print("obs=%s | length=%s | inv=%s | pow=%s"%(self.obscured,length,invLength,flarePower))
			
			# Clamp the flare power to some values
			if flarePower < 0 and self.obscured > 0: flarePower = 0.0
			if flarePower < 0 and self.obscured <= 0: flarePower = 0.3
			if flarePower > 1  : flarePower = 1
			
			print("flarepower=%s"%(flarePower))
			
			#
			if self.obscured >= 0.8:
				self.texcardNP.find('**/Sun:starburstNode').hide()
			else:
				self.texcardNP.find('**/Sun:starburstNode').show()
				
				#drawing the lens-flare effect...
				r= self.suncolor.getX()
				g= self.suncolor.getY()
				b= self.suncolor.getZ()
				r = math.sqrt(r*r+length*length) * self.strength
				g = math.sqrt(g*g+length*length) * self.strength
				b = math.sqrt(b*b+length*length) * self.strength
				print("%s,%s,%s"%(r,g,b))
				
				# 
				if self.obscured > 0.19:
					a = self.obscured - 0.2
				else:
					a = 0.4 - flarePower
				
				#
				if a < 0 : a = 0
				if a > 0.8 : a = 0.8
				
				#
				self.hdr.setColor(r,g,b,0.8-a)
				self.hdr.setR(90*length)
				self.texcardNP.find('**/Sun:starburstNode').setColor(r,g,b,0.5+length)
				self.hdr.setPos(pos2d.getX(),0,pos2d.getY())
				self.hdr.setScale(8.5+(5*length))
				
				vecMid = Vec2(self.mid2d.getX(), self.mid2d.getZ())
				vec2d = Vec2(vecMid-pos2d)
				vec3d = Vec3(vec2d.getX(), 0, vec2d.getY())
				
				self.starburst_0.setPos(self.hdr.getPos()-(vec3d*10))
				self.starburst_1.setPos(self.hdr.getPos()-(vec3d*5))
				self.starburst_2.setPos(self.hdr.getPos()-(vec3d*10))
				self.texcardNP.show()
				#print "a",a
		else:
			#hide the lens-flare effect for a light source, if it is not visible...
			self.texcardNP.hide()
			
		return Task.cont
Ejemplo n.º 7
0
class TexturePainter(DirectObject):
    def __init__(self):
        self.editTexture = None
        self.editModel = None

        self.texturePainterStatus = TEXTURE_PAINTER_STATUS_DISABLED

        self.paintColor = VBase4D(1, 1, 1, 1)
        self.paintSize = 10
        self.paintEffect = PNMBrush.BEBlend
        self.paintSmooth = True
        self.paintMode = TEXTUREPAINTER_FUNCTION_PAINT_POINT

        self.painter = None

    # --- creation and destroying of the whole editor ---
    def enableEditor(self):
        ''' create the editor
    change from disabled to enabled'''
        if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_DISABLED:
            self.texturePainterStatus = TEXTURE_PAINTER_STATUS_ENABLED
            self.__enableEditor()
        else:
            print "E: TexturePainter.enableEditor: not disabled", self.texturePainterStatus

    def disableEditor(self):
        ''' destroy the editor, automatically stop the editor and painting
    change from enabled to disabled'''
        # try stopping if more advanced mode
        #if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
        #  self.stopEditor()

        if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_ENABLED:
            self.texturePainterStatus = TEXTURE_PAINTER_STATUS_DISABLED
            self.__disableEditor()
        else:
            print "E: TexturePainter.disableEditor: not enabled", self.texturePainterStatus

    # ---
    def startEditor(self,
                    editModel,
                    editTexture,
                    backgroundShader=MODEL_COLOR_SHADER):
        ''' prepare to paint
    change from enabled to initialized'''
        if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_ENABLED:
            self.texturePainterStatus = TEXTURE_PAINTER_STATUS_INITIALIZED
            self.__startEditor(editModel, editTexture, backgroundShader)
        else:
            print "E: TexturePainter.startEditor: not enabled", self.texturePainterStatus

    def stopEditor(self):
        ''' stop painting, automatically stop painting
    change from initialized to enabled'''
        #if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
        #  self.stopPaint()
        if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
            self.texturePainterStatus = TEXTURE_PAINTER_STATUS_ENABLED
            return self.__stopEditor()
        else:
            print "E: TexturePainter.startEditor: not initialized", self.texturePainterStatus

    """ # this is not externally callable
  # ---
  def startPaint(self):
    ''' start painting on the model
    change from initialized to running '''
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_RUNNING
      self.__startPaint()
    else:
      print "E: TexturePainter.startPaint: not enabled", self.texturePainterStatus"""

    def stopPaint(self):
        ''' stop painting
    change from running to initialized '''
        if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_RUNNING:
            self.texturePainterStatus = TEXTURE_PAINTER_STATUS_INITIALIZED
            self.__stopPaint()
        else:
            print "E: TexturePainter.stopPaint: not running", self.texturePainterStatus

    # --- brush settings for painting ---
    ''' changing brush settings is possible all the time '''

    def setBrushSettings(self, color, size, smooth, effect):
        #print "I: TexturePainter.setBrushSettings", color, size, smooth, effect
        self.paintColor = color
        self.paintSize = size
        self.paintEffect = effect
        self.paintSmooth = smooth
        if effect in [
                PNMBrush.BESet, PNMBrush.BEBlend, PNMBrush.BEDarken,
                PNMBrush.BELighten
        ]:
            self.brush = PNMBrush.makeSpot(color, size, smooth, effect)
            #if self.paintModel:
            if self.painter:
                self.painter.setPen(self.brush)

    def getBrushSettings(self):
        return self.paintColor, self.paintSize, self.paintSmooth, self.paintEffect

    def setPaintMode(self, newMode):
        self.paintMode = newMode
        # clear last point if mode changed
        if newMode == TEXTUREPAINTER_FUNCTION_PAINT_POINT or \
           newMode == TEXTUREPAINTER_FUNCTION_READ:
            self.lastPoint = None

    def getPaintMode(self):
        return self.paintMode

    def __enableEditor(self):
        ''' create the background rendering etc., but the model is not yet defined '''
        print "I: TexturePainter.__enableEditor"
        # the buffer the model with the color texture is rendered into
        self.modelColorBuffer = None
        self.modelColorCam = None
        # the buffer the picked position color is rendered into
        self.colorPickerBuffer = None
        self.colorPickerCam = None
        # create the buffers
        self.__createBuffer()

        # when the window is resized, the background buffer etc must be updated.
        self.accept("window-event", self.__windowEvent)

        # some debugging stuff
        self.accept("v", base.bufferViewer.toggleEnable)
        self.accept("V", base.bufferViewer.toggleEnable)

    def __disableEditor(self):
        print "I: TexturePainter.__disableEditor"

        self.__destroyBuffer()

        # ignore window-event and debug
        self.ignoreAll()

    def __windowEvent(self, win=None):
        ''' when the editor is enabled, update the buffers etc. when the window
    is resized '''
        print "I: TexturePainter.windowEvent"

        # with a fixed backgroudn buffer size this is not needed anymore

        if False:
            #if self.texturePainterStatus != TEXTURE_PAINTER_STATUS_DISABLED:
            if self.modelColorBuffer:
                if WindowManager.activeWindow:
                    # on window resize there seems to be never a active window
                    win = WindowManager.activeWindow.win
                else:
                    win = base.win
                if self.modelColorBuffer.getXSize() != win.getXSize(
                ) or self.modelColorBuffer.getYSize() != win.getYSize():
                    '''print "  - window resized",\
              self.modelColorBuffer.getXSize(),\
              win.getXSize(),\
              self.modelColorBuffer.getYSize(),\
              win.getYSize()'''
                    # if the buffer size doesnt match the window size (window has been resized)
                    self.__destroyBuffer()
                    self.__createBuffer()
                    self.__updateModel()
            else:
                print "W: TexturePainter.__windowEvent: no buffer"
                self.__createBuffer()

    def __createBuffer(self):
        ''' create the buffer we render in the background into '''
        print "I: TexturePainter.__createBuffer"
        # the window has been modified
        if WindowManager.activeWindow:
            # on window resize there seems to be never a active window
            win = WindowManager.activeWindow.win
        else:
            win = base.win

        # get the window size
        self.windowSizeX = win.getXSize()
        self.windowSizeY = win.getYSize()

        # create a buffer in which we render the model using a shader
        self.paintMap = Texture()
        # 1.5.4 cant handle non power of 2 buffers
        self.modelColorBuffer = createOffscreenBuffer(
            -3, TEXTUREPAINTER_BACKGROUND_BUFFER_RENDERSIZE[0],
            TEXTUREPAINTER_BACKGROUND_BUFFER_RENDERSIZE[1]
        )  #self.windowSizeX, self.windowSizeY)
        self.modelColorBuffer.addRenderTexture(self.paintMap,
                                               GraphicsOutput.RTMBindOrCopy,
                                               GraphicsOutput.RTPColor)
        self.modelColorCam = base.makeCamera(self.modelColorBuffer,
                                             lens=base.cam.node().getLens(),
                                             sort=1)

        # Create a small buffer for the shader program that will fetch the point from the texture made
        # by the self.modelColorBuffer
        self.colorPickerImage = PNMImage()
        self.colorPickerTex = Texture()
        self.colorPickerBuffer = base.win.makeTextureBuffer(
            "color picker buffer", 2, 2, self.colorPickerTex, True)

        self.colorPickerScene = NodePath('color picker scene')

        self.colorPickerCam = base.makeCamera(self.colorPickerBuffer,
                                              lens=base.cam.node().getLens(),
                                              sort=2)
        self.colorPickerCam.reparentTo(self.colorPickerScene)
        self.colorPickerCam.setY(-2)

        cm = CardMaker('color picker scene card')
        cm.setFrameFullscreenQuad()
        pickerCard = self.colorPickerScene.attachNewNode(cm.generate())

        loadPicker = NodePath(PandaNode('pointnode'))
        loadPicker.setShader(Shader.make(COLOR_PICKER_SHADER), 10001)

        # Feed the paintmap from the paintBuffer to the shader and initial mouse positions
        self.colorPickerScene.setShaderInput('paintmap', self.paintMap)
        self.colorPickerScene.setShaderInput('mousepos', 0, 0, 0, 1)
        self.colorPickerCam.node().setInitialState(loadPicker.getState())

    def __destroyBuffer(self):
        print "I: TexturePainter.__destroyBuffer"
        if self.modelColorBuffer:

            # Destroy the buffer
            base.graphicsEngine.removeWindow(self.modelColorBuffer)
            self.modelColorBuffer = None
            # Remove the camera
            self.modelColorCam.removeNode()
            del self.modelColorCam

            self.colorPickerScene.removeNode()
            del self.colorPickerScene
            # remove cam
            self.colorPickerCam.removeNode()
            del self.colorPickerCam
            # Destroy the buffer
            base.graphicsEngine.removeWindow(self.colorPickerBuffer)
            self.colorPickerBuffer = None

            del self.colorPickerTex
            del self.colorPickerImage

    def __startEditor(self,
                      editModel,
                      editTexture,
                      backgroundShader=MODEL_COLOR_SHADER):
        print "I: TexturePainter.__startEditor"

        # this is needed as on startup the editor may not have had a window etc.
        self.__windowEvent()

        if not editModel or not editTexture:
            print "W: TexturePainter.__startEditor: model or texture invalid", editModel, editTexture
            return False

        self.editModel = editModel
        self.editTexture = editTexture
        self.editImage = None
        self.backgroundShader = backgroundShader

        if type(self.editTexture) == Texture:
            # if the image to modify is a texture, create a pnmImage which we modify
            self.editImage = PNMImage()
            # copy the image from the texture to the working layer
            self.editTexture.store(self.editImage)
        else:
            self.editImage = self.editTexture

        # create the brush for painting
        self.painter = PNMPainter(self.editImage)
        self.setBrushSettings(*self.getBrushSettings())

        self.__updateModel()

        # start edit
        messenger.send(EVENT_TEXTUREPAINTER_STARTEDIT)

        for startEvent in TEXTUREPAINTER_START_PAINT_EVENTS:
            self.accept(startEvent, self.__startPaint)
        for stopEvent in TEXTUREPAINTER_STOP_PAINT_EVENTS:
            self.accept(stopEvent, self.__stopPaint)

        self.modelColorCam.node().copyLens(
            WindowManager.activeWindow.camera.node().getLens())

        taskMgr.add(self.__paintTask, 'paintTask')

        #modelModificator.toggleEditmode(False)

        self.isPainting = False

    def __stopEditor(self):
        print "I: TexturePainter.__stopEditor"
        for startEvent in TEXTUREPAINTER_START_PAINT_EVENTS:
            self.ignore(startEvent)
        for stopEvent in TEXTUREPAINTER_STOP_PAINT_EVENTS:
            self.ignore(stopEvent)

        taskMgr.remove('paintTask')
        # stop edit end

        # must be reset before we loose the properties
        if self.editModel and self.editTexture and self.editImage:
            try:
                # hide the model from cam 2
                self.editModel.hide(BitMask32.bit(1))
                self.editModel = None
            except:
                print "E: TexturePainter.__stopEditor: the model has already been deleted"

        # stop edit
        messenger.send(EVENT_TEXTUREPAINTER_STOPEDIT)

        self.editImage = None
        self.editTexture = None
        self.painter = None
        self.brush = None

        #modelModificator.toggleEditmode(True)

    def __updateModel(self):
        if self.editModel:
            # create a image with the same size of the texture
            textureSize = (self.editTexture.getXSize(),
                           self.editTexture.getYSize())

            # create a dummy node, where we setup the parameters for the background rendering
            loadPaintNode = NodePath(PandaNode('paintnode'))
            loadPaintNode.setShader(Shader.make(self.backgroundShader), 10001)
            loadPaintNode.setShaderInput('texsize', textureSize[0],
                                         textureSize[1], 0, 0)

            # copy the state onto the camera
            self.modelColorCam.node().setInitialState(loadPaintNode.getState())

            # the camera gets a special bitmask, to show/hide models from it
            self.modelColorCam.node().setCameraMask(BitMask32.bit(1))

            if False:
                # doesnt work, but would be nicer (not messing with the default render state)

                hiddenNode = NodePath(PandaNode('hiddennode'))
                hiddenNode.hide(BitMask32.bit(1))
                showTroughNode = NodePath(PandaNode('showtroughnode'))
                showTroughNode.showThrough(BitMask32.bit(1))

                self.modelColorCam.node().setTagStateKey(
                    'show-on-backrender-cam')
                self.modelColorCam.node().setTagState('False',
                                                      hiddenNode.getState())
                self.modelColorCam.node().setTagState(
                    'True', showTroughNode.getState())

                render.setTag('show-on-backrender-cam', 'False')
                self.editModel.setTag('show-on-backrender-cam', 'True')
            else:
                # make only the model visible to the background camera
                render.hide(BitMask32.bit(1))
                self.editModel.showThrough(BitMask32.bit(1))

    # --- start the paint tasks ---
    def __startPaint(self):
        self.isPainting = True

    def __stopPaint(self):
        self.isPainting = False

    # --- modification tasks ---
    def __textureUpdateTask(self, task=None):
        ''' modify the texture using the edited image
    '''
        if type(self.editTexture) == Texture:
            self.editTexture.load(self.editImage)

        if task:  # task may be None
            return task.again

    def __paintTask(self, task):
        #print "I: TexturePainter.__paintTask:"

        if not WindowManager.activeWindow or not WindowManager.activeWindow.mouseWatcherNode.hasMouse(
        ):
            '''print "  - abort:", WindowManager.activeWindow
      if WindowManager.activeWindow:
        print "  - mouse:", WindowManager.activeWindow.mouseWatcherNode.hasMouse()'''
            return task.cont

        # update the camera according to the active camera
        #self.modelColorCam.setMat(render, WindowManager.activeWindow.camera.getMat(render))

        mpos = base.mouseWatcherNode.getMouse()
        x_ratio = min(max(((mpos.getX() + 1) / 2), 0), 1)
        y_ratio = min(max(((mpos.getY() + 1) / 2), 0), 1)
        mx = int(x_ratio * self.windowSizeX)
        my = self.windowSizeY - int(y_ratio * self.windowSizeY)

        self.colorPickerScene.setShaderInput('mousepos', x_ratio, y_ratio, 0,
                                             1)

        if self.colorPickerTex.hasRamImage():
            self.colorPickerTex.store(self.colorPickerImage)

            # get the color below the mousepick from the rendered frame
            r = self.colorPickerImage.getRedVal(0, 0)
            g = self.colorPickerImage.getGreenVal(0, 0)
            b = self.colorPickerImage.getBlueVal(0, 0)
            # calculate uv-texture position from the color
            x = r + ((b % 16) * 256)
            y = g + ((b // 16) * 256)

            if self.isPainting:
                self.__paintPixel(x, y)
                self.__textureUpdateTask()
        else:
            # this might happen if no frame has been rendered yet since creation of the texture
            print "W: TexturePainter.__paintTask: colorPickerTex.hasRamMipmapImage() =", self.colorPickerTex.hasRamImage(
            )

        return task.cont

    def __paintPixel(self, x, y):
        ''' paint at x/y with the defined settings '''

        imageMaxX = self.editImage.getXSize()
        imageMaxY = self.editImage.getYSize()

        def inImage(x, y):
            ''' is the given x/y position within the image '''
            return ((imageMaxX > x >= 0) and (imageMaxY > y >= 0))

        # how smooth should be painted
        if self.paintSmooth:
            # a smooth brush
            hardness = 1.0
        else:
            # a hard brush
            hardness = 0.1
        hardness = min(1.0, max(0.05, hardness))

        # the paint radius
        radius = int(round(self.paintSize / 2.0))
        radiusSquare = float(radius * radius)

        # a function to get the brush color/strength, depending on the radius
        def getBrushColor(diffPosX, diffPosY):
            distance = diffPosX**2 + diffPosY**2
            brushStrength = (
                1 - (min(distance, radiusSquare) / radiusSquare)) / hardness
            return min(1.0, max(0.0, brushStrength))

        if inImage(x, y):
            if self.paintMode == TEXTUREPAINTER_FUNCTION_PAINT_POINT:
                if self.paintEffect in [
                        PNMBrush.BESet, PNMBrush.BEBlend, PNMBrush.BEDarken,
                        PNMBrush.BELighten
                ]:
                    # render a spot into the texture
                    self.painter.drawPoint(x, y)

                elif self.paintEffect in [
                        TEXTUREPAINTER_BRUSH_FLATTEN,
                        TEXTUREPAINTER_BRUSH_SMOOTH,
                        TEXTUREPAINTER_BRUSH_RANDOMIZE
                ]:

                    if self.paintEffect == TEXTUREPAINTER_BRUSH_SMOOTH:
                        # calculate average values
                        data = dict()
                        smoothRadius = 2
                        for dx in xrange(-radius, radius + 1):
                            for dy in xrange(-radius, radius + 1):
                                if inImage(x + dx, y + dy):
                                    average = VBase4D(0)
                                    dividor = 0
                                    for px in xrange(-smoothRadius,
                                                     smoothRadius + 1):
                                        for py in xrange(
                                                -smoothRadius,
                                                smoothRadius + 1):
                                            if inImage(x + dx + px,
                                                       y + dy + py):
                                                average += self.editImage.getXelA(
                                                    x + dx + px, y + dy + py)
                                                dividor += 1
                                    average /= float(dividor)
                                    data[(x + dx, y + dy)] = average

                        # save to image
                        for (px, py), newValue in data.items():
                            currentValue = self.editImage.getXelA(px, py)
                            diffValue = currentValue - newValue

                            dx = px - x
                            dy = py - y

                            multiplier = getBrushColor(dx, dy)
                            print dx, dy, multiplier
                            '''if self.paintSmooth:
                multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
              else:
                # not sure if this is correct
                multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
                            '''r = currentValue.getX() * (1-multiplier*self.paintColor.getX()) + diffValue.getX() * multiplier*self.paintColor.getX()
              g = currentValue.getY() * (1-multiplier*self.paintColor.getY()) + diffValue.getY() * multiplier*self.paintColor.getY()
              b = currentValue.getZ() * (1-multiplier*self.paintColor.getZ()) + diffValue.getZ() * multiplier*self.paintColor.getZ()
              a = currentValue.getW() * (1-multiplier*self.paintColor.getW()) + diffValue.getW() * multiplier*self.paintColor.getW()'''
                            r = currentValue.getX(
                            ) - multiplier * diffValue.getX()
                            g = currentValue.getY(
                            ) - multiplier * diffValue.getY()
                            b = currentValue.getZ(
                            ) - multiplier * diffValue.getZ()
                            a = currentValue.getW(
                            ) - multiplier * diffValue.getW()
                            if self.editImage.hasAlpha():
                                self.editImage.setXelA(px, py,
                                                       VBase4D(r, g, b, a))
                            else:
                                self.editImage.setXel(px, py, VBase3D(r, g, b))

                            #self.editImage.setXelA(x,y,value)

                    if self.paintEffect == TEXTUREPAINTER_BRUSH_FLATTEN:
                        dividor = 0
                        average = VBase4D(0)
                        for dx in xrange(-radius, radius + 1):
                            for dy in xrange(-radius, radius + 1):
                                if inImage(x + dx, y + dy):
                                    multiplier = getBrushColor(dx, dy)
                                    '''if self.paintSmooth:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
                  else:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
                                    dividor += multiplier
                                    average += self.editImage.getXelA(
                                        x + dx, y + dy) * multiplier
                        average /= dividor
                        for dx in xrange(-radius, radius + 1):
                            for dy in xrange(-radius, radius + 1):
                                if inImage(x + dx, y + dy):
                                    multiplier = getBrushColor(dx, dy)
                                    '''if self.paintSmooth:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
                  else:
                    # not sure if this is correct
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
                                    currentValue = self.editImage.getXelA(
                                        x + dx, y + dy)
                                    r = currentValue.getX() * (
                                        1 -
                                        multiplier * self.paintColor.getX()
                                    ) + average.getX(
                                    ) * multiplier * self.paintColor.getX()
                                    g = currentValue.getY() * (
                                        1 -
                                        multiplier * self.paintColor.getY()
                                    ) + average.getY(
                                    ) * multiplier * self.paintColor.getY()
                                    b = currentValue.getZ() * (
                                        1 -
                                        multiplier * self.paintColor.getZ()
                                    ) + average.getZ(
                                    ) * multiplier * self.paintColor.getZ()
                                    a = currentValue.getW() * (
                                        1 -
                                        multiplier * self.paintColor.getW()
                                    ) + average.getW(
                                    ) * multiplier * self.paintColor.getW()
                                    if self.editImage.hasAlpha():
                                        self.editImage.setXelA(
                                            x + dx, y + dy,
                                            VBase4D(r, g, b, a))
                                    else:
                                        self.editImage.setXel(
                                            x + dx, y + dy, VBase3D(r, g, b))

                    elif self.paintEffect == TEXTUREPAINTER_BRUSH_RANDOMIZE:
                        for dx in xrange(-radius, radius + 1):
                            for dy in xrange(-radius, radius + 1):
                                if inImage(x + dx, y + dy):
                                    r = VBase4D(
                                        random.random() *
                                        self.paintColor.getX() -
                                        self.paintColor.getX() / 2.,
                                        random.random() *
                                        self.paintColor.getY() -
                                        self.paintColor.getY() / 2.,
                                        random.random() *
                                        self.paintColor.getZ() -
                                        self.paintColor.getZ() / 2.,
                                        random.random() *
                                        self.paintColor.getW() -
                                        self.paintColor.getW() / 2.)
                                    multiplier = getBrushColor(dx, dy)
                                    '''if self.paintSmooth:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
                  else:
                    # not sure if this is correct
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
                                    currentValue = self.editImage.getXelA(
                                        x + dx, y + dy)
                                    self.editImage.setXelA(
                                        x + dx, y + dy,
                                        currentValue + r * multiplier)

            elif self.paintMode == TEXTUREPAINTER_FUNCTION_READ:
                if inImage(x, y):
                    col = self.editImage.getXelA(x, y)
                    if self.editImage.hasAlpha():
                        self.paintColor = VBase4D(col[0], col[1], col[2],
                                                  col[3])
                    else:
                        self.paintColor = VBase4D(col[0], col[1], col[2], 1.0)
                    messenger.send(EVENT_TEXTUREPAINTER_BRUSHCHANGED)

            elif self.paintMode == TEXTUREPAINTER_FUNCTION_PAINT_LINE:
                if self.lastPoint != None:
                    self.painter.drawLine(x, y, self.lastPoint[0],
                                          self.lastPoint[1])

            elif self.paintMode == TEXTUREPAINTER_FUNCTION_PAINT_RECTANGLE:
                if self.lastPoint != None:
                    self.painter.drawRectangle(x, y, self.lastPoint[0],
                                               self.lastPoint[1])

            self.lastPoint = (x, y)