Merge branch 'master' into wip-trails

This commit is contained in:
Bill Currie 2023-10-02 00:48:14 +09:00
commit 6423c13108
371 changed files with 25968 additions and 7437 deletions

82
config.d/attributes.m4 Normal file
View file

@ -0,0 +1,82 @@
dnl ==================================================================
dnl Checks for compiler attributes
dnl ==================================================================
AC_MSG_CHECKING(for __attribute__)
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[static __attribute__ ((unused)) const char *foo = "bar";]]
[[int bar(void);]],
[[return bar();]])],
[AC_DEFINE(HAVE___ATTRIBUTE__)
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)]
)
AH_VERBATIM([HAVE___ATTRIBUTE__],
[/* Define this if the GCC __attribute__ keyword is available */
#undef HAVE___ATTRIBUTE__
#ifndef HAVE___ATTRIBUTE__
# define __attribute__(x)
#endif])
AC_MSG_CHECKING(for __attribute__ ((visibility)))
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[void foo (void);]]
[[__attribute__ ((visibility ("default"))) void foo (void) {}]]
[[int bar(void);]],
[[return bar();]]
)],
[AC_DEFINE(HAVE___ATTRIBUTE__VISIBILITY)
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)]
)
AH_VERBATIM([HAVE___ATTRIBUTE__VISIBILITY],
[/* Define this if the GCC visibility __attribute__ is available */
#undef HAVE___ATTRIBUTE__VISIBILITY
#ifdef HAVE___ATTRIBUTE__VISIBILITY
# define VISIBLE __attribute__((visibility ("default")))
#else
# define VISIBLE
#endif])
AC_MSG_CHECKING(for __attribute__ ((designated_init)))
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[struct x { char y; } __attribute__ ((designated_init));]]
[[int bar(void);]],
[[return bar();]]
)],
[AC_DEFINE(HAVE___ATTRIBUTE__DESIGNATED_INIT)
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)]
)
AH_VERBATIM([HAVE___ATTRIBUTE__DESIGNATED_INIT],
[/* Define this if the GCC designated_init __attribute__ is available */
#undef HAVE___ATTRIBUTE__DESIGNATED_INIT
#ifdef HAVE___ATTRIBUTE__DESIGNATED_INIT
# define DESIGNATED_INIT __attribute__((designated_init))
#else
# define DESIGNATED_INIT
#endif])
if test "x$SYSTYPE" = "xWIN32"; then
AC_MSG_CHECKING(for __attribute__ ((gcc_struct)))
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[typedef struct { int foo; }]]
[[__attribute__ ((gcc_struct)) gcc_struct_test;]],
[[return gcc_struct_test.foo]])],
[AC_DEFINE(HAVE___ATTRIBUTE__GCC_STRUCT)
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)
])
fi
AH_VERBATIM([HAVE___ATTRIBUTE__GCC_STRUCT],
[/* Define this if the GCC gcc_struct __attribute__ is available */
#undef HAVE___ATTRIBUTE__GCC_STRUCT
#ifdef HAVE___ATTRIBUTE__GCC_STRUCT
# define GCC_STRUCT __attribute__((gcc_struct))
#else
# define GCC_STRUCT
#endif])

View file

@ -329,7 +329,7 @@ if test x"${top_need_libs}" = xyes; then
qfac_include_qf_input="\$(include_qf_input)"
qfac_include_qf_math="\$(include_qf_math)"
qfac_include_qf_plugin="\$(include_qf_plugin)"
qfac_include_qf_progs="\$(include_qf_progs)"
qfac_include_qf_progs="\$(include_qf_progs) \$(include_qf_progs_gen)"
qfac_include_qf_scene="\$(include_qf_scene)"
qfac_include_qf_simd="\$(include_qf_simd)"
qfac_include_qf_ui="\$(include_qf_ui)"

View file

@ -6,6 +6,18 @@ else
cvs_def_disabled="!= xno"
fi
AC_MSG_CHECKING(for clang)
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[]],
[[#ifndef __clang__],
[ choke me],
[#endif]])],
[CLANG=yes],
[CLANG=no]
)
AC_MSG_RESULT($CLANG)
AC_MSG_CHECKING(for CFLAGS pre-set)
leave_cflags_alone=no
if test "x$CFLAGS" != "x"; then
@ -29,10 +41,14 @@ AC_LINK_IFELSE(
)
AH_VERBATIM([HAVE_C99INLINE],
[#undef HAVE_C99INLINE
#ifdef HAVE_C99INLINE
# define GNU89INLINE
#ifdef __clang__
# define GNU89INLINE static
#else
# define GNU89INLINE extern
# ifdef HAVE_C99INLINE
# define GNU89INLINE
# else
# define GNU89INLINE extern
# endif
#endif])
if test "x$GCC" = xyes; then
@ -82,7 +98,7 @@ dnl We want warnings, lots of warnings...
dnl The help text should be INVERTED before release!
dnl when in git, this test defaults to ENABLED.
dnl In a release, this test defaults to DISABLED.
if test "x$GCC" = "xyes"; then
if test "x$GCC" = "xyes" -a "x$leave_cflags_alone" != xyes; then
if test "x$enable_Werror" $cvs_def_enabled; then
CFLAGS="$CFLAGS -Wall -Werror -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations"
else
@ -91,6 +107,10 @@ if test "x$GCC" = "xyes"; then
CFLAGS="$CFLAGS -fno-common"
fi
if test "x$CLANG" = xyes -a "x$leave_cflags_alone" != xyes; then
CFLAGS="$CFLAGS -Wno-misleading-indentation"
fi
AC_ARG_ENABLE(optimize,
AS_HELP_STRING([--disable-optimize],
[compile without optimizations (for development)]),
@ -146,8 +166,8 @@ if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then
dnl if test "$CC_MAJ" -ge 4; then
dnl QF_CC_OPTION(-finline-limit=32000 -Winline)
dnl fi
dnl heavy="-O2 $CFLAGS -ffast-math -fno-unsafe-math-optimizations -funroll-loops -fomit-frame-pointer"
heavy="-O2 $CFLAGS -fno-fast-math -funroll-loops -fomit-frame-pointer "
dnl heavy="-O2 -ffast-math -fno-unsafe-math-optimizations -funroll-loops -fomit-frame-pointer"
heavy="-O2 -fno-fast-math -funroll-loops -fomit-frame-pointer "
CFLAGS="$saved_cflags"
light="-O2"
AC_ARG_ENABLE(strict-aliasing,
@ -229,7 +249,7 @@ AC_ARG_ENABLE(profile,
[compile with profiling (for development)]),
profile=$enable_profile
)
if test "x$profile" = xyes; then
if test "x$profile" = xyes -a "x$leave_cflags_alone" != xyes; then
BUILD_TYPE="$BUILD_TYPE Profile"
if test "x$GCC" = xyes; then
CFLAGS="`echo $CFLAGS | sed -e 's/-fomit-frame-pointer//g'` -pg"
@ -240,7 +260,7 @@ if test "x$profile" = xyes; then
fi
check_pipe=no
if test "x$GCC" = xyes; then
if test "x$GCC" = xyes -a "x$leave_cflags_alone" != xyes; then
dnl Check for -pipe vs -save-temps.
AC_MSG_CHECKING(for -pipe vs -save-temps)
AC_ARG_ENABLE(save-temps,
@ -279,7 +299,7 @@ dnl with many compilers that do not support the latest ISO standards. Well,
dnl that is our cover story -- the reality is that we like them and do not want
dnl to give them up. :)
dnl Make the compiler swallow its pride...
if test "x$GCC" != xyes; then
if test "x$GCC" != xyes -a "x$CLANG" != xyes -a "x$leave_cflags_alone" != xyes; then
AC_MSG_CHECKING(for how to deal with BCPL-style comments)
case "${host}" in
*-aix*)
@ -300,6 +320,25 @@ if test "x$GCC" != xyes; then
esac
fi
if test "x$leave_cflags_alone" != xyes; then
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[bool flag = true;]],
[[return flag ? 1 : 0]])],
[],
[QF_CC_OPTION_TEST(-std=gnu23,[],QF_CC_OPTION(-std=gnu2x))]
)
fi
AC_MSG_CHECKING([for c23])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[bool flag = true;]
[int bar (void);]],
[[return bar();]])],
[AC_MSG_RESULT(yes)],
[AC_MSG_ERROR(QuakeForge requires C23 to compile)]
)
AS="$CC"
if test "x$SYSTYPE" = "xWIN32"; then
ASFLAGS="\$(DEFS) \$(CFLAGS) \$(CPPFLAGS) \$(DEFAULT_INCLUDES) \$(INCLUDES) -D_WIN32"

View file

@ -30,3 +30,19 @@ AC_SUBST(HARFBUZZ_LIBS)
if test "x$HAVE_HARFBUZZ" == "xyes"; then
AC_DEFINE(HAVE_HARFBUZZ, 1, [Define if you have the HarfBuzz library])
fi
AC_ARG_ENABLE(fontconfig,
AS_HELP_STRING([--disable-fontconfig], [disable fontconfig support]))
if test "x$enable_fontconfig" != "xno"; then
if test "x$PKG_CONFIG" != "x"; then
PKG_CHECK_MODULES([FONTCONFIG], [fontconfig], HAVE_FONTCONFIG=yes, HAVE_FONTCONFIG=no)
fi
else
HAVE_FONTCONFIG=no
FONTCONFIG_LIBS=
fi
AC_SUBST(FONTCONFIG_LIBS)
if test "x$HAVE_FONTCONFIG" == "xyes"; then
AC_DEFINE(HAVE_FONTCONFIG, 1, [Define if you have the fontconfig library])
fi

View file

@ -48,20 +48,20 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <dlfcn.h>]], [[int foo = RTLD_DEEP
])
fi
dnl Checks for stricmp/strcasecmp
#dnl Checks for stricmp/strcasecmp
#AC_CHECK_FUNC(strcasecmp,
# ,
# AC_CHECK_FUNC(stricmp,
# AC_DEFINE(strcasecmp, stricmp)
# )
#)
AC_CHECK_FUNC(strcasecmp, strcasecmp=yes, strcasecmp=no)
if test "x$strcasecmp" = xno; then
AC_CHECK_FUNC(stricmp,
AC_DEFINE(strcasecmp, stricmp, [Define strcasecmp as stricmp if you have one but not the other]),
AC_MSG_ERROR([Neither stricmp nor strcasecmp found])
)
fi
#AC_CHECK_FUNC(strcasecmp, strcasecmp=yes, strcasecmp=no)
#if test "x$strcasecmp" = xno; then
# AC_CHECK_FUNC(stricmp,
# AC_DEFINE(strcasecmp, stricmp, [Define strcasecmp as stricmp if you have one but not the other]),
# AC_MSG_ERROR([Neither stricmp nor strcasecmp found])
# )
#fi
dnl Check for vsnprintf
if test "x$ac_cv_func_vsnprintf" = "xno" -a \
@ -80,14 +80,14 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[fnmatch();]])],[BUILD_FNMATCH=no
AM_CONDITIONAL(BUILD_FNMATCH, test "x$BUILD_FNMATCH" = "xyes")
AC_MSG_CHECKING(for opendir)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[opendir();]])],[BUILD_DIRENT=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[extern void opendir(); opendir();]])],[BUILD_DIRENT=no
AC_MSG_RESULT(yes)],[BUILD_DIRENT=yes
AC_MSG_RESULT(no)
])
AM_CONDITIONAL(BUILD_DIRENT, test "x$BUILD_DIRENT" = "xyes")
AC_MSG_CHECKING(for getopt_long)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[getopt_long();]])],[BUILD_GETOPT=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[extern void getopt_long(); getopt_long();]])],[BUILD_GETOPT=no
AC_MSG_RESULT(yes)],[BUILD_GETOPT=yes
AC_MSG_RESULT(no)
])

View file

@ -14,47 +14,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>]], [[int foo = _SC_PAGE
])
fi
AC_MSG_CHECKING(for __attribute__)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[static __attribute__ ((unused)) const char *foo = "bar";]], [[]])],[AC_DEFINE(HAVE___ATTRIBUTE__)
AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)
])
AH_VERBATIM([HAVE___ATTRIBUTE__],
[/* Define this if the GCC __attribute__ keyword is available */
#undef HAVE___ATTRIBUTE__
#ifndef HAVE___ATTRIBUTE__
# define __attribute__(x)
#endif])
AC_MSG_CHECKING(for __attribute__ ((visibility)))
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[void foo (void);
__attribute__ ((sivibility ("default"))) void foo (void) {}]], [[]])],[AC_DEFINE(HAVE___ATTRIBUTE__VISIBILITY)
AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)
])
AH_VERBATIM([HAVE___ATTRIBUTE__VISIBILITY],
[/* Define this if the GCC visibility __attribute__ is available */
#undef HAVE___ATTRIBUTE__VISIBILITY
#ifdef HAVE___ATTRIBUTE__VISIBILITY
# define VISIBLE __attribute__((visibility ("default")))
#else
# define VISIBLE
#endif])
if test "x$SYSTYPE" = "xWIN32"; then
AC_MSG_CHECKING(for __attribute__ ((gcc_struct)))
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[typedef struct { int foo; }
__attribute__ ((gcc_struct)) gcc_struct_test;]], [[]])],[AC_DEFINE(HAVE___ATTRIBUTE__GCC_STRUCT)
AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)
])
fi
AH_VERBATIM([HAVE___ATTRIBUTE__GCC_STRUCT],
[/* Define this if the GCC gcc_struct __attribute__ is available */
#undef HAVE___ATTRIBUTE__GCC_STRUCT
#ifdef HAVE___ATTRIBUTE__GCC_STRUCT
# define GCC_STRUCT __attribute__((gcc_struct))
#else
# define GCC_STRUCT
#endif])
AC_MSG_CHECKING(for __builtin_expect)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[int x;]], [[if (__builtin_expect(!x, 1)) {}]])],[AC_DEFINE(HAVE___BUILTIN_EXPECT)
AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)

View file

@ -54,7 +54,27 @@ case "$host_os" in
;;
*)
dnl Checks for working -lm
AC_CHECK_LIB(m, pow,, AC_MSG_ERROR([math library (-lm) appears broken]))
AC_MSG_CHECKING(for pow and atan2 in standard library)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <math.h>
int func_ind;
double (*func[])(double, double) = {pow, atan2};]],
[[return (int)(func[func_ind])(2, 3);]])],
[AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)
AC_MSG_CHECKING(for pow and atan2 in -lm)
LIBS="-lm $LIBS"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <math.h>
int func_ind;
double (*func[])(double, double) = {pow, atan2};]],
[[return (int)(func[func_ind])(2, 3);]])],
[AC_MSG_RESULT(yes)],
[AC_MSG_ERROR([math library (-lm) appears broken])]
)]
)
;;
esac
@ -70,6 +90,11 @@ m4_include(config.d/sdl.m4)
m4_include(config.d/curses.m4)
m4_include(config.d/freetype.m4)
m4_include(config.d/networking.m4)
m4_include(config.d/compiling.m4)
m4_include(config.d/attributes.m4)
dnl ==================================================================
dnl Checks for system type
dnl ==================================================================
@ -115,13 +140,10 @@ m4_include(config.d/joystick.m4)
m4_include(config.d/evdev.m4)
m4_include(config.d/cdrom.m4)
m4_include(config.d/networking.m4)
m4_include(config.d/paths.m4)
m4_include(config.d/build_control.m4)
m4_include(config.d/qfcc.m4)
m4_include(config.d/compiling.m4)
AC_ARG_ENABLE(static-doc,
AS_HELP_STRING([--enable-static-doc],

View file

@ -12,6 +12,7 @@ EXTRA_DIST += \
include/block8.h \
include/bsearch.h \
include/buildnum.h \
include/cl_console.h \
include/compat.h \
include/context_sdl.h \
include/context_win.h \
@ -62,12 +63,10 @@ EXTRA_DIST += \
include/quicksort.h \
include/r_cvar.h \
include/r_dynamic.h \
include/r_font.h \
include/r_internal.h \
include/r_local.h \
include/r_scrap.h \
include/r_shared.h \
include/r_text.h \
include/regex.h \
include/rua_internal.h \
include/skin_stencil.h \

View file

@ -60,7 +60,7 @@ typedef struct elechain_s {
struct elechain_s *next;
int model_index;
elements_t *elements;
vec4f_t *transform;
const vec4f_t *transform;
float *color;
} elechain_t;

View file

@ -151,6 +151,9 @@ include_qf_progs = \
include/QF/progs/pr_type.h \
include/QF/progs/pr_type_names.h
include_qf_progs_gen = \
include/QF/progs/pr_opcode.hinc
include_qf_scene = \
include/QF/scene/camera.h \
include/QF/scene/entity.h \
@ -172,8 +175,10 @@ include_qf_simd = \
include_qf_ui = \
include/QF/ui/canvas.h \
include/QF/ui/font.h \
include/QF/ui/imui.h \
include/QF/ui/inputline.h \
include/QF/ui/passage.h \
include/QF/ui/shaper.h \
include/QF/ui/text.h \
include/QF/ui/txtbuffer.h \
include/QF/ui/view.h \
@ -188,12 +193,14 @@ include_qf_vulkan = \
include/QF/Vulkan/debug.h \
include/QF/Vulkan/descriptor.h \
include/QF/Vulkan/device.h \
include/QF/Vulkan/dsmanager.h \
include/QF/Vulkan/funclist.h \
include/QF/Vulkan/image.h \
include/QF/Vulkan/instance.h \
include/QF/Vulkan/memory.h \
include/QF/Vulkan/pipeline.h \
include/QF/Vulkan/projection.h \
include/QF/Vulkan/render.h \
include/QF/Vulkan/resource.h \
include/QF/Vulkan/qf_alias.h \
include/QF/Vulkan/qf_bsp.h \
@ -202,12 +209,12 @@ include_qf_vulkan = \
include/QF/Vulkan/qf_iqm.h \
include/QF/Vulkan/qf_lighting.h \
include/QF/Vulkan/qf_lightmap.h \
include/QF/Vulkan/qf_main.h \
include/QF/Vulkan/qf_matrices.h \
include/QF/Vulkan/qf_model.h \
include/QF/Vulkan/qf_output.h \
include/QF/Vulkan/qf_palette.h \
include/QF/Vulkan/qf_particles.h \
include/QF/Vulkan/qf_planes.h \
include/QF/Vulkan/qf_scene.h \
include/QF/Vulkan/qf_sprite.h \
include/QF/Vulkan/qf_texture.h \

View file

@ -22,6 +22,7 @@ typedef struct qfv_bufferbarrier_s {
enum {
qfv_LT_Undefined_to_TransferDst,
qfv_LT_Undefined_to_General,
qfv_LT_Undefined_to_ShaderReadOnly,
qfv_LT_TransferDst_to_TransferSrc,
qfv_LT_TransferDst_to_General,
qfv_LT_TransferDst_to_ShaderReadOnly,

View file

@ -14,7 +14,7 @@ struct tex_s;
typedef void (*capfunc_t) (struct tex_s *screencap, void *data);
typedef struct qfv_capture_frame_s {
VkBuffer buffer;
struct qfv_resobj_s *buffer;
byte *data;
bool initiated;
@ -27,12 +27,10 @@ typedef struct qfv_capture_frame_set_s
typedef struct qfv_capturectx_s {
qfv_capture_frame_set_t frames;
struct qfv_device_s *device;
VkExtent2D extent;
size_t imgsize;
size_t memsize;
byte *data;
VkDeviceMemory memory;
struct qfv_resource_s *resources;
} qfv_capturectx_t;
struct vulkan_ctx_s;

View file

@ -0,0 +1,46 @@
#ifndef __QF_Vulkan_mouse_pick_h
#define __QF_Vulkan_mouse_pick_h
#ifndef VK_NO_PROTOTYPES
#define VK_NO_PROTOTYPES
#endif
#include <vulkan/vulkan.h>
#include "QF/darray.h"
#include "QF/qtypes.h"
#define mousepick_size 5
struct vulkan_ctx_s;
typedef void (*mousepickfunc_t) (const uint32_t *entid, void *data);
typedef struct qfv_mousepick_frame_s {
VkBuffer entid_buffer;
uint32_t *entid_data;
bool initiated;
mousepickfunc_t callback;
void *callback_data;
uint32_t x, y;
VkOffset3D offset;
VkExtent3D extent;
VkImage entid_image;
} qfv_mousepick_frame_t;
typedef struct qfv_mousepick_frame_set_s
DARRAY_TYPE (qfv_mousepick_frame_t) qfv_mousepick_frame_set_t;
typedef struct qfv_mousepickctx_s {
qfv_mousepick_frame_set_t frames;
struct qfv_resobj_s *entid_res;
struct qfv_resource_s *resources;
} qfv_mousepickctx_t;
struct vulkan_ctx_s;
void QFV_MousePick_Init (struct vulkan_ctx_s *ctx);
void QFV_MousePick_Shutdown (struct vulkan_ctx_s *ctx);
void QFV_MousePick_Read (struct vulkan_ctx_s *ctx, uint32_t x, uint32_t y,
mousepickfunc_t callback, void *data);
#endif//__QF_Vulkan_mouse_pick_h

View file

@ -5,8 +5,19 @@
void QFV_Orthographic (mat4f_t proj, float xmin, float xmax,
float ymin, float ymax, float znear, float zfar);
void QFV_OrthographicV (mat4f_t proj, vec4f_t mins, vec4f_t maxs);
// fov_x and fov_y are tan(fov/2) for x and y respectively
void QFV_PerspectiveTan (mat4f_t proj, float fov_x, float fov_y);
void QFV_PerspectiveCos (mat4f_t proj, float fov);
void QFV_PerspectiveTan (mat4f_t proj, float fov_x, float fov_y,
float nearclip);
void QFV_InversePerspectiveTan (mat4f_t proj, float fov_x, float fov_y,
float nearclip);
void QFV_PerspectiveTanFar (mat4f_t proj, float fov_x, float fov_y,
float nearclip, float farclip);
void QFV_InversePerspectiveTanFar (mat4f_t proj, float fov_x, float fov_y,
float nearclip, float farclip);
void QFV_PerspectiveCos (mat4f_t proj, float fov, float nearclip);
extern const mat4f_t qfv_z_up;
extern const mat4f_t qfv_box_rotations[6];
#endif//__QF_Vulkan_projection_h

View file

@ -38,6 +38,11 @@
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
enum {
alias_main,
alias_shadow,
};
typedef struct aliasvrt_s {
float vertex[4];
float normal[4];

View file

@ -270,6 +270,7 @@ typedef struct bsp_pass_s {
vec4f_t position; ///< view position
const struct mod_brush_s *brush;///< data for current model
struct bspctx_s *bsp_context; ///< owning bsp context
struct entqueue_s *entqueue; ///< entities to render this pass
/** \name GPU data
*
* The indices to be drawn and the entity ids associated with each draw
@ -324,6 +325,14 @@ typedef enum {
QFV_bspNumPasses
} QFV_BspQueue;
typedef enum {
QFV_bspMain,
QFV_bspShadow,
QFV_bspDebug,
QFV_bspNumStages
} QFV_BspPass;
typedef struct bspframe_s {
uint32_t *index_data; // pointer into mega-buffer for this frame (c)
uint32_t index_offset; // offset of index_data within mega-buffer (c)
@ -331,7 +340,6 @@ typedef struct bspframe_s {
uint32_t *entid_data;
uint32_t entid_offset;
uint32_t entid_count;
qfv_cmdbufferset_t cmdSet;
} bspframe_t;
typedef struct bspframeset_s
@ -364,10 +372,11 @@ typedef struct bspctx_s {
VkDescriptorSet skybox_descriptor;
bsp_pass_t main_pass; ///< camera view depth, gbuffer, etc
bsp_pass_t shadow_pass;
bsp_pass_t debug_pass;
VkSampler sampler;
VkDeviceMemory texture_memory;
size_t vertex_buffer_size;
size_t index_buffer_size;
VkBuffer vertex_buffer;
@ -388,6 +397,7 @@ void Vulkan_BuildDisplayLists (model_t **models, int num_models,
void Vulkan_Bsp_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Bsp_Setup (struct vulkan_ctx_s *ctx);
void Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx);
bsp_pass_t *Vulkan_Bsp_GetPass (struct vulkan_ctx_s *ctx, QFV_BspPass pass_ind);
///@}
#endif//__QF_Vulkan_qf_bsp_h

View file

@ -36,7 +36,7 @@
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
#define COMPOSE_IMAGE_INFOS 1
#define COMPOSE_IMAGE_INFOS 3
typedef struct composeframe_s {
VkDescriptorImageInfo imageInfo[COMPOSE_IMAGE_INFOS];

View file

@ -37,75 +37,115 @@
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
#include "QF/Vulkan/image.h"
#include "QF/Vulkan/render.h"
#include "QF/simd/types.h"
typedef struct qfv_lightmatset_s DARRAY_TYPE (mat4f_t) qfv_lightmatset_t;
#define MaxLights 768
#define MaxLights 2048
#define ST_NONE 0 // no shadows
#define ST_PLANE 1 // single plane shadow map (small spotlight)
#define ST_CASCADE 2 // cascaded shadow maps
#define ST_CUBE 3 // cubemap (omni, large spotlight)
enum {
ST_NONE, // no shadows
ST_PLANE, // single plane shadow map (small spotlight)
ST_CASCADE, // cascaded shadow maps
ST_CUBE, // cubemap (omni, large spotlight)
typedef struct qfv_light_buffer_s {
light_t lights[MaxLights] __attribute__((aligned(16)));
int lightCount;
//mat4f_t shadowMat[MaxLights];
//vec4f_t shadowCascade[MaxLights];
} qfv_light_buffer_t;
ST_COUNT
};
enum {
lighting_main,
lighting_shadow,
lighting_debug,
};
typedef struct qfv_light_render_s {
// mat_id (13) map_id (5) layer (11) type (2)
uint32_t id_data;
// light style (6)
uint32_t style;
} qfv_light_render_t;
#define LIGHTING_BUFFER_INFOS 1
#define LIGHTING_ATTACH_INFOS 5
#define LIGHTING_ATTACH_INFOS 4
#define LIGHTING_SHADOW_INFOS 32
#define LIGHTING_DESCRIPTORS (LIGHTING_BUFFER_INFOS + LIGHTING_ATTACH_INFOS + 1)
typedef struct qfv_framebufferset_s
DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t;
typedef struct light_queue_s {
uint16_t start;
uint16_t count;
} light_queue_t;
typedef struct lightingframe_s {
VkDescriptorSet shadowmat_set;
VkDescriptorSet lights_set;
VkDescriptorSet attach_set;
VkBuffer shadowmat_buffer;
VkBuffer light_buffer;
VkDescriptorBufferInfo bufferInfo[LIGHTING_BUFFER_INFOS];
VkDescriptorImageInfo attachInfo[LIGHTING_ATTACH_INFOS];
VkDescriptorImageInfo shadowInfo[LIGHTING_SHADOW_INFOS];
union {
VkWriteDescriptorSet descriptors[LIGHTING_DESCRIPTORS];
struct {
VkWriteDescriptorSet bufferWrite[LIGHTING_BUFFER_INFOS];
VkWriteDescriptorSet attachWrite[LIGHTING_ATTACH_INFOS];
VkWriteDescriptorSet shadowWrite;
};
};
VkBuffer render_buffer;
VkBuffer style_buffer;
VkBuffer id_buffer;
VkBuffer entid_buffer;
light_queue_t light_queue[4];
qfv_imageviewset_t views;
qfv_framebufferset_t framebuffers;
} lightingframe_t;
typedef struct lightingframeset_s
DARRAY_TYPE (lightingframe_t) lightingframeset_t;
typedef struct light_renderer_s {
VkRenderPass renderPass; // shared
VkFramebuffer framebuffer;
VkImage image; // shared
VkImageView view;
uint32_t size;
uint32_t layer;
uint32_t numLayers;
int mode;
} light_renderer_t;
typedef struct light_control_s {
uint8_t renderpass_index;
uint8_t map_index;
uint16_t size;
uint16_t layer;
uint8_t numLayers;
uint8_t mode;
uint16_t light_id;
uint16_t matrix_id;
} light_control_t;
typedef struct light_control_set_s
DARRAY_TYPE (light_control_t) light_control_set_t;
typedef struct light_renderer_set_s
DARRAY_TYPE (light_renderer_t) light_renderer_set_t;
typedef struct lightingctx_s {
lightingframeset_t frames;
VkPipeline pipeline;
VkSampler sampler;
VkDeviceMemory light_memory;
struct qfv_resource_s *shadow_resources;
struct qfv_resource_s *light_resources;
qfv_lightmatset_t light_mats;
qfv_imageset_t light_images;
light_renderer_set_t light_renderers;
VkImage *map_images;
VkImageView *map_views;
bool *map_cube;
int num_maps;
VkImage default_map;
VkImageView default_view_cube;
VkImageView default_view_2d;
VkRenderPass renderpass_6;
VkRenderPass renderpass_4;
VkRenderPass renderpass_1;
light_control_set_t light_control;
qfv_attachmentinfo_t shadow_info;
VkSampler shadow_sampler;
VkDescriptorSet shadow_cube_set;
VkDescriptorSet shadow_2d_set;
VkBuffer splat_verts;
VkBuffer splat_inds;
vec4f_t world_mins;
vec4f_t world_maxs;
uint32_t dynamic_base;
uint32_t dynamic_matrix_base;
uint32_t dynamic_count;
struct lightingdata_s *ldata;
struct scene_s *scene;
} lightingctx_t;
@ -116,5 +156,7 @@ void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Lighting_Setup (struct vulkan_ctx_s *ctx);
void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx);
void Vulkan_LoadLights (struct scene_s *scene, struct vulkan_ctx_s *ctx);
VkDescriptorSet Vulkan_Lighting_Descriptors (struct vulkan_ctx_s *ctx,
int frame) __attribute__((pure));
#endif//__QF_Vulkan_qf_lighting_h

View file

@ -61,6 +61,8 @@ typedef struct matrixctx_s {
double sky_time;
int dirty;
float fov_x, fov_y;
matrixframeset_t frames;
struct qfv_resource_s *resource;

View file

@ -33,6 +33,7 @@
#include "QF/darray.h"
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
#include "QF/Vulkan/render.h"
typedef struct outputframe_s {
VkImageView input;
@ -47,6 +48,7 @@ typedef struct outputctx_s {
VkSampler sampler;
VkImageView input;
VkFramebuffer *framebuffers; // one per swapchain image
qfv_attachmentinfo_t swapchain_info;
} outputctx_t;
struct vulkan_ctx_s;

View file

@ -0,0 +1,62 @@
/*
qf_planes.h
Vulkan debug planes rendering
Copyright (C) 2023 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2023/7/20
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef __QF_Vulkan_qf_planes_h
#define __QF_Vulkan_qf_planes_h
#include "QF/darray.h"
#include "QF/model.h"
#include "QF/modelgen.h"
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
typedef struct planes_frame_s {
VkDescriptorSet descriptor;
} planes_frame_t;
typedef struct planes_frameset_s
DARRAY_TYPE (planes_frame_t) planes_frameset_t;
typedef struct planesctx_s {
planes_frameset_t frames;
VkSampler sampler;
struct qfv_dsmanager_s *dsmanager;
struct qfv_resource_s *resources;
} planesctx_t;
struct vulkan_ctx_s;
struct entity_s;
struct mod_planes_ctx_s;
struct planes_s;
void Vulkan_Planes_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Planes_Setup (struct vulkan_ctx_s *ctx);
void Vulkan_Planes_Shutdown (struct vulkan_ctx_s *ctx);
#endif//__QF_Vulkan_qf_planes_h

View file

@ -64,6 +64,7 @@ typedef struct scenectx_s {
struct qfv_resource_s *entities;
scnframeset_t frames;
int max_entities;
struct scene_s *scene;
} scenectx_t;
struct vulkan_ctx_s;
@ -77,4 +78,6 @@ VkDescriptorSet Vulkan_Scene_Descriptors (struct vulkan_ctx_s *ctx) __attribute_
int Vulkan_Scene_AddEntity (struct vulkan_ctx_s *ctx, struct entity_s entity);
void Vulkan_Scene_Flush (struct vulkan_ctx_s *ctx);
void Vulkan_NewScene (struct scene_s *scene, struct vulkan_ctx_s *ctx);
#endif//__QF_Vulkan_qf_scene_h

View file

@ -21,9 +21,12 @@ typedef struct qfv_transtate_s {
typedef struct translucentframe_s {
VkDescriptorSet flat;
VkDescriptorSet cube;
VkImage heads;
VkImage cube_heads;
VkBuffer state;
struct qfv_resobj_s *heads;
struct qfv_resobj_s *cube_heads;
struct qfv_resobj_s *heads_view;
struct qfv_resobj_s *cube_heads_view;
struct qfv_resobj_s *state;
struct qfv_resobj_s *frags;
} translucentframe_t;
typedef struct translucentframeset_s
@ -32,6 +35,7 @@ typedef struct translucentframeset_s
typedef struct translucentctx_s {
translucentframeset_t frames;
struct qfv_resource_s *resources;
VkExtent2D extent;
int maxFragments;
} translucentctx_t;
@ -43,7 +47,5 @@ void Vulkan_Translucent_Setup (struct vulkan_ctx_s *ctx);
void Vulkan_Translucent_Shutdown (struct vulkan_ctx_s *ctx);
VkDescriptorSet Vulkan_Translucent_Descriptors (struct vulkan_ctx_s *ctx,
int frame)__attribute__((pure));
void Vulkan_Translucent_CreateBuffers (struct vulkan_ctx_s *ctx,
VkExtent2D extent);
#endif//__QF_Vulkan_qf_translucent_h

View file

@ -64,7 +64,7 @@ enum {
QFV_attachEmission,
QFV_attachNormal,
QFV_attachPosition,
QFV_attachOpaque,
QFV_attachLight,
QFV_attachSwapchain,
};

View file

@ -81,6 +81,7 @@ typedef struct qfv_imageinfo_s {
VkImageTiling tiling;
VkImageUsageFlags usage;
VkImageLayout initialLayout;
struct qfv_resobj_s *object;
} qfv_imageinfo_t;
typedef struct qfv_imageviewinfo_s {
@ -91,6 +92,7 @@ typedef struct qfv_imageviewinfo_s {
VkFormat format;
VkComponentMapping components;
VkImageSubresourceRange subresourceRange;
struct qfv_resobj_s *object;
} qfv_imageviewinfo_t;
typedef struct qfv_bufferinfo_s {
@ -303,6 +305,12 @@ typedef struct qfv_samplerinfo_s {
} qfv_samplerinfo_t;
#ifndef __QFCC__
typedef struct qfv_time_s {
int64_t cur_time;
int64_t min_time;
int64_t max_time;
} qfv_time_t;
typedef struct qfv_label_s {
vec4f_t color;
const char *name;
@ -355,6 +363,8 @@ typedef struct qfv_renderpass_s {
qfv_framebufferinfo_t *framebufferinfo;
VkImageView output;
qfv_reference_t outputref;
struct qfv_resource_s *resources;
} qfv_renderpass_t;
typedef struct qfv_render_s {
@ -382,13 +392,11 @@ typedef struct qfv_step_s {
qfv_render_t *render;
qfv_compute_t *compute;
qfv_process_t *process;
qfv_time_t time;
} qfv_step_t;
typedef struct qfv_job_s {
qfv_label_t label;
struct qfv_resource_s *resources;
struct qfv_resobj_s *images;
struct qfv_resobj_s *image_views;
uint32_t num_renderpasses;
uint32_t num_pipelines;
@ -401,6 +409,7 @@ typedef struct qfv_job_s {
qfv_cmdbufferset_t commands;
uint32_t num_dsmanagers;
struct qfv_dsmanager_s **dsmanager;
qfv_time_t time;
} qfv_job_t;
typedef struct qfv_renderframe_s {
@ -412,14 +421,19 @@ typedef struct qfv_renderframe_s {
typedef struct qfv_renderframeset_s
DARRAY_TYPE (qfv_renderframe_t) qfv_renderframeset_t;
typedef struct qfv_attachmentinfoset_s
DARRAY_TYPE (qfv_attachmentinfo_t *) qfv_attachmentinfoset_t;
typedef struct qfv_renderctx_s {
struct hashctx_s *hashctx;
exprtab_t task_functions;
qfv_attachmentinfoset_t external_attachments;
qfv_jobinfo_t *jobinfo;
qfv_samplerinfo_t *samplerinfo;
qfv_job_t *job;
qfv_job_t *job;
qfv_renderframeset_t frames;
int64_t size_time;
struct qfv_renderdebug_s *debug;
} qfv_renderctx_t;
typedef struct qfv_taskctx_s {
@ -427,11 +441,14 @@ typedef struct qfv_taskctx_s {
qfv_pipeline_t *pipeline;
qfv_renderpass_t *renderpass;
VkCommandBuffer cmd;
void *data;
} qfv_taskctx_t;
VkCommandBuffer QFV_GetCmdBuffer (struct vulkan_ctx_s *ctx, bool secondary);
void QFV_AppendCmdBuffer (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd);
void QFV_RunRenderPass (struct vulkan_ctx_s *ctx, qfv_renderpass_t *renderpass,
uint32_t width, uint32_t height, void *data);
void QFV_RunRenderJob (struct vulkan_ctx_s *ctx);
void QFV_LoadRenderInfo (struct vulkan_ctx_s *ctx, const char *name);
void QFV_LoadSamplerInfo (struct vulkan_ctx_s *ctx, const char *name);
@ -439,8 +456,13 @@ void QFV_BuildRender (struct vulkan_ctx_s *ctx);
void QFV_Render_Init (struct vulkan_ctx_s *ctx);
void QFV_Render_Shutdown (struct vulkan_ctx_s *ctx);
void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys);
void QFV_Render_AddAttachments (struct vulkan_ctx_s *ctx,
uint32_t num_attachments,
qfv_attachmentinfo_t **attachments);
void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx, qfv_renderpass_t *rp);
void QFV_DestroyFramebuffer (struct vulkan_ctx_s *ctx, qfv_renderpass_t *rp);
void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx, qfv_renderpass_t *rp,
VkExtent2D extent);
struct qfv_dsmanager_s *
QFV_Render_DSManager (struct vulkan_ctx_s *ctx,
@ -449,6 +471,12 @@ VkSampler QFV_Render_Sampler (struct vulkan_ctx_s *ctx, const char *name);
qfv_step_t *QFV_GetStep (const exprval_t *param, qfv_job_t *job);
qfv_step_t *QFV_FindStep (const char *step, qfv_job_t *job) __attribute__((pure));
struct qfv_resobj_s *QFV_FindResource (const char *name, qfv_renderpass_t *rp) __attribute__((pure));
struct imui_ctx_s;
void QFV_Render_UI (struct vulkan_ctx_s *ctx, struct imui_ctx_s *imui_ctx);
void QFV_Render_Menu (struct vulkan_ctx_s *ctx, struct imui_ctx_s *imui_ctx);
void QFV_Render_UI_Shutdown (struct vulkan_ctx_s *ctx);
#endif//__QFCC__

View file

@ -25,6 +25,11 @@ typedef struct qfv_stagebuf_s {
void *data;
} qfv_stagebuf_t;
typedef struct qfv_scatter_s {
VkDeviceSize srcOffset;
VkDeviceSize dstOffset;
VkDeviceSize length;
} qfv_scatter_t;
qfv_stagebuf_t *QFV_CreateStagingBuffer (struct qfv_device_s *device,
const char *name, size_t size,
@ -38,6 +43,9 @@ struct qfv_bufferbarrier_s;
void QFV_PacketCopyBuffer (qfv_packet_t *packet,
VkBuffer dstBuffer, VkDeviceSize offset,
const struct qfv_bufferbarrier_s *dstBarrier);
void QFV_PacketScatterBuffer (qfv_packet_t *packet, VkBuffer dstBuffer,
uint32_t count, qfv_scatter_t *scatter,
const struct qfv_bufferbarrier_s *dstBarrier);
struct qfv_imagebarrier_s;
void QFV_PacketCopyImage (qfv_packet_t *packet, VkImage dstImage,
int width, int height,

View file

@ -106,6 +106,9 @@ static struct DARRAY_TYPE(t *) n##_blocks = DARRAY_STATIC_INIT(8)
v = (t *) calloc (1, sizeof (t)); \
} while (0)
#define ALLOC_STATE(t,n) \
static t *n##_freelist;
#define FREE(n, p) do { free (p); } while (0)
#endif

View file

@ -112,7 +112,7 @@ typedef struct lump_s {
\ingroup formats_bsp
*/
///@{
/** Holdes version and lump offset information.
/** Holds version and lump offset information.
Always at offset 0 of the BSP file.
*/
@ -186,7 +186,7 @@ typedef struct dmiptexlump_s {
The beginning of the name of the texture specifies some of the texture's
properties:
- sky The texture is used for the dual-layer skies. Expected
to be 256x128. Sky face get special treatment by the
to be 256x128. Sky faces get special treatment by the
renderer.
- * "Water" face. Texture-warped by the renderer. Usually
unlit (ie, always full-bright).
@ -195,6 +195,7 @@ typedef struct dmiptexlump_s {
the texture belongs and the texture's position in that
sequence. The rest of the name specifies the group name.
\ref bsp_texture_animation
- { Tranclucent surface (community extension).
The texture may be rectangular, but the size must be a multiple of 16
pixels in both directions.
@ -239,7 +240,7 @@ typedef struct dplane_s {
/** \defgroup bsp_plane_definition Plane definitions
\ingroup bsp_planes
Planes are always canonical in that thier normals always point along
Planes are always canonical in that their normals always point along
a positive axis for axial planes ((1, 0, 0), (0, 1, 0), or (0, 0, 1)),
or the largest component is positive.
*/
@ -276,8 +277,8 @@ typedef struct dplane_s {
The node's plane divides the space into a front side and a back side,
where a point is in front of the plane if its dot product with the plane
normal is positive or 0, and ond behind (in back of) the plane if the
dot product is negative.
normal is positive or 0, and behind (in back of) the plane if the dot
product is negative.
*/
typedef struct dnode_s { //BSP2 version (bsp 29 version is in bspfile.c)
uint32_t planenum; ///< Index of plane defining this node
@ -328,7 +329,7 @@ typedef struct texinfo_s {
/// For each index, the first three elements are the X, Y, Z components
/// of the basis vector, and the fourth component is the offset. Can be
/// viewed as a 2 row x 4 column matrix (\a M) that is multiplied by
/// a homogeneos vector (\a v) for a face vertex to determine that
/// a homogeneous vector (\a v) for a face vertex to determine that
/// vertex's UV coordinates (ie, \a M \a v)
float vecs[2][4];
/// Index of the miptex block in the texture data lump
@ -350,7 +351,7 @@ typedef struct texinfo_s {
/** \defgroup bsp_edges BSP edges lump
\ingroup formats_bsp
\note Edge 0 is never used as negative edge indices are indicate
\note Edge 0 is never used as negative edge indices indicate
counterclockwise use of the edge in a face.
*/
///@{

View file

@ -27,6 +27,10 @@
#ifndef __QF_expr_h
#define __QF_expr_h
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
struct exprval_s;
@ -57,7 +61,7 @@ typedef struct exprtype_s {
binop_t *binops;
unop_t *unops;
void *data;
} __attribute__((designated_init)) exprtype_t;
} DESIGNATED_INIT exprtype_t;
typedef struct exprval_s {
exprtype_t *type;

View file

@ -59,7 +59,6 @@ typedef enum {
extern int con_linewidth;
extern struct plugin_s *con_module;
extern struct console_data_s con_data;
//extern int con_totallines;
//extern bool con_initialized;
@ -69,7 +68,7 @@ void Con_DrawConsole (void);
void Con_Printf (const char *fmt, ...) __attribute__((format(PRINTF, 1, 2)));
void Con_Print (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0)));
void Con_SetState (con_state_t state);
void Con_SetState (con_state_t state, bool hide_mouse);
struct inputline_s;
// wrapper function to attempt to either complete the command line

View file

@ -131,6 +131,8 @@ void ECS_DelSubpoolRange (ecs_registry_t *registry, uint32_t component,
uint32_t id);
ECSINLINE ecs_range_t ECS_GetSubpoolRange (ecs_registry_t *registry,
uint32_t component, uint32_t id);
void ECS_MoveSubpoolLast (ecs_registry_t *registry, uint32_t component,
uint32_t id);
#undef ECSINLINE
#ifndef IMPLEMENT_ECS_Funcs

View file

@ -42,6 +42,7 @@
*/
///@{
struct imui_ctx_s;
struct ecs_registry_s;
typedef struct component_s {
size_t size;
@ -51,6 +52,9 @@ typedef struct component_s {
uint32_t (*rangeid) (struct ecs_registry_s *reg, uint32_t ent,
uint32_t comp);
const char *name;
void (*ui) (void *comp, struct imui_ctx_s *imui_ctx,
struct ecs_registry_s *reg, uint32_t ent,
void *data);
} component_t;
#define COMPINLINE GNU89INLINE inline
@ -60,6 +64,9 @@ COMPINLINE void Component_ResizeArray (const component_t *component,
COMPINLINE void *Component_MoveElements (const component_t *component,
void *array, uint32_t dstIndex,
uint32_t srcIndex, uint32_t count);
COMPINLINE void Component_RotateElements (const component_t *component,
void *array, uint32_t dstIndex,
uint32_t srcIndex, uint32_t count);
COMPINLINE void Component_SwapElements (const component_t *component,
void *a, void *b);
COMPINLINE void *Component_CopyElements (const component_t *component,
@ -98,6 +105,49 @@ Component_MoveElements (const component_t *component,
return memmove (dst, src, count * component->size);
}
COMPINLINE void
Component_RotateElements (const component_t *component,
void *array, uint32_t dstIndex, uint32_t srcIndex,
uint32_t count)
{
if (dstIndex == srcIndex) {
puts ("a");
return;
}
auto dst = (byte *) array + dstIndex * component->size;
auto src = (byte *) array + srcIndex * component->size;
size_t countSize = count * component->size;
if (dstIndex < srcIndex) {
uint32_t bcount = srcIndex - dstIndex;
size_t bcountSize = bcount * component->size;
if (count < bcount) {
byte tmp[countSize];
memcpy (tmp, src, countSize);
memmove (dst + countSize, dst, bcountSize);
memcpy (dst, tmp, countSize);
} else {
byte tmp[bcountSize];
memcpy (tmp, dst, bcountSize);
memmove (dst, src, countSize);
memcpy (dst + countSize, tmp, bcountSize);
}
} else if (dstIndex < srcIndex + count) {
uint32_t bcount = dstIndex - srcIndex;
size_t bcountSize = bcount * component->size;
byte tmp[bcountSize];
memcpy (tmp, src + countSize, bcountSize);
memmove (dst, src, countSize);
memcpy (src, tmp, bcountSize);
} else {
uint32_t bcount = dstIndex - srcIndex;
size_t bcountSize = bcount * component->size;
byte tmp[countSize];
memcpy (tmp, src, countSize);
memmove (src, src + countSize, bcountSize);
memcpy (dst, tmp, countSize);
}
}
COMPINLINE void
Component_SwapElements (const component_t *component, void *a, void *b)
{

View file

@ -48,11 +48,13 @@ ENTINLINE uint32_t Ent_Generation (uint32_t id);
ENTINLINE uint32_t Ent_NextGen (uint32_t id);
ENTINLINE int Ent_HasComponent (uint32_t ent, uint32_t comp,
ecs_registry_t *reg);
ecs_registry_t *reg);
ENTINLINE void *Ent_GetComponent (uint32_t ent, uint32_t comp,
ecs_registry_t *reg);
ecs_registry_t *reg);
ENTINLINE void *Ent_SafeGetComponent (uint32_t ent, uint32_t comp,
ecs_registry_t *reg);
ENTINLINE void *Ent_SetComponent (uint32_t ent, uint32_t comp,
ecs_registry_t *registry, const void *data);
ecs_registry_t *registry, const void *data);
#undef ENTINLINE
#ifndef IMPLEMENT_ECS_ENTITY_Funcs
@ -103,6 +105,18 @@ Ent_GetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg)
return data + ind * component->size;
}
ENTINLINE void *
Ent_SafeGetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg)
{
if (!ECS_EntValid (ent, reg) || !Ent_HasComponent (ent, comp, reg)) {
return 0;
}
const component_t *component = &reg->components.a[comp];
uint32_t ind = reg->comp_pools[comp].sparse[Ent_Index (ent)];
byte *data = reg->comp_pools[comp].data;
return data + ind * component->size;
}
void *Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry);
void Ent_RemoveComponent (uint32_t ent, uint32_t comp,
ecs_registry_t *registry);

View file

@ -57,18 +57,24 @@ typedef struct hierarchy_s {
uint32_t *childCount;
uint32_t *childIndex;
uint32_t *parentIndex;
uint32_t *nextIndex;
uint32_t *lastIndex;
const hierarchy_type_t *type;
void **components;
struct ecs_registry_s *reg;
uint32_t href_comp;
bool tree_mode; // use for fast building
} hierarchy_t;
#define nullindex (~0u)
hierarchy_t *Hierarchy_New (struct ecs_registry_s *reg, uint32_t href_comp,
const hierarchy_type_t *type, int createRoot);
void Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count);
hierarchy_t *Hierarchy_Copy (struct ecs_registry_s *reg, uint32_t href_comp,
const hierarchy_t *src);
void Hierarchy_Delete (hierarchy_t *hierarchy);
void Hierarchy_SetTreeMode (hierarchy_t *hierarchy, bool tree_mode);
uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src,
uint32_t dstParent, uint32_t srcRoot);

View file

@ -349,7 +349,11 @@ IN_ClampAxis (in_axis_t *axis, float minval, float maxval)
void IN_ButtonAction (in_button_t *buttin, int id, int pressed);
int IN_RegisterButton (in_button_t *button);
int IN_UnregisterButton (in_button_t *button);
void IN_ButtonInit (void);
int IN_RegisterAxis (in_axis_t *axis);
int IN_UnregisterAxis (in_axis_t *axis);
void IN_AxisInit (void);
in_button_t *IN_FindButton (const char *name);
void IN_ButtonClearStates (void);
in_axis_t *IN_FindAxis (const char *name);
@ -367,7 +371,6 @@ struct IE_event_s;
int IN_Binding_HandleEvent (const struct IE_event_s *ie_event);
void IN_Binding_Activate (void);
void IN_Binding_Init (void);
void IN_Binding_Shutdown (void);
struct plitem_s;
void IN_Binding_SaveConfig (struct plitem_s *config);
void IN_Binding_LoadConfig (struct plitem_s *config);

View file

@ -48,6 +48,7 @@ typedef enum {
ies_capslock = 2,
ies_control = 4,
ies_alt = 8,
ies_numlock = 16,
} IE_shift;
typedef enum {
@ -121,6 +122,7 @@ typedef struct IE_event_s {
typedef int ie_handler_t (const IE_event_t *, void *data);
void IN_Event_Init (void);
int IE_Send_Event (const IE_event_t *event);
int IE_Add_Handler (ie_handler_t *event_handler, void *data);
void IE_Remove_Handler (int handle);

View file

@ -130,7 +130,6 @@ void IMT_BindButton (imt_t *imt, int button, const char *binding);
bool IMT_ProcessAxis (int axis, int value);
bool IMT_ProcessButton (int button, int state);
void IMT_Init (void);
void IMT_Shutdown (void);
struct plitem_s;
void IMT_SaveConfig (struct plitem_s *config);
void IMT_SaveAxisConfig (struct plitem_s *axes, int axis_ind, int dev_axis);

View file

@ -31,7 +31,7 @@ typedef struct iqmmesh_s {
uint32_t first_triangle, num_triangles;
} iqmmesh;
enum {
typedef enum : uint32_t {
IQM_POSITION = 0,
IQM_TEXCOORD = 1,
IQM_NORMAL = 2,
@ -40,9 +40,9 @@ enum {
IQM_BLENDWEIGHTS = 5,
IQM_COLOR = 6,
IQM_CUSTOM = 0x10
};
} iqmverttype;
enum {
typedef enum : uint32_t {
IQM_BYTE = 0,
IQM_UBYTE = 1,
IQM_SHORT = 2,
@ -52,7 +52,7 @@ enum {
IQM_HALF = 6,
IQM_FLOAT = 7,
IQM_DOUBLE = 8
};
} iqmformat;
typedef struct iqmtriangle_s {
uint32_t vertex[3];
@ -84,21 +84,21 @@ typedef struct iqmpose_s {
float channelscale[10];
} iqmpose;
typedef enum : uint32_t {
IQM_LOOP = 1<<0
} iqmanimflags;
typedef struct iqmanim_s {
uint32_t name;
uint32_t first_frame, num_frames;
float framerate;
uint32_t flags;
iqmanimflags flags;
} iqmanim;
enum {
IQM_LOOP = 1<<0
};
typedef struct iqmvertexarray_s {
uint32_t type;
iqmverttype type;
uint32_t flags;
uint32_t format;
iqmformat format;
uint32_t size;
uint32_t offset;
} iqmvertexarray;

View file

@ -79,7 +79,7 @@ typedef struct instsurf_s {
struct instsurf_s *tex_chain; ///< next in texture chain
struct instsurf_s *lm_chain; ///< next in lightmap chain
struct msurface_s *surface; ///< surface to render
vec4f_t *transform;
const vec4f_t *transform;
float *color;
} instsurf_t;
@ -369,18 +369,22 @@ typedef enum {
mod_alias,
mod_iqm,
mod_light,
mod_num_types
} modtype_t;
#define EF_ROCKET 1 // leave a trail
#define EF_GRENADE 2 // leave a trail
#define EF_GIB 4 // leave a trail
#define EF_ROTATE 8 // rotate (bonus items)
#define EF_TRACER 16 // green split trail
#define EF_ZOMGIB 32 // small blood trail
#define EF_TRACER2 64 // orange split trail + rotate
#define EF_TRACER3 128 // purple trail
#define EF_GLOWTRAIL 4096 // glowcolor particle trail
typedef enum {
ME_ROCKET = 1, // leave a trail
ME_GRENADE = 2, // leave a trail
ME_GIB = 4, // leave a trail
ME_ROTATE = 8, // rotate (bonus items)
ME_TRACER = 16, // green split trail
ME_ZOMGIB = 32, // small blood trail
ME_TRACER2 = 64, // orange split trail + rotate
ME_TRACER3 = 128, // purple trail
ME_GLOWTRAIL = 4096, // glowcolor particle trail
} modeffects_t;
typedef struct model_s {
//FIXME use pointers. needs care in bsp submodel loading
@ -389,13 +393,12 @@ typedef struct model_s {
const struct vpath_s *vpath;// virtual path where this model was found
bool needload; // bmodels and sprites don't cache normally
aliashdr_t *aliashdr; // if not null, alias model is not cached
bool hasfullbrights;
modtype_t type;
int numframes;
synctype_t synctype;
int flags;
modeffects_t effects;
// lighting info
float min_light;
@ -407,10 +410,6 @@ typedef struct model_s {
// FIXME: bbox cruft has to stay until sw rendering gets updated
vec3_t mins, maxs;
// solid volume for clipping
bool clipbox;
vec3_t clipmins, clipmaxs;
// brush model
//FIXME should be a pointer (submodels make things tricky)
mod_brush_t brush;
@ -432,13 +431,12 @@ model_t *Mod_ForName (const char *name, bool crash);
void Mod_TouchModel (const char *name);
void Mod_UnloadModel (model_t *model);
// brush specific
mleaf_t *Mod_PointInLeaf (vec4f_t p, model_t *model) __attribute__((pure));
struct set_s *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model);
void Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis,
struct set_s *pvs);
void Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis,
struct set_s *pvs);
mleaf_t *Mod_PointInLeaf (vec4f_t p, const mod_brush_t *brush) __attribute__((pure));
struct set_s;
void Mod_LeafPVS_set (const mleaf_t *leaf, const mod_brush_t *brush,
byte defvis, struct set_s *pvs);
void Mod_LeafPVS_mix (const mleaf_t *leaf, const mod_brush_t *brush,
byte defvis, struct set_s *pvs);
void Mod_Print (void);

View file

@ -39,7 +39,7 @@ typedef struct console_funcs_s {
void (*process_input) (void);
void (*draw_console) (void);
void (*new_map) (void);
void (*set_state) (con_state_t state);
void (*set_state) (con_state_t state, bool hide_mouse);
} console_funcs_t;
typedef struct console_data_s {

View file

@ -83,13 +83,13 @@ typedef struct vid_model_funcs_s {
struct tex_s;
struct font_s;
struct draw_charbuffer_s;
struct imui_ctx_s;
typedef void (*capfunc_t) (struct tex_s *screencap, void *data);
typedef struct vid_render_funcs_s {
void (*init) (void);
void (*UpdateScreen) (struct transform_s camera, double realtime,
SCR_Func *scr_funcs);
void (*UpdateScreen) (SCR_Func *scr_funcs);
void (*Draw_CharBuffer) (int x, int y, struct draw_charbuffer_s *buffer);
void (*Draw_SetScale) (int scale);
void (*Draw_Character) (int x, int y, unsigned ch);
@ -117,7 +117,6 @@ typedef struct vid_render_funcs_s {
int (*Draw_AddFont) (struct font_s *font);
void (*Draw_Glyph) (int x, int y, int fontid, int glyphid, int c);
struct psystem_s *(*ParticleSystem) (void);
void (*R_Init) (void);
void (*R_ClearState) (void);
@ -143,6 +142,8 @@ typedef struct vid_render_funcs_s {
void (*capture_screen) (capfunc_t callback, void *data);
void (*debug_ui) (struct imui_ctx_s *imui_ctx);
vid_model_funcs_t *model_funcs;
} vid_render_funcs_t;

View file

@ -96,7 +96,7 @@ extern const char * const pr_type_name[ev_type_count];
#define RESERVED_OFS 28
typedef enum {
typedef enum : pr_ushort_t {
OP_DONE_v6p,
OP_MUL_F_v6p,
OP_MUL_V_v6p,
@ -432,7 +432,7 @@ typedef enum {
} pr_opcode_v6p_e;
#define OP_BREAK 0x8000
typedef enum {
typedef enum : pr_ushort_t {
#ifndef IN_DOXYGEN
#include "QF/progs/pr_opcode.hinc"
#endif
@ -489,8 +489,8 @@ extern const opcode_t pr_opcodes[512];
const opcode_t *PR_Opcode (pr_ushort_t opcode) __attribute__((const));
typedef struct dstatement_s {
pr_opcode_e op:16; // will be pr_opcode_v6p_e for older progs
pr_ushort_t a,b,c;
pr_opcode_e op; // will be pr_opcode_v6p_e for older progs
pr_short_t a,b,c;
} GCC_STRUCT dstatement_t;
typedef struct ddef_s {
@ -563,7 +563,7 @@ typedef struct pr_va_list_s {
|(((0x##c) & 0xfff) << 0) )
#define PROG_ID_VERSION 6
#define PROG_V6P_VERSION PROG_VERSION_ENCODE(0,fff,00a)
#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,010)
#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,011)
typedef struct pr_chunk_s {
pr_uint_t offset;

View file

@ -49,6 +49,7 @@ typedef enum {
ty_class,
ty_alias,
ty_handle,
ty_algebra,
} ty_meta_e;
typedef struct qfot_alias_s {
@ -105,6 +106,13 @@ typedef struct qfot_array_s {
pr_int_t size; ///< number of elements in array
} qfot_array_t;
typedef struct qfot_algebra_s {
etype_t type; ///< always ev_float or ev_double
pr_int_t width; ///< components in multivector
pr_ptr_t algebra; ///< algebra descriptor
pr_int_t element; ///< element within algebra
} qfot_algebra_t;
/** QFO type encoding.
\note As this holds a union of all type representations, and those
@ -126,6 +134,7 @@ typedef struct qfot_type_s {
pr_string_t class; ///< ty_class
qfot_alias_t alias; ///< ty_alias
qfot_handle_t handle; ///< ty_handle
qfot_algebra_t algebra; ///< ty_algebra
};
} qfot_type_t;

View file

@ -52,22 +52,6 @@
typedef uint8_t byte;
#endif
#if __STDC_VERSION__ < 202000
#define auto __auto_type
#ifndef _DEF_BOOL_
# define _DEF_BOOL_
// KJB Undefined true and false defined in SciTech's DEBUG.H header
# ifdef __cplusplus
# define __bool_true_false_are_defined
# endif
# ifndef __bool_true_false_are_defined
# undef true
# undef false
typedef enum {false, true} bool;
# endif
#endif
#endif
// From mathlib...
typedef float vec_t; ///< The basic vector component type
typedef vec_t vec3_t[3]; ///< A 3D vector (used for Euler angles and motion vectors)

View file

@ -96,22 +96,16 @@ typedef struct subpic_s {
// dynamic lights ===========================================================
typedef struct dlight_s
{
int key; // so entities can reuse same entry
vec3_t origin;
typedef struct dlight_s {
vec4f_t origin;
vec4f_t color;
float radius;
float die; // stop lighting after this time
float decay; // drop this each second
float minlight; // don't add when contributing less
float color[4];
} dlight_t;
extern dlight_t *r_dlights;
extern unsigned int r_maxdlights;
typedef struct
{
typedef struct {
int length;
char map[MAX_STYLESTRING];
char average;
@ -180,8 +174,6 @@ void R_LoadModule (struct vid_internal_s *vid_internal);
struct progs_s;
void R_Progs_Init (struct progs_s *pr);
dlight_t *R_AllocDlight (int key);
void R_DecayLights (double frametime);
void Fog_Update (float density, float red, float green, float blue,
float time);
struct plitem_s;

View file

@ -75,12 +75,14 @@ typedef struct visibility_s {
typedef struct renderer_s {
struct model_s *model; // NULL = no model
struct skin_s *skin;
unsigned fullbright:1;
unsigned noshadows:1;
unsigned onlyshadows:1;
unsigned depthhack:1;
float colormod[4]; // color tint and alpha for model
int skinnum; // for Alias models
int fullbright;
float min_light;
int render_id;
mat4f_t full_transform;
} renderer_t;
typedef struct entityset_s DARRAY_TYPE (entity_t) entityset_t;
@ -150,6 +152,8 @@ Entity_Transform (entity_t ent)
}
struct mod_brush_s;
efrag_t **R_LinkEfrag (struct mleaf_s *leaf, entity_t ent, uint32_t queue,
efrag_t **lastlink);
void R_AddEfrags (struct mod_brush_s *, entity_t ent);
void R_ShutdownEfrags (void);
void R_ClearEfragChain (efrag_t *ef);

View file

@ -53,15 +53,7 @@ typedef struct light_s {
vec4f_t attenuation;
} light_t;
typedef struct lightset_s DARRAY_TYPE (light_t) lightset_t;
typedef struct lightleafset_s DARRAY_TYPE (int) lightintset_t;
typedef struct lightvisset_s DARRAY_TYPE (byte) lightvisset_t;
typedef struct lightingdata_s {
lightset_t lights;
lightintset_t lightstyles;
lightintset_t lightleafs;
lightvisset_t lightvis;
struct set_s *sun_pvs;
// A fat PVS of leafs visible from visible leafs so hidden lights can
// illuminate the leafs visible to the player
@ -73,8 +65,11 @@ typedef struct lightingdata_s {
lightingdata_t *Light_CreateLightingData (struct scene_s *scene);
void Light_DestroyLightingData (lightingdata_t *ldata);
void Light_ClearLights (lightingdata_t *ldata);
void Light_AddLight (lightingdata_t *ldata, const light_t *light, int style);
void Light_AddLight (lightingdata_t *ldata, const light_t *light,
uint32_t style);
void Light_EnableSun (lightingdata_t *ldata);
void Light_FindVisibleLights (lightingdata_t *ldata);
void Light_DecayLights (lightingdata_t *ldata, float frametime,
double realtime);
void Light_LinkLight (lightingdata_t *ldata, uint32_t entid);
#endif//__QF_scene_light_h

View file

@ -49,6 +49,14 @@ enum scene_components {
scene_old_origin, //XXX FIXME XXX should not be here
scene_colormap,
scene_dynlight,
scene_light,
scene_efrags,
scene_lightstyle,
scene_lightleaf,
scene_lightid,
//FIXME these should probably be private to the sw renderer (and in a
//group, which needs to be implemented), but need to sort out a good
//scheme for semi-dynamic components
@ -69,7 +77,13 @@ typedef struct scene_s {
struct lightingdata_s *lights;
} scene_t;
scene_t *Scene_NewScene (void);
typedef struct scene_system_s {
struct ecs_system_s *system;
const struct component_s *components;
uint32_t component_count;
} scene_system_t;
scene_t *Scene_NewScene (scene_system_t *extra_systems);
void Scene_DeleteScene (scene_t *scene);
struct entity_s Scene_CreateEntity (scene_t *scene);
void Scene_DestroyEntity (scene_t *scene, struct entity_s entity);

View file

@ -40,8 +40,7 @@ typedef void (*SCR_Func)(void);
// scr_funcs is a null terminated array
void SCR_UpdateScreen (struct transform_s camera, double realtime,
SCR_Func *scr_funcs);
void SCR_UpdateScreen_legacy (struct transform_s camera, double realtime,
SCR_Func *scr_funcs);
void SCR_UpdateScreen_legacy (SCR_Func *scr_funcs);
void SCR_SetFOV (float fov);
// control whether the 3d viewport is user-controlled or always fullscreen
void SCR_SetFullscreen (bool fullscreen);
@ -54,6 +53,10 @@ extern int r_zgraph;
extern int scr_copytop;
extern bool scr_skipupdate;
extern bool r_lock_viewleaf;
extern bool r_override_camera;
extern struct transform_s r_camera;
struct view_pos_s;
void R_TimeGraph (struct view_pos_s abs, struct view_pos_s len);
void R_ZGraph (struct view_pos_s abs, struct view_pos_s len);

View file

@ -47,7 +47,7 @@ extern int sys_sleep;
extern int developer;
extern bool sys_quake_encoding;
extern const char sys_char_map[256];
typedef struct date_s {
@ -131,6 +131,8 @@ size_t Sys_PageSize (void);
void *Sys_Alloc (size_t size);
void Sys_Free (void *mem, size_t size);
int Sys_LockMemory (void *mem, size_t size);
size_t Sys_PeakRSS (void);
size_t Sys_CurrentRSS (void);
int Sys_ProcessorCount (void);

View file

@ -44,18 +44,26 @@ enum {
canvas_cachepic,
canvas_fill,
canvas_charbuff,
canvas_passage_glyphs, // copy of text_passage_glyphs
canvas_glyphs, // copy of text_passage_glyphs
canvas_func,
canvas_outline,
canvas_lateupdate,
// last so deleting an entity removes the grouped components first
// also, does not have a subpool
canvas_canvas,
canvas_comp_count
};
typedef struct canvas_s {
uint32_t range[canvas_comp_count];
ecs_registry_t *reg;
uint32_t base;
int16_t draw_order;
int16_t draw_group;
bool visible;
uint32_t range[canvas_canvas];
} canvas_t;
extern const struct component_s canvas_components[canvas_comp_count];
@ -65,6 +73,7 @@ typedef struct canvas_system_s {
uint32_t base;
uint32_t view_base;
uint32_t text_base;
uint32_t imui_base;
} canvas_system_t;
struct view_s;
@ -87,9 +96,15 @@ uint32_t Canvas_New (canvas_system_t canvas_sys);
void Canvas_Draw (canvas_system_t canvas_sys);
void Canvas_SortComponentPool (canvas_system_t canvas_sys, uint32_t ent,
uint32_t component);
void Canvas_SetLen (canvas_system_t canvas_sys, view_pos_t len);
void Canvas_SetLen (canvas_system_t canvas_sys, uint32_t ent, view_pos_t len);
CANVASINLINE view_t Canvas_GetRootView (canvas_system_t canvas_sys,
uint32_t ent);
CANVASINLINE bool *Canvas_Visible (canvas_system_t canvas_sys, uint32_t ent);
CANVASINLINE int16_t *Canvas_DrawGroup (canvas_system_t canvas_sys,
uint32_t ent);
CANVASINLINE int16_t *Canvas_DrawOrder (canvas_system_t canvas_sys,
uint32_t ent);
void Canvas_DrawSort (canvas_system_t canvas_sys);
#undef CANVASINLINE
#ifndef IMPLEMENT_CANVAS_Funcs
@ -106,6 +121,33 @@ Canvas_GetRootView (canvas_system_t canvas_sys, uint32_t ent)
return View_FromEntity (viewsys, ent);
}
CANVASINLINE
bool *
Canvas_Visible (canvas_system_t canvas_sys, uint32_t ent)
{
uint32_t comp = canvas_sys.base + canvas_canvas;
auto canvas = (canvas_t *) Ent_GetComponent (ent, comp, canvas_sys.reg);
return &canvas->visible;
}
CANVASINLINE
int16_t *
Canvas_DrawGroup (canvas_system_t canvas_sys, uint32_t ent)
{
uint32_t comp = canvas_sys.base + canvas_canvas;
auto canvas = (canvas_t *) Ent_GetComponent (ent, comp, canvas_sys.reg);
return &canvas->draw_group;
}
CANVASINLINE
int16_t *
Canvas_DrawOrder (canvas_system_t canvas_sys, uint32_t ent)
{
uint32_t comp = canvas_sys.base + canvas_canvas;
auto canvas = (canvas_t *) Ent_GetComponent (ent, comp, canvas_sys.reg);
return &canvas->draw_order;
}
#undef CANVASINLINE
#endif//__QF_scene_canvas_h

View file

@ -57,5 +57,7 @@ typedef struct font_s {
void Font_Init (void);
void Font_Free (font_t *font);
font_t *Font_Load (QFile *font_file, int size);
// free the returned string
char *Font_SystemFont (const char *font_pattern);
#endif//__QF_ui_font_h

208
include/QF/ui/imui.h Normal file
View file

@ -0,0 +1,208 @@
/*
imui.h
Immediate mode user interface
Copyright (C) 2023 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2023/07/01
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef __QF_ui_imui_h
#define __QF_ui_imui_h
#include "QF/ui/view.h"
typedef struct imui_ctx_s imui_ctx_t;
struct canvas_system_s;
struct IE_event_s;
enum {
imui_percent_x, ///< int
imui_percent_y, ///< int
imui_reference, ///< imui_reference_t
imui_comp_count
};
extern const component_t imui_components[imui_comp_count];
typedef enum {
imui_size_none,
imui_size_pixels,
imui_size_fittext,
imui_size_percent,
imui_size_fitchildren,
imui_size_expand,
} imui_size_t;
typedef union imui_color_s {
struct {
uint32_t normal;
uint32_t hot;
uint32_t active;
};
uint32_t color[3];
} imui_color_t;
typedef struct imui_style_s {
imui_color_t background;
imui_color_t foreground;
imui_color_t text;
} imui_style_t;
typedef struct imui_reference_s {
uint32_t ref_id;
} imui_reference_t;
typedef struct imui_window_s {
const char *name;
int xpos;
int ypos;
int xlen;
int ylen;
int group_offset;
int mode;
bool is_open;
bool is_collapsed;
const char *reference;
grav_t reference_gravity;
grav_t anchor_gravity;
struct imui_window_s *parent; // for submenus
bool no_collapse;
} imui_window_t;
typedef struct imui_io_s {
view_pos_t mouse;
uint32_t buttons;
uint32_t pressed;
uint32_t released;
uint32_t hot;
uint32_t active;
} imui_io_t;
imui_ctx_t *IMUI_NewContext (struct canvas_system_s canvas_sys,
const char *font, float fontsize);
void IMUI_DestroyContext (imui_ctx_t *ctx);
void IMUI_SetVisible (imui_ctx_t *ctx, bool visible);
void IMUI_SetSize (imui_ctx_t *ctx, int xlen, int ylen);
bool IMUI_ProcessEvent (imui_ctx_t *ctx, const struct IE_event_s *ie_event);
imui_io_t IMUI_GetIO (imui_ctx_t *ctx) __attribute__((pure));
void IMUI_BeginFrame (imui_ctx_t *ctx);
void IMUI_Draw (imui_ctx_t *ctx);
int IMUI_PushLayout (imui_ctx_t *ctx, bool vertical);
void IMUI_PopLayout (imui_ctx_t *ctx);
void IMUI_Layout_SetXSize (imui_ctx_t *ctx, imui_size_t size, int value);
void IMUI_Layout_SetYSize (imui_ctx_t *ctx, imui_size_t size, int value);
int IMUI_PushStyle (imui_ctx_t *ctx, const imui_style_t *style);
void IMUI_PopStyle (imui_ctx_t *ctx);
void IMUI_Style_Update (imui_ctx_t *ctx, const imui_style_t *style);
void IMUI_Style_Fetch (const imui_ctx_t *ctx, imui_style_t *style);
void IMUI_Label (imui_ctx_t *ctx, const char *label);
void IMUI_Labelf (imui_ctx_t *ctx, const char *fmt, ...)__attribute__((format(PRINTF,2,3)));
bool IMUI_Button (imui_ctx_t *ctx, const char *label);
bool IMUI_Checkbox (imui_ctx_t *ctx, bool *flag, const char *label);
void IMUI_Radio (imui_ctx_t *ctx, int *curvalue, int value, const char *label);
void IMUI_Slider (imui_ctx_t *ctx, float *value, float minval, float maxval,
const char *label);
void IMUI_Spacer (imui_ctx_t *ctx,
imui_size_t xsize, int xvalue,
imui_size_t ysize, int yvalue);
int IMUI_StartPanel (imui_ctx_t *ctx, imui_window_t *panel);
int IMUI_ExtendPanel (imui_ctx_t *ctx, const char *panel_name);
void IMUI_EndPanel (imui_ctx_t *ctx);
int IMUI_StartMenu (imui_ctx_t *ctx, imui_window_t *menu, bool vertical);
void IMUI_EndMenu (imui_ctx_t *ctx);
bool IMUI_MenuItem (imui_ctx_t *ctx, const char *label, bool collapse);
int IMUI_StartWindow (imui_ctx_t *ctx, imui_window_t *window);
void IMUI_EndWindow (imui_ctx_t *ctx);
#define IMUI_DeferLoop(begin, end) \
for (int _i_ = (begin); !_i_; _i_++, (end))
// #define IMUI_context to an imui_ctx_t * variable
#define UI_Label(label) \
IMUI_Label(IMUI_context, label)
#define UI_Labelf(fmt...) \
IMUI_Labelf(IMUI_context, fmt)
#define UI_Button(label) \
IMUI_Button(IMUI_context, label)
#define UI_Checkbox(flag, label) \
IMUI_Checkbox(IMUI_context, flag, label)
#define UI_Radio(state, value, label) \
IMUI_Radio(IMUI_context, state, value, label)
#define UI_Slider(value, minval, maxval, label) \
IMUI_Slider(IMUI_context, value, minval, maxval, label)
#define UI_FlexibleSpace() \
IMUI_Spacer(IMUI_context, imui_size_expand, 100, imui_size_expand, 100)
#define UI_Layout(vertical) \
IMUI_DeferLoop (IMUI_PushLayout (IMUI_context, vertical), \
IMUI_PopLayout (IMUI_context ))
#define UI_Panel(panel) \
IMUI_DeferLoop (IMUI_StartPanel (IMUI_context, panel), \
IMUI_EndPanel (IMUI_context))
#define UI_ExtendPanel(panel_name) \
IMUI_DeferLoop (IMUI_ExtendPanel (IMUI_context, panel_name), \
IMUI_EndPanel (IMUI_context))
#define UI_Menu(menu) \
IMUI_DeferLoop (IMUI_StartMenu (IMUI_context, menu, true), \
IMUI_EndMenu (IMUI_context))
#define UI_MenuBar(menu) \
IMUI_DeferLoop (IMUI_StartMenu (IMUI_context, menu, false), \
IMUI_EndMenu (IMUI_context))
#define UI_MenuItem(label) \
IMUI_MenuItem (IMUI_context, label, true)
#define UI_Window(window) \
IMUI_DeferLoop (IMUI_StartWindow (IMUI_context, window), \
IMUI_EndWindow (IMUI_context))
#define UI_Style(style) \
IMUI_DeferLoop (IMUI_PushStyle (IMUI_context, style), \
IMUI_PopStyle (IMUI_context ))
#define UI_Horizontal UI_Layout(false)
#define UI_Vertical UI_Layout(true)
#endif//__QF_ui_imui_h

58
include/QF/ui/shaper.h Normal file
View file

@ -0,0 +1,58 @@
/*
shaper.h
Text shaping system
Copyright (C) 2023 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2023/07/07
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef __QF_ui_shaper_h
#define __QF_ui_shaper_h
#include "QF/ui/text.h"
typedef struct text_shaper_s text_shaper_t;
typedef struct shaped_glyphs_s {
const hb_glyph_info_t *glyphInfo;
const hb_glyph_position_t *glyphPos;
unsigned count;
} shaped_glyphs_t;
typedef struct shaping_s {
const script_component_t *script;
const featureset_t *features;
const struct font_s *font;
} shaping_t;
text_shaper_t *Shaper_New (void);
void Shaper_Delete (text_shaper_t *shaper);
void Shaper_FlushUnused (text_shaper_t *shaper);
shaped_glyphs_t Shaper_ShapeText (text_shaper_t *shaper,
const shaping_t *control,
const char *text, size_t text_len);
#endif//__QF_ui_shaper_h

View file

@ -77,9 +77,11 @@ enum {
text_passage_glyphs,
// glyphs for a single text object
text_glyphs,
// tint color for glyphs
text_color,
// text_script, text_font and text_features on the passage root object set
// the defaults for all text objects in the passage. The settings can be
// overridden at the paragraph level or individiual text object level by
// overridden at the paragraph level or individual text object level by
// adding the appropriate component to that text object.
// script settings for the text object
text_script,
@ -104,16 +106,28 @@ extern hb_feature_t CligOn;
struct font_s;
struct passage_s;
struct text_shaper_s;
struct view_s Text_View (ecs_system_t viewsys,
struct font_s *font, struct passage_s *passage);
void Text_SetScript (ecs_system_t textsys, uint32_t textid,
typedef struct text_system_s {
ecs_registry_t *reg;
uint32_t view_base;
uint32_t text_base;
} text_system_t;
struct view_s Text_PassageView (text_system_t textsys,
struct font_s *font, struct passage_s *passage);
struct view_s Text_StringView (text_system_t textsys, struct view_s parent,
struct font_s *font,
const char *str, uint32_t len,
script_component_t *sc, featureset_t *fs,
struct text_shaper_s *shaper);
void Text_SetScript (text_system_t textsys, uint32_t textid,
const char *lang, hb_script_t script, text_dir_e dir);
void Text_SetFont (ecs_system_t textsys, uint32_t textid,
void Text_SetFont (text_system_t textsys, uint32_t textid,
struct font_s *font);
void Text_SetFeatures (ecs_system_t textsys, uint32_t textid,
void Text_SetFeatures (text_system_t textsys, uint32_t textid,
featureset_t *features);
void Text_AddFeature (ecs_system_t textsys, uint32_t textid,
void Text_AddFeature (text_system_t textsys, uint32_t textid,
hb_feature_t feature);
#endif//__QF_ui_text_h

View file

@ -83,6 +83,12 @@ typedef struct viewcont_s {
unsigned resize_y:1; ///< If true, view's height follows parent's.
unsigned bol_suppress:1; ///< If true, view_flow skips at start of line.
unsigned flow_size:1; ///< If true, view's size is adjusted to flow.
unsigned semantic_x:3; ///< layout size control (IMUI_SizeKind)
unsigned semantic_y:3; ///< layout size control (IMUI_SizeKind)
unsigned free_x:1; ///< don't set position automatically
unsigned free_y:1; ///< don't set position automatically
unsigned vertical:1; ///< true: layout is vertical, else horizontal
unsigned active:1; ///< can respond to the mouse
} viewcont_t;
enum {
@ -160,7 +166,7 @@ VIEWINLINE view_pos_t View_GetAbs (view_t view);
VIEWINLINE view_pos_t View_GetRel (view_t view);
VIEWINLINE void View_SetLen (view_t view, int x, int y);
VIEWINLINE view_pos_t View_GetLen (view_t view);
VIEWINLINE viewcont_t* View_Control (view_t view);
VIEWINLINE viewcont_t *View_Control (view_t view);
VIEWINLINE void View_SetGravity (view_t view, grav_t grav);
VIEWINLINE grav_t View_GetGravity (view_t view);
VIEWINLINE void View_SetVisible (view_t view, int visible);

View file

@ -45,6 +45,8 @@ typedef struct {
unsigned short *colormap16; // 256 * VID_GRADES size
unsigned int *colormap32; // 256 * VID_GRADES size
int fullbright; // index of first fullbright color
int x;
int y;
unsigned width;
unsigned height;
int numpages;
@ -71,8 +73,10 @@ void VID_Init_Cvars (void);
// the palette data will go away after the call, so it must be copied off if
// the video driver will need it again
void VID_Init (byte *palette, byte *colormap);
void VID_SendSize (void);
void VID_SetPalette (byte *palette, byte *colormap);
void VID_SetCaption (const char *text);
void VID_SetCursor (bool visible);
void VID_ClearMemory (void);
void VID_OnPaletteChange_AddListener (viddef_listener_t listener, void *data);

13
include/cl_console.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef __cl_console_h
#define __cl_console_h
extern struct console_data_s con_data;
extern bool con_debug;
void Con_Debug_Init (void);
void Con_Debug_InitCvars (void);
void Con_Debug_Shutdown (void);
void Con_Debug_Draw (void);
void Con_Show_Mouse (bool visible);
#endif//__cl_console_h

View file

@ -31,17 +31,28 @@
#define __client_effects_h
#include "QF/simd/types.h"
#include "QF/ecs/component.h"
enum {
effect_light, // light entity id
effect_muzzleflash, // light entity id
effect_comp_count,
};
extern const component_t effect_components[effect_comp_count];
extern struct ecs_system_s effect_system;
struct entity_s;
struct entity_state_s;
void CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size,
byte glow_color, double time);
void CL_ModelEffects (struct entity_s ent, int num, int glow_color,
void CL_NewDlight (struct entity_s ent, vec4f_t org, int effects,
byte glow_size, byte glow_color, double time);
void CL_ModelEffects (struct entity_s ent, int glow_color,
double time);
void CL_EntityEffects (int num, struct entity_s ent,
struct entity_state_s *state, double time);
void CL_MuzzleFlash (vec4f_t position, vec4f_t fv, float zoffset, int num,
double time);
void CL_EntityEffects (struct entity_s ent, struct entity_state_s *state,
double time);
void CL_MuzzleFlash (struct entity_s ent, vec4f_t position, vec4f_t fv,
float zoffset, double time);
#endif//__client_effects_h

View file

@ -101,7 +101,9 @@ typedef struct viewstate_s {
#define VF_GIB 2
struct msg_s;
struct scene_s;
void V_NewScene (viewstate_t *vs, struct scene_s *scene);
void V_Init (viewstate_t *vs);
void V_Init_Cvars (void);
void V_RenderView (viewstate_t *vs);

View file

@ -66,6 +66,7 @@ void CL_ParseBaseline (struct msg_s *msg, struct entity_state_s *baseline,
void CL_ParseStatic (struct msg_s *msg, int version);
void CL_MapCfg (const char *mapname);
void CL_World_NewMap (const char *mapname, const char *skyname);
void CL_World_Clear (void);
void CL_LoadLights (struct plitem_s *entities, struct scene_s *scene);
#endif//__client_world_h

View file

@ -57,6 +57,7 @@ extern int x_height;
extern int x_shmeventtype;
extern Time x_time;
extern Time x_mouse_time;
extern Cursor x_nullcursor;
extern bool oktodraw;
extern bool x_have_focus;

View file

@ -123,6 +123,7 @@ typedef struct
int color;
} zpointdesc_t;
extern int d_framecount;
extern int r_drawflat;
extern int r_framecount; // sequence # of current frame since Quake
// started

View file

@ -45,8 +45,6 @@ typedef enum {
struct entity_s;
void R_PushDlights (const vec3_t entorigin);
void R_MaxDlightsCheck (int max_dlights);
void R_Particles_Init_Cvars (void);
void R_Particle_New (const char *type, int texnum, const vec3_t org,
float scale, const vec3_t vel, float die, int color,

View file

@ -50,8 +50,19 @@ void R_RunParticles (float dT);
struct scene_s;
void R_NewScene (struct scene_s *scene);
typedef struct visstate_s {
const struct mleaf_s *viewleaf;
int *node_visframes;
int *leaf_visframes;
int *face_visframes;
int visframecount;
const struct mod_brush_s *brush;
} visstate_t;
extern visstate_t r_visstate;//FIXME
// LordHavoc: relative bmodel lighting
void R_PushDlights (const vec3_t entorigin);
void R_PushDlights (const vec3_t entorigin, const visstate_t *visstate);
void R_DrawWaterSurfaces (void);
void *D_SurfaceCacheAddress (void) __attribute__((pure));
@ -65,10 +76,7 @@ void R_LoadSkys (const char *);
void R_ClearEfrags (void);
void R_FindNearLights (vec4f_t pos, int count, dlight_t **lights);
dlight_t *R_AllocDlight (int key);
void R_DecayLights (double frametime);
void R_ClearDlights (void);
int R_FindNearLights (vec4f_t pos, int count, dlight_t **lights);
int R_InitGraphTextures (int base);
@ -77,11 +85,9 @@ struct animation_s;
struct transform_s;
void R_DrawAliasModel (struct entity_s *e);
void R_MarkLeaves (struct mleaf_s *viewleaf, int *node_visframes,
int *leaf_visframes, int *face_visframes);
extern int *r_node_visframes;
extern int *r_leaf_visframes;
extern int *r_face_visframes;
struct set_s;
void R_MarkLeavesPVS (visstate_t *state, const struct set_s *pvs);
void R_MarkLeaves (visstate_t *state, const struct mleaf_s *viewleaf);
void GL_SetPalette (void *data, const byte *palette);
void GLSL_SetPalette (void *data, const byte *palette);

View file

@ -120,8 +120,6 @@ extern plane_t screenedge[4];
extern vec4f_t r_entorigin;
extern int r_visframecount;
//=============================================================================
extern int vstartscan;
@ -310,7 +308,7 @@ void R_SetupFrame (void);
void R_cshift_f (void);
void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1);
void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip);
void R_RecursiveMarkLights (mod_brush_t *brush, vec4f_t lightorigin,
void R_RecursiveMarkLights (const mod_brush_t *brush, vec4f_t lightorigin,
struct dlight_s *light, int bit, int node_id);
void R_LoadSkys (const char *);

View file

@ -10,6 +10,7 @@ typedef struct vid_system_s {
void (*set_palette) (byte *palette, byte *colormap);
void (*init_cvars) (void);
void (*update_fullscreen) (int fullscreen);
void (*set_cursor) (bool visible);
} vid_system_t;
extern vid_system_t vid_system;
@ -37,7 +38,7 @@ extern int vid_system_gamma;
extern float vid_gamma;
void VID_GetWindowSize (int def_w, int def_h);
void VID_SetWindowSize (int width, int height);
void VID_SetWindow (int x, int y, int width, int height);
void VID_InitGamma (const byte *);
bool VID_SetGamma (double);

View file

@ -10,6 +10,8 @@
#include "QF/qtypes.h"
#include "QF/simd/types.h"
#define VA_CTX_COUNT 64
typedef struct qfv_renderpassset_s
DARRAY_TYPE (struct qfv_orenderpass_s *) qfv_renderpassset_t;
@ -38,6 +40,7 @@ typedef struct vulkan_ctx_s {
struct scriptctx_s *script_context;
struct qfv_renderctx_s *render_context;
struct qfv_capturectx_s *capture_context;
struct qfv_mousepickctx_s *mousepick_context;
struct texturectx_s *texture_context;
struct matrixctx_s *matrix_context;
struct translucentctx_s *translucent_context;
@ -47,6 +50,7 @@ typedef struct vulkan_ctx_s {
struct scenectx_s *scene_context;
struct palettectx_s *palette_context;
struct particlectx_s *particle_context;
struct planesctx_s *planes_context;
struct spritectx_s *sprite_context;
struct drawctx_s *draw_context;
struct lightingctx_s *lighting_context;

View file

@ -38,10 +38,12 @@
# include <strings.h>
#endif
#include "QF/ecs.h"
#include "QF/render.h"
#include "QF/plugin/vid_render.h" //FIXME
#include "QF/scene/entity.h"
#include "QF/scene/light.h"
#include "QF/scene/scene.h"
#include "client/entities.h"
@ -49,16 +51,61 @@
#include "client/particles.h"
#include "client/world.h"
ecs_system_t effect_system;
const component_t effect_components[effect_comp_count] = {
[effect_light] = {
.size = sizeof (uint32_t),
.name = "effect light",
},
[effect_muzzleflash] = {
.size = sizeof (uint32_t),
.name = "muzzle flash",
},
};
#define c_light (effect_system.base + effect_light)
static bool
has_light (entity_t ent)
{
return Ent_HasComponent (ent.id, c_light, ent.reg);
}
static uint32_t
get_light (entity_t ent)
{
return *(uint32_t *) Ent_GetComponent (ent.id, c_light, ent.reg);
}
static void
set_light (entity_t ent, uint32_t light)
{
Ent_SetComponent (ent.id, c_light, ent.reg, &light);
}
static uint32_t
attach_light_ent (entity_t ent)
{
uint32_t light = nullent;
if (has_light (ent)) {
light = get_light (ent);
}
if (!ECS_EntValid (light, ent.reg)) {
light = ECS_NewEntity (ent.reg);
set_light (ent, light);
}
return light;
}
void
CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size,
CL_NewDlight (entity_t ent, vec4f_t org, int effects, byte glow_size,
byte glow_color, double time)
{
float radius;
dlight_t *dl;
static quat_t normal = {0.4, 0.2, 0.05, 0.7};
static quat_t red = {0.5, 0.05, 0.05, 0.7};
static quat_t blue = {0.05, 0.05, 0.5, 0.7};
static quat_t purple = {0.5, 0.05, 0.5, 0.7};
static vec4f_t normal = {0.4, 0.2, 0.05, 0.7};
static vec4f_t red = {0.5, 0.05, 0.05, 0.7};
static vec4f_t blue = {0.05, 0.05, 0.5, 0.7};
static vec4f_t purple = {0.5, 0.05, 0.5, 0.7};
effects &= EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT;
if (!effects) {
@ -66,60 +113,56 @@ CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size,
return;
}
dl = R_AllocDlight (key);
if (!dl)
return;
VectorCopy (org, dl->origin);
float radius = 0;
float die = time + 0.1;
vec4f_t color = normal;
if (effects & (EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT)) {
radius = 200 + (rand () & 31);
if (effects & EF_BRIGHTLIGHT) {
radius += 200;
dl->origin[2] += 16;
org[2] += 16;
}
if (effects & EF_DIMLIGHT)
if (effects & ~EF_DIMLIGHT)
radius -= 100;
dl->radius = radius;
dl->die = time + 0.1;
switch (effects & (EF_RED | EF_BLUE)) {
case EF_RED | EF_BLUE:
QuatCopy (purple, dl->color);
break;
case EF_RED:
QuatCopy (red, dl->color);
break;
case EF_BLUE:
QuatCopy (blue, dl->color);
break;
default:
QuatCopy (normal, dl->color);
break;
case EF_RED | EF_BLUE: color = purple; break;
case EF_RED: color = red; break;
case EF_BLUE: color = blue; break;
default: color = normal; break;
}
}
if (glow_size) {
dl->radius += glow_size < 128 ? glow_size * 8.0 :
(glow_size - 256) * 8.0;
dl->die = time + 0.1;
radius += glow_size < 128 ? glow_size * 8.0 : (glow_size - 256) * 8.0;
if (glow_color) {
if (glow_color == 255) {
dl->color[0] = dl->color[1] = dl->color[2] = 1.0;
color = (vec4f_t) { 1, 1, 1, 0.7 };
} else {
byte *tempcolor;
tempcolor = (byte *) &d_8to24table[glow_color];
VectorScale (tempcolor, 1 / 255.0, dl->color);
VectorScale (tempcolor, 1 / 255.0, color);
color[3] = 0.7;
}
}
}
uint32_t light = attach_light_ent (ent);
Ent_SetComponent (light, scene_dynlight, ent.reg, &(dlight_t) {
.origin = org,
.color = color,
.radius = radius,
.die = die,
});
Light_LinkLight (cl_world.scene->lights, light);
}
void
CL_ModelEffects (entity_t ent, int num, int glow_color, double time)
CL_ModelEffects (entity_t ent, int glow_color, double time)
{
dlight_t *dl;
transform_t transform = Entity_Transform (ent);
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg);
model_t *model = renderer->model;
@ -127,54 +170,36 @@ CL_ModelEffects (entity_t ent, int num, int glow_color, double time)
vec4f_t ent_origin = Transform_GetWorldPosition (transform);
// add automatic particle trails
if (model->flags & EF_ROCKET) {
dl = R_AllocDlight (num);
if (dl) {
VectorCopy (ent_origin, dl->origin);
dl->radius = 200.0;
dl->die = time + 0.1;
if (model->effects & ME_ROCKET) {
uint32_t light = attach_light_ent (ent);
Ent_SetComponent (light, scene_dynlight, ent.reg, &(dlight_t) {
.origin = ent_origin,
//FIXME VectorCopy (r_firecolor, dl->color);
VectorSet (0.9, 0.7, 0.0, dl->color);
dl->color[3] = 0.7;
}
.color = { 0.9, 0.7, 0.0, 0.7 },
.radius = 200,
.die = time + 0.1,
});
Light_LinkLight (cl_world.scene->lights, light);
clp_funcs->RocketTrail (*old_origin, ent_origin);
} else if (model->flags & EF_GRENADE)
renderer->noshadows = 1;
} else if (model->effects & ME_GRENADE)
clp_funcs->GrenadeTrail (*old_origin, ent_origin);
else if (model->flags & EF_GIB)
else if (model->effects & ME_GIB)
clp_funcs->BloodTrail (*old_origin, ent_origin);
else if (model->flags & EF_ZOMGIB)
else if (model->effects & ME_ZOMGIB)
clp_funcs->SlightBloodTrail (*old_origin, ent_origin);
else if (model->flags & EF_TRACER)
else if (model->effects & ME_TRACER)
clp_funcs->WizTrail (*old_origin, ent_origin);
else if (model->flags & EF_TRACER2)
else if (model->effects & ME_TRACER2)
clp_funcs->FlameTrail (*old_origin, ent_origin);
else if (model->flags & EF_TRACER3)
else if (model->effects & ME_TRACER3)
clp_funcs->VoorTrail (*old_origin, ent_origin);
else if (model->flags & EF_GLOWTRAIL)
else if (model->effects & ME_GLOWTRAIL)
clp_funcs->GlowTrail (*old_origin, ent_origin, glow_color);
}
void
CL_MuzzleFlash (vec4f_t position, vec4f_t fv, float zoffset, int num,
double time)
{
dlight_t *dl = R_AllocDlight (num);
if (dl) {
position += 18 * fv;
VectorCopy (position, dl->origin);
dl->origin[2] += zoffset;
dl->radius = 200 + (rand () & 31);
dl->die = time + 0.1;
dl->minlight = 32;
dl->color[0] = 0.2;
dl->color[1] = 0.1;
dl->color[2] = 0.05;
dl->color[3] = 0.7;
}
}
void
CL_EntityEffects (int num, entity_t ent, entity_state_t *state, double time)
CL_EntityEffects (entity_t ent, entity_state_t *state, double time)
{
transform_t transform = Entity_Transform (ent);
vec4f_t position = Transform_GetWorldPosition (transform);
@ -182,6 +207,6 @@ CL_EntityEffects (int num, entity_t ent, entity_state_t *state, double time)
clp_funcs->EntityParticles (position);
if (state->effects & EF_MUZZLEFLASH) {
vec4f_t fv = Transform_Forward (transform);
CL_MuzzleFlash (position, fv, 16, num, time);
CL_MuzzleFlash (ent, position, fv, 16, time);
}
}

View file

@ -75,7 +75,7 @@ in_axis_t in_move_side = {
in_axis_t in_move_up = {
.mode = ina_set,
.name = "move.up",
.description = "Move up (positive) or down (negative)",
.description = "Move up (negative) or down (positive)",
};
in_axis_t in_cam_forward = {
@ -581,7 +581,7 @@ static int
cl_key_event (const IE_event_t *ie_event)
{
if (ie_event->key.code == QFK_ESCAPE) {
Con_SetState (con_menu);
Con_SetState (con_menu, true);
return 1;
}
return 0;

View file

@ -10,6 +10,8 @@
#include "QF/plist.h"
#include "QF/progs.h" //for ED_ConvertToPlist
#include "QF/set.h"
#include "QF/ecs.h"
#include "QF/scene/entity.h"
#include "QF/scene/light.h"
#include "QF/scene/scene.h"
#include "QF/simd/vec4f.h"
@ -17,8 +19,12 @@
#include "client/world.h"
static void
dump_light (light_t *light, int leaf)
dump_light (light_t *light, efrag_t *efrags)
{
int leafcount = 0;
for (auto e = efrags; e; e = e->leafnext) {
leafcount++;
}
Sys_MaskPrintf (SYS_lighting,
"[%g, %g, %g] %g, "
"[%g, %g, %g, %g], [%g %g %g] %g, [%g, %g, %g, %g] %d\n",
@ -26,7 +32,7 @@ dump_light (light_t *light, int leaf)
VEC4_EXP (light->position),
VEC4_EXP (light->direction),
VEC4_EXP (light->attenuation),
leaf);
leafcount);
}
static float
@ -323,8 +329,12 @@ CL_LoadLights (plitem_t *entities, scene_t *scene)
}
PL_Release (targets);
for (size_t i = 0; i < ldata->lights.size; i++) {
dump_light (&ldata->lights.a[i], ldata->lightleafs.a[i]);
auto lights = &scene->reg->comp_pools[scene_light];
auto lefrags = &scene->reg->comp_pools[scene_efrags];
for (uint32_t i = 0; i < lights->count; i++) {
auto light = &((light_t *)lights->data)[i];
auto efrags = ((efrag_t **)lefrags->data)[i];
dump_light (light, efrags);
}
Sys_MaskPrintf (SYS_lighting, "loaded %zd lights\n", ldata->lights.size);
Sys_MaskPrintf (SYS_lighting, "loaded %d lights\n", lights->count);
}

View file

@ -99,13 +99,59 @@ static view_t loading_view;
static view_t ram_view;
static view_t turtle_view;
static view_t pause_view;
static view_t crosshair_view;
static view_t cshift_view;
static view_t centerprint_view;
static viewstate_t *_vs;//FIXME ick
canvas_system_t cl_canvas_sys;
static ecs_system_t cl_view_system;
static view_t
clscr_view (int x, int y, int w, int h, grav_t gravity)
{
auto view = View_New (cl_view_system, cl_screen_view);
View_SetPos (view, x, y);
View_SetLen (view, w, h);
View_SetGravity (view, gravity);
View_SetVisible (view, 0);
return view;
}
static void
SCR_CShift (void)
clscr_set_pic (view_t view, qpic_t *pic)
{
Ent_SetComponent (view.id, canvas_pic, view.reg, &pic);
}
static void
clscr_set_cachepic (view_t view, const char *name)
{
Ent_SetComponent (view.id, canvas_cachepic, view.reg, &name);
}
static void
clscr_set_canvas_func (view_t view, canvas_func_f func)
{
Ent_SetComponent (view.id, canvas_func, view.reg, &func);
}
static void
cl_draw_crosshair (view_pos_t abs, view_pos_t len)
{
r_funcs->Draw_Crosshair ();
}
static void
cl_draw_centerprint (view_pos_t abs, view_pos_t len)
{
Sbar_DrawCenterPrint ();
}
static void
SCR_CShift (view_pos_t abs, view_pos_t len)
{
mleaf_t *leaf;
int contents = CONTENTS_EMPTY;
@ -113,7 +159,7 @@ SCR_CShift (void)
if (_vs->active && cl_world.scene->worldmodel) {
vec4f_t origin;
origin = Transform_GetWorldPosition (_vs->camera_transform);
leaf = Mod_PointInLeaf (origin, cl_world.scene->worldmodel);
leaf = Mod_PointInLeaf (origin, &cl_world.scene->worldmodel->brush);
contents = leaf->contents;
}
V_SetContentsColor (_vs, contents);
@ -140,17 +186,13 @@ scr_draw_views (void)
double msg_time = _vs->realtime - _vs->last_servermessage;
View_SetVisible (net_view, (!_vs->demoplayback && msg_time >= 0.3));
View_SetVisible (loading_view, _vs->loading);
View_SetVisible (crosshair_view, !_vs->intermission);
// FIXME cvar callbacks
View_SetVisible (timegraph_view, r_timegraph);
View_SetVisible (zgraph_view, r_zgraph);
if (!_vs->intermission) {
r_funcs->Draw_Crosshair ();//FIXME canvas_func
}
Con_DrawConsole ();
Canvas_Draw (cl_canvas_sys);
SCR_CShift ();//FIXME canvas_func
Sbar_DrawCenterPrint ();//FIXME canvas_func
}
static SCR_Func scr_funcs[] = {
@ -167,10 +209,9 @@ cl_set_size (void)
{
int xlen = cl_xlen / cl_scale;
int ylen = cl_ylen / cl_scale;
printf ("cl_set_size: %d %d %d\n", cl_scale, xlen, ylen);
//View_SetLen (cl_screen_view, xlen, ylen);
//View_UpdateHierarchy (cl_screen_view);
Canvas_SetLen (cl_canvas_sys, (view_pos_t) { xlen, ylen });
//printf ("cl_set_size: %d %d %d\n", cl_scale, xlen, ylen);
Canvas_SetLen (cl_canvas_sys, cl_canvas, (view_pos_t) { xlen, ylen });
Canvas_SetLen (cl_canvas_sys, hud_canvas, (view_pos_t) { xlen, ylen });
}
static void
@ -188,11 +229,58 @@ cl_vidsize_listener (void *data, const viddef_t *vdef)
cl_set_size ();
}
static void
cl_create_views (void)
{
qpic_t *pic;
const char *name;
auto vid = r_data->vid;
pic = r_funcs->Draw_PicFromWad ("ram");
ram_view = clscr_view (32, 0, pic->width, pic->height, grav_northwest);
clscr_set_pic (ram_view, pic);
pic = r_funcs->Draw_PicFromWad ("turtle");
turtle_view = clscr_view (32, 0, pic->width, pic->height, grav_northwest);
clscr_set_pic (turtle_view, pic);
pic = r_funcs->Draw_PicFromWad ("net");
net_view = clscr_view (64, 0, pic->width, pic->height, grav_northwest);
clscr_set_pic (net_view, pic);
timegraph_view = clscr_view (0, 0, vid->width, 100, grav_southwest);
clscr_set_canvas_func (timegraph_view, R_TimeGraph);
View_SetVisible (timegraph_view, r_timegraph);
zgraph_view = clscr_view (0, 0, vid->width, 100, grav_southwest);
clscr_set_canvas_func (zgraph_view, R_ZGraph);
View_SetVisible (zgraph_view, r_zgraph);
name = "gfx/loading.lmp";
pic = r_funcs->Draw_CachePic (name, 1);
loading_view = clscr_view (0, -24, pic->width, pic->height, grav_center);
clscr_set_cachepic (loading_view, name);
name = "gfx/pause.lmp";
pic = r_funcs->Draw_CachePic (name, 1);
pause_view = clscr_view (0, -24, pic->width, pic->height, grav_center);
clscr_set_cachepic (pause_view, name);
crosshair_view = clscr_view (0, 0, vid->width, vid->height, grav_northwest);
clscr_set_canvas_func (crosshair_view, cl_draw_crosshair);
cshift_view = clscr_view (0, 0, vid->width, vid->height, grav_northwest);
clscr_set_canvas_func (cshift_view, SCR_CShift);
View_SetVisible (cshift_view, 1);
centerprint_view = clscr_view (0, 0, vid->width, vid->height,
grav_northwest);
clscr_set_canvas_func (centerprint_view, cl_draw_centerprint);
}
void
CL_Init_Screen (void)
{
qpic_t *pic;
__auto_type reg = ECS_NewRegistry ();
Canvas_InitSys (&cl_canvas_sys, reg);
if (con_module) {
@ -207,7 +295,7 @@ CL_Init_Screen (void)
cl_xlen = viddef.width;
cl_ylen = viddef.height;
ecs_system_t vsys = {
cl_view_system = (ecs_system_t) {
.reg = reg,
.base = cl_canvas_sys.view_base,
};
@ -222,68 +310,11 @@ CL_Init_Screen (void)
View_SetGravity (cl_screen_view, grav_northwest);
View_SetVisible (cl_screen_view, 1);
pic = r_funcs->Draw_PicFromWad ("ram");
ram_view = View_New (vsys, cl_screen_view);
View_SetPos (ram_view, 32, 0);
View_SetLen (ram_view, pic->width, pic->height);
View_SetGravity (ram_view, grav_northwest);
Ent_SetComponent (ram_view.id, canvas_pic, ram_view.reg, &pic);
View_SetVisible (ram_view, 0);
pic = r_funcs->Draw_PicFromWad ("turtle");
turtle_view = View_New (vsys, cl_screen_view);
View_SetPos (turtle_view, 32, 0);
View_SetLen (turtle_view, pic->width, pic->height);
View_SetGravity (turtle_view, grav_northwest);
Ent_SetComponent (turtle_view.id, canvas_pic, turtle_view.reg, &pic);
View_SetVisible (turtle_view, 0);
Cvar_Register (&scr_showpause_cvar, 0, 0);
Cvar_Register (&scr_showram_cvar, 0, 0);
Cvar_Register (&scr_showturtle_cvar, 0, 0);
pic = r_funcs->Draw_PicFromWad ("net");
net_view = View_New (vsys, cl_screen_view);
View_SetPos (net_view, 64, 0);
View_SetLen (net_view, pic->width, pic->height);
View_SetGravity (net_view, grav_northwest);
Ent_SetComponent (net_view.id, canvas_pic, net_view.reg, &pic);
View_SetVisible (net_view, 0);
timegraph_view = View_New (vsys, cl_screen_view);
View_SetPos (timegraph_view, 0, 0);
View_SetLen (timegraph_view, r_data->vid->width, 100);
View_SetGravity (timegraph_view, grav_southwest);
void *rtg = R_TimeGraph;
Ent_SetComponent (timegraph_view.id, canvas_func, timegraph_view.reg, &rtg);
View_SetVisible (timegraph_view, r_timegraph);
zgraph_view = View_New (vsys, cl_screen_view);
View_SetPos (zgraph_view, 0, 0);
View_SetLen (zgraph_view, r_data->vid->width, 100);
View_SetGravity (zgraph_view, grav_southwest);
void *rzg = R_ZGraph;
Ent_SetComponent (zgraph_view.id, canvas_func, zgraph_view.reg, &rzg);
View_SetVisible (zgraph_view, r_zgraph);
const char *name = "gfx/loading.lmp";
pic = r_funcs->Draw_CachePic (name, 1);
loading_view = View_New (vsys, cl_screen_view);
View_SetPos (loading_view, 0, -24);
View_SetLen (loading_view, pic->width, pic->height);
View_SetGravity (loading_view, grav_center);
Ent_SetComponent (loading_view.id, canvas_cachepic,
loading_view.reg, &name);
View_SetVisible (loading_view, 0);
name = "gfx/pause.lmp";
pic = r_funcs->Draw_CachePic (name, 1);
pause_view = View_New (vsys, cl_screen_view);
View_SetPos (pause_view, 0, -24);
View_SetLen (pause_view, pic->width, pic->height);
View_SetGravity (pause_view, grav_center);
Ent_SetComponent (pause_view.id, canvas_cachepic, pause_view.reg, &name);
View_SetVisible (pause_view, 0);
cl_create_views ();
cvar_t *con_scale = Cvar_FindVar ("con_scale");
Cvar_AddListener (con_scale, cl_scale_listener, 0);

View file

@ -38,6 +38,7 @@
# include <strings.h>
#endif
#include "QF/darray.h"
#include "QF/msg.h"
#include "QF/progs.h" // for PR_RESMAP
#include "QF/quakefs.h"
@ -47,6 +48,7 @@
#include "QF/plugin/vid_render.h" //FIXME
//
#include "QF/scene/entity.h"
#include "QF/scene/light.h"
#include "QF/scene/scene.h"
#include "client/effects.h"
@ -325,15 +327,55 @@ CL_ParseBeam (qmsg_t *net_message, model_t *m, double time, TEntContext_t *ctx)
}
}
typedef struct tempent_s DARRAY_TYPE (entity_t) tempent_t;
static tempent_t light_entities = DARRAY_STATIC_INIT (32);
static void
free_stale_entities (void)
{
size_t i, j;
for (i = 0, j = 0; i < light_entities.size; i++) {
auto ent = light_entities.a[i];
if (Ent_HasComponent (ent.id, scene_dynlight, ent.reg)) {
if (j != i) {
light_entities.a[j] = ent;
}
j++;
} else {
ECS_DelEntity (ent.reg, ent.id);
}
}
light_entities.size = j;
}
static void
spawn_light (vec4f_t position, vec4f_t color, float radius, float die,
float decay)
{
entity_t ent = {
.reg = cl_world.scene->reg,
.id = ECS_NewEntity (cl_world.scene->reg),
};
DARRAY_APPEND (&light_entities, ent);
Ent_SetComponent (ent.id, scene_dynlight, ent.reg, &(dlight_t) {
.origin = position,
.color = color,
.radius = radius,
.die = die,
.decay = decay,
});
Light_LinkLight (cl_world.scene->lights, ent.id);
}
static void
parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx,
TE_Effect type)
{
dlight_t *dl;
tent_obj_t *to;
explosion_t *ex;
int colorStart, colorLength;
quat_t color;
vec4f_t color;
vec4f_t position = {0, 0, 0, 1};
int count;
const char *name;
@ -369,23 +411,16 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx,
renderer_t *renderer = Ent_GetComponent (ex->tent->ent.id, scene_renderer, cl_world.scene->reg);
renderer->model = cl_spr_explod;
Transform_SetLocalPosition (transform, position);
color = (vec4f_t) {0.86, 0.31, 0.24, 0.7};
goto TE_Explosion_no_sprite;
case TE_Explosion:
MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME
color = (vec4f_t) {1.0, 0.5, 0.25, 0.7};
TE_Explosion_no_sprite:
// particles
clp_funcs->ParticleExplosion (position);
// light
dl = R_AllocDlight (0);
if (dl) {
VectorCopy (position, dl->origin);
dl->radius = 350;
dl->die = time + 0.5;
dl->decay = 300;
QuatSet (0.86, 0.31, 0.24, 0.7, dl->color);
//FIXME? nq: QuatSet (1.0, 0.5, 0.25, 0.7, dl->color);
}
spawn_light (position, color, 250, time + 0.5, 300);
// sound
S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1);
@ -396,32 +431,20 @@ TE_Explosion_no_sprite:
colorLength = MSG_ReadByte (net_message);
S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1);
clp_funcs->ParticleExplosion2 (position, colorStart, colorLength);
dl = R_AllocDlight (0);
if (!dl)
break;
VectorCopy (position, dl->origin);
dl->radius = 350;
dl->die = time + 0.5;
dl->decay = 300;
colorStart = (colorStart + (rand () % colorLength)) * 3;
VectorScale (&r_data->vid->palette[colorStart], 1.0 / 255.0,
dl->color);
dl->color[3] = 0.7;
VectorScale (&r_data->vid->palette[colorStart], 1.0 / 255.0, color);
color[3] = 0.7;
spawn_light (position, color, 350, time + 0.5, 300);
break;
case TE_Explosion3:
MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME
MSG_ReadCoordV (net_message, color); // OUCH!
MSG_ReadCoordV (net_message, (vec_t*)&color); //FIXME OUCH!
color[3] = 0.7;
clp_funcs->ParticleExplosion (position);
S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1);
dl = R_AllocDlight (0);
if (dl) {
VectorCopy (position, dl->origin);
dl->radius = 350;
dl->die = time + 0.5;
dl->decay = 300;
QuatCopy (color, dl->color);
}
spawn_light (position, color, 350, time + 0.5, 300);
break;
case TE_Gunshot1:
MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME
@ -457,15 +480,8 @@ TE_Explosion_no_sprite:
case TE_LightningBlood:
MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME
// light
dl = R_AllocDlight (0);
if (dl) {
VectorCopy (position, dl->origin);
dl->radius = 150;
dl->die = time + 0.1;
dl->decay = 200;
QuatSet (0.25, 0.40, 0.65, 1, dl->color);
}
color = (vec4f_t) {0.25, 0.40, 0.65, 1};
spawn_light (position, color, 150, time + 0.1, 200);
clp_funcs->LightningBloodEffect (position);
break;
@ -650,6 +666,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx)
void
CL_UpdateTEnts (double time, TEntContext_t *ctx)
{
free_stale_entities ();
CL_UpdateBeams (time, ctx);
CL_UpdateExplosions (time, ctx);
}
@ -732,3 +749,48 @@ CL_ParseProjectiles (qmsg_t *net_message, bool nail2, TEntContext_t *ctx)
*tail = cl_projectiles;
cl_projectiles = head;
}
#define c_muzzleflash (effect_system.base + effect_muzzleflash)
static bool
has_muzzleflash (entity_t ent)
{
return Ent_HasComponent (ent.id, c_muzzleflash, ent.reg);
}
static uint32_t
get_muzzleflash (entity_t ent)
{
return *(uint32_t *) Ent_GetComponent (ent.id, c_muzzleflash, ent.reg);
}
static void
set_muzzleflash (entity_t ent, uint32_t light)
{
Ent_SetComponent (ent.id, c_muzzleflash, ent.reg, &light);
}
void
CL_MuzzleFlash (entity_t ent, vec4f_t position, vec4f_t fv, float zoffset,
double time)
{
// spawn a new entity so the light doesn't mess with the owner
uint32_t light = nullent;
if (has_muzzleflash (ent)) {
light = get_muzzleflash (ent);
}
if (!ECS_EntValid (light, ent.reg)) {
light = ECS_NewEntity (ent.reg);
set_muzzleflash (ent, light);
}
DARRAY_APPEND (&light_entities, ((entity_t) {.reg = ent.reg, .id = light}));
Ent_SetComponent (light, scene_dynlight, ent.reg, &(dlight_t) {
.origin = position + 18 * fv + zoffset * (vec4f_t) {0, 0, 1, 0},
.color = { 0.2, 0.1, 0.05, 0.7 },
.radius = 200 + (rand () & 31),
.die = time + 0.1,
.minlight = 32,
});
Light_LinkLight (cl_world.scene->lights, light);
}

View file

@ -932,9 +932,11 @@ void
V_RenderView (viewstate_t *vs)
{
if (!vs->active) {
vec4f_t base = { 0, 0, 0, 1 };
Transform_SetWorldPosition (vs->camera_transform, base);
Transform_SetWorldRotation (vs->camera_transform, base);
if (Transform_Valid (vs->camera_transform)) {
vec4f_t base = { 0, 0, 0, 1 };
Transform_SetWorldPosition (vs->camera_transform, base);
Transform_SetWorldRotation (vs->camera_transform, base);
}
return;
}
@ -952,6 +954,13 @@ V_RenderView (viewstate_t *vs)
}
}
void
V_NewScene (viewstate_t *viewstate, scene_t *scene)
{
viewstate->camera_transform = Transform_New (cl_world.scene->reg,
nulltransform);
}
void
V_Init (viewstate_t *viewstate)
{
@ -965,9 +974,6 @@ V_Init (viewstate_t *viewstate)
"currently being displayed.\n"
"Used when you are underwater, hit, have the Ring of "
"Shadows, or Quad Damage. (v_cshift r g b intensity)");
viewstate->camera_transform = Transform_New (cl_world.scene->reg,
nulltransform);
}
void

View file

@ -43,16 +43,12 @@
#include "QF/idparse.h"
#include "QF/quakefs.h"
#include "QF/plist.h"
#include "QF/progs.h"
#include "QF/msg.h"
#include "QF/scene/entity.h"
#include "QF/scene/light.h"
#include "QF/scene/scene.h"
#include "QF/simd/vec4f.h"
#include "QF/plugin/vid_render.h" //FIXME
#include "client/effects.h"
#include "client/entities.h"
#include "client/temp_entities.h"
#include "client/world.h"
@ -64,7 +60,13 @@ worldscene_t cl_world = {
void
CL_World_Init (void)
{
cl_world.scene = Scene_NewScene ();
scene_system_t extra_systems[] = {
{ .system = &effect_system,
.components = effect_components,
.component_count = effect_comp_count },
{}
};
cl_world.scene = Scene_NewScene (extra_systems);
cl_world.scene->lights = Light_CreateLightingData (cl_world.scene);
}
@ -119,6 +121,7 @@ CL_ParseStatic (qmsg_t *msg, int version)
// copy it to the current state
renderer->model = cl_world.models.a[es.modelindex];
renderer->noshadows = renderer->model->shadow_alpha < 0.5;
animation->frame = es.frame;
renderer->skinnum = es.skinnum;
@ -233,3 +236,10 @@ CL_World_NewMap (const char *mapname, const char *skyname)
SCR_NewScene (cl_world.scene);
map_cfg (mapname, 1);
}
void
CL_World_Clear (void)
{
Scene_FreeAllEntities (cl_world.scene);
CL_ClearTEnts ();
}

View file

@ -290,7 +290,6 @@ void
locs_draw (double time, vec4f_t simorg)
{
//FIXME custom ent rendering code would be nice
dlight_t *dl;
location_t *nearloc;
vec4f_t trueloc;
vec4f_t zero = {};
@ -298,16 +297,15 @@ locs_draw (double time, vec4f_t simorg)
nearloc = locs_find (simorg);
if (nearloc) {
dl = R_AllocDlight (4096);
if (dl) {
VectorCopy (nearloc->loc, dl->origin);
dl->radius = 200;
dl->die = time + 0.1;
dl->color[0] = 0;
dl->color[1] = 1;
dl->color[2] = 0;
dl->color[3] = 0.7;
}
#if 0//FIXME
Ent_SetComponent (ent.id, scene_dynlight, ent.reg, &(dlight_t) {
.origin = nearloc->loc,
.color = { 0, 1, 0, 0.7 },
.radius = 200,
.die = time + 0.1,
});
Light_LinkLight (cl_world.scene->lights, ent.id);
#endif
trueloc = nearloc->loc;
clp_funcs->Particle_New (pt_smokecloud, part_tex_smoke, trueloc, 2.0,
zero, time + 9.0, 254,

View file

@ -11,10 +11,13 @@ console_common_sources= \
libs/console/console.c \
libs/console/list.c \
libs/console/filelist.c
client_sources= \
libs/console/bi_inputline.c \
libs/console/cl_debug.c \
libs/console/client.c \
libs/console/menu.c
server_sources= \
libs/console/server.c

719
libs/console/cl_debug.c Normal file
View file

@ -0,0 +1,719 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/cbuf.h"
#include "QF/cvar.h"
#include "QF/input.h"
#include "QF/keys.h"
#include "QF/render.h"
#include "QF/screen.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/input/event.h"
#include "QF/scene/scene.h"
#include "QF/scene/transform.h"
#include "QF/ui/canvas.h"
#include "QF/ui/imui.h"
#include "QF/plugin/console.h"
#include "QF/plugin/vid_render.h"
#include "cl_console.h"
static in_axis_t deb_move_forward = {
.mode = ina_set,
.name = "debug.move.forward",
.description = "[debug] Move forward (negative) or backward (positive)",
};
static in_axis_t deb_move_side = {
.mode = ina_set,
.name = "debug.move.side",
.description = "[debug] Move right (positive) or left (negative)",
};
static in_axis_t deb_move_up = {
.mode = ina_set,
.name = "debug.move.up",
.description = "[debug] Move up (negative) or down (positive)",
};
static in_axis_t deb_move_pitch = {
.mode = ina_set,
.name = "debug.move.pitch",
.description = "[debug] Pitch axis",
};
static in_axis_t deb_move_yaw = {
.mode = ina_set,
.name = "debug.move.yaw",
.description = "[debug] Yaw axis",
};
static in_axis_t deb_move_roll = {
.mode = ina_set,
.name = "debug.move.roll",
.description = "[debug] Roll axis",
};
static in_axis_t deb_mouse_x = {
.mode = ina_set,
.name = "debug.mouse.x",
.description = "[debug] Mouse X",
};
static in_axis_t deb_mouse_y = {
.mode = ina_set,
.name = "debug.mouse.y",
.description = "[debug] Mouse Y",
};
static in_button_t deb_left = {
.name = "debug.left",
.description = "[debug] When active the player is turning left"
};
static in_button_t deb_right = {
.name = "debug.right",
.description = "[debug] When active the player is turning right"
};
static in_button_t deb_forward = {
.name = "debug.forward",
.description = "[debug] When active the player is moving forward"
};
static in_button_t deb_back = {
.name = "debug.back",
.description = "[debug] When active the player is moving backwards"
};
static in_button_t deb_lookup = {
.name = "debug.lookup",
.description = "[debug] When active the player's view is looking up"
};
static in_button_t deb_lookdown = {
.name = "debug.lookdown",
.description = "[debug] When active the player's view is looking down"
};
static in_button_t deb_moveleft = {
.name = "debug.moveleft",
.description = "[debug] When active the player is strafing left"
};
static in_button_t deb_moveright = {
.name = "debug.moveright",
.description = "[debug] When active the player is strafing right"
};
static in_button_t deb_up = {
.name = "debug.moveup",
.description = "[debug] When active the player is swimming up in a liquid"
};
static in_button_t deb_down = {
.name = "debug.movedown",
.description = "[debug] When active the player is swimming down in a liquid"
};
static in_axis_t *deb_in_axes[] = {
&deb_move_forward,
&deb_move_side,
&deb_move_up,
&deb_move_pitch,
&deb_move_yaw,
&deb_move_roll,
&deb_mouse_x,
&deb_mouse_y,
0
};
static in_button_t *deb_in_buttons[] = {
&deb_left,
&deb_right,
&deb_forward,
&deb_back,
&deb_lookup,
&deb_lookdown,
&deb_moveleft,
&deb_moveright,
&deb_up,
&deb_down,
0
};
static int debug_event_id;
static int debug_saved_focus;
static int debug_context;
static int debug_saved_context;
static imui_ctx_t *debug_imui;
static int64_t debug_enable_time;
#define IMUI_context debug_imui
static scene_t *debug_scene;
static transform_t debug_camera_pivot;
static transform_t debug_camera;
bool con_debug;
static cvar_t con_debug_cvar = {
.name = "con_debug",
.description =
"Enable the debug interface",
.default_value = "false",
.flags = CVAR_NONE,
.value = { .type = &cexpr_bool, .value = &con_debug },
};
static char *deb_fontname;
static cvar_t deb_fontname_cvar = {
.name = "deb_fontname",
.description =
"Font name/patter for debug interface",
.default_value = "Consolas",
.flags = CVAR_NONE,
.value = { .type = 0, .value = &deb_fontname },
};
static float deb_fontsize;
static cvar_t deb_fontsize_cvar = {
.name = "deb_fontsize",
.description =
"Font size for debug interface",
.default_value = "22",
.flags = CVAR_NONE,
.value = { .type = &cexpr_float, .value = &deb_fontsize },
};
static int deb_xlen = -1;
static int deb_ylen = -1;
static vec4f_t mouse_start;
static void
con_debug_f (void *data, const cvar_t *cvar)
{
Con_Show_Mouse (con_debug);
if (debug_imui) {
IMUI_SetVisible (debug_imui, con_debug);
debug_enable_time = Sys_LongTime ();
if (!con_debug) {
IE_Set_Focus (debug_saved_focus);
IMT_SetContext (debug_saved_context);
r_override_camera = false;
} else {
IMUI_SetSize (debug_imui, deb_xlen, deb_ylen);
}
}
}
static int
debug_app_window (const IE_event_t *ie_event)
{
if (deb_xlen != ie_event->app_window.xlen
|| deb_ylen != ie_event->app_window.ylen) {
deb_xlen = ie_event->app_window.xlen;
deb_ylen = ie_event->app_window.ylen;
IMUI_SetSize (debug_imui, deb_xlen, deb_ylen);
}
return 1;
}
static int
capture_mouse_event (const IE_event_t *ie_event)
{
static IE_mouse_event_t prev_mouse;
static bool dragging;
if (ie_event->mouse.type == ie_mousedown
&& ((ie_event->mouse.buttons ^ prev_mouse.buttons) & 4)) {
IN_UpdateGrab (1);
dragging = true;
mouse_start = (vec4f_t) {
ie_event->mouse.x,
ie_event->mouse.y,
};
} else if (ie_event->mouse.type == ie_mouseup
&& ((ie_event->mouse.buttons ^ prev_mouse.buttons) & 4)) {
IN_UpdateGrab (0);
dragging = false;
}
prev_mouse = ie_event->mouse;
return !dragging;
}
static int
debug_mouse (const IE_event_t *ie_event)
{
if (!IMUI_ProcessEvent (debug_imui, ie_event)) {
return capture_mouse_event (ie_event);
}
return 1;
}
static void
close_debug (void)
{
con_debug = false;
con_debug_f (0, &con_debug_cvar);
}
static int
debug_key (const IE_event_t *ie_event)
{
int shift = ie_event->key.shift & ~(ies_capslock | ies_numlock);
if (ie_event->key.code == QFK_ESCAPE && shift == ies_control) {
close_debug ();
}
IMUI_ProcessEvent (debug_imui, ie_event);
return 1;
}
static int
debug_event_handler (const IE_event_t *ie_event, void *data)
{
static int (*handlers[ie_event_count]) (const IE_event_t *ie_event) = {
[ie_app_window] = debug_app_window,
[ie_mouse] = debug_mouse,
[ie_key] = debug_key,
};
if ((unsigned) ie_event->type >= ie_event_count
|| !handlers[ie_event->type]) {
return IN_Binding_HandleEvent (ie_event);
}
return handlers[ie_event->type] (ie_event);
}
void
Con_Debug_InitCvars (void)
{
Cvar_Register (&con_debug_cvar, con_debug_f, 0);
Cvar_Register (&deb_fontname_cvar, 0, 0);
Cvar_Register (&deb_fontsize_cvar, 0, 0);
}
static imui_style_t current_style;
void
Con_Debug_Init (void)
{
for (int i = 0; deb_in_axes[i]; i++) {
IN_RegisterAxis (deb_in_axes[i]);
}
for (int i = 0; deb_in_buttons[i]; i++) {
IN_RegisterButton (deb_in_buttons[i]);
}
debug_event_id = IE_Add_Handler (debug_event_handler, 0);
debug_context = IMT_CreateContext ("debug.context");
debug_imui = IMUI_NewContext (*con_data.canvas_sys,
deb_fontname, deb_fontsize);
IMUI_SetVisible (debug_imui, con_debug);
IMUI_Style_Fetch (debug_imui, &current_style);
debug_scene = Scene_NewScene (0);
}
void
Con_Debug_Shutdown (void)
{
IE_Remove_Handler (debug_event_id);
Scene_DeleteScene (debug_scene);
}
static void
color_window (void)
{
static imui_window_t style_editor = {
.name = "Style Colors",
.xpos = 75,
.ypos = 75,
.is_open = false,
};
static int style_selection;
static int style_mode;
static int style_color;
UI_Window (&style_editor) {
if (style_editor.is_collapsed) {
continue;
}
UI_Vertical {
UI_Horizontal {
UI_FlexibleSpace ();
UI_Radio (&style_selection, 0, "Background");
UI_FlexibleSpace ();
UI_Radio (&style_selection, 1, "Foreground");
UI_FlexibleSpace ();
UI_Radio (&style_selection, 2, "Text");
UI_FlexibleSpace ();
}
UI_Horizontal {
UI_FlexibleSpace ();
UI_Radio (&style_mode, 0, "Normal");
UI_FlexibleSpace ();
UI_Radio (&style_mode, 1, "Hot");
UI_FlexibleSpace ();
UI_Radio (&style_mode, 2, "Active");
UI_FlexibleSpace ();
}
if (style_selection == 0) {
style_color = current_style.background.color[style_mode];
} else if (style_selection == 1) {
style_color = current_style.foreground.color[style_mode];
} else if (style_selection == 2) {
style_color = current_style.text.color[style_mode];
}
imui_style_t style;
IMUI_Style_Fetch (debug_imui, &style);
auto bg_save = style.background.normal;
auto fg_save = style.foreground.normal;
UI_Style (0) for (int y = 0; y < 16; y++) {
UI_Horizontal for (int x = 0; x < 16; x++) {
if (!x) UI_FlexibleSpace ();
int c = y * 16 + x;
int ic = y * 16 + (15-x);
style.background.normal = c;
style.foreground.normal = c == style_color ? c : ic;
IMUI_Style_Update (debug_imui, &style);
UI_Radio (&style_color, c, va (0, "##color_%x%x", y, x));
if (x == 15) {
style.background.normal = bg_save;
style.foreground.normal = fg_save;
IMUI_Style_Update (debug_imui, &style);
UI_FlexibleSpace ();
}
}
}
}
if (style_selection == 0) {
current_style.background.color[style_mode] = style_color;
} else if (style_selection == 1) {
current_style.foreground.color[style_mode] = style_color;
} else if (style_selection == 2) {
current_style.text.color[style_mode] = style_color;
}
}
}
static transform_t
create_debug_camera (void)
{
debug_camera_pivot = Transform_New (debug_scene->reg, nulltransform);
debug_camera = Transform_New (debug_scene->reg, debug_camera_pivot);
return debug_camera;
}
static void
camera_mouse_first_person (void)
{
vec4f_t delta_pos = {};
vec4f_t delta_rot = {};
delta_pos[0] -= IN_UpdateAxis (&deb_move_forward);
delta_pos[1] -= IN_UpdateAxis (&deb_move_side);
delta_pos[2] -= IN_UpdateAxis (&deb_move_up);
float dt = *con_data.frametime;
vec4f_t rot = Transform_GetLocalRotation (debug_camera_pivot);
delta_pos = qvmulf (rot, delta_pos) * dt;
vec4f_t pos = Transform_GetLocalPosition (debug_camera_pivot);
Transform_SetLocalPosition (debug_camera_pivot, pos + delta_pos);
delta_rot[PITCH] -= IN_UpdateAxis (&deb_move_pitch);
delta_rot[YAW] -= IN_UpdateAxis (&deb_move_yaw);
delta_rot[ROLL] -= IN_UpdateAxis (&deb_move_roll);
delta_rot *= dt;
vec4f_t drot;
AngleQuat ((vec_t*)&delta_rot, (vec_t*)&drot);
vec4f_t r = normalf (qmulf (rot, drot));
Transform_SetLocalRotation (debug_camera_pivot, r);
}
static vec4f_t
trackball_vector (vec4f_t xy)
{
// xy is already in -1..1 order of magnitude range (ie, might be a bit
// over due to screen aspect)
// This is very similar to blender's trackball calculation (based on it,
// really)
float r = 1;
float t = r * r / 2;
float d = dotf (xy, xy)[0];
vec4f_t vec = xy;
if (d < t) {
// less than 45 degrees around the sphere from the viewer facing
// pole, so map the mouse point to the sphere
vec[2] = sqrt (r * r - d);
} else {
// beyond 45 degrees around the sphere from the veiwer facing
// pole, so the slope is rapidly approaching infinity or the mouse
// point may miss the sphere entirely, so instead map the mouse
// point to the hyperbolic cone pointed towards the viewer. The
// cone and sphere are tangential at the 45 degree latitude
vec[2] = t / sqrt (d);
}
return (vec4f_t) { vec[2], vec[0], vec[1] };
}
static float trackball_sensitivity = 0.1;
#define sphere_scale 1.0f
static void
camera_mouse_trackball (void)
{
vec4f_t delta = {
IN_UpdateAxis (&deb_mouse_x),
IN_UpdateAxis (&deb_mouse_y),
};
float size = min (deb_xlen, deb_ylen) / 2;
vec4f_t center = { deb_xlen, deb_ylen }; center /= 2;
vec4f_t start = mouse_start - center;
vec4f_t end = start + delta;
start = trackball_vector (start / (size * sphere_scale));
end = trackball_vector (end / (size * sphere_scale));
vec4f_t drot = crossf (end, start);
float ma = dotf (drot, drot)[0];
if (ma < 1e-7) {
return;
}
drot /= sqrtf (ma);
float dist = sqrtf (dotf (delta, delta)[0]) * trackball_sensitivity;
dist /= size;
drot *= sinf (dist);
drot[3] = cosf (dist);
vec4f_t rot = Transform_GetLocalRotation (debug_camera_pivot);
vec4f_t r = normalf (qmulf (rot, drot));
Transform_SetLocalRotation (debug_camera_pivot, r);
}
static void
hs (void)
{
IMUI_Spacer (debug_imui, imui_size_pixels, 10, imui_size_expand, 100);
}
static imui_window_t system_info_window = {
.name = "System Info##window",
.xpos = 50,
.ypos = 50,
};
static imui_window_t cam_window = {
.name = "Debug Camera",
};
static imui_window_t inp_window = {
.name = "Debug Input",
};
static imui_window_t debug_menu = {
.name = "Debug##menu",
.group_offset = 0,
.is_open = true,
.no_collapse = true,
};
static imui_window_t renderer_menu = {
.name = "Renderer##menu",
.group_offset = 1,
.reference_gravity = grav_northwest,
.anchor_gravity = grav_southwest,
};
static void
menu_bar (void)
{
UI_MenuBar (&debug_menu) {
if (UI_MenuItem ("System Info##menu_item")) {
system_info_window.is_open = true;
}
hs ();
if (UI_MenuItem ("Camera")) {
cam_window.is_open = true;
}
hs ();
if (UI_MenuItem ("Input")) {
inp_window.is_open = true;
}
if (r_funcs->debug_ui) {
hs ();
// create the menu so the renderer can access it
UI_Menu (&renderer_menu);
}
}
}
static void
camera_window (void)
{
static int cam_state;
static int cam_mode;
int old_mode = cam_mode;
UI_Window (&cam_window) {
if (cam_window.is_collapsed) {
continue;
}
UI_Horizontal {
UI_Radio (&cam_state, 0, "Game##camera");
IMUI_Spacer (debug_imui, imui_size_pixels, 10,
imui_size_expand, 100);
UI_Radio (&cam_state, 1, "Debug##camera");
UI_FlexibleSpace ();
}
if (cam_state) {
UI_Horizontal {
UI_Radio (&cam_mode, 0, "First Person##camera");
IMUI_Spacer (debug_imui, imui_size_pixels, 10,
imui_size_expand, 100);
UI_Radio (&cam_mode, 1, "Trackball##camera");
// IMUI_Spacer (debug_imui, imui_size_pixels, 10,
// imui_size_expand, 100);
// UI_Radio (&cam_mode, 2, "Turntable##camera");
UI_FlexibleSpace ();
}
UI_Horizontal {
UI_Checkbox (&r_lock_viewleaf, "Lock VIS##camera");
UI_FlexibleSpace ();
}
}
if (r_override_camera) {
if (cam_mode == 0) {
camera_mouse_first_person();
} else if (cam_mode == 1) {
camera_mouse_trackball ();
}
}
}
if (cam_state) {
if (!Transform_Valid (r_camera)) {
r_camera = create_debug_camera ();
}
if (!r_override_camera || old_mode != cam_mode) {
// the camera is still whatever the client set it to (or what
// the renderer last used if switching modes)
static vec4f_t forward = {1, 0, 0, 0};
static vec4f_t up = {0, 0, 1, 0};
static vec4f_t qident = {0, 0, 0, 1};
vec4f_t f = r_data->refdef->camera[0]; //X is forward
vec4f_t u = r_data->refdef->camera[2]; //Z is up
vec4f_t q1 = qrotf (forward, f);
vec4f_t up1 = qvmulf (q1, up);
u -= dotf (u, f) * f; // ensure orthogonal (should be, but...)
vec4f_t q2 = qrotf (up1, u);
vec4f_t q = qmulf (q2, q1);
Transform_SetLocalRotation (debug_camera_pivot, q);
vec4f_t pos = r_data->refdef->camera[3];
float dist = cam_mode == 0 ? 0 : 128;
vec4f_t offs = dist * Transform_Forward (debug_camera_pivot);
Transform_SetLocalPosition (debug_camera_pivot, pos + offs);
Transform_SetLocalRotation (debug_camera, qident);
Transform_SetLocalPosition (debug_camera, (vec4f_t) {-dist,0,0,1});
}
r_override_camera = true;
} else {
r_override_camera = false;
}
}
static void
input_window (void)
{
UI_Window (&inp_window) {
if (inp_window.is_collapsed) {
continue;
}
for (int i = 0; deb_in_axes[i]; i++) {
auto axis = deb_in_axes[i];
UI_Horizontal {
UI_Label (axis->name);
UI_FlexibleSpace ();
UI_Labelf ("%8g", axis->rel_input);
}
}
}
}
static bool close_debug_pressed = false;
static void
system_info (void)
{
UI_Window (&system_info_window) {
if (system_info_window.is_collapsed) {
continue;
}
UI_Vertical {
UI_Horizontal {
if (UI_Button ("Close Debug")) {
close_debug_pressed = true;
}
IMUI_Spacer (debug_imui, imui_size_pixels, 10,
imui_size_expand, 100);
if (UI_Button ("Screenshot")) {
Cbuf_AddText (con_data.cbuf, "screenshot\n");
}
UI_FlexibleSpace ();
}
#if 0
for (int i = 0; deb_in_axes[i]; i++) {
UI_Horizontal {
UI_Label (deb_in_axes[i]->name);
UI_FlexibleSpace ();
//IN_UpdateAxis (deb_in_axes[i]);
UI_Labelf ("%6.3f", deb_in_axes[i]->value);
}
}
#endif
static int64_t prev_time;
static int64_t min_delta = INT64_MAX;
static int64_t max_delta = -INT64_MAX;
int64_t cur_time = Sys_LongTime ();
int64_t delta = cur_time - prev_time;
prev_time = cur_time;
min_delta = min (min_delta, delta);
max_delta = max (max_delta, delta);
UI_Horizontal {
UI_Label ("frame: ");
UI_FlexibleSpace ();
UI_Labelf ("%'7"PRIu64"\u03bcs##frame.time", min_delta);
UI_Labelf ("%'7"PRIu64"\u03bcs##frame.time", delta);
UI_Labelf ("%'7"PRIu64"\u03bcs##frame.time", max_delta);
}
UI_Horizontal {
UI_FlexibleSpace ();
if (UI_Button ("Reset##timings")) {
max_delta = -INT64_MAX;
min_delta = INT64_MAX;
}
}
UI_Horizontal {
UI_Labelf ("mem: %'zd", Sys_CurrentRSS ());
UI_FlexibleSpace ();
}
UI_FlexibleSpace ();
}
}
}
void
Con_Debug_Draw (void)
{
if (debug_enable_time && Sys_LongTime () - debug_enable_time > 1000) {
debug_saved_focus = IE_Get_Focus ();
IE_Set_Focus (debug_event_id);
debug_saved_context = IMT_GetContext ();
IMT_SetContext (debug_context);
debug_enable_time = 0;
}
IMUI_BeginFrame (debug_imui);
IMUI_Style_Update (debug_imui, &current_style);
menu_bar ();
system_info ();
color_window ();
camera_window ();
input_window ();
if (r_funcs->debug_ui) {
r_funcs->debug_ui (debug_imui);
}
if (close_debug_pressed) {
close_debug_pressed = false;
close_debug ();
}
IMUI_Draw (debug_imui);
}

View file

@ -46,6 +46,7 @@
#include "QF/console.h"
#include "QF/cvar.h"
#include "QF/dstring.h"
#include "QF/input.h"
#include "QF/keys.h"
#include "QF/qargs.h"
#include "QF/quakefs.h"
@ -61,6 +62,7 @@
#include "QF/ui/inputline.h"
#include "QF/ui/view.h"
#include "cl_console.h"
#include "compat.h"
static con_buffer_t *con;
@ -155,8 +157,11 @@ static uint32_t canvas_base;
static uint32_t view_base;
static con_state_t con_state;
static bool con_hide_mouse; // external requested state
static bool con_show_mouse; // local (overrides con_hide_mouse)
static bool con_force_mouse_visible;// internal (overrides all for show)
static int con_event_id;
static int con_saved_focos;
static int con_saved_focus;
static bool con_debuglog;
static bool chat_team;
@ -332,16 +337,37 @@ ClearNotify (void)
}
static void
C_SetState (con_state_t state)
con_update_mouse (void)
{
bool show_cursor = (con_force_mouse_visible
|| con_show_mouse
|| !con_hide_mouse);
VID_SetCursor (show_cursor);
IN_UpdateGrab (show_cursor ? 0 : in_grab);
}
void
Con_Show_Mouse (bool visible)
{
con_show_mouse = visible;
con_update_mouse ();
}
static void
C_SetState (con_state_t state, bool hide_mouse)
{
con_state_t old_state = con_state;
con_state = state;
con_hide_mouse = hide_mouse;
if (con_state == con_inactive) {
IE_Set_Focus (con_saved_focos);
IE_Set_Focus (con_saved_focus);
con_force_mouse_visible = false;
} else if (old_state == con_inactive) {
con_saved_focos = IE_Get_Focus ();
con_saved_focus = IE_Get_Focus ();
IE_Set_Focus (con_event_id);
con_force_mouse_visible = true;
}
con_update_mouse ();
if (state == con_message) {
say_line.prompt = "say:";
@ -369,10 +395,10 @@ ToggleConsole_f (void)
case con_message:
return;
case con_inactive:
C_SetState (con_active);
C_SetState (con_active, con_hide_mouse);
break;
case con_active:
C_SetState (con_inactive);
C_SetState (con_inactive, con_hide_mouse);
break;
case con_fullscreen:
break;
@ -413,7 +439,7 @@ static void
con_end_message (inputline_t *line)
{
Con_ClearTyping (line, 1);
C_SetState (con_inactive);
C_SetState (con_inactive, con_hide_mouse);
}
static void
@ -545,14 +571,14 @@ draw_input_line (inputline_t *il, draw_charbuffer_t *buffer)
char *src = il->lines[il->edit_line] + il->scroll + 1;
size_t i;
*dst++ = il->scroll ? '<' | 0x80 : il->lines[il->edit_line][0];
*dst++ = il->scroll ? (char) ('<' | 0x80) : il->lines[il->edit_line][0];
for (i = 0; i < il->width - 2 && *src; i++) {
*dst++ = *src++;
}
while (i++ < il->width - 2) {
*dst++ = ' ';
}
*dst++ = *src ? '>' | 0x80 : ' ';
*dst++ = *src ? (char) ('<' | 0x80) : ' ';
}
static void
@ -765,6 +791,9 @@ setup_console (void)
static void
C_DrawConsole (void)
{
if (con_debug) {
Con_Debug_Draw ();
}
setup_console ();
view_pos_t screen_len = View_GetLen (screen_view);
@ -839,8 +868,8 @@ con_set_size (void)
int xlen = win_xlen / con_scale;
int ylen = win_ylen / con_scale;
if (xlen > 0 && ylen > 0) {
View_SetLen (screen_view, xlen, ylen);
View_UpdateHierarchy (screen_view);
Canvas_SetLen (*con_data.canvas_sys, screen_canvas,
(view_pos_t) { xlen, ylen });
}
}
@ -979,7 +1008,7 @@ MessageMode_f (void)
if (con_state != con_inactive)
return;
chat_team = false;
C_SetState (con_message);
C_SetState (con_message, con_hide_mouse);
}
static void
@ -988,7 +1017,7 @@ MessageMode2_f (void)
if (con_state != con_inactive)
return;
chat_team = true;
C_SetState (con_message);
C_SetState (con_message, con_hide_mouse);
}
static void
@ -1032,6 +1061,7 @@ C_InitCvars (void)
Cvar_Register (&con_size_cvar, 0, 0);
Cvar_Register (&con_speed_cvar, 0, 0);
Cvar_Register (&cl_conmode_cvar, 0, 0);
Con_Debug_InitCvars ();
}
static void
@ -1053,6 +1083,8 @@ C_Init (void)
// The console will get resized, so assume initial size is 320x200
ecs_system_t sys = { con_data.canvas_sys->reg, view_base };
screen_canvas = Canvas_New (*con_data.canvas_sys);
Con_Debug_Init ();
screen_view = Canvas_GetRootView (*con_data.canvas_sys, screen_canvas);
console_view = View_New (sys, screen_view);
buffer_view = View_New (sys, console_view);
@ -1111,6 +1143,8 @@ C_Init (void)
con_setfitpic (console_view, conback);
}
con_linewidth = 320 / 8;
cmd_line.prompt = "";
cmd_line.input_line = Con_CreateInputLine (32, MAXCMDLINE, ']');
cmd_line.input_line->complete = Con_BasicCompleteCommandLine;
@ -1137,7 +1171,6 @@ C_Init (void)
con_setinput (say_view, &say_line);
con_setinput (command_view, &cmd_line);
view_pos_t len;
len = View_GetLen (buffer_view);
@ -1193,6 +1226,8 @@ C_Init (void)
static void
C_shutdown (void)
{
Con_Debug_Shutdown ();
r_funcs->Draw_DestroyPic (conback);
IE_Remove_Handler (con_event_id);
Menu_Shutdown ();

View file

@ -175,10 +175,10 @@ Con_Print (const char *fmt, va_list args)
}
VISIBLE void
Con_SetState (con_state_t state)
Con_SetState (con_state_t state, bool hide_mouse)
{
if (con_module) {
con_module->functions->console->set_state (state);
con_module->functions->console->set_state (state, hide_mouse);
}
}

View file

@ -54,6 +54,8 @@
#include "QF/plugin/console.h"
#include "QF/plugin/vid_render.h"
#include "cl_console.h"
typedef struct menu_pic_s {
struct menu_pic_s *next;
int x, y;
@ -378,7 +380,7 @@ bi_Menu_SelectMenu (progs_t *pr, void *data)
if (name && *name)
menu = Hash_Find (menu_hash, name);
if (menu) {
Con_SetState (con_menu);
Con_SetState (con_menu, true);
if (menu->enter_hook) {
run_menu_pre ();
PR_ExecuteProgram (&menu_pr_state, menu->enter_hook);
@ -387,7 +389,7 @@ bi_Menu_SelectMenu (progs_t *pr, void *data)
} else {
if (name && *name)
Sys_Printf ("no menu \"%s\"\n", name);
Con_SetState (con_inactive);
Con_SetState (con_inactive, true);
}
}
@ -472,7 +474,7 @@ bi_Menu_Leave (progs_t *pr, void *data)
}
menu = menu->parent;
if (!menu) {
Con_SetState (con_inactive);
Con_SetState (con_inactive, true);
}
}
}
@ -851,14 +853,14 @@ void
Menu_Enter ()
{
if (!top_menu) {
Con_SetState (con_active);
Con_SetState (con_active, true);
return;
}
if (!menu) {
menu = Hash_Find (menu_hash, top_menu);
}
if (menu) {
Con_SetState (con_menu);
Con_SetState (con_menu, true);
if (menu->enter_hook) {
run_menu_pre ();
PR_ExecuteProgram (&menu_pr_state, menu->enter_hook);
@ -878,7 +880,7 @@ Menu_Leave ()
}
menu = menu->parent;
if (!menu) {
Con_SetState (con_inactive);
Con_SetState (con_inactive, true);
}
}
}

View file

@ -146,11 +146,7 @@ enum {
sv_cursor = 8,
};
#ifdef HAVE_NCURSES
static int use_curses = 1;
#else
static int use_curses = 0;
#endif
static view_t sv_view;
static view_t output;
@ -855,12 +851,14 @@ C_ProcessInput (void)
static void
C_DrawConsole (void)
{
#ifdef HAVE_NCURSES
// only the status bar is drawn because the inputline and output views
// take care of themselves
if (use_curses) {
draw_status (status);
sv_refresh_windows ();
}
#endif
}
static void

View file

@ -141,13 +141,12 @@ static int
test_3 (void)
{
int ret = 1;
static char text[] = R"(01 don't forget this line
02 and some more lines here
03 adsf
04 adfa
06 hi there
06 don't forget there's line 07
)";
static char text[] = "01 don't forget this line\n\
02 and some more lines here\n\
03 adsf\n\
04 adfa\n\
06 hi there\n\
06 don't forget there's line 07\n";
static uint32_t lengths[] = { 26, 28, 9, 8, 12, 32, 0 };
static uint32_t lengths2[] = { 1, 5, 2 };

View file

@ -88,12 +88,13 @@ ECS_CreateComponentPools (ecs_registry_t *registry)
{
uint32_t count = registry->components.size;
registry->comp_pools = calloc (count, sizeof (ecs_pool_t));
registry->subpools = calloc (count, sizeof (ecs_subpool_t));
size_t size = registry->max_entities * sizeof (uint32_t);
for (uint32_t i = 0; i < count; i++) {
registry->comp_pools[i].sparse = malloc (size);
memset (registry->comp_pools[i].sparse, nullent, size);
registry->subpools[i].next = nullent;
}
registry->subpools = calloc (count, sizeof (ecs_subpool_t));
}
typedef struct {

View file

@ -116,7 +116,6 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry)
uint32_t ind = pool->sparse[id];
component_t *c = &registry->components.a[comp];
if (ind < pool->count && pool->dense[ind] == ent) {
uint32_t last = pool->count - 1;
// invalidate the entity for this component to prevent the component
// being double-removed due to deletion of the component resulting
// in the entity being deleted (happens with hierarchies)
@ -137,6 +136,7 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry)
}
}
}
uint32_t last = pool->count - 1;
if (last > ind) {
pool->sparse[Ent_Index (pool->dense[last])] = ind;
pool->dense[ind] = pool->dense[last];

View file

@ -43,6 +43,10 @@ static component_t ent_component = { .size = sizeof (uint32_t) };
static component_t childCount_component = { .size = sizeof (uint32_t) };
static component_t childIndex_component = { .size = sizeof (uint32_t) };
static component_t parentIndex_component = { .size = sizeof (uint32_t) };
static component_t nextIndex_component = { .size = sizeof (uint32_t) };
static component_t lastIndex_component = { .size = sizeof (uint32_t) };
static void
hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start,
@ -107,6 +111,10 @@ Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count)
(void **) &hierarchy->childIndex, new_max);
Component_ResizeArray (&parentIndex_component,
(void **) &hierarchy->parentIndex, new_max);
Component_ResizeArray (&nextIndex_component,
(void **) &hierarchy->nextIndex, new_max);
Component_ResizeArray (&lastIndex_component,
(void **) &hierarchy->lastIndex, new_max);
if (hierarchy->type) {
for (uint32_t i = 0; i < hierarchy->type->num_components; i++) {
@ -126,6 +134,9 @@ hierarchy_open (hierarchy_t *hierarchy, uint32_t index, uint32_t count)
hierarchy->num_objects += count;
uint32_t dstIndex = index + count;
count = hierarchy->num_objects - index - count;
if (!count) {
return;
}
Component_MoveElements (&ent_component,
hierarchy->ent, dstIndex, index, count);
Component_MoveElements (&childCount_component,
@ -134,6 +145,10 @@ hierarchy_open (hierarchy_t *hierarchy, uint32_t index, uint32_t count)
hierarchy->childIndex, dstIndex, index, count);
Component_MoveElements (&parentIndex_component,
hierarchy->parentIndex, dstIndex, index, count);
Component_MoveElements (&nextIndex_component,
hierarchy->nextIndex, dstIndex, index, count);
Component_MoveElements (&lastIndex_component,
hierarchy->lastIndex, dstIndex, index, count);
if (hierarchy->type) {
for (uint32_t i = 0; i < hierarchy->type->num_components; i++) {
Component_MoveElements (&hierarchy->type->components[i],
@ -160,6 +175,10 @@ hierarchy_close (hierarchy_t *hierarchy, uint32_t index, uint32_t count)
hierarchy->childIndex, index, srcIndex, count);
Component_MoveElements (&parentIndex_component,
hierarchy->parentIndex, index, srcIndex, count);
Component_MoveElements (&nextIndex_component,
hierarchy->nextIndex, index, srcIndex, count);
Component_MoveElements (&lastIndex_component,
hierarchy->lastIndex, index, srcIndex, count);
if (hierarchy->type) {
for (uint32_t i = 0; i < hierarchy->type->num_components; i++) {
Component_MoveElements (&hierarchy->type->components[i],
@ -210,6 +229,7 @@ hierarchy_init (hierarchy_t *dst, uint32_t index,
dst->parentIndex[index + i] = parentIndex;
dst->childCount[index + i] = 0;
dst->childIndex[index + i] = childIndex;
dst->lastIndex[index + i] = nullindex;
}
if (dst->type) {
for (uint32_t i = 0; i < dst->type->num_components; i++) {
@ -220,8 +240,8 @@ hierarchy_init (hierarchy_t *dst, uint32_t index,
}
static uint32_t
hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src,
uint32_t dstParent, uint32_t *srcRoot, uint32_t count)
hierarchy_insert_flat (hierarchy_t *dst, const hierarchy_t *src,
uint32_t dstParent, uint32_t *srcRoot, uint32_t count)
{
uint32_t insertIndex; // where the objects will be inserted
uint32_t childIndex; // where the objects' children will inserted
@ -271,6 +291,62 @@ hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src,
return insertIndex;
}
static uint32_t
hierarchy_insert_tree (hierarchy_t *dst, const hierarchy_t *src,
uint32_t dstParent, uint32_t *srcRoot, uint32_t count)
{
uint32_t insertIndex;
if (dst == src) {
// reparenting within the hierarchy, so need only to update indices
// of course, easier said than done
insertIndex = *srcRoot;
uint32_t srcParent = dst->parentIndex[insertIndex];
uint32_t *next = &dst->nextIndex[srcParent];
while (*next != insertIndex) {
next = &dst->nextIndex[*next];
}
if (dst->lastIndex[srcParent] == insertIndex) {
// removing src from the end of srcParent's child chain
dst->lastIndex[srcParent] = next - dst->nextIndex;
}
*next = dst->nextIndex[insertIndex];
dst->nextIndex[insertIndex] = nullindex;
dst->nextIndex[dst->lastIndex[dstParent]] = insertIndex;
dst->lastIndex[dstParent] = insertIndex;
} else {
// new objecs are always appended
insertIndex = dst->num_objects;
hierarchy_open (dst, insertIndex, count);
if (dst->childCount[dstParent]) {
dst->nextIndex[dst->lastIndex[dstParent]] = insertIndex;
} else {
dst->childIndex[dstParent] = insertIndex;
}
dst->childCount[dstParent] += count;
dst->lastIndex[dstParent] = insertIndex;
dst->nextIndex[insertIndex] = nullindex;
if (src) {
hierarchy_move (dst, src, insertIndex, *srcRoot, count);
} else {
hierarchy_init (dst, insertIndex, dstParent, nullindex, count);
}
}
return insertIndex;
}
static uint32_t
hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src,
uint32_t dstParent, uint32_t *srcRoot, uint32_t count)
{
if (dst->tree_mode) {
return hierarchy_insert_tree (dst, src, dstParent, srcRoot, count);
} else {
return hierarchy_insert_flat (dst, src, dstParent, srcRoot, count);
}
}
static void
hierarchy_insert_children (hierarchy_t *dst, const hierarchy_t *src,
uint32_t dstParent, uint32_t *srcRoot)
@ -297,7 +373,7 @@ hierarchy_insertHierarchy (hierarchy_t *dst, const hierarchy_t *src,
{
uint32_t insertIndex;
if (dstParent == nullent) {
if (dstParent == nullindex) {
if (dst->num_objects) {
Sys_Error ("attempt to insert root in non-empty hierarchy");
}
@ -305,7 +381,7 @@ hierarchy_insertHierarchy (hierarchy_t *dst, const hierarchy_t *src,
if (src) {
hierarchy_move (dst, src, 0, *srcRoot, 1);
}
dst->parentIndex[0] = nullent;
dst->parentIndex[0] = nullindex;
dst->childIndex[0] = 1;
dst->childCount[0] = 0;
insertIndex = 0;
@ -361,6 +437,9 @@ void
Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index,
int delEntities)
{
if (hierarchy->tree_mode) {
Sys_Error ("Hierarchy_RemoveHierarchy tree mode not implemented");
}
uint32_t parentIndex = hierarchy->parentIndex[index];
hierarchy_remove_children (hierarchy, index, delEntities);
@ -371,7 +450,7 @@ Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index,
hierarchy_close (hierarchy, index, 1);
hierarchy_UpdateTransformIndices (hierarchy, index, -1);
if (parentIndex != nullent) {
if (parentIndex != nullindex) {
hierarchy_UpdateChildIndices (hierarchy, parentIndex + 1, -1);
hierarchy->childCount[parentIndex] -= 1;
}
@ -394,20 +473,21 @@ Hierarchy_New (ecs_registry_t *reg, uint32_t href_comp,
if (createRoot) {
hierarchy_open (hierarchy, 0, 1);
hierarchy_init (hierarchy, 0, nullent, 1, 1);
hierarchy_init (hierarchy, 0, nullindex, 1, 1);
}
return hierarchy;
}
void
Hierarchy_Delete (hierarchy_t *hierarchy)
static void
hierarchy_delete (hierarchy_t *hierarchy)
{
hierarchy_InvalidateReferences (hierarchy, 0, hierarchy->num_objects);
free (hierarchy->ent);
free (hierarchy->childCount);
free (hierarchy->childIndex);
free (hierarchy->parentIndex);
free (hierarchy->nextIndex);
free (hierarchy->lastIndex);
if (hierarchy->type) {
for (uint32_t i = 0; i < hierarchy->type->num_components; i++) {
free (hierarchy->components[i]);
@ -419,10 +499,138 @@ Hierarchy_Delete (hierarchy_t *hierarchy)
PR_RESFREE (reg->hierarchies, hierarchy);
}
void
Hierarchy_Delete (hierarchy_t *hierarchy)
{
hierarchy_InvalidateReferences (hierarchy, 0, hierarchy->num_objects);
hierarchy_delete (hierarchy);
}
static uint32_t
copy_one_node (hierarchy_t *dst, const hierarchy_t *src,
uint32_t dstIndex, uint32_t childIndex)
{
uint32_t srcIndex = dst->parentIndex[dstIndex];
uint32_t childCount = src->childCount[srcIndex];
dst->childIndex[dstIndex] = childIndex;
dst->childCount[dstIndex] = childCount;
dst->ent[dstIndex] = src->ent[srcIndex];
if (dst->type) {
for (uint32_t i = 0; i < dst->type->num_components; i++) {
Component_CopyElements (&dst->type->components[i],
dst->components[i], dstIndex,
src->components[i], srcIndex, 1);
}
}
return srcIndex;
}
static uint32_t
queue_tree_nodes (hierarchy_t *dst, const hierarchy_t *src,
uint32_t queueIndex, uint32_t srcIndex)
{
uint32_t srcChild = src->childIndex[srcIndex];
uint32_t childCount = src->childCount[srcIndex];
for (uint32_t i = 0; i < childCount; i++) {
dst->parentIndex[queueIndex + i] = srcChild;
srcChild = src->nextIndex[srcChild];
}
return childCount;
}
static void
copy_tree_nodes (hierarchy_t *dst, const hierarchy_t *src,
uint32_t dstIndex, uint32_t *queueIndex)
{
auto ind = copy_one_node (dst, src, dstIndex, *queueIndex);
auto count = queue_tree_nodes (dst, src, *queueIndex, ind);
*queueIndex += count;
}
static void
swap_pointers (void *a, void *b)
{
void *t = *(void **)a;
*(void **)a = *(void **) b;
*(void **)b = t;
}
void
Hierarchy_SetTreeMode (hierarchy_t *hierarchy, bool tree_mode)
{
if (!hierarchy->tree_mode == !tree_mode) {
// no change
return;
}
hierarchy->tree_mode = tree_mode;
if (tree_mode) {
// switching from a cononical hierarchy to tree mode, noed only to
// ensure next/last indices are correct
// root node has no siblings
hierarchy->nextIndex[0] = nullindex;
for (uint32_t i = 0; i < hierarchy->num_objects; i++) {
uint32_t count = hierarchy->childCount[i];
uint32_t child = hierarchy->childIndex[i];
for (uint32_t j = 0; count && j < count - 1; j++) {
hierarchy->nextIndex[child + j] = child + j + 1;
}
hierarchy->lastIndex[i] = count ? child + count - 1 : nullindex;
if (count) {
hierarchy->nextIndex[hierarchy->lastIndex[i]] = nullindex;
} else {
hierarchy->childIndex[i] = nullindex;
}
}
return;
}
auto src = hierarchy;
auto tmp = Hierarchy_New (src->reg, src->href_comp, src->type, 0);
Hierarchy_Reserve (tmp, src->num_objects);
tmp->num_objects = src->num_objects;
// treat parentIndex as a queue for breadth-first traversal
tmp->parentIndex[0] = 0; // start at root of src
uint32_t queueIndex = 1;
for (uint32_t i = 0; i < src->num_objects; i++) {
copy_tree_nodes (tmp, src, i, &queueIndex);
}
tmp->parentIndex[0] = nullindex;
for (uint32_t i = 0; i < src->num_objects; i++) {
for (uint32_t j = 0; j < tmp->childCount[i]; j++) {
tmp->parentIndex[tmp->childIndex[i] + j] = i;
}
}
auto href_comp = src->href_comp;
for (uint32_t i = 0; i < src->num_objects; i++) {
hierref_t *ref = Ent_GetComponent (tmp->ent[i], href_comp, tmp->reg);
ref->index = i;
}
swap_pointers (&tmp->ent, &src->ent);
swap_pointers (&tmp->childCount, &src->childCount);
swap_pointers (&tmp->childIndex, &src->childIndex);
swap_pointers (&tmp->parentIndex, &src->parentIndex);
swap_pointers (&tmp->nextIndex, &src->nextIndex);
swap_pointers (&tmp->lastIndex, &src->lastIndex);
if (src->type) {
for (uint32_t i = 0; i < src->type->num_components; i++) {
swap_pointers (&tmp->components[i], &src->components[i]);
}
}
hierarchy_delete (tmp);
}
hierarchy_t *
Hierarchy_Copy (ecs_registry_t *dstReg, uint32_t href_comp,
const hierarchy_t *src)
{
if (src->tree_mode) {
Sys_Error ("Hierarchy_Copy tree mode not implemented");
}
hierarchy_t *dst = Hierarchy_New (dstReg, href_comp, src->type, 0);
size_t count = src->num_objects;
@ -441,6 +649,10 @@ Hierarchy_Copy (ecs_registry_t *dstReg, uint32_t href_comp,
dst->childIndex, 0, src->childIndex, 0, count);
Component_CopyElements (&parentIndex_component,
dst->parentIndex, 0, src->parentIndex, 0, count);
Component_CopyElements (&nextIndex_component,
dst->nextIndex, 0, src->nextIndex, 0, count);
Component_CopyElements (&lastIndex_component,
dst->lastIndex, 0, src->lastIndex, 0, count);
if (dst->type) {
for (uint32_t i = 0; i < dst->type->num_components; i++) {
Component_CopyElements (&dst->type->components[i],
@ -455,8 +667,11 @@ hierref_t
Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent,
hierarchy_t *src, uint32_t srcRoot)
{
if (src->tree_mode) {
Sys_Error ("Hierarchy_SetParent tree mode not implemented");
}
hierref_t r = {};
if (dst && dstParent != nullent) {
if (dst && dstParent != nullindex) {
if (dst->type != src->type) {
Sys_Error ("Can't set parent in hierarchy of different type");
}

View file

@ -77,14 +77,44 @@ ECS_DelSubpoolRange (ecs_registry_t *registry, uint32_t component, uint32_t id)
uint32_t next = subpool->next | Ent_NextGen (Ent_Generation (id));
uint32_t ind = Ent_Index (id);
uint32_t count = subpool->num_ranges - subpool->available;
uint32_t range = subpool->sorted[ind];
subpool->rangeids[ind] = next;
subpool->next = ind;
subpool->available++;
memmove (subpool->ranges + ind, subpool->ranges + ind + 1,
(count - 1 - ind) * sizeof (ecs_range_t));
memmove (subpool->ranges + range, subpool->ranges + range + 1,
(subpool->num_ranges - 1 - range) * sizeof (ecs_range_t));
for (uint32_t i = 0; i < count; i++) {
if (subpool->sorted[i] > ind) {
if (subpool->sorted[i] > range) {
subpool->sorted[i]--;
}
}
}
VISIBLE void
ECS_MoveSubpoolLast (ecs_registry_t *registry, uint32_t component, uint32_t id)
{
ecs_pool_t *pool = &registry->comp_pools[component];
ecs_subpool_t *subpool = &registry->subpools[component];
uint32_t ind = Ent_Index (id);
component_t *c = &registry->components.a[component];
uint32_t range = subpool->sorted[ind];
uint32_t num_ranges = subpool->num_ranges - subpool->available;
uint32_t last_range = num_ranges - 1;
uint32_t start = range ? subpool->ranges[range - 1] : 0;
uint32_t end = subpool->ranges[range];
uint32_t last = subpool->ranges[last_range];
uint32_t count = end - start;
uint32_t srcIndex = start;
uint32_t dstIndex = last - count;
for (uint32_t i = range; i < last_range; i++) {
subpool->ranges[i] = subpool->ranges[i + 1] - count;
}
for (uint32_t i = 0; i < num_ranges; i++) {
if (subpool->sorted[i] > range) {
subpool->sorted[i]--;
}
}
subpool->sorted[ind] = last_range;
Component_RotateElements (c, pool->data, dstIndex, srcIndex, count);
}

View file

@ -1,8 +1,10 @@
libs_ecs_tests = \
libs/ecs/test/test-components \
libs/ecs/test/test-compops \
libs/ecs/test/test-hierarchy \
libs/ecs/test/test-registry \
libs/ecs/test/test-subpools
libs/ecs/test/test-subpools \
libs/ecs/test/test-treehierarchy
TESTS += $(libs_ecs_tests)
@ -19,6 +21,13 @@ libs_ecs_test_test_components_LDADD= \
libs_ecs_test_test_components_DEPENDENCIES= \
$(libs_ecs_test_libs)
libs_ecs_test_test_compops_SOURCES= \
libs/ecs/test/test-compops.c
libs_ecs_test_test_compops_LDADD= \
$(libs_ecs_test_libs)
libs_ecs_test_test_compops_DEPENDENCIES= \
$(libs_ecs_test_libs)
libs_ecs_test_test_hierarchy_SOURCES= \
libs/ecs/test/test-hierarchy.c
libs_ecs_test_test_hierarchy_LDADD= \
@ -39,3 +48,10 @@ libs_ecs_test_test_subpools_LDADD= \
$(libs_ecs_test_libs)
libs_ecs_test_test_subpools_DEPENDENCIES= \
$(libs_ecs_test_libs)
libs_ecs_test_test_treehierarchy_SOURCES= \
libs/ecs/test/test-treehierarchy.c
libs_ecs_test_test_treehierarchy_LDADD= \
$(libs_ecs_test_libs)
libs_ecs_test_test_treehierarchy_DEPENDENCIES= \
$(libs_ecs_test_libs)

View file

@ -0,0 +1,86 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "QF/ecs.h"
enum {
test_comp,
};
static int counter = 0;
static void
create_test_comp (void *comp)
{
*(int *) comp = counter++;
}
static const component_t test_component[] = {
[test_comp] = {
.size = sizeof (int),
.create = create_test_comp,
.name = "position",
},
};
static int
test_rotation (const component_t *comp, int *array, uint32_t array_count,
uint32_t dstIndex, uint32_t srcIndex, uint32_t count,
int *expect)
{
counter = 0;
Component_CreateElements (comp, array, 0, array_count);
for (uint32_t i = 0; i < array_count; i++) {
if (array[i] != (int) i) {
printf ("array initialized incorrectly");
return 1;
}
}
Component_RotateElements (comp, array, dstIndex, srcIndex, count);
for (uint32_t i = 0; i < array_count; i++) {
printf ("%d ", expect[i]);
}
puts ("");
for (uint32_t i = 0; i < array_count; i++) {
printf ("%d ", array[i]);
}
puts ("");
for (uint32_t i = 0; i < array_count; i++) {
if (array[i] != expect[i]) {
printf ("array rotated incorrectly");
return 1;
}
}
return 0;
}
static int expect1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
static int expect2[] = { 0, 1, 6, 7, 8, 2, 3, 4, 5, 9 };
static int expect3[] = { 0, 1, 4, 5, 6, 7, 8, 2, 3, 9 };
static int expect4[] = { 0, 6, 7, 8, 1, 2, 3, 4, 5, 9 };
static int expect5[] = { 0, 4, 5, 6, 7, 8, 1, 2, 3, 9 };
static int *test_array = 0;
int
main (void)
{
auto comp = &test_component[test_comp];
Component_ResizeArray (comp, (void **) &test_array, 10);
if (test_rotation (comp, test_array, 10, 2, 2, 3, expect1))
return 1;
if (test_rotation (comp, test_array, 10, 2, 6, 3, expect2))
return 1;
if (test_rotation (comp, test_array, 10, 2, 4, 5, expect3))
return 1;
if (test_rotation (comp, test_array, 10, 4, 1, 5, expect4))
return 1;
if (test_rotation (comp, test_array, 10, 6, 1, 3, expect5))
return 1;
return 0;
}

View file

@ -10,13 +10,26 @@
#include "QF/mathlib.h"
#include "QF/ecs.h"
#define DFL "\e[39;49m"
#define BLK "\e[30;40m"
#define RED "\e[31;40m"
#define GRN "\e[32;40m"
#define ONG "\e[33;40m"
#define BLU "\e[34;40m"
#define MAG "\e[35;40m"
#define CYN "\e[36;40m"
#define WHT "\e[37;40m"
enum test_components {
test_subpool,
test_obj,
test_name,
test_num_components
};
#define prent(e) (Ent_Generation (e) >> ENT_IDBITS), (Ent_Index (e))
static uint32_t
obj_rangeid (ecs_registry_t *reg, uint32_t ent, uint32_t comp)
{
@ -34,8 +47,19 @@ static const component_t test_components[] = {
.name = "obj",
.rangeid = obj_rangeid,
},
[test_name] = {
.size = sizeof (const char *),
.name = "name",
},
};
static void
set_ent_name (uint32_t ent, uint32_t base, ecs_registry_t *reg,
const char *name)
{
Ent_SetComponent (ent, base + test_name, reg, &name);
}
static void
dump_sp_ids (ecs_registry_t *reg, uint32_t comp)
{
@ -44,7 +68,8 @@ dump_sp_ids (ecs_registry_t *reg, uint32_t comp)
uint32_t *id = pool->data;
for (uint32_t i = 0; i < pool->count; i++) {
printf ("ent[%d]: %d, %d\n", i, ent[i], id[i]);
const char **n = Ent_GetComponent (ent[i], test_name, reg);
printf ("ent[%d]: %2d, %2d %s\n", i, ent[i], id[i], *n);
}
}
@ -53,13 +78,43 @@ check_subpool_ranges (ecs_subpool_t *subpool, uint32_t *expect)
{
uint32_t count = subpool->num_ranges - subpool->available;
uint32_t *range = subpool->ranges;
int ret = 0;
while (count--) {
uint32_t *r = range++;
uint32_t e = *expect++;
printf ("%d: %d %d\n", (int)(r - subpool->ranges), *r, e);
printf ("%2d: %2d %2d\n", (int)(r - subpool->ranges), *r, e);
if (*r != e++) {
return 1;
ret = 1;
}
}
return ret;
}
static int
check_subpool_sorted (ecs_subpool_t *subpool)
{
uint32_t *sorted = subpool->sorted;
uint32_t *ranges = subpool->ranges;
uint32_t count = subpool->num_ranges - subpool->available;
for (uint32_t i = 0; i < count; i++) {
printf ("sorted[%d]: %d %d\n", i, sorted[i], ranges[sorted[i]]);
}
for (uint32_t i = 0; i < count; i++) {
for (uint32_t j = i + 1; j < count; j++) {
if (sorted[j] == sorted[i]) {
printf ("subpool sorted duplicated\n");
return 1;
}
if (sorted[j] >= count) {
printf ("subpool sorted out of bounds\n");
return 1;
}
if (ranges[sorted[j]] > ranges[count - 1]) {
printf ("subpool sorted bogus\n");
return 1;
}
}
}
return 0;
@ -73,7 +128,8 @@ check_obj_comps (ecs_registry_t *reg, uint32_t comp, uint32_t *expect)
int fail = 0;
for (uint32_t i = 0; i < pool->count; i++) {
printf ("val[%d]: %d %d\n", i, val[i], expect[i]);
const char **n = Ent_GetComponent (pool->dense[i], test_name, reg);
printf ("val[%d]: %2d %2d %s\n", i, val[i], expect[i], *n);
if (val[i] != expect[i]) {
fail = 1;
}
@ -93,7 +149,7 @@ main (void)
uint32_t sp2 = ECS_NewSubpoolRange (reg, base + test_obj);
uint32_t sp3 = ECS_NewSubpoolRange (reg, base + test_obj);
printf ("%d %d %d\n", sp1, sp2, sp3);
printf ("%d.%d %d.%d %d.%d\n", prent (sp1), prent (sp2), prent (sp3));
if (reg->subpools[base + test_subpool].num_ranges != 0
|| reg->subpools[base + test_subpool].available != 0) {
printf ("subpool not 0 count: %d %d\n",
@ -134,6 +190,15 @@ main (void)
Ent_SetComponent (entg, base + test_subpool, reg, &sp2);
Ent_SetComponent (enth, base + test_subpool, reg, &sp1);
set_ent_name (enta, base, reg, MAG"a"DFL);
set_ent_name (entb, base, reg, MAG"b"DFL);
set_ent_name (entc, base, reg, ONG"c"DFL);
set_ent_name (entd, base, reg, CYN"d"DFL);
set_ent_name (ente, base, reg, CYN"e"DFL);
set_ent_name (entf, base, reg, ONG"f"DFL);
set_ent_name (entg, base, reg, ONG"g"DFL);
set_ent_name (enth, base, reg, MAG"h"DFL);
dump_sp_ids (reg, base + test_subpool);
if (check_subpool_ranges (&reg->subpools[base + test_obj],
(uint32_t[]) { 0, 0, 0 })) {
@ -233,7 +298,7 @@ main (void)
}
sp2 = ECS_NewSubpoolRange (reg, base + test_obj);
printf ("sp2: %d\n", sp2);
printf ("sp2: %d.%d\n", prent (sp2));
if (check_subpool_ranges (&reg->subpools[base + test_obj],
(uint32_t[]) { 2, 4, 4 })) {
printf ("oops\n");
@ -256,6 +321,26 @@ main (void)
return 1;
}
if (check_subpool_sorted (&reg->subpools[base + test_obj])) {
printf ("oops\n");
return 1;
}
ECS_MoveSubpoolLast (reg, base + test_obj, sp3);
if (check_subpool_sorted (&reg->subpools[base + test_obj])) {
printf ("oops\n");
return 1;
}
if (check_subpool_ranges (&reg->subpools[base + test_obj],
(uint32_t[]) { 2, 5, 7})) {
printf ("oops\n");
return 1;
}
if (check_obj_comps (reg, base + test_obj,
(uint32_t[]) { 0, 7, 10, 11, 12, 9, 8 })) {
printf ("oops\n");
return 1;
}
ECS_DelRegistry (reg);
return 0;
}

View file

@ -0,0 +1,623 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "QF/ecs.h"
enum {
test_href,
test_name,
test_highlight,
test_num_components
};
static const component_t test_components[] = {
[test_href] = {
.size = sizeof (hierref_t),
.create = 0,//create_href,
.name = "href",
.destroy = Hierref_DestroyComponent,
},
[test_name] = {
.size = sizeof (const char *),
.name = "name",
},
[test_highlight] = {
.size = sizeof (byte),
.name = "highlight",
},
};
ecs_registry_t *test_reg;
#define DFL "\e[39;49m"
#define BLK "\e[30;40m"
#define RED "\e[31;40m"
#define GRN "\e[32;40m"
#define ONG "\e[33;40m"
#define BLU "\e[34;40m"
#define MAG "\e[35;40m"
#define CYN "\e[36;40m"
#define WHT "\e[37;40m"
static int
check_hierarchy_size (hierarchy_t *h, uint32_t size)
{
if (h->num_objects != size) {
printf ("hierarchy does not have exactly %u transform\n", size);
return 0;
}
ecs_registry_t *reg = h->reg;
for (uint32_t i = 0; i < h->num_objects; i++) {
hierref_t *ref = Ent_GetComponent (h->ent[i], test_href, reg);
char **name = Ent_GetComponent (h->ent[i], test_name, reg);;
if (ref->hierarchy != h) {
printf ("transform %d (%s) does not point to hierarchy\n",
i, *name);
}
}
return 1;
}
static const char *
ref_index_color (uint32_t i, uint32_t rind)
{
return rind != i ? RED : DFL;
}
static const char *
parent_index_color (hierarchy_t *h, uint32_t i)
{
if (!i && h->parentIndex[i] == nullindex) {
return GRN;
}
if (h->parentIndex[i] >= i) {
return RED;
}
uint32_t ci = h->childIndex[h->parentIndex[i]];
uint32_t cc = h->childCount[h->parentIndex[i]];
if (i < ci || i >= ci + cc) {
return ONG;
}
return DFL;
}
static const char *
child_index_color (hierarchy_t *h, uint32_t i)
{
if (h->tree_mode) {
if ((h->childCount[i] && h->childIndex[i] == nullindex)
|| (!h->childCount[i] && h->childIndex[i] != nullindex)) {
return RED;
}
if (h->childIndex[i] != nullindex
&& h->childIndex[i] >= h->num_objects) {
return RED;
}
} else {
if (h->childIndex[i] > h->num_objects
|| h->childCount[i] > h->num_objects
|| h->childIndex[i] + h->childCount[i] > h->num_objects) {
return RED;
}
if (h->childIndex[i] <= i) {
return ONG;
}
}
return DFL;
}
static const char *
child_count_color (hierarchy_t *h, uint32_t i)
{
if (h->childCount[i] > h->num_objects) {
return RED;
}
if (h->tree_mode) {
if ((h->childCount[i] && h->childIndex[i] == nullindex)
|| (!h->childCount[i] && h->childIndex[i] != nullindex)) {
return RED;
}
} else {
if (h->childIndex[i] > h->num_objects
|| h->childIndex[i] + h->childCount[i] > h->num_objects) {
return RED;
}
}
return DFL;
}
static bool
check_for_loops (hierarchy_t *h)
{
for (uint32_t i = 0; i < h->num_objects; i++) {
if (!h->childCount[i]) {
continue;
}
uint32_t n, c;
for (n = h->childIndex[i], c = h->childCount[i];
n != nullindex; n = h->nextIndex[n], c--) {
if (!c) {
break;
}
}
if (!c && n != nullindex) {
printf ("too many children at %d\n", i);
return false;
}
if (c && n == nullindex) {
printf ("too few children at %d\n", i);
return false;
}
if (c && n != nullindex) {
printf ("what the what?!? at %d\n", i);
return false;
}
}
return true;
}
static bool
check_next_index (hierarchy_t *h, uint32_t i)
{
if (i == 0) {
// root never has siblings
if (h->nextIndex[i] != nullindex) {
return false;
}
return true;
}
uint32_t p;
if ((p = h->parentIndex[i]) >= h->num_objects
|| h->childIndex[p] > h->num_objects
|| h->childCount[p] > h->num_objects
|| h->childIndex[p] + h->childCount[p] > h->num_objects
|| h->lastIndex[p] >= h->num_objects
|| (h->nextIndex[i] == nullindex && h->lastIndex[p] != i)
|| (h->nextIndex[i] != nullindex && h->lastIndex[p] == i)) {
return false;
}
if (h->nextIndex[i] != nullindex && h->parentIndex[h->nextIndex[i]] != p) {
return false;
}
return true;
}
static const char *
next_index_color (hierarchy_t *h, uint32_t i)
{
return check_next_index (h, i) ? DFL : RED;
}
static bool
check_last_index (hierarchy_t *h, uint32_t i)
{
if ((h->childCount[i] && h->childIndex[i] >= h->num_objects)
|| h->childCount[i] >= h->num_objects
|| (h->childCount[i] && h->lastIndex[i] == nullindex)
|| (!h->childCount[i] && h->lastIndex[i] != nullindex)) {
return false;
}
if (h->lastIndex[i] != nullindex && h->parentIndex[h->lastIndex[i]] != i) {
return false;
}
return true;
}
static const char *
last_index_color (hierarchy_t *h, uint32_t i)
{
return check_last_index (h, i) ? DFL : RED;
}
static const char *
entity_color (hierarchy_t *h, uint32_t i)
{
return h->ent[i] == nullent ? MAG : DFL;
}
static const char *
highlight_color (hierarchy_t *h, uint32_t i)
{
uint32_t ent = h->ent[i];
if (ECS_EntValid (ent, test_reg)
&& Ent_HasComponent (ent, test_highlight, test_reg)) {
static char color_str[] = "\e[3.;4.m";
byte *color = Ent_GetComponent (ent, test_highlight, test_reg);
if (*color) {
byte fg = *color & 0x0f;
byte bg = *color >> 4;
color_str[3] = fg < 8 ? '0' + fg : '9';
color_str[6] = bg < 8 ? '0' + bg : '9';
return color_str;
}
}
return "";
}
static void
print_header (hierarchy_t *h)
{
if (h->tree_mode) {
puts ("in: ri pa ci cc ni li en|name");
} else {
puts ("in: ri pa ci cc en|name");
}
}
static void
print_line (hierarchy_t *h, uint32_t ind, int level)
{
ecs_registry_t *reg = h->reg;
uint32_t rind = nullindex;
static char fake_name[] = ONG "null" DFL;
static char *fake_nameptr = fake_name;
char **name = &fake_nameptr;
if (ECS_EntValid (h->ent[ind], reg)) {
hierref_t *ref = Ent_GetComponent (h->ent[ind], test_href, reg);
rind = ref->index;
if (Ent_HasComponent (h->ent[ind], test_name, reg)) {
name = Ent_GetComponent (h->ent[ind], test_name, reg);
}
}
printf ("%2d: %s%2d %s%2d %s%2d %s%2d", ind,
ref_index_color (ind, rind), rind,
parent_index_color (h, ind), h->parentIndex[ind],
child_index_color (h, ind), h->childIndex[ind],
child_count_color (h, ind), h->childCount[ind]);
if (h->tree_mode) {
printf (" %s%2d %s%2d",
next_index_color (h, ind), h->nextIndex[ind],
last_index_color (h, ind), h->lastIndex[ind]);
}
printf (" %s%2d"DFL"|%*s%s%s"DFL"\n",
entity_color (h, ind), h->ent[ind],
level * 3, "", highlight_color (h, ind), *name);
}
static void
dump_hierarchy (hierarchy_t *h)
{
print_header (h);
for (uint32_t i = 0; i < h->num_objects; i++) {
print_line (h, i, 0);
}
puts ("");
}
static void
dump_tree (hierarchy_t *h, uint32_t ind, int level)
{
if (ind >= h->num_objects) {
printf ("index %d out of bounds (%d)\n", ind, h->num_objects);
return;
}
if (!level) {
print_header (h);
}
print_line (h, ind, level);
if (h->tree_mode) {
uint32_t count = h->childCount[ind];
uint32_t child;
for (child = h->childIndex[ind]; count && child != nullindex;
child = h->nextIndex[child], count--) {
dump_tree (h, child, level + 1);
}
} else {
if (h->childIndex[ind] > ind) {
for (uint32_t i = 0; i < h->childCount[ind]; i++) {
if (h->childIndex[ind] + i >= h->num_objects) {
break;
}
dump_tree (h, h->childIndex[ind] + i, level + 1);
}
}
}
if (!level) {
puts ("");
}
}
static int
check_indices (uint32_t ent, uint32_t index, uint32_t parentIndex,
uint32_t childIndex, uint32_t childCount)
{
ecs_registry_t *reg = test_reg;
char **entname = Ent_GetComponent (ent, test_name, reg);;
hierref_t *ref = Ent_GetComponent (ent, test_href, reg);
hierarchy_t *h = ref->hierarchy;
if (ref->index != index) {
char **name = Ent_GetComponent (h->ent[index], test_name, reg);;
printf ("%s/%s index incorrect: expect %u got %u\n",
*entname, *name,
index, ref->index);
return 0;
}
if (h->parentIndex[index] != parentIndex) {
printf ("%s parent index incorrect: expect %u got %u\n",
*entname, parentIndex, h->parentIndex[index]);
return 0;
}
if (h->childIndex[index] != childIndex) {
printf ("%s child index incorrect: expect %u got %u\n",
*entname, childIndex, h->childIndex[index]);
return 0;
}
if (h->childCount[index] != childCount) {
printf ("%s child count incorrect: expect %u got %u\n",
*entname, childCount, h->childCount[index]);
return 0;
}
return 1;
}
static bool
check_next_last_indices (hierarchy_t *h)
{
for (uint32_t i = 0; i < h->num_objects; i++) {
if (!check_next_index (h, i)) {
printf ("incorrect next index at %d: %d\n", i, h->nextIndex[i]);
return false;
}
if (!check_last_index (h, i)) {
printf ("incorrect last index at %d: %d\n", i, h->lastIndex[i]);
return false;
}
}
return true;
}
static uint32_t
create_ent (uint32_t parent, const char *name)
{
uint32_t ent = ECS_NewEntity (test_reg);
Ent_SetComponent (ent, test_name, test_reg, &name);
hierref_t *ref = Ent_AddComponent (ent, test_href, test_reg);
if (parent != nullindex) {
hierref_t *pref = Ent_GetComponent (parent, test_href, test_reg);
ref->hierarchy = pref->hierarchy;
ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, 0,
pref->index, 0);
} else {
ref->hierarchy = Hierarchy_New (test_reg, test_href, 0, 1);
ref->index = 0;
}
ref->hierarchy->ent[ref->index] = ent;
return ent;
}
#if 0
static void
highlight_ent (uint32_t ent, byte color)
{
Ent_SetComponent (ent, test_highlight, test_reg, &color);
}
static void
set_parent (uint32_t child, uint32_t parent)
{
if (parent != nullindex) {
hierref_t *pref = Ent_GetComponent (parent, test_href, test_reg);
hierref_t *cref = Ent_GetComponent (child, test_href, test_reg);
Hierarchy_SetParent (pref->hierarchy, pref->index,
cref->hierarchy, cref->index);
} else {
hierref_t *cref = Ent_GetComponent (child, test_href, test_reg);
Hierarchy_SetParent (0, nullindex, cref->hierarchy, cref->index);
}
}
#endif
static int
test_build_hierarchy (void)
{
printf ("test_build_hierarchy\n");
uint32_t root = create_ent (nullent, "root");
uint32_t A = create_ent (root, "A");
uint32_t B = create_ent (root, "B");
uint32_t C = create_ent (root, "C");
hierref_t *ref = Ent_GetComponent (root, test_href, test_reg);
if (!check_indices (root, 0, nullindex, 1, 3)) { return 1; }
if (!check_indices (A, 1, 0, 4, 0)) { return 1; }
if (!check_indices (B, 2, 0, 4, 0)) { return 1; }
if (!check_indices (C, 3, 0, 4, 0)) { return 1; }
uint32_t B1 = create_ent (B, "B1");
if (!check_indices (root, 0, nullindex, 1, 3)) { return 1; }
if (!check_indices ( A, 1, 0, 4, 0)) { return 1; }
if (!check_indices ( B, 2, 0, 4, 1)) { return 1; }
if (!check_indices ( C, 3, 0, 5, 0)) { return 1; }
if (!check_indices (B1, 4, 2, 5, 0)) { return 1; }
uint32_t A1 = create_ent (A, "A1");
if (!check_indices (root, 0, nullindex, 1, 3)) { return 1; }
if (!check_indices ( A, 1, 0, 4, 1)) { return 1; }
if (!check_indices ( B, 2, 0, 5, 1)) { return 1; }
if (!check_indices ( C, 3, 0, 6, 0)) { return 1; }
if (!check_indices (A1, 4, 1, 6, 0)) { return 1; }
if (!check_indices (B1, 5, 2, 6, 0)) { return 1; }
uint32_t A1a = create_ent (A1, "A1a");
uint32_t B2 = create_ent (B, "B2");
uint32_t A2 = create_ent (A, "A2");
uint32_t B3 = create_ent (B, "B3");
uint32_t B2a = create_ent (B2, "B2a");
if (!check_hierarchy_size (ref->hierarchy, 11)) { return 1; }
if (!check_indices (root, 0, nullindex, 1, 3)) { return 1; }
if (!check_indices ( A, 1, 0, 4, 2)) { return 1; }
if (!check_indices ( B, 2, 0, 6, 3)) { return 1; }
if (!check_indices ( C, 3, 0, 9, 0)) { return 1; }
if (!check_indices ( A1, 4, 1, 9, 1)) { return 1; }
if (!check_indices ( A2, 5, 1, 10, 0)) { return 1; }
if (!check_indices ( B1, 6, 2, 10, 0)) { return 1; }
if (!check_indices ( B2, 7, 2, 10, 1)) { return 1; }
if (!check_indices ( B3, 8, 2, 11, 0)) { return 1; }
if (!check_indices (A1a, 9, 4, 11, 0)) { return 1; }
if (!check_indices (B2a, 10, 7, 11, 0)) { return 1; }
uint32_t D = create_ent (root, "D");
if (!check_hierarchy_size (ref->hierarchy, 12)) { return 1; }
if (!check_indices (root, 0, nullindex, 1, 4)) { return 1; }
if (!check_indices ( A, 1, 0, 5, 2)) { return 1; }
if (!check_indices ( B, 2, 0, 7, 3)) { return 1; }
if (!check_indices ( C, 3, 0, 10, 0)) { return 1; }
if (!check_indices ( D, 4, 0, 10, 0)) { return 1; }
if (!check_indices ( A1, 5, 1, 10, 1)) { return 1; }
if (!check_indices ( A2, 6, 1, 11, 0)) { return 1; }
if (!check_indices ( B1, 7, 2, 11, 0)) { return 1; }
if (!check_indices ( B2, 8, 2, 11, 1)) { return 1; }
if (!check_indices ( B3, 9, 2, 12, 0)) { return 1; }
if (!check_indices (A1a, 10, 5, 12, 0)) { return 1; }
if (!check_indices (B2a, 11, 8, 12, 0)) { return 1; }
dump_hierarchy (ref->hierarchy);
uint32_t C1 = create_ent (C, "C1");
dump_hierarchy (ref->hierarchy);
if (!check_hierarchy_size (ref->hierarchy, 13)) { return 1; }
if (!check_indices (root, 0, nullindex, 1, 4)) { return 1; }
if (!check_indices ( A, 1, 0, 5, 2)) { return 1; }
if (!check_indices ( B, 2, 0, 7, 3)) { return 1; }
if (!check_indices ( C, 3, 0, 10, 1)) { return 1; }
if (!check_indices ( D, 4, 0, 11, 0)) { return 1; }
if (!check_indices ( A1, 5, 1, 11, 1)) { return 1; }
if (!check_indices ( A2, 6, 1, 12, 0)) { return 1; }
if (!check_indices ( B1, 7, 2, 12, 0)) { return 1; }
if (!check_indices ( B2, 8, 2, 12, 1)) { return 1; }
if (!check_indices ( B3, 9, 2, 13, 0)) { return 1; }
if (!check_indices ( C1, 10, 3, 13, 0)) { return 1; }
if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; }
if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; }
dump_tree (ref->hierarchy, 0, 0);
Hierarchy_SetTreeMode (ref->hierarchy, true);
//ref->hierarchy->tree_mode = true;
dump_hierarchy (ref->hierarchy);
dump_tree (ref->hierarchy, 0, 0);
if (!check_for_loops (ref->hierarchy)) { return 1; }
if (!check_next_last_indices (ref->hierarchy)) { return 1; }
create_ent (root, "E");
create_ent (B1, "B1a");
create_ent (A2, "A2a");
dump_hierarchy (ref->hierarchy);
dump_tree (ref->hierarchy, 0, 0);
if (!check_for_loops (ref->hierarchy)) { return 1; }
if (!check_next_last_indices (ref->hierarchy)) { return 1; }
// Delete the hierarchy directly as setparent isn't fully tested
Hierarchy_Delete (ref->hierarchy);
return 0;
}
static int
test_build_hierarchy2 (void)
{
printf ("test_build_hierarchy2\n");
uint32_t root = create_ent (nullent, "root");
hierref_t *ref = Ent_GetComponent (root, test_href, test_reg);
Hierarchy_SetTreeMode (ref->hierarchy, true);
uint32_t A = create_ent (root, "A");
uint32_t A1 = create_ent (A, "A1");
uint32_t A1a = create_ent (A1, "A1a");
uint32_t A2 = create_ent (A, "A2");
uint32_t B = create_ent (root, "B");
uint32_t B1 = create_ent (B, "B1");
uint32_t B2 = create_ent (B, "B2");
uint32_t B2a = create_ent (B2, "B2a");
uint32_t B3 = create_ent (B, "B3");
uint32_t C = create_ent (root, "C");
uint32_t C1 = create_ent (C, "C1");
uint32_t D = create_ent (root, "D");
//check_indices (ent, index, parentIndex, childIndex, childCount)
#define ni nullindex
if (!check_indices (root, 0, ni, 1, 4)) { return 1; }
if (!check_indices ( A, 1, 0, 2, 2)) { return 1; }
if (!check_indices ( A1, 2, 1, 3, 1)) { return 1; }
if (!check_indices (A1a, 3, 2, ni, 0)) { return 1; }
if (!check_indices ( A2, 4, 1, ni, 0)) { return 1; }
if (!check_indices ( B, 5, 0, 6, 3)) { return 1; }
if (!check_indices ( B1, 6, 5, ni, 0)) { return 1; }
if (!check_indices ( B2, 7, 5, 8, 1)) { return 1; }
if (!check_indices (B2a, 8, 7, ni, 0)) { return 1; }
if (!check_indices ( B3, 9, 5, ni, 0)) { return 1; }
if (!check_indices ( C, 10, 0, 11, 1)) { return 1; }
if (!check_indices ( C1, 11, 10, ni, 0)) { return 1; }
if (!check_indices ( D, 12, 0, ni, 0)) { return 1; }
if (!check_next_last_indices (ref->hierarchy)) { return 1; }
if (!check_for_loops (ref->hierarchy)) { return 1; }
dump_hierarchy (ref->hierarchy);
dump_tree (ref->hierarchy, 0, 0);
Hierarchy_SetTreeMode (ref->hierarchy, true);// shouldn't do anything
if (!check_indices (root, 0, ni, 1, 4)) { return 1; }
if (!check_indices ( A, 1, 0, 2, 2)) { return 1; }
if (!check_indices ( A1, 2, 1, 3, 1)) { return 1; }
if (!check_indices (A1a, 3, 2, ni, 0)) { return 1; }
if (!check_indices ( A2, 4, 1, ni, 0)) { return 1; }
if (!check_indices ( B, 5, 0, 6, 3)) { return 1; }
if (!check_indices ( B1, 6, 5, ni, 0)) { return 1; }
if (!check_indices ( B2, 7, 5, 8, 1)) { return 1; }
if (!check_indices (B2a, 8, 7, ni, 0)) { return 1; }
if (!check_indices ( B3, 9, 5, ni, 0)) { return 1; }
if (!check_indices ( C, 10, 0, 11, 1)) { return 1; }
if (!check_indices ( C1, 11, 10, ni, 0)) { return 1; }
if (!check_indices ( D, 12, 0, ni, 0)) { return 1; }
if (!check_next_last_indices (ref->hierarchy)) { return 1; }
if (!check_for_loops (ref->hierarchy)) { return 1; }
Hierarchy_SetTreeMode (ref->hierarchy, false);
puts("Hierarchy_SetTreeMode");
dump_hierarchy (ref->hierarchy);
dump_tree (ref->hierarchy, 0, 0);
if (!check_indices (root, 0, nullindex, 1, 4)) { return 1; }
if (!check_indices ( A, 1, 0, 5, 2)) { return 1; }
if (!check_indices ( B, 2, 0, 7, 3)) { return 1; }
if (!check_indices ( C, 3, 0, 10, 1)) { return 1; }
if (!check_indices ( D, 4, 0, 11, 0)) { return 1; }
if (!check_indices ( A1, 5, 1, 11, 1)) { return 1; }
if (!check_indices ( A2, 6, 1, 12, 0)) { return 1; }
if (!check_indices ( B1, 7, 2, 12, 0)) { return 1; }
if (!check_indices ( B2, 8, 2, 12, 1)) { return 1; }
if (!check_indices ( B3, 9, 2, 13, 0)) { return 1; }
if (!check_indices ( C1, 10, 3, 13, 0)) { return 1; }
if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; }
if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; }
// Delete the hierarchy directly as setparent isn't fully tested
Hierarchy_Delete (ref->hierarchy);
return 0;
}
int
main (void)
{
test_reg = ECS_NewRegistry ();
ECS_RegisterComponents (test_reg, test_components, test_num_components);
ECS_CreateComponentPools (test_reg);
if (test_build_hierarchy ()) { return 1; }
if (test_build_hierarchy2 ()) { return 1; }
ECS_DelRegistry (test_reg);
return 0;
}

View file

@ -1,4 +1,5 @@
print("""// encoding is teemmm
print("""// encoding is rteemmm
// r = 0: forward, r = 1: reverse (also reverses component order for 2 and 3)
// t = 0: 32-bit, t = 1: 64-bit
// e = 00: 0
// e = 01: 1.0
@ -29,9 +30,9 @@ extend = [
["0", "INT64_C(0x3ff0000000000000)", "0", "INT64_C(0xbff0000000000000)"],
]
def case_str(type, ext, mode):
case = (type << 5) | (ext << 3) | (mode)
return f"case {case:03o}:"
def case_str(reverse, type, ext, mode):
case = (reverse << 6) | (type << 5) | (ext << 3) | (mode)
return f"case {case:04o}:"
def dst_str(type, ext, mode):
return f"OPC({types[type][mode]})"
@ -39,39 +40,61 @@ def dst_str(type, ext, mode):
def cast_str(type, ext, mode):
return f"(pr_{types[type][mode]}_t)"
def init_str(type, ext, mode):
def init_str(reverse, type, ext, mode):
ext_str = extend[type][ext]
src = f"OPA({src_types[type][mode]})"
if mode == 0:
if ext == 2:
ext_str = src
return f"{src}, {ext_str}"
if reverse:
return f"{ext_str}, {src}"
else:
return f"{src}, {ext_str}"
elif mode == 1:
if ext == 2:
ext_str = src
return f"{src}, {ext_str}, {ext_str}"
if reverse:
return f"{ext_str}, {ext_str}, {src}"
else:
return f"{src}, {ext_str}, {ext_str}"
elif mode == 2:
if ext == 2:
ext_str = src
return f"{src}, {ext_str}, {ext_str}, {ext_str}"
elif mode == 3:
return f"{src}[0], {src}[1], {ext_str}"
elif mode == 4:
if ext == 2:
return f"{src}[0], {src}[1], {src}[0], {src}[1]"
if reverse:
return f"{ext_str}, {ext_str}, {ext_str}, {src}"
else:
return f"{src}[0], {src}[1], {ext_str}, {ext_str}"
elif mode == 5:
return f"{src}[0], {src}[1], {src}[2], {ext_str}"
for type in range(2):
for ext in range(4):
for mode in range(6): # 6, 7 are reserved
case = case_str(type, ext, mode)
dst = dst_str(type, ext, mode)
cast = cast_str(type, ext, mode)
init = init_str(type, ext, mode)
if mode in [1, 3]:
print(f"{case} VectorSet({init}, {dst}); break;");
return f"{src}, {ext_str}, {ext_str}, {ext_str}"
elif mode == 3:
if reverse:
return f"{ext_str}, {src}[1], {src}[0]"
else:
return f"{src}[0], {src}[1], {ext_str}"
elif mode == 4:
if reverse:
if ext == 2:
return f"{src}[1], {src}[0], {src}[1], {src}[0]"
else:
print(f"{case} {dst} = {cast} {{ {init} }}; break;");
return f"{ext_str}, {ext_str}, {src}[1], {src}[0]"
else:
if ext == 2:
return f"{src}[0], {src}[1], {src}[0], {src}[1]"
else:
return f"{src}[0], {src}[1], {ext_str}, {ext_str}"
elif mode == 5:
if reverse:
return f"{ext_str}, {src}[2], {src}[1], {src}[0]"
else:
return f"{src}[0], {src}[1], {src}[2], {ext_str}"
for reverse in range(2):
for type in range(2):
for ext in range(4):
for mode in range(6): # 6, 7 are reserved
case = case_str(reverse, type, ext, mode)
dst = dst_str(type, ext, mode)
cast = cast_str(type, ext, mode)
init = init_str(reverse, type, ext, mode)
if mode in [1, 3]:
print(f"{case} VectorSet({init}, {dst}); break;");
else:
print(f"{case} {dst} = {cast} {{ {init} }}; break;");

View file

@ -3,6 +3,8 @@ bitmap_txt = """
0 0001 mmss store
0 0010 mmss push
0 0011 mmss pop
0 0111 00ts swizzle2
0 0111 01t0 wedge2
0 1ccc ttss compare
0 0000 00nn
0 0000 0000 noop
@ -155,11 +157,12 @@ compare_formats = {
"mnemonic": "{op_cmp[ccc]}.{cmp_type[tt]}",
"opname": "{op_cmp[ccc]}",
"widths": "{ss+1}, {ss+1}, {ss+1}",
"types": "{cmp_types[tt]}, {cmp_types[tt]}, ev_int",
"types": "{cmp_types[tt]}, {cmp_types[tt]}, {res_types[tt & 2]}",
"args": {
"op_cmp": compare_ccc,
"cmp_type": type_tt,
"cmp_types": etype_tt,
"res_types": etype_tt,
},
}
compare2_formats = {
@ -212,7 +215,7 @@ extend_formats = {
"opcode": "OP_EXTEND",
"mnemonic": "extend",
"opname": "extend",
"format": "%Ga %Hb %gc",
"format": "%Ga%Xb, %gc",
"widths": "-1, 0, -1",
"types": "ev_void, ev_short, ev_void",
}
@ -220,7 +223,7 @@ hops_formats = {
"opcode": "OP_HOPS",
"mnemonic": "hops",
"opname": "hops",
"format": "%Ga %Hb %gc",
"format": "%Hb %Ga, %gc",
"widths": "-1, 0, 1",
"types": "ev_void, ev_short, ev_void",
}
@ -508,15 +511,39 @@ string_formats = {
},
}
swizzle_formats = {
"opcode": "OP_SWIZZLE_{swiz_type[t]}",
"opcode": "OP_SWIZZLE_{swiz_type[t]}_4",
"mnemonic": "swizzle.{swiz_type[t]}",
"opname": "swizzle",
"format": "%Ga %sb %gc",
"format": "%Ga.%Sb %gc",
"widths": "4, 0, 4",
"types": "{swizzle_types[t]}",
"types": "{swizzle_types[t]}, ev_short, {swizzle_types[t]}",
"args": {
"swiz_type": ['F', 'D'],
"swizzle_types": float_t,
"swizzle_types": unsigned_t,
},
}
swizzle2_formats = {
"opcode": "OP_SWIZZLE_{swiz_type[t]}_{s+2}",
"mnemonic": "swizzle.{swiz_type[t]}",
"opname": "swizzle",
"format": "%Ga.%Sb %gc",
"widths": "{s+2}, 0, {s+2}",
"types": "{swizzle_types[t]}, ev_short, {swizzle_types[t]}",
"args": {
"swiz_type": ['F', 'D'],
"swizzle_types": unsigned_t,
},
}
wedge2_formats = {
"opcode": "OP_WEDGE_{wedge_type[t]}_2",
"mnemonic": "wedge.{wedge_type[t]}",
"opname": "wedge",
"format": "%Ga, %Gb, %gc",
"widths": "2, 2, 1",
"types": "{wedge_types[t]}",
"args": {
"wedge_type": ['F', 'D'],
"wedge_types": float_t,
},
}
return_formats = {
@ -551,9 +578,9 @@ vecops_formats = {
"vop_type": ['F', 'D'],
"vec_widths": [
"3, 3, 3",
"2, 2, 2",
"3, 3, 3",
"4, 4, 4",
"2, 2, 1",
"3, 3, 1",
"4, 4, 1",
"2, 2, 2",
"4, 3, 3",
"3, 4, 3",
@ -614,10 +641,12 @@ group_map = {
"store64": store64_formats,
"string": string_formats,
"swizzle": swizzle_formats,
"swizzle2": swizzle2_formats,
"return": return_formats,
"udivops": udivops_formats,
"vecops": vecops_formats,
"vecops2": vecops2_formats,
"wedge2": wedge2_formats,
"with": with_formats,
}

View file

@ -260,6 +260,8 @@ pr_debug_type_size (const progs_t *pr, const qfot_type_t *type)
case ty_alias:
aux_type = &G_STRUCT (pr, qfot_type_t, type->alias.aux_type);
return pr_debug_type_size (pr, aux_type);
case ty_algebra:
return 1; //FIXME wip
}
return 0;
}
@ -1053,6 +1055,12 @@ static void
value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value)
{
switch (type->meta) {
case ty_algebra:
if (type->type == ev_invalid) {
dstring_appendstr (data->dstr, "<?""?>");
break;
}
// fall through
case ty_handle:
case ty_basic:
switch (type->type) {
@ -1174,6 +1182,65 @@ global_string (pr_debug_data_t *data, pr_ptr_t offset, qfot_type_t *type,
return dstr->str;
}
static const char *
extend_string (pr_debug_data_t *data, pr_uint_t ext)
{
progs_t *pr = data->pr;
prdeb_resources_t *res = pr->pr_debug_resources;
static const char *extend_range[] = {
"1>2", "1>3", "1>4",
"2>3", "2>4", "3>4",
"res1", "res2",
};
static const char *extend_string[] = {
"0", "1", "c", "-1",
};
return va (res->va, "[%s%s:%s]%d",
extend_range[ext & 7],
ext & 0100 ? ":r" : "",
extend_string[(ext >> 3) & 2],
32 << ((ext >> 5) & 1));
}
static const char *
hop_string (pr_debug_data_t *data, pr_uint_t hop)
{
progs_t *pr = data->pr;
prdeb_resources_t *res = pr->pr_debug_resources;
static const char *hop_string[] = {
"and", "or", "xor", "add",
"nad", "nor", "xnor", "add",
};
static const char *type_string[2][8] = {
{"I", "I", "I", "I", "I", "I", "I", "F"},
{"L", "L", "L", "L", "L", "L", "L", "D"},
};
return va (res->va, "%s.%s{%d}",
hop_string[hop & 7],
type_string[(hop >> 5) & 1][hop & 7],
((hop >> 3) & 3) + 1);
}
static const char *
swizzle_string (pr_debug_data_t *data, pr_uint_t swiz)
{
progs_t *pr = data->pr;
prdeb_resources_t *res = pr->pr_debug_resources;
static char swizzle_components[] = "xyzw";
const char *swizzle = "";
for (int i = 0; i < 4; i++) {
if (swiz & (0x1000 << i)) {
swizzle = va (res->va, "%s0", swizzle);
} else {
swizzle = va (res->va, "%s%s%c", swizzle,
swiz & (0x100 << i) ? "-" : "",
swizzle_components[(swiz >> 2 * i) & 3]);
}
}
return swizzle;
}
const char *
PR_Debug_ValueString (progs_t *pr, pr_ptr_t offset, qfot_type_t *type,
dstring_t *dstr)
@ -1187,7 +1254,18 @@ static void
pr_debug_void_view (qfot_type_t *type, pr_type_t *value, void *_data)
{
__auto_type data = (pr_debug_data_t *) _data;
dasprintf (data->dstr, "<void>");
dstring_t *dstr = data->dstr;
if (!type->basic.width) {
dasprintf (dstr, "<void>");
return;
}
for (int i = 0; i < type->basic.width; i++, value++) {
if (i) {
dstring_appendstr (dstr, ", ");
}
dasprintf (dstr, "<%08x>", PR_PTR (int, value));
}
}
static void
@ -1238,12 +1316,23 @@ pr_debug_float_view (qfot_type_t *type, pr_type_t *value, void *_data)
__auto_type data = (pr_debug_data_t *) _data;
dstring_t *dstr = data->dstr;
if (data->pr->progs->version == PROG_ID_VERSION
&& ISDENORM (PR_PTR (int, value))
&& PR_PTR (uint, value) != 0x80000000) {
dasprintf (dstr, "<%08x>", PR_PTR (int, value));
} else {
dasprintf (dstr, "%.9g", PR_PTR (float, value));
if (type->basic.width > 1) {
dstring_appendstr (dstr, "[");
}
for (int i = 0; i < type->basic.width; i++, value++) {
if (i) {
dstring_appendstr (dstr, ", ");
}
if (data->pr->progs->version == PROG_ID_VERSION
&& ISDENORM (PR_PTR (int, value))
&& PR_PTR (uint, value) != 0x80000000) {
dasprintf (dstr, "<%08x>", PR_PTR (int, value));
} else {
dasprintf (dstr, "%.9g", PR_PTR (float, value));
}
}
if (type->basic.width > 1) {
dstring_appendstr (dstr, "]");
}
}
@ -1344,7 +1433,18 @@ pr_debug_int_view (qfot_type_t *type, pr_type_t *value, void *_data)
__auto_type data = (pr_debug_data_t *) _data;
dstring_t *dstr = data->dstr;
dasprintf (dstr, "%d", PR_PTR (int, value));
if (type->basic.width > 1) {
dstring_appendstr (dstr, "[");
}
for (int i = 0; i < type->basic.width; i++, value++) {
if (i) {
dstring_appendstr (dstr, ", ");
}
dasprintf (dstr, "%d", PR_PTR (int, value));
}
if (type->basic.width > 1) {
dstring_appendstr (dstr, "]");
}
}
static void
@ -1353,7 +1453,18 @@ pr_debug_uint_view (qfot_type_t *type, pr_type_t *value, void *_data)
__auto_type data = (pr_debug_data_t *) _data;
dstring_t *dstr = data->dstr;
dasprintf (dstr, "$%08x", PR_PTR (uint, value));
if (type->basic.width > 1) {
dstring_appendstr (dstr, "[");
}
for (int i = 0; i < type->basic.width; i++, value++) {
if (i) {
dstring_appendstr (dstr, ", ");
}
dasprintf (dstr, "$%08x", PR_PTR (uint, value));
}
if (type->basic.width > 1) {
dstring_appendstr (dstr, "]");
}
}
static void
@ -1371,7 +1482,18 @@ pr_debug_double_view (qfot_type_t *type, pr_type_t *value, void *_data)
__auto_type data = (pr_debug_data_t *) _data;
dstring_t *dstr = data->dstr;
dasprintf (dstr, "%.17g", *(double *)value);
if (type->basic.width > 1) {
dstring_appendstr (dstr, "[");
}
for (int i = 0; i < type->basic.width; i++, value += 2) {
if (i) {
dstring_appendstr (dstr, ", ");
}
dasprintf (dstr, "%.17g", *(double *)value);
}
if (type->basic.width > 1) {
dstring_appendstr (dstr, "]");
}
}
static void
@ -1380,7 +1502,18 @@ pr_debug_long_view (qfot_type_t *type, pr_type_t *value, void *_data)
__auto_type data = (pr_debug_data_t *) _data;
dstring_t *dstr = data->dstr;
dasprintf (dstr, "%" PRIi64, *(int64_t *)value);
if (type->basic.width > 1) {
dstring_appendstr (dstr, "[");
}
for (int i = 0; i < type->basic.width; i++, value += 2) {
if (i) {
dstring_appendstr (dstr, ", ");
}
dasprintf (dstr, "%" PRIi64, *(int64_t *)value);
}
if (type->basic.width > 1) {
dstring_appendstr (dstr, "]");
}
}
static void
@ -1389,7 +1522,18 @@ pr_debug_ulong_view (qfot_type_t *type, pr_type_t *value, void *_data)
__auto_type data = (pr_debug_data_t *) _data;
dstring_t *dstr = data->dstr;
dasprintf (dstr, "%" PRIu64, *(uint64_t *)value);
if (type->basic.width > 1) {
dstring_appendstr (dstr, "[");
}
for (int i = 0; i < type->basic.width; i++, value += 2) {
if (i) {
dstring_appendstr (dstr, ", ");
}
dasprintf (dstr, "%" PRIx64, *(uint64_t *)value);
}
if (type->basic.width > 1) {
dstring_appendstr (dstr, "]");
}
}
static void
@ -1514,17 +1658,26 @@ PR_Debug_Print (progs_t *pr, const char *expr)
}
static const char *
print_raw_op (progs_t *pr, pr_ushort_t op, pr_ushort_t base_ind,
print_raw_op (progs_t *pr, pr_short_t op, pr_ushort_t base_ind,
etype_t op_type, int op_width)
{
prdeb_resources_t *res = pr->pr_debug_resources;
const char *width = va (res->va, "%d", op_width);
return va (res->va, "%d:%04x<%08x>%s:%-8s",
return va (res->va, "%d:%04hx<%08x>%s:%-8s",
base_ind, op, op + pr->pr_bases[base_ind],
op_width > 0 ? width : op_width < 0 ? "X" : "?",
pr_type_name[op_type]);
}
static pr_uint_t
get_opval (progs_t *pr, pr_short_t op)
{
if (pr->progs->version < PROG_VERSION) {
return (pr_ushort_t) op;
}
return op;
}
VISIBLE void
PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
{
@ -1591,7 +1744,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
if (pr_debug > 2) {
if (pr->progs->version < PROG_VERSION) {
dasprintf (res->line,
"%03x %04x(%8s) %04x(%8s) %04x(%8s)\t",
"%03x %04hx(%8s) %04hx(%8s) %04hx(%8s)\t",
s->op,
s->a, pr_type_name[op_type[0]],
s->b, pr_type_name[op_type[1]],
@ -1624,7 +1777,8 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
pr_uint_t shift = 0;
pr_uint_t opreg;
pr_uint_t opval;
qfot_type_t *optype = &res->void_type;
qfot_type_t basic_type = {};
qfot_type_t *optype = &basic_type;
pr_func_t func;
if (mode == 'P') {
@ -1647,18 +1801,21 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
switch (opchar) {
case 'a':
opreg = PR_BASE_IND (s->op, A);
opval = s->a;
optype = res->type_encodings[op_type[0]];
opval = get_opval (pr, s->a);
basic_type = *res->type_encodings[op_type[0]];
basic_type.basic.width = op_width[0];
break;
case 'b':
opreg = PR_BASE_IND (s->op, B);
opval = s->b;
optype = res->type_encodings[op_type[1]];
opval = get_opval (pr, s->b);
basic_type = *res->type_encodings[op_type[1]];
basic_type.basic.width = op_width[1];
break;
case 'c':
opreg = PR_BASE_IND (s->op, C);
opval = s->c;
optype = res->type_encodings[op_type[2]];
opval = get_opval (pr, s->c);
basic_type = *res->type_encodings[op_type[2]];
basic_type.basic.width = op_width[2];
break;
case 'o':
opreg = 0;
@ -1719,6 +1876,15 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
case 's':
str = dsprintf (res->dva, "%d", (short) opval);
break;
case 'H':
str = hop_string (&data, opval);
break;
case 'S':
str = swizzle_string (&data, opval);
break;
case 'X':
str = extend_string (&data, opval);
break;
case 'O':
str = dsprintf (res->dva, "%04x",
addr + (short) opval);
@ -1729,8 +1895,8 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
case 'E':
{
edict_t *ed = 0;
opval = G_ENTITY (pr, s->a);
param_ind = G_FIELD (pr, s->b);
opval = G_ENTITY (pr, (pr_ushort_t) s->a);
param_ind = G_FIELD (pr, (pr_ushort_t) s->b);
if (param_ind < pr->progs->entityfields
&& opval > 0
&& opval < pr->pr_edict_area_size) {
@ -1744,7 +1910,8 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
str = global_string (&data, opval, optype,
contents & 1);
str = dsprintf (res->dva, "$%x $%x %s",
s->a, s->b, str);
(pr_ushort_t) s->a,
(pr_ushort_t) s->b, str);
}
break;
case 'M':
@ -1761,7 +1928,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
case 2:
ptr = s->a + PR_BASE (pr, s, A);
ptr = G_POINTER (pr, ptr);
offs = (short) s->b;
offs = s->b;
break;
case 3:
ptr = s->a + PR_BASE (pr, s, A);

View file

@ -547,9 +547,9 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
PR_RunError (pr, "runaway loop error");
}
op_a = pr->pr_globals + st->a;
op_b = pr->pr_globals + st->b;
op_c = pr->pr_globals + st->c;
op_a = pr->pr_globals + (pr_ushort_t) st->a;
op_b = pr->pr_globals + (pr_ushort_t) st->b;
op_c = pr->pr_globals + (pr_ushort_t) st->c;
if (pr->pr_trace) {
if (pr->debug_handler) {
@ -888,7 +888,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
case OP_ADDRESS_I_v6p:
case OP_ADDRESS_P_v6p:
case OP_ADDRESS_D_v6p:
OPC(int) = st->a;
OPC(int) = (pr_ushort_t) st->a;
break;
case OP_LOAD_F_v6p:
@ -990,7 +990,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
case OP_LOADBI_FN_v6p:
case OP_LOADBI_I_v6p:
case OP_LOADBI_P_v6p:
pointer = OPA(ptr) + (short) st->b;
pointer = OPA(ptr) + st->b;
if (pr_boundscheck) {
PR_BoundsCheck (pr, pointer, ev_int);
}
@ -998,7 +998,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
OPC(int) = ptr->value;
break;
case OP_LOADBI_V_v6p:
pointer = OPA(ptr) + (short) st->b;
pointer = OPA(ptr) + st->b;
if (pr_boundscheck) {
PR_BoundsCheck (pr, pointer, ev_vector);
}
@ -1006,7 +1006,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
VectorCopy (G_VECTOR (pr, pointer), &OPC(float));
break;
case OP_LOADBI_Q_v6p:
pointer = OPA(ptr) + (short) st->b;
pointer = OPA(ptr) + st->b;
if (pr_boundscheck) {
PR_BoundsCheck (pr, pointer, ev_quaternion);
}
@ -1014,7 +1014,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
QuatCopy (G_QUAT (pr, pointer), &OPC(float));
break;
case OP_LOADBI_D_v6p:
pointer = OPA(ptr) + (short) st->b;
pointer = OPA(ptr) + st->b;
if (pr_boundscheck) {
PR_BoundsCheck (pr, pointer, ev_quaternion);
}
@ -1028,7 +1028,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
break;
case OP_LEAI_v6p:
pointer = OPA(ptr) + (short) st->b;
pointer = OPA(ptr) + st->b;
OPC(ptr) = pointer;
break;
@ -1078,7 +1078,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
case OP_STOREBI_FN_v6p:
case OP_STOREBI_I_v6p:
case OP_STOREBI_P_v6p:
pointer = OPB(ptr) + (short) st->c;
pointer = OPB(ptr) + st->c;
if (pr_boundscheck) {
PR_BoundsCheck (pr, pointer, ev_int);
}
@ -1086,7 +1086,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
ptr->value = OPA(int);
break;
case OP_STOREBI_V_v6p:
pointer = OPB(ptr) + (short) st->c;
pointer = OPB(ptr) + st->c;
if (pr_boundscheck) {
PR_BoundsCheck (pr, pointer, ev_vector);
}
@ -1094,7 +1094,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
VectorCopy (&OPA(float), G_VECTOR (pr, pointer));
break;
case OP_STOREBI_Q_v6p:
pointer = OPB(ptr) + (short) st->c;
pointer = OPB(ptr) + st->c;
if (pr_boundscheck) {
PR_BoundsCheck (pr, pointer, ev_quaternion);
}
@ -1102,7 +1102,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
QuatCopy (&OPA(float), G_QUAT (pr, pointer));
break;
case OP_STOREBI_D_v6p:
pointer = OPB(ptr) + (short) st->c;
pointer = OPB(ptr) + st->c;
if (pr_boundscheck) {
PR_BoundsCheck (pr, pointer, ev_quaternion);
}
@ -1217,7 +1217,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
pr_ptr_t stack = *pr->globals.stack - 1;
pr_type_t *stk = pr->pr_globals + stack;
pointer = OPA(ptr) + st->b;
pointer = OPA(ptr) + (pr_ushort_t) st->b;
ptr = pr->pr_globals + pointer;
if (pr_boundscheck) {
@ -1233,7 +1233,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
{
pr_ptr_t stack = *pr->globals.stack - 3;
pointer = OPA(ptr) + st->b;
pointer = OPA(ptr) + (pr_ushort_t) st->b;
ptr = pr->pr_globals + pointer;
if (pr_boundscheck) {
@ -1249,7 +1249,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
{
pr_ptr_t stack = *pr->globals.stack - 4;
pointer = OPA(ptr) + st->b;
pointer = OPA(ptr) + (pr_ushort_t) st->b;
ptr = pr->pr_globals + pointer;
if (pr_boundscheck) {
@ -1369,7 +1369,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
pr_ptr_t stack = *pr->globals.stack;
pr_type_t *stk = pr->pr_globals + stack;
pointer = OPA(ptr) + st->b;
pointer = OPA(ptr) + (pr_ushort_t) st->b;
ptr = pr->pr_globals + pointer;
if (pr_boundscheck) {
@ -1385,7 +1385,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
{
pr_ptr_t stack = *pr->globals.stack;
pointer = OPA(ptr) + st->b;
pointer = OPA(ptr) + (pr_ushort_t) st->b;
ptr = pr->pr_globals + pointer;
if (pr_boundscheck) {
@ -1401,7 +1401,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
{
pr_ptr_t stack = *pr->globals.stack;
pointer = OPA(ptr) + st->b;
pointer = OPA(ptr) + (pr_ushort_t) st->b;
ptr = pr->pr_globals + pointer;
if (pr_boundscheck) {
@ -1417,42 +1417,42 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
// ==================
case OP_IFNOT_v6p:
if (!OPA(int)) {
pr->pr_xstatement += (short)st->b - 1; // offset the st++
pr->pr_xstatement += st->b - 1; // offset the st++
st = pr->pr_statements + pr->pr_xstatement;
}
break;
case OP_IF_v6p:
if (OPA(int)) {
pr->pr_xstatement += (short)st->b - 1; // offset the st++
pr->pr_xstatement += st->b - 1; // offset the st++
st = pr->pr_statements + pr->pr_xstatement;
}
break;
case OP_IFBE_v6p:
if (OPA(int) <= 0) {
pr->pr_xstatement += (short)st->b - 1; // offset the st++
pr->pr_xstatement += st->b - 1; // offset the st++
st = pr->pr_statements + pr->pr_xstatement;
}
break;
case OP_IFB_v6p:
if (OPA(int) < 0) {
pr->pr_xstatement += (short)st->b - 1; // offset the st++
pr->pr_xstatement += st->b - 1; // offset the st++
st = pr->pr_statements + pr->pr_xstatement;
}
break;
case OP_IFAE_v6p:
if (OPA(int) >= 0) {
pr->pr_xstatement += (short)st->b - 1; // offset the st++
pr->pr_xstatement += st->b - 1; // offset the st++
st = pr->pr_statements + pr->pr_xstatement;
}
break;
case OP_IFA_v6p:
if (OPA(int) > 0) {
pr->pr_xstatement += (short)st->b - 1; // offset the st++
pr->pr_xstatement += st->b - 1; // offset the st++
st = pr->pr_statements + pr->pr_xstatement;
}
break;
case OP_GOTO_v6p:
pr->pr_xstatement += (short)st->a - 1; // offset the st++
pr->pr_xstatement += st->a - 1; // offset the st++
st = pr->pr_statements + pr->pr_xstatement;
break;
case OP_JUMP_v6p:
@ -1464,7 +1464,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth)
st = pr->pr_statements + pr->pr_xstatement;
break;
case OP_JUMPB_v6p:
pointer = st->a + OPB(int);
pointer = (pr_ushort_t) st->a + OPB(int);
if (pr_boundscheck) {
PR_BoundsCheck (pr, pointer, ev_int);
}
@ -1684,7 +1684,7 @@ op_call:
break;
case OP_MOVEI_v6p:
memmove (op_c, op_a, st->b * 4);
memmove (op_c, op_a, (pr_ushort_t) st->b * 4);
break;
case OP_MOVEP_v6p:
if (pr_boundscheck) {
@ -1697,15 +1697,15 @@ op_call:
break;
case OP_MOVEPI_v6p:
if (pr_boundscheck) {
PR_BoundsCheckSize (pr, OPC(ptr), st->b);
PR_BoundsCheckSize (pr, OPA(ptr), st->b);
PR_BoundsCheckSize (pr, OPC(ptr), (pr_ushort_t) st->b);
PR_BoundsCheckSize (pr, OPA(ptr), (pr_ushort_t) st->b);
}
memmove (pr->pr_globals + OPC(ptr),
pr->pr_globals + OPA(ptr),
st->b * 4);
(pr_ushort_t) st->b * 4);
break;
case OP_MEMSETI_v6p:
pr_memset (op_c, OPA(ptr), st->b);
pr_memset (op_c, OPA(ptr), (pr_ushort_t) st->b);
break;
case OP_MEMSETP_v6p:
if (pr_boundscheck) {
@ -1716,10 +1716,10 @@ op_call:
break;
case OP_MEMSETPI_v6p:
if (pr_boundscheck) {
PR_BoundsCheckSize (pr, OPC(ptr), st->b);
PR_BoundsCheckSize (pr, OPC(ptr), (pr_ushort_t) st->b);
}
pr_memset (pr->pr_globals + OPC(ptr), OPA(int),
st->b);
(pr_ushort_t) st->b);
break;
case OP_GE_D_v6p:
OPC(float) = OPA(double) >= OPB(double);
@ -1758,9 +1758,10 @@ op_call:
// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
/*
case OP_BOUNDCHECK_v6p:
if (OPA(ptr) >= st->b) {
if (OPA(ptr) >= (pr_ushort_t) st->b) {
PR_RunError (pr, "Progs boundcheck failed at line number "
"%d, value is < 0 or >= %d", st->b, st->c);
"%d, value is < 0 or >= %d", (pr_ushort_t) st->b,
(pr_ushort_t) st->c);
}
break;
@ -1781,7 +1782,7 @@ op_call:
old_val.value = pr->watch->value;
}
}
exit_program:
exit_program:;
}
#define MM(type) (*((pr_##type##_t *) (mm)))
@ -1793,6 +1794,7 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind)
pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A);
pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B);
pr_ptr_t mm_offs = 0;
pr_ptr_t edict_area = 0;
switch (mm_ind) {
case 0:
@ -1801,12 +1803,12 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind)
break;
case 1:
// entity.field (equivalent to OP_LOAD_t_v6p)
pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals;
edict_area = pr->pr_edict_area - pr->pr_globals;
mm_offs = edict_area + OPA(entity) + OPB(field);
break;
case 2:
// constant indexed pointer: *a + b (supports -ve offset)
mm_offs = OPA(ptr) + (short) st->b;
mm_offs = OPA(ptr) + st->b;
break;
case 3:
// variable indexed pointer: *a + *b (supports -ve offset)
@ -1814,7 +1816,7 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind)
break;
case 4:
// global access with constant offset (supports -ve offset)
mm_offs = op_a - pr->pr_globals + (short) st->b;
mm_offs = op_a - pr->pr_globals + st->b;
break;
case 5:
// global access with variable offset (supports -ve offset)
@ -1830,6 +1832,7 @@ pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind)
pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A);
pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B);
pr_ptr_t mm_offs = 0;
pr_ptr_t edict_area = 0;
switch (mm_ind) {
case 1:
@ -1838,7 +1841,7 @@ pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind)
break;
case 2:
// constant indexed pointer: *a + b (supports -ve offset)
mm_offs = OPA(ptr) + (short) st->b;
mm_offs = OPA(ptr) + st->b;
break;
case 3:
// variable indexed pointer: *a + *b (supports -ve offset)
@ -1846,7 +1849,7 @@ pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind)
break;
case 4:
// entity.field (equivalent to OP_LOAD_t_v6p)
pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals;
edict_area = pr->pr_edict_area - pr->pr_globals;
mm_offs = edict_area + OPA(entity) + OPB(field);
break;
}
@ -1863,7 +1866,7 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st, int jump_ind)
switch (jump_ind) {
case 0:
// instruction relative offset
jump_offs = jump_offs + (short) st->a;
jump_offs = jump_offs + st->a;
break;
case 1:
// variable indexed array: a + *b (only +ve)
@ -1871,7 +1874,7 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st, int jump_ind)
break;
case 2:
// constant indexed pointer: *a + b (supports -ve offset)
jump_offs = OPA(ptr) + (short) st->b;
jump_offs = OPA(ptr) + st->b;
break;
case 3:
// variable indexed pointer: *a + *b (supports -ve offset)
@ -1936,24 +1939,24 @@ pr_with (progs_t *pr, const dstatement_t *st)
// fixed offset
case 0:
// hard-0 base
pr->pr_bases[st->c & 3] = st->b;
pr->pr_bases[st->c & 3] = (pr_ushort_t) st->b;
return;
case 1:
// relative to current base (-ve offset)
pr->pr_bases[st->c & 3] = PR_BASE (pr, st, B) + (pr_short_t) st->b;
pr->pr_bases[st->c & 3] = PR_BASE (pr, st, B) + st->b;
return;
case 2:
// relative to stack (-ve offset)
pr->pr_bases[st->c & 3] = *pr->globals.stack + (pr_short_t) st->b;
pr->pr_bases[st->c & 3] = *pr->globals.stack + st->b;
return;
case 3:
// relative to edict_area (only +ve)
pr->pr_bases[st->c & 3] = edict_area + st->b;
pr->pr_bases[st->c & 3] = edict_area + (pr_ushort_t) st->b;
return;
case 4:
// hard-0 base
pr->pr_bases[st->c & 3] = G_POINTER (pr, st->b);;
pr->pr_bases[st->c & 3] = G_POINTER (pr, (pr_ushort_t) st->b);;
return;
case 5:
pr->pr_bases[st->c & 3] = OPB(ptr);
@ -2148,13 +2151,16 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
pr_type_t *stk;
pr_type_t *mm;
pr_func_t function;
int ret_size = 0;
pr_opcode_e st_op = st->op & OP_MASK;
switch (st_op) {
// 0 0000
case OP_NOP:
break;
case OP_ADJSTK:
pr_stack_adjust (pr, st->a, (short) st->b);
pr_stack_adjust (pr, (pr_ushort_t) st->a, st->b);
break;
case OP_LDCONST:
PR_RunError (pr, "OP_LDCONST not implemented");
@ -2285,6 +2291,51 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
// 0 0110
// spare
// 0 0111
case OP_SWIZZLE_F_2:
{
auto s2 = OPA(ivec2);
pr_ivec4_t s4 = { s2[0], s2[1] };
s4 = pr_swizzle_f (s4, (pr_ushort_t) st->b);
OPC(ivec2) = (pr_ivec2_t) { s4[0], s4[1] };
}
break;
case OP_SWIZZLE_F_3:
{
auto s4 = loadvec3i (&OPA(int));
s4 = pr_swizzle_f (s4, (pr_ushort_t) st->b);
storevec3i (&OPA(int), s4);
}
break;
case OP_SWIZZLE_D_2:
{
auto s2 = OPA(lvec2);
pr_lvec4_t s4 = { s2[0], s2[1] };
s4 = pr_swizzle_d (s4, (pr_ushort_t) st->b);
OPC(lvec2) = (pr_lvec2_t) { s4[0], s4[1] };
}
break;
case OP_SWIZZLE_D_3:
{
auto s4 = loadvec3l (&OPA(long));
s4 = pr_swizzle_d (s4, (pr_ushort_t) st->b);
storevec3l (&OPC(long), s4);
}
break;
case OP_WEDGE_F_2:
{
auto a = OPA(vec2);
auto b = OPB(vec2);
OPC(float) = a[0] * b[1] - a[1] * b[0];
}
break;
// spare
case OP_WEDGE_D_2:
{
auto a = OPA(dvec2);
auto b = OPB(dvec2);
OPC(double) = a[0] * b[1] - a[1] * b[0];
}
break;
// spare
#define OP_cmp_1(OP, T, rt, cmp, ct) \
@ -2547,16 +2598,16 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
break;
OP_cmp_T (LT, U, long, lvec2, lvec4, <, ulong, ulvec2, ulvec4);
case OP_RETURN:
int ret_size = (st->c & 0x1f) + 1; // up to 32 words
if (st->c != 0xffff) {
mm = pr_address_mode (pr, st, st->c >> 5);
ret_size = (st->c & 0x1f) + 1; // up to 32 words
if ((pr_ushort_t) st->c != 0xffff) {
mm = pr_address_mode (pr, st, ((pr_ushort_t) st->c) >> 5);
memcpy (&R_INT (pr), mm, ret_size * sizeof (*op_a));
}
pr->pr_xfunction->profile += profile - startprofile;
startprofile = profile;
PR_LeaveFunction (pr, pr->pr_depth == exitdepth);
st = pr->pr_statements + pr->pr_xstatement;
if (pr->pr_depth== exitdepth) {
if (pr->pr_depth == exitdepth) {
if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth) {
pr->pr_trace = false;
}
@ -2577,8 +2628,8 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
break;
// 1 1010
OP_cmp_T (GT, u, int, ivec2, ivec4, >, uint, uivec2, uivec4);
case OP_SWIZZLE_F:
OPC(ivec4) = pr_swizzle_f (OPA(ivec4), st->b);
case OP_SWIZZLE_F_4:
OPC(ivec4) = pr_swizzle_f (OPA(ivec4), (pr_ushort_t) st->b);
break;
case OP_SCALE_F_2:
OPC(vec2) = OPA(vec2) * OPB(float);
@ -2590,8 +2641,8 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
OPC(vec4) = OPA(vec4) * OPB(float);
break;
OP_cmp_T (GT, U, long, lvec2, lvec4, >, ulong, ulvec2, ulvec4);
case OP_SWIZZLE_D:
OPC(lvec4) = pr_swizzle_d (OPA(lvec4), st->b);
case OP_SWIZZLE_D_4:
OPC(lvec4) = pr_swizzle_d (OPA(lvec4), (pr_ushort_t) st->b);
break;
case OP_SCALE_D_2:
OPC(dvec2) = OPA(dvec2) * OPB(double);
@ -2612,17 +2663,13 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
}
break;
case OP_CDOT_F:
OPC(vec2) = dot2f (OPA(vec2), OPB(vec2));
OPC(float) = dot2f (OPA(vec2), OPB(vec2))[0];
break;
case OP_VDOT_F:
{
vec_t d = DotProduct (&OPA(float),
&OPB(float));
VectorSet (d, d, d, &OPC(float));
}
OPC(float) = DotProduct (&OPA(float), &OPB(float));
break;
case OP_QDOT_F:
OPC(vec4) = dotf (OPA(vec4), OPB(vec4));
OPC(float) = dotf (OPA(vec4), OPB(vec4))[0];
break;
case OP_CMUL_F:
OPC(vec2) = cmulf (OPA(vec2), OPB(vec2));
@ -2653,17 +2700,13 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
}
break;
case OP_CDOT_D:
OPC(dvec2) = dot2d (OPA(dvec2), OPB(dvec2));
OPC(double) = dot2d (OPA(dvec2), OPB(dvec2))[0];
break;
case OP_VDOT_D:
{
double d = DotProduct (&OPA(double),
&OPB(double));
VectorSet (d, d, d, &OPC(double));
}
OPC(double) = DotProduct (&OPA(double), &OPB(double));
break;
case OP_QDOT_D:
OPC(dvec4) = dotd (OPA(dvec4), OPB(dvec4));
OPC(double) = dotd (OPA(dvec4), OPB(dvec4))[0];
break;
case OP_CMUL_D:
OPC(dvec2) = cmuld (OPA(dvec2), OPB(dvec2));
@ -2693,7 +2736,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
// 1 1101
OP_cmp_T (GE, u, int, ivec2, ivec4, >=, uint, uivec2, uivec4);
case OP_MOVE_I:
memmove (op_c, op_a, st->b * sizeof (pr_type_t));
memmove (op_c, op_a, (pr_ushort_t) st->b * sizeof (pr_type_t));
break;
case OP_MOVE_P:
memmove (pr->pr_globals + OPC(ptr), pr->pr_globals + OPA(ptr),
@ -2701,7 +2744,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
break;
case OP_MOVE_PI:
memmove (pr->pr_globals + OPC(ptr), pr->pr_globals + OPA(ptr),
st->b * sizeof (pr_type_t));
(pr_ushort_t) st->b * sizeof (pr_type_t));
break;
case OP_STATE_ft:
{
@ -2717,13 +2760,14 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
break;
OP_cmp_T (GE, U, long, lvec2, lvec4, >=, ulong, ulvec2, ulvec4);
case OP_MEMSET_I:
pr_memset (op_c, OPA(int), st->b);
pr_memset (op_c, OPA(int), (pr_ushort_t) st->b);
break;
case OP_MEMSET_P:
pr_memset (pr->pr_globals + OPC(ptr), OPA(int), OPB(uint));
break;
case OP_MEMSET_PI:
pr_memset (pr->pr_globals + OPC(ptr), OPA(int), st->b);
pr_memset (pr->pr_globals + OPC(ptr), OPA(int),
(pr_ushort_t) st->b);
break;
case OP_STATE_ftt:
{
@ -2833,35 +2877,37 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
OPC(float) = ~ (int) OPA(float);
break;
case OP_CONV:
switch (st->b) {
switch ((pr_ushort_t) st->b) {
#include "libs/gamecode/pr_convert.cinc"
default:
PR_RunError (pr, "invalid conversion code: %04o",
st->b);
(pr_ushort_t) st->b);
}
break;
case OP_WITH:
pr_with (pr, st);
break;
case OP_EXTEND:
switch (st->b) {
switch ((pr_ushort_t) st->b) {
#include "libs/gamecode/pr_extend.cinc"
default:
PR_RunError (pr, "invalid extend code: %04o", st->b);
PR_RunError (pr, "invalid extend code: %04o",
(pr_ushort_t) st->b);
}
break;
#define OP_hop2(vec, op) ((vec)[0] op (vec)[1])
#define OP_hop3(vec, op) ((vec)[0] op (vec)[1] op (vec)[2])
#define OP_hop4(vec, op) ((vec)[0] op (vec)[1] op (vec)[2] op (vec)[3])
case OP_HOPS:
switch (st->b) {
switch ((pr_ushort_t) st->b) {
#include "libs/gamecode/pr_hops.cinc"
default:
PR_RunError (pr, "invalid hops code: %04o", st->b);
PR_RunError (pr, "invalid hops code: %04o",
(pr_ushort_t) st->b);
}
break;
default:
PR_RunError (pr, "Bad opcode o%03o", st->op & OP_MASK);
PR_RunError (pr, "Bad opcode x%03x", st->op & OP_MASK);
}
if (pr->watch && pr->watch->value != old_val.value) {
if (!pr->wp_conditional
@ -2876,7 +2922,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
old_val.value = pr->watch->value;
}
}
exit_program:
exit_program:;
}
/*
PR_ExecuteProgram

View file

@ -269,7 +269,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
pr->pr_statements = (dstatement_t *) (base + pr->progs->statements.offset);
pr->pr_globals = (pr_type_t *) (base + pr->progs->globals.offset);
pr->stack = (pr_type_t *) ((byte *) pr->zone + pr->zone_size);
pr->stack = (pr_type_t *) (heap + pr->zone_size);
pr->stack_bottom = pr->stack - pr->pr_globals;
pr->globals_size = (pr_type_t *) ((byte *) pr->stack + pr->stack_size)
- pr->pr_globals;

View file

@ -219,6 +219,9 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s)
pr_type_t *d;
dfunction_t *func;
vec3_t vec = {};
char *str = 0;
d = &base[key->ofs];
switch (key->type & ~DEF_SAVEGLOBAL) {
@ -231,8 +234,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s)
break;
case ev_vector:
vec3_t vec = {};
char *str = alloca (strlen (s) + 1);
str = alloca (strlen (s) + 1);
strcpy (str, s);
for (char *v = str; *v; v++) {
if (*v == ',') {
@ -446,7 +448,6 @@ static void
ED_SpawnEntities (progs_t *pr, plitem_t *entity_list)
{
edict_t *ent;
int inhibit = 0;
plitem_t *entity;
plitem_t *item;
int i;
@ -479,7 +480,6 @@ ED_SpawnEntities (progs_t *pr, plitem_t *entity_list)
// remove things from different skill levels or deathmatch
if (pr->prune_edict && pr->prune_edict (pr, ent)) {
ED_Free (pr, ent);
inhibit++;
continue;
}

View file

@ -1058,7 +1058,8 @@ fmt_state_modifiers (fmt_state_t *state)
// no modifiers supported
if (state->c[0] == 'l'
&& (state->c[1] == 'i' || state->c[1] == 'd' || state->c[1] == 'x'
|| state->c[1] == 'u')) {
|| state->c[1] == 'u'
|| state->c[1] == 'v' || state->c[1] == 'q')) {
(*state->fi)->flags |= FMT_LONG;
state->c++;
}
@ -1070,10 +1071,11 @@ fmt_state_conversion (fmt_state_t *state)
{
progs_t *pr = state->pr;
char conv;
pr_ptr_t at_param;
switch ((conv = *state->c++)) {
case '@':
// object
pr_ptr_t at_param = P_UINT (pr, state->fmt_count);
at_param = P_UINT (pr, state->fmt_count);
if (state->at_handler) {
const char *at_str = state->at_handler (pr, at_param,
state->at_handler_data);
@ -1182,8 +1184,13 @@ fmt_state_conversion (fmt_state_t *state)
(*state->fi)->precision = precision;
(*state->fi)->minFieldWidth = minWidth;
(*state->fi)->type = 'g';
(*state->fi)->data.float_var =
P_VECTOR (pr, state->fmt_count)[i];
if (flags & FMT_LONG) {
(*state->fi)->data.double_var
= (&P_var (pr, state->fmt_count, double))[i];
} else {
(*state->fi)->data.float_var =
P_VECTOR (pr, state->fmt_count)[i];
}
fmt_append_item (state);
}

View file

@ -30,6 +30,7 @@ static void
test_debug_handler (prdebug_t event, void *param, void *data)
{
progs_t *pr = data;
dstatement_t *st = 0;
switch (event) {
case prd_breakpoint:
@ -44,7 +45,7 @@ test_debug_handler (prdebug_t event, void *param, void *data)
case prd_subexit:
break;
case prd_trace:
dstatement_t *st = test_pr.pr_statements + test_pr.pr_xstatement;
st = test_pr.pr_statements + test_pr.pr_xstatement;
if (verbose > 1) {
printf ("---\n");
printf ("debug: trace %05x %04x %04x %04x %04x%s\n",

View file

@ -67,13 +67,13 @@ static dstatement_t callret_statements[] = {
#define c 20 // in locals int
{ OP(2, 0, 1, OP_STORE_A_1), xn+1,0, x }, // init xn to [1, x, 0, 0]
{ OP(2, 0, 0, OP_STORE_A_1), xn, 0, 4 },
{ OP(2, 0, 2, OP_SWIZZLE_F), xn, 0x0044, xn }, // xn -> [1, x, 1, x]
{ OP(2, 0, 2, OP_SWIZZLE_F_4), xn, 0x0044, xn },// xn -> [1, x, 1, x]
{ OP(1, 1, 2, OP_MUL_F_1), x, x, x2 }, // x2 -> [x*x, ?, ?, ?]
{ OP(2, 0, 2, OP_SWIZZLE_F), x2, 0x0300, x2},//x2 -> [-x*x, -x*x, x*x, x*x]
{ OP(2, 0, 2, OP_SWIZZLE_F_4), x2, 0x0300, x2},//x2 -> [-x*x, -x*x, x*x, x*x]
{ OP(2, 0, 0, OP_STORE_A_1), fa, 0, 4 }, // init factorial
{ OP(2, 0, 0, OP_STORE_A_1), fa+1,0, 5 },
{ OP(2, 0, 2, OP_SWIZZLE_F), fa, 0x0044, fa }, // fa -> [1, 2, 1, 2]
{ OP(2, 0, 2, OP_SWIZZLE_F), fa, 0x0000, fi }, // init fi -> [1, 1, 1, 1]
{ OP(2, 0, 2, OP_SWIZZLE_F_4), fa, 0x0044, fa },// fa -> [1, 2, 1, 2]
{ OP(2, 0, 2, OP_SWIZZLE_F_4), fa, 0x0000, fi },// init fi -> [1, 1, 1, 1]
{ OP(2, 2, 2, OP_SUB_F_4), ac, ac, ac }, // init acc (output) to 0
{ OP(0, 0, 2, OP_LEA_A), 25, 0, c }, // init count
// loop:

Some files were not shown because too many files have changed in this diff Show more