Initial commit
Import existing source tree; original VCS history is no longer available. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
noinst_LIBRARIES = libgraphics.a
|
||||
|
||||
INCLUDES = @LOCALCFLAGS@
|
||||
|
||||
libgraphics_a_SOURCES = cs.c sprite.c filters.c glSDL.c \
|
||||
gfxengine.cpp window.cpp sofont.cpp \
|
||||
display.cpp toolkit.cpp vidmodes.c \
|
||||
region.c
|
||||
|
||||
EXTRA_DIST = *.h
|
||||
@@ -0,0 +1,457 @@
|
||||
# Makefile.in generated by automake 1.9.6 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ..
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
subdir = graphics
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.in
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/aconfig.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
AR = ar
|
||||
ARFLAGS = cru
|
||||
libgraphics_a_AR = $(AR) $(ARFLAGS)
|
||||
libgraphics_a_LIBADD =
|
||||
am_libgraphics_a_OBJECTS = cs.$(OBJEXT) sprite.$(OBJEXT) \
|
||||
filters.$(OBJEXT) glSDL.$(OBJEXT) gfxengine.$(OBJEXT) \
|
||||
window.$(OBJEXT) sofont.$(OBJEXT) display.$(OBJEXT) \
|
||||
toolkit.$(OBJEXT) vidmodes.$(OBJEXT) region.$(OBJEXT)
|
||||
libgraphics_a_OBJECTS = $(am_libgraphics_a_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
CXXLD = $(CXX)
|
||||
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
|
||||
-o $@
|
||||
SOURCES = $(libgraphics_a_SOURCES)
|
||||
DIST_SOURCES = $(libgraphics_a_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AUDIO_LIBS = @AUDIO_LIBS@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BUILD_MACOSX_BUNDLE_FALSE = @BUILD_MACOSX_BUNDLE_FALSE@
|
||||
BUILD_MACOSX_BUNDLE_TRUE = @BUILD_MACOSX_BUNDLE_TRUE@
|
||||
BUILD_SIMPLE_BUNDLE_FALSE = @BUILD_SIMPLE_BUNDLE_FALSE@
|
||||
BUILD_SIMPLE_BUNDLE_TRUE = @BUILD_SIMPLE_BUNDLE_TRUE@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CONFIGDIR = @CONFIGDIR@
|
||||
CONFIGFILE = @CONFIGFILE@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DATADIR = @DATADIR@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
EXEFILE = @EXEFILE@
|
||||
GREP = @GREP@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LOCALCFLAGS = @LOCALCFLAGS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MATHLIB = @MATHLIB@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
POW_LIB = @POW_LIB@
|
||||
RANLIB = @RANLIB@
|
||||
SCOREDIR = @SCOREDIR@
|
||||
SDL_CFLAGS = @SDL_CFLAGS@
|
||||
SDL_CONFIG = @SDL_CONFIG@
|
||||
SDL_LIBS = @SDL_LIBS@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
UNIX_SCOREDIR_FALSE = @UNIX_SCOREDIR_FALSE@
|
||||
UNIX_SCOREDIR_TRUE = @UNIX_SCOREDIR_TRUE@
|
||||
VERSION = @VERSION@
|
||||
XMKMF = @XMKMF@
|
||||
X_CFLAGS = @X_CFLAGS@
|
||||
X_EXTRA_LIBS = @X_EXTRA_LIBS@
|
||||
X_LIBS = @X_LIBS@
|
||||
X_PRE_LIBS = @X_PRE_LIBS@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
noinst_LIBRARIES = libgraphics.a
|
||||
INCLUDES = @LOCALCFLAGS@
|
||||
libgraphics_a_SOURCES = cs.c sprite.c filters.c glSDL.c \
|
||||
gfxengine.cpp window.cpp sofont.cpp \
|
||||
display.cpp toolkit.cpp vidmodes.c \
|
||||
region.c
|
||||
|
||||
EXTRA_DIST = *.h
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .cpp .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign graphics/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign graphics/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
libgraphics.a: $(libgraphics_a_OBJECTS) $(libgraphics_a_DEPENDENCIES)
|
||||
-rm -f libgraphics.a
|
||||
$(libgraphics_a_AR) libgraphics.a $(libgraphics_a_OBJECTS) $(libgraphics_a_LIBADD)
|
||||
$(RANLIB) libgraphics.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cs.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/display.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filters.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gfxengine.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glSDL.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/region.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sofont.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sprite.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/toolkit.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vidmodes.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/window.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.cpp.o:
|
||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||
|
||||
.cpp.obj:
|
||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
uninstall-info-am:
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkdir_p) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LIBRARIES)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-info-am
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-noinstLIBRARIES ctags distclean distclean-compile \
|
||||
distclean-generic distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-exec install-exec-am install-info \
|
||||
install-info-am install-man install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
|
||||
uninstall-am uninstall-info-am
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
+720
@@ -0,0 +1,720 @@
|
||||
/*(LGPL)
|
||||
* Project Spitfire sprites + scrolling engine for SDL
|
||||
----------------------------------------------------------------------
|
||||
cs.c - Simplistic Control System
|
||||
----------------------------------------------------------------------
|
||||
* Copyright (C) 2001, 2003, 2007 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#define DBG(x)
|
||||
|
||||
#include "cs.h"
|
||||
#include "logger.h"
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
/*#define ABS(x) (((x)>=0) ? (x) : (-(x)))*/
|
||||
#define ABS(x) labs(x)
|
||||
|
||||
|
||||
static inline void __wrap_point(cs_point_t *p, int wx, int wy)
|
||||
{
|
||||
if(wx)
|
||||
{
|
||||
if(p->gx < 0)
|
||||
p->gx += (-p->gx / wx + 1) * wx;
|
||||
p->gx %= wx;
|
||||
}
|
||||
if(wy)
|
||||
{
|
||||
if(p->gy < 0)
|
||||
p->gy += (-p->gy / wy + 1) * wy;
|
||||
p->gy %= wy;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Make one point do it's thing...
|
||||
*/
|
||||
static inline void __move_point(cs_point_t *p, int wx, int wy)
|
||||
{
|
||||
/*
|
||||
* Push filter
|
||||
*/
|
||||
p->ox = p->v.x;
|
||||
p->oy = p->v.y;
|
||||
|
||||
/*
|
||||
* Update position and speed
|
||||
*/
|
||||
p->v.x += p->v.xv;
|
||||
p->v.y += p->v.yv;
|
||||
p->v.xv += p->v.xa;
|
||||
p->v.yv += p->v.ya;
|
||||
|
||||
__wrap_point(p, wx, wy);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update the motion filtered output of a point.
|
||||
*/
|
||||
static inline void __update_point_f(cs_point_t *p, int ff, int wx, int wy)
|
||||
{
|
||||
int ogx = p->gx;
|
||||
int ogy = p->gy;
|
||||
int ox = p->ox;
|
||||
int oy = p->oy;
|
||||
|
||||
/* Unwrap filter for correct interpolation */
|
||||
if(wx | wy)
|
||||
{
|
||||
if((ox - p->v.x) > (wx >> 1))
|
||||
ox -= wx;
|
||||
else if((p->v.x - ox) > (wx >> 1))
|
||||
ox += wx;
|
||||
if((oy - p->v.y) > (wy >> 1))
|
||||
oy -= wy;
|
||||
else if((p->v.y - oy) > (wy >> 1))
|
||||
oy += wy;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpolate output graphics coordinate
|
||||
*/
|
||||
p->gx = (ff * p->v.x + (256 - ff) * ox) >> 8;
|
||||
p->gy = (ff * p->v.y + (256 - ff) * oy) >> 8;
|
||||
|
||||
/*
|
||||
* Wrap interpolated output
|
||||
*/
|
||||
if(wx)
|
||||
{
|
||||
while(p->gx < 0)
|
||||
p->gx += wx;
|
||||
p->gx %= wx;
|
||||
}
|
||||
if(wy)
|
||||
{
|
||||
while(p->gy < 0)
|
||||
p->gy += wy;
|
||||
p->gy %= wy;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate "changed" flag mask.
|
||||
*/
|
||||
p->changed = (ogx ^ p->gx) | (ogy ^ p->gy);
|
||||
}
|
||||
|
||||
|
||||
static inline void __update_point(cs_point_t *p, int ff)
|
||||
{
|
||||
int ogx = p->gx;
|
||||
int ogy = p->gy;
|
||||
|
||||
/*
|
||||
* Interpolate output graphics coordinate
|
||||
*/
|
||||
p->gx = p->v.x;
|
||||
p->gy = p->v.y;
|
||||
|
||||
/*
|
||||
* Generate "changed" flag mask.
|
||||
*/
|
||||
p->changed = (ogx ^ p->gx) | (ogy ^ p->gy);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
* cs_obj_t
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Final adjustment of interpolated graphics coords to deal
|
||||
* with the display window wrapping over the edge of the world.
|
||||
*/
|
||||
static inline void __fix_wrap(cs_engine_t *e, cs_obj_t *o)
|
||||
{
|
||||
if(o->point.gx + (o->w << __CS_SHIFT) < 0)
|
||||
o->point.gx += e->wx;
|
||||
else if(o->point.gx > (e->w << __CS_SHIFT))
|
||||
o->point.gx -= e->wx;
|
||||
if(o->point.gy + (o->h << __CS_SHIFT) < 0)
|
||||
o->point.gy += e->wy;
|
||||
else if(o->point.gy > (e->h << __CS_SHIFT))
|
||||
o->point.gy -= e->wy;
|
||||
}
|
||||
|
||||
|
||||
static inline int __onscreen(cs_engine_t *e, cs_obj_t *o)
|
||||
{
|
||||
int gx = CS2PIXEL(o->point.gx);
|
||||
int gy = CS2PIXEL(o->point.gy);
|
||||
if((gx + o->w < 0) || (gx > e->w))
|
||||
return 0;
|
||||
if((gy + o->h < 0) || (gy > e->h))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static inline void __obj_set_layer(cs_obj_t *o, unsigned int layer)
|
||||
{
|
||||
if(o->layer < 0)
|
||||
o->layer = CS_DEFAULT_LAYER;
|
||||
if(layer >= CS_LAYERS)
|
||||
layer = CS_LAYERS - 1;
|
||||
o->layer = layer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add object *first*, ie with lowest priority.
|
||||
* (Hmmm... Isn't that how some h/w sprite generators do it,
|
||||
* if you allocate in increasing channel order?)
|
||||
*/
|
||||
static inline void __obj_attach(cs_obj_t *o)
|
||||
{
|
||||
if(o->head || o->next || o->prev)
|
||||
{
|
||||
log_printf(ELOG, "cs: HEEEELP! Someone's trying"
|
||||
" to short-circuit my guts!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(o->layer < 0)
|
||||
o->layer = CS_DEFAULT_LAYER;
|
||||
o->next = o->owner->objects[o->layer];
|
||||
o->head = &o->owner->objects[o->layer];
|
||||
if(o->next)
|
||||
o->next->prev = o;
|
||||
o->owner->objects[o->layer] = o;
|
||||
}
|
||||
|
||||
/*
|
||||
* BEWARE! There's a nasty hack in here; these objects need to
|
||||
* keep track of the addresses of their list heads in order to
|
||||
* remove themselves properly!
|
||||
*/
|
||||
static inline void __obj_detach(cs_obj_t *o)
|
||||
{
|
||||
/* "Bypass" */
|
||||
if(o->next)
|
||||
o->next->prev = o->prev;
|
||||
if(o->prev)
|
||||
o->prev->next = o->next;
|
||||
/* In case we're the first object in the list... */
|
||||
if(o->head)
|
||||
if(*(o->head) == o)
|
||||
*(o->head) = o->next;
|
||||
|
||||
o->head = NULL;
|
||||
o->next = NULL;
|
||||
o->prev = NULL;
|
||||
}
|
||||
|
||||
|
||||
void cs_obj_layer(cs_obj_t *o, unsigned int layer)
|
||||
{
|
||||
if(layer == o->layer)
|
||||
return;
|
||||
|
||||
__obj_set_layer(o, layer);
|
||||
if(o->flags | CS_OBJ_ACTIVE)
|
||||
{
|
||||
__obj_detach(o);
|
||||
__obj_attach(o);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cs_obj_activate(cs_obj_t *o)
|
||||
{
|
||||
if(o->flags | CS_OBJ_ACTIVE)
|
||||
{
|
||||
DBG(log_printf(DLOG, "cs: Tried to activate active object!\n");)
|
||||
return;
|
||||
}
|
||||
|
||||
__obj_attach(o);
|
||||
o->flags |= CS_OBJ_ACTIVE;
|
||||
}
|
||||
|
||||
|
||||
void cs_obj_deactivate(cs_obj_t *o)
|
||||
{
|
||||
if(!(o->flags | CS_OBJ_ACTIVE))
|
||||
{
|
||||
DBG(log_printf(DLOG, "cs: Tried to deactivate passive object!\n");)
|
||||
return;
|
||||
}
|
||||
|
||||
__obj_detach(o);
|
||||
o->flags &= ~CS_OBJ_ACTIVE;
|
||||
}
|
||||
|
||||
|
||||
/* Basic methods */
|
||||
|
||||
void cs_obj_pos(cs_obj_t *o, int x, int y)
|
||||
{
|
||||
o->point.v.x = PIXEL2CS(x);
|
||||
o->point.v.y = PIXEL2CS(y);
|
||||
}
|
||||
|
||||
|
||||
void cs_obj_vel(cs_obj_t *o, int xs, int ys)
|
||||
{
|
||||
o->point.v.xv = xs;
|
||||
o->point.v.yv = ys;
|
||||
}
|
||||
|
||||
|
||||
/*Set movement acceleration*/
|
||||
void cs_obj_acc(cs_obj_t *o, int xa, int ya)
|
||||
{
|
||||
o->point.v.xa = xa;
|
||||
o->point.v.ya = ya;
|
||||
}
|
||||
|
||||
|
||||
/*Disable display*/
|
||||
void cs_obj_hide(cs_obj_t *o)
|
||||
{
|
||||
o->flags &= ~CS_OBJ_VISIBLE;
|
||||
}
|
||||
|
||||
|
||||
/*Enable display*/
|
||||
void cs_obj_show(cs_obj_t *o)
|
||||
{
|
||||
if(o->flags & CS_OBJ_VISIBLE)
|
||||
return;
|
||||
|
||||
o->flags |= CS_OBJ_VISIBLE;
|
||||
/*
|
||||
* Kludge? I'm not sure this is really the right place...
|
||||
*/
|
||||
cs_point_force(&o->point);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove and throw back in the pool
|
||||
*/
|
||||
void cs_obj_free(cs_obj_t *o)
|
||||
{
|
||||
if(o->head == &o->owner->pool)
|
||||
{
|
||||
DBG(log_printf(DLOG, "cs: Tried to free free object %p!\n",
|
||||
o);)
|
||||
return;
|
||||
}
|
||||
cs_obj_deactivate(o);
|
||||
if(o->on_free)
|
||||
o->on_free(o);
|
||||
cs_obj_clear(o);
|
||||
|
||||
/* Set up head pointer for error checking. */
|
||||
o->head = &o->owner->pool;
|
||||
|
||||
/* Link to pool; singly only */
|
||||
o->next = o->owner->pool;
|
||||
o->owner->pool = o;
|
||||
|
||||
++o->owner->pool_free;
|
||||
}
|
||||
|
||||
void cs_obj_clear(cs_obj_t *o)
|
||||
{
|
||||
o->flags = 0;
|
||||
o->layer = -1;
|
||||
o->fire.rate = 0;
|
||||
o->score = 0;
|
||||
o->health = 0;
|
||||
}
|
||||
|
||||
void cs_obj_vector(cs_obj_t *o, cs_vector_t * v)
|
||||
{
|
||||
if(v)
|
||||
o->point.v = *v;
|
||||
else
|
||||
memset(&(o->point.v), 0, sizeof(o->point.v));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Animation methods */
|
||||
void cs_obj_anim(cs_obj_t *o, int bank,
|
||||
int first, int num, int start, int spd)
|
||||
{
|
||||
o->anim.bank = bank;
|
||||
o->anim.frame = first;
|
||||
o->anim.fframe = first;
|
||||
o->anim.aframes = num;
|
||||
o->anim.cframe = start << 4;
|
||||
o->anim.aspeed = spd;
|
||||
o->flags |= CS_OBJ_DOANIM;
|
||||
}
|
||||
|
||||
|
||||
void cs_obj_image(cs_obj_t *o, int bank, int frame)
|
||||
{
|
||||
o->anim.bank = bank;
|
||||
o->anim.frame = frame;
|
||||
o->flags &= ~CS_OBJ_DOANIM;
|
||||
if((bank >= 0) && (bank < o->owner->nimageinfo))
|
||||
{
|
||||
o->w = o->owner->imageinfo[bank].w;
|
||||
o->h = o->owner->imageinfo[bank].h;
|
||||
}
|
||||
else
|
||||
o->w = o->h = 1;
|
||||
}
|
||||
|
||||
|
||||
/*Start death sequence*/
|
||||
void cs_obj_explode(cs_obj_t *o)
|
||||
{
|
||||
o->flags |= CS_OBJ_DYING;
|
||||
/*
|
||||
FIXME: Hardcoded bank for explosion!!!
|
||||
*/
|
||||
cs_obj_anim(o, 4, 0, 15, 0, 12);
|
||||
if(o->on_dying)
|
||||
o->on_dying(o);
|
||||
}
|
||||
|
||||
void cs_obj_shoot(cs_obj_t *o, int xo, int yo, int xs,
|
||||
int ys, int rate, int delay, int ammo)
|
||||
{
|
||||
o->fire.v.x = xo;
|
||||
o->fire.v.y = yo;
|
||||
o->fire.v.xv = xs;
|
||||
o->fire.v.yv = ys;
|
||||
o->fire.rate = rate;
|
||||
o->fire.timer = delay;
|
||||
o->fire.ammo = ammo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* cs_engine_t
|
||||
*/
|
||||
|
||||
static cs_obj_t *__new_obj(cs_engine_t *e)
|
||||
{
|
||||
cs_obj_t *o = calloc(1, sizeof(cs_obj_t));
|
||||
if(!o)
|
||||
return NULL;
|
||||
|
||||
o->owner = e;
|
||||
o->prev = NULL;
|
||||
o->next = NULL;
|
||||
cs_obj_clear(o);
|
||||
++e->pool_total;
|
||||
return o;
|
||||
}
|
||||
|
||||
cs_engine_t *cs_engine_create(int w, int h, int objects)
|
||||
{
|
||||
cs_engine_t *e = calloc(1, sizeof(cs_engine_t));
|
||||
if(!e)
|
||||
return NULL;
|
||||
|
||||
cs_engine_set_size(e, w, h);
|
||||
cs_engine_set_wrap(e, 0, 0);
|
||||
|
||||
/*
|
||||
* Create some objects and throw into the pool.
|
||||
* Note that "pool_free" gets initialized by
|
||||
* cs_obj_die(), objects are initialized and so
|
||||
* on, this way - automatically!
|
||||
*/
|
||||
while(objects--)
|
||||
{
|
||||
cs_obj_t *o = __new_obj(e);
|
||||
if(o)
|
||||
cs_obj_free(o);
|
||||
else
|
||||
{
|
||||
/* Oops, no memory... */
|
||||
cs_engine_delete(e);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
cs_obj_t *cs_engine_get_obj(cs_engine_t *e)
|
||||
{
|
||||
cs_obj_t *o = e->pool;
|
||||
if(o)
|
||||
{
|
||||
e->pool = o->next;
|
||||
o->head = NULL;
|
||||
o->prev = NULL;
|
||||
o->next = NULL;
|
||||
--e->pool_free;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
void cs_engine_set_size(cs_engine_t *e, int w, int h)
|
||||
{
|
||||
e->w = w;
|
||||
e->h = h;
|
||||
}
|
||||
|
||||
|
||||
void cs_engine_set_image_size(cs_engine_t *e, int bank, int w, int h)
|
||||
{
|
||||
if(bank < 0)
|
||||
return;
|
||||
|
||||
if(bank >= e->nimageinfo)
|
||||
{
|
||||
int nnii = bank + 16;
|
||||
image_info_t *nii = realloc(e->imageinfo,
|
||||
sizeof(image_info_t) * nnii);
|
||||
if(!nii)
|
||||
return;
|
||||
|
||||
e->nimageinfo = nnii;
|
||||
e->imageinfo = nii;
|
||||
}
|
||||
|
||||
e->imageinfo[bank].w = w;
|
||||
e->imageinfo[bank].h = h;
|
||||
}
|
||||
|
||||
|
||||
void cs_engine_set_wrap(cs_engine_t *e, int x, int y)
|
||||
{
|
||||
e->wx = PIXEL2CS(x);
|
||||
e->wy = PIXEL2CS(y);
|
||||
}
|
||||
|
||||
|
||||
void cs_engine_delete(cs_engine_t *e)
|
||||
{
|
||||
cs_obj_t *o;
|
||||
/* First get all objects to the pool... */
|
||||
cs_engine_reset(e);
|
||||
/* ...then empty the pool. */
|
||||
while((o = cs_engine_get_obj(e)))
|
||||
free(o);
|
||||
free(e->imageinfo);
|
||||
free(e);
|
||||
}
|
||||
|
||||
|
||||
void cs_engine_reset(cs_engine_t *e)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < CS_LAYERS; ++i)
|
||||
while(e->objects[i])
|
||||
cs_obj_free(e->objects[i]);
|
||||
e->time = 0.0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
* The actual *engine* :-)
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void __enemy_fire(cs_obj_t *o)
|
||||
{
|
||||
log_printf(DLOG, "fire!\n");
|
||||
}
|
||||
|
||||
void __make_move(cs_obj_t *o, int wx, int wy)
|
||||
{
|
||||
/*
|
||||
* Movement
|
||||
*/
|
||||
__move_point(&o->point, wx, wy);
|
||||
|
||||
/*
|
||||
* Animation
|
||||
*/
|
||||
if(o->flags & CS_OBJ_DOANIM)
|
||||
{
|
||||
/*
|
||||
FIXME: Dirty hack here... Should play *any* death animation one-shot and then die.
|
||||
*/
|
||||
if((o->flags & CS_OBJ_DYING)
|
||||
&& (o->anim.cframe >> 4 == 14))
|
||||
cs_obj_free(o);
|
||||
|
||||
o->anim.cframe += o->anim.aspeed;
|
||||
o->anim.cframe %= o->anim.aframes << 4;
|
||||
o->anim.frame = (o->anim.cframe >> 4) + o->anim.fframe;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fire / spawning
|
||||
*/
|
||||
if(!(o->flags & CS_OBJ_DYING) && o->fire.rate)
|
||||
{
|
||||
if(o->fire.timer > 0)
|
||||
--o->fire.timer;
|
||||
else
|
||||
{
|
||||
o->fire.timer = o->fire.rate;
|
||||
__enemy_fire(o);
|
||||
if(o->on_fire)
|
||||
o->on_fire(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void __update_points(cs_engine_t *e, float frac_frame)
|
||||
{
|
||||
cs_obj_t *o;
|
||||
int i;
|
||||
int ff = frac_frame * 256.0;
|
||||
|
||||
if(ff < 0)
|
||||
ff = 0;
|
||||
else if(ff > 256)
|
||||
ff = 256;
|
||||
|
||||
if(e->filter)
|
||||
for(i = 0; i < CS_USER_POINTS; ++i)
|
||||
__update_point_f(&e->points[i], ff, e->wx, e->wy);
|
||||
else
|
||||
for(i = 0; i < CS_USER_POINTS; ++i)
|
||||
__update_point(&e->points[i], ff);
|
||||
|
||||
for(i = 0; i < CS_LAYERS; ++i)
|
||||
{
|
||||
if(e->filter)
|
||||
__update_point_f(&e->offsets[i], ff, e->wx, e->wy);
|
||||
else
|
||||
__update_point(&e->offsets[i], ff);
|
||||
e->changed[i] = 0;
|
||||
o = e->objects[i];
|
||||
while(o)
|
||||
{
|
||||
if(e->filter)
|
||||
__update_point_f(&o->point, ff, e->wx,
|
||||
e->wy);
|
||||
else
|
||||
__update_point(&o->point, ff);
|
||||
o->point.gx -= e->offsets[i].gx;
|
||||
o->point.gy -= e->offsets[i].gy;
|
||||
e->changed[i] |= o->point.changed;
|
||||
__fix_wrap(e, o);
|
||||
o = o->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void __run_all(cs_engine_t *e)
|
||||
{
|
||||
int i;
|
||||
cs_obj_t *o;
|
||||
|
||||
for(i = 0; i < CS_USER_POINTS; ++i)
|
||||
__move_point(&e->points[i], e->wx, e->wy);
|
||||
|
||||
for(i = 0; i < CS_LAYERS; ++i)
|
||||
{
|
||||
__move_point(&e->offsets[i], e->wx, e->wy);
|
||||
o = e->objects[i];
|
||||
while(o)
|
||||
{
|
||||
__make_move(o, e->wx, e->wy);
|
||||
o = o->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void __wrap_all(cs_engine_t *e)
|
||||
{
|
||||
int i;
|
||||
cs_obj_t *o;
|
||||
|
||||
for(i = 0; i < CS_USER_POINTS; ++i)
|
||||
__wrap_point(&e->points[i], e->wx, e->wy);
|
||||
|
||||
for(i = 0; i < CS_LAYERS; ++i)
|
||||
{
|
||||
__wrap_point(&e->offsets[i], e->wx, e->wy);
|
||||
o = e->objects[i];
|
||||
while(o)
|
||||
{
|
||||
__wrap_point(&o->point, e->wx, e->wy);
|
||||
o = o->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cs_engine_advance(cs_engine_t *e, double to_frame)
|
||||
{
|
||||
if(to_frame > 0)
|
||||
{
|
||||
int frames = floor(to_frame) - floor(e->time);
|
||||
if(frames > 0)
|
||||
{
|
||||
while(frames--)
|
||||
{
|
||||
__run_all(e);
|
||||
e->on_frame(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
e->time = to_frame;
|
||||
if(e->wx || e->wy)
|
||||
__wrap_all(e);
|
||||
__update_points(e, to_frame - floor(to_frame));
|
||||
}
|
||||
|
||||
|
||||
void cs_engine_render(cs_engine_t *e)
|
||||
{
|
||||
cs_obj_t *o;
|
||||
int i;
|
||||
|
||||
for(i = CS_LAYERS - 1; i >= 0; --i)
|
||||
{
|
||||
o = e->objects[i];
|
||||
while(o)
|
||||
{
|
||||
if(o->flags & CS_OBJ_VISIBLE)
|
||||
if(o->render)
|
||||
if(__onscreen(e, o))
|
||||
o->render(o);
|
||||
o = o->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
+472
@@ -0,0 +1,472 @@
|
||||
/*(LGPL)
|
||||
* Project Spitfire sprites + scrolling engine for SDL
|
||||
----------------------------------------------------------------------
|
||||
cs.h - Simplistic Control System
|
||||
----------------------------------------------------------------------
|
||||
* Copyright (C) 2001, 2003, 2007 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note on coordinates:
|
||||
* Normally, cs assumes that the world continues
|
||||
* indefinitely in every direction. (Actually,
|
||||
* it wraps at 4 Gpixel intervals... :-)
|
||||
*
|
||||
* However, by calling cs_engine_set_wrap(x, y),
|
||||
* it's possible to make the engine wrap
|
||||
* automatically, to nicely support old style
|
||||
* endless scrolling games. The movement system
|
||||
* will automatically wrap around edges, and
|
||||
* most importantly, *interpolation* will work
|
||||
* correctly in conjunction with wrapping. This
|
||||
* applies to all points in the system, user
|
||||
* points included.
|
||||
*
|
||||
* Note that cs doesn't have an internal notion
|
||||
* of layers when it comes to wrapping, which
|
||||
* means that it's not trivial to implement
|
||||
* wrapping for parallax scrolling correctly.
|
||||
* All parallax layers have to be of the same
|
||||
* size, as cs cannot tell which points belong
|
||||
* to which layer when performing the internal
|
||||
* calculations.
|
||||
*
|
||||
* Call cs_engine_set_wrap(0, 0); to disable
|
||||
* wrapping. Wrapping can be set or disabled
|
||||
* individually for each axis.
|
||||
*
|
||||
* Note on graphics coordinates:
|
||||
* Graphics coordinates don't always wrap at the
|
||||
* same time as their corresponding object
|
||||
* coordinates! This is because the engine must
|
||||
* consider the view rectangle and the bounding
|
||||
* rectangles of objects, and adjust the wrapping
|
||||
* so that all objects that should be visible
|
||||
* are.
|
||||
*
|
||||
* Note on wrapping (with wrapping enabled only):
|
||||
* When a layer is scrolled so that it's limits
|
||||
* end up inside the display window, the engine
|
||||
* automatically makes objects wrap around from
|
||||
* the far edge, so that continuous looping is
|
||||
* possible.
|
||||
* However, note that this breaks if objects can
|
||||
* be seen at more than one edge at a time! That
|
||||
* is, (wrap size - display size) must be bigger
|
||||
* than the size of the largest object.
|
||||
*
|
||||
* TODO:
|
||||
* * Scrap the animation system and throw
|
||||
* something nicer in. A primitive VM based
|
||||
* "scripting" system with <frame, duration>
|
||||
* commands and switches based on speed,
|
||||
* direction, state etc would be incredibly
|
||||
* powerful, and still not too complicated.
|
||||
*
|
||||
* * Implement collision detection. There should
|
||||
* be flags to enable/disable it on per-layer
|
||||
* as well as per-object basis.
|
||||
*
|
||||
* * Group all per-layer stuff into a struct,
|
||||
* and then use an array of structs.
|
||||
*
|
||||
* * Split each layer into two lists; one for
|
||||
* visible objects and one for hidden objects,
|
||||
* so they can be handled more efficiently.
|
||||
* (Hidden objects are skipped one by one in
|
||||
* the render loop now, for example - it will
|
||||
* become worse over time, I think.)
|
||||
*
|
||||
* * Implement some sort of zone based collision
|
||||
* detection engine that scales better than
|
||||
* "check everything against everything".
|
||||
*/
|
||||
/*
|
||||
*
|
||||
* BUGS:
|
||||
* * There is a restriction on object movement
|
||||
* speed in a wrapping world: No object must
|
||||
* move more than half of the extent of the
|
||||
* world on either axis in one engine cycle.
|
||||
* STATUS: Who cares?
|
||||
*
|
||||
* * Objects that are not free or active (they
|
||||
* do *not* have to be visible!) are "missing
|
||||
* in action" as far as the engine is concerned.
|
||||
* It won't find them unless you free them,
|
||||
* or make them visible.
|
||||
* STATUS: Can and should be fixed.
|
||||
*/
|
||||
|
||||
#ifndef _CS_H_
|
||||
#define _CS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define __CS_SHIFT 8
|
||||
#define CS2PIXEL(x) ( (x) >> __CS_SHIFT )
|
||||
#define PIXEL2CS(x) ( (x) << __CS_SHIFT )
|
||||
|
||||
#define CS_LAYERS 8
|
||||
#define CS_DEFAULT_LAYER 1 /*0 is normally for overlays*/
|
||||
#define CS_USER_POINTS 16
|
||||
|
||||
/*
|
||||
FIXME: This fixpoint crap should probably be changed to float...
|
||||
FIXME: Would break the "changed" mask bonus feature described
|
||||
FIXME: below, though.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* 24:8 fixpoint values */
|
||||
int x, y; /* logic position */
|
||||
int xv, yv;
|
||||
int xa, ya;
|
||||
} cs_vector_t;
|
||||
|
||||
|
||||
/*
|
||||
* Some handy vector construction macros...
|
||||
*
|
||||
* NOTE: position (x,y) in integer format, not fixpoint!
|
||||
*/
|
||||
|
||||
/* Point */
|
||||
static inline cs_vector_t cs_vector_p(int x, int y)
|
||||
{
|
||||
cs_vector_t v;
|
||||
v.x = PIXEL2CS(x);
|
||||
v.y = PIXEL2CS(y);
|
||||
v.xv = v.yv = v.xa = v.ya = 0;
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Point + velocity */
|
||||
static inline cs_vector_t cs_vector_pv(int x, int y, int xv, int yv)
|
||||
{
|
||||
cs_vector_t v;
|
||||
v.x = PIXEL2CS(x);
|
||||
v.y = PIXEL2CS(y);
|
||||
v.xv = xv;
|
||||
v.yv = yv;
|
||||
v.xa = v.ya = 0;
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Point + velocity + acceleration */
|
||||
static inline cs_vector_t cs_vector_pva(int x, int y, int xv, int yv, int xa, int ya)
|
||||
{
|
||||
cs_vector_t v;
|
||||
v.x = PIXEL2CS(x);
|
||||
v.y = PIXEL2CS(y);
|
||||
v.xv = xv;
|
||||
v.yv = yv;
|
||||
v.xa = xa;
|
||||
v.ya = ya;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generic coordinate + speed and acceleration type. Position filtering
|
||||
* support is built-in as well, for smooth animation regardless of
|
||||
* control system / video frame rate ratio.
|
||||
FIXME: Interpolation can break detailed animations involving multiple
|
||||
FIXME: sprites that move and animate (changing images) at the same
|
||||
FIXME: time. Provide a "CS_OBJ_NO_INTERPOLATION" flag?
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* 24:8 fixpoint values here as well */
|
||||
cs_vector_t v;
|
||||
|
||||
int ox, oy; /* last position (for filtering) */
|
||||
int gx, gy; /* graphic position */
|
||||
|
||||
/* (changed != 0) if gx or gy changed during the last update.
|
||||
* This is a bit mask with the same format as the coords,
|
||||
* which means that you can mask some low bits off to set
|
||||
* a coarse movement sensitivity threshold.
|
||||
* Ex. (changed & 0xffffff00) == "gx or gy moved to
|
||||
* another pixel posn."
|
||||
*/
|
||||
int changed;
|
||||
} cs_point_t;
|
||||
|
||||
|
||||
/*
|
||||
* Force the interpolation filter of a point to the current
|
||||
* position of the vector. (This is required when activating
|
||||
* new objects.)
|
||||
*/
|
||||
static inline void cs_point_force(cs_point_t *p)
|
||||
{
|
||||
p->ox = p->gx = p->v.x;
|
||||
p->oy = p->gy = p->v.y;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This stuff is translated from Object Pascal to "Object
|
||||
* Oriented Style C" with my new naming conventions...
|
||||
* I don't consider this code needing advanced OO, so I
|
||||
* don't want to drag C++ in.
|
||||
*/
|
||||
|
||||
struct cs_engine_t;
|
||||
struct cs_obj_t;
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
* cs_obj_t (used to be object + sprite)
|
||||
----------------------------------------------------------------------
|
||||
*
|
||||
* "The Basic Move Object.
|
||||
*
|
||||
* This object reperesents a moving object on the screen.
|
||||
* You just tell it in what direction to go, and the Game Graphics
|
||||
* system will do the job."
|
||||
*
|
||||
* What to do in the callbacks:
|
||||
* collision() Check accurately if two objects really collide.
|
||||
* (The control system will ask when bounding rects
|
||||
* are overlapping and the collision masks indicate
|
||||
* that a collision would affect one or both objects.)
|
||||
*/
|
||||
typedef struct cs_obj_t
|
||||
{
|
||||
struct cs_engine_t *owner;
|
||||
struct cs_obj_t **head;
|
||||
struct cs_obj_t *next, *prev;
|
||||
|
||||
cs_point_t point; /* Position, speed, acceleration */
|
||||
|
||||
int w, h; /* Sprite bounding rect size (pixels) */
|
||||
|
||||
int flags;
|
||||
int layer;
|
||||
|
||||
/* Collision filter (new) */
|
||||
int group_mask; /* bit set = "belongs to group" */
|
||||
int hit_mask; /* bit set = "can hit group" */
|
||||
|
||||
struct
|
||||
{
|
||||
int bank; /* Image bank */
|
||||
int frame; /* Image frame */
|
||||
int fframe; /* First frame (integer) */
|
||||
int aframes; /* # of frames; from fframe (integer) */
|
||||
int cframe; /* Current frame; from fframe (28:4 fixp) */
|
||||
int aspeed; /* Frames / engine cycle (28:4 fixp) */
|
||||
} anim;
|
||||
|
||||
struct
|
||||
{
|
||||
cs_vector_t v; /* weapon offset + vel + acc */
|
||||
int rate; /* frames/shot */
|
||||
int timer;
|
||||
int ammo; /* bullet type */
|
||||
} fire;
|
||||
|
||||
int score; /*Score for destroy*/
|
||||
int health; /*Health points*/
|
||||
|
||||
/*
|
||||
* Event callbacks
|
||||
*/
|
||||
int (*on_hit)(struct cs_obj_t *o); /* Ouch! */
|
||||
int (*on_dying)(struct cs_obj_t *o); /* Destructing... */
|
||||
int (*on_fire)(struct cs_obj_t *o); /* BOOM! */
|
||||
|
||||
/*
|
||||
* Collision detection callbacks
|
||||
* Called when bounding rect intersection is detected.
|
||||
* Should return 1 if there actually is a collision.
|
||||
*/
|
||||
int (*collision)(struct cs_obj_t *o1, struct cs_obj_t *o2);
|
||||
|
||||
/*
|
||||
* Rendering callback
|
||||
* NOTE: Use (gx,gy) when rendering, *NOT* (x,y)!
|
||||
*/
|
||||
void (*render)(struct cs_obj_t *o);
|
||||
|
||||
/*
|
||||
* User destructor; Object is freed after you return.
|
||||
*/
|
||||
int (*on_free)(struct cs_obj_t *o);
|
||||
|
||||
/* User data */
|
||||
int tag; /* user ID */
|
||||
void *user; /* user data */
|
||||
} cs_obj_t;
|
||||
|
||||
|
||||
/* cs_obj_t flags */
|
||||
|
||||
/*
|
||||
* True when an object is "in the system"; ie when it's in one of
|
||||
* the sprite lists, as opposed to in the free pool, or unattached.
|
||||
* ("Unattached" is the state an object is in when you've just got
|
||||
* it from cs_engine_get_obj().)
|
||||
*/
|
||||
#define CS_OBJ_ACTIVE 0x00000001
|
||||
|
||||
/*
|
||||
* Note that an object with a 0 visible flag is still *active*! It's
|
||||
* coordinates are updated, animation, collisions, spawning/shooting
|
||||
* etc runs - it's just not visible. (Well, whatever is spawned is.)
|
||||
*/
|
||||
#define CS_OBJ_VISIBLE 0x00000002
|
||||
|
||||
/*
|
||||
* Set by the collision detection system whenever any part of the
|
||||
* object's bounding rectangle is inside the bounding rectangle
|
||||
* of the screen.
|
||||
*/
|
||||
#define CS_OBJ_ONSCREN 0x00000004
|
||||
|
||||
/*
|
||||
* Set whenever the cs animation system is to be used to generate
|
||||
* image frame numbers for this object.
|
||||
*/
|
||||
#define CS_OBJ_DOANIM 0x00000008
|
||||
|
||||
/*
|
||||
* Set while the object is marked as dying. Normally, you would
|
||||
* run some animation and perhaps spawn some explosion objects,
|
||||
* and then free the object.
|
||||
*/
|
||||
#define CS_OBJ_DYING 0x00000010
|
||||
|
||||
|
||||
/* Basic methods */
|
||||
/*
|
||||
* Note: You only really need cs_obj_layer(), cs_obj_show()
|
||||
* and cs_obj_free(). The others are just for more fine
|
||||
* grained life cycle control.
|
||||
*/
|
||||
void cs_obj_layer(cs_obj_t *o, unsigned int layer);
|
||||
void cs_obj_activate(cs_obj_t *o); /* Add to cs */
|
||||
void cs_obj_show(cs_obj_t *o); /* Enable display */
|
||||
void cs_obj_hide(cs_obj_t *o); /* Disable display */
|
||||
void cs_obj_deactivate(cs_obj_t *o); /* Disengage from cs */
|
||||
void cs_obj_free(cs_obj_t *o); /* Remove and throw back in the pool */
|
||||
|
||||
void cs_obj_pos(cs_obj_t *o, int x, int y); /* Set new position */
|
||||
void cs_obj_vel(cs_obj_t *o, int xs, int ys); /* Set movement speed */
|
||||
void cs_obj_acc(cs_obj_t *o, int xa, int ya); /* Set movement acceleration */
|
||||
void cs_obj_vector(cs_obj_t *o, cs_vector_t *v);/* Set all */
|
||||
|
||||
void cs_obj_clear(cs_obj_t *o);
|
||||
|
||||
/* Animation methods */
|
||||
void cs_obj_image(cs_obj_t *o, int bank, int frame);
|
||||
void cs_obj_anim(cs_obj_t *o, int bank,
|
||||
int first, int num,
|
||||
int start, int spd);
|
||||
void cs_obj_explode(cs_obj_t *o); /*Start death sequence*/
|
||||
|
||||
/* Fire/spawning control */
|
||||
/* NOTE:
|
||||
In the original version, spawned object speed was
|
||||
absolute, while here, it's relative to object 'o'.
|
||||
*/
|
||||
void cs_obj_shoot(cs_obj_t *o, int xo, int yo, int xs,
|
||||
int ys, int rate, int delay, int ammo);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int w, h;
|
||||
} image_info_t;
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
* cs_engine_t (new)
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
typedef struct cs_engine_t
|
||||
{
|
||||
/* Display window size (pixels) */
|
||||
int w, h;
|
||||
|
||||
/* Wrapping limits (pixels) */
|
||||
int wx, wy;
|
||||
|
||||
/* Motion filtering */
|
||||
int filter; /* 0: newest,
|
||||
* 1: linear interpolation
|
||||
*/
|
||||
|
||||
/* Current time in frames */
|
||||
double time;
|
||||
|
||||
/*
|
||||
* Callback that's called once per Control System
|
||||
* frame from within cs_engine_advance().
|
||||
*/
|
||||
void (*on_frame)(struct cs_engine_t *e);
|
||||
|
||||
/* Active objects */
|
||||
cs_obj_t *objects[CS_LAYERS];
|
||||
|
||||
/* Layer position/offset control */
|
||||
cs_point_t offsets[CS_LAYERS];
|
||||
|
||||
/* Position control for custom stuff */
|
||||
cs_point_t points[CS_USER_POINTS];
|
||||
|
||||
/*
|
||||
* Combined "changed" flag masks for the object groups above.
|
||||
*/
|
||||
int changed[CS_LAYERS];
|
||||
|
||||
/* Pool of unused objects */
|
||||
cs_obj_t *pool;
|
||||
int pool_free; /* # of objects in here */
|
||||
int pool_total; /* # of objects in system */
|
||||
|
||||
/* Image info table */
|
||||
image_info_t *imageinfo;
|
||||
int nimageinfo;
|
||||
} cs_engine_t;
|
||||
|
||||
|
||||
cs_engine_t *cs_engine_create(int w, int h, int objects);
|
||||
void cs_engine_set_size(cs_engine_t *e, int w, int h);
|
||||
void cs_engine_set_image_size(cs_engine_t *e, int bank, int w, int h);
|
||||
void cs_engine_set_wrap(cs_engine_t *e, int x, int y);
|
||||
void cs_engine_delete(cs_engine_t *e);
|
||||
|
||||
void cs_engine_reset(cs_engine_t *e);
|
||||
void cs_engine_advance(cs_engine_t *e, double to_frame); /* 0 == reset timer*/
|
||||
void cs_engine_render(cs_engine_t *e);
|
||||
|
||||
cs_obj_t *cs_engine_get_obj(cs_engine_t *e);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _CS_H_ */
|
||||
@@ -0,0 +1,104 @@
|
||||
/*(LGPL)
|
||||
* Simple display for score, lives etc.
|
||||
* © David Olofson, 2001-2003, 2007
|
||||
*/
|
||||
|
||||
#define D_LINE_HEIGHT 9
|
||||
|
||||
#define D_LINE1_POS 1
|
||||
#define D_LINE1_TXOFFS 0
|
||||
|
||||
#define D_LINE2_POS 9
|
||||
#define D_LINE2_TXOFFS 0
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "window.h"
|
||||
#include "display.h"
|
||||
|
||||
display_t::display_t()
|
||||
{
|
||||
_on = 0;
|
||||
caption("CAPTION");
|
||||
text("TEXT");
|
||||
on();
|
||||
}
|
||||
|
||||
|
||||
void display_t::color(Uint32 _cl)
|
||||
{
|
||||
_color = _cl;
|
||||
if(_on)
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
void display_t::caption(const char *cap)
|
||||
{
|
||||
strncpy(_caption, cap, sizeof(_caption));
|
||||
if(_on)
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
void display_t::text(const char *txt)
|
||||
{
|
||||
strncpy(_text, txt, sizeof(_text));
|
||||
if(_on)
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
void display_t::on()
|
||||
{
|
||||
if(_on)
|
||||
return;
|
||||
|
||||
_on = 1;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
void display_t::off()
|
||||
{
|
||||
if(!_on)
|
||||
return;
|
||||
|
||||
_on = 0;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
void display_t::render_caption()
|
||||
{
|
||||
SDL_Rect r;
|
||||
r.x = 0;
|
||||
r.y = D_LINE1_POS;
|
||||
r.w = width();
|
||||
r.h = D_LINE_HEIGHT;
|
||||
background(_color);
|
||||
clear(&r);
|
||||
if(_on)
|
||||
center(D_LINE1_POS + D_LINE1_TXOFFS, _caption);
|
||||
}
|
||||
|
||||
|
||||
void display_t::render_text()
|
||||
{
|
||||
SDL_Rect r;
|
||||
r.x = 0;
|
||||
r.y = D_LINE2_POS;
|
||||
r.w = width();
|
||||
r.h = D_LINE_HEIGHT;
|
||||
background(_color);
|
||||
clear(&r);
|
||||
if(_on)
|
||||
center(D_LINE2_POS + D_LINE2_TXOFFS, _text);
|
||||
}
|
||||
|
||||
|
||||
void display_t::refresh(SDL_Rect *r)
|
||||
{
|
||||
render_caption();
|
||||
render_text();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*(LGPL)
|
||||
* Simple display for score, lives etc.
|
||||
* © David Olofson, 2001
|
||||
*/
|
||||
|
||||
#include "window.h"
|
||||
|
||||
class display_t : public window_t
|
||||
{
|
||||
char _caption[64];
|
||||
char _text[64];
|
||||
int _on;
|
||||
Uint32 _color;
|
||||
void render_caption();
|
||||
void render_text();
|
||||
public:
|
||||
display_t();
|
||||
void refresh(SDL_Rect *r);
|
||||
void color(Uint32 _cl);
|
||||
void caption(const char *cap);
|
||||
void text(const char *txt);
|
||||
void on();
|
||||
void off();
|
||||
};
|
||||
+1159
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,192 @@
|
||||
/*(LGPL)
|
||||
----------------------------------------------------------------------
|
||||
filters.h - Filters for the sprite manager
|
||||
----------------------------------------------------------------------
|
||||
* Copyright (C) David Olofson, 2001, 2003
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef SPRITE_FILTERS_H
|
||||
#define SPRITE_FILTERS_H
|
||||
|
||||
#include "sprite.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Flags (args.flags) that apply to most plugins:
|
||||
*/
|
||||
#define SF_CLAMP_EXTEND 0x00000001
|
||||
#define SF_CLAMP_SFONT 0x00000002
|
||||
|
||||
|
||||
/*
|
||||
* Convert bank to RGBA 8:8:8:8 format.
|
||||
*
|
||||
* (No arguments.)
|
||||
*/
|
||||
int s_filter_rgba8(s_bank_t *b, unsigned first, unsigned frames,
|
||||
s_filter_args_t *args);
|
||||
|
||||
/*
|
||||
* Dither R, G and B channels to the specified bit depth.
|
||||
*
|
||||
* args.x = 1 activates 16 bit RGBA fix (assume +/-16 dither depth for RGBA)
|
||||
* args.y = dither type (0 = 2x2 filter, 1 = random)
|
||||
*
|
||||
* args.r = red dither depth
|
||||
* args.g = green dither depth
|
||||
* args.b = blue dither depth
|
||||
*
|
||||
* args.flags;
|
||||
* SF_CLAMP_SFONT SFont mode; first row is ignored.
|
||||
*
|
||||
* Note: This plugin does *not* dither the alpha channel!
|
||||
*/
|
||||
int s_filter_dither(s_bank_t *b, unsigned first, unsigned frames,
|
||||
s_filter_args_t *args);
|
||||
|
||||
/*
|
||||
* Convert bank to display format for fast rendering.
|
||||
*
|
||||
* args.x = 1 forces use of SDL_DisplayFormat().
|
||||
* RGBA surfaces get a colorkey of <0,0,0,0>.
|
||||
*/
|
||||
int s_filter_displayformat(s_bank_t *b, unsigned first, unsigned frames,
|
||||
s_filter_args_t *args);
|
||||
|
||||
/*
|
||||
* Convert colorkey to alpha channel.
|
||||
*
|
||||
* The global colorkey variable is used for base colorkey value.
|
||||
* args.max = colorkey detection fuzziness factor
|
||||
* args.flags;
|
||||
* SF_CLAMP_SFONT SFont mode; first row is ignored.
|
||||
*/
|
||||
int s_filter_key2alpha(s_bank_t *b, unsigned first, unsigned frames,
|
||||
s_filter_args_t *args);
|
||||
|
||||
/*
|
||||
* Adjust alpha level and contrast, and then clean out almost opaque
|
||||
* and almost transparent pixels.
|
||||
*
|
||||
* args.fx = alpha contrast (1.0 = unchanged; 2.0 = double; scales around 128)
|
||||
* args.x = alpha offset (0 = unchanged; -255 = all transp.; 255 = all opaque)
|
||||
*
|
||||
* args.min = min alpha passed (lower ==> 0)
|
||||
* args.max = max alpha passed (higher ==> 255)
|
||||
*
|
||||
* args.flags;
|
||||
* SF_CLAMP_SFONT SFont mode; first row is ignored.
|
||||
*/
|
||||
int s_filter_cleanalpha(s_bank_t *b, unsigned first, unsigned frames,
|
||||
s_filter_args_t *args);
|
||||
|
||||
/*
|
||||
* Adjust brightness and contrast.
|
||||
*
|
||||
* args.fx = brightness (1.0 = unchanged; 0.0 = black; 2.0 = white)
|
||||
* args.fy = contrast (1.0 = unchanged; 0.5 = 50%; 2.0 = 200%)
|
||||
*
|
||||
* args.min = min value (clamping)
|
||||
* args.max = max value (clamping)
|
||||
*
|
||||
* args.flags;
|
||||
* SF_CLAMP_SFONT SFont mode; first row is ignored.
|
||||
*/
|
||||
int s_filter_brightness(s_bank_t *b, unsigned first, unsigned frames,
|
||||
s_filter_args_t *args);
|
||||
|
||||
/*
|
||||
* Scale images by the specified factor, using the specified method.
|
||||
*
|
||||
* args.x = scaling mode;
|
||||
* SF_SCALE_NEAREST Nearest
|
||||
* SF_SCALE_BILINEAR Bilinear interpolation
|
||||
* SF_SCALE_SCALE2X Scale2x (Based on an algo from AdvanceMAME)
|
||||
* SF_SCALE_DIAMOND Diamond (Weighted diamond shaped core)
|
||||
*
|
||||
* args.fx = horizontal scale factor (1.0 ==> 1:1)
|
||||
* args.fy = vertical scale factor (1.0 ==> 1:1)
|
||||
*
|
||||
* args.flags;
|
||||
* SF_CLAMP_EXTEND Clamp at edges; image edge is extended outwards
|
||||
* SF_CLAMP_SFONT SFont mode; first row is treated specially.
|
||||
*
|
||||
*/
|
||||
#define SF_SCALE_NEAREST 0
|
||||
#define SF_SCALE_BILINEAR 1
|
||||
#define SF_SCALE_SCALE2X 2
|
||||
#define SF_SCALE_DIAMOND 3
|
||||
int s_filter_scale(s_bank_t *b, unsigned first, unsigned frames,
|
||||
s_filter_args_t *args);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
TODO:
|
||||
* Add shaded light to images.
|
||||
*
|
||||
* args.fx = Highlight X position ([0,1])
|
||||
* args.fy = Highlight Y position ([0,1])
|
||||
* args.fz = Highlight "half intensity" radius
|
||||
*
|
||||
* args.x = Gradient type:
|
||||
* SF_LIGHT_LINEAR Linear gradient
|
||||
* SF_LIGHT_CIRCULAR Circular spotlight
|
||||
*
|
||||
* args.z = Gradient rotation (65536 units/rotation)
|
||||
*
|
||||
* args.min = "Ambient light"
|
||||
* args.max = Max brightness
|
||||
*
|
||||
* args.r = Light color, red component
|
||||
* args.g = Light color, green component
|
||||
* args.b = Light color, blue component
|
||||
*
|
||||
* args.flags;
|
||||
* SF_CLAMP_SFONT SFont mode; first row is ignored.
|
||||
*/
|
||||
#define SF_LIGHT_LINEAR 0
|
||||
#define SF_LIGHT_CIRCULAR 1
|
||||
int s_filter_light(s_bank_t *b, unsigned first, unsigned frames,
|
||||
s_filter_args_t *args);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Add single colored noise to images.
|
||||
*
|
||||
* args.x = Pseudo-RNG seed for first frame
|
||||
*
|
||||
* args.min = Min brightness ([0,255])
|
||||
* args.max = Max brightness ([0,255])
|
||||
*
|
||||
* args.r = Noise color, red component ([0,255])
|
||||
* args.g = Noise color, green component ([0,255])
|
||||
* args.b = Noise color, blue component ([0,255])
|
||||
*
|
||||
* args.flags;
|
||||
* SF_CLAMP_SFONT SFont mode; first row is ignored.
|
||||
*/
|
||||
int s_filter_noise(s_bank_t *b, unsigned first, unsigned frames,
|
||||
s_filter_args_t *args);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SPRITE_FILTERS_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,282 @@
|
||||
/*(LGPL)
|
||||
----------------------------------------------------------------------
|
||||
gfxengine.h - Graphics Engine
|
||||
----------------------------------------------------------------------
|
||||
* Copyright (C) 2001-2003, 2007 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _GFXENGINE_H_
|
||||
#define _GFXENGINE_H_
|
||||
|
||||
#define GFX_BANKS 256
|
||||
#define MAX_DIRTYRECTS 1024
|
||||
#define MAX_PAGES 3
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "glSDL.h"
|
||||
#include "sprite.h"
|
||||
#include "cs.h"
|
||||
|
||||
enum gfx_drivers_t
|
||||
{
|
||||
GFX_DRIVER_SDL2D = 0,
|
||||
GFX_DRIVER_GLSDL = 1
|
||||
};
|
||||
|
||||
enum gfx_scalemodes_t
|
||||
{
|
||||
GFX_SCALE_NEAREST = 0,
|
||||
GFX_SCALE_BILINEAR = 1,
|
||||
GFX_SCALE_BILIN_OVER = 2,
|
||||
GFX_SCALE_SCALE2X = 3,
|
||||
GFX_SCALE_DIAMOND = 4
|
||||
};
|
||||
|
||||
class window_t;
|
||||
class SoFont;
|
||||
|
||||
class gfxengine_t
|
||||
{
|
||||
friend class window_t;
|
||||
public:
|
||||
gfxengine_t();
|
||||
virtual ~gfxengine_t();
|
||||
|
||||
void output(window_t *outwin);
|
||||
window_t *output() { return window; }
|
||||
|
||||
void screen(window_t *fullwin);
|
||||
window_t *screen() { return fullwin; }
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
void size(int w, int h);
|
||||
void centered(int c);
|
||||
void scale(float x, float y);
|
||||
void driver(gfx_drivers_t drv);
|
||||
void mode(int bits, int fullscreen);
|
||||
|
||||
// 1: Use double buffering if possible
|
||||
void doublebuffer(int use);
|
||||
|
||||
// -1: Use default for shadow() and doublebuffer() settings
|
||||
// 0: None; assume flipping gives you a garbage buffer
|
||||
// 1: Assume flipping leaves the back buffer intact
|
||||
// 2: Assume two buffers that are swapped when flipping
|
||||
// 3: Assume three buffers cycled when flipping
|
||||
void pages(int np);
|
||||
|
||||
// 1: Enable vsync, if available
|
||||
void vsync(int use);
|
||||
|
||||
// 1: Use a software shadow back buffer, if possible
|
||||
void shadow(int use);
|
||||
|
||||
void autoinvalidate(int use);
|
||||
|
||||
void interpolation(int inter);
|
||||
|
||||
// 0 to reset internal timer
|
||||
void period(float frameduration);
|
||||
|
||||
// 0 to disable timing, running one logic frame per rendered frame.
|
||||
// 1 to disable filtering, using raw delta times for timing.
|
||||
void timefilter(float coeff);
|
||||
|
||||
void wrap(int x, int y);
|
||||
|
||||
/* Info */
|
||||
int doublebuffer() { return _doublebuf; }
|
||||
int shadow() { return _shadow; }
|
||||
int autoinvalidate() { return _autoinvalidate; }
|
||||
|
||||
/* Engine open/close */
|
||||
int open(int objects = 1024, int extraflags = 0);
|
||||
void close();
|
||||
|
||||
/* Data management (use while engine is open) */
|
||||
void reset_filters();
|
||||
void filterflags(int fgs);
|
||||
void scalemode(gfx_scalemodes_t sm, int clamping = 0);
|
||||
void source_scale(float x, float y);
|
||||
// void colorkey(Uint8 r, Uint8 g, Uint8 b);
|
||||
void clampcolor(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
||||
void dither(int type = 0, int _broken_rgba8 = 0);
|
||||
void noalpha(int threshold = 128);
|
||||
void brightness(float bright, float contr);
|
||||
|
||||
int loadimage(int bank, const char *name);
|
||||
int loadtiles(int bank, int w, int h, const char *name);
|
||||
int loadfont(int bank, const char *name);
|
||||
int copyrect(int bank, int sbank, int sframe, SDL_Rect *r);
|
||||
|
||||
int is_loaded(int bank);
|
||||
void reload();
|
||||
void unload(int bank = -1);
|
||||
|
||||
/* Settings (use while engine is open) */
|
||||
void title(const char *win, const char *icon);
|
||||
|
||||
/* Display show/hide */
|
||||
int show();
|
||||
void hide();
|
||||
|
||||
/* Main loop take-over */
|
||||
void run();
|
||||
|
||||
/*
|
||||
* Override these;
|
||||
* frame() is called once per control system frame,
|
||||
* after the control system has executed.
|
||||
* pre_render() is called after the engine has advanced
|
||||
* to the state for the current video frame
|
||||
* (interpolated state is calculated), before
|
||||
* the engine renders all graphics.
|
||||
* post_render() is called after the engine have
|
||||
* rendered all sprites, but before video the
|
||||
* sync/flip/update operation.
|
||||
*/
|
||||
virtual void frame();
|
||||
virtual void pre_render();
|
||||
virtual void post_render();
|
||||
|
||||
/*
|
||||
---------------------------------------------
|
||||
* The members below this line can safely be
|
||||
* called from within the frame() handler.
|
||||
*/
|
||||
|
||||
/* Rendering */
|
||||
void clear(Uint32 _color = 0x000000);
|
||||
void invalidate(SDL_Rect *rect = NULL, window_t *window = NULL);
|
||||
|
||||
/* Screenshots */
|
||||
void screenshot();
|
||||
|
||||
/* Control */
|
||||
cs_engine_t *cs() { return csengine; }
|
||||
SDL_Surface *surface();
|
||||
void flip(); // Flip pages
|
||||
void update(); // Full update, making current draw page visible
|
||||
void stop();
|
||||
cs_obj_t *get_obj(int layer);
|
||||
void free_obj(cs_obj_t *obj);
|
||||
void cursor(int csr);
|
||||
|
||||
s_sprite_t *get_sprite(unsigned bank, int _frame)
|
||||
{
|
||||
return s_get_sprite(gfx, bank, _frame);
|
||||
}
|
||||
SoFont *get_font(unsigned int f);
|
||||
int set_hotspot(unsigned bank, int _frame, int x, int y)
|
||||
{
|
||||
return s_set_hotspot(gfx, bank, _frame, x, y);
|
||||
}
|
||||
|
||||
void scroll_ratio(int layer, float xr, float yr);
|
||||
void scroll(int xs, int ys);
|
||||
void force_scroll();
|
||||
|
||||
int xoffs(int layer);
|
||||
int yoffs(int layer);
|
||||
|
||||
/* Info */
|
||||
int objects_in_use();
|
||||
|
||||
int width() { return _width; }
|
||||
int height() { return _height; }
|
||||
float xscale() { return xs * (1.f/256.f); }
|
||||
float yscale() { return ys * (1.f/256.f); }
|
||||
|
||||
protected:
|
||||
gfx_drivers_t _driver;
|
||||
gfx_scalemodes_t _scalemode;
|
||||
int _clamping;
|
||||
SDL_Surface *screen_surface;
|
||||
SDL_Surface *softbuf;
|
||||
int backpage;
|
||||
int frontpage;
|
||||
int dirtyrects[MAX_PAGES];
|
||||
SDL_Rect dirtytable[MAX_PAGES][MAX_DIRTYRECTS];
|
||||
window_t *dirtywtable[MAX_PAGES][MAX_DIRTYRECTS];
|
||||
window_t *fullwin;
|
||||
window_t *window;
|
||||
window_t *windows; // Linked list
|
||||
int wx, wy;
|
||||
int xs, ys; // fix 24:8
|
||||
int sxs, sys; // fix 24:8
|
||||
s_filter_t *sf1, *sf2; // Scaling filter plugins
|
||||
s_filter_t *acf; // Alpha cleaning plugin
|
||||
s_filter_t *bcf; // Brightness/contrast plugin
|
||||
s_filter_t *df; // Dither filter plugin
|
||||
s_filter_t *dsf; // Display format plugin
|
||||
int xscroll, yscroll;
|
||||
float xratio[CS_LAYERS];
|
||||
float yratio[CS_LAYERS];
|
||||
s_container_t *gfx;
|
||||
SoFont *fonts[GFX_BANKS]; // Kludge.
|
||||
cs_engine_t *csengine;
|
||||
int xflags;
|
||||
int _doublebuf;
|
||||
int _pages;
|
||||
int _vsync;
|
||||
int _shadow;
|
||||
int _fullscreen;
|
||||
int _centered;
|
||||
int _autoinvalidate;
|
||||
int use_interpolation;
|
||||
int _width, _height;
|
||||
int _depth;
|
||||
const char *_title;
|
||||
const char *_icontitle;
|
||||
int _cursor;
|
||||
int _dither;
|
||||
int _dither_type;
|
||||
int broken_rgba8; //Klugde for OpenGL (if RGBA8 ==> RGBA4)
|
||||
int alpha_threshold; //For noalpha()
|
||||
float _brightness;
|
||||
float _contrast;
|
||||
|
||||
int last_tick;
|
||||
float ticks_per_frame;
|
||||
float _timefilter;
|
||||
|
||||
int is_showing;
|
||||
int is_running;
|
||||
int is_open;
|
||||
|
||||
int screenshot_count;
|
||||
|
||||
void __invalidate(int page, SDL_Rect *rect = NULL,
|
||||
window_t *window = NULL);
|
||||
void refresh_rect(SDL_Rect *r);
|
||||
|
||||
static void on_frame(cs_engine_t *e);
|
||||
void __frame();
|
||||
|
||||
void start_engine();
|
||||
void stop_engine();
|
||||
static void render_sprite(cs_obj_t *o);
|
||||
};
|
||||
|
||||
|
||||
extern gfxengine_t *gfxengine;
|
||||
|
||||
#endif
|
||||
+2328
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,399 @@
|
||||
/*(LGPL)
|
||||
------------------------------------------------------------
|
||||
glSDL 0.9 - SDL 2D API on top of OpenGL
|
||||
------------------------------------------------------------
|
||||
* Copyright (C) 2001-2004, 2006-2007 David Olofson
|
||||
* This code is released under the terms of the GNU LGPL.
|
||||
*/
|
||||
|
||||
#ifndef _GLSDL_H_
|
||||
#define _GLSDL_H_
|
||||
|
||||
/*
|
||||
* If you don't use GNU autotools or similar, uncomment this to
|
||||
* compile with OpenGL enabled:
|
||||
#define HAVE_OPENGL
|
||||
*
|
||||
* NOTE:
|
||||
* See README about using this glSDL wrapper with
|
||||
* SDL versions that have the glSDL backend!
|
||||
*/
|
||||
|
||||
/* We're still using SDL datatypes here - we just add some stuff. */
|
||||
#include "SDL.h"
|
||||
|
||||
/*
|
||||
* Ignore the flag from SDL w/ glSDL backend, since we're going
|
||||
* to use glSDL/wrapper by default.
|
||||
*/
|
||||
#ifdef SDL_GLSDL
|
||||
#undef SDL_GLSDL
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_OPENGL
|
||||
|
||||
/* Fakes to make glSDL code compile with SDL. */
|
||||
#define SDL_GLSDL 0
|
||||
#define GLSDL_FIX_SURFACE(s)
|
||||
|
||||
#else /* HAVE_OPENGL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (SDL_MAJOR_VERSION <= 1) && (SDL_MINOR_VERSION <= 2) && \
|
||||
(SDL_PATCHLEVEL < 5)
|
||||
#warning glSDL: Using SDL version 1.2.5 or later is strongly recommended!
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------
|
||||
SDL style API
|
||||
----------------------------------------------------------*/
|
||||
|
||||
typedef enum glSDL_TileModes
|
||||
{
|
||||
GLSDL_TM_SINGLE,
|
||||
GLSDL_TM_HORIZONTAL,
|
||||
GLSDL_TM_VERTICAL,
|
||||
GLSDL_TM_HUGE
|
||||
} glSDL_TileModes;
|
||||
|
||||
|
||||
typedef struct glSDL_TexInfo
|
||||
{
|
||||
int textures;
|
||||
int *texture;
|
||||
int texsize; /* width/height of OpenGL texture */
|
||||
glSDL_TileModes tilemode;
|
||||
int tilew, tileh; /* At least one must equal texsize! */
|
||||
int tilespertex;
|
||||
|
||||
/* Area of surface to download when/after unlocking */
|
||||
SDL_Rect invalid_area;
|
||||
} glSDL_TexInfo;
|
||||
|
||||
#define GLSDL_FIX_SURFACE(s) (s)->unused1 = 0;
|
||||
#define IS_GLSDL_SURFACE(s) ((s) && texinfotab && glSDL_GetTexInfo(s))
|
||||
|
||||
#ifdef SDL_GLSDL
|
||||
#undef SDL_GLSDL /* In case SDL has the glSDL backend... */
|
||||
#endif
|
||||
#define SDL_GLSDL 0x00100000 /* Create an OpenGL 2D rendering context */
|
||||
|
||||
|
||||
/*
|
||||
* Wraps SDL_SetVideoMode(), and adds support for the SDL_GLSDL flag.
|
||||
*
|
||||
* If 'flags' contains SDL_GLSDL, glSDL_SetVideoMode() sets up a "pure"
|
||||
* OpenGL rendering context for use with the glSDL_ calls.
|
||||
*
|
||||
* SDL can be closed as usual (using SDL_ calls), but you should call
|
||||
* glSDL_Quit() (kludge) to allow glSDL to clean up it's internal stuff.
|
||||
*/
|
||||
SDL_Surface *glSDL_SetVideoMode(int width, int height, int bpp, Uint32 flags);
|
||||
void glSDL_Quit(void);
|
||||
|
||||
void glSDL_QuitSubSystem(Uint32 flags);
|
||||
|
||||
/* Replaces SDL_Quit() entirely, when using the override defines */
|
||||
void glSDL_FullQuit(void);
|
||||
|
||||
SDL_Surface *glSDL_GetVideoSurface(void);
|
||||
|
||||
void glSDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects);
|
||||
void glSDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h);
|
||||
|
||||
/*
|
||||
* Works like SDL_Flip(), but may also perform enqueued blits.
|
||||
* (That is, it's possible that the implementation renders
|
||||
* *nothing* until glSDL_Flip() is called.)
|
||||
*/
|
||||
int glSDL_Flip(SDL_Surface *screen);
|
||||
|
||||
void glSDL_FreeSurface(SDL_Surface *surface);
|
||||
|
||||
int glSDL_LockSurface(SDL_Surface *surface);
|
||||
void glSDL_UnlockSurface(SDL_Surface *surface);
|
||||
|
||||
/*
|
||||
* Like the respective SDL functions, although they ignore
|
||||
* SDL_RLEACCEL, as it makes no sense in this context.
|
||||
*/
|
||||
int glSDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);
|
||||
int glSDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha);
|
||||
|
||||
/*
|
||||
* Sets up clipping for the screen, or a SDL_Surface.
|
||||
*
|
||||
* Note that this function takes both SDL_Surfaces and
|
||||
* glSDL_Surfaces.
|
||||
*/
|
||||
SDL_bool glSDL_SetClipRect(SDL_Surface *surface, SDL_Rect *rect);
|
||||
|
||||
int glSDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect,
|
||||
SDL_Surface *dst, SDL_Rect *dstrect);
|
||||
|
||||
int glSDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
|
||||
|
||||
/*
|
||||
* Convert the given surface into a SDL_Surface (if it isn't
|
||||
* one already), and makes sure that the underlying SDL_Surface
|
||||
* is of a pixel format suitable for fast texture downloading.
|
||||
*
|
||||
* Note that you *only* have to use this function if you want
|
||||
* fast pixel access to surfaces (ie "procedural textures").
|
||||
* Any surfaces that aren't converted will be downloaded
|
||||
* automatically upon the first call to glSDL_BlitSurface(),
|
||||
* but if conversion is required, it will be required for
|
||||
* every glSDL_UnlockSurface() call.
|
||||
*
|
||||
* IMPORTANT:
|
||||
* You *can* pass an SDL_Surface directly to this function,
|
||||
* and it will try to deal with it nicely. However, this
|
||||
* requires that a temporary SDL_Surface is created, and
|
||||
* this surface is cached only until the texture memory is
|
||||
* needed for new surfaces.
|
||||
*/
|
||||
SDL_Surface *glSDL_DisplayFormat(SDL_Surface *surface);
|
||||
SDL_Surface *glSDL_DisplayFormatAlpha(SDL_Surface *surface);
|
||||
|
||||
SDL_Surface *glSDL_ConvertSurface
|
||||
(SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags);
|
||||
SDL_Surface *glSDL_CreateRGBSurface
|
||||
(Uint32 flags, int width, int height, int depth,
|
||||
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
|
||||
SDL_Surface *glSDL_CreateRGBSurfaceFrom(void *pixels,
|
||||
int width, int height, int depth, int pitch,
|
||||
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
|
||||
SDL_Surface *glSDL_LoadBMP(const char *file);
|
||||
int glSDL_SaveBMP(SDL_Surface *surface, const char *file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Some ugly "overriding"... */
|
||||
#ifndef _GLSDL_NO_REDEFINES_
|
||||
/*
|
||||
* You *always* need to lock and unlock a glSDL surface in
|
||||
* order to get glSDL to update the OpenGL texture!
|
||||
*/
|
||||
#undef SDL_MUSTLOCK
|
||||
#define SDL_MUSTLOCK(surface) \
|
||||
(surface->offset || \
|
||||
((surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_RLEACCEL)) != 0) || \
|
||||
IS_GLSDL_SURFACE(surface))
|
||||
|
||||
#define SDL_SetVideoMode glSDL_SetVideoMode
|
||||
#define SDL_GetVideoSurface glSDL_GetVideoSurface
|
||||
#define SDL_Quit glSDL_FullQuit
|
||||
#define SDL_QuitSubSystem glSDL_QuitSubSystem
|
||||
#define SDL_UpdateRects glSDL_UpdateRects
|
||||
#define SDL_UpdateRect glSDL_UpdateRect
|
||||
#define SDL_Flip glSDL_Flip
|
||||
#define SDL_FreeSurface glSDL_FreeSurface
|
||||
#define SDL_LockSurface glSDL_LockSurface
|
||||
#define SDL_UnlockSurface glSDL_UnlockSurface
|
||||
#define SDL_SetColorKey glSDL_SetColorKey
|
||||
#define SDL_SetAlpha glSDL_SetAlpha
|
||||
#define SDL_SetClipRect glSDL_SetClipRect
|
||||
#undef SDL_BlitSurface
|
||||
#define SDL_BlitSurface glSDL_BlitSurface
|
||||
#define SDL_FillRect glSDL_FillRect
|
||||
#define SDL_DisplayFormat glSDL_DisplayFormat
|
||||
#define SDL_DisplayFormatAlpha glSDL_DisplayFormatAlpha
|
||||
#define SDL_ConvertSurface glSDL_ConvertSurface
|
||||
#define SDL_CreateRGBSurface glSDL_CreateRGBSurface
|
||||
#define SDL_CreateRGBSurfaceFrom glSDL_CreateRGBSurfaceFrom
|
||||
#undef SDL_AllocSurface
|
||||
#define SDL_AllocSurface glSDL_CreateRGBSurface
|
||||
#undef SDL_LoadBMP
|
||||
#define SDL_LoadBMP glSDL_LoadBMP
|
||||
#undef SDL_SaveBMP
|
||||
#define SDL_SaveBMP glSDL_SaveBMP
|
||||
#define IMG_Load(x) glSDL_IMG_Load(x)
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_OPENGL */
|
||||
|
||||
|
||||
#ifdef HAVE_OPENGL
|
||||
|
||||
/* Some extra overloading for common external lib calls... */
|
||||
#include "SDL_image.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
SDL_Surface *glSDL_IMG_Load(const char *file);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_OPENGL */
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
glSDL API extensions, transparent
|
||||
----------------------------------------------------------*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Invalidate part of a texture.
|
||||
*
|
||||
* This function can be used either between calls to
|
||||
* glSDL_LockSurface() and glSDL_UnlockSurface(), or before
|
||||
* calling glSDL_DownloadSurface().
|
||||
*
|
||||
* In either case, it causes only the specified area to be
|
||||
* downloaded when unlocking the surface, or calling
|
||||
* glSDL_UnlockSurface(), respectively.
|
||||
*
|
||||
* Note that if this function is not used, glSDL assumes that
|
||||
* the entire surface has to be updated. (That is, it's safe
|
||||
* to ignore this function - it's "just a performance hack.")
|
||||
*
|
||||
* Passing a rectangle with zero height or width cancels the
|
||||
* downloading when/after unlocking the surface. Use if you
|
||||
* just want to read the texture, but feel like being nice and
|
||||
* obeying SDL_MUSTLOCK() - which is a good idea, as things
|
||||
* may change...
|
||||
*
|
||||
* Passing NULL for the 'area' argument results in the entire
|
||||
* surface being invalidated.
|
||||
*
|
||||
* NOTE: This function does NOT perform clipping! Weird or
|
||||
* even Bad Things may happen if you specify areas
|
||||
* that protrude outside the edges of the actual
|
||||
* surface.
|
||||
*/
|
||||
void glSDL_Invalidate(SDL_Surface *surface, SDL_Rect *area);
|
||||
|
||||
/*
|
||||
* Make sure that the texture of the specified surface is up
|
||||
* to date in OpenGL texture memory.
|
||||
*
|
||||
* This can be used together with glSDL_UnloadSurface() to
|
||||
* implement custom texture caching schemes.
|
||||
*
|
||||
* Returns 0 on success, or a negative value if something
|
||||
* went wrong.
|
||||
*/
|
||||
int glSDL_UploadSurface(SDL_Surface *surface);
|
||||
|
||||
/*
|
||||
* Free the texture space used by the specified surface.
|
||||
*
|
||||
* Normally, glSDL should download textures when needed, and
|
||||
* unload the oldest (in terms of use) surfaces, if it runs out
|
||||
* of texture space.
|
||||
*/
|
||||
void glSDL_UnloadSurface(SDL_Surface *surface);
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
glSDL API extensions, OpenGL mode ONLY
|
||||
----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Enable, disable or check the state of "vsync" or
|
||||
* vertical retrace synchronization. Note that enabling
|
||||
* this does not *guarantee* that the driver actually
|
||||
* uses vsync; it only instructs OpenGL to do so if
|
||||
* possible.
|
||||
* Pass 1 for 'use' to enable vsync, '0' to disable
|
||||
* it, and -1 to just return the current state without
|
||||
* changing it.
|
||||
* Returns the vsync state *before* any change made
|
||||
* by the call.
|
||||
*
|
||||
* NOTE: Ignored when not using OpenGL acceleration!
|
||||
*/
|
||||
int glSDL_VSync(int use);
|
||||
|
||||
/*
|
||||
* Set alpha multiplier. This is multiplied with any full
|
||||
* surface alpha or alpha channels of surfaces.
|
||||
*
|
||||
* The default value is 255, which makes glSDL render like
|
||||
* the standard SDL 2D backends, ie based only on the
|
||||
* surface settings.
|
||||
*
|
||||
* This function affects the global state of glSDL.
|
||||
*
|
||||
* NOTE: NOT available without OpenGL acceleration!
|
||||
*/
|
||||
void glSDL_SetBlendAlpha(Uint8 alpha);
|
||||
|
||||
/*
|
||||
* Set color multipliers. These are multiplied with the
|
||||
* respective color channers of rendered surfaces,
|
||||
* modulating the brightness of the resulting output.
|
||||
*
|
||||
* The default values are 255, which makes glSDL render
|
||||
* like the standard SDL 2D backends.
|
||||
*
|
||||
* This function affects the global state of glSDL.
|
||||
*
|
||||
* NOTE: NOT available without OpenGL acceleration!
|
||||
*/
|
||||
void glSDL_SetBlendColor(Uint8 r, Uint8 g, Uint8 b);
|
||||
|
||||
/*
|
||||
* Set center offset in pixels for scaling and rotation.
|
||||
*
|
||||
* The default is (0, 0), which makes surfaces rotate and
|
||||
* scale around their centers.
|
||||
*
|
||||
* This function affects the global state of glSDL.
|
||||
*
|
||||
* NOTE: NOT available without OpenGL acceleration!
|
||||
*/
|
||||
void glSDL_SetCenter(float x, float y);
|
||||
|
||||
|
||||
/*
|
||||
* Set rotation angle in degrees. Rotation is done around
|
||||
* the center point, which is defined as
|
||||
* (w/2 + cx, h/2 + cy)
|
||||
* where w and h are the width and height of the source
|
||||
* surface, and cx and cy are the center offsets set by
|
||||
* glSDL_SetCenter().
|
||||
*
|
||||
* The default value is 0.0f, which makes glSDL render
|
||||
* like a normal SDL 2D backend.
|
||||
*
|
||||
* This function affects the global state of glSDL.
|
||||
*
|
||||
* NOTE: NOT available without OpenGL acceleration!
|
||||
*/
|
||||
void glSDL_SetRotation(float angle);
|
||||
|
||||
/*
|
||||
* Set scale factor. Scaling is centered around around
|
||||
* the point
|
||||
* (w/2 + cx, h/2 + cy)
|
||||
* where w and h are the width and height of the source
|
||||
* surface, and cx and cy are the center offsets set by
|
||||
* glSDL_SetCenter().
|
||||
*
|
||||
* The default value is 1.0f, which makes glSDL render
|
||||
* like a normal SDL 2D backend.
|
||||
*
|
||||
* This function affects the global state of glSDL.
|
||||
*
|
||||
* NOTE: NOT available without OpenGL acceleration!
|
||||
*/
|
||||
void glSDL_SetScale(float x, float y);
|
||||
|
||||
/*
|
||||
* Reset glSDL global state to defaults.
|
||||
*/
|
||||
void glSDL_ResetState(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _GLSDL_H_ */
|
||||
@@ -0,0 +1,213 @@
|
||||
/*(LGPL)
|
||||
----------------------------------------------------------------------
|
||||
region.c - Graphics Engine
|
||||
----------------------------------------------------------------------
|
||||
* Copyright (C) 2007 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "region.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static struct
|
||||
{
|
||||
RGN_region *region;
|
||||
int x, y;
|
||||
SDL_Surface *target;
|
||||
} s;
|
||||
|
||||
|
||||
static Uint32 gp1(SDL_Surface *surface, int x, int y)
|
||||
{
|
||||
return *((Uint8 *)surface->pixels + y * surface->pitch + x);
|
||||
}
|
||||
|
||||
|
||||
static Uint32 gp2(SDL_Surface *surface, int x, int y)
|
||||
{
|
||||
return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
|
||||
}
|
||||
|
||||
|
||||
static Uint32 gp3(SDL_Surface *surface, int x, int y)
|
||||
{
|
||||
int bpp = surface->format->BytesPerPixel;
|
||||
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
|
||||
#if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
|
||||
return p[0] << 16 | p[1] << 8 | p[2];
|
||||
#else
|
||||
return p[0] | p[1] << 8 | p[2] << 16;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static Uint32 gp4(SDL_Surface *surface, int x, int y)
|
||||
{
|
||||
return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
|
||||
}
|
||||
|
||||
|
||||
RGN_region *RGN_ScanMask(SDL_Surface *src, Uint32 key)
|
||||
{
|
||||
RGN_region *rgn = (RGN_region *)calloc(1, sizeof(RGN_region));
|
||||
Uint32 (*gp)(SDL_Surface *surface, int x, int y);
|
||||
int x, y;
|
||||
if(!rgn)
|
||||
return NULL;
|
||||
rgn->rows = src->h;
|
||||
rgn->spans = (Uint16 **)calloc(1, sizeof(Uint16 *) * src->h);
|
||||
if(!rgn->spans)
|
||||
{
|
||||
RGN_FreeRegion(rgn);
|
||||
return NULL;
|
||||
}
|
||||
switch(src->format->BytesPerPixel)
|
||||
{
|
||||
case 1:
|
||||
gp = gp1;
|
||||
break;
|
||||
case 2:
|
||||
gp = gp2;
|
||||
break;
|
||||
case 3:
|
||||
gp = gp3;
|
||||
break;
|
||||
case 4:
|
||||
gp = gp4;
|
||||
break;
|
||||
default:
|
||||
RGN_FreeRegion(rgn);
|
||||
return NULL;
|
||||
}
|
||||
SDL_LockSurface(src);
|
||||
for(y = 0; y < src->h; ++y)
|
||||
{
|
||||
int i = 0;
|
||||
int drawing = 0;
|
||||
Uint16 *sp = (Uint16 *)malloc(sizeof(Uint16) * 2 * (src->w + 1));
|
||||
if(!sp)
|
||||
{
|
||||
SDL_UnlockSurface(src);
|
||||
RGN_FreeRegion(rgn);
|
||||
return NULL;
|
||||
}
|
||||
for(x = 0; x < src->w; ++x)
|
||||
{
|
||||
int nd = (gp(src, x, y) == key);
|
||||
if(nd != drawing)
|
||||
{
|
||||
sp[i++] = x;
|
||||
drawing = nd;
|
||||
}
|
||||
}
|
||||
if(drawing)
|
||||
sp[i++] = src->w;
|
||||
sp[i++] = 0;
|
||||
sp[i++] = 0;
|
||||
rgn->spans[y] = (Uint16 *)realloc(sp, sizeof(Uint16) * i);
|
||||
if(!rgn->spans[y])
|
||||
rgn->spans[y] = sp;
|
||||
}
|
||||
SDL_UnlockSurface(src);
|
||||
return rgn;
|
||||
}
|
||||
|
||||
|
||||
void RGN_FreeRegion(RGN_region *rgn)
|
||||
{
|
||||
if(!rgn)
|
||||
return;
|
||||
if(rgn->spans)
|
||||
{
|
||||
int i;
|
||||
for(i = rgn->rows - 1; i >= 0; --i)
|
||||
free(rgn->spans[i]);
|
||||
free(rgn->spans);
|
||||
}
|
||||
free(rgn);
|
||||
}
|
||||
|
||||
|
||||
void RGN_Target(SDL_Surface *tgt)
|
||||
{
|
||||
s.target = tgt;
|
||||
}
|
||||
|
||||
|
||||
void RGN_SetRegion(RGN_region *rgn, int xpos, int ypos)
|
||||
{
|
||||
s.region = rgn;
|
||||
s.x = xpos;
|
||||
s.y = ypos;
|
||||
}
|
||||
|
||||
|
||||
int RGN_Blit(SDL_Surface *src, SDL_Rect *sr, int x, int y)
|
||||
{
|
||||
// FIXME: Clipping is only half done here...
|
||||
int yy0, yy, yy1;
|
||||
int sxmin, sxmax, symin, symax;
|
||||
SDL_Rect sr2;
|
||||
if(!s.region)
|
||||
{
|
||||
SDL_Rect dr;
|
||||
dr.x = x;
|
||||
dr.y = y;
|
||||
return SDL_BlitSurface(src, sr, s.target, &dr);
|
||||
}
|
||||
if(sr)
|
||||
{
|
||||
sxmin = sr->x;
|
||||
symin = sr->y;
|
||||
sxmax = sxmin + sr->w;
|
||||
symax = symin + sr->h;
|
||||
}
|
||||
else
|
||||
{
|
||||
sxmin = 0;
|
||||
symin = 0;
|
||||
sxmax = src->w;
|
||||
symax = src->h;
|
||||
}
|
||||
yy0 = s.y;
|
||||
if(yy0 >= y + (symax - symin))
|
||||
return 0;
|
||||
if(yy0 < y)
|
||||
yy0 = y;
|
||||
yy1 = s.y + s.region->rows;
|
||||
if(y >= yy1)
|
||||
return 0;
|
||||
if(yy1 > y + (symax - symin))
|
||||
yy1 = y + (symax - symin);
|
||||
sr2.h = 1;
|
||||
for(yy = yy0; yy < yy1; ++yy)
|
||||
{
|
||||
SDL_Rect dr;
|
||||
Uint16 *spans = s.region->spans[yy - s.y];
|
||||
sr2.y = symin + y - yy0;
|
||||
dr.y = yy;
|
||||
for( ; spans[0] && spans[1] ; spans += 2)
|
||||
{
|
||||
int x0 = s.x + spans[0];
|
||||
int x1 = s.x + spans[1];
|
||||
dr.x = x0;
|
||||
sr2.x = sxmin + x0 - x;
|
||||
sr2.w = x1 - x0;
|
||||
SDL_BlitSurface(src, &sr2, s.target, &dr);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*(LGPL)
|
||||
----------------------------------------------------------------------
|
||||
region.h - Graphics Engine
|
||||
----------------------------------------------------------------------
|
||||
* Copyright (C) 2007 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef KOBO_REGION_H
|
||||
#define KOBO_REGION_H
|
||||
|
||||
#include "glSDL.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Region
|
||||
* Describes an area as a number of pixel spaced rows,
|
||||
* each containing zero or more spans on the form <start, end>.
|
||||
*/
|
||||
typedef struct RGN_region
|
||||
{
|
||||
int rows;
|
||||
Uint16 **spans;
|
||||
} RGN_region;
|
||||
|
||||
/* Construct region by scanning an SDL surface */
|
||||
RGN_region *RGN_ScanMask(SDL_Surface *src, Uint32 key);
|
||||
|
||||
/* Free a region */
|
||||
void RGN_FreeRegion(RGN_region *rgn);
|
||||
|
||||
/* Set target for region rendering */
|
||||
void RGN_Target(SDL_Surface *tgt);
|
||||
|
||||
/* Select and position region for subsequent operations */
|
||||
void RGN_SetRegion(RGN_region *rgn, int xpos, int ypos);
|
||||
|
||||
/* Blit to region! */
|
||||
int RGN_Blit(SDL_Surface *src, SDL_Rect *sr, int x, int y);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* KOBO_REGION_H */
|
||||
@@ -0,0 +1,577 @@
|
||||
#include "logger.h"
|
||||
#include "stdlib.h"
|
||||
#include "sofont.h"
|
||||
#include "string.h"
|
||||
|
||||
SoFont::SoFont()
|
||||
{
|
||||
picture = NULL;
|
||||
CharPos = NULL;
|
||||
CharOffset = NULL;
|
||||
Spacing = NULL;
|
||||
height = 0;
|
||||
max_i = 0;
|
||||
spacew = 0;
|
||||
cursShift = 0;
|
||||
background = 0;
|
||||
xspace = 1;
|
||||
}
|
||||
|
||||
SoFont::~SoFont()
|
||||
{
|
||||
if(picture)
|
||||
SDL_FreeSurface(picture);
|
||||
delete[]CharPos;
|
||||
delete[]CharOffset;
|
||||
delete[]Spacing;
|
||||
}
|
||||
|
||||
namespace SoFontUtilities
|
||||
{
|
||||
Uint32 SoFontGetPixel(SDL_Surface * Surface, Sint32 X, Sint32 Y)
|
||||
{
|
||||
Uint8 *bits;
|
||||
Uint32 Bpp;
|
||||
|
||||
if(!Surface)
|
||||
{
|
||||
log_printf(ELOG, "SoFontGetPixel: No surface!\n");
|
||||
return 0;
|
||||
}
|
||||
if((X < 0) || (X >= Surface->w))
|
||||
{
|
||||
log_printf(ELOG, "SoFontGetPixel: X (%d)"
|
||||
" out of range!\n", X);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Bpp = Surface->format->BytesPerPixel;
|
||||
|
||||
bits = ((Uint8 *) Surface->pixels) + Y * Surface->pitch +
|
||||
X * Bpp;
|
||||
|
||||
switch (Bpp)
|
||||
{
|
||||
case 1:
|
||||
return *((Uint8 *) Surface->pixels +
|
||||
Y * Surface->pitch + X);
|
||||
break;
|
||||
case 2:
|
||||
return *((Uint16 *) Surface->pixels +
|
||||
Y * Surface->pitch / 2 + X);
|
||||
break;
|
||||
case 3:
|
||||
// Format/endian independent
|
||||
Uint8 r, g, b;
|
||||
r = *((bits) + Surface->format->Rshift / 8);
|
||||
g = *((bits) + Surface->format->Gshift / 8);
|
||||
b = *((bits) + Surface->format->Bshift / 8);
|
||||
return SDL_MapRGB(Surface->format, r, g, b);
|
||||
break;
|
||||
case 4:
|
||||
return *((Uint32 *) Surface->pixels +
|
||||
Y * Surface->pitch / 4 + X);
|
||||
break;
|
||||
}
|
||||
log_printf(ELOG, "SoFontGetPixel: Unsupported pixel format!\n");
|
||||
return 0; // David (to get rid of warning)
|
||||
}
|
||||
void SoFontSetPixel(SDL_Surface * Surface, Sint32 X, Sint32 Y,
|
||||
Uint32 c)
|
||||
{
|
||||
Uint8 *bits;
|
||||
Uint32 Bpp;
|
||||
|
||||
if(!Surface)
|
||||
{
|
||||
log_printf(ELOG, "SoFontSetPixel: No surface!\n");
|
||||
return;
|
||||
}
|
||||
if((X < 0) || (X >= Surface->w))
|
||||
{
|
||||
log_printf(ELOG, "SoFontSetPixel: X (%d)"
|
||||
" out of range!\n", X);
|
||||
return;
|
||||
}
|
||||
|
||||
Bpp = Surface->format->BytesPerPixel;
|
||||
|
||||
bits = ((Uint8 *) Surface->pixels) + Y * Surface->pitch +
|
||||
X * Bpp;
|
||||
|
||||
switch (Bpp)
|
||||
{
|
||||
case 1:
|
||||
*((Uint8 *) Surface->pixels + Y * Surface->pitch +
|
||||
X) = (Uint8) c;
|
||||
break;
|
||||
case 2:
|
||||
*((Uint16 *) Surface->pixels +
|
||||
Y * Surface->pitch / 2 + X) =
|
||||
(Uint16) c;
|
||||
break;
|
||||
case 3:
|
||||
// Format/endian independent
|
||||
Uint8 r, g, b;
|
||||
SDL_GetRGB(c, Surface->format, &r, &g, &b);
|
||||
*((bits) + Surface->format->Rshift / 8) = r;
|
||||
*((bits) + Surface->format->Gshift / 8) = g;
|
||||
*((bits) + Surface->format->Bshift / 8) = b;
|
||||
break;
|
||||
case 4:
|
||||
*((Uint32 *) Surface->pixels +
|
||||
Y * Surface->pitch / 4 + X) = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
void clipx(SDL_Rect * srcrect, SDL_Rect * dstrect, SDL_Rect * clip)
|
||||
{
|
||||
// Use if destination have the same size than source.
|
||||
int dx = clip->x - dstrect->x;
|
||||
|
||||
int sw = srcrect->w; // Because SDL_Rect.w are
|
||||
// unsigned.
|
||||
int dw = dstrect->w;
|
||||
|
||||
if(dx > 0)
|
||||
{
|
||||
srcrect->x += dx;
|
||||
dstrect->x += dx;
|
||||
|
||||
sw -= dx;
|
||||
dw -= dx;
|
||||
}
|
||||
|
||||
int dwx = (dstrect->x + dstrect->w) - (clip->x + clip->w);
|
||||
|
||||
if(dwx > 0)
|
||||
{
|
||||
sw -= dwx;
|
||||
dw -= dwx;
|
||||
}
|
||||
|
||||
if(sw > 0)
|
||||
srcrect->w = sw;
|
||||
else
|
||||
srcrect->w = 0;
|
||||
|
||||
if(dw > 0)
|
||||
dstrect->w = dw;
|
||||
else
|
||||
dstrect->w = 0;
|
||||
}
|
||||
void sdcRects(SDL_Rect * source, SDL_Rect * destination,
|
||||
SDL_Rect clipping)
|
||||
{
|
||||
// Use if destination have the same size than source &
|
||||
// cliping on destination
|
||||
int dx = clipping.x - destination->x;
|
||||
int dy = clipping.y - destination->y;
|
||||
|
||||
int sw = source->w;
|
||||
int sh = source->h;
|
||||
|
||||
if(dx > 0)
|
||||
{
|
||||
source->x += dx;
|
||||
destination->x += dx;
|
||||
|
||||
sw -= dx;
|
||||
destination->w -= dx;
|
||||
}
|
||||
if(dy > 0)
|
||||
{
|
||||
source->y += dy;
|
||||
destination->y += dy;
|
||||
|
||||
sh -= dy;
|
||||
destination->h -= dy;
|
||||
}
|
||||
|
||||
int dwx = (destination->x + destination->w) - (clipping.x +
|
||||
clipping.w);
|
||||
int dhy = (destination->y + destination->h) - (clipping.y +
|
||||
clipping.h);
|
||||
|
||||
if(dwx > 0)
|
||||
{
|
||||
sw -= dwx;
|
||||
destination->w -= dwx;
|
||||
}
|
||||
if(dhy > 0)
|
||||
{
|
||||
sh -= dhy;
|
||||
destination->h -= dhy;
|
||||
}
|
||||
|
||||
if(sw > 0)
|
||||
source->w = sw;
|
||||
else
|
||||
source->w = 0;
|
||||
|
||||
if(sh > 0)
|
||||
source->h = sh;
|
||||
else
|
||||
source->h = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
using namespace SoFontUtilities;
|
||||
|
||||
bool SoFont::DoStartNewChar(Sint32 x)
|
||||
{
|
||||
if(!picture)
|
||||
return false;
|
||||
return SoFontGetPixel(picture, x, 0) ==
|
||||
SDL_MapRGB(picture->format, 255, 0, 255);
|
||||
}
|
||||
|
||||
void SoFont::CleanSurface()
|
||||
{
|
||||
if(!picture)
|
||||
return;
|
||||
|
||||
int x = 0, y = 0;
|
||||
Uint32 pix = SDL_MapRGB(picture->format, 255, 0, 255);
|
||||
|
||||
while(x < picture->w)
|
||||
{
|
||||
y = 0;
|
||||
if(SoFontGetPixel(picture, x, y) == pix)
|
||||
SoFontSetPixel(picture, x, y, background);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SoFont::load(SDL_Surface * FontSurface)
|
||||
{
|
||||
int x = 0, i = 0, s = 0;
|
||||
|
||||
int _CharPos[256];
|
||||
int _CharOffset[256];
|
||||
int _Spacing[256];
|
||||
|
||||
if(!FontSurface)
|
||||
{
|
||||
log_printf(ELOG, "SoFont recieved a NULL SDL_Surface\n");
|
||||
return false;
|
||||
}
|
||||
if(picture)
|
||||
SDL_FreeSurface(picture);
|
||||
picture = FontSurface;
|
||||
height = picture->h - 1;
|
||||
while(x < picture->w)
|
||||
{
|
||||
if(DoStartNewChar(x))
|
||||
{
|
||||
if(i)
|
||||
_Spacing[i - 1] = x - s + xspace;
|
||||
int p = x;
|
||||
while((x < picture->w) && (DoStartNewChar(x)))
|
||||
x++;
|
||||
s = x;
|
||||
_CharPos[i] = (x + p + 1) / 2;
|
||||
_CharOffset[i] = x - _CharPos[i];
|
||||
i++;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
//Note that spacing is not needed for the last char,
|
||||
//as it's just used for the blit width calculation.
|
||||
if(i)
|
||||
_Spacing[i - 1] = x - s;
|
||||
_Spacing[i] = 0;
|
||||
_CharOffset[i] = 0;
|
||||
_CharPos[i++] = picture->w;
|
||||
|
||||
max_i = START_CHAR + i - 1;
|
||||
background = SoFontGetPixel(picture, 0, height);
|
||||
// FIXME: Use this when there is no alpha channel?
|
||||
// SDL_SetColorKey(picture, SDL_SRCCOLORKEY, background);
|
||||
CleanSurface();
|
||||
|
||||
delete[]CharPos;
|
||||
delete[]CharOffset;
|
||||
delete[]Spacing;
|
||||
CharPos = new int[i];
|
||||
CharOffset = new int[i];
|
||||
Spacing = new int[i];
|
||||
memcpy(CharPos, _CharPos, i * sizeof(int));
|
||||
memcpy(CharOffset, _CharOffset, i * sizeof(int));
|
||||
memcpy(Spacing, _Spacing, i * sizeof(int));
|
||||
|
||||
// We search for a smart space width:
|
||||
// Changed from "a", "A", "0" for Kobo Deluxe.
|
||||
// Spaces were *way* to wide! //David
|
||||
spacew = 0;
|
||||
if(!spacew)
|
||||
spacew = TextWidth("i") * 3 / 2;
|
||||
if(!spacew)
|
||||
spacew = TextWidth("I") * 3 / 2;
|
||||
if(!spacew)
|
||||
spacew = TextWidth(".") * 3 / 2;
|
||||
if(!spacew)
|
||||
spacew = CharPos[1] - CharPos[0];
|
||||
|
||||
// We search for a smart cursor position:
|
||||
int cursBegin = 0;
|
||||
int cursWidth = 0;
|
||||
cursShift = 0;
|
||||
if('|' > max_i)
|
||||
return true; //No bar in this font!
|
||||
|
||||
if(background == SoFontGetPixel(picture, CharPos['|' - START_CHAR],
|
||||
height / 2))
|
||||
{
|
||||
// Up to the first | color
|
||||
for(cursBegin = 0; cursBegin <= TextWidth("|");
|
||||
cursBegin++)
|
||||
if(background != SoFontGetPixel(picture,
|
||||
CharPos['|' - START_CHAR] +
|
||||
cursBegin, height / 2))
|
||||
break;
|
||||
// Up to the end of the | color
|
||||
for(cursWidth = 0; cursWidth <= TextWidth("|");
|
||||
cursWidth++)
|
||||
if(background == SoFontGetPixel(picture,
|
||||
CharPos['|' - START_CHAR] +
|
||||
cursBegin + cursWidth,
|
||||
height / 2))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Up to the end of the | color
|
||||
for(cursWidth = 0; cursWidth <= TextWidth("|");
|
||||
cursWidth++)
|
||||
if(background == SoFontGetPixel(picture,
|
||||
CharPos['|' - START_CHAR] +
|
||||
cursWidth, height / 2))
|
||||
break;
|
||||
}
|
||||
cursShift = cursBegin + 1; // cursWidth could be used if
|
||||
// image format changes.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SoFont::PutString(SDL_Surface *Surface, int x, int y,
|
||||
const char *text, SDL_Rect *clip)
|
||||
{
|
||||
if((!picture) || (!Surface) || (!text))
|
||||
return;
|
||||
int ofs, i = 0;
|
||||
SDL_Rect srcrect, dstrect;
|
||||
while(text[i] != '\0')
|
||||
{
|
||||
if(text[i] == ' ')
|
||||
{
|
||||
x += spacew;
|
||||
i++;
|
||||
}
|
||||
else if((text[i] >= START_CHAR) && (text[i] <= max_i))
|
||||
{
|
||||
ofs = text[i] - START_CHAR;
|
||||
srcrect.w = dstrect.w =
|
||||
this->CharPos[ofs + 1] -
|
||||
this->CharPos[ofs];
|
||||
srcrect.h = dstrect.h = height;
|
||||
srcrect.x = this->CharPos[ofs];
|
||||
srcrect.y = 1;
|
||||
dstrect.x = x - CharOffset[ofs];
|
||||
dstrect.y = y;
|
||||
x += Spacing[ofs];
|
||||
if(clip)
|
||||
sdcRects(&srcrect, &dstrect, *clip);
|
||||
SDL_BlitSurface(picture, &srcrect, Surface,
|
||||
&dstrect);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
i++; // other chars are ignored
|
||||
|
||||
// Coarse clipping
|
||||
if(clip)
|
||||
{
|
||||
if(x > clip->x + clip->w)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(x > Surface->w)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoFont::PutStringWithCursor(SDL_Surface * Surface, int xs, int y,
|
||||
const char *text, int cursPos, SDL_Rect * clip,
|
||||
bool showCurs)
|
||||
{
|
||||
if((!picture) || (!Surface) || (!text))
|
||||
return;
|
||||
if('|' > max_i)
|
||||
showCurs = false;
|
||||
int ofs, i = 0, x = xs;
|
||||
|
||||
SDL_Rect srcrect, dstrect;
|
||||
|
||||
// We want the cursor to appear under the main text.
|
||||
if(showCurs)
|
||||
{
|
||||
while(text[i] != '\0')
|
||||
if(i == cursPos)
|
||||
break;
|
||||
else if(text[i] == ' ')
|
||||
{
|
||||
x += spacew;
|
||||
i++;
|
||||
}
|
||||
else if((text[i] >= START_CHAR)
|
||||
&& (text[i] <= max_i))
|
||||
{
|
||||
ofs = text[i] - START_CHAR;
|
||||
x += Spacing[ofs];
|
||||
i++;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
ofs = '|' - START_CHAR;
|
||||
|
||||
srcrect.w = dstrect.w = CharPos[ofs + 1] - CharPos[ofs];
|
||||
srcrect.h = dstrect.h = height;
|
||||
srcrect.x = this->CharPos[ofs];
|
||||
srcrect.y = 1;
|
||||
dstrect.x = x - cursShift;
|
||||
dstrect.y = y;
|
||||
if(clip)
|
||||
sdcRects(&srcrect, &dstrect, *clip);
|
||||
SDL_BlitSurface(picture, &srcrect, Surface, &dstrect);
|
||||
}
|
||||
// Then the text:
|
||||
PutString(Surface, xs, y, text, clip);
|
||||
}
|
||||
int SoFont::TextWidth(const char *text, int min, int max)
|
||||
{
|
||||
if(!picture)
|
||||
return 0;
|
||||
int ofs, x = 0, i = min;
|
||||
while((text[i] != '\0') && (i < max))
|
||||
{
|
||||
if(text[i] == ' ')
|
||||
{
|
||||
x += spacew;
|
||||
i++;
|
||||
}
|
||||
else if((text[i] >= START_CHAR) && (text[i] <= max_i))
|
||||
{
|
||||
ofs = text[i] - START_CHAR;
|
||||
x += Spacing[ofs];
|
||||
i++;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
void SoFont::XCenteredString(SDL_Surface * Surface, int y,
|
||||
const char *text, SDL_Rect * clip)
|
||||
{
|
||||
if(!picture)
|
||||
return;
|
||||
PutString(Surface, Surface->w / 2 - TextWidth(text) / 2, y, text,
|
||||
clip);
|
||||
}
|
||||
|
||||
void SoFont::CenteredString(SDL_Surface * Surface, int x, int y,
|
||||
const char *text, SDL_Rect * clip)
|
||||
{
|
||||
if(!picture)
|
||||
return;
|
||||
PutString(Surface, x - TextWidth(text) / 2, y - height / 2, text,
|
||||
clip);
|
||||
}
|
||||
|
||||
void SoFont::CenteredString(SDL_Surface * Surface, const char *text,
|
||||
SDL_Rect * clip)
|
||||
{
|
||||
if(!picture)
|
||||
return;
|
||||
CenteredString(Surface, Surface->clip_rect.w / 2,
|
||||
Surface->clip_rect.h / 2, text, clip);
|
||||
}
|
||||
|
||||
void SoFont::PutStringCleverCursor(SDL_Surface * Surface, const char *text,
|
||||
int cursPos, SDL_Rect * r, SDL_Rect * clip, bool showCurs)
|
||||
{
|
||||
if((!picture) || (!text))
|
||||
return;
|
||||
|
||||
int w1, w2;
|
||||
|
||||
w1 = TextWidth(text, 0, cursPos);
|
||||
w2 = TextWidth(text);
|
||||
|
||||
if((w2 < r->w) || (w1 < r->w / 2))
|
||||
PutStringWithCursor(Surface, r->x,
|
||||
r->y + (r->h - height) / 2, text, cursPos,
|
||||
clip, showCurs);
|
||||
else if(w1 < w2 - r->w / 2)
|
||||
PutStringWithCursor(Surface, r->x - w1 + r->w / 2,
|
||||
r->y + (r->h - height) / 2, text, cursPos,
|
||||
clip, showCurs);
|
||||
else
|
||||
PutStringWithCursor(Surface, r->x - w2 + r->w,
|
||||
r->y + (r->h - height) / 2, text, cursPos,
|
||||
clip, showCurs);
|
||||
}
|
||||
|
||||
int SoFont::TextCursorAt(const char *text, int px)
|
||||
{
|
||||
if(!picture)
|
||||
return 0;
|
||||
int ofs, x = 0, i = 0, ax = 0;
|
||||
|
||||
if(px <= 0)
|
||||
return 0;
|
||||
|
||||
while(text[i] != '\0')
|
||||
{
|
||||
if(text[i] == ' ')
|
||||
{
|
||||
x += spacew;
|
||||
i++;
|
||||
}
|
||||
else if((text[i] >= START_CHAR) && (text[i] <= max_i))
|
||||
{
|
||||
ofs = text[i] - START_CHAR;
|
||||
x += Spacing[ofs];
|
||||
i++;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
|
||||
if(px < (ax + x) / 2)
|
||||
return (i - 1);
|
||||
ax = x;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int SoFont::CleverTextCursorAt(const char *text, int px, int cursPos,
|
||||
SDL_Rect * r)
|
||||
{
|
||||
if((!picture) || (!text))
|
||||
return 0;
|
||||
int w1, w2;
|
||||
w1 = TextWidth(text, 0, cursPos);
|
||||
w2 = TextWidth(text);
|
||||
if((w2 < r->w) || (w1 < r->w / 2))
|
||||
return TextCursorAt(text, px);
|
||||
else if(w1 < w2 - r->w / 2)
|
||||
return TextCursorAt(text, px + w1 - (r->w / 2));
|
||||
else
|
||||
return TextCursorAt(text, px + w2 - r->w);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
SoFont - SDL Object Font Library
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Originally from C Library:
|
||||
Karl Bartel
|
||||
|
||||
* SFONT - SDL Font Library by Karl Bartel <karlb@gmx.net> *
|
||||
* *
|
||||
* All functions are explained below. There are two versions of each *
|
||||
* funtction. The first is the normal one, the function with the *
|
||||
* 2 at the end can be used when you want to handle more than one font *
|
||||
* in your program. *
|
||||
* *
|
||||
|
||||
Copied into a C++ object to allow multiple fonts by:
|
||||
Luc-Olivier de Charriere
|
||||
|
||||
David Olofson <david@olofson.net>:
|
||||
* Strings changed to 'const char *'
|
||||
* Cursor tests first check if '|' is present.
|
||||
* Shadowed variables fixed.
|
||||
* Garbage data in spacing table fixed. (Thanks to
|
||||
Andreas Spångberg for discovering this one!)
|
||||
* Added ExtraSpace(). (Scaling support hack...)
|
||||
* Disabled colorkeying. (Ruins some RGBA fonts!)
|
||||
*/
|
||||
|
||||
#ifndef __SOFONT_H
|
||||
#define __SOFONT_H
|
||||
|
||||
#include "glSDL.h"
|
||||
|
||||
class SoFont
|
||||
{
|
||||
public:
|
||||
SoFont();
|
||||
~SoFont();
|
||||
|
||||
bool load(SDL_Surface *FontSurface);
|
||||
|
||||
// Blits a string to a surface
|
||||
// Destination: the suface you want to blit to
|
||||
// text: a string containing the text you want to blit.
|
||||
void PutString(SDL_Surface *Surface, int x, int y, const char *text, SDL_Rect *clip=NULL);
|
||||
void PutStringWithCursor(SDL_Surface *Surface, int x, int y, const char *text, int cursPos, SDL_Rect *clip=NULL, bool showCurs=true);
|
||||
|
||||
// Returns the width of "text" in pixels
|
||||
int TextWidth(const char *text, int min=0, int max=255);
|
||||
|
||||
int FontHeight() { return height; }
|
||||
|
||||
// Blits a string to with centered x position
|
||||
void XCenteredString(SDL_Surface *Surface, int y, const char *text, SDL_Rect* clip=NULL);
|
||||
// Blits a string to with centered x & y position
|
||||
void CenteredString(SDL_Surface *Surface, const char *text, SDL_Rect* clip=NULL);
|
||||
// Blits a string to with centered around x & y positions
|
||||
void CenteredString(SDL_Surface *Surface, int x, int y, const char *text, SDL_Rect* clip=NULL);
|
||||
|
||||
// This was specially developped for GUI
|
||||
void PutStringCleverCursor(SDL_Surface *Surface, const char *text, int cursPos, SDL_Rect *r, SDL_Rect* clip=NULL, bool showCurs=true);
|
||||
|
||||
// Gives the cursor position given a x-axix point in the text
|
||||
int TextCursorAt(const char *text, int px);
|
||||
int CleverTextCursorAt(const char *text, int px, int cursPos, SDL_Rect *r);
|
||||
|
||||
# define START_CHAR 33
|
||||
int getMinChar(){return START_CHAR;}
|
||||
int getMaxChar(){return max_i;}
|
||||
|
||||
void ExtraSpace(int xs)
|
||||
{
|
||||
xspace = xs;
|
||||
}
|
||||
|
||||
protected:
|
||||
int height;
|
||||
SDL_Surface *picture;
|
||||
int *CharPos;
|
||||
int *CharOffset;
|
||||
int *Spacing;
|
||||
int xspace;
|
||||
|
||||
int max_i, spacew, cursShift;
|
||||
Uint32 background;
|
||||
bool DoStartNewChar(Sint32 x);
|
||||
void CleanSurface();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,612 @@
|
||||
/*(LGPL)
|
||||
----------------------------------------------------------------------
|
||||
sprite.c - Sprite engine for use with cs.h
|
||||
----------------------------------------------------------------------
|
||||
* Copyright (C) 2001, 2003, 2007 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
TODO: Automatic extension of the bank and sprite
|
||||
TODO: tables as needed when loading banks.
|
||||
*/
|
||||
|
||||
#define DBG(x) x
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "logger.h"
|
||||
#include "glSDL.h"
|
||||
#include "SDL_image.h"
|
||||
#include "sprite.h"
|
||||
#include "filters.h"
|
||||
|
||||
|
||||
s_blitmodes_t s_blitmode = S_BLITMODE_AUTO;
|
||||
pix_t s_colorkey = {0, 0, 0, 0};
|
||||
pix_t s_clampcolor = {0, 0, 0, 0};
|
||||
unsigned char s_alpha = SDL_ALPHA_OPAQUE;
|
||||
int s_filter_flags = 0;
|
||||
|
||||
|
||||
s_filter_t *filters = NULL;
|
||||
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
Filter Plugin Interface
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
s_filter_t *s_insert_filter(s_filter_cb_t callback)
|
||||
{
|
||||
s_filter_t *nf = calloc(1, sizeof(s_filter_t));
|
||||
if(!nf)
|
||||
return NULL;
|
||||
|
||||
nf->callback = callback;
|
||||
nf->next = filters;
|
||||
filters = nf;
|
||||
return nf;
|
||||
}
|
||||
|
||||
|
||||
s_filter_t *s_add_filter(s_filter_cb_t callback)
|
||||
{
|
||||
s_filter_t *nf = calloc(1, sizeof(s_filter_t));
|
||||
if(!nf)
|
||||
return NULL;
|
||||
|
||||
nf->callback = callback;
|
||||
if(!filters)
|
||||
filters = nf;
|
||||
else
|
||||
{
|
||||
s_filter_t *f = filters;
|
||||
while(f->next)
|
||||
f = f->next;
|
||||
f->next = nf;
|
||||
}
|
||||
return nf;
|
||||
}
|
||||
|
||||
|
||||
/* filter == NULL means "remove all plugins" */
|
||||
void s_remove_filter(s_filter_t *filter)
|
||||
{
|
||||
s_filter_t *f;
|
||||
if(!filters)
|
||||
return;
|
||||
|
||||
f = filters;
|
||||
while(f->next)
|
||||
{
|
||||
if(f->next == filter || !filter)
|
||||
{
|
||||
s_filter_t *df = f->next;
|
||||
f->next = f->next->next;
|
||||
free(df);
|
||||
}
|
||||
else
|
||||
f = f->next;
|
||||
}
|
||||
if(filters == filter || !filter)
|
||||
{
|
||||
s_filter_t *df = filters;
|
||||
filters = filters->next;
|
||||
free(df);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void __run_plugins(s_bank_t *b, unsigned first, unsigned frames)
|
||||
{
|
||||
s_filter_t *f = filters;
|
||||
while(f)
|
||||
{
|
||||
int oflags = f->args.flags;
|
||||
f->args.flags |= s_filter_flags;
|
||||
f->callback(b, first, frames, &f->args);
|
||||
f->args.flags = oflags;
|
||||
f = f->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
Basic Container Management
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int __alloc_bank_table(s_container_t *c, unsigned int count)
|
||||
{
|
||||
c->max = count - 1;
|
||||
c->banks = (s_bank_t **)calloc((unsigned)count, sizeof(s_bank_t *));
|
||||
return -(c->banks == NULL);
|
||||
}
|
||||
|
||||
s_container_t *s_new_container(unsigned banks)
|
||||
{
|
||||
s_container_t *ret = (s_container_t *)calloc(1, sizeof(s_container_t));
|
||||
if(!ret)
|
||||
return NULL;
|
||||
if(__alloc_bank_table(ret, banks) < 0)
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void s_delete_container(s_container_t *c)
|
||||
{
|
||||
s_delete_all_banks(c);
|
||||
free(c->banks);
|
||||
free(c);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allocates a new sprite.
|
||||
* If the sprite exists already, it's surface will be removed, so
|
||||
* that one can safely expect to get an *empty* sprite.
|
||||
*/
|
||||
s_sprite_t *s_new_sprite_b(s_bank_t *b, unsigned frame)
|
||||
{
|
||||
s_sprite_t *s = NULL;
|
||||
if(frame > b->max)
|
||||
return NULL;
|
||||
if(!b->sprites[frame])
|
||||
{
|
||||
s = calloc(1, sizeof(s_sprite_t));
|
||||
if(!s)
|
||||
return NULL;
|
||||
b->sprites[frame] = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(s->surface)
|
||||
SDL_FreeSurface(s->surface);
|
||||
s->surface = NULL;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allocates a new sprite.
|
||||
* If the sprite exists already, it's surface will be removed, so
|
||||
* that one can safely expect to get an *empty* sprite.
|
||||
*
|
||||
* If the bank does not exist, or if the operation failed for
|
||||
* other reasons, this call returns NULL.
|
||||
*/
|
||||
s_sprite_t *s_new_sprite(s_container_t *c, unsigned bank, unsigned frame)
|
||||
{
|
||||
if(bank > c->max)
|
||||
return NULL;
|
||||
if(!c->banks[bank])
|
||||
return NULL;
|
||||
|
||||
return s_new_sprite_b(c->banks[bank], frame);
|
||||
}
|
||||
|
||||
|
||||
void s_delete_sprite_b(s_bank_t *b, unsigned frame)
|
||||
{
|
||||
if(!b->sprites) /* This can happen when failing to create a new bank */
|
||||
return;
|
||||
if(frame > b->max)
|
||||
return;
|
||||
if(!b->sprites[frame])
|
||||
return;
|
||||
if(b->sprites[frame]->surface)
|
||||
SDL_FreeSurface(b->sprites[frame]->surface);
|
||||
b->sprites[frame]->surface = NULL;
|
||||
free(b->sprites[frame]);
|
||||
b->sprites[frame] = NULL;
|
||||
}
|
||||
|
||||
|
||||
void s_delete_sprite(s_container_t *c, unsigned bank, unsigned frame)
|
||||
{
|
||||
s_bank_t *b = s_get_bank(c, bank);
|
||||
if(b)
|
||||
s_delete_sprite_b(b, frame);
|
||||
}
|
||||
|
||||
|
||||
static int __alloc_sprite_table(s_bank_t *b, unsigned frames)
|
||||
{
|
||||
b->max = frames - 1;
|
||||
b->sprites = (s_sprite_t **)calloc(frames, sizeof(s_sprite_t *));
|
||||
if(!b->sprites)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
s_bank_t *s_new_bank(s_container_t *c, unsigned bank, unsigned frames,
|
||||
unsigned w, unsigned h)
|
||||
{
|
||||
s_bank_t *b;
|
||||
DBG(log_printf(DLOG, "s_new_bank(%p, %d, %d, %d, %d)\n",
|
||||
c, bank, frames, w, h);)
|
||||
if(bank > c->max)
|
||||
return NULL;
|
||||
if(c->banks[bank])
|
||||
s_delete_bank(c, bank);
|
||||
|
||||
c->banks[bank] = (s_bank_t *)calloc(1, sizeof(s_bank_t));
|
||||
if(!c->banks[bank])
|
||||
return NULL;
|
||||
if(__alloc_sprite_table(c->banks[bank], frames) < 0)
|
||||
{
|
||||
s_delete_bank(c, bank);
|
||||
return NULL;
|
||||
}
|
||||
b = c->banks[bank];
|
||||
b->max = frames - 1;
|
||||
b->w = w;
|
||||
b->h = h;
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
void s_delete_bank(s_container_t *c, unsigned bank)
|
||||
{
|
||||
unsigned i;
|
||||
s_bank_t *b;
|
||||
if(!c->banks)
|
||||
return;
|
||||
if(bank > c->max)
|
||||
return;
|
||||
b = c->banks[bank];
|
||||
if(b)
|
||||
{
|
||||
for(i = 0; i <= b->max; ++i)
|
||||
s_delete_sprite_b(b, i);
|
||||
free(b->sprites);
|
||||
free(b);
|
||||
c->banks[bank] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void s_delete_all_banks(s_container_t *c)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i <= c->max; ++i)
|
||||
s_delete_bank(c, i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
Getting data
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
s_bank_t *s_get_bank(s_container_t *c, unsigned bank)
|
||||
{
|
||||
if(bank > c->max)
|
||||
return NULL;
|
||||
if(!c->banks[bank])
|
||||
return NULL;
|
||||
return c->banks[bank];
|
||||
}
|
||||
|
||||
s_sprite_t *s_get_sprite(s_container_t *c, unsigned bank, unsigned frame)
|
||||
{
|
||||
s_bank_t *b = s_get_bank(c, bank);
|
||||
if(!b)
|
||||
return NULL;
|
||||
if(frame > b->max)
|
||||
return NULL;
|
||||
return b->sprites[frame];
|
||||
}
|
||||
|
||||
s_sprite_t *s_get_sprite_b(s_bank_t *b, unsigned frame)
|
||||
{
|
||||
if(!b)
|
||||
return NULL;
|
||||
if(frame > b->max)
|
||||
return NULL;
|
||||
return b->sprites[frame];
|
||||
}
|
||||
|
||||
void s_detach_sprite(s_container_t *c, unsigned bank, unsigned frame)
|
||||
{
|
||||
s_sprite_t *s = s_get_sprite(c, bank, frame);
|
||||
if(!s)
|
||||
return;
|
||||
s->surface = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
File tools
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int extract_sprite(s_bank_t *bank, unsigned frame,
|
||||
SDL_Surface *src, SDL_Rect *from)
|
||||
{
|
||||
int y;
|
||||
SDL_Surface *tmp;
|
||||
if(frame > bank->max)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Too many frames!\n");
|
||||
return -1;
|
||||
}
|
||||
if(!s_new_sprite_b(bank, frame))
|
||||
return -2;
|
||||
|
||||
tmp = SDL_CreateRGBSurface(src->flags,
|
||||
from->w, from->h,
|
||||
src->format->BitsPerPixel,
|
||||
src->format->Rmask,
|
||||
src->format->Gmask,
|
||||
src->format->Bmask,
|
||||
src->format->Amask );
|
||||
if(!tmp)
|
||||
return -3;
|
||||
|
||||
/* Copy the pixel data */
|
||||
if(SDL_LockSurface(src) < 0)
|
||||
{
|
||||
log_printf(ELOG, "sprite: extract_sprite() failed to lock surface!\n");
|
||||
SDL_FreeSurface(tmp);
|
||||
return -4;
|
||||
}
|
||||
for(y = 0; y < tmp->h; ++y)
|
||||
{
|
||||
char *s = (char *)src->pixels + src->pitch * (y + from->y) +
|
||||
from->x * src->format->BytesPerPixel;
|
||||
char *d = (char *)tmp->pixels + tmp->pitch * y;
|
||||
memcpy(d, s, src->format->BytesPerPixel * tmp->w);
|
||||
}
|
||||
SDL_UnlockSurface(src);
|
||||
|
||||
/* Copy palette, if any */
|
||||
if(src->format->palette)
|
||||
SDL_SetColors(tmp, src->format->palette->colors, 0,
|
||||
src->format->palette->ncolors);
|
||||
|
||||
/* Copy alpha and colorkey */
|
||||
if(src->flags & SDL_SRCALPHA)
|
||||
SDL_SetAlpha(tmp, src->flags & (SDL_SRCALPHA | SDL_RLEACCEL),
|
||||
src->format->alpha);
|
||||
if(src->flags & SDL_SRCCOLORKEY)
|
||||
SDL_SetColorKey(tmp, src->flags & (SDL_SRCCOLORKEY | SDL_RLEACCEL),
|
||||
src->format->colorkey);
|
||||
|
||||
bank->sprites[frame]->surface = tmp;
|
||||
|
||||
DBG(log_printf(DLOG, "image %d: (%d,%d)/%dx%d @ %p\n", frame,
|
||||
from->x, from->y, from->w, from->h,
|
||||
bank->sprites[frame]->surface);)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int s_copy_rect(s_container_t *c, unsigned bank,
|
||||
unsigned frombank, unsigned fromframe, SDL_Rect *from)
|
||||
{
|
||||
#if 0
|
||||
s_filter_args_t args;
|
||||
#endif
|
||||
SDL_Surface *src;
|
||||
s_sprite_t *s;
|
||||
s_bank_t *b;
|
||||
|
||||
/* Get source image */
|
||||
s = s_get_sprite(c, frombank, fromframe);
|
||||
if(!s)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Couldn't get source sprite %d:%d!\n",
|
||||
frombank, fromframe);
|
||||
return -1;
|
||||
}
|
||||
src = s->surface;
|
||||
if(!src)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Sprite %d:%d"
|
||||
" does not have a surface!\n",
|
||||
frombank, fromframe);
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Create destination bank */
|
||||
b = s_new_bank(c, bank, 1, from->w, from->h);
|
||||
if(!b)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Failed to allocate bank %d!\n", bank);
|
||||
return -3;
|
||||
}
|
||||
|
||||
if(extract_sprite(b, 0, src, from) < 0)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Something went wrong while "
|
||||
"copying from sprite %d:%d.\n",
|
||||
frombank, fromframe);
|
||||
return -4;
|
||||
}
|
||||
#if 0
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.x = 0;
|
||||
s_filter_displayformat(b, 0, 1, &args);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int s_load_image(s_container_t *c, unsigned bank, const char *name)
|
||||
{
|
||||
SDL_Surface *src;
|
||||
s_bank_t *b;
|
||||
|
||||
src = IMG_Load(name);
|
||||
if(!src)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Failed to load sprite \"%s\"!\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
b = s_new_bank(c, bank, 1, src->clip_rect.w, src->clip_rect.h);
|
||||
if(!b)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Failed to allocate bank for \"%s\"!\n", name);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(extract_sprite(b, 0, src, &src->clip_rect) < 0)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Something went wrong while"
|
||||
" extracting sprite \"%s\".\n", name);
|
||||
return -3;
|
||||
}
|
||||
|
||||
SDL_FreeSurface(src);
|
||||
__run_plugins(b, 0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int s_load_sprite(s_container_t *c, unsigned bank, unsigned frame,
|
||||
const char *name)
|
||||
{
|
||||
SDL_Surface *src;
|
||||
SDL_Rect from;
|
||||
s_bank_t *b = s_get_bank(c, bank);
|
||||
if(!b)
|
||||
{
|
||||
log_printf(ELOG, "sprite: While loading \"%s\":"
|
||||
" Bank %d does not exist!\n", name, bank);
|
||||
return -2;
|
||||
}
|
||||
|
||||
src = IMG_Load(name);
|
||||
if(!src)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Failed to load sprite \"%s\"!\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
from = src->clip_rect;
|
||||
if( (from.w != b->w) || (from.h != b->h) )
|
||||
{
|
||||
log_printf(ELOG, "sprite: Warning: Sprite \"%s\" cropped"
|
||||
" to fit in bank %d.\n", name, bank);
|
||||
from.w = b->w;
|
||||
from.h = b->h;
|
||||
}
|
||||
|
||||
if(extract_sprite(b, frame, src, &from) < 0)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Something went wrong while"
|
||||
" extracting sprite \"%s\".\n", name);
|
||||
return -3;
|
||||
}
|
||||
|
||||
SDL_FreeSurface(src);
|
||||
__run_plugins(b, frame, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int s_load_bank(s_container_t *c, unsigned bank, unsigned w, unsigned h,
|
||||
const char *name)
|
||||
{
|
||||
SDL_Surface *src;
|
||||
s_bank_t *b;
|
||||
int x, y;
|
||||
unsigned frame = 0;
|
||||
unsigned frames;
|
||||
|
||||
DBG(log_printf(DLOG, "s_load_bank(%p, %d, %d, %d, %s)\n",
|
||||
c, bank, w, h, name);)
|
||||
|
||||
src = IMG_Load(name);
|
||||
if(!src)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Failed to load sprite palette %s!\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(w > src->w)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Source image %s not wide enough!\n", name);
|
||||
return -4;
|
||||
}
|
||||
|
||||
if(h > src->h)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Source image %s not high enough!\n", name);
|
||||
return -5;
|
||||
}
|
||||
|
||||
frames = (src->w / w) * (src->h / h);
|
||||
b = s_new_bank(c, bank, frames, w, h);
|
||||
if(!b)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Failed to allocate bank for \"%s\"!\n", name);
|
||||
return -2;
|
||||
}
|
||||
for(y = 0; y <= src->h - h; y += h)
|
||||
for(x = 0; x <= src->w - w; x += w)
|
||||
{
|
||||
SDL_Rect r;
|
||||
r.x = x;
|
||||
r.y = y;
|
||||
r.w = w;
|
||||
r.h = h;
|
||||
if(extract_sprite(b, frame, src, &r) < 0)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Something went wrong while"
|
||||
" extracting sprites.\n");
|
||||
return -3;
|
||||
}
|
||||
++frame;
|
||||
}
|
||||
SDL_FreeSurface(src);
|
||||
__run_plugins(b, 0, frames);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int s_set_hotspot(s_container_t *c, unsigned bank, int frame, int x, int y)
|
||||
{
|
||||
if(frame < 0)
|
||||
{
|
||||
frame = 0;
|
||||
while(1)
|
||||
{
|
||||
s_sprite_t *s = s_get_sprite(c, bank, frame++);
|
||||
if(!s)
|
||||
break;
|
||||
s->x = x;
|
||||
s->y = y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s_sprite_t *s = s_get_sprite(c, bank, frame);
|
||||
s->x = x;
|
||||
s->y = y;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
/*(LGPL)
|
||||
----------------------------------------------------------------------
|
||||
sprite.h - Sprite engine for use with cs.h
|
||||
----------------------------------------------------------------------
|
||||
* Copyright (C) 2001, 2003, 2007 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _SPRITE_H_
|
||||
#define _SPRITE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "glSDL.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
S_BLITMODE_AUTO = 0, /* Use source alpha if present */
|
||||
S_BLITMODE_OPAQUE, /* Alpha: blend over black during conv. */
|
||||
S_BLITMODE_COLORKEY, /* Like OPAQUE, but apply colorkey to the result */
|
||||
S_BLITMODE_ALPHA /* Apply source alpha during conv,
|
||||
* then use full surface alpha */
|
||||
} s_blitmodes_t;
|
||||
|
||||
struct s_container_t;
|
||||
|
||||
/* sprite image */
|
||||
typedef struct
|
||||
{
|
||||
int x, y; /* kern or hot-spot*/
|
||||
#if 0
|
||||
/* TODO TODO TODO TODO TODO TODO */
|
||||
struct
|
||||
{
|
||||
int x, y, w, h; /* spacing or collision rect */
|
||||
} logic;
|
||||
/* /TODO TODO TODO TODO TODO TODO */
|
||||
#endif
|
||||
SDL_Surface *surface;
|
||||
} s_sprite_t;
|
||||
|
||||
/* Bank of sprite images */
|
||||
typedef struct
|
||||
{
|
||||
#if 0
|
||||
/* TODO TODO TODO TODO TODO TODO */
|
||||
struct s_container_t *container;
|
||||
int index; /* Index of this bank */
|
||||
/* /TODO TODO TODO TODO TODO TODO */
|
||||
#endif
|
||||
unsigned w, h; /* Same size for all sprites in bank! */
|
||||
unsigned last;
|
||||
unsigned max;
|
||||
s_sprite_t **sprites;
|
||||
} s_bank_t;
|
||||
|
||||
/* Two dimensionally indexed sprite container */
|
||||
typedef struct s_container_t
|
||||
{
|
||||
unsigned max;
|
||||
s_bank_t **banks;
|
||||
} s_container_t;
|
||||
|
||||
|
||||
/*
|
||||
* Basic Container Management
|
||||
*/
|
||||
s_container_t *s_new_container(unsigned banks);
|
||||
void s_delete_container(s_container_t *c);
|
||||
|
||||
s_bank_t *s_new_bank(s_container_t *c, unsigned bank, unsigned frames,
|
||||
unsigned w, unsigned h);
|
||||
void s_delete_bank(s_container_t *c, unsigned bank);
|
||||
void s_delete_all_banks(s_container_t *c);
|
||||
|
||||
s_sprite_t *s_new_sprite(s_container_t *c, unsigned bank, unsigned frame);
|
||||
void s_delete_sprite(s_container_t *c, unsigned bank, unsigned frame);
|
||||
|
||||
/*
|
||||
* Getting data
|
||||
*/
|
||||
s_sprite_t *s_get_sprite(s_container_t *c, unsigned bank, unsigned frame);
|
||||
/* Detach sprite image from the manager. */
|
||||
void s_detach_sprite(s_container_t *c, unsigned bank, unsigned frame);
|
||||
|
||||
/*
|
||||
* File Import Tools
|
||||
* (Will run plugins as files are loaded!)
|
||||
*/
|
||||
int s_load_image(s_container_t *c, unsigned bank, const char *name);
|
||||
int s_load_bank(s_container_t *c, unsigned bank, unsigned w, unsigned h,
|
||||
const char *name);
|
||||
int s_load_sprite(s_container_t *c, unsigned bank, unsigned frame,
|
||||
const char *name);
|
||||
|
||||
/*
|
||||
* Rendering Tools
|
||||
*/
|
||||
int s_generate_bank(s_container_t *c, unsigned bank, unsigned w, unsigned h,
|
||||
const char *name);
|
||||
|
||||
/*
|
||||
* Sprite metadata
|
||||
*/
|
||||
/* Set sprite hotspot. Pass -1 for 'frame' to set hotspot for all frames. */
|
||||
int s_set_hotspot(s_container_t *c, unsigned bank, int frame, int x, int y);
|
||||
|
||||
|
||||
/*
|
||||
* Internal data manipulation API
|
||||
* (Will not automatically run plugins.)
|
||||
*/
|
||||
int s_copy_rect(s_container_t *c, unsigned bank,
|
||||
unsigned frombank, unsigned fromframe, SDL_Rect *from);
|
||||
|
||||
/*
|
||||
* Lower level interfaces
|
||||
*/
|
||||
s_bank_t *s_get_bank(s_container_t *c, unsigned bank);
|
||||
s_sprite_t *s_get_sprite_b(s_bank_t *b, unsigned frame);
|
||||
s_sprite_t *s_new_sprite_b(s_bank_t *b, unsigned frame);
|
||||
void s_delete_sprite_b(s_bank_t *b, unsigned frame);
|
||||
|
||||
|
||||
/*
|
||||
* Filter Plugin Interface
|
||||
*
|
||||
* Rules:
|
||||
* * Plugins are called to process one bank at a time,
|
||||
* after new frames have been loaded.
|
||||
*
|
||||
* * Plugins are called in the order they were
|
||||
* registered.
|
||||
*
|
||||
* * Plugins may replace the surfaces of sprites. If
|
||||
* they do so, they're responsible for disposing of
|
||||
* the old surfaces.
|
||||
*
|
||||
* * It is recommended that plugins operate only on
|
||||
* the specified range of frames in a bank.
|
||||
*
|
||||
* * The surface size of all sprites in a bank should
|
||||
* preferably match that of the bank. A chain of
|
||||
* plugins may break this rule temporarily, as long
|
||||
* as "order is restored" (ie surfaces are resized, or
|
||||
* bank size values is adjusted) before the chain ends.
|
||||
*
|
||||
* Cool plugin ideas:
|
||||
* * Rotator:
|
||||
* Takes a bank and generates N rotated versions of
|
||||
* each sprite.
|
||||
*
|
||||
* * Bumpmapper:
|
||||
* Takes a bank and applies light, shadows, highlights
|
||||
* and stuff to frames that have bumpmap channels.
|
||||
* (Q: Where do we put bumpmaps? Extend the bank to
|
||||
* twice the # of frames, using the last half for BMs?
|
||||
* Use two banks? I think we need an API change that
|
||||
* make plugins operators; X = A <op> B, where the
|
||||
* banks X, A and B are arguments.)
|
||||
*
|
||||
* * Mixer:
|
||||
* A plugin that takes two banks and performs various
|
||||
* operations between them to produce the output.
|
||||
*
|
||||
* * Colorizer:
|
||||
* Converts images to HSV and then replaces hue with
|
||||
* a fixed color.
|
||||
*
|
||||
* * Map Colorizer:
|
||||
* Like Colorizer, but uses a (wrapping) source image
|
||||
* as a map to determine the new hue for each pixel.
|
||||
*
|
||||
* * Tiled Stretch:
|
||||
* Given a list of tile interdependencies, generate
|
||||
* all tiles required for seamless rendering of the
|
||||
* map for which the interdependency list was generated.
|
||||
*/
|
||||
typedef struct s_filter_args_t
|
||||
{
|
||||
int x, y, z;
|
||||
float fx, fy, fz;
|
||||
int min, max;
|
||||
short r, g, b;
|
||||
int flags;
|
||||
unsigned bank;
|
||||
void *data;
|
||||
} s_filter_args_t;
|
||||
|
||||
typedef int (*s_filter_cb_t)(s_bank_t *b, unsigned first, unsigned frames,
|
||||
s_filter_args_t *args);
|
||||
|
||||
typedef struct s_filter_t
|
||||
{
|
||||
struct s_filter_t *next;
|
||||
s_filter_cb_t callback;
|
||||
s_filter_args_t args;
|
||||
} s_filter_t;
|
||||
|
||||
s_filter_t *s_insert_filter(s_filter_cb_t callback);
|
||||
s_filter_t *s_add_filter(s_filter_cb_t callback);
|
||||
/* callback == NULL means "remove all plugins" */
|
||||
void s_remove_filter(s_filter_t *filter);
|
||||
|
||||
/* RGBA pixel type (used internally by most filters as well) */
|
||||
typedef struct
|
||||
{
|
||||
Uint8 r;
|
||||
Uint8 g;
|
||||
Uint8 b;
|
||||
Uint8 a;
|
||||
} pix_t;
|
||||
|
||||
/*
|
||||
* UURGH!!! This should be OO like the rest...
|
||||
*/
|
||||
extern s_blitmodes_t s_blitmode;
|
||||
extern pix_t s_colorkey; /* NOTE: Alpha is ignored! */
|
||||
extern pix_t s_clampcolor;
|
||||
extern unsigned char s_alpha;
|
||||
extern int s_filter_flags; /* Global flags; applied to all plugins. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _SPRITE_H_ */
|
||||
@@ -0,0 +1,764 @@
|
||||
/*(LGPL)
|
||||
---------------------------------------------------------------------------
|
||||
toolkit.cpp - Simple "GUI" toolkit for config screens.
|
||||
---------------------------------------------------------------------------
|
||||
* Copyright (C) 2001 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "window.h"
|
||||
#include "toolkit.h"
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
ct_widget_t::
|
||||
----------------------------------------------------------*/
|
||||
|
||||
ct_widget_t::ct_widget_t()
|
||||
{
|
||||
interactive = 0;
|
||||
transparent = 1;
|
||||
highlighted = 0;
|
||||
user = NULL;
|
||||
user2 = 0;
|
||||
tag = 0;
|
||||
_color = 0;
|
||||
next = prev = NULL;
|
||||
_widget_index = -1;
|
||||
halign(ALIGN_DEFAULT);
|
||||
valign(ALIGN_DEFAULT);
|
||||
_token = 0;
|
||||
xo = yo = 0.0;
|
||||
}
|
||||
|
||||
|
||||
void ct_widget_t::halign(ct_align_t ha)
|
||||
{
|
||||
if(ALIGN_DEFAULT == ha)
|
||||
_halign = ALIGN_RIGHT;
|
||||
else
|
||||
_halign = ha;
|
||||
}
|
||||
|
||||
|
||||
void ct_widget_t::valign(ct_align_t va)
|
||||
{
|
||||
if(ALIGN_DEFAULT == va)
|
||||
_valign = ALIGN_TOP;
|
||||
else
|
||||
_valign = va;
|
||||
}
|
||||
|
||||
|
||||
void ct_widget_t::init(gfxengine_t *e)
|
||||
{
|
||||
window_t::init(e);
|
||||
_color = map_rgb(0,0,0);
|
||||
}
|
||||
|
||||
|
||||
void ct_widget_t::transparency(int t)
|
||||
{
|
||||
if(t == transparent)
|
||||
return;
|
||||
|
||||
transparent = t;
|
||||
if(!transparent)
|
||||
render();
|
||||
}
|
||||
|
||||
|
||||
void ct_widget_t::highlight(int hl)
|
||||
{
|
||||
if(hl == highlighted)
|
||||
return;
|
||||
|
||||
highlighted = hl;
|
||||
if(!transparent)
|
||||
render();
|
||||
}
|
||||
|
||||
|
||||
void ct_widget_t::color(Uint32 _cl)
|
||||
{
|
||||
if(_cl == _color)
|
||||
return;
|
||||
|
||||
_color = _cl;
|
||||
if(!transparent)
|
||||
render();
|
||||
}
|
||||
|
||||
|
||||
void ct_widget_t::render()
|
||||
{
|
||||
if(!transparent)
|
||||
{
|
||||
foreground(_color);
|
||||
fillrect(0, 0, width(), height());
|
||||
}
|
||||
if(highlighted)
|
||||
ct_engine.render_highlight(this);
|
||||
}
|
||||
|
||||
|
||||
/* Handy tool function used by some descendents. */
|
||||
void ct_widget_t::render_text_aligned(const char *buf)
|
||||
{
|
||||
int yy = 0;
|
||||
switch(_valign)
|
||||
{
|
||||
case ALIGN_DEFAULT: //dummy
|
||||
case ALIGN_NONE:
|
||||
case ALIGN_TOP:
|
||||
yy = yoffs();
|
||||
break;
|
||||
case ALIGN_BOTTOM:
|
||||
yy = height() - fontheight() - yoffs();
|
||||
break;
|
||||
case ALIGN_CENTER:
|
||||
case ALIGN_CENTER_TOKEN:
|
||||
yy = (height() - fontheight()) / 2 + yoffs();
|
||||
break;
|
||||
}
|
||||
switch(_halign)
|
||||
{
|
||||
case ALIGN_DEFAULT: //dummy
|
||||
case ALIGN_NONE:
|
||||
case ALIGN_LEFT:
|
||||
string(xoffs(), yy, buf);
|
||||
break;
|
||||
case ALIGN_RIGHT:
|
||||
center_token(width() - xoffs(), yy, buf);
|
||||
break;
|
||||
case ALIGN_CENTER:
|
||||
center_token(xoffs(), yy, buf, -1);
|
||||
break;
|
||||
case ALIGN_CENTER_TOKEN:
|
||||
center_token(xoffs(), yy, buf, _token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ct_widget_t::change(int delta)
|
||||
{
|
||||
_value += delta;
|
||||
}
|
||||
|
||||
|
||||
void ct_widget_t::value(int val)
|
||||
{
|
||||
_value = val;
|
||||
}
|
||||
|
||||
|
||||
int ct_widget_t::value()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
ct_engine_t::
|
||||
----------------------------------------------------------*/
|
||||
|
||||
void default_render_highlight(ct_widget_t *wg)
|
||||
{
|
||||
Uint32 hlc[6];
|
||||
hlc[0] = wg->map_rgb(0x440000);
|
||||
hlc[1] = wg->map_rgb(0x660000);
|
||||
hlc[2] = wg->map_rgb(0x880000);
|
||||
hlc[3] = wg->map_rgb(0x990000);
|
||||
hlc[4] = wg->map_rgb(0xaa0000);
|
||||
hlc[5] = wg->map_rgb(0xbb0000);
|
||||
wg->foreground(hlc[5]);
|
||||
wg->fillrect(0, 6, wg->width(), wg->height()-6-1);
|
||||
for(int i = 0; i < 6; ++i)
|
||||
{
|
||||
wg->foreground(hlc[i]);
|
||||
wg->fillrect(0, i, wg->width(), 1);
|
||||
wg->fillrect(0, wg->height()-1-i, wg->width(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ct_engine_t::ct_engine_t()
|
||||
{
|
||||
ct_engine.render_highlight = default_render_highlight;
|
||||
}
|
||||
|
||||
|
||||
ct_engine_t ct_engine;
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
ct_label_t::
|
||||
----------------------------------------------------------*/
|
||||
|
||||
ct_label_t::ct_label_t(const char *cap)
|
||||
{
|
||||
xo = 0.5;
|
||||
if(cap)
|
||||
caption(cap);
|
||||
else
|
||||
caption("Label");
|
||||
}
|
||||
|
||||
|
||||
void ct_label_t::halign(ct_align_t ha)
|
||||
{
|
||||
if(ALIGN_DEFAULT == ha)
|
||||
_halign = ALIGN_CENTER;
|
||||
else
|
||||
_halign = ha;
|
||||
}
|
||||
|
||||
|
||||
void ct_label_t::caption(const char *cap)
|
||||
{
|
||||
strncpy(_caption, cap, sizeof(_caption));
|
||||
_caption[sizeof(_caption)-1] = 0;
|
||||
if(!transparent)
|
||||
render();
|
||||
}
|
||||
|
||||
|
||||
void ct_label_t::render()
|
||||
{
|
||||
ct_widget_t::render();
|
||||
render_text_aligned(_caption);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
ct_item_t::
|
||||
----------------------------------------------------------*/
|
||||
|
||||
ct_item_t::ct_item_t(const char *cap, int val)
|
||||
{
|
||||
if(cap)
|
||||
caption(cap);
|
||||
else
|
||||
caption("Item");
|
||||
_value = val;
|
||||
}
|
||||
|
||||
|
||||
void ct_item_t::caption(const char *cap)
|
||||
{
|
||||
strncpy(_caption, cap, sizeof(_caption));
|
||||
_caption[sizeof(_caption)-1] = 0;
|
||||
}
|
||||
|
||||
|
||||
static ct_item_t dummy_item("<error>", -1);
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
ct_list_t::
|
||||
----------------------------------------------------------*/
|
||||
|
||||
ct_list_t::ct_list_t(const char *cap) : ct_label_t(cap)
|
||||
{
|
||||
interactive = 1;
|
||||
if(cap)
|
||||
caption(cap);
|
||||
else
|
||||
caption("List");
|
||||
items = NULL;
|
||||
_selected = NULL;
|
||||
|
||||
_token = ':';
|
||||
xo = 0.55;
|
||||
}
|
||||
|
||||
|
||||
ct_list_t::~ct_list_t()
|
||||
{
|
||||
clean();
|
||||
}
|
||||
|
||||
|
||||
void ct_list_t::halign(ct_align_t ha)
|
||||
{
|
||||
if(ALIGN_DEFAULT == ha)
|
||||
_halign = ALIGN_CENTER_TOKEN;
|
||||
else
|
||||
_halign = ha;
|
||||
}
|
||||
|
||||
|
||||
void ct_list_t::clean()
|
||||
{
|
||||
if(!items)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Break the circular list first, or we'll
|
||||
* blow up the memory manager...! :-)
|
||||
*/
|
||||
items->prev->next = NULL;
|
||||
|
||||
while(items)
|
||||
{
|
||||
ct_item_t *i = items;
|
||||
items = i->next;
|
||||
delete i;
|
||||
}
|
||||
|
||||
items = NULL;
|
||||
_selected = NULL;
|
||||
}
|
||||
|
||||
|
||||
void ct_list_t::add(ct_item_t *item)
|
||||
{
|
||||
if(items)
|
||||
{
|
||||
item->next = items;
|
||||
item->prev = items->prev;
|
||||
items->prev->next = item;
|
||||
items->prev = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->next = item->prev = item;
|
||||
items = item;
|
||||
_selected = item;
|
||||
if(!transparent)
|
||||
render();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ct_list_t::add(const char *cap, int val)
|
||||
{
|
||||
ct_item_t *it = new ct_item_t(cap, val);
|
||||
add(it);
|
||||
}
|
||||
|
||||
|
||||
void ct_list_t::select(ct_item_t *item)
|
||||
{
|
||||
_selected = item;
|
||||
#if 0
|
||||
ct_item_t *i = items;
|
||||
if(i)
|
||||
for(int n = 0; n < 10000; ++n) //Just in case...
|
||||
{
|
||||
if(i == _selected)
|
||||
{
|
||||
_value = n;
|
||||
break;
|
||||
}
|
||||
i = i->next;
|
||||
}
|
||||
#endif
|
||||
if(_selected)
|
||||
_value = _selected->value();
|
||||
if(!transparent)
|
||||
render();
|
||||
}
|
||||
|
||||
|
||||
void ct_list_t::select(int ind)
|
||||
{
|
||||
if(!items)
|
||||
return;
|
||||
|
||||
_selected = items;
|
||||
for(int i = 0; i < ind; ++i)
|
||||
_selected = _selected->next;
|
||||
select(_selected); //To update _value, render etc...
|
||||
}
|
||||
|
||||
|
||||
ct_item_t *ct_list_t::selected()
|
||||
{
|
||||
if(!items)
|
||||
return &dummy_item;
|
||||
|
||||
return _selected;
|
||||
}
|
||||
|
||||
|
||||
void ct_list_t::value(int val)
|
||||
{
|
||||
if(!items)
|
||||
return;
|
||||
|
||||
ct_item_t *best = items;
|
||||
_selected = items;
|
||||
while(_selected->value() != val)
|
||||
{
|
||||
if(labs(_selected->value()-val) < labs(best->value()-val))
|
||||
best = _selected;
|
||||
if(_selected->next == items)
|
||||
break;
|
||||
_selected = _selected->next;
|
||||
}
|
||||
if(_selected->value() != val)
|
||||
_selected = best;
|
||||
select(_selected); //To update _value, render etc...
|
||||
}
|
||||
|
||||
|
||||
int ct_list_t::value()
|
||||
{
|
||||
if(!items)
|
||||
return dummy_item.value();
|
||||
if(_selected)
|
||||
return _selected->value();
|
||||
else
|
||||
return dummy_item.value();
|
||||
}
|
||||
|
||||
|
||||
void ct_list_t::change(int delta)
|
||||
{
|
||||
if(_selected)
|
||||
{
|
||||
if(0 == delta)
|
||||
delta = 1;
|
||||
if(delta > 0)
|
||||
for(int i = 0; i < delta; ++i)
|
||||
_selected = _selected->next;
|
||||
else if(delta < 0)
|
||||
for(int i = 0; i > delta; --i)
|
||||
_selected = _selected->prev;
|
||||
select(_selected); //To update _value, render etc...
|
||||
}
|
||||
ct_widget_t::change(delta);
|
||||
}
|
||||
|
||||
|
||||
void ct_list_t::render()
|
||||
{
|
||||
char buf[128];
|
||||
const char *ic;
|
||||
if(_selected)
|
||||
ic = _selected->caption();
|
||||
else
|
||||
ic = dummy_item.caption();
|
||||
ct_widget_t::render();
|
||||
snprintf(buf, sizeof(buf), "%s: %s", caption(), ic);
|
||||
//center(0, buf);
|
||||
//center_token(width()*3/5, 0, buf, ':');
|
||||
render_text_aligned(buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
ct_spin_t::
|
||||
----------------------------------------------------------*/
|
||||
|
||||
ct_spin_t::ct_spin_t(const char *cap, int _min, int _max,
|
||||
const char *__unit) : ct_label_t(cap)
|
||||
{
|
||||
interactive = 1;
|
||||
min = _min;
|
||||
max = _max;
|
||||
_token = ':';
|
||||
xo = 0.55;
|
||||
if(__unit)
|
||||
unit(__unit);
|
||||
else
|
||||
unit("");
|
||||
}
|
||||
|
||||
|
||||
void ct_spin_t::unit(const char *txt)
|
||||
{
|
||||
strncpy(_unit, txt, sizeof(_unit));
|
||||
_unit[sizeof(_unit)-1] = 0;
|
||||
if(!transparent)
|
||||
render();
|
||||
}
|
||||
|
||||
|
||||
void ct_spin_t::value(int val)
|
||||
{
|
||||
val -= min;
|
||||
while(val < 0)
|
||||
val += max - min + 1;
|
||||
val %= max - min + 1;
|
||||
val += min;
|
||||
ct_label_t::value(val);
|
||||
}
|
||||
|
||||
|
||||
void ct_spin_t::change(int delta)
|
||||
{
|
||||
value(_value + delta);
|
||||
}
|
||||
|
||||
|
||||
void ct_spin_t::render()
|
||||
{
|
||||
char buf[128];
|
||||
ct_widget_t::render();
|
||||
snprintf(buf, sizeof(buf), "%s: %d %s", caption(), _value, unit());
|
||||
//center(0, buf);
|
||||
//center_token(width()*3/5, 0, buf, ':');
|
||||
render_text_aligned(buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
ct_button_t::
|
||||
----------------------------------------------------------*/
|
||||
|
||||
ct_button_t::ct_button_t(const char *cap) : ct_label_t(cap)
|
||||
{
|
||||
interactive = 1;
|
||||
}
|
||||
|
||||
|
||||
void ct_button_t::render()
|
||||
{
|
||||
ct_label_t::render();
|
||||
}
|
||||
|
||||
|
||||
void ct_button_t::change(int delta)
|
||||
{
|
||||
ct_label_t::change(delta);
|
||||
if(!transparent)
|
||||
render();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
ct_form_t::
|
||||
----------------------------------------------------------*/
|
||||
|
||||
ct_form_t::ct_form_t()
|
||||
{
|
||||
widgets = NULL;
|
||||
_selected = NULL;
|
||||
}
|
||||
|
||||
|
||||
ct_form_t::~ct_form_t()
|
||||
{
|
||||
if(!widgets)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Break the circular list first, or we'll
|
||||
* blow up the memory manager...! :-)
|
||||
*/
|
||||
widgets->prev->next = NULL;
|
||||
|
||||
while(widgets)
|
||||
{
|
||||
ct_widget_t *i = widgets;
|
||||
widgets = i->next;
|
||||
delete i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ct_form_t::add(ct_widget_t *widget)
|
||||
{
|
||||
if(widgets)
|
||||
{
|
||||
widget->next = widgets;
|
||||
widget->prev = widgets->prev;
|
||||
widgets->prev->next = widget;
|
||||
widgets->prev = widget;
|
||||
widget->_widget_index = widget->prev->_widget_index + 1;
|
||||
if(!_selected->interactive)
|
||||
select(widget);
|
||||
}
|
||||
else
|
||||
{
|
||||
widget->_widget_index = 0;
|
||||
widget->next = widget->prev = widget;
|
||||
widgets = widget;
|
||||
select(widget);
|
||||
}
|
||||
render_nontransparent();
|
||||
}
|
||||
|
||||
|
||||
void ct_form_t::clean()
|
||||
{
|
||||
if(!widgets)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Break the circular list first, or we'll
|
||||
* blow up the memory manager...! :-)
|
||||
*/
|
||||
widgets->prev->next = NULL;
|
||||
|
||||
while(widgets)
|
||||
{
|
||||
ct_widget_t *w = widgets;
|
||||
widgets = w->next;
|
||||
delete w;
|
||||
}
|
||||
|
||||
widgets = NULL;
|
||||
_selected = NULL;
|
||||
}
|
||||
|
||||
|
||||
void ct_form_t::select(ct_widget_t *widget)
|
||||
{
|
||||
if(_selected)
|
||||
_selected->highlight(0);
|
||||
_selected = widget;
|
||||
if(_selected)
|
||||
{
|
||||
_selected->highlight(1);
|
||||
if(!_selected->transparent)
|
||||
_selected->render();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ct_form_t::select(int ind)
|
||||
{
|
||||
if(!widgets)
|
||||
return;
|
||||
|
||||
if(!widgets)
|
||||
return;
|
||||
|
||||
ct_widget_t *sel = widgets;
|
||||
for(int i = 0; i < ind; ++i)
|
||||
sel = sel->next;
|
||||
|
||||
int lim = 10000;
|
||||
while(!sel->interactive)
|
||||
{
|
||||
if(!lim--)
|
||||
break;
|
||||
sel = sel->next;
|
||||
}
|
||||
select(sel);
|
||||
}
|
||||
|
||||
|
||||
void ct_form_t::next()
|
||||
{
|
||||
if(!widgets)
|
||||
return;
|
||||
|
||||
if(!_selected)
|
||||
{
|
||||
select(0);
|
||||
return;
|
||||
}
|
||||
|
||||
ct_widget_t *sel = _selected->next;
|
||||
|
||||
int lim = 1000;
|
||||
while(!sel->interactive)
|
||||
{
|
||||
if(!lim--)
|
||||
break;
|
||||
sel = sel->next;
|
||||
}
|
||||
select(sel);
|
||||
}
|
||||
|
||||
|
||||
void ct_form_t::prev()
|
||||
{
|
||||
if(!widgets)
|
||||
return;
|
||||
|
||||
if(!_selected)
|
||||
{
|
||||
select(0);
|
||||
return;
|
||||
}
|
||||
|
||||
ct_widget_t *sel = _selected->prev;
|
||||
|
||||
int lim = 1000;
|
||||
while(!sel->interactive)
|
||||
{
|
||||
if(!lim--)
|
||||
break;
|
||||
sel = sel->prev;
|
||||
}
|
||||
select(sel);
|
||||
}
|
||||
|
||||
|
||||
ct_widget_t *ct_form_t::selected()
|
||||
{
|
||||
return _selected;
|
||||
}
|
||||
|
||||
|
||||
int ct_form_t::selected_index()
|
||||
{
|
||||
if(_selected)
|
||||
return _selected->_widget_index;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void ct_form_t::change(int delta)
|
||||
{
|
||||
if(_selected)
|
||||
_selected->change(delta);
|
||||
}
|
||||
|
||||
|
||||
void ct_form_t::render()
|
||||
{
|
||||
ct_widget_t *w = widgets;
|
||||
while(w)
|
||||
{
|
||||
w->render();
|
||||
w = w->next;
|
||||
if(w == widgets)
|
||||
break; //Done!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ct_form_t::render_nontransparent()
|
||||
{
|
||||
ct_widget_t *w = widgets;
|
||||
while(w)
|
||||
{
|
||||
if(!w->transparent)
|
||||
w->render();
|
||||
w = w->next;
|
||||
if(w == widgets)
|
||||
break; //Done!
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*(LGPL)
|
||||
---------------------------------------------------------------------------
|
||||
toolkit.h - Simple "GUI" toolkit for config screens.
|
||||
---------------------------------------------------------------------------
|
||||
* Copyright (C) 2001, David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note: change(0) means "apply", and would be the normal
|
||||
* result of pressing enter while a widget is selected.
|
||||
*/
|
||||
|
||||
#include "window.h"
|
||||
|
||||
enum ct_align_t
|
||||
{
|
||||
ALIGN_DEFAULT = -1,
|
||||
ALIGN_NONE = 0,
|
||||
ALIGN_LEFT,
|
||||
ALIGN_TOP = ALIGN_LEFT,
|
||||
ALIGN_RIGHT,
|
||||
ALIGN_BOTTOM = ALIGN_RIGHT,
|
||||
ALIGN_CENTER,
|
||||
ALIGN_CENTER_TOKEN
|
||||
};
|
||||
|
||||
class ct_widget_t : public window_t
|
||||
{
|
||||
protected:
|
||||
friend class ct_form_t;
|
||||
int interactive;
|
||||
int transparent;
|
||||
int highlighted;
|
||||
Uint32 _color;
|
||||
int _value;
|
||||
int _widget_index;
|
||||
ct_align_t _halign;
|
||||
ct_align_t _valign;
|
||||
char _token;
|
||||
float xo, yo; //[0,1] maps to [0,width()]!
|
||||
virtual void render();
|
||||
void render_text_aligned(const char *buf);
|
||||
public:
|
||||
ct_widget_t *next, *prev; //*CIRCULAR* list!
|
||||
void *user; //user stuff
|
||||
int user2; //user stuff
|
||||
int tag; //user stuff
|
||||
ct_widget_t();
|
||||
virtual void init(gfxengine_t *e);
|
||||
void transparency(int t);
|
||||
void highlight(int hl);
|
||||
void color(Uint32 _cl);
|
||||
virtual void change(int delta);
|
||||
virtual void value(int val);
|
||||
virtual int value();
|
||||
|
||||
//Contents alignment modes.
|
||||
virtual void halign(ct_align_t ha);
|
||||
virtual void valign(ct_align_t va);
|
||||
ct_align_t halign() { return _halign; }
|
||||
ct_align_t valign() { return _valign; }
|
||||
|
||||
//Token and offsets- used by some alignment modes.
|
||||
virtual void token(char tok) { _token = tok; }
|
||||
char token() { return _token; }
|
||||
virtual void offset(float x, float y) { xo = x; yo = y; }
|
||||
int xoffs() { return (int)(xo * width()); }
|
||||
int yoffs() { return (int)(yo * height()); }
|
||||
float rxoffs() { return xo; }
|
||||
float ryoffs() { return yo; }
|
||||
};
|
||||
|
||||
|
||||
class ct_engine_t
|
||||
{
|
||||
public:
|
||||
ct_engine_t();
|
||||
void (*render_highlight)(ct_widget_t *wg);
|
||||
};
|
||||
|
||||
extern ct_engine_t ct_engine;
|
||||
|
||||
|
||||
class ct_label_t : public ct_widget_t
|
||||
{
|
||||
protected:
|
||||
char _caption[64];
|
||||
void render();
|
||||
public:
|
||||
ct_label_t(const char *cap = NULL);
|
||||
void caption(const char *cap);
|
||||
const char *caption() { return _caption; }
|
||||
virtual void halign(ct_align_t ha);
|
||||
};
|
||||
|
||||
|
||||
class ct_item_t
|
||||
{
|
||||
protected:
|
||||
char _caption[64];
|
||||
int _index;
|
||||
int _value;
|
||||
public:
|
||||
ct_item_t *next, *prev; //*CIRCULAR* list!
|
||||
ct_item_t(const char *cap = NULL, int val = 0);
|
||||
void caption(const char *cap);
|
||||
const char *caption() { return _caption; }
|
||||
void value(int val) { _value = val; }
|
||||
int value() { return _value; }
|
||||
void index(int i) { _index = i; }
|
||||
int index() { return _index; }
|
||||
};
|
||||
|
||||
class ct_list_t : public ct_label_t
|
||||
{
|
||||
protected:
|
||||
ct_item_t *items;
|
||||
ct_item_t *_selected;
|
||||
void render();
|
||||
public:
|
||||
ct_list_t(const char *cap = NULL);
|
||||
virtual ~ct_list_t();
|
||||
void add(ct_item_t *item);
|
||||
void add(const char *cap, int val);
|
||||
void clean();
|
||||
void select(ct_item_t *item);
|
||||
void select(int ind);
|
||||
ct_item_t *selected();
|
||||
void value(int val);
|
||||
int value();
|
||||
void change(int delta);
|
||||
virtual void halign(ct_align_t ha);
|
||||
};
|
||||
|
||||
|
||||
class ct_spin_t : public ct_label_t
|
||||
{
|
||||
protected:
|
||||
int min;
|
||||
int max;
|
||||
char _unit[32];
|
||||
void render();
|
||||
public:
|
||||
ct_spin_t(const char *cap = NULL, int _min = 0, int _max = 99999,
|
||||
const char *__unit = NULL);
|
||||
void value(int val);
|
||||
void change(int delta);
|
||||
void unit(const char *txt);
|
||||
const char *unit() { return _unit; }
|
||||
};
|
||||
|
||||
|
||||
class ct_button_t : public ct_label_t
|
||||
{
|
||||
protected:
|
||||
void render();
|
||||
public:
|
||||
ct_button_t(const char *cap = NULL);
|
||||
void change(int delta);
|
||||
};
|
||||
|
||||
|
||||
class ct_form_t : public window_t
|
||||
{
|
||||
protected:
|
||||
ct_widget_t *widgets;
|
||||
ct_widget_t *_selected;
|
||||
public:
|
||||
ct_form_t();
|
||||
virtual ~ct_form_t();
|
||||
void add(ct_widget_t *w);
|
||||
void clean();
|
||||
virtual void select(ct_widget_t *w);
|
||||
virtual void select(int ind);
|
||||
virtual void next();
|
||||
virtual void prev();
|
||||
ct_widget_t *selected();
|
||||
int selected_index();
|
||||
void render();
|
||||
void render_nontransparent();
|
||||
virtual void change(int delta);
|
||||
};
|
||||
@@ -0,0 +1,193 @@
|
||||
/*(LGPL)
|
||||
---------------------------------------------------------------------------
|
||||
vidmodes.c - Video Mode Manager for Kobo Deluxe
|
||||
---------------------------------------------------------------------------
|
||||
* Copyright (C) 2007 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "vidmodes.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct VMM_IMode
|
||||
{
|
||||
int flags, width, height, id;
|
||||
const char *name;
|
||||
} VMM_IMode;
|
||||
|
||||
static VMM_IMode modetab[] =
|
||||
{
|
||||
// 4:3 modes
|
||||
{VMM_4_3 | VMM_PC, 320, 200, 0x04300, "CGA"},
|
||||
{VMM_4_3 | VMM_PC, 320, 240, 0x04301, "QVGA"},
|
||||
{VMM_4_3, 320, 256, 0x04302, "Amiga LoRes"},
|
||||
{VMM_4_3 | VMM_LORES, 400, 300, 0x04310, NULL},
|
||||
{VMM_4_3 | VMM_LORES, 512, 384, 0x04320, NULL},
|
||||
{VMM_4_3 | VMM_PC, 640, 480, 0x04330, "VGA"},
|
||||
{VMM_4_3, 640, 512, 0x04331, "Amiga HiRes"},
|
||||
{VMM_4_3 | VMM_TV, 768, 576, 0x04340, "PAL"},
|
||||
{VMM_4_3 | VMM_PC, 800, 600, 0x04350, NULL},
|
||||
{VMM_4_3 | VMM_LORES, 960, 720, 0x04360, NULL},
|
||||
{VMM_4_3 | VMM_PC, 1024, 768, 0x04370, "XGA"},
|
||||
{VMM_4_3 | VMM_PC, 1152, 864, 0x04380, NULL},
|
||||
{VMM_4_3 | VMM_PC, 1280, 960, 0x04390, NULL},
|
||||
{VMM_4_3 | VMM_PC, 1400, 1050, 0x043a0, "SXGA+"},
|
||||
{VMM_4_3 | VMM_PC, 1600, 1200, 0x043b0, "UXGA"},
|
||||
{VMM_4_3 | VMM_PC, 1920, 1440, 0x043c0, NULL},
|
||||
{VMM_4_3 | VMM_PC, 2048, 1536, 0x043d0, "QXGA"},
|
||||
|
||||
// 3:2 modes
|
||||
{VMM_3_2 | VMM_LORES, 360, 240, 0x03200, NULL},
|
||||
{VMM_3_2 | VMM_LORES, 720, 480, 0x03240, "NTSC"},
|
||||
{VMM_3_2, 1152, 768, 0x03280, NULL},
|
||||
{VMM_3_2, 1280, 854, 0x03290, NULL},
|
||||
{VMM_3_2, 1440, 960, 0x032a0, NULL},
|
||||
|
||||
// 5:4 modes
|
||||
{VMM_5_4 | VMM_LORES, 320, 256, 0x05400, "Amiga LoRes"},
|
||||
{VMM_5_4 | VMM_LORES, 640, 512, 0x05430, "Amiga HiRes"},
|
||||
{VMM_5_4 | VMM_PC, 1280, 1024, 0x05490, "SXGA"},
|
||||
{VMM_5_4, 2560, 2048, 0x054e0, "QSXGA"},
|
||||
|
||||
// 16:10 modes
|
||||
{VMM_16_10 | VMM_LORES, 320, 200, 0x10a00, NULL},
|
||||
{VMM_16_10 | VMM_PC, 640, 400, 0x10a30, NULL},
|
||||
{VMM_16_10 | VMM_LORES, 840, 525, 0x10a50, NULL},
|
||||
{VMM_16_10 | VMM_PC, 1280, 800, 0x10a90, NULL},
|
||||
{VMM_16_10 | VMM_PC, 1680, 1050, 0x10ab0, "WSXGA+"},
|
||||
{VMM_16_10 | VMM_PC, 1920, 1200, 0x10ac0, "WUXGA"},
|
||||
{VMM_16_10 | VMM_PC, 2560, 1600, 0x10ae0, "WQXGA"},
|
||||
|
||||
// 16:9 modes
|
||||
{VMM_16_9 | VMM_LORES, 480, 270, 0x10910, NULL},
|
||||
{VMM_16_9 | VMM_LORES, 678, 384, 0x10930, NULL},
|
||||
{VMM_16_9 | VMM_TV, 854, 480, 0x10950, "WVGA"},
|
||||
{VMM_16_9 | VMM_LORES, 960, 540, 0x10960, NULL},
|
||||
{VMM_16_9, 1280, 720, 0x10990, "HD 720"},
|
||||
{VMM_16_9 | VMM_TV, 1356, 768, 0x109a0, "Flat TV"},
|
||||
{VMM_16_9 | VMM_TV, 1920, 1080, 0x109c0, "HD 1080"},
|
||||
{VMM_16_9, 2560, 1440, 0x109e0, NULL},
|
||||
|
||||
// End of table
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Gathering and constructing modes
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
static VMM_Mode *vmm_modes = NULL;
|
||||
|
||||
int vmm_Init(int show, int hide)
|
||||
{
|
||||
int i;
|
||||
VMM_Mode *lastm = NULL;
|
||||
vmm_Close();
|
||||
|
||||
/*
|
||||
TODO: Include detected SDL modes, if requested.
|
||||
*/
|
||||
|
||||
for(i = 0; modetab[i].width; ++i)
|
||||
{
|
||||
VMM_Mode *m;
|
||||
double nominal_aspect;
|
||||
VMM_IMode *im = &modetab[i];
|
||||
if(im->flags & hide)
|
||||
continue;
|
||||
if(!(im->flags & show))
|
||||
continue;
|
||||
m = calloc(1, sizeof(VMM_Mode));
|
||||
if(!m)
|
||||
return -1; /* Out of memory! */
|
||||
m->id = im->id;
|
||||
m->width = im->width;
|
||||
m->height = im->height;
|
||||
m->flags = im->flags;
|
||||
if(im->flags & VMM_3_2)
|
||||
nominal_aspect = 3.0f / 2.0f;
|
||||
else if(im->flags & VMM_5_4)
|
||||
nominal_aspect = 5.0f / 4.0f;
|
||||
else if(im->flags & VMM_16_10)
|
||||
nominal_aspect = 16.0f / 10.0f;
|
||||
else if(im->flags & VMM_16_9)
|
||||
nominal_aspect = 16.0f / 9.0f;
|
||||
else
|
||||
nominal_aspect = 4.0f / 3.0f;
|
||||
if(im->width)
|
||||
m->aspect = nominal_aspect / im->width * im->height;
|
||||
else
|
||||
m->aspect = 1.0f;
|
||||
if(im->name)
|
||||
m->name = strdup(im->name);
|
||||
if(lastm)
|
||||
lastm->next = m;
|
||||
else
|
||||
vmm_modes = m;
|
||||
lastm = m;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void vmm_Close(void)
|
||||
{
|
||||
VMM_Mode *m = vmm_First();
|
||||
while(m)
|
||||
{
|
||||
VMM_Mode *dm = m;
|
||||
m = vmm_Next(m);
|
||||
free(dm->name);
|
||||
free(dm);
|
||||
}
|
||||
vmm_modes = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Scanning
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
VMM_Mode *vmm_First(void)
|
||||
{
|
||||
return vmm_modes;
|
||||
}
|
||||
|
||||
|
||||
VMM_Mode *vmm_Next(VMM_Mode *current)
|
||||
{
|
||||
return current->next;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Indexing
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
VMM_Mode *vmm_FindMode(int id)
|
||||
{
|
||||
VMM_Mode *m = vmm_First();
|
||||
while(m)
|
||||
{
|
||||
if(m->id == id)
|
||||
return m;
|
||||
m = vmm_Next(m);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*(LGPL)
|
||||
---------------------------------------------------------------------------
|
||||
vidmodes.h - Video Mode Manager for Kobo Deluxe
|
||||
---------------------------------------------------------------------------
|
||||
* Copyright (C) 2007 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef KOBO_VIDMODES_H
|
||||
#define KOBO_VIDMODES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Data Types and Structures
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VMM_ALL = 0xffffffff,
|
||||
VMM_DETECT = 0x00000001, /* Available modes as detected by SDL */
|
||||
VMM_4_3 = 0x00000010, /* 4:3 modes */
|
||||
VMM_3_2 = 0x00000020, /* 3:2 modes */
|
||||
VMM_5_4 = 0x00000040, /* 5:4 modes */
|
||||
VMM_16_10 = 0x00000080, /* 16:10 modes */
|
||||
VMM_16_9 = 0x00000100, /* 16:9 modes */
|
||||
VMM_PC = 0x00010000, /* Standard PC/Mac modes */
|
||||
VMM_WPC = 0x00020000, /* Widescreen PC/Mac modes */
|
||||
VMM_TV = 0x00040000, /* Standard TV modes */
|
||||
VMM_WTV = 0x00080000, /* Widescreen TV modes */
|
||||
VMM_LORES = 0x10000000 /* Special low resolution modes */
|
||||
} VMM_Flags;
|
||||
|
||||
|
||||
typedef struct VMM_Mode VMM_Mode;
|
||||
struct VMM_Mode
|
||||
{
|
||||
VMM_Mode *next; /* Next mode in list */
|
||||
char *name; /* Name, if any */
|
||||
int id; /* Somewhat constant mode ID */
|
||||
int width; /* Display width in pixels */
|
||||
int height; /* Display height in pixels */
|
||||
int flags; /* (WMM_Flags) */
|
||||
float aspect; /* Pixel aspect ratio */
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Gathering and constructing modes
|
||||
-------------------------------------------------------------------------*/
|
||||
int vmm_Init(int show, int hide);
|
||||
void vmm_Close(void);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Scanning
|
||||
-------------------------------------------------------------------------*/
|
||||
VMM_Mode *vmm_First(void);
|
||||
VMM_Mode *vmm_Next(VMM_Mode *current);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Indexing
|
||||
-------------------------------------------------------------------------*/
|
||||
VMM_Mode *vmm_FindMode(int id);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Searching
|
||||
-------------------------------------------------------------------------*/
|
||||
/* TODO: VMM_Mode *vmm_Find(int width, int height, int aspect); */
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* KOBO_VIDMODES_H */
|
||||
@@ -0,0 +1,654 @@
|
||||
/*(LGPL)
|
||||
---------------------------------------------------------------------------
|
||||
window.cpp - Generic Rendering Window
|
||||
---------------------------------------------------------------------------
|
||||
* Copyright (C) 2001-2003, 2006, 2007 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
#include "window.h"
|
||||
#include "gfxengine.h"
|
||||
#include "sofont.h"
|
||||
|
||||
#define SELECT if(selected != this) _select();
|
||||
|
||||
window_t *window_t::selected = NULL;
|
||||
|
||||
window_t::window_t()
|
||||
{
|
||||
engine = NULL;
|
||||
surface = NULL;
|
||||
next = NULL;
|
||||
prev = NULL;
|
||||
phys_rect.x = phys_rect.y = 0;
|
||||
phys_rect.w = 320;
|
||||
phys_rect.h = 240;
|
||||
fgcolor = bgcolor = 0;
|
||||
selected = 0;
|
||||
xs = ys = 256;
|
||||
bg_bank = -1;
|
||||
bg_frame = -1;
|
||||
_visible = 1;
|
||||
_offscreen = 0;
|
||||
}
|
||||
|
||||
|
||||
window_t::~window_t()
|
||||
{
|
||||
if(_offscreen && surface)
|
||||
SDL_FreeSurface(surface);
|
||||
if(selected == this)
|
||||
selected = NULL;
|
||||
unlink();
|
||||
}
|
||||
|
||||
|
||||
void window_t::init(gfxengine_t *e)
|
||||
{
|
||||
link(e);
|
||||
xs = engine->xs;
|
||||
ys = engine->ys;
|
||||
if(_offscreen && surface)
|
||||
{
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
_offscreen = 0;
|
||||
surface = engine->surface();
|
||||
}
|
||||
|
||||
|
||||
void window_t::visible(int vis)
|
||||
{
|
||||
if(_offscreen)
|
||||
return; // Cannot be visible!
|
||||
if(_visible == vis)
|
||||
return;
|
||||
_visible = vis;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
void window_t::link(gfxengine_t *e)
|
||||
{
|
||||
unlink();
|
||||
engine = e;
|
||||
next = NULL;
|
||||
prev = engine->windows;
|
||||
if(prev)
|
||||
{
|
||||
while(prev->next)
|
||||
prev = prev->next;
|
||||
prev->next = this;
|
||||
}
|
||||
else
|
||||
engine->windows = this;
|
||||
}
|
||||
|
||||
|
||||
void window_t::unlink(void)
|
||||
{
|
||||
if(engine)
|
||||
{
|
||||
if(engine->windows == this)
|
||||
engine->windows = next;
|
||||
if(engine->surface() == surface)
|
||||
surface = NULL;
|
||||
}
|
||||
if(next)
|
||||
next->prev = prev;
|
||||
if(prev)
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
|
||||
void window_t::place(int left, int top, int sizex, int sizey)
|
||||
{
|
||||
int x2 = ((left + sizex) * xs + 128) >> 8;
|
||||
int y2 = ((top + sizey) * ys + 128) >> 8;
|
||||
phys_rect.x = (left * xs + 128) >> 8;
|
||||
phys_rect.y = (top * ys + 128) >> 8;
|
||||
phys_rect.w = x2 - phys_rect.x;
|
||||
phys_rect.h = y2 - phys_rect.y;
|
||||
}
|
||||
|
||||
|
||||
int window_t::offscreen()
|
||||
{
|
||||
if(!engine)
|
||||
return -1;
|
||||
if(!engine->surface())
|
||||
return -1;
|
||||
if(_offscreen)
|
||||
return 0; // Already offscreen!
|
||||
visible(0);
|
||||
_offscreen = 1;
|
||||
SDL_Surface *s = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
phys_rect.w, phys_rect.h,
|
||||
32, 0xff000000, 0x00ff0000,
|
||||
0x0000ff00, 0x000000ff);
|
||||
if(!s)
|
||||
return -1;
|
||||
surface = SDL_DisplayFormat(s);
|
||||
SDL_FreeSurface(s);
|
||||
if(!surface)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void window_t::select()
|
||||
{
|
||||
if(engine)
|
||||
_select();
|
||||
}
|
||||
|
||||
|
||||
void window_t::_select()
|
||||
{
|
||||
SDL_Rect r = phys_rect;
|
||||
selected = this;
|
||||
if(surface)
|
||||
SDL_SetClipRect(surface, &r);
|
||||
}
|
||||
|
||||
|
||||
void window_t::invalidate(SDL_Rect *r)
|
||||
{
|
||||
if(!engine)
|
||||
return;
|
||||
if(!engine->surface())
|
||||
return;
|
||||
|
||||
SELECT
|
||||
|
||||
if(_offscreen)
|
||||
{
|
||||
if(!r)
|
||||
{
|
||||
SDL_Rect rr;
|
||||
rr.x = 0;
|
||||
rr.y = 0;
|
||||
rr.w = phys_rect.w;
|
||||
rr.h = phys_rect.h;
|
||||
phys_refresh(&rr);
|
||||
glSDL_Invalidate(surface, &rr);
|
||||
}
|
||||
else
|
||||
{
|
||||
phys_refresh(r);
|
||||
glSDL_Invalidate(surface, r);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(!r)
|
||||
engine->invalidate(&phys_rect, this);
|
||||
else
|
||||
{
|
||||
/* Translate to screen coordinates */
|
||||
SDL_Rect dr = *r;
|
||||
dr.x = (dr.x * xs + 128) >> 8;
|
||||
dr.y = (dr.y * ys + 128) >> 8;
|
||||
dr.w = (((dr.w + dr.x) * xs + 128) >> 8) - dr.x;
|
||||
dr.h = (((dr.h + dr.y) * ys + 128) >> 8) - dr.y;
|
||||
dr.x += phys_rect.x;
|
||||
dr.y += phys_rect.y;
|
||||
|
||||
/* Clip to window (stolen from SDL_surface.c) */
|
||||
int Amin, Amax, Bmin, Bmax;
|
||||
|
||||
/* Horizontal intersection */
|
||||
Amin = dr.x;
|
||||
Amax = Amin + dr.w;
|
||||
Bmin = phys_rect.x;
|
||||
Bmax = Bmin + phys_rect.w;
|
||||
if(Bmin > Amin)
|
||||
Amin = Bmin;
|
||||
dr.x = Amin;
|
||||
if(Bmax < Amax)
|
||||
Amax = Bmax;
|
||||
dr.w = Amax - Amin > 0 ? Amax - Amin : 0;
|
||||
|
||||
/* Vertical intersection */
|
||||
Amin = dr.y;
|
||||
Amax = Amin + dr.h;
|
||||
Bmin = phys_rect.y;
|
||||
Bmax = Bmin + phys_rect.h;
|
||||
if(Bmin > Amin)
|
||||
Amin = Bmin;
|
||||
dr.y = Amin;
|
||||
if(Bmax < Amax)
|
||||
Amax = Bmax;
|
||||
dr.h = Amax - Amin > 0 ? Amax - Amin : 0;
|
||||
|
||||
if(dr.w && dr.h)
|
||||
engine->invalidate(&dr, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Rendering API
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
Uint32 window_t::map_rgb(Uint8 r, Uint8 g, Uint8 b)
|
||||
{
|
||||
if(!engine)
|
||||
return 0;
|
||||
|
||||
if(surface)
|
||||
return SDL_MapRGB(surface->format, r, g, b);
|
||||
else
|
||||
return 0xffffff;
|
||||
}
|
||||
|
||||
Uint32 window_t::map_rgb(Uint32 rgb)
|
||||
{
|
||||
if(!engine)
|
||||
return 0;
|
||||
|
||||
Uint8 r = (rgb >> 16) & 0xff;
|
||||
Uint8 g = (rgb >> 8) & 0xff;
|
||||
Uint8 b = rgb & 0xff;
|
||||
|
||||
if(surface)
|
||||
return SDL_MapRGB(surface->format, r, g, b);
|
||||
else
|
||||
return 0xffffff;
|
||||
}
|
||||
|
||||
void window_t::bgimage(int bank, int frame)
|
||||
{
|
||||
bg_bank = bank;
|
||||
bg_frame = frame;
|
||||
}
|
||||
|
||||
|
||||
void window_t::colorkey(Uint32 color)
|
||||
{
|
||||
if(!engine)
|
||||
return;
|
||||
if(!engine->surface())
|
||||
return;
|
||||
if(!_offscreen)
|
||||
return;
|
||||
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, color);
|
||||
}
|
||||
|
||||
void window_t::colorkey()
|
||||
{
|
||||
if(!engine)
|
||||
return;
|
||||
if(!engine->surface())
|
||||
return;
|
||||
if(!_offscreen)
|
||||
return;
|
||||
SDL_SetColorKey(surface, 0, 0);
|
||||
}
|
||||
|
||||
void window_t::alpha(float a)
|
||||
{
|
||||
if(!engine)
|
||||
return;
|
||||
if(!engine->surface())
|
||||
return;
|
||||
if(!_offscreen)
|
||||
return;
|
||||
SDL_SetAlpha(surface, SDL_SRCALPHA, (int)(a * 255.0));
|
||||
}
|
||||
|
||||
|
||||
void window_t::font(int fnt)
|
||||
{
|
||||
_font = fnt;
|
||||
}
|
||||
|
||||
|
||||
void window_t::string(int _x, int _y, const char *txt)
|
||||
{
|
||||
string_fxp(PIXEL2CS(_x), PIXEL2CS(_y), txt);
|
||||
}
|
||||
|
||||
|
||||
void window_t::center(int _y, const char *txt)
|
||||
{
|
||||
center_fxp(PIXEL2CS(_y), txt);
|
||||
}
|
||||
|
||||
|
||||
void window_t::center_token(int _x, int _y, const char *txt, char token)
|
||||
{
|
||||
center_token_fxp(PIXEL2CS(_x), PIXEL2CS(_y), txt, token);
|
||||
}
|
||||
|
||||
|
||||
void window_t::string_fxp(int _x, int _y, const char *txt)
|
||||
{
|
||||
if(!engine)
|
||||
return;
|
||||
|
||||
_x = CS2PIXEL((_x * xs + 128) >> 8);
|
||||
_y = CS2PIXEL((_y * ys + 128) >> 8);
|
||||
SoFont *f = engine->get_font(_font);
|
||||
if(!f)
|
||||
return;
|
||||
SELECT
|
||||
_x += phys_rect.x;
|
||||
_y += phys_rect.y;
|
||||
if(surface)
|
||||
f->PutString(surface, _x, _y, txt);
|
||||
}
|
||||
|
||||
|
||||
void window_t::center_fxp(int _y, const char *txt)
|
||||
{
|
||||
_y = CS2PIXEL((_y * ys + 128) >> 8);
|
||||
|
||||
if(!engine)
|
||||
return;
|
||||
|
||||
SoFont *f = engine->get_font(_font);
|
||||
if(!f)
|
||||
return;
|
||||
SELECT
|
||||
int _x = (phys_rect.w - f->TextWidth(txt) + 1) / 2;
|
||||
_x += phys_rect.x;
|
||||
_y += phys_rect.y;
|
||||
if(surface)
|
||||
f->PutString(surface, _x, _y, txt);
|
||||
}
|
||||
|
||||
|
||||
void window_t::center_token_fxp(int _x, int _y, const char *txt, char token)
|
||||
{
|
||||
_x = CS2PIXEL((_x * xs + 128) >> 8);
|
||||
_y = CS2PIXEL((_y * ys + 128) >> 8);
|
||||
|
||||
if(!engine)
|
||||
return;
|
||||
|
||||
SoFont *f = engine->get_font(_font);
|
||||
if(!f)
|
||||
return;
|
||||
SELECT
|
||||
int _cx;
|
||||
if(-1 == token)
|
||||
_cx = _x - f->TextWidth(txt)/2;
|
||||
else
|
||||
{
|
||||
int tokpos;
|
||||
/*
|
||||
* My docs won't say if strchr(???, 0) is legal
|
||||
* or even defined, so I'm not taking any chances...
|
||||
*/
|
||||
if(token)
|
||||
{
|
||||
char *tok = strchr(txt, token);
|
||||
if(tok)
|
||||
tokpos = tok-txt;
|
||||
else
|
||||
tokpos = 255;
|
||||
}
|
||||
else
|
||||
tokpos = 255;
|
||||
_cx = _x - f->TextWidth(txt, 0, tokpos);
|
||||
}
|
||||
_cx += phys_rect.x;
|
||||
_y += phys_rect.y;
|
||||
if(surface)
|
||||
f->PutString(surface, _cx, _y, txt);
|
||||
}
|
||||
|
||||
|
||||
int window_t::textwidth_fxp(const char *txt, int min, int max)
|
||||
{
|
||||
if(!engine)
|
||||
return strlen(txt);
|
||||
|
||||
SoFont *f = engine->get_font(_font);
|
||||
if(!f)
|
||||
return strlen(txt);
|
||||
|
||||
return (f->TextWidth(txt, min, max) << 16) / xs;
|
||||
}
|
||||
|
||||
|
||||
int window_t::textwidth(const char *txt, int min, int max)
|
||||
{
|
||||
if(!engine)
|
||||
return strlen(txt);
|
||||
|
||||
SoFont *f = engine->get_font(_font);
|
||||
if(!f)
|
||||
return strlen(txt);
|
||||
|
||||
return (f->TextWidth(txt, min, max) << 8) / xs;
|
||||
}
|
||||
|
||||
|
||||
int window_t::fontheight()
|
||||
{
|
||||
if(!engine)
|
||||
return 1;
|
||||
|
||||
SoFont *f = engine->get_font(_font);
|
||||
if(!f)
|
||||
return 1;
|
||||
|
||||
return (f->FontHeight() * 256) / ys;
|
||||
}
|
||||
|
||||
|
||||
void window_t::clear(SDL_Rect *r)
|
||||
{
|
||||
SDL_Rect sr, dr;
|
||||
if(!engine)
|
||||
return;
|
||||
if(!surface)
|
||||
return;
|
||||
SELECT
|
||||
if(!r)
|
||||
{
|
||||
sr = phys_rect;
|
||||
sr.x = 0;
|
||||
sr.y = 0;
|
||||
dr = phys_rect;
|
||||
}
|
||||
else
|
||||
{
|
||||
sr.x = ((int)r->x * xs + 128) >> 8;
|
||||
sr.y = ((int)r->y * ys + 128) >> 8;
|
||||
sr.w = (((int)(r->x + r->w) * xs + 128) >> 8) - sr.x;
|
||||
sr.h = (((int)(r->y + r->h) * ys + 128) >> 8) - sr.y;
|
||||
dr = sr;
|
||||
dr.x += phys_rect.x;
|
||||
dr.y += phys_rect.y;
|
||||
}
|
||||
if((-1 == bg_bank) && (-1 == bg_frame))
|
||||
SDL_FillRect(surface, &dr, bgcolor);
|
||||
else
|
||||
{
|
||||
s_sprite_t *s = engine->get_sprite(bg_bank, bg_frame);
|
||||
if(!s || !s->surface)
|
||||
{
|
||||
SDL_FillRect(surface, &dr, bgcolor);
|
||||
return;
|
||||
}
|
||||
SDL_BlitSurface(s->surface, &sr, surface, &dr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void window_t::point(int _x, int _y)
|
||||
{
|
||||
int x2 = ((_x + 1) * xs + 128) >> 8;
|
||||
int y2 = ((_y + 1) * ys + 128) >> 8;
|
||||
_x = (_x * xs + 128) >> 8;
|
||||
_y = (_y * ys + 128) >> 8;
|
||||
|
||||
if(!engine)
|
||||
return;
|
||||
SELECT
|
||||
/* Quick hack; slow */
|
||||
SDL_Rect r;
|
||||
r.x = phys_rect.x + _x;
|
||||
r.y = phys_rect.y + _y;
|
||||
r.w = x2 - _x;
|
||||
r.h = y2 - _y;
|
||||
if(surface)
|
||||
SDL_FillRect(surface, &r, fgcolor);
|
||||
}
|
||||
|
||||
|
||||
void window_t::fillrect(int _x, int _y, int w, int h)
|
||||
{
|
||||
int x2 = ((_x + w) * xs + 128) >> 8;
|
||||
int y2 = ((_y + h) * ys + 128) >> 8;
|
||||
_x = (_x * xs + 128) >> 8;
|
||||
_y = (_y * ys + 128) >> 8;
|
||||
|
||||
if(!engine)
|
||||
return;
|
||||
SELECT
|
||||
SDL_Rect r;
|
||||
r.x = phys_rect.x + _x;
|
||||
r.y = phys_rect.y + _y;
|
||||
r.w = x2 - _x;
|
||||
r.h = y2 - _y;
|
||||
if(surface)
|
||||
SDL_FillRect(surface, &r, fgcolor);
|
||||
}
|
||||
|
||||
|
||||
void window_t::rectangle(int _x, int _y, int w, int h)
|
||||
{
|
||||
fillrect(_x, _y, w, 1);
|
||||
fillrect(_x, _y + h - 1, w, 1);
|
||||
fillrect(_x, _y + 1, 1, h - 2);
|
||||
fillrect(_x + w - 1, _y + 1, 1, h - 2);
|
||||
}
|
||||
|
||||
|
||||
void window_t::fillrect_fxp(int _x, int _y, int w, int h)
|
||||
{
|
||||
int xx = CS2PIXEL((_x * xs + 128) >> 8);
|
||||
int yy = CS2PIXEL((_y * ys + 128) >> 8);
|
||||
w = CS2PIXEL(((w + _x) * xs + 128) >> 8) - xx;
|
||||
h = CS2PIXEL(((h + _y) * ys + 128) >> 8) - yy;
|
||||
|
||||
if(!engine)
|
||||
return;
|
||||
SELECT
|
||||
SDL_Rect r;
|
||||
r.x = phys_rect.x + xx;
|
||||
r.y = phys_rect.y + yy;
|
||||
r.w = w;
|
||||
r.h = h;
|
||||
if(surface)
|
||||
SDL_FillRect(surface, &r, fgcolor);
|
||||
}
|
||||
|
||||
|
||||
void window_t::sprite(int _x, int _y, int bank, int frame, int inval)
|
||||
{
|
||||
sprite_fxp(PIXEL2CS(_x), PIXEL2CS(_y), bank, frame, inval);
|
||||
}
|
||||
|
||||
|
||||
void window_t::sprite_fxp(int _x, int _y, int bank, int frame, int inval)
|
||||
{
|
||||
if(!engine)
|
||||
return;
|
||||
s_sprite_t *s = engine->get_sprite(bank, frame);
|
||||
if(!s || !s->surface)
|
||||
return;
|
||||
_x = CS2PIXEL(((_x - (s->x << 8)) * xs + 128) >> 8);
|
||||
_y = CS2PIXEL(((_y - (s->y << 8)) * ys + 128) >> 8);
|
||||
SDL_Rect dest_rect;
|
||||
|
||||
SELECT
|
||||
dest_rect.x = phys_rect.x + _x;
|
||||
dest_rect.y = phys_rect.y + _y;
|
||||
if(surface)
|
||||
SDL_BlitSurface(s->surface, NULL, surface, &dest_rect);
|
||||
|
||||
if(inval && !engine->autoinvalidate())
|
||||
{
|
||||
dest_rect.w = s->surface->w;
|
||||
dest_rect.h = s->surface->h;
|
||||
engine->invalidate(&dest_rect, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void window_t::blit(int dx, int dy,
|
||||
int sx, int sy, int sw, int sh, window_t *src)
|
||||
{
|
||||
if(!engine)
|
||||
return;
|
||||
if(!src)
|
||||
return;
|
||||
if(!surface)
|
||||
return;
|
||||
if(!src->surface)
|
||||
return;
|
||||
SELECT
|
||||
|
||||
SDL_Rect src_rect;
|
||||
int sx2 = ((sx + sw) * xs + 128) >> 8;
|
||||
int sy2 = ((sy + sh) * ys + 128) >> 8;
|
||||
src_rect.x = (sx * xs + 128) >> 8;
|
||||
src_rect.y = (sy * ys + 128) >> 8;
|
||||
src_rect.w = sx2 - src_rect.x;
|
||||
src_rect.h = sy2 - src_rect.y;
|
||||
|
||||
SDL_Rect dest_rect;
|
||||
dest_rect.x = phys_rect.x + ((dx * xs + 128) >> 8);
|
||||
dest_rect.y = phys_rect.y + ((dy * ys + 128) >> 8);
|
||||
|
||||
SDL_BlitSurface(src->surface, &src_rect, surface, &dest_rect);
|
||||
}
|
||||
|
||||
|
||||
void window_t::blit(int dx, int dy, window_t *src)
|
||||
{
|
||||
if(!engine)
|
||||
return;
|
||||
if(!src)
|
||||
return;
|
||||
if(!surface)
|
||||
return;
|
||||
if(!src->surface)
|
||||
return;
|
||||
|
||||
SELECT
|
||||
dx = (dx * xs + 128) >> 8;
|
||||
dy = (dy * ys + 128) >> 8;
|
||||
|
||||
SDL_Rect src_rect;
|
||||
src_rect.x = 0;
|
||||
src_rect.y = 0;
|
||||
src_rect.w = src->surface->w;
|
||||
src_rect.h = src->surface->h;
|
||||
|
||||
SDL_Rect dest_rect;
|
||||
dest_rect.x = phys_rect.x + dx;
|
||||
dest_rect.y = phys_rect.y + dy;
|
||||
|
||||
SDL_BlitSurface(src->surface, &src_rect, surface, &dest_rect);
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
/*(LGPL)
|
||||
---------------------------------------------------------------------------
|
||||
window.h - Generic Rendering Window
|
||||
---------------------------------------------------------------------------
|
||||
* Copyright (C) 2001-2003, 2007 David Olofson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Programmer's Documentation:
|
||||
* The window_t class represents a simple window of the
|
||||
* screen surface. It provides some high level rendering
|
||||
* functions that operate inside the window's bounding
|
||||
* rectangle. All operations are clipped. However,
|
||||
* window occlusion is *not* handled, so you can't use
|
||||
* this class for "real" windows.
|
||||
*
|
||||
* virtual void init(gfxengine_t *e);
|
||||
* Call this to connect a window_t instance to
|
||||
* the gfxengine_t instance that manages your
|
||||
* screen. You *must* call this for pretty much
|
||||
* any other calls to work.
|
||||
*
|
||||
* void place(int left, int top, int sizex, int sizey);
|
||||
* Position the window on the screen.
|
||||
*
|
||||
* int offscreen();
|
||||
* Make this an off-screen window, with a
|
||||
* surface of it's own for rendering. An off-
|
||||
* screen window will never be directly visible,
|
||||
* but can be used as a source window for blit().
|
||||
* May return -1 if there is an error.
|
||||
*
|
||||
* void select();
|
||||
* Makes this window active, and sets up SDL's
|
||||
* clipping appropriately. You should not use
|
||||
* this call normally, but it's provided to
|
||||
* allow this engine to interface with other
|
||||
* SDL code.
|
||||
*
|
||||
* void invalidate(SDL_Rect *r = NULL);
|
||||
* Invalidate the specified area, or the whole
|
||||
* window if r is NULL. This will ensure that
|
||||
* any changes in the invalidated area are made
|
||||
* visible on the screen. Note that this call
|
||||
* may also indirectly cause one or more calls
|
||||
* to refresh().
|
||||
*
|
||||
* virtual void refresh(SDL_Rect *r);
|
||||
* Virtual refresh call to be implemented by
|
||||
* windows that aren't repainted every frame.
|
||||
* After a call to invalidate(), refresh() will
|
||||
* be called by the engine as necessary to
|
||||
* produce a correct display. Note that in some
|
||||
* cases, this means that refresh() will be
|
||||
* called once for each screen flip, until all
|
||||
* buffers (usually two) are up to date. Also
|
||||
* note that you should do all rendering to the
|
||||
* window either directly *or* in the refresh()
|
||||
* function.
|
||||
*
|
||||
* Uint32 map_rgb(Uint8 r, Uint8 g, Uint8 b);
|
||||
* Uint32 map_rgb(Uint32 rgb);
|
||||
* Two different ways of translating a color in
|
||||
* standard RGB format (separate components or
|
||||
* HTML style hex code, respectively) into a
|
||||
* pixel value compatible with the screen.
|
||||
*
|
||||
* void foreground(Uint32 color);
|
||||
* void background(Uint32 color);
|
||||
* Change the foreground and background colors
|
||||
* used by subsequent rendering operations.
|
||||
* Note that the arguments have to be in screen
|
||||
* pixel format - the easiest way is to use the
|
||||
* map_rgb() calls to generate the values.
|
||||
*
|
||||
* void bgimage(int bank, int frame);
|
||||
* Select a background image, to use instead of
|
||||
* a background color. Setting bank and frame to
|
||||
* -1 (default) disables the image, so that the
|
||||
* background color is used instead.
|
||||
*
|
||||
* void colorkey(Uint32 color);
|
||||
* void colorkey();
|
||||
* Set the colorkey for this window to 'color'
|
||||
* and enable colorkeying. This affects blit()
|
||||
* when this window is used as the source. The
|
||||
* version without arguments disables
|
||||
* colorkeying for this window.
|
||||
* NOTE: Colorkeying is only supported by
|
||||
* offscreen windows.
|
||||
*
|
||||
* void alpha(float a);
|
||||
* Set the full surface alpha of this window.
|
||||
* 0.0 is fully transparent and 1.0 is opaque.
|
||||
* NOTE: Alpha is only supported by offscreen
|
||||
* windows.
|
||||
*
|
||||
* void clear(SDL_Rect *r = NULL);
|
||||
* Fill the specified rectangle with the current
|
||||
* background color or background image. If r is
|
||||
* NULL (default), clear the whole window.
|
||||
*
|
||||
* void font(int fnt);
|
||||
* Select the font to be used for subsequent
|
||||
* text rendering operations. The argument is a
|
||||
* gfxengine_t bank index, and must refer to a
|
||||
* bank that has been loaded with
|
||||
* gfxengine_t::loadfont().
|
||||
*
|
||||
* void string(int _x, int _y, const char *txt);
|
||||
* Put text string 'txt' starting at (_x, _y).
|
||||
*
|
||||
* void center(int _y, const char *txt);
|
||||
* Put text string 'txt' centered horizontally
|
||||
* inside the window, using '_y' as the y coord.
|
||||
*
|
||||
* void center_token(int _x, int _y, const char *txt, char token = 0);
|
||||
* Print string 'txt', positioning it so that
|
||||
* the first occurrence of character 'token'
|
||||
* is located at (_x, _y). Omitting the 'token'
|
||||
* argument, or passing 0 aligns the end of the
|
||||
* string with _x. Setting 'token' to -1 results
|
||||
* in the graphical center of the string being
|
||||
* located at (_x, _y) - basically an advanced
|
||||
* version of center().
|
||||
*
|
||||
* void string_fxp(int _x, int _y, const char *txt);
|
||||
* void center_fxp(int _y, const char *txt);
|
||||
* void center_token_fxp(int _x, int _y, const char *txt, char token = 0);
|
||||
* gfxengine_t fixed point format versions of
|
||||
* the corresponding non-fxp calls. (For sub-
|
||||
* pixel accurate rendering and/or to make use
|
||||
* of the higher resolutions in scaled modes.)
|
||||
*
|
||||
* int textwidth(const char *txt, int min = 0, int max = 255);
|
||||
* Calculates the graphical width of 'txt' if it
|
||||
* was to be printed with the current font.
|
||||
* Calculation starts at position 'min' in the
|
||||
* string, and ends at 'max', which makes it
|
||||
* possible to use this call for various
|
||||
* advanced alignment calculations.
|
||||
*
|
||||
* int fontheight();
|
||||
* Returns the height of the currently selected
|
||||
* font.
|
||||
*
|
||||
* void point(int _x, int _y);
|
||||
* Plot a pixel with the current foreground
|
||||
* color at (_x, _y). Note that the pixel will
|
||||
* become a quadratic block if the screen is
|
||||
* scaled to a higher resolution.
|
||||
*
|
||||
* void rectangle(int _x, int _y, int w, int h);
|
||||
* Draw a hollow rectangle of w x h pixels at
|
||||
* (_x, _y). The line thickness is scaled along
|
||||
* with screen resolution, as with point().
|
||||
*
|
||||
* void fillrect(int _x, int _y, int w, int h);
|
||||
* Draw a solid rectangle of w x h pixels at
|
||||
* (_x, _y).
|
||||
*
|
||||
* void fillrect_fxp(int _x, int _y, int w, int h);
|
||||
* As fillrect(), but with pixel or sub-pixel
|
||||
* accuracy, depending on scaling and video
|
||||
* driver.
|
||||
*
|
||||
* void sprite(int _x, int _y, int bank, int frame, int inval = 1);
|
||||
* Render sprite 'bank':'frame' at (_x, _y). If
|
||||
* inval is passed and set to 0, the affected
|
||||
* area will *not* be invalidated automatically.
|
||||
*
|
||||
* void sprite_fxp(int _x, int _y, int bank, int frame, int inval = 1);
|
||||
* As sprite(), but with pixel or sub-pixel
|
||||
* accuracy, depending on scaling and video
|
||||
* driver.
|
||||
*
|
||||
* void blit(int dx, int dy, window_t *src);
|
||||
* Blit from window 'src' into this window, placing
|
||||
* the top left corner of 'src' at (dx, dy).
|
||||
*
|
||||
* void blit(int dx, int dy, int sx, int sy, int sw, int sh, window_t *src);
|
||||
* Blit rectangle (sx, sy, sw, sh) from window 'src'
|
||||
* into this window, placing the top left corner of
|
||||
* 'src' at (dx, dy).
|
||||
*
|
||||
* int x() { return rect.x / xsc; }
|
||||
* int y() { return rect.y / ysc; }
|
||||
* int width() { return rect.w / xsc; }
|
||||
* int height() { return rect.h / ysc; }
|
||||
* Get the current screen position of the
|
||||
* window's top-left corner, and it's size.
|
||||
*
|
||||
* int x2() { return (rect.x + rect.w) / xsc; }
|
||||
* int y2() { return (rect.y + rect.h) / ysc; }
|
||||
* Get the screen position of the bottom-right
|
||||
* corner of the window.
|
||||
*/
|
||||
|
||||
#ifndef _WINDOW_H_
|
||||
#define _WINDOW_H_
|
||||
|
||||
#include "glSDL.h"
|
||||
|
||||
class gfxengine_t;
|
||||
|
||||
class window_t
|
||||
{
|
||||
friend class gfxengine_t;
|
||||
public:
|
||||
window_t();
|
||||
window_t(gfxengine_t *e);
|
||||
virtual ~window_t();
|
||||
|
||||
virtual void init(gfxengine_t *e);
|
||||
void place(int left, int top, int sizex, int sizey);
|
||||
int offscreen();
|
||||
void visible(int vis);
|
||||
int visible() { return _visible; }
|
||||
void select();
|
||||
void invalidate(SDL_Rect *r = NULL);
|
||||
virtual void refresh(SDL_Rect *r) { ; }
|
||||
|
||||
/* Color tools */
|
||||
Uint32 mulrgb(Uint32 c1, Uint32 c2)
|
||||
{
|
||||
int r = ((c1 >> 16) & 0xff) * ((c2 >> 16) & 0xff) * 258 >> 16;
|
||||
int g = ((c1 >> 8) & 0xff) * ((c2 >> 8) & 0xff) * 258 >> 16;
|
||||
int b = (c1 & 0xff) * (c2 & 0xff) * 258 >> 16;
|
||||
return r << 16 | g << 8 | b;
|
||||
}
|
||||
Uint32 fadergb(Uint32 rgb, Uint8 fade)
|
||||
{
|
||||
int r = ((rgb >> 16) & 0xff) * fade * 258 >> 16;
|
||||
int g = ((rgb >> 8) & 0xff) * fade * 258 >> 16;
|
||||
int b = (rgb & 0xff) * fade * 258 >> 16;
|
||||
return r << 16 | g << 8 | b;
|
||||
}
|
||||
|
||||
/* Rendering */
|
||||
Uint32 map_rgb(Uint8 r, Uint8 g, Uint8 b);
|
||||
Uint32 map_rgb(Uint32 rgb);
|
||||
void foreground(Uint32 color) { fgcolor = color; }
|
||||
void background(Uint32 color) { bgcolor = color; };
|
||||
|
||||
void bgimage(int bank = -1, int frame = -1);
|
||||
void colorkey(Uint32 color);
|
||||
void colorkey();
|
||||
void alpha(float a);
|
||||
|
||||
void clear(SDL_Rect *r = NULL);
|
||||
void font(int fnt);
|
||||
void string(int _x, int _y, const char *txt);
|
||||
void center(int _y, const char *txt);
|
||||
void center_token(int _x, int _y, const char *txt, char token = 0);
|
||||
void string_fxp(int _x, int _y, const char *txt);
|
||||
void center_fxp(int _y, const char *txt);
|
||||
void center_token_fxp(int _x, int _y, const char *txt, char token = 0);
|
||||
int textwidth(const char *txt, int min = 0, int max = 255);
|
||||
int textwidth_fxp(const char *txt, int min = 0, int max = 255);
|
||||
int fontheight();
|
||||
|
||||
void point(int _x, int _y);
|
||||
void rectangle(int _x, int _y, int w, int h);
|
||||
void fillrect(int _x, int _y, int w, int h);
|
||||
void fillrect_fxp(int _x, int _y, int w, int h);
|
||||
|
||||
void sprite(int _x, int _y, int bank, int frame, int inval = 1);
|
||||
void sprite_fxp(int _x, int _y, int bank, int frame, int inval = 1);
|
||||
|
||||
void blit(int dx, int dy, int sx, int sy, int sw, int sh, window_t *src);
|
||||
void blit(int dx, int dy, window_t *src);
|
||||
|
||||
int x() { return (phys_rect.x * 256 + 128) / xs; }
|
||||
int y() { return (phys_rect.y * 256 + 128) / ys; }
|
||||
int x2() { return ((phys_rect.x + phys_rect.w) * 256 + 128) / xs; }
|
||||
int y2() { return ((phys_rect.y + phys_rect.h) * 256 + 128) / ys; }
|
||||
int width() { return x2() - x(); }
|
||||
int height() { return y2() - y(); }
|
||||
|
||||
SDL_Rect phys_rect;
|
||||
|
||||
protected:
|
||||
window_t *next, *prev;
|
||||
/*
|
||||
* Kludge: This is for window selection to work.
|
||||
* the problem is that this will break (along
|
||||
* with some other things) if more than one
|
||||
* gfxengine_t instance is used.
|
||||
*/
|
||||
static window_t *selected; //Currently selected window
|
||||
|
||||
gfxengine_t *engine;
|
||||
SDL_Surface *surface;
|
||||
int xs, ys; //fixp 24:8
|
||||
Uint32 fgcolor, bgcolor;
|
||||
int bg_bank, bg_frame;
|
||||
int _font;
|
||||
int _visible;
|
||||
int _offscreen;
|
||||
|
||||
void _select(); //Internal version
|
||||
void link(gfxengine_t *e);
|
||||
void unlink(void);
|
||||
|
||||
void phys_refresh(SDL_Rect *r)
|
||||
{
|
||||
if(!r)
|
||||
refresh(NULL);
|
||||
else
|
||||
{
|
||||
SDL_Rect dr;
|
||||
dr.x = r->x - phys_rect.x;
|
||||
dr.y = r->y - phys_rect.y;
|
||||
int x2 = (int)(dr.x + r->w) * 256 / xs;
|
||||
int y2 = (int)(dr.y + r->h) * 256 / ys;
|
||||
dr.x = (int)dr.x * 256 / xs;
|
||||
dr.y = (int)dr.y * 256 / ys;
|
||||
dr.w = x2 - dr.x;
|
||||
dr.h = y2 - dr.y;
|
||||
refresh(&dr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user