1713 lines
51 KiB
C
1713 lines
51 KiB
C
/* n_pt_persp.c
|
|
|
|
1-, 2-, and 3-point perspective, axonometric (isometric, dimetric,
|
|
and trimetric), and oblique line-drawing tools,
|
|
|
|
Different complexity (expertise) levels offer different
|
|
tools. In Advanced mode, there are "Draw" and "Select"
|
|
(vanishing point editing) tools. In Beginner mode,
|
|
there are only "Draw" tools; the user is forced to use our
|
|
default vanishing points (a second "3-point" draw tool is
|
|
provided with an alternative vanishing point). And in
|
|
Novice mode, this plugin offers NO tools.
|
|
|
|
by Bill Kendrick <bill@newbreedsoftware.com>
|
|
|
|
December 12, 2023 - January 13, 2024
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <libintl.h>
|
|
|
|
#include "tp_magic_api.h"
|
|
#include "SDL_image.h"
|
|
#include "SDL_mixer.h"
|
|
|
|
#define SNAP 10
|
|
|
|
/* All _possible_ tools */
|
|
enum
|
|
{
|
|
/* 1-point perspective */
|
|
TOOL_1PT_SELECT, /* advanced only */
|
|
TOOL_1PT_DRAW, /* advanced & beginner */
|
|
|
|
/* 2-point perspective */
|
|
TOOL_2PT_SELECT, /* advanced only */
|
|
TOOL_2PT_DRAW, /* advanced & beginner */
|
|
|
|
/* 3-point perspective */
|
|
TOOL_3PT_SELECT, /* advanced only */
|
|
TOOL_3PT_DRAW, /* advanced & beginner */
|
|
TOOL_3PT_SELECT_ALT, /* beginner only (not directly accessible; used for drawing guides) */
|
|
TOOL_3PT_DRAW_ALT, /* beginner only */
|
|
|
|
/* Isometric */
|
|
TOOL_ISO_SELECT, /* (not directly accessible; used for drawing guides) */
|
|
TOOL_ISO_DRAW, /* advanced & beginner (N.B. isometric defined by exact angles; no "SELECT" tool) */
|
|
|
|
/* Dimetric */
|
|
TOOL_DIM_SELECT, /* advanced only */
|
|
TOOL_DIM_DRAW, /* advanced & beginner */
|
|
|
|
/* Trimetric */
|
|
TOOL_TRI_SELECT, /* advanced only */
|
|
TOOL_TRI_DRAW, /* advanced & beginner */
|
|
|
|
/* Oblique */
|
|
TOOL_OBLQ_SELECT, /* advanced only */
|
|
TOOL_OBLQ_DRAW, /* advanced & beginner */
|
|
TOOL_OBLQ_SELECT_ALT, /* beginner only (not directly accessible; used for drawing guides) */
|
|
TOOL_OBLQ_DRAW_ALT, /* beginner only */
|
|
|
|
NUM_TOOLS
|
|
};
|
|
|
|
// #define DEBUG
|
|
|
|
#ifdef DEBUG
|
|
char * tool_debug_names[NUM_TOOLS] = {
|
|
/* 1-point perspective */
|
|
"1pt select",
|
|
"1pt draw",
|
|
|
|
/* 2-point perspective */
|
|
"2pt select",
|
|
"2pt draw",
|
|
|
|
/* 3-point perspective */
|
|
"3pt select",
|
|
"3pt draw",
|
|
"3pt select alt",
|
|
"3pt draw alt",
|
|
|
|
/* Isometric */
|
|
"iso select",
|
|
"iso draw",
|
|
|
|
/* Dimetric */
|
|
"dim select",
|
|
"dim draw",
|
|
|
|
/* Trimetric */
|
|
"tri select",
|
|
"tri draw",
|
|
|
|
/* Oblique */
|
|
"oblq select alt",
|
|
"oblq draw alt",
|
|
"oblq select",
|
|
"oblq draw",
|
|
};
|
|
#endif
|
|
|
|
Uint8 complexity;
|
|
|
|
int num_tools[NUM_MAGIC_COMPLEXITY_LEVELS] = {
|
|
0, /* Novice */
|
|
9, /* Beginner */
|
|
13, /* Advanced */
|
|
};
|
|
|
|
int * which_to_tool;
|
|
|
|
int which_to_tool_per_complexity[NUM_MAGIC_COMPLEXITY_LEVELS][NUM_TOOLS] = {
|
|
/* Novice */
|
|
{
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
},
|
|
/* Beginner */
|
|
{
|
|
TOOL_1PT_DRAW,
|
|
TOOL_2PT_DRAW,
|
|
TOOL_3PT_DRAW,
|
|
TOOL_3PT_DRAW_ALT,
|
|
TOOL_ISO_DRAW,
|
|
TOOL_DIM_DRAW,
|
|
TOOL_TRI_DRAW,
|
|
TOOL_OBLQ_DRAW,
|
|
TOOL_OBLQ_DRAW_ALT,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
},
|
|
/* Advanced */
|
|
{
|
|
TOOL_1PT_SELECT,
|
|
TOOL_1PT_DRAW,
|
|
TOOL_2PT_SELECT,
|
|
TOOL_2PT_DRAW,
|
|
TOOL_3PT_SELECT,
|
|
TOOL_3PT_DRAW,
|
|
TOOL_ISO_DRAW,
|
|
TOOL_DIM_SELECT,
|
|
TOOL_DIM_DRAW,
|
|
TOOL_TRI_SELECT,
|
|
TOOL_TRI_DRAW,
|
|
TOOL_OBLQ_SELECT,
|
|
TOOL_OBLQ_DRAW,
|
|
-1, -1, -1, -1, -1,
|
|
},
|
|
};
|
|
|
|
const char *icon_filenames[NUM_TOOLS] = {
|
|
/* 1-point perspective */
|
|
"1pt_persp_select.png",
|
|
"1pt_persp_draw.png",
|
|
|
|
/* 2-point perspective */
|
|
"2pt_persp_select.png",
|
|
"2pt_persp_draw.png",
|
|
|
|
/* 3-point perspective */
|
|
"3pt_persp_select.png",
|
|
"3pt_persp_draw.png",
|
|
"",
|
|
"3pt_persp_draw_alt.png",
|
|
|
|
/* Isometric */
|
|
"",
|
|
"isometric_draw.png",
|
|
|
|
/* Dimetric */
|
|
"Snow_flake4.png", // FIXME
|
|
"dimetric_draw.png",
|
|
|
|
/* Trimetric */
|
|
"Snow_flake4.png", // FIXME
|
|
"trimetric_draw.png",
|
|
|
|
/* Oblique */
|
|
"Snow_flake4.png", // FIXME
|
|
"oblique_draw.png",
|
|
"",
|
|
"oblique_draw_alt.png",
|
|
};
|
|
|
|
|
|
const char *tool_names[NUM_TOOLS] = {
|
|
/* 1-point perspective */
|
|
gettext_noop("1-Point Select"),
|
|
gettext_noop("1-Point Draw"),
|
|
|
|
/* 2-point perspective */
|
|
gettext_noop("2-Point Select"),
|
|
gettext_noop("2-Point Draw"),
|
|
|
|
/* 3-point perspective */
|
|
gettext_noop("3-Point Select"),
|
|
gettext_noop("3-Point Draw"),
|
|
"",
|
|
gettext_noop("3-Point Draw Down"),
|
|
|
|
/* Isometric */
|
|
"",
|
|
gettext_noop("Isometric Lines"),
|
|
|
|
/* Dimetric */
|
|
gettext_noop("Dimetric Select"),
|
|
gettext_noop("Dimetric Draw"),
|
|
|
|
/* Trimetric */
|
|
gettext_noop("Trimetric Select"),
|
|
gettext_noop("Trimetric Draw"),
|
|
|
|
/* Oblique */
|
|
gettext_noop("Oblique Select"),
|
|
gettext_noop("Oblique Draw"),
|
|
"",
|
|
gettext_noop("Oblique Draw Left"),
|
|
};
|
|
|
|
|
|
const char *tool_descriptions[NUM_TOOLS] = {
|
|
/* 1-point perspective */
|
|
gettext_noop("Click in your drawing to pick a vanishing point for the 1-point perspective painting tool."),
|
|
gettext_noop("Click and drag to draw lines with your 1-point perspective vanishing point."),
|
|
|
|
/* 2-point perspective */
|
|
gettext_noop("Click two places in your drawing to pick vanishing points for the 2-point perspective painting tool."),
|
|
gettext_noop("Click and drag to draw lines with your 2-point perspective vanishing points."),
|
|
|
|
/* 3-point perspective */
|
|
gettext_noop("Click three places in your drawing to pick vanishing points for the 3-point perspective painting tool."),
|
|
gettext_noop("Click and drag to draw lines with your 3-point perspective vanishing points."),
|
|
"",
|
|
gettext_noop("Click and drag to draw lines with your 3-point perspective vanishing points (downward perspective)."),
|
|
|
|
/* Isometric */
|
|
"",
|
|
gettext_noop("Click and drag to draw lines with an isometric projection."),
|
|
|
|
/* Dimetric */
|
|
gettext_noop("Click in your drawing to adjust the angle used by the dimetric projection painting tool."),
|
|
gettext_noop("Click and drag to draw lines with dimetric projection."),
|
|
|
|
/* Trimetric */
|
|
gettext_noop("Click in your drawing to adjust the angles used by the trimetric projection painting tool."),
|
|
gettext_noop("Click and drag to draw lines with trimetric projection."),
|
|
|
|
/* Oblique */
|
|
gettext_noop("Click in your drawing to adjust the angle used by the oblique projection painting tool."),
|
|
gettext_noop("Click and drag to draw lines with oblique projection."),
|
|
"",
|
|
gettext_noop("Click and drag to draw lines with oblique projection (right-facing)."),
|
|
};
|
|
|
|
|
|
/* Sound effects (same for everyone) */
|
|
enum {
|
|
SND_SELECT,
|
|
SND_DRAW_CLICK,
|
|
SND_DRAW_RELEASE,
|
|
NUM_SNDS
|
|
};
|
|
|
|
Mix_Chunk *sound_effects[NUM_SNDS];
|
|
|
|
const char *sound_filenames[NUM_SNDS] = {
|
|
"n_pt_persp_select.ogg",
|
|
"n_pt_persp_click.ogg",
|
|
"n_pt_persp_release.ogg",
|
|
};
|
|
|
|
Uint8 n_pt_persp_r, n_pt_persp_g, n_pt_persp_b;
|
|
Uint8 n_pt_persp_size = 1;
|
|
SDL_Surface * n_pt_persp_snapshot = NULL;
|
|
|
|
int a1_pt_x, a1_pt_y;
|
|
int a2_pt_x[2], a2_pt_y[2], a2_pt_cur;
|
|
int a3_pt_x[3], a3_pt_y[3], a3_pt_cur;
|
|
int a3b_pt_x[3], a3b_pt_y[3];
|
|
float dim_ang;
|
|
int tri_ang_chosen;
|
|
float tri_ang[2];
|
|
float oblq_ang;
|
|
float oblqb_ang;
|
|
|
|
#define MIN_AXONOMETRIC_ANGLE (15.0 * M_PI / 180.0)
|
|
#define MAX_AXONOMETRIC_ANGLE (75.0 * M_PI / 180.0)
|
|
|
|
int line_start_x, line_start_y;
|
|
float a2_valid_angle[8];
|
|
float a3_valid_angle[8];
|
|
|
|
/* Function prototypes: */
|
|
Uint32 n_pt_persp_api_version(void);
|
|
int n_pt_persp_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level);
|
|
int n_pt_persp_get_tool_count(magic_api * api);
|
|
SDL_Surface *n_pt_persp_get_icon(magic_api * api, int which);
|
|
char *n_pt_persp_get_name(magic_api * api, int which);
|
|
int n_pt_persp_get_group(magic_api * api, int which);
|
|
char *n_pt_persp_get_description(magic_api * api, int which, int mode);
|
|
int n_pt_persp_requires_colors(magic_api * api, int which);
|
|
int n_pt_persp_modes(magic_api * api, int which);
|
|
Uint8 n_pt_persp_accepted_sizes(magic_api * api, int which, int mode);
|
|
Uint8 n_pt_persp_default_size(magic_api * api, int which, int mode);
|
|
void n_pt_persp_shutdown(magic_api * api);
|
|
void n_pt_persp_click(magic_api * api, int which, int mode,
|
|
SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y,
|
|
SDL_Rect * update_rect);
|
|
void n_pt_persp_vanish_pt_moved(magic_api * api, int which, SDL_Surface * canvas, SDL_Rect * update_rect);
|
|
void n_pt_persp_drag(magic_api * api, int which,
|
|
SDL_Surface * canvas, SDL_Surface * snapshot,
|
|
int old_x, int old_y, int x, int y,
|
|
SDL_Rect * update_rect);
|
|
void n_pt_persp_work(magic_api * api, int tool,
|
|
SDL_Surface * canvas, int x, int y,
|
|
SDL_Rect * update_rect, int xor);
|
|
void n_pt_persp_release(magic_api * api, int which,
|
|
SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y,
|
|
SDL_Rect * update_rect);
|
|
void n_pt_persp_set_color(magic_api * api, int which, SDL_Surface * canvas,
|
|
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
|
|
SDL_Rect * update_rect);
|
|
void n_pt_persp_set_size(magic_api * api, int which, int mode,
|
|
SDL_Surface * canvas, SDL_Surface * last,
|
|
Uint8 size, SDL_Rect * update_rect);
|
|
void n_pt_persp_line_xor_callback(void *pointer, int tool, SDL_Surface * canvas,
|
|
SDL_Surface * snapshot, int x, int y);
|
|
void n_pt_persp_line_callback(void *pointer, int tool, SDL_Surface * canvas,
|
|
SDL_Surface * snapshot, int x, int y);
|
|
void n_pt_persp_switchin(magic_api * api, int which, int mode,
|
|
SDL_Surface * canvas);
|
|
void n_pt_persp_switchout(magic_api * api, int which, int mode,
|
|
SDL_Surface * canvas);
|
|
void n_pt_persp_draw_points(magic_api * api, int tool, SDL_Surface * canvas);
|
|
void n_pt_persp_draw_one_point(magic_api * api, SDL_Surface * canvas, int x, int y, int i);
|
|
|
|
|
|
Uint32 n_pt_persp_api_version(void)
|
|
{
|
|
return (TP_MAGIC_API_VERSION);
|
|
}
|
|
|
|
|
|
int n_pt_persp_init(magic_api * api, Uint8 disabled_features ATTRIBUTE_UNUSED, Uint8 complexity_level)
|
|
{
|
|
int i;
|
|
char filename[1024];
|
|
|
|
for (i = 0; i < NUM_SNDS; i++) {
|
|
sound_effects[i] = NULL;
|
|
}
|
|
|
|
complexity = complexity_level;
|
|
which_to_tool = which_to_tool_per_complexity[complexity_level];
|
|
|
|
#ifdef DEBUG
|
|
printf("complexity level %d; tool mapping:\n", complexity);
|
|
fflush(stdout);
|
|
for (i = 0; i < NUM_TOOLS; i++) {
|
|
printf("%d -> %d ", i, which_to_tool[i]);
|
|
fflush(stdout);
|
|
if (which_to_tool[i] != -1) {
|
|
printf("%s", tool_debug_names[which_to_tool[i]]);
|
|
}
|
|
printf("\n");
|
|
fflush(stdout);
|
|
}
|
|
#endif
|
|
|
|
|
|
if (complexity_level == MAGIC_COMPLEXITY_NOVICE) {
|
|
/* No N-point perspective tools _at all_, if in Novice mode */
|
|
#ifdef DEBUG
|
|
printf("n_pt_persp_init -- MAGIC_COMPLEXITY_NOVICE so no tools for you!\n");
|
|
fflush(stdout);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
for (i = 0; i < NUM_SNDS; i++)
|
|
{
|
|
snprintf(filename, sizeof(filename), "%s/sounds/magic/%s", api->data_directory,
|
|
sound_filenames[i]);
|
|
sound_effects[i] = Mix_LoadWAV(filename);
|
|
}
|
|
|
|
/* Set default vanishing point positions: */
|
|
|
|
/* 1-pt perspective initial vanishing point: Center of canvas */
|
|
a1_pt_x = api->canvas_w / 2;
|
|
a1_pt_y = api->canvas_w / 2;
|
|
|
|
/* 2-pt perspective initial vanishing points: Left and right, midway up/down the canvas */
|
|
a2_pt_x[0] = 0;
|
|
a2_pt_y[0] = api->canvas_h / 2;
|
|
|
|
a2_pt_x[1] = api->canvas_w - 1;
|
|
a2_pt_y[1] = api->canvas_h / 2;
|
|
|
|
a2_pt_cur = 0;
|
|
|
|
/* 3-pt perspective initial vanishing points: top center, and left and right near bottom of canvas */
|
|
a3_pt_x[0] = api->canvas_w * 1 / 20;
|
|
a3_pt_y[0] = api->canvas_h * 19 / 20;
|
|
|
|
a3_pt_x[1] = api->canvas_w * 19 / 20;
|
|
a3_pt_y[1] = api->canvas_h * 19 / 20;
|
|
|
|
a3_pt_x[2] = api->canvas_w / 2;
|
|
a3_pt_y[2] = api->canvas_h * 1 / 20;
|
|
|
|
a3_pt_cur = 0;
|
|
|
|
/* 3-pt perspective alternative initial vanishing points: bottom center, and left and right near top of canvas */
|
|
a3b_pt_x[0] = api->canvas_w * 1 / 20;
|
|
a3b_pt_y[0] = api->canvas_h * 1 / 20;
|
|
|
|
a3b_pt_x[1] = api->canvas_w * 19 / 20;
|
|
a3b_pt_y[1] = api->canvas_h * 1 / 20;
|
|
|
|
a3b_pt_x[2] = api->canvas_w / 2;
|
|
a3b_pt_y[2] = api->canvas_h * 19 / 20;
|
|
|
|
|
|
/* Set default angles: */
|
|
dim_ang = 45.0 * M_PI / 180.0;
|
|
|
|
tri_ang[0] = 30 * M_PI / 180.0;
|
|
tri_ang[1] = 165 * M_PI / 180.0;
|
|
tri_ang_chosen = 0;
|
|
|
|
oblq_ang = 45 * M_PI / 180.0;
|
|
oblqb_ang = -45 * M_PI / 180.0;
|
|
|
|
|
|
/* Generate our own snapshot surface */
|
|
|
|
n_pt_persp_snapshot = SDL_CreateRGBSurface(SDL_SWSURFACE, api->canvas_w, api->canvas_h,
|
|
32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); // FIXME: Safe?
|
|
if (n_pt_persp_snapshot == NULL) {
|
|
fprintf(stderr, "n_pt_persp -- Could not create a 32-bit surface of size %d x %d!\n", api->canvas_w, api->canvas_h);
|
|
return (0);
|
|
}
|
|
|
|
return (1);
|
|
}
|
|
|
|
|
|
int n_pt_persp_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)
|
|
{
|
|
return (num_tools[complexity]);
|
|
}
|
|
|
|
|
|
SDL_Surface *n_pt_persp_get_icon(magic_api * api, int which)
|
|
{
|
|
char filename[1024];
|
|
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_get_icon\n");
|
|
printf("%d becomes %d (%s)\n", which, which_to_tool[which], tool_debug_names[which_to_tool[which]]);
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
snprintf(filename, sizeof(filename), "%s/images/magic/%s",
|
|
api->data_directory, icon_filenames[which_to_tool[which]]);
|
|
|
|
return (IMG_Load(filename));
|
|
}
|
|
|
|
|
|
char *n_pt_persp_get_name(magic_api * api ATTRIBUTE_UNUSED, int which)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_get_name\n");
|
|
printf("%d becomes %d (%s)\n", which, which_to_tool[which], tool_debug_names[which_to_tool[which]]);
|
|
fflush(stdout);
|
|
#endif
|
|
return (strdup(gettext(tool_names[which_to_tool[which]])));
|
|
}
|
|
|
|
|
|
int n_pt_persp_get_group(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
|
|
{
|
|
return (MAGIC_TYPE_PROJECTIONS);
|
|
}
|
|
|
|
|
|
char *n_pt_persp_get_description(magic_api * api ATTRIBUTE_UNUSED, int which, int mode ATTRIBUTE_UNUSED)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_get_description\n");
|
|
printf("%d becomes %d (%s)\n", which, which_to_tool[which], tool_debug_names[which_to_tool[which]]);
|
|
fflush(stdout);
|
|
#endif
|
|
return (strdup(gettext(tool_descriptions[which_to_tool[which]])));
|
|
}
|
|
|
|
|
|
int n_pt_persp_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_requires_colors\n");
|
|
printf("%d becomes %d (%s)\n", which, which_to_tool[which], tool_debug_names[which_to_tool[which]]);
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
which = which_to_tool[which];
|
|
|
|
if (which == TOOL_1PT_DRAW || which == TOOL_2PT_DRAW || which == TOOL_3PT_DRAW || which == TOOL_3PT_DRAW_ALT ||
|
|
which == TOOL_ISO_DRAW || which == TOOL_DIM_DRAW || which == TOOL_TRI_DRAW ||
|
|
which == TOOL_OBLQ_DRAW || which == TOOL_OBLQ_DRAW_ALT
|
|
)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
int n_pt_persp_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
|
|
{
|
|
return MODE_PAINT;
|
|
}
|
|
|
|
Uint8 n_pt_persp_accepted_sizes(magic_api * api ATTRIBUTE_UNUSED, int which, int mode ATTRIBUTE_UNUSED)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_accepted_sizes\n");
|
|
printf("%d becomes %d (%s)\n", which, which_to_tool[which], tool_debug_names[which_to_tool[which]]);
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
which = which_to_tool[which];
|
|
|
|
if (which == TOOL_1PT_DRAW || which == TOOL_2PT_DRAW || which == TOOL_3PT_DRAW || which == TOOL_3PT_DRAW_ALT ||
|
|
which == TOOL_ISO_DRAW || which == TOOL_DIM_DRAW || which == TOOL_TRI_DRAW ||
|
|
which == TOOL_OBLQ_DRAW || which == TOOL_OBLQ_DRAW_ALT
|
|
) {
|
|
return 4;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
Uint8 n_pt_persp_default_size(magic_api * api ATTRIBUTE_UNUSED,
|
|
int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
|
|
void n_pt_persp_shutdown(magic_api * api ATTRIBUTE_UNUSED)
|
|
{
|
|
int i;
|
|
|
|
if (n_pt_persp_snapshot != NULL) {
|
|
SDL_FreeSurface(n_pt_persp_snapshot);
|
|
}
|
|
|
|
for (i = 0; i < NUM_SNDS; i++) {
|
|
if (sound_effects[i] != NULL) {
|
|
Mix_FreeChunk(sound_effects[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void n_pt_persp_click(magic_api * api, int which, int mode ATTRIBUTE_UNUSED,
|
|
SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y,
|
|
SDL_Rect * update_rect)
|
|
{
|
|
int pick, i, tool;
|
|
float dist, min_dist;
|
|
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_click\n");
|
|
printf("%d becomes %d (%s)\n", which, which_to_tool[which], tool_debug_names[which_to_tool[which]]);
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
tool = which_to_tool[which];
|
|
|
|
pick = 0;
|
|
min_dist = FLT_MAX;
|
|
|
|
if (tool == TOOL_1PT_SELECT) {
|
|
/* Set position of 1-point perspective */
|
|
a1_pt_x = x;
|
|
a1_pt_y = y;
|
|
|
|
n_pt_persp_vanish_pt_moved(api, tool, canvas, update_rect);
|
|
} else if (tool == TOOL_2PT_SELECT) {
|
|
/* Pick closest 2-point perspective & move it */
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
dist = sqrt(pow(a2_pt_x[i] - x, 2) + pow(a2_pt_y[i] - y, 2));
|
|
if (dist < min_dist) {
|
|
pick = i;
|
|
min_dist = dist;
|
|
}
|
|
}
|
|
|
|
a2_pt_cur = pick;
|
|
|
|
a2_pt_x[a2_pt_cur] = x;
|
|
a2_pt_y[a2_pt_cur] = y;
|
|
|
|
n_pt_persp_vanish_pt_moved(api, tool, canvas, update_rect);
|
|
} else if (tool == TOOL_3PT_SELECT) {
|
|
/* Pick closest 3-point perspective & move it */
|
|
for (i = 0; i < 3; i++) {
|
|
dist = sqrt(pow(a3_pt_x[i] - x, 2) + pow(a3_pt_y[i] - y, 2));
|
|
if (dist < min_dist) {
|
|
pick = i;
|
|
min_dist = dist;
|
|
}
|
|
}
|
|
|
|
a3_pt_cur = pick;
|
|
|
|
a3_pt_x[a3_pt_cur] = x;
|
|
a3_pt_y[a3_pt_cur] = y;
|
|
|
|
n_pt_persp_vanish_pt_moved(api, tool, canvas, update_rect);
|
|
} else if (tool == TOOL_DIM_SELECT || tool == TOOL_TRI_SELECT || tool == TOOL_OBLQ_SELECT) {
|
|
/* The call to _drag() below will set angle(s) for Dimetric, Trimetric, and Oblique */
|
|
if (tool == TOOL_TRI_SELECT) {
|
|
if (x < canvas->w / 2) {
|
|
if (y < canvas->h / 2) {
|
|
/* top left */
|
|
tri_ang_chosen = 1;
|
|
} else {
|
|
/* bottom left */
|
|
tri_ang_chosen = 0;
|
|
}
|
|
} else {
|
|
if (y < canvas->h / 2) {
|
|
/* top right */
|
|
tri_ang_chosen = 0;
|
|
} else {
|
|
/* bottom right */
|
|
tri_ang_chosen = 1;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* Not a SELECT; must be a DRAW! */
|
|
int i;
|
|
|
|
api->playsound(sound_effects[SND_DRAW_CLICK], (x * 255) / canvas->w, 255);
|
|
|
|
/* Start drawing a line */
|
|
SDL_BlitSurface(canvas, NULL, n_pt_persp_snapshot, NULL);
|
|
|
|
if (tool == TOOL_2PT_DRAW) {
|
|
/* Horizon between vanishing points, and perpendicular (rise above/below) */
|
|
a2_valid_angle[0] = atan2(a2_pt_y[1] - a2_pt_y[0], a2_pt_x[1] - a2_pt_x[0]);
|
|
a2_valid_angle[1] = a2_valid_angle[0] + M_PI;
|
|
a2_valid_angle[2] = a2_valid_angle[0] + (M_PI / 2.0);
|
|
a2_valid_angle[3] = a2_valid_angle[0] + (M_PI / 2.0) + M_PI;
|
|
|
|
/* Angles that point toward the two vanishing points */
|
|
if (x == a2_pt_x[0]) {
|
|
x++;
|
|
}
|
|
if (x == a2_pt_x[1]) {
|
|
x++;
|
|
}
|
|
a2_valid_angle[4] = atan2(a2_pt_y[0] - y, a2_pt_x[0] - x);
|
|
a2_valid_angle[5] = a2_valid_angle[4] + M_PI;
|
|
a2_valid_angle[6] = atan2(a2_pt_y[1] - y, a2_pt_x[1] - x);
|
|
a2_valid_angle[7] = a2_valid_angle[6] + M_PI;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
if (a2_valid_angle[i] > M_PI) {
|
|
a2_valid_angle[i] -= (M_PI * 2);
|
|
}
|
|
}
|
|
} else if (tool == TOOL_3PT_DRAW) {
|
|
/* Horizon between vanishing points, and perpendicular (rise above/below) */
|
|
a3_valid_angle[0] = atan2(a3_pt_y[1] - a3_pt_y[0], a3_pt_x[1] - a3_pt_x[0]);
|
|
a3_valid_angle[1] = a3_valid_angle[0] + M_PI;
|
|
|
|
/* Angles that point toward the three vanishing points */
|
|
a3_valid_angle[2] = atan2(a3_pt_y[0] - y, a3_pt_x[0] - x);
|
|
a3_valid_angle[3] = a3_valid_angle[2] + M_PI;
|
|
a3_valid_angle[4] = atan2(a3_pt_y[1] - y, a3_pt_x[1] - x);
|
|
a3_valid_angle[5] = a3_valid_angle[4] + M_PI;
|
|
a3_valid_angle[6] = atan2(a3_pt_y[2] - y, a3_pt_x[2] - x);
|
|
a3_valid_angle[7] = a3_valid_angle[6] + M_PI;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
if (a3_valid_angle[i] > M_PI) {
|
|
a3_valid_angle[i] -= (M_PI * 2);
|
|
}
|
|
}
|
|
} else if (tool == TOOL_3PT_DRAW_ALT) {
|
|
/* Horizon between vanishing points, and perpendicular (rise above/below) */
|
|
a3_valid_angle[0] = atan2(a3b_pt_y[1] - a3b_pt_y[0], a3b_pt_x[1] - a3b_pt_x[0]);
|
|
a3_valid_angle[1] = a3_valid_angle[0] + M_PI;
|
|
|
|
/* Angles that point toward the three vanishing points */
|
|
a3_valid_angle[2] = atan2(a3b_pt_y[0] - y, a3b_pt_x[0] - x);
|
|
a3_valid_angle[3] = a3_valid_angle[2] + M_PI;
|
|
a3_valid_angle[4] = atan2(a3b_pt_y[1] - y, a3b_pt_x[1] - x);
|
|
a3_valid_angle[5] = a3_valid_angle[4] + M_PI;
|
|
a3_valid_angle[6] = atan2(a3b_pt_y[2] - y, a3b_pt_x[2] - x);
|
|
a3_valid_angle[7] = a3_valid_angle[6] + M_PI;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
if (a3_valid_angle[i] > M_PI) {
|
|
a3_valid_angle[i] -= (M_PI * 2);
|
|
}
|
|
}
|
|
}
|
|
/* N.B. For Isometric, Dimetric, Trimetric, and Oblique,
|
|
* angles are always the same, regardless of the line's
|
|
* position (unlike the perspective tools, where the angles
|
|
* are related to the drawing position & the vanishing point(s)
|
|
*/
|
|
|
|
line_start_x = x;
|
|
line_start_y = y;
|
|
n_pt_persp_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
|
|
}
|
|
}
|
|
|
|
|
|
void n_pt_persp_vanish_pt_moved(magic_api * api, int which, SDL_Surface * canvas, SDL_Rect * update_rect) {
|
|
SDL_BlitSurface(n_pt_persp_snapshot, NULL, canvas, NULL);
|
|
n_pt_persp_draw_points(api, which, canvas);
|
|
|
|
update_rect->x = 0;
|
|
update_rect->y = 0;
|
|
update_rect->w = canvas->w;
|
|
update_rect->h = canvas->h;
|
|
|
|
api->playsound(sound_effects[SND_SELECT], 128, 255);
|
|
}
|
|
|
|
|
|
/* Affect the canvas on drag: */
|
|
void n_pt_persp_drag(magic_api * api, int which,
|
|
SDL_Surface * canvas, SDL_Surface * snapshot ATTRIBUTE_UNUSED,
|
|
int old_x ATTRIBUTE_UNUSED, int old_y ATTRIBUTE_UNUSED,
|
|
int x, int y, SDL_Rect * update_rect)
|
|
{
|
|
int i, x1, y1, x2, y2;
|
|
float slope;
|
|
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_drag\n");
|
|
printf("%d becomes %d (%s)\n", which, which_to_tool[which], tool_debug_names[which_to_tool[which]]);
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
which = which_to_tool[which];
|
|
|
|
/* Draw the line (preview) */
|
|
n_pt_persp_work(api, which /* the tool */, canvas, x, y, update_rect, 1);
|
|
|
|
/* Show some guides */
|
|
if (which == TOOL_1PT_DRAW) {
|
|
/* 1-point perspective - draw */
|
|
|
|
/* Horizontal line (horizon) */
|
|
if (y != a1_pt_y) {
|
|
api->line((void *) api, which, canvas, NULL,
|
|
0, a1_pt_y, canvas->w - 1, a1_pt_y, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
}
|
|
|
|
/* Horizontal line (from cursor) */
|
|
api->line((void *) api, which, canvas, NULL,
|
|
0, y, canvas->w - 1, y, 6,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* Vertical line */
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x, 0, x, canvas->h - 1, 6,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* Diagonal line to the vanishing point */
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x, y, a1_pt_x, a1_pt_y, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
} else if (which == TOOL_2PT_DRAW) {
|
|
/* 2-point perspective - draw */
|
|
n_pt_persp_draw_points(api, TOOL_2PT_SELECT, canvas);
|
|
|
|
slope = ((float) a2_pt_y[0] - (float) a2_pt_y[1]) / ((float) a2_pt_x[0] - (float) a2_pt_x[1]);
|
|
|
|
/* Horizon line (from the cursor) */
|
|
x1 = 0;
|
|
y1 = y - (x * slope);
|
|
x2 = canvas->w;
|
|
y2 = y + ((canvas->w - x) * slope);
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x1, y1, x2, y2, 5,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* Perpendicular-to-horizon line (from the cursor) */
|
|
if (slope == 0.0 || slope == M_PI) {
|
|
x1 = x;
|
|
y1 = 0;
|
|
x2 = x;
|
|
y2 = canvas->h;
|
|
} else {
|
|
float perp_slope = -(slope);
|
|
|
|
x1 = x - (y * perp_slope);
|
|
y1 = 0;
|
|
x2 = x + ((canvas->h - y) * perp_slope);
|
|
y2 = canvas->h;
|
|
}
|
|
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x1, y1, x2, y2, 5,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* Diagonal lines from cursor to the vanishing points */
|
|
for (i = 0; i < 2; i++) {
|
|
if (x != a2_pt_x[i]) {
|
|
slope = ((float) y - (float) a2_pt_y[i]) / ((float) x - (float) a2_pt_x[i]);
|
|
|
|
x1 = 0;
|
|
y1 = a2_pt_y[i] - (a2_pt_x[i] * slope);
|
|
x2 = canvas->w;
|
|
y2 = a2_pt_y[i] + ((canvas->w - a2_pt_x[i]) * slope);
|
|
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x1, y1, x2, y2, 2,
|
|
n_pt_persp_line_xor_callback);
|
|
}
|
|
}
|
|
} else if (which == TOOL_3PT_DRAW || which == TOOL_3PT_DRAW_ALT) {
|
|
/* 3-point perspective - draw */
|
|
|
|
int a3_x[3], a3_y[3];
|
|
|
|
if (which == TOOL_3PT_DRAW) {
|
|
a3_x[0] = a3_pt_x[0];
|
|
a3_y[0] = a3_pt_y[0];
|
|
a3_x[1] = a3_pt_x[1];
|
|
a3_y[1] = a3_pt_y[1];
|
|
a3_x[2] = a3_pt_x[2];
|
|
a3_y[2] = a3_pt_y[2];
|
|
n_pt_persp_draw_points(api, TOOL_3PT_SELECT, canvas);
|
|
} else {
|
|
a3_x[0] = a3b_pt_x[0];
|
|
a3_y[0] = a3b_pt_y[0];
|
|
a3_x[1] = a3b_pt_x[1];
|
|
a3_y[1] = a3b_pt_y[1];
|
|
a3_x[2] = a3b_pt_x[2];
|
|
a3_y[2] = a3b_pt_y[2];
|
|
n_pt_persp_draw_points(api, TOOL_3PT_SELECT_ALT, canvas);
|
|
}
|
|
|
|
/* Horizon line (from the cursor) */
|
|
slope = ((float) a3_y[0] - (float) a3_y[1]) / ((float) a3_x[0] - (float) a3_x[1]);
|
|
x1 = 0;
|
|
y1 = y - (x * slope);
|
|
x2 = canvas->w;
|
|
y2 = y + ((canvas->w - x) * slope);
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x1, y1, x2, y2, 5,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* N.B. No "vertical" line; the 3rd vanishing point defines "up" and "down" */
|
|
|
|
/* Diagonal lines from cursor to the vanishing points */
|
|
for (i = 0; i < 3; i++) {
|
|
if (x != a3_x[i]) {
|
|
slope = ((float) y - (float) a3_y[i]) / ((float) x - (float) a3_x[i]);
|
|
|
|
x1 = 0;
|
|
y1 = a3_y[i] - (a3_x[i] * slope);
|
|
x2 = canvas->w;
|
|
y2 = a3_y[i] + ((canvas->w - a3_x[i]) * slope);
|
|
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x1, y1, x2, y2, 2,
|
|
n_pt_persp_line_xor_callback);
|
|
}
|
|
}
|
|
} else if (which == TOOL_ISO_DRAW || which == TOOL_DIM_DRAW || which == TOOL_TRI_DRAW ||
|
|
which == TOOL_OBLQ_DRAW || which == TOOL_OBLQ_DRAW_ALT) {
|
|
int guide_len;
|
|
|
|
guide_len = max(canvas->w, canvas->h);
|
|
|
|
/* All of these tools have a vertical guide */
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x, 0, x, canvas->h - 1, 6,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* Isometric, Dimetric, Trimetric, or Oblique draw */
|
|
if (which == TOOL_ISO_DRAW) {
|
|
/* Isometric */
|
|
float ang;
|
|
|
|
ang = 30.0 * M_PI / 180.0;
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x - cos(ang) * guide_len, y + sin(ang) * guide_len,
|
|
x + cos(ang) * guide_len, y - sin(ang) * guide_len,
|
|
6,
|
|
n_pt_persp_line_xor_callback);
|
|
ang = 150.0 * M_PI / 180.0;
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x - cos(ang) * guide_len, y + sin(ang) * guide_len,
|
|
x + cos(ang) * guide_len, y - sin(ang) * guide_len,
|
|
6,
|
|
n_pt_persp_line_xor_callback);
|
|
} else if (which == TOOL_DIM_DRAW) {
|
|
/* Dimetric */
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x - cos(dim_ang) * guide_len, y + sin(dim_ang) * guide_len,
|
|
x + cos(dim_ang) * guide_len, y - sin(dim_ang) * guide_len,
|
|
6,
|
|
n_pt_persp_line_xor_callback);
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x - cos(M_PI - dim_ang) * guide_len, y + sin(M_PI - dim_ang) * guide_len,
|
|
x + cos(M_PI - dim_ang) * guide_len, y - sin(M_PI - dim_ang) * guide_len,
|
|
6,
|
|
n_pt_persp_line_xor_callback);
|
|
} else if (which == TOOL_TRI_DRAW) {
|
|
/* Trimetric */
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x - cos(tri_ang[0]) * guide_len, y + sin(tri_ang[0]) * guide_len,
|
|
x + cos(tri_ang[0]) * guide_len, y - sin(tri_ang[0]) * guide_len,
|
|
6,
|
|
n_pt_persp_line_xor_callback);
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x - cos(tri_ang[1]) * guide_len, y + sin(tri_ang[1]) * guide_len,
|
|
x + cos(tri_ang[1]) * guide_len, y - sin(tri_ang[1]) * guide_len,
|
|
6,
|
|
n_pt_persp_line_xor_callback);
|
|
} else if (which == TOOL_OBLQ_DRAW || which == TOOL_OBLQ_DRAW_ALT) {
|
|
/* Oblique */
|
|
float ang;
|
|
api->line((void *) api, which, canvas, NULL,
|
|
0, y, canvas->w - 1, y, 6,
|
|
n_pt_persp_line_xor_callback);
|
|
if (which == TOOL_OBLQ_DRAW) {
|
|
ang = oblq_ang;
|
|
} else {
|
|
ang = oblqb_ang;
|
|
}
|
|
api->line((void *) api, which, canvas, NULL,
|
|
x - cos(ang) * guide_len, y + sin(ang) * guide_len,
|
|
x + cos(ang) * guide_len, y - sin(ang) * guide_len,
|
|
6,
|
|
n_pt_persp_line_xor_callback);
|
|
}
|
|
} else if (which == TOOL_1PT_SELECT) {
|
|
/* 1-point perspective - select */
|
|
a1_pt_x = x;
|
|
a1_pt_y = y;
|
|
|
|
n_pt_persp_vanish_pt_moved(api, which, canvas, update_rect);
|
|
} else if (which == TOOL_2PT_SELECT) {
|
|
/* 2-point perspective - select */
|
|
a2_pt_x[a2_pt_cur] = x;
|
|
a2_pt_y[a2_pt_cur] = y;
|
|
|
|
n_pt_persp_vanish_pt_moved(api, which, canvas, update_rect);
|
|
} else if (which == TOOL_3PT_SELECT) {
|
|
/* 3-point perspective - select */
|
|
a3_pt_x[a3_pt_cur] = x;
|
|
a3_pt_y[a3_pt_cur] = y;
|
|
|
|
n_pt_persp_vanish_pt_moved(api, which, canvas, update_rect);
|
|
} else if (which == TOOL_DIM_SELECT) {
|
|
/* Dimetric - select */
|
|
|
|
if (y > canvas->h / 2) {
|
|
y = canvas->h - y;
|
|
}
|
|
if (x > canvas->w / 2) {
|
|
x = canvas->w - x;
|
|
}
|
|
dim_ang = atan2f(canvas->h / 2 - y, canvas->w / 2 - x);
|
|
|
|
if (dim_ang < MIN_AXONOMETRIC_ANGLE) {
|
|
dim_ang = MIN_AXONOMETRIC_ANGLE;
|
|
} else if (dim_ang > MAX_AXONOMETRIC_ANGLE) {
|
|
dim_ang = MAX_AXONOMETRIC_ANGLE;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Dimetric select %.2f\n", dim_ang * 180.0 / M_PI);
|
|
#endif
|
|
|
|
n_pt_persp_vanish_pt_moved(api, which, canvas, update_rect);
|
|
} else if (which == TOOL_TRI_SELECT) {
|
|
/* Trimetric - select */
|
|
float ang, offset;
|
|
|
|
ang = atan2f(canvas->h / 2 - y, x - canvas->w / 2);
|
|
|
|
#ifdef DEBUG
|
|
printf("cursor ang = %.2f -> ", ang * 180.0 / M_PI);
|
|
#endif
|
|
if (ang > M_PI) {
|
|
ang -= M_PI;
|
|
} else if (ang < 0) {
|
|
ang += M_PI;
|
|
}
|
|
#ifdef DEBUG
|
|
printf("%.2f -> clipping for %d -> ", ang * 180.0 / M_PI, tri_ang_chosen);
|
|
#endif
|
|
|
|
offset = ((M_PI / 2) * tri_ang_chosen);
|
|
if (ang < MIN_AXONOMETRIC_ANGLE + offset) {
|
|
ang = MIN_AXONOMETRIC_ANGLE + offset;
|
|
} else if (ang > MAX_AXONOMETRIC_ANGLE + offset) {
|
|
ang = MAX_AXONOMETRIC_ANGLE + offset;
|
|
}
|
|
#ifdef DEBUG
|
|
printf("%.2f -> \n", ang * 180.0 / M_PI);
|
|
#endif
|
|
|
|
tri_ang[tri_ang_chosen] = ang;
|
|
|
|
#ifdef DEBUG
|
|
printf("Trimetric select %.2f, %.2f\n",
|
|
tri_ang[0] * 180.0 / M_PI,
|
|
tri_ang[1] * 180.0 / M_PI);
|
|
#endif
|
|
|
|
n_pt_persp_vanish_pt_moved(api, which, canvas, update_rect);
|
|
} else if (which == TOOL_OBLQ_SELECT) {
|
|
/* Oblique - select */
|
|
|
|
if (y > canvas->h / 2) {
|
|
y = canvas->h - y;
|
|
x = canvas->w - x;
|
|
}
|
|
oblq_ang = atan2f(canvas->h / 2 - y, x - canvas->w / 2);
|
|
|
|
if (oblq_ang < MIN_AXONOMETRIC_ANGLE) {
|
|
oblq_ang = MIN_AXONOMETRIC_ANGLE;
|
|
} else if (oblq_ang > MAX_AXONOMETRIC_ANGLE && oblq_ang < M_PI - MAX_AXONOMETRIC_ANGLE) {
|
|
oblq_ang = MAX_AXONOMETRIC_ANGLE;
|
|
} else if (oblq_ang > M_PI - MIN_AXONOMETRIC_ANGLE) {
|
|
oblq_ang = M_PI - MIN_AXONOMETRIC_ANGLE;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Oblique select %.2f\n", oblq_ang * 180.0 / M_PI);
|
|
#endif
|
|
n_pt_persp_vanish_pt_moved(api, which, canvas, update_rect);
|
|
}
|
|
}
|
|
|
|
void n_pt_persp_work(magic_api * api, int tool,
|
|
SDL_Surface * canvas, int x, int y,
|
|
SDL_Rect * update_rect, int xor)
|
|
{
|
|
int x1, y1, x2, y2;
|
|
float slope, slope2;
|
|
int i, best_angle_idx;
|
|
float cursor_angle, diff, best_diff;
|
|
/* SDL_Rect area_rect; */
|
|
|
|
if (n_pt_persp_snapshot == NULL)
|
|
return;
|
|
|
|
/* N.B. "which" is already set to the appropriate tool by the calling function! */
|
|
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_work\n");
|
|
printf("%d (%s)\n", tool, tool_debug_names[tool]);
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
/* Adhere x & y to perspective! */
|
|
|
|
x1 = y1 = x2 = y2 = 0;
|
|
|
|
if (tool == TOOL_1PT_DRAW) {
|
|
/* 1-point perspective */
|
|
|
|
x1 = line_start_x;
|
|
y1 = line_start_y;
|
|
|
|
if (abs(line_start_x - x) <= SNAP) {
|
|
/* Vertical */
|
|
x2 = x1;
|
|
y2 = y;
|
|
} else if (abs(line_start_y - y) <= SNAP) {
|
|
/* Horizontal */
|
|
x2 = x;
|
|
y2 = y1;
|
|
} else {
|
|
/* Diagonal */
|
|
|
|
slope = ((float) y1 - (float) a1_pt_y) / ((float) x1 - (float) a1_pt_x);
|
|
x2 = x;
|
|
y2 = line_start_y + (slope * (x - line_start_x));
|
|
|
|
/* Don't go past our cursor's Y */
|
|
if ((y < line_start_y && y2 < y) ||
|
|
(y > line_start_y && y2 > y)) {
|
|
if (slope != 0.0) {
|
|
y2 = y;
|
|
x2 = ((y - line_start_y) / slope) + line_start_x;
|
|
}
|
|
}
|
|
|
|
/* Snap to horizontal if cursor is on the wrong side */
|
|
slope2 = ((float) line_start_y - (float) y) / ((float) line_start_x - (float) x);
|
|
if ((slope2 > 0.00 && slope < 0.00) ||
|
|
(slope2 < 0.00 && slope > 0.00)) {
|
|
x2 = x;
|
|
y2 = y1;
|
|
}
|
|
}
|
|
} else if (tool == TOOL_2PT_DRAW || tool == TOOL_3PT_DRAW || tool == TOOL_3PT_DRAW_ALT) {
|
|
float * valid_angle;
|
|
|
|
/* 2- & 3-point perspective */
|
|
|
|
if (tool == TOOL_2PT_DRAW) {
|
|
valid_angle = a2_valid_angle;
|
|
} else { /* TOOL_3PT_DRAW || TOOL_3PT_DRAW_ALT */
|
|
valid_angle = a3_valid_angle;
|
|
}
|
|
|
|
/* Find the valid angle that the drawn angle fits best to */
|
|
cursor_angle = atan2f(y - line_start_y, x - line_start_x);
|
|
|
|
best_angle_idx = -1;
|
|
best_diff = M_PI * 2;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
diff = fabs(cursor_angle - valid_angle[i]);
|
|
|
|
if (diff < best_diff) {
|
|
best_angle_idx = i;
|
|
best_diff = diff;
|
|
}
|
|
}
|
|
|
|
if (best_angle_idx == -1) {
|
|
printf("???\n");
|
|
return;
|
|
}
|
|
|
|
/* Calculate a line segment, so we can determine the slope */
|
|
x1 = line_start_x;
|
|
y1 = line_start_y;
|
|
x2 = line_start_x + cos(valid_angle[best_angle_idx]) * 1000;
|
|
y2 = line_start_y + sin(valid_angle[best_angle_idx]) * 1000;
|
|
|
|
if (abs(x2 - x1) >= 2) {
|
|
slope = ((float) y2 - (float) y1) / ((float) x2 - (float) x1);
|
|
x2 = x;
|
|
y2 = line_start_y + (slope * (x - line_start_x));
|
|
|
|
/* Don't go past our cursor's Y */
|
|
if ((y < line_start_y && y2 < y) ||
|
|
(y > line_start_y && y2 > y)) {
|
|
if (slope != 0.0) {
|
|
y2 = y;
|
|
x2 = ((y - line_start_y) / slope) + line_start_x;
|
|
}
|
|
}
|
|
} else {
|
|
x2 = x1;
|
|
y2 = y;
|
|
}
|
|
} else if (tool == TOOL_ISO_DRAW || tool == TOOL_DIM_DRAW || tool == TOOL_TRI_DRAW ||
|
|
tool == TOOL_OBLQ_DRAW || tool == TOOL_OBLQ_DRAW_ALT) {
|
|
float valid_angles[6];
|
|
float ang;
|
|
|
|
/* Orthographic projections (isometric, dimetric, trimetric, oblique) */
|
|
|
|
if (line_start_x == x) {
|
|
/* Vertical */
|
|
x1 = line_start_x;
|
|
y1 = line_start_y;
|
|
x2 = x1;
|
|
y2 = y;
|
|
} else {
|
|
/* all tools include vertical */
|
|
valid_angles[0] = -M_PI / 2;
|
|
|
|
if (tool == TOOL_ISO_DRAW) {
|
|
/* isometric diagonals */
|
|
valid_angles[1] = -(30.0 * M_PI / 180.0);
|
|
valid_angles[2] = -(150.0 * M_PI / 180.0);
|
|
} else if (tool == TOOL_DIM_DRAW) {
|
|
/* dimetric diagonals */
|
|
valid_angles[1] = dim_ang;
|
|
valid_angles[2] = M_PI - dim_ang;
|
|
} else if (tool == TOOL_TRI_DRAW) {
|
|
/* trimetric diagonals */
|
|
valid_angles[1] = M_PI - tri_ang[0];
|
|
valid_angles[2] = M_PI - tri_ang[1];
|
|
} else if (tool == TOOL_OBLQ_DRAW) {
|
|
/* horizontal */
|
|
valid_angles[1] = 0.0;
|
|
/* oblique diagonal */
|
|
valid_angles[2] = M_PI - oblq_ang;
|
|
} else if (tool == TOOL_OBLQ_DRAW_ALT) {
|
|
/* horizontal */
|
|
valid_angles[1] = 0.0;
|
|
/* oblique diagonal */
|
|
valid_angles[2] = M_PI - oblqb_ang;
|
|
}
|
|
|
|
/* And the opposite directions */
|
|
for (i = 0; i < 3; i++) {
|
|
valid_angles[i + 3] = valid_angles[i] + M_PI;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("\n");
|
|
#endif
|
|
for (i = 0; i < 6; i++) {
|
|
#ifdef DEBUG
|
|
printf(" %.2f -> ", valid_angles[i] * 180.0 / M_PI);
|
|
#endif
|
|
if (valid_angles[i] > M_PI) {
|
|
valid_angles[i] -= (M_PI * 2);
|
|
}
|
|
#ifdef DEBUG
|
|
printf("%.2f\n", valid_angles[i] * 180.0 / M_PI);
|
|
#endif
|
|
}
|
|
|
|
cursor_angle = atan2f(line_start_y- y, line_start_x - x);
|
|
#ifdef DEBUG
|
|
printf("cursor ang = %.2f\n", cursor_angle * 180.0 / M_PI);
|
|
#endif
|
|
|
|
best_angle_idx = -1;
|
|
best_diff = M_PI * 2;
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
#ifdef DEBUG
|
|
printf(" #%d %.2f vs %.2f\n", i, cursor_angle * 180.0 / M_PI, valid_angles[i] * 180.0 / M_PI);
|
|
#endif
|
|
diff = fabs(cursor_angle - valid_angles[i]);
|
|
if (diff < best_diff) {
|
|
best_angle_idx = i;
|
|
best_diff = diff;
|
|
}
|
|
diff = fabs((cursor_angle - (M_PI * 2)) - valid_angles[i]);
|
|
if (diff < best_diff) {
|
|
best_angle_idx = i;
|
|
best_diff = diff;
|
|
}
|
|
}
|
|
|
|
if (best_angle_idx == -1) {
|
|
printf("???\n");
|
|
return;
|
|
}
|
|
|
|
ang = valid_angles[best_angle_idx];
|
|
#ifdef DEBUG
|
|
printf("best ang = [%d] %.2f\n", best_angle_idx, ang * 180.0 / M_PI);
|
|
#endif
|
|
|
|
x1 = line_start_x;
|
|
y1 = line_start_y;
|
|
x2 = line_start_x + cos(ang) * 1000;
|
|
y2 = line_start_y + sin(ang) * 1000;
|
|
|
|
if (abs(x2 - x1) >= 2) {
|
|
slope = ((float) y2 - (float) y1) / ((float) x2 - (float) x1);
|
|
x2 = x;
|
|
y2 = line_start_y + (slope * (x - line_start_x));
|
|
|
|
/* Don't go past our cursor's Y */
|
|
if ((y < line_start_y && y2 < y) ||
|
|
(y > line_start_y && y2 > y)) {
|
|
if (slope != 0.0) {
|
|
y2 = y;
|
|
x2 = ((y - line_start_y) / slope) + line_start_x;
|
|
}
|
|
}
|
|
} else {
|
|
x2 = x1;
|
|
y2 = y;
|
|
}
|
|
}
|
|
}
|
|
|
|
SDL_BlitSurface(n_pt_persp_snapshot, NULL, canvas, NULL);
|
|
|
|
/* Draw the line */
|
|
|
|
if (xor) {
|
|
/* Still moving; use XOR */
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
x1, y1, x2, y2, 3,
|
|
n_pt_persp_line_xor_callback);
|
|
} else {
|
|
/* Released; draw the line for real */
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
x1, y1, x2, y2, 1,
|
|
n_pt_persp_line_callback);
|
|
}
|
|
|
|
update_rect->x = 0;
|
|
update_rect->y = 0;
|
|
update_rect->w = canvas->w;
|
|
update_rect->h = canvas->h;
|
|
}
|
|
|
|
|
|
void n_pt_persp_release(magic_api * api, int which,
|
|
SDL_Surface * canvas, SDL_Surface * snapshot ATTRIBUTE_UNUSED,
|
|
int x, int y, SDL_Rect * update_rect)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_release\n");
|
|
printf("%d becomes %d (%s)\n", which, which_to_tool[which], tool_debug_names[which_to_tool[which]]);
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
which = which_to_tool[which];
|
|
|
|
if (which == TOOL_1PT_SELECT) {
|
|
/* 1-point perspective - vanishing point drag released */
|
|
api->stopsound();
|
|
} else if (which == TOOL_2PT_SELECT) {
|
|
/* 2-point perspective - vanishing point drag released */
|
|
if (abs(a2_pt_x[0] - a2_pt_x[1]) < SNAP) {
|
|
if (a2_pt_x[0] <= a2_pt_x[1]) {
|
|
a2_pt_x[0] -= (SNAP / 2);
|
|
a2_pt_x[1] += (SNAP / 2);
|
|
} else {
|
|
a2_pt_x[0] += (SNAP / 2);
|
|
a2_pt_x[1] -= (SNAP / 2);
|
|
}
|
|
}
|
|
api->stopsound();
|
|
} else if (which == TOOL_3PT_SELECT) {
|
|
/* 3-point perspective - vanishing point drag released */
|
|
api->stopsound();
|
|
} else if (which == TOOL_DIM_SELECT || which == TOOL_TRI_SELECT || which == TOOL_OBLQ_SELECT) {
|
|
/* Dimetric, Trimetric, Oblique - angle adjustment drag released */
|
|
api->stopsound();
|
|
} else {
|
|
/* Draw the line (for real) */
|
|
n_pt_persp_work(api, which, canvas, x, y, update_rect, 0);
|
|
|
|
api->playsound(sound_effects[SND_DRAW_RELEASE], (x * 255) / canvas->w, 255);
|
|
}
|
|
}
|
|
|
|
|
|
void n_pt_persp_set_color(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED,
|
|
SDL_Surface * canvas ATTRIBUTE_UNUSED,
|
|
SDL_Surface * snapshot ATTRIBUTE_UNUSED,
|
|
Uint8 r, Uint8 g, Uint8 b,
|
|
SDL_Rect * update_rect ATTRIBUTE_UNUSED)
|
|
{
|
|
n_pt_persp_r = r;
|
|
n_pt_persp_g = g;
|
|
n_pt_persp_b = b;
|
|
}
|
|
|
|
|
|
void n_pt_persp_set_size(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
|
|
SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * last ATTRIBUTE_UNUSED,
|
|
Uint8 size, SDL_Rect * update_rect ATTRIBUTE_UNUSED)
|
|
{
|
|
n_pt_persp_size = ((size - 1) * 2) + 1;
|
|
}
|
|
|
|
|
|
void n_pt_persp_line_xor_callback(void *pointer, int tool ATTRIBUTE_UNUSED, SDL_Surface * canvas,
|
|
SDL_Surface * snapshot ATTRIBUTE_UNUSED, int x, int y)
|
|
{
|
|
magic_api *api = (magic_api *) pointer;
|
|
|
|
api->xorpixel(canvas, x, y);
|
|
api->xorpixel(canvas, x + 1, y + 1);
|
|
}
|
|
|
|
void n_pt_persp_line_callback(void *pointer ATTRIBUTE_UNUSED, int tool ATTRIBUTE_UNUSED,
|
|
SDL_Surface * canvas, SDL_Surface * snapshot ATTRIBUTE_UNUSED,
|
|
int x, int y)
|
|
{
|
|
SDL_Rect r;
|
|
|
|
r.x = x - n_pt_persp_size / 2;
|
|
r.y = y - n_pt_persp_size / 2;
|
|
r.w = n_pt_persp_size;
|
|
r.h = n_pt_persp_size;
|
|
|
|
SDL_FillRect(canvas, &r, SDL_MapRGB(canvas->format, n_pt_persp_r, n_pt_persp_g, n_pt_persp_b));
|
|
}
|
|
|
|
void n_pt_persp_switchin(magic_api * api, int which, int mode ATTRIBUTE_UNUSED,
|
|
SDL_Surface * canvas)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_switchin\n");
|
|
printf("%d becomes %d (%s)\n", which, which_to_tool[which], tool_debug_names[which_to_tool[which]]);
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
which = which_to_tool[which];
|
|
|
|
if (which == TOOL_1PT_SELECT || which == TOOL_2PT_SELECT || which == TOOL_3PT_SELECT ||
|
|
which == TOOL_DIM_SELECT || which == TOOL_TRI_SELECT || which == TOOL_OBLQ_SELECT
|
|
) {
|
|
SDL_BlitSurface(canvas, NULL, n_pt_persp_snapshot, NULL);
|
|
|
|
n_pt_persp_draw_points(api, which, canvas);
|
|
}
|
|
}
|
|
|
|
void n_pt_persp_switchout(magic_api * api ATTRIBUTE_UNUSED, int which, int mode ATTRIBUTE_UNUSED,
|
|
SDL_Surface * canvas)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_switchout\n");
|
|
printf("%d becomes %d (%s)\n", which, which_to_tool[which], tool_debug_names[which_to_tool[which]]);
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
which = which_to_tool[which];
|
|
|
|
if (which == TOOL_1PT_SELECT || which == TOOL_2PT_SELECT || which == TOOL_3PT_SELECT ||
|
|
which == TOOL_DIM_SELECT || which == TOOL_TRI_SELECT || which == TOOL_OBLQ_SELECT
|
|
) {
|
|
SDL_BlitSurface(n_pt_persp_snapshot, NULL, canvas, NULL);
|
|
}
|
|
}
|
|
|
|
void n_pt_persp_draw_points(magic_api * api, int tool, SDL_Surface * canvas) {
|
|
int i, l, m, x1, y1, x2, y2, x;
|
|
float slope;
|
|
|
|
#ifdef DEBUG
|
|
printf("\nn_pt_persp_draw_points\n");
|
|
printf("%d (%s)\n", tool, tool_debug_names[tool]);
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
if (tool == TOOL_1PT_SELECT) {
|
|
/* 1-point perspective */
|
|
|
|
n_pt_persp_draw_one_point(api, canvas, a1_pt_x, a1_pt_y, 0);
|
|
|
|
for (l = 0; l < 5; l++) {
|
|
/* Diagonal from left to right sides of canvas */
|
|
|
|
y1 = (a1_pt_y - (canvas->h / 2)) + (canvas->h / 5) * l + (canvas->h / 10);
|
|
|
|
if (a1_pt_x > canvas->w / 2) {
|
|
x1 = 0;
|
|
x2 = canvas->w - 1;
|
|
} else {
|
|
x1 = canvas->w - 1;
|
|
x2 = 0;
|
|
}
|
|
|
|
slope = ((float) a1_pt_y - (float) y1) / ((float) a1_pt_x - (float) x1);
|
|
y2 = y1 + (x2 - x1) * slope;
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
x1, y1, x2, y2, 6,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* Some vertical lines between the diagonals */
|
|
if (l == 0) {
|
|
for (m = 0; m < 8; m++) {
|
|
int xx, yy1, yy2;
|
|
int m_scale[8] = {-8,-4,-2,-1,1,2,4,8};
|
|
|
|
xx = a1_pt_x + ((float) (canvas->w / 10) * (float) m_scale[m]);
|
|
yy1 = a1_pt_y + (a1_pt_x - xx) * slope;
|
|
yy2 = a1_pt_y + (xx - a1_pt_x) * slope;
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
xx, yy1, xx, yy2, 3,
|
|
n_pt_persp_line_xor_callback);
|
|
}
|
|
}
|
|
}
|
|
} else if (tool == TOOL_2PT_SELECT) {
|
|
/* 2-point perspective */
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
n_pt_persp_draw_one_point(api, canvas, a2_pt_x[i], a2_pt_y[i], i);
|
|
}
|
|
|
|
/* Horizon line (vanishing point) */
|
|
slope = ((float) a2_pt_y[0] - (float) a2_pt_y[1]) / ((float) a2_pt_x[0] - (float) a2_pt_x[1]);
|
|
x1 = 0;
|
|
y1 = a2_pt_y[0] - (a2_pt_x[0] * slope);
|
|
x2 = canvas->w;
|
|
y2 = a2_pt_y[0] + ((canvas->w - a2_pt_x[0]) * slope);
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
x1, y1, x2, y2, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
x = (a2_pt_x[0] + a2_pt_x[1]) / 2;
|
|
|
|
/* Perpendicular-to-horizon line */
|
|
if (slope == 0.0 || slope == M_PI) {
|
|
x1 = x;
|
|
y1 = 0;
|
|
x2 = x;
|
|
y2 = canvas->h;
|
|
} else {
|
|
float perp_slope = -(slope);
|
|
int y;
|
|
|
|
x = (a2_pt_x[0] + a2_pt_x[1]) / 2;
|
|
y = (a2_pt_y[0] + a2_pt_y[1]) / 2;
|
|
|
|
x1 = x - (y * perp_slope);
|
|
y1 = 0;
|
|
x2 = x + ((canvas->h - y) * perp_slope);
|
|
y2 = canvas->h;
|
|
}
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
x1, y1, x2, y2, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
a2_pt_x[0], a2_pt_y[0], x2, y2, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
a2_pt_x[1], a2_pt_y[1], x2, y2, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
x1, y1, a2_pt_x[0], a2_pt_y[0], 12,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
x1, y1, a2_pt_x[1], a2_pt_y[1], 12,
|
|
n_pt_persp_line_xor_callback);
|
|
} else if (tool == TOOL_3PT_SELECT || tool == TOOL_3PT_SELECT_ALT) {
|
|
/* 3-point perspective */
|
|
int a3_x[3], a3_y[3];
|
|
|
|
if (tool == TOOL_3PT_SELECT) {
|
|
a3_x[0] = a3_pt_x[0];
|
|
a3_y[0] = a3_pt_y[0];
|
|
a3_x[1] = a3_pt_x[1];
|
|
a3_y[1] = a3_pt_y[1];
|
|
a3_x[2] = a3_pt_x[2];
|
|
a3_y[2] = a3_pt_y[2];
|
|
} else {
|
|
a3_x[0] = a3b_pt_x[0];
|
|
a3_y[0] = a3b_pt_y[0];
|
|
a3_x[1] = a3b_pt_x[1];
|
|
a3_y[1] = a3b_pt_y[1];
|
|
a3_x[2] = a3b_pt_x[2];
|
|
a3_y[2] = a3b_pt_y[2];
|
|
}
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
n_pt_persp_draw_one_point(api, canvas, a3_x[i], a3_y[i], i);
|
|
}
|
|
|
|
/* Horizon line (vanishing point) */
|
|
slope = ((float) a3_y[0] - (float) a3_y[1]) / ((float) a3_x[0] - (float) a3_x[1]);
|
|
x1 = 0;
|
|
y1 = a3_y[0] - (a3_x[0] * slope);
|
|
x2 = canvas->w;
|
|
y2 = a3_y[0] + ((canvas->w - a3_x[0]) * slope);
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
x1, y1, x2, y2, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
x1 = a3_x[0] + (((a3_x[1] - a3_x[0]) / 5) * i);
|
|
y1 = a3_y[0] + ((x1 - a3_x[0]) * slope);
|
|
x2 = a3_x[2];
|
|
y2 = a3_y[2];
|
|
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
x1, y1, x2, y2, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
}
|
|
} else if (tool == TOOL_ISO_SELECT) {
|
|
/* Isometric */
|
|
|
|
/* vertical */
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
canvas->w / 2, 0,
|
|
canvas->w / 2, canvas->h - 1, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* the angle (always 30) */
|
|
x1 = cos(30.0 * M_PI / 180.0) * canvas->w;
|
|
y1 = sin(30.0 * M_PI / 180.0) * canvas->h;
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
canvas->w / 2 - x1, canvas->h / 2 - y1,
|
|
canvas->w / 2 + x1, canvas->h / 2 + y1, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
canvas->w / 2 - x1, canvas->h / 2 + y1,
|
|
canvas->w / 2 + x1, canvas->h / 2 - y1, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
} else if (tool == TOOL_DIM_SELECT) {
|
|
/* Dimetric */
|
|
|
|
/* vertical */
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
canvas->w / 2, 0,
|
|
canvas->w / 2, canvas->h - 1, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* the angle */
|
|
x1 = cos(dim_ang) * canvas->w;
|
|
y1 = sin(dim_ang) * canvas->h;
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
canvas->w / 2 - x1, canvas->h / 2 - y1,
|
|
canvas->w / 2 + x1, canvas->h / 2 + y1, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
canvas->w / 2 - x1, canvas->h / 2 + y1,
|
|
canvas->w / 2 + x1, canvas->h / 2 - y1, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
} else if (tool == TOOL_TRI_SELECT) {
|
|
/* Trimetric */
|
|
|
|
/* vertical */
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
canvas->w / 2, 0,
|
|
canvas->w / 2, canvas->h - 1, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* angle 1 */
|
|
x1 = cos(tri_ang[0]) * canvas->w;
|
|
y1 = sin(tri_ang[0]) * canvas->w;
|
|
for (i = 0; i < ((tri_ang_chosen == 0) * 3) + 1; i++) {
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
canvas->w / 2 - x1 + i, canvas->h / 2 + y1,
|
|
canvas->w / 2 + x1 + i, canvas->h / 2 - y1, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
}
|
|
|
|
/* angle 2 */
|
|
x1 = cos(tri_ang[1]) * canvas->w;
|
|
y1 = sin(tri_ang[1]) * canvas->w;
|
|
for (i = 0; i < ((tri_ang_chosen == 1) * 3) + 1; i++) {
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
canvas->w / 2 - x1 + i, canvas->h / 2 + y1,
|
|
canvas->w / 2 + x1 + i, canvas->h / 2 - y1, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
}
|
|
} else if (tool == TOOL_OBLQ_SELECT || tool == TOOL_OBLQ_SELECT_ALT) {
|
|
/* Oblique */
|
|
|
|
/* vertical */
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
canvas->w / 2, 0,
|
|
canvas->w / 2, canvas->h - 1, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* horizontal */
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
0, canvas->h / 2,
|
|
canvas->w - 1, canvas->h / 2, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
|
|
/* diagonal (receding) */
|
|
x1 = cos(oblq_ang) * canvas->w;
|
|
y1 = sin(oblq_ang) * canvas->h;
|
|
if (tool == TOOL_OBLQ_SELECT_ALT) {
|
|
y1 = -y1;
|
|
}
|
|
api->line((void *) api, tool, canvas, NULL,
|
|
canvas->w / 2 - x1, canvas->h / 2 + y1,
|
|
canvas->w / 2 + x1, canvas->h / 2 - y1, 12,
|
|
n_pt_persp_line_xor_callback);
|
|
}
|
|
}
|
|
|
|
#define DOT_WIDTH 12
|
|
|
|
void n_pt_persp_draw_one_point(magic_api * api, SDL_Surface * canvas, int x, int y, int i) {
|
|
int xx, yy;
|
|
Uint8 r, g, b;
|
|
|
|
for (yy = -(DOT_WIDTH + i); yy <= DOT_WIDTH + i; yy++) {
|
|
for (xx = -(DOT_WIDTH + i) + (yy % 2); xx <= DOT_WIDTH + i; xx += 2) {
|
|
if (api->in_circle(xx, yy, DOT_WIDTH) && abs(xx) >= i && abs(yy) >= i) {
|
|
SDL_GetRGB(api->getpixel(canvas, x + xx, y + yy), canvas->format, &r, &g, &b);
|
|
r ^= 255;
|
|
g ^= 255;
|
|
b ^= 255;
|
|
api->putpixel(canvas, x + xx, y + yy, SDL_MapRGB(canvas->format, r, g, b));
|
|
}
|
|
}
|
|
}
|
|
}
|