From 3f116427a1b76ab986020164742b81a5ae572674 Mon Sep 17 00:00:00 2001 From: eddebaby Date: Tue, 20 Apr 2021 01:16:59 +0100 Subject: [PATCH] One Click Highlight - SHIFT to get DK2+ style marking (#1016) Use SHIFT and LMB to drag an area of slabs to tag/untag Hold SHIFT and RMB to drag an area of slabs to tag/untag, and then click LMB to tag/untag the selected slabs Also resolved some build warnings --- src/config_campaigns.c | 2 +- src/dungeon_data.h | 3 + src/front_input.c | 13 +++- src/frontend.cpp | 7 +- src/main.cpp | 4 +- src/packets.c | 73 ++++++++++++++----- src/packets.h | 1 + src/roomspace.c | 150 ++++++++++++++++++++++++++++++++++---- src/roomspace.h | 5 ++ src/roomspace_detection.c | 2 +- version.mk | 2 +- 11 files changed, 219 insertions(+), 43 deletions(-) diff --git a/src/config_campaigns.c b/src/config_campaigns.c index c5cdd4faab..47b6d74c86 100644 --- a/src/config_campaigns.c +++ b/src/config_campaigns.c @@ -642,7 +642,7 @@ short parse_campaign_common_blocks(struct GameCampaign *campgn,char *buf,long le else { k = atoi(word_buf); if (k > 0) { - char* newname = get_string(STRINGS_MAX+k); + const char* newname = get_string(STRINGS_MAX+k); if (strcasecmp(newname,"") != 0) { LbStringCopy(campgn->name,newname,LINEMSG_SIZE); // use the index provided in the config file to get a specific UI string } diff --git a/src/dungeon_data.h b/src/dungeon_data.h index 050a1877fd..973206a939 100644 --- a/src/dungeon_data.h +++ b/src/dungeon_data.h @@ -308,6 +308,9 @@ struct DungeonAdd unsigned long evil_creatures_converted; unsigned long good_creatures_converted; TbBool one_click_lock_cursor; + TbBool ignore_next_PCtr_RBtnRelease; + TbBool ignore_next_PCtr_LBtnRelease; + long swap_to_untag_mode; // 0 = no, 1 = maybe, 2= yes, -1 = disable }; /******************************************************************************/ extern struct Dungeon bad_dungeon; diff --git a/src/front_input.c b/src/front_input.c index d185da7e1e..b5a45eef6a 100644 --- a/src/front_input.c +++ b/src/front_input.c @@ -137,7 +137,6 @@ void update_gui_layer() // Determine the current/correct GUI Layer to use at this moment struct PlayerInfo* player = get_my_player(); - struct DungeonAdd *dungeonadd = get_dungeonadd(player->id_number); if ( ((player->work_state == PSt_Sell) || (player->work_state == PSt_BuildRoom) || (render_roomspace.highlight_mode)) && (is_game_key_pressed(Gkey_BestRoomSpace, NULL, true) || is_game_key_pressed(Gkey_SquareRoomSpace, NULL, true)) ) { @@ -194,6 +193,12 @@ int is_game_key_pressed(long key_id, long *val, TbBool ignore_mods) { return 0; } + if ( (key_id == Gkey_CrtrContrlMod) && ( + (settings.kbkeys[Gkey_CrtrContrlMod].code == settings.kbkeys[Gkey_BestRoomSpace].code) || + (settings.kbkeys[Gkey_CrtrContrlMod].code == settings.kbkeys[Gkey_SquareRoomSpace].code) ) ) + { + return 0; + } } if ((key_id == Gkey_RotateMod) || (key_id == Gkey_SpeedMod) || (key_id == Gkey_CrtrContrlMod) || (key_id == Gkey_CrtrQueryMod)) { @@ -1818,7 +1823,7 @@ TbBool get_player_coords_and_context(struct Coord3d *pos, unsigned char *context unsigned int slb_y = subtile_slab_fast(y); struct SlabMap* slb = get_slabmap_block(slb_x, slb_y); struct SlabAttr* slbattr = get_slab_attrs(slb); - if (slab_kind_is_door(slb->kind) && (slabmap_owner(slb) == player->id_number)) + if (slab_kind_is_door(slb->kind) && (slabmap_owner(slb) == player->id_number) && (dungeonadd->one_click_lock_cursor == 0)) { *context = CSt_DoorKey; pos->x.val = (x<<8) + top_pointed_at_frac_x; @@ -1836,13 +1841,13 @@ TbBool get_player_coords_and_context(struct Coord3d *pos, unsigned char *context pos->x.val = (x<<8) + top_pointed_at_frac_x; pos->y.val = (y<<8) + top_pointed_at_frac_y; } else - if ((slb_x >= map_tiles_x) || (slb_y >= map_tiles_y)) + if (((slb_x >= map_tiles_x) || (slb_y >= map_tiles_y)) && (dungeonadd->one_click_lock_cursor == 0)) { *context = CSt_DefaultArrow; pos->x.val = (block_pointed_at_x<<8) + pointed_at_frac_x; pos->y.val = (block_pointed_at_y<<8) + pointed_at_frac_y; } else - if (((slbattr->block_flags & (SlbAtFlg_Filled|SlbAtFlg_Digable|SlbAtFlg_Valuable)) != 0) || dungeonadd->one_click_lock_cursor == 1) + if (((slbattr->block_flags & (SlbAtFlg_Filled|SlbAtFlg_Digable|SlbAtFlg_Valuable)) != 0) || (dungeonadd->one_click_lock_cursor == 1)) { *context = CSt_PickAxe; pos->x.val = (x<<8) + top_pointed_at_frac_x; diff --git a/src/frontend.cpp b/src/frontend.cpp index 5db0f0ad77..3c5ce8f8e4 100644 --- a/src/frontend.cpp +++ b/src/frontend.cpp @@ -644,12 +644,15 @@ void create_message_box(const char *title, const char *line1, const char *line2, short game_is_busy_doing_gui(void) { + struct PlayerInfo *player; + player = get_my_player(); + struct DungeonAdd *dungeonadd = get_dungeonadd(player->id_number); + if (dungeonadd->one_click_lock_cursor) + return false; if (!busy_doing_gui) return false; if (battle_creature_over <= 0) return true; - struct PlayerInfo *player; - player = get_my_player(); PowerKind pwkind; pwkind = 0; if (player->work_state < PLAYER_STATES_COUNT) diff --git a/src/main.cpp b/src/main.cpp index 2036a6ddfa..47c0866eae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3102,7 +3102,9 @@ void tag_cursor_blocks_dig(PlayerNumber plyr_idx, MapSubtlCoord stl_x, MapSubtlC { SYNCDBG(7,"Starting for player %d at subtile (%d,%d)",(int)plyr_idx,(int)stl_x,(int)stl_y); //_DK_tag_cursor_blocks_dig(plyr_idx, stl_x, stl_y, full_slab); + struct PlayerInfo* player = get_player(plyr_idx); struct DungeonAdd* dungeonadd = get_dungeonadd(plyr_idx); + struct Packet* pckt = get_packet_direct(player->packet_num); MapSlabCoord slb_x = subtile_slab_fast(stl_x); MapSlabCoord slb_y = subtile_slab_fast(stl_y); int floor_height_z = floor_height_for_volume_box(plyr_idx, slb_x, slb_y); @@ -3124,7 +3126,7 @@ void tag_cursor_blocks_dig(PlayerNumber plyr_idx, MapSubtlCoord stl_x, MapSubtlC { line_color = SLC_YELLOW; } - if (is_my_player_number(plyr_idx) && !game_is_busy_doing_gui() && (game.small_map_state != 2)) + if (is_my_player_number(plyr_idx) && !game_is_busy_doing_gui() && (game.small_map_state != 2) && ((pckt->control_flags & PCtr_MapCoordsValid) != 0)) { map_volume_box.visible = 1; map_volume_box.color = line_color; diff --git a/src/packets.c b/src/packets.c index 3f2232627e..51fb1afe30 100644 --- a/src/packets.c +++ b/src/packets.c @@ -515,7 +515,7 @@ TbBool process_dungeon_power_hand_state(long plyr_idx) return false; } struct Thing* thing = get_nearest_thing_for_hand_or_slap(plyr_idx, x, y); - if (!thing_is_invalid(thing)) + if (!thing_is_invalid(thing) && (dungeonadd->one_click_lock_cursor == 0)) { SYNCDBG(19,"Thing %d under hand at (%d,%d)",(int)thing->index,(int)thing->mappos.x.stl.num,(int)thing->mappos.y.stl.num); if (player->hand_thing_idx == 0) @@ -689,7 +689,8 @@ void set_tag_untag_mode(PlayerNumber plyr_idx, MapSubtlCoord stl_x, MapSubtlCoor struct PlayerInfo* player = get_player(plyr_idx); // The commented out section is the old way, this check is now performed as part of keeper_highlight_roomspace() in roomspace.cabs // which sets render_roomspace.untag_mode - /*i = get_subtile_number(stl_slab_center_subtile(stl_x),stl_slab_center_subtile(stl_y)); + /*long i; + i = get_subtile_number(stl_slab_center_subtile(stl_x),stl_slab_center_subtile(stl_y)); if (find_from_task_list(plyr_idx,i) != -1) player->allocflags |= PlaF_ChosenSlabHasActiveTask; else @@ -704,8 +705,6 @@ void set_tag_untag_mode(PlayerNumber plyr_idx, MapSubtlCoord stl_x, MapSubtlCoor TbBool process_dungeon_control_packet_dungeon_control(long plyr_idx) { struct Thing *thing; - - long i; struct PlayerInfo* player = get_player(plyr_idx); struct Dungeon* dungeon = get_players_dungeon(player); struct DungeonAdd* dungeonadd = get_dungeonadd(plyr_idx); @@ -714,8 +713,6 @@ TbBool process_dungeon_control_packet_dungeon_control(long plyr_idx) MapCoord y = ((unsigned short)pckt->pos_y); MapSubtlCoord stl_x = coord_subtile(x); MapSubtlCoord stl_y = coord_subtile(y); - MapSubtlCoord cx = stl_slab_starting_subtile(stl_x); - MapSubtlCoord cy = stl_slab_starting_subtile(stl_y); if ((pckt->control_flags & PCtr_LBtnAnyAction) == 0) player->secondary_cursor_state = CSt_DefaultArrow; player->primary_cursor_state = (unsigned short)(pckt->additional_packet_values & PCAdV_ContextMask) >> 1; // get current cursor state from pckt->additional_packet_values @@ -786,15 +783,18 @@ TbBool process_dungeon_control_packet_dungeon_control(long plyr_idx) } if (player->cursor_button_down != 0) { - if (player->primary_cursor_state == player->secondary_cursor_state) + if (!render_roomspace.drag_mode) // allow drag and click to not place on LMB hold { - if (player->secondary_cursor_state == CSt_PickAxe) - { - keeper_highlight_roomspace(plyr_idx, &render_roomspace, 0); - } else - if ((player->secondary_cursor_state == CSt_PowerHand) && ((player->additional_flags & PlaAF_NoThingUnderPowerHand) != 0)) + if (player->primary_cursor_state == player->secondary_cursor_state) { - keeper_highlight_roomspace(plyr_idx, &render_roomspace, 0); + if (player->secondary_cursor_state == CSt_PickAxe) + { + keeper_highlight_roomspace(plyr_idx, &render_roomspace, 0); + } else + if ((player->secondary_cursor_state == CSt_PowerHand) && ((player->additional_flags & PlaAF_NoThingUnderPowerHand) != 0)) + { + keeper_highlight_roomspace(plyr_idx, &render_roomspace, 0); + } } } unset_packet_control(pckt, PCtr_LBtnRelease); @@ -809,6 +809,15 @@ TbBool process_dungeon_control_packet_dungeon_control(long plyr_idx) { if (player->secondary_cursor_state == CSt_DefaultArrow) player->secondary_cursor_state = player->primary_cursor_state; + if (dungeonadd->ignore_next_PCtr_LBtnRelease) + { + dungeonadd->ignore_next_PCtr_LBtnRelease = false; + if ((pckt->control_flags & PCtr_RBtnHeld) == 0) + { + player->cursor_button_down = 0; + } + unset_packet_control(pckt, PCtr_LBtnRelease); + } else if (player->cursor_button_down != 0) { thing = thing_get(player->thing_under_hand); @@ -850,7 +859,7 @@ TbBool process_dungeon_control_packet_dungeon_control(long plyr_idx) } else if (player->secondary_cursor_state == player->primary_cursor_state) { - if (player->primary_cursor_state == CSt_PickAxe) + if ((player->primary_cursor_state == CSt_PickAxe) || ((player->primary_cursor_state == CSt_PowerHand) && render_roomspace.drag_mode)) { keeper_highlight_roomspace(plyr_idx, &render_roomspace, 9); } else @@ -865,9 +874,21 @@ TbBool process_dungeon_control_packet_dungeon_control(long plyr_idx) if ((pckt->control_flags & PCtr_RBtnHeld) == 0) { player->cursor_button_down = 0; + dungeonadd->one_click_lock_cursor = 0; } unset_packet_control(pckt, PCtr_LBtnRelease); - dungeonadd->one_click_lock_cursor = 0; + if (render_roomspace.drag_mode) + { + if ((pckt->control_flags & PCtr_RBtnHeld) == 0) + { + render_roomspace.drag_mode = false; + } + else + { + render_roomspace.untag_mode = !render_roomspace.untag_mode; + set_tag_untag_mode(plyr_idx, stl_x, stl_y); + } + } player->secondary_cursor_state = CSt_DefaultArrow; player->additional_flags &= ~PlaAF_NoThingUnderPowerHand; } @@ -875,9 +896,18 @@ TbBool process_dungeon_control_packet_dungeon_control(long plyr_idx) if ((pckt->control_flags & PCtr_RBtnRelease) != 0) { + if (dungeonadd->ignore_next_PCtr_RBtnRelease && (dungeonadd->one_click_lock_cursor == 0)) + { + dungeonadd->ignore_next_PCtr_RBtnRelease = false; + if ((pckt->control_flags & PCtr_LBtnHeld) == 0) + { + player->cursor_button_down = 0; + } + unset_packet_control(pckt, PCtr_RBtnRelease); + } else if (player->cursor_button_down != 0) { - if (!power_hand_is_empty(player)) + if (!power_hand_is_empty(player) && (dungeonadd->one_click_lock_cursor == 0)) { if (dump_first_held_thing_on_map(player->id_number, stl_x, stl_y, 1)) { if ((pckt->control_flags & PCtr_LBtnHeld) == 0) @@ -888,18 +918,24 @@ TbBool process_dungeon_control_packet_dungeon_control(long plyr_idx) } } else { - if (player->primary_cursor_state == CSt_PowerHand) { + if (player->primary_cursor_state == CSt_PowerHand && (dungeonadd->one_click_lock_cursor == 0)) { thing = get_nearest_thing_for_slap(plyr_idx, subtile_coord_center(stl_x), subtile_coord_center(stl_y)); magic_use_available_power_on_thing(plyr_idx, PwrK_SLAP, 0, stl_x, stl_y, thing, PwMod_Default); } if ((pckt->control_flags & PCtr_LBtnHeld) == 0) { player->cursor_button_down = 0; + dungeonadd->one_click_lock_cursor = 0; } unset_packet_control(pckt, PCtr_RBtnRelease); } } } + if (player->cursor_button_down == 0 || dungeonadd->one_click_lock_cursor == 0) + { + //if (untag_or_tag_completed_or_cancelled) + dungeonadd->swap_to_untag_mode = 0; // no + } return true; } @@ -908,6 +944,7 @@ TbBool process_dungeon_control_packet_clicks(long plyr_idx) struct Thing *thing; PowerKind pwkind; struct PlayerInfo* player = get_player(plyr_idx); + struct DungeonAdd *dungeonadd = get_dungeonadd(plyr_idx); struct Packet* pckt = get_packet_direct(player->packet_num); SYNCDBG(6,"Starting for player %d state %s",(int)plyr_idx,player_state_code_name(player->work_state)); player->full_slab_cursor = 1; @@ -1824,7 +1861,7 @@ TbBool process_dungeon_control_packet_clicks(long plyr_idx) } if (((pckt->control_flags & PCtr_HeldAnyButton) != 0) && (influence_own_creatures)) { - if ((player->secondary_cursor_state == CSt_DefaultArrow) || (player->secondary_cursor_state == CSt_PowerHand)) + if (((player->secondary_cursor_state == CSt_DefaultArrow) || (player->secondary_cursor_state == CSt_PowerHand)) && (dungeonadd->one_click_lock_cursor == 0)) stop_creatures_around_hand(plyr_idx, stl_x, stl_y); } return ret; diff --git a/src/packets.h b/src/packets.h index e891d0ac9a..4ea7d912f1 100644 --- a/src/packets.h +++ b/src/packets.h @@ -261,6 +261,7 @@ void close_packet_file(void); TbBool reinit_packets_after_load(void); struct Room *keeper_build_room(long stl_x,long stl_y,long plyr_idx,long rkind); TbBool player_sell_room_at_subtile(long plyr_idx, long stl_x, long stl_y); +void set_tag_untag_mode(PlayerNumber plyr_idx, MapSubtlCoord stl_x, MapSubtlCoord stl_y); /******************************************************************************/ #ifdef __cplusplus } diff --git a/src/roomspace.c b/src/roomspace.c index cbedd300b5..0348ab7c36 100644 --- a/src/roomspace.c +++ b/src/roomspace.c @@ -33,7 +33,7 @@ extern "C" { /******************************************************************************/ int user_defined_roomspace_width = DEFAULT_USER_ROOMSPACE_WIDTH; int roomspace_detection_looseness = DEFAULT_USER_ROOMSPACE_DETECTION_LOOSENESS; -struct RoomSpace render_roomspace = { {{false}}, 1, true, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0, false, true, false, false, false, false }; +struct RoomSpace render_roomspace = { {{false}}, 1, true, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0, false, true, false, false, false, false, 0, 0, 0, 0, false }; /******************************************************************************/ TbBool can_afford_roomspace(PlayerNumber plyr_idx, RoomKind rkind, int slab_count) { @@ -78,6 +78,42 @@ int can_build_roomspace_of_dimensions_loose(PlayerNumber plyr_idx, RoomKind rkin return count; } +struct RoomSpace create_box_roomspace_from_drag(struct RoomSpace roomspace, MapSlabCoord start_x, MapSlabCoord start_y, MapSlabCoord end_x, MapSlabCoord end_y) +{ + if (abs(end_x - start_x) >= MAX_USER_ROOMSPACE_WIDTH) + { + end_x = ((end_x >= start_x) ? (start_x + MAX_USER_ROOMSPACE_WIDTH - 1) : (start_x - MAX_USER_ROOMSPACE_WIDTH + 1)); + } + if (abs(end_y - start_y) >= MAX_USER_ROOMSPACE_WIDTH) + { + end_y = ((end_y >= start_y) ? (start_y + MAX_USER_ROOMSPACE_WIDTH - 1) : (start_y - MAX_USER_ROOMSPACE_WIDTH + 1)); + } + TbBool blank_slab_grid[MAX_ROOMSPACE_WIDTH][MAX_ROOMSPACE_WIDTH] = {{false}}; + memcpy(&roomspace.slab_grid, &blank_slab_grid, sizeof(blank_slab_grid)); + roomspace.left = ((start_x <= end_x) ? start_x : end_x); + roomspace.right = ((end_x >= start_x) ? end_x : start_x); + roomspace.top = ((start_y <= end_y) ? start_y : end_y); + roomspace.bottom = ((end_y >= start_y) ? end_y : start_y); + roomspace.width = roomspace.right - roomspace.left + 1; + roomspace.height = roomspace.bottom - roomspace.top + 1; + roomspace.slab_count = roomspace.width * roomspace.height; + roomspace.centreX = roomspace.left + calc_distance_from_roomspace_centre(roomspace.width, 0); + roomspace.centreY = roomspace.top + calc_distance_from_roomspace_centre(roomspace.height, 0); + roomspace.is_roomspace_a_single_subtile = false; + roomspace.is_roomspace_a_box = true; + roomspace.render_roomspace_as_box = true; + roomspace.tag_for_dig = false; + roomspace.highlight_mode = false; + roomspace.untag_mode = false; + roomspace.one_click_mode_exclusive = false; + roomspace.drag_mode = true; + roomspace.drag_start_x = start_x; + roomspace.drag_start_y = start_y; + roomspace.drag_end_x = end_x; + roomspace.drag_end_y = end_y; + return roomspace; +} + struct RoomSpace create_box_roomspace(struct RoomSpace roomspace, int width, int height, int centre_x, int centre_y) { TbBool blank_slab_grid[MAX_ROOMSPACE_WIDTH][MAX_ROOMSPACE_WIDTH] = {{false}}; @@ -98,6 +134,7 @@ struct RoomSpace create_box_roomspace(struct RoomSpace roomspace, int width, int roomspace.highlight_mode = false; roomspace.untag_mode = false; roomspace.one_click_mode_exclusive = false; + roomspace.drag_mode = false; return roomspace; } @@ -356,7 +393,7 @@ struct RoomSpace get_current_room_as_roomspace(PlayerNumber current_plyr_idx, Ma { struct SlabMap *slb = get_slabmap_block(cursor_x, cursor_y); // Set default "room" - i.e. 1x1 slabs, centred on the cursor - struct RoomSpace default_room = { {{false}}, 0, true, 1, 1, cursor_x, cursor_y, cursor_x, cursor_y, cursor_x, cursor_y, 0, 0, current_plyr_idx, RoK_SELL, false, 0, 0, false, true, false, false, false, false }; + struct RoomSpace default_room = { {{false}}, 0, true, 1, 1, cursor_x, cursor_y, cursor_x, cursor_y, cursor_x, cursor_y, 0, 0, current_plyr_idx, RoK_SELL, false, 0, 0, false, true, false, false, false, false, 0, 0, 0, 0, false }; if (slabmap_owner(slb) == current_plyr_idx) { @@ -459,13 +496,48 @@ void get_dungeon_highlight_user_roomspace(PlayerNumber plyr_idx, MapSubtlCoord s TbBool highlight_mode = false; TbBool untag_mode = false; TbBool one_click_mode_exclusive = false; + MapSlabCoord drag_start_x = slb_x; + MapSlabCoord drag_start_y = slb_y; struct DungeonAdd *dungeonadd = get_dungeonadd(player->id_number); struct Packet* pckt = get_packet_direct(player->packet_num); + if (!is_game_key_pressed(Gkey_BestRoomSpace, &keycode, true)) + { + // exit out of click and drag mode + if (render_roomspace.drag_mode) + { + dungeonadd->one_click_lock_cursor = 0; + if ((pckt->control_flags & PCtr_LBtnHeld) == PCtr_LBtnHeld) + { + dungeonadd->ignore_next_PCtr_LBtnRelease = true; + } + } + render_roomspace.drag_mode = false; + } + if (dungeonadd->ignore_next_PCtr_LBtnRelease) + { + // because player cancelled a tag/untag with RMB, we need to default back to vanilla 1x1 box + render_roomspace.drag_mode = false; + dungeonadd->one_click_lock_cursor = 0; + reset_dungeon_build_room_ui_variables(); + current_roomspace = create_box_roomspace(render_roomspace, width, height, slb_x, slb_y); + current_roomspace.highlight_mode = false; + current_roomspace.untag_mode = false; + current_roomspace.one_click_mode_exclusive = false; + current_roomspace = check_roomspace_for_diggable_slabs(current_roomspace, plyr_idx); + player->boxsize = current_roomspace.slab_count; + render_roomspace = current_roomspace; + return; + } + if (!render_roomspace.drag_mode) // reset drag start slab + { + render_roomspace.drag_start_x = slb_x; + render_roomspace.drag_start_y = slb_y; + } if ((pckt->control_flags & PCtr_LBtnHeld) == PCtr_LBtnHeld) // highlight "paint mode" enabled { dungeonadd->one_click_lock_cursor = 1; - untag_mode = render_roomspace.untag_mode; + untag_mode = render_roomspace.untag_mode; // get tag/untag mode from the slab that was clicked (before the user started holding mouse button) } else // user is hovering the mouse cursor { @@ -474,8 +546,39 @@ void get_dungeon_highlight_user_roomspace(PlayerNumber plyr_idx, MapSubtlCoord s untag_mode = true; } } - - if (is_game_key_pressed(Gkey_SquareRoomSpace, &keycode, true)) // Define square room (mouse scroll-wheel changes size - default is 5x5) + if (dungeonadd->swap_to_untag_mode == 0) // if swap_to_untag_mode == no / enabled + { + //if (untag_or_tag_started_on_undiggable_highslab) + if ((subtile_is_diggable_for_player(plyr_idx, stl_x, stl_y, true)) && (!subtile_is_diggable_for_player(plyr_idx, stl_x, stl_y, false))) + { + dungeonadd->swap_to_untag_mode = 1; // maybe + } + } + if (is_game_key_pressed(Gkey_BestRoomSpace, &keycode, true)) // Use "modern" click and drag method + { + if (((pckt->control_flags & PCtr_HeldAnyButton) != 0) || ((pckt->control_flags & PCtr_LBtnRelease) != 0)) + { + dungeonadd->one_click_lock_cursor = 1; // Allow click and drag over low slabs (if clicked on high slab) + untag_mode = render_roomspace.untag_mode; // get tag/untag mode from the slab that was clicked (before the user started holding mouse button) + one_click_mode_exclusive = true; // Block camera zoom/rotate if Ctrl is held with LMB/RMB + drag_start_x = render_roomspace.drag_start_x; // if we are dragging, get the starting coords from the slab the player clicked on + drag_start_y = render_roomspace.drag_start_y; + } + if (((pckt->control_flags & PCtr_RBtnHeld) != 0) && ((pckt->control_flags & PCtr_LBtnClick) != 0)) + { + dungeonadd->ignore_next_PCtr_RBtnRelease = true; + } + if (((pckt->control_flags & PCtr_LBtnHeld) != 0) && ((pckt->control_flags & PCtr_RBtnClick) != 0)) + { + dungeonadd->ignore_next_PCtr_LBtnRelease = true; + dungeonadd->ignore_next_PCtr_RBtnRelease = true; + drag_start_x = slb_x; + drag_start_y = slb_y; + } + highlight_mode = true; + current_roomspace = create_box_roomspace_from_drag(render_roomspace, drag_start_x, drag_start_y, slb_x, slb_y); + } + else if (is_game_key_pressed(Gkey_SquareRoomSpace, &keycode, true)) // Define square room (mouse scroll-wheel changes size - default is 5x5) { if ((pckt->control_flags & PCtr_HeldAnyButton) != 0) // Block camera zoom/rotate if Ctrl is held with LMB/RMB { @@ -497,28 +600,39 @@ void get_dungeon_highlight_user_roomspace(PlayerNumber plyr_idx, MapSubtlCoord s } width = height = user_defined_roomspace_width; highlight_mode = true; + current_roomspace = create_box_roomspace(render_roomspace, width, height, slb_x, slb_y); } else { reset_dungeon_build_room_ui_variables(); width = height = numpad_to_value(false); + current_roomspace = create_box_roomspace(render_roomspace, width, height, slb_x, slb_y); } - current_roomspace = create_box_roomspace(render_roomspace, width, height, slb_x, slb_y); current_roomspace.highlight_mode = highlight_mode; current_roomspace.untag_mode = untag_mode; current_roomspace.one_click_mode_exclusive = one_click_mode_exclusive; current_roomspace = check_roomspace_for_diggable_slabs(current_roomspace, plyr_idx); - if (dungeonadd->one_click_lock_cursor == 0 && !untag_mode && current_roomspace.slab_count == 0 && ((current_roomspace.width > 1) || (current_roomspace.height > 1))) + if (dungeonadd->swap_to_untag_mode == 1) // if swap_to_untag_mode == maybe { - // if highlight roomspace is empty (and we aren't in paint mode, and we were trying to tag slabs) - // then check for slabs to untag instead, and if some are found, give that option to the player - struct RoomSpace untag_roomspace = current_roomspace; - untag_roomspace.untag_mode = true; - untag_roomspace = check_roomspace_for_diggable_slabs(untag_roomspace, plyr_idx); - if (untag_roomspace.slab_count > 0) + // highlight roomspace was started on undiggable highslab, and we are therefore in "tag mode"... + if (current_roomspace.slab_count == 0) { - current_roomspace = untag_roomspace; + // if highlight roomspace is empty + // then check for slabs for untagging instead, and if some are found, change to untag mode + struct RoomSpace untag_roomspace = current_roomspace; + untag_roomspace.untag_mode = true; + untag_roomspace = check_roomspace_for_diggable_slabs(untag_roomspace, plyr_idx); + if (untag_roomspace.slab_count > 0) + { + current_roomspace = untag_roomspace; + dungeonadd->swap_to_untag_mode = 2; + } + } + else if (current_roomspace.slab_count > 0) + { + // player has started a "room" in tag mode, so... + dungeonadd->swap_to_untag_mode = -1; // disable } } player->boxsize = current_roomspace.slab_count; @@ -526,11 +640,17 @@ void get_dungeon_highlight_user_roomspace(PlayerNumber plyr_idx, MapSubtlCoord s { current_roomspace.tag_for_dig = true; } - if (dungeonadd->one_click_lock_cursor == 1) + if (dungeonadd->one_click_lock_cursor == 1 && ((pckt->control_flags & PCtr_LBtnHeld) != 0) && !current_roomspace.drag_mode) { current_roomspace.is_roomspace_a_box = true; // force full box cursor in "paint mode" - this stops the accurate boundbox appearing for a frame, before the slabs are tagged/untagged (which appears as flickering to the user) } render_roomspace = current_roomspace; + if (dungeonadd->swap_to_untag_mode == 2) // if swap_to_untag_mode == yes + { + // change to untag mode, as requested, and disable swap_to_untag_mode + set_tag_untag_mode(plyr_idx, stl_x, stl_y); + dungeonadd->swap_to_untag_mode = -1; // disable + } } void get_dungeon_sell_user_roomspace(PlayerNumber plyr_idx, MapSubtlCoord stl_x, MapSubtlCoord stl_y) diff --git a/src/roomspace.h b/src/roomspace.h index 982b8e6680..8dd162a7ea 100644 --- a/src/roomspace.h +++ b/src/roomspace.h @@ -84,6 +84,11 @@ struct RoomSpace { TbBool highlight_mode; TbBool untag_mode; TbBool one_click_mode_exclusive; + MapSlabCoord drag_start_x; + MapSlabCoord drag_start_y; + MapSlabCoord drag_end_x; + MapSlabCoord drag_end_y; + TbBool drag_mode; }; /******************************************************************************/ extern int user_defined_roomspace_width; diff --git a/src/roomspace_detection.c b/src/roomspace_detection.c index 9f7989e5b9..93b0a0526b 100644 --- a/src/roomspace_detection.c +++ b/src/roomspace_detection.c @@ -416,7 +416,7 @@ struct RoomSpace get_biggest_roomspace(PlayerNumber plyr_idx, RoomKind rkind, int subRoomCheckCount = 6; // the number of sub-rooms to combine in to a final meta-room int bestRoomsCount = 0; // Set default "room" - i.e. 1x1 slabs, centred on the cursor - struct RoomSpace best_room = { {{false}}, 1, true, 1, 1, cursor_x, cursor_y, cursor_x, cursor_y, cursor_x, cursor_y, rkind_cost, 0, plyr_idx, rkind, false, 0, 0, false, true, false, false, false, false }; + struct RoomSpace best_room = { {{false}}, 1, true, 1, 1, cursor_x, cursor_y, cursor_x, cursor_y, cursor_x, cursor_y, rkind_cost, 0, plyr_idx, rkind, false, 0, 0, false, true, false, false, false, false, 0, 0, 0, 0, false }; //int leniency = (((mode & 16) == 16)) ? tolerance : 0; // mode=16 :- (setting to 1 would allow e.g. 1 dirt block in the room) int leniency = 0; struct RoomSpace best_corridor = best_room; diff --git a/version.mk b/version.mk index fa1dac73f3..45cbbf7877 100644 --- a/version.mk +++ b/version.mk @@ -1,5 +1,5 @@ VER_MAJOR=0 VER_MINOR=4 VER_RELEASE=8 -VER_BUILD=2362 +VER_BUILD=2366 PACKAGE_SUFFIX=