From: Lukáš Jiřiště Date: Sat, 21 Dec 2024 22:06:45 +0000 (+0100) Subject: Add wire (node) drawing to schema mode X-Git-Url: https://git.ljiriste.work/?a=commitdiff_plain;h=dcfb63fb220c6c04818033b725a456f88d03bc78;p=FET_sim.git Add wire (node) drawing to schema mode Using the "c" key while in schema mode will start the drawing. When it is started over an existing node, the node is extended, else new node is created. When ending on a node, the drawn node and the end node are merged together. To exit the mode use any other key than the movement keys (best use "c"?). To choose the correct symbol for a segment, the t_node_segment had to be changed, and with that some functions (unrelated to wire drawing) had to be changed also. --- diff --git a/inc/FET_sim.h b/inc/FET_sim.h index a8c0a84..12eb982 100644 --- a/inc/FET_sim.h +++ b/inc/FET_sim.h @@ -52,10 +52,18 @@ typedef struct s_position long y; } t_position; +typedef char t_bitflag; + +// connects is a bitflag that encodes which sides the segment is connected to +// it seems reasonable to use (1 << orientation) +// UP = 1 +// LEFT = 2 +// DOWN = 4 +// RIGHT = 8 typedef struct s_node_segment { t_position position; - t_symbol symbol; + t_bitflag connects; } t_node_segment; typedef struct s_node @@ -136,6 +144,7 @@ typedef struct s_windows } t_windows; t_node *add_node(t_vec *nodes, t_state set_state); +void remove_node(t_vec *nodes, t_node *to_remove); t_mosfet *add_mosfet(t_vec *mosfets, t_type type, t_position pos, t_orientation orient); t_node *get_node_by_id(t_vec *nodes, t_id id); t_mosfet *get_mosfet_by_id(t_vec *mosfets, t_id id); @@ -152,6 +161,7 @@ const char *state_color_escape(t_state state); void draw_single(WINDOW *command_win, t_vec *nodes, const t_mosfet *mosfet); void schema_draw_mosfet(WINDOW *schematics_win, t_vec *nodes, const t_mosfet *mosfet); void schema_draw_node(WINDOW *schematics_win, const t_node *node); +void schema_draw_segment(WINDOW *schematics_win, const t_node_segment *segment); void update_nodes(t_vec *nodes, t_vec *mosfets); int should_open(t_vec *nodes, const t_mosfet *mosfet); diff --git a/src/build_helper.c b/src/build_helper.c index ff0f6d9..b8557ca 100644 --- a/src/build_helper.c +++ b/src/build_helper.c @@ -23,7 +23,7 @@ t_mosfet *get_connected(t_vec *mosfets, t_vec *connected, size_t ind) } int node_identity(const void *, const void *); -static void remove_node(t_vec *nodes, t_node *to_remove) +void remove_node(t_vec *nodes, t_node *to_remove) { size_t index; diff --git a/src/colors.c b/src/colors.c index 0f6cada..525c0db 100644 --- a/src/colors.c +++ b/src/colors.c @@ -130,32 +130,50 @@ void schema_draw_mosfet(WINDOW *schematics_win, t_vec *nodes, const t_mosfet *mo return ; } -t_symbol seg_symbol_to_print(t_symbol seg_symbol) +t_symbol seg_connects_to_symbol(t_bitflag connects) { - if (seg_symbol == 'd' || seg_symbol == 'u') - return (ACS_VLINE); - else if (seg_symbol == 'r' || seg_symbol == 'l') - return (ACS_HLINE); - else - return (seg_symbol); + switch (connects) + { + case 0x1: return ('^'); + case 0x2: return ('<'); + case 0x4: return ('v'); + case 0x8: return ('>'); + case 0x3: return (ACS_LRCORNER); + case 0x6: return (ACS_URCORNER); + case 0xC: return (ACS_ULCORNER); + case 0x9: return (ACS_LLCORNER); + case 0x5: return (ACS_VLINE); + case 0xA: return (ACS_HLINE); + case 0x7: return (ACS_RTEE); + case 0xE: return (ACS_TTEE); + case 0xD: return (ACS_LTEE); + case 0xB: return (ACS_BTEE); + case 0xF: return (ACS_PLUS); + default: return ('\0'); + } +} + +void schema_draw_segment(WINDOW *schematics_win, const t_node_segment *segment) +{ + t_symbol symbol; + + symbol = seg_connects_to_symbol(segment->connects); + if (symbol != '\0') + mvwaddch(schematics_win, segment->position.y, segment->position.x, symbol); + return ; } void schema_draw_node(WINDOW *schematics_win, const t_node *node) { const t_node_segment *seg; size_t i; - t_symbol symbol; wattron(schematics_win, COLOR_PAIR(get_state_color(node->state))); i = 0; while (i < node->segments.size) { seg = ft_vec_caccess(&node->segments, i); - symbol = seg_symbol_to_print(seg->symbol); - if (symbol != ' ') - { - mvwaddch(schematics_win, seg->position.y, seg->position.x, symbol); - } + schema_draw_segment(schematics_win, seg); ++i; } wattroff(schematics_win, COLOR_PAIR(get_state_color(node->state))); diff --git a/src/schema_mode.c b/src/schema_mode.c index 6153414..f910b52 100644 --- a/src/schema_mode.c +++ b/src/schema_mode.c @@ -54,6 +54,11 @@ static t_position pos_sub(t_position pos1, t_position pos2) return (res); } +static int pos_is_equal(t_position pos1, t_position pos2) +{ + return ((pos1.x == pos2.x) && (pos1.y == pos2.y)); +} + void add_terminal_segment(t_node *node, t_mosfet *mosfet, t_terminal term) { t_node_segment segment; @@ -62,38 +67,17 @@ void add_terminal_segment(t_node *node, t_mosfet *mosfet, t_terminal term) if (term == source) { segment.position = pos_add(mosfet_channel_rel_pos(mosfet), mosfet_up_rel_pos(mosfet)); - if (mosfet->orientation == LEFT) - segment.symbol = 'd'; - else if (mosfet->orientation == DOWN) - segment.symbol = 'r'; - else if (mosfet->orientation == RIGHT) - segment.symbol = 'u'; - else if (mosfet->orientation == UP) - segment.symbol = 'l'; + segment.connects = 1 << ((mosfet->orientation + 1) % 4); } else if (term == drain) { segment.position = pos_sub(mosfet_channel_rel_pos(mosfet), mosfet_up_rel_pos(mosfet)); - if (mosfet->orientation == LEFT) - segment.symbol = 'u'; - else if (mosfet->orientation == DOWN) - segment.symbol = 'l'; - else if (mosfet->orientation == RIGHT) - segment.symbol = 'd'; - else if (mosfet->orientation == UP) - segment.symbol = 'r'; + segment.connects = 1 << ((mosfet->orientation + 3) % 4); } else if (term == gate) { segment.position = pos_sub(segment.position, mosfet_channel_rel_pos(mosfet)); - if (mosfet->orientation == LEFT) - segment.symbol = 'r'; - else if (mosfet->orientation == DOWN) - segment.symbol = 'u'; - else if (mosfet->orientation == RIGHT) - segment.symbol = 'l'; - else if (mosfet->orientation == UP) - segment.symbol = 'd'; + segment.connects = 1 << ((mosfet->orientation + 2) % 4); } segment.position = pos_add(segment.position, mosfet->position); ft_vec_append(&node->segments, &segment); @@ -166,6 +150,143 @@ void schema_add_mosfet(WINDOW *schematics_win, t_vec *nodes, t_vec *mosfets, t_p } } +t_node_segment *find_node_seg_at_pos(t_node *node, t_position pos) +{ + size_t i; + t_node_segment *seg; + + i = 0; + while (i < node->segments.size) + { + seg = ft_vec_access(&node->segments, i); + if (pos_is_equal(seg->position, pos)) + return (seg); + ++i; + } + return (NULL); +} + +t_node *find_node_at_pos(t_vec *nodes, t_position pos) +{ + size_t i; + t_node *node; + + i = 0; + while (i < nodes->size) + { + node = ft_vec_access(nodes, i); + if (find_node_seg_at_pos(node, pos)) + return (node); + ++i; + } + return (NULL); +} + +t_bitflag merge_connect(t_bitflag connects1, t_bitflag connects2) +{ + return (connects1 | connects2); +} + +int place_segment(WINDOW *schematics_win, t_node *node, t_node_segment *prediction) +{ + char ch; + t_node_segment tmp; + + wmove(schematics_win, prediction->position.y, prediction->position.x); + ch = wgetch(schematics_win); + tmp = *prediction; + if (ch == 'l') + { + tmp.connects = 1 << LEFT; + ++tmp.position.x; + prediction->connects = merge_connect(prediction->connects, 1 << RIGHT); + } + else if (ch == 'k') + { + tmp.connects = 1 << DOWN; + --tmp.position.y; + prediction->connects = merge_connect(prediction->connects, 1 << UP); + } + else if (ch == 'j') + { + tmp.connects = 1 << UP; + ++tmp.position.y; + prediction->connects = merge_connect(prediction->connects, 1 << DOWN); + } + else if (ch == 'h') + { + tmp.connects = 1 << RIGHT; + --tmp.position.x; + prediction->connects = merge_connect(prediction->connects, 1 << LEFT); + } + else + return (1); // The choice not to ungetch is deliberate, because it felt weird sing it + ft_vec_append(&node->segments, prediction); + schema_draw_segment(schematics_win, prediction); + *prediction = tmp; + return (0); +} + +int cmp_seg(const void *v_seg1, const void *v_seg2) +{ + const t_node_segment *seg1; + const t_node_segment *seg2; + + seg1 = v_seg1; + seg2 = v_seg2; + if (seg1->position.x != seg2->position.x) + return ((seg1->position.x > seg2->position.x) - (seg1->position.x < seg2->position.x)); + if (seg1->position.y != seg2->position.y) + return ((seg1->position.y > seg2->position.y) - (seg1->position.x < seg2->position.x)); + return (0); +} + +void schema_user_draw_node(WINDOW *schematics_win, t_vec *nodes, t_vec *mosfets, t_position pos) +{ + t_node *chosen_node; + t_node *end_node; + t_node_segment seg; + t_node_segment *merge_seg; + size_t index; + + chosen_node = find_node_at_pos(nodes, pos); + if (!chosen_node) + { + chosen_node = add_node(nodes, floating); + seg.position = pos; + seg.connects = 0; + } + else + { + // I'm finding the seg twice here + seg = *find_node_seg_at_pos(chosen_node, pos); + ft_vec_find_index(&chosen_node->segments, &seg, &index, cmp_seg); + ft_vec_erase(&chosen_node->segments, index, NULL); + } + while (!place_segment(schematics_win, chosen_node, &seg)); + if (chosen_node->segments.size == 0) + { + remove_node(nodes, chosen_node); + return ; + } + end_node = find_node_at_pos(nodes, seg.position); + if (end_node) + { + merge_seg = find_node_seg_at_pos(end_node, seg.position); + merge_seg->connects = merge_connect(merge_seg->connects, seg.connects); + if (end_node->id != chosen_node->id) + merge_nodes(nodes, mosfets, chosen_node, end_node); + schema_draw_segment(schematics_win, merge_seg); + } + else + { + ft_vec_append(&chosen_node->segments, &seg); + schema_draw_segment(schematics_win, &seg); + } + wmove(schematics_win, seg.position.y, seg.position.x); + return ; +} + int handle_key_press(int ch, WINDOW *schematics_win, t_vec *nodes, t_vec *mosfets) { t_position pos; @@ -181,6 +302,8 @@ int handle_key_press(int ch, WINDOW *schematics_win, t_vec *nodes, t_vec *mosfet wmove(schematics_win, --pos.y, pos.x); else if (ch == 't') schema_add_mosfet(schematics_win, nodes, mosfets, pos); + else if (ch == 'c') + schema_user_draw_node(schematics_win, nodes, mosfets, pos); return (0); }