Files
pyFun/utils_old.py
T
2014-07-07 18:18:56 -07:00

323 lines
12 KiB
Python

# Utility functions
# ToDo: Put everything in a class as staticmethods when imported, if
# name=__main__, keep them local
from pygame import locals as pygame_consts
from functools import partial
import inspect
import logging
import types
import pygame
from uniquelist import uniquelist
def register(list_to_register=None):
''' Used as decorator: Adds the function (or anything else) to list_to_register '''
def temp_func(what_to_register):
list_to_register.append(what_to_register)
return what_to_register
return temp_func
KW_EVENTS_IB = {
"QUIT": pygame_consts.QUIT,
"ACTIVE_EVENT": pygame_consts.ACTIVEEVENT,
"KEY_DOWN": pygame_consts.KEYDOWN,
"KEY_UP": pygame_consts.KEYUP,
"MOUSE_MOTION": pygame_consts.MOUSEMOTION,
"MOUSE_BUTTON_UP": pygame_consts.MOUSEBUTTONUP,
"MOUSE_BUTTON_DOWN": pygame_consts.MOUSEBUTTONDOWN,
"JOY_AXIS_MOTION": pygame_consts.JOYAXISMOTION,
"JOY_BALL_MOTION": pygame_consts.JOYBALLMOTION,
"JOY_HAT_MOTION": pygame_consts.JOYHATMOTION,
"JOY_BUTTON_UP": pygame_consts.JOYBUTTONUP,
"JOY_BUTTOND_OWN": pygame_consts.JOYBUTTONDOWN,
"VIDEO_RESIZE": pygame_consts.VIDEORESIZE,
"VIDEO_EXPOSE": pygame_consts.VIDEOEXPOSE,
# "USER_EVENT": pygame_consts.USEREVENT,
# think of begin_step, step and end_step
}
# Make kw_events_user automatically
LIST_EVENTS_USER = ["BEGIN_STEP", "STEP", "DRAW", "END_STEP"]
KW_EVENTS_USER = {}
KW_EVENTS_ALL = {}
def populate_KW_EVENTS_USER(LIST_EVENTS_USER=LIST_EVENTS_USER):
'''Populates KW_EVENTS_USER and also updates KW_EVENTS_ALL'''
tmp_event_numb = pygame_consts.USEREVENT
for tmp_event_name in LIST_EVENTS_USER:
KW_EVENTS_USER[tmp_event_name] = tmp_event_numb
tmp_event_numb += 1
global KW_EVENTS_ALL
KW_EVENTS_ALL = {}
for tmp_event_name in KW_EVENTS_IB:
KW_EVENTS_ALL[tmp_event_name] = KW_EVENTS_IB[tmp_event_name]
for tmp_event_name in KW_EVENTS_USER:
KW_EVENTS_ALL[tmp_event_name] = KW_EVENTS_USER[tmp_event_name]
# populated by default, may be repopulated later
populate_KW_EVENTS_USER()
CUE_EVENTS_IB = "unordered IB events here"
LIST_EVENTS_ORDERED = [KW_EVENTS_USER["BEGIN_STEP"], CUE_EVENTS_IB, KW_EVENTS_USER["STEP"],
KW_EVENTS_USER["DRAW"], KW_EVENTS_USER["END_STEP"]]
def sort_events(ev1, ev2):
ev_args = [ev1, ev2]
args_pos = [None, None]
# fix next line
for tmp_index in range(len(ev_args)):
tmp_ev = ev_args[tmp_index]
if (tmp_ev.type in KW_EVENTS_IB.values()):
args_pos[tmp_index] = LIST_EVENTS_ORDERED.index(CUE_EVENTS_IB)
elif (tmp_ev.type in KW_EVENTS_USER.values()):
args_pos[tmp_index] = LIST_EVENTS_ORDERED.index(tmp_ev.type)
tmp_diff = args_pos[0] - args_pos[1]
# convert -ve to -1, 0 to 0, +ve to +1
if tmp_diff == 0:
tmp_diff_unit = 0
else:
tmp_diff_unit = tmp_diff / abs(tmp_diff)
return tmp_diff_unit
def append_user_events(list_):
for temp_ev_name in LIST_EVENTS_USER:
temp_ev_numb = KW_EVENTS_USER[temp_ev_name]
list_.append(pygame.event.Event(temp_ev_numb))
return list_
def fuzzy_match_event_name(string, event_or_action):
str_upper = string.upper()
if not (str_upper in KW_EVENTS_ALL):
event_or_action = event_or_action.lower()
if event_or_action.lower() == "event" or event_or_action.lower() == "action":
# STR_STARTER becomes event_ or action_
STR_STARTER = event_or_action.upper() + "_"
else:
raise AttributeError(
"event_or_action arg must be 'event' or 'action'.")
str_normalized = str_upper[
str_upper.find(STR_STARTER) + len(STR_STARTER):]
for tmp_event_name in KW_EVENTS_ALL:
# tmp event is the event_name, keys of KW_EVENTS
tmp_event_name_normalized = tmp_event_name.replace("_", "")
if str_normalized.startswith(tmp_event_name) or str_normalized.startswith(tmp_event_name_normalized):
return tmp_event_name
else:
return str_upper
class Action(object):
""" pygame.event.Action(type, dict): return Action
pygame.Action.Action(type, **attributes): return Action
"""
def __init__(self, type, *args, **kwargs):
super(Action, self).__init__()
self.type = type
_dict = {}
if len(args) == 1:
_dict.update(args[0])
elif len(args) > 1:
raise TypeError(
"Max one non-keyword argument allowed (which is set to dict)")
if kwargs:
_dict.update(kwargs)
if _dict:
self.dict = _dict
def copy_func(f, name=None):
return types.FunctionType(f.func_code, f.func_globals, name or f.func_name,
f.func_defaults, f.func_closure)
def selfie_depreceated(f):
"""Decorate function `f` to pass a reference to the function
as the first argument"""
return partial(f, f)
def selfie(f):
"""Decorate function `f` to pass a reference to the function
as the first argument"""
return f.__get__(f, type(f))
def sync_func(func1, func2):
'''Makes the 1st param (func) equivalent to 2nd param (func).'''
func1.func_code = func2.func_code
func1.func_defaults = func2.func_defaults
func1.func_dict = func2.func_dict
func1.func_doc = func2.func_doc
func1.func_name = func2.func_name
class meta_accessor_class(type):
''' This metaclass allows class access to any function (or as extended use, to metaclasses)'''
# Using metaclass and decorator to allow class access during class creation time
# No method defined within the class should have "_process_meta" as arg
# Potential problems: Using closures, function.func_globals is read-only
# Doesnt get appropiate globals, maybe pass it (or the reqd global vars)
# as param on func defn
def __new__(cls, name, base, clsdict):
temp_cls = type.__new__(cls, name, base, clsdict)
temp_cls.list_instance = uniquelist()
temp_cls.list_check_func = uniquelist()
# dict_action_func -> dict of action funcs, key=event_numb like KEYDOWN
temp_cls.dict_action_func = {}
methods = inspect.getmembers(temp_cls, inspect.ismethod)
for (method_name, method_obj) in methods:
if fuzzy_match_event_name(method_name, "action"):
temp_cls.register_event(method_obj)
return temp_cls
@selfie
def run_dec_on_meta(self, what_to_do):
'''Runs decorator (what_to_do) passed to it during meta with args, cls=>class and func=>function which this is used on'''
# make copies of this func and instead of params use .vars. Should accept
# *args,*kwargs to main_func. Next step: multiple funcs, think.
def inter_run_dec_on_meta(*args, **kwargs):
# this intermediate func is used to produce func_process_meta for each
# time
def func_process_meta(self, *args, **kwargs):
if not hasattr(self, "_process_meta"):
# changing own's state, should be restored at last step before
# meta-return
self._process_meta = False
#(below) unneccesary here
if not hasattr(self, "__old_args") and not hasattr(self, "__old_kwargs"):
self.__old_args = None
self.__old_kwargs = None
if not self._process_meta:
# as long as not being meta-processed
# its not really main_func, really its just what_to_do's param
if (self.__old_args or self.__old_kwargs):
self.what_to_do = partial(
self.what_to_do, *(self.__old_args), **(self.__old_kwargs))
self.__old_args = args
self.__old_kwargs = kwargs
return selfie(self)
else:
self.main_func = self.__old_args[0]
return self
func_process_meta.__old_args = args
func_process_meta.__old_kwargs = kwargs
func_process_meta.what_to_do = what_to_do
func_process_meta.selfie = True
func_process_meta = selfie(func_process_meta)
return func_process_meta
return inter_run_dec_on_meta
def run_func_on_meta(run_func):
'''Runs func (run_func) passed to it during meta with arg, cls.
run_func remains a method of the class.'''
run_func._run_meta = True
return run_func
def register_event(event_name=None, func_to_register=None, cls=None):
'''
@fun_Class.register_event() # @fun_Class.register_event === @fun_Class.register_event()
def event_key_down(ev):
pass
OR
# event_name=KEYDOWN (or "key_down")
@fun_Class.register_event(event_name)
def whatever(ev):
pass
OR
fun_Class.register_event(event_name,func)
'''
if (event_name is None) and (func_to_register is None):
# i.e No param passed, used as decorator (1st step of ex. 1)
logging.info("Nothing passed")
return register_event
elif (not(event_name is None)) and (func_to_register is None):
# i.e. one param is passed, maybe func or (str or int)
logging.info("Event Name only passed")
if isinstance(event_name, str):
# i.e. 1st parm-> str , is event name, acts as decorator
# (2nd ex.)
# dont hardcode func name- use metaclass
logging.info("Event Name is event_name")
return partial(cls.register_event, event_name)
elif hasattr(event_name, "__call__"):
# first param is func, actually func_to_register.
# So get event_name from func_name (2nd step of 1st ex.)
logging.info("Event Name is actually func")
func_to_register = event_name
event_name = fuzzy_match_event_name(
func_to_register.func_name, "action")
return register_event(event_name=event_name, func_to_register=func_to_register, cls=cls)
else:
raise TypeError("event_name must be str or func")
else:
# Both params present
logging.info("Both param passed")
if isinstance(event_name, str):
event_name = fuzzy_match_event_name(event_name, "action")
logging.info("Registering func")
if not (event_name in cls.dict_action_func):
cls.dict_action_func[event_name] = []
cls.dict_action_func[event_name].append(func_to_register)
return func_to_register
def register_class(game_class, cls=None):
''' Register this class on mega_class.
Calls _regitser_class_ on mega_class with arg cls'''
if cls is None:
return partial(register_class, game_class)
game_class.register_class(cls)
cls.Game = game_class
return cls
def remove_from_list(list_, val, recursive=False):
if val in list_:
list_.remove(val)
if recursive:
while (val in list_):
list_.remove(val)
return list_
def rect_to_pygame_rect(rect):
if hasattr(rect, "bbox"):
rect = rect.bbox
return rect
# _register_event_ = register_event
# del register_event
# so that register event is actually delegated register
# register_event = run_dec_on_meta(_register_event_)
# Move to test
##import pygame
# pygame.init()
##evs = []
# evs.append(pygame.event.Event(KW_EVENTS_IB["KEY_DOWN"]))
# evs.append(pygame.event.Event(KW_EVENTS_IB["JOY_AXIS_MOTION"]))
# evs.append(pygame.event.Event(KW_EVENTS_IB["KEY_UP"]))
# evs.append(pygame.event.Event(KW_EVENTS_IB["MOUSE_BUTTON_UP"]))
# evs.append(pygame.event.Event(KW_EVENTS_USER["DRAW"]))
# evs.append(pygame.event.Event(KW_EVENTS_USER["BEGIN_STEP"]))
# evs.append(pygame.event.Event(KW_EVENTS_USER["END_STEP"]))
# evs.append(pygame.event.Event(KW_EVENTS_USER["STEP"]))
# evs.sort(sort_events)