Interactive/BackdropCustom.py

# (C) Copyright 2012 Autodesk, Inc.  All rights reserved.
#
# Use of this software is subject to the terms of the Autodesk license
# agreement provided at the time of installation or download, or which
# otherwise accompanies this software in either electronic or hard copy
# form.

__all__ = ['BackdropCustom', 'instantiate']

# Put a movie on the backdrop.  Must be in the backdrop environment for it to work.
#

theDynamicTextureId = "dtx:BackdropMovie"

from Application         import theApplication
from awSupportApi        import ApplicationMode, PerformanceMonitor
from MessageInterpreter  import MessageInterpreter
from RTFapi              import AviFrames, VoidPointer, DynamicTextures
from UserCustomization   import UserCustomBase, CustomInfo
from WarningWindow       import WarningWindow

import wx

class BackdropCustom (UserCustomBase):
    def __init__(self):
        self.myBackdropId = None
        self.myTextureId = None
        self.myWindow = None
        self.myInterpreter = LocalInterpreter()

    def getInterpreter(self,isInteractive):
        if isInteractive:
            return self.myInterpreter
        return None

    def appendMenuItems(self,id,menu):
        if "Appearance" == id:
            self.myBackdropId = menu.appendItem(_( 'Add backdrop movie' ),
                                                self.__onBackdrop )
            self.myTextureId = menu.appendItem(_( 'Add movie texture' ),
                                               self.__onTexture )
            self.myWindow = menu.getParentWindow()

    def enableMenuStates(self,id,enableStates):
        if "Appearance" == id:
            if self.myInterpreter:
                enabled = self.myInterpreter.Enabled()
            else:
                enabled = False
            enableStates[self.myBackdropId] = enabled
            enableStates[self.myTextureId] = enabled

    # ------------------------------------------------

    def __onBackdrop( self, event ):
        if self.myInterpreter:
            dlg = wx.FileDialog( self.myWindow,
                                 message=_("Choose the movie file for the backdrop"),
                                 wildcard=_("Movie Files (*.avi)|*.avi|"),
                                 style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST )
            if dlg.ShowModal() == wx.ID_OK:
                output = dlg.GetPath()
                self.myInterpreter.Backdrop(output)

    def __onTexture( self, event ):
        if self.myInterpreter:
            dlg = wx.FileDialog( self.myWindow,
                                 message=_("Choose the movie file for texturing"),
                                 wildcard=_("Movie Files (*.avi)|*.avi|"),
                                 style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST )
            if dlg.ShowModal() == wx.ID_OK:
                output = dlg.GetPath()
                id = self.myInterpreter.Texture(output)

                ww = WarningWindow( self.myWindow,
                                    title=_("Movie texture"),
                                    message=_("Dynamic texture %s is now available.\nWrite this down, you will need it for the material properties dialog.") % (id),
                                    continueButtonLabel=_("OK"),
                                    cancelButtonLabel=None )
                ww.ShowModal()
                ww.Destroy()



# -----------------------------------------------------------------------

class LocalInterpreter( MessageInterpreter ):

    def __init__( self ):
        MessageInterpreter.__init__( self )
        self.myAviFrames = {}
        self.myCounter = {}
        self.myAviCounter = 0

    def NewID(self):
        self.myAviCounter += 1
        return "%s%d" % (theDynamicTextureId,self.myAviCounter)

    def Setup(self, filename):
        if filename in self.myAviFrames:
            return self.myAviFrames[filename][0]

        id = self.NewID()
        dt = DynamicTextures()
        dt.set(id,VoidPointer())

        # Turn off idle mode pause, as the movie could be playing all the time...
        PerformanceMonitor.instance().setForceAlwaysDraw( True );

        frames = AviFrames()
        self.myCounter[id] = 0
        ok = frames.load(filename)

        # Create the dynamic texture record for the particular size:
        dt.create(id, frames.width(), frames.height())

        # Point it to the correct memory location:
        dt.set(id,frames.frame())

        self.myAviFrames[filename] = (id,frames)
        return id


    def Backdrop( self, filename ):
        id = self.Setup(filename)
        self.sendMessage( 'ENVIRONMENT_CHANGE_BACKDROP_IMAGE',
                          ( (), id, () ))


    def Texture( self, filename ):
        id = self.Setup(filename)
        print "Dynamic texture %s now available." % (id)
        return id


    def Enabled( self ):
        # Should really check if the environment is a backdrop one
        return (ApplicationMode.instance().isAuthoringMode() and
                theApplication.getCurrentDocument() is not None)


    def FRAME_SYNCHRONIZE_START(self, message):
        for filename in self.myAviFrames:
            (id,frames) = self.myAviFrames[filename]

            # This will update the memory location that holds the image
            # and since the pointer itself doesn't change, we just need
            # to worry about setting it dirty with the modified call.
            frames.set(self.myCounter[id],True)
            DynamicTextures().modified(id)
            fc = frames.getFrameCount()
            if fc > 0:
                self.myCounter[id] = (self.myCounter[id]+1) % fc

# --------------------------------------------------------------------

def instantiate():
    # Are the relevant files elsewhere?
    # sys.path.append( "where the files are" )
    return BackdropCustom()


def info():
    customInfo = CustomInfo()
    customInfo.vendor = 'Autodesk'
    customInfo.version = '3.0'
    customInfo.api = '2013'
    customInfo.shortInfo = "Movies as textures"
    customInfo.longInfo = \
"""Set the backdrop image from a movie file, or create a dynamic texture from a movie file that can then be used instead of image files for any Showcase material."""
    return customInfo