Source

pygamekit / engine.pxi

Full commit

import sys, imp, traceback

cdef extern from "gkLogger.h":
    #cdef cppclass gkLogger:
    void gkLogger_enable "gkLogger::enable"(const_std_string&, bool verbose)
    void gkLogger_disable "gkLogger::disable"()
    void gkLogger_write "gkLogger::write"(const_std_string& msg, bool force = 0)
    
    void gkPrintf(char *fmt, ...)
    int GK_CPP_VERBOSE_LOG
    
cdef extern from "gkUserDefs.h":
    cdef cppclass gkUserDefs:
        void load(const_std_string& fname)
        void parseString(const_std_string& key, const_std_string& val)


        OgreRenderSystem        rendersystem       # Ogre render system to use
        std_string              viewportOrientation# portrait, landscaperight, landscapeleft
        int                     sceneManager       # TODO scene manager to use
        std_string              log                # Main log file name
        bool                    verbose            # Enable/Disable Ogre print-out
        gkmath.Vector2          winsize            # Window width & height
        std_string              wintitle           # Window title
        std_string              extWinhandle       # External Window Handle
        bool                    fullscreen         # Fullscreen mode
        int                     framingType        # crop/letterbox/extend. Used when window is larger then requested
        std_string              resources          # resources to load
        bool                    blendermat         # convert meshes using blender materials
        bool                    grabInput          # hide & grab the mouse
        bool                    debugFps           # show fps and profiling information
        bool                    debugPhysics       # enable / disable physics debugging
        bool                    debugPhysicsAabb   # show / hide bounding box
        bool                    buildStaticGeometry# Use Static geometry
        bool                    useBulletDbvt      # Use Bullet Dynamic AABB Tree
        bool                    showDebugProps     # Show variable debugging information.
        bool                    debugSounds        # Show 3D sound debug info
        bool                    disableSound       # Disable OpenAL sound.
        bool                    fsaa               # Enable Full scene anti aliasing.
        int                     fsaaSamples        # Anti aliasing samples.
        bool                    enableshadows
        int                     defaultMipMap      # Number of mipmaps to generate per texture (default 5)

        std_string                shadowtechnique
        #gkColor                 colourshadow
        #gkScalar                fardistanceshadow

        #static OgreRenderSystem getOgreRenderSystem(const_std_string& val)
        int getViewportFramingType(const_std_string& val)
        
cdef extern from "gkEngine.h":
    
    cdef cppclass pyEngineListener "gkEngine::Listener":
        pass
        
    cdef cppclass gkEngine:
                    
        gkEngine(gkUserDefs *defs)
        
        void initialize()
        void finalize()
        void run()

        bool initializeStepLoop()
        bool stepOneFrame()
        void finalizeStepLoop()

        bool isInitialized()
        bool isRunning()

        void initializeWindow()

        bool hasActiveScene()

        gkUserDefs& getUserDefs()
        void requestExit()

        void loadResources(const_std_string& name)

        #void addDebugProperty(gkVariable* prop)
        #void removeDebugProperty(gkVariable* prop)

        Real getStepRate()
        Real getTickRate()

        gkScene* getActiveScene()

        void registerActiveScene(gkScene* scene)
        void unregisterActiveScene(gkScene* scene)

        void addListener(pyEngineListener* listener)
        void removeListener(pyEngineListener* listener)

    gkEngine* gkEngine_getSingleton "&(gkEngine::getSingleton)"()


#cdef extern from "gkApplication.h":
#    int mein(gkEngine*)

cdef extern from "Graphics/gkHUDManager.h":
    cdef cppclass gkHUDManager:
        pass

cdef extern from "Graphics/gkHUD.h":
    cdef cppclass gkHUD:
        pass

cdef extern from "Graphics/gkHUDElement.h":
    cdef cppclass gkHUDElement:
        pass

cdef extern from "gkTextFile.h":
    cdef cppclass gkTextFile:
        std_string& getText()

cdef extern from "gkTextManager.h":
    void* gkTextManager_getByName "gkTextManager::getSingleton().getByName"(const_std_string&)
    bool gkTextManager_exists "gkTextManager::getSingleton().exists"(const_std_string&)

#----------------------------------------------------------------------------
# Globals
cdef list tick_callback = []
cdef bool initialized = False
cdef Engine currentEngine
    
cdef class Engine:
    cdef gkEngine *eng
    cdef gkClock *timer
    #cdef gkHUDManager* mgr

    def __init__(self, bfile=None, cfgfile=None, initialize=True, seek=0):
        
        global initialized, currentEngine
        
        if initialize:
            if cfgfile:
                prefs.load(to_stdstring(cfgfile))
                
            self.eng = new gkEngine(prefs)
            self.eng.initialize()
            if not self.eng.isInitialized():
                print("Failed to initialize enigne.")
                sys.exit(1)
            #self.mgr = new gkHUDManager()

            if bfile:
                self.load_blend(bfile, seek)
                
            self.eng.initializeStepLoop()
            
            self.timer = new gkClock()
            self.timer.reset()
            
            initialized = True
            currentEngine = self
            
    def __del__(self):
        self.eng.requestExit()

    property active_scene:
        def __get__(self):
            return Scene().P(self.eng.getActiveScene())

    def _step_one_frame(self):
        try:
            evaluate_all_callbacks()
        except SystemExit:
            return False
        except:
            traceback.print_exc()
        return self.eng.stepOneFrame()
    
    def load_blend(self, bfile, seek=0):
        cdef gkScene* scn
        
        b = BlendFile()
        b.load(bfile,IGNORE_CACHE_FILE,seek=seek)
        
        scn = self.eng.getActiveScene()
        
        if scn:
            copyObjects(b.bfile.getMainScene(), scn, OBJ_CAMERA | OBJ_LIGHT)
        else:
            scn = b.bfile.getMainScene()
            
            self.eng.registerActiveScene(scn)
            
            scn.createInstance()
            
    def run(self):
        while self._step_one_frame():
            pass

cdef class TickSensor(Sensor):
    
    def __init__(self):
        self.init_sensor(tick_callback)
        
    def __nonzero__(self):
        return True
            
cdef void evaluate_tick_callbacks() except *:
    for s in tick_callback[:]:
        (<TickSensor>s).execute()
    
cdef public void evaluate_all_callbacks() except *:
    
    #TODO: make tick time configurable (now fixed at 60)
    
    #For the moment will not compensate slow graphics with substeps,
    #so use tickSensor.elapsedTime to make your interactions proportional.
    
    #TODO: now I'm blocking to limir overall FPS, to fix collisions
    cdef int us=currentEngine.timer.getMicroseconds()
    if us<16666:
        usleep(16666-us)
    if 1:#currentEngine.timer.getMicroseconds()>16666: #60 FPS
        currentEngine.timer.reset()
        evaluate_input_callbacks()
        evaluate_collision_callbacks()
        evaluate_timer_callbacks()
        evaluate_tick_callbacks()
        
def get_engine():
    if currentEngine: return currentEngine
    
def get_active_scene():
    cdef gkEngine* e = gkEngine_getSingleton()
    return Scene().P(e.getActiveScene())

class TextBlockImporter(object):
    def find_module(self, module_name, package_path):
        if package_path: return
        module_name += '.py'
        if initialized and gkTextManager_exists(to_stdstring(module_name)):
            return self
            
    def load_module(self, module_name):
        mod = imp.new_module(module_name)
        sys.modules[module_name] = mod
        module_name += '.py'
        code = str((<gkTextFile*>gkTextManager_getByName(to_stdstring(module_name))).getText().c_str())
        exec code in mod.__dict__
        return mod

sys.meta_path.append(TextBlockImporter())
del TextBlockImporter

def has_text_block(name):
    if initialized: return gkTextManager_exists(to_stdstring(name))
    
def get_text_block(name):
    if initialized:
        return str((<gkTextFile*>gkTextManager_getByName(to_stdstring(name))).getText().c_str())
    
def reload_init():
    pass

def destroy_all_links():
    for c in tick_callback, key_callbacks, mouse_move_callbacks, mousebutton_callbacks, timer_callbacks:
        for s in c:
            (<Sensor>s).unlink_all()
        del(c[:])