undo, axis editing
This commit is contained in:
parent
6d6230c6a1
commit
5f7b8bac6d
BIN
apps/tools/twndel/data/bong.ogg
(Stored with Git LFS)
BIN
apps/tools/twndel/data/bong.ogg
(Stored with Git LFS)
Binary file not shown.
@ -78,6 +78,10 @@ typedef struct State {
|
|||||||
|
|
||||||
Object *objects;
|
Object *objects;
|
||||||
uint8_t objects_sz;
|
uint8_t objects_sz;
|
||||||
|
|
||||||
|
/* which axes are blocked and which are not */
|
||||||
|
/* order: x, y, z */
|
||||||
|
bool axis_mask[3];
|
||||||
} State;
|
} State;
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,13 +247,53 @@ static void process_operation_move_point(Operation *op) {
|
|||||||
/* TODO: show thresholds */
|
/* TODO: show thresholds */
|
||||||
|
|
||||||
/* change along axes, delta is accumulated when threshold is met*/
|
/* change along axes, delta is accumulated when threshold is met*/
|
||||||
int16_t zch = (int16_t)(floorf(vec3_dot(b, (Vec3){0,0,1}) * (float)POINTS_PER_METER));
|
int16_t xch = (int16_t)(floorf(vec3_dot(b, (Vec3){0,0,1}) * (float)POINTS_PER_METER)) * !state.axis_mask[0];
|
||||||
op->data.move_point.delta_x += zch;
|
xch -= xch % state.grid_snap_granularity;
|
||||||
state.points[op->data.move_point.point].x += zch;
|
state.points[op->data.move_point.point].x += xch;
|
||||||
|
op->data.move_point.delta_x += xch;
|
||||||
|
|
||||||
|
int16_t ych = (int16_t)(floorf(vec3_dot(b, (Vec3){0,-1,0}) * (float)POINTS_PER_METER)) * !state.axis_mask[1];
|
||||||
|
ych -= ych % state.grid_snap_granularity;
|
||||||
|
state.points[op->data.move_point.point].y += ych;
|
||||||
|
op->data.move_point.delta_y += ych;
|
||||||
|
|
||||||
|
int16_t zch = (int16_t)(floorf(vec3_dot(b, (Vec3){-1,0,0}) * (float)POINTS_PER_METER)) * !state.axis_mask[2];
|
||||||
|
zch -= zch % state.grid_snap_granularity;
|
||||||
|
state.points[op->data.move_point.point].z += zch;
|
||||||
|
op->data.move_point.delta_z += zch;
|
||||||
|
|
||||||
|
if (xch != 0 || ych != 0 || zch != 0)
|
||||||
|
audio_play("/data/bong.ogg", NULL, false, 0.12f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void reverse_operation_move_point(Operation *op) {
|
||||||
|
SDL_assert(op->kind == OPERATION_MOVE_POINT);
|
||||||
|
state.points[op->data.move_point.point].x -= op->data.move_point.delta_x;
|
||||||
|
state.points[op->data.move_point.point].y -= op->data.move_point.delta_y;
|
||||||
|
state.points[op->data.move_point.point].z -= op->data.move_point.delta_z;
|
||||||
|
audio_play("/data/drop.ogg", NULL, false, 0.4f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void process_operations(void) {
|
static void process_operations(void) {
|
||||||
|
if (input_action_just_pressed("undo")) {
|
||||||
|
/* TODO: checks and defined limit */
|
||||||
|
Operation *op = &state.op_stack[state.op_stack_ptr % UNDO_STACK_SIZE];
|
||||||
|
state.op_stack_ptr--;
|
||||||
|
|
||||||
|
switch (op->kind) {
|
||||||
|
case OPERATION_MOVE_POINT: {
|
||||||
|
reverse_operation_move_point(op);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
(void)0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!state.op_active) {
|
if (!state.op_active) {
|
||||||
uint16_t point_select; uint8_t obj_select;
|
uint16_t point_select; uint8_t obj_select;
|
||||||
if (find_closest_point(&obj_select, &point_select)) {
|
if (find_closest_point(&obj_select, &point_select)) {
|
||||||
@ -280,6 +320,7 @@ static void process_operations(void) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
(void)0;
|
(void)0;
|
||||||
}
|
}
|
||||||
@ -294,13 +335,20 @@ void game_tick(void) {
|
|||||||
state.camera_position = (Vec3){2,1,2};
|
state.camera_position = (Vec3){2,1,2};
|
||||||
state.camera_direction = vec3_norm(((Vec3){-2,-1,-2}));
|
state.camera_direction = vec3_norm(((Vec3){-2,-1,-2}));
|
||||||
state.camera_zoom = 0.5f;
|
state.camera_zoom = 0.5f;
|
||||||
|
state.grid_snap_granularity = 16;
|
||||||
|
state.axis_mask[1] = 1; state.axis_mask[2] = 1;
|
||||||
init = true;
|
init = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
input_action("toggle_display_mode", "Q");
|
input_action("toggle_display_mode", "Q");
|
||||||
input_action("toggle_projection", "E");
|
input_action("toggle_projection", "E");
|
||||||
|
|
||||||
|
input_action("toggle_x_axis", "Z");
|
||||||
|
input_action("toggle_y_axis", "X");
|
||||||
|
input_action("toggle_z_axis", "C");
|
||||||
|
|
||||||
input_action("select", "LCLICK");
|
input_action("select", "LCLICK");
|
||||||
|
input_action("undo", "F");
|
||||||
|
|
||||||
if (input_action_just_pressed("toggle_display_mode")) {
|
if (input_action_just_pressed("toggle_display_mode")) {
|
||||||
audio_play("/data/click.wav", NULL, false, 0.7f, 0.0f);
|
audio_play("/data/click.wav", NULL, false, 0.7f, 0.0f);
|
||||||
@ -312,32 +360,46 @@ void game_tick(void) {
|
|||||||
state.camera_is_orthographic = !state.camera_is_orthographic;
|
state.camera_is_orthographic = !state.camera_is_orthographic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (input_action_just_pressed("toggle_x_axis")) {
|
||||||
|
state.axis_mask[0] = 0; state.axis_mask[1] = 1; state.axis_mask[2] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_action_just_pressed("toggle_y_axis")) {
|
||||||
|
state.axis_mask[0] = 1; state.axis_mask[1] = 0; state.axis_mask[2] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_action_just_pressed("toggle_z_axis")) {
|
||||||
|
state.axis_mask[0] = 1; state.axis_mask[1] = 1; state.axis_mask[2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
process_camera_movement();
|
process_camera_movement();
|
||||||
process_operations();
|
process_operations();
|
||||||
|
|
||||||
/* axis helpers */
|
/* axis helpers */
|
||||||
/* idea: black out inactives when dragging points */
|
/* idea: black out inactives when dragging points */
|
||||||
/* idea: double selection of axes for diagonal edits */
|
/* idea: double selection of axes for diagonal edits */
|
||||||
draw_line_3d((Vec3){0}, (Vec3){0,0,256}, 1, (Color){255,0,0,125});
|
draw_line_3d((Vec3){0}, (Vec3){256,0,0}, 1, state.axis_mask[0] ? (Color){0,0,0,75} : (Color){255,0,0,125});
|
||||||
draw_billboard("/data/x.png",
|
draw_billboard("/data/x.png",
|
||||||
(Vec3){0,0,2},
|
|
||||||
(Vec2){0.1f, 0.1f},
|
|
||||||
(Rect){0},
|
|
||||||
(Color){255,0,0,255},
|
|
||||||
false);
|
|
||||||
draw_line_3d((Vec3){0}, (Vec3){256,0,0}, 1, (Color){0,0,255,125});
|
|
||||||
draw_billboard("/data/y.png",
|
|
||||||
(Vec3){2,0,0},
|
(Vec3){2,0,0},
|
||||||
(Vec2){0.1f, 0.1f},
|
(Vec2){0.1f, 0.1f},
|
||||||
(Rect){0},
|
(Rect){0},
|
||||||
(Color){0,0,255,255},
|
state.axis_mask[0] ? (Color){0,0,0,255} : (Color){255,0,0,255},
|
||||||
false);
|
false);
|
||||||
draw_line_3d((Vec3){0}, (Vec3){0,256,0}, 1, (Color){75,125,25,125});
|
|
||||||
draw_billboard("/data/z.png",
|
draw_line_3d((Vec3){0}, (Vec3){0,256,0}, 1, state.axis_mask[1] ? (Color){0,0,0,75} : (Color){75,125,25,125});
|
||||||
|
draw_billboard("/data/y.png",
|
||||||
(Vec3){0,1.5f,0},
|
(Vec3){0,1.5f,0},
|
||||||
(Vec2){0.1f, 0.1f},
|
(Vec2){0.1f, 0.1f},
|
||||||
(Rect){0},
|
(Rect){0},
|
||||||
(Color){75,125,25,255},
|
state.axis_mask[1] ? (Color){0,0,0,255} : (Color){75,125,25,255},
|
||||||
|
false);
|
||||||
|
|
||||||
|
draw_line_3d((Vec3){0}, (Vec3){0,0,256}, 1, state.axis_mask[2] ? (Color){0,0,0,75} : (Color){0,0,255,125});
|
||||||
|
draw_billboard("/data/z.png",
|
||||||
|
(Vec3){0,0,2},
|
||||||
|
(Vec2){0.1f, 0.1f},
|
||||||
|
(Rect){0},
|
||||||
|
state.axis_mask[2] ? (Color){0,0,0,255} : (Color){0,0,255,255},
|
||||||
false);
|
false);
|
||||||
|
|
||||||
for (uint8_t obj = 0; obj < state.objects_sz; ++obj)
|
for (uint8_t obj = 0; obj < state.objects_sz; ++obj)
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
/* plays audio file at specified channel or at scratch channel if NULL is passed, without ability to refer to it later */
|
/* plays audio file at specified channel or at scratch channel if NULL is passed, without ability to refer to it later */
|
||||||
/* path path must contain valid file extension to infer which file format it is */
|
/* path path must contain valid file extension to infer which file format it is */
|
||||||
/* supported formats: .ogg, .xm */
|
/* supported formats: .ogg, .xm */
|
||||||
|
/* mono or stereo only */
|
||||||
TWN_API void audio_play(const char *audio,
|
TWN_API void audio_play(const char *audio,
|
||||||
const char *channel, /* optional */
|
const char *channel, /* optional */
|
||||||
bool repeat, /* default: false */
|
bool repeat, /* default: false */
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
#include <physfs.h>
|
#include <physfs.h>
|
||||||
#include <physfsrwops.h>
|
#include <physfsrwops.h>
|
||||||
|
|
||||||
|
#define STB_VORBIS_MAX_CHANNELS 2
|
||||||
|
#define STB_VORBIS_NO_STDIO
|
||||||
|
#define STB_VORBIS_NO_INTEGER_CONVERSION
|
||||||
#define STB_VORBIS_NO_PUSHDATA_API
|
#define STB_VORBIS_NO_PUSHDATA_API
|
||||||
#define STB_VORBIS_HEADER_ONLY
|
#define STB_VORBIS_HEADER_ONLY
|
||||||
#include <stb_vorbis.c>
|
#include <stb_vorbis.c>
|
||||||
|
Loading…
Reference in New Issue
Block a user