38 #include <QPainterPath>
119 const QPixmap *sprite;
123 *width = *height = 2;
129 *width = rect.width() + 8;
130 *height = rect.height() + 8;
143 max_icon_height = std::max(max_icon_height, sprite->height());
144 icons_width_sum += sprite->width() + 2;
153 if (VUT_ADVANCE == preq->source.kind
158 max_icon_height =
MAX(max_icon_height, sprite->height());
159 icons_width_sum += sprite->width() + 2;
171 if (VUT_ADVANCE == preq->source.kind
174 max_icon_height =
MAX(max_icon_height, sprite->height());
175 icons_width_sum += sprite->width() + 2;
182 *height += max_icon_height;
183 if (*width < icons_width_sum) {
184 *width = icons_width_sum;
207 for (j = 0; j < node->
nrequire; j++) {
231 if (i < tree->layer_size[
layer] - 1) {
251 int i,
layer, layer_offs;
272 if (i < tree->layer_size[
layer] - 1) {
297 node->
node_x = layer_offs;
302 layer_offs += max_width * 5 / 4 + 80;
304 layer_offs += max_width + 10;
353 std::vector<struct tree_node *>
nodes;
360 nodes[tech] =
nullptr;
363 if (pplayer && !show_all
367 nodes[tech] =
nullptr;
384 if (nodes[tech] ==
nullptr) {
391 if (!show_all &&
A_NONE != tech_one &&
A_LAST != tech_two
393 && (nodes[tech_one] ==
nullptr || nodes[tech_two] ==
nullptr)) {
420 tree->
nodes[j++] = nodes[tech];
440 delete tree->
nodes[i];
442 delete[] tree->
nodes;
462 if (node->
layer != -1) {
466 for (i = 0; i < node->
nrequire; i++) {
469 node->
layer = max + 1;
481 if (tree->
nodes[i]) {
493 int max = node->
layer;
495 for (i = 0; i < node->
nprovide; i++) {
510 int num_dummy_nodes = 0;
517 if (tree->
nodes[i] ==
nullptr) {
522 num_dummy_nodes += mpl - tree->
nodes[i]->
layer - 1;
541 for (i = 0; i < num_dummy_nodes; i++) {
557 if (mpl > node->
layer + 1) {
559 for (j = node->
layer + 2; j < mpl; j++) {
563 for (j = node->
layer + 1; j < mpl; j++) {
569 for (j = 0; j < node->
nprovide; j++) {
572 if (provide_y == node->
layer + 1) {
579 new_tree->
nodes[k + provide_y - node->
layer - 2]);
583 if (mpl > node->
layer + 1) {
584 k += mpl - node->
layer - 1;
588 new_tree->
layers =
nullptr;
613 T.resize(num_layers);
617 for (i = 0; i < num_layers; i++) {
625 for (i = 0; i < num_layers; i++) {
657 std::vector<struct node_and_float> T;
668 for (j = 0; j < node->
nrequire; j++) {
672 v /=
static_cast<float>(node->
nrequire);
676 std::sort(T.begin(), T.end(),
cmp_func);
680 T[i].node->
order = i;
692 X.resize(layer2_size);
696 for (i = 0; i < layer2_size; i++) {
700 for (i = 0; i < layer1_size; i++) {
703 for (j = 0; j < node->
nprovide; j++) {
706 for (j = 0; j < node->
nprovide; j++) {
726 node1->
order = order2;
727 node2->
order = order1;
736 std::vector<int> crossings;
738 int i, x1, x2,
layer;
749 layer_sum += crossings[
layer - 1];
751 if (layer < tree->num_layers - 1) {
752 layer_sum += crossings[
layer];
755 for (x1 = 0; x1 < layer_size; x1++) {
756 for (x2 = x1 + 1; x2 < layer_size; x2++) {
757 int new_crossings = 0;
758 int new_crossings_before = 0;
764 if (layer < tree->num_layers - 1) {
767 if (new_crossings + new_crossings_before > layer_sum) {
770 layer_sum = new_crossings + new_crossings_before;
772 crossings[
layer - 1] = new_crossings_before;
774 if (layer < tree->num_layers - 1) {
775 crossings[
layer] = new_crossings;
801 for (j = 0; j < 20; j++) {
808 for (j = 0; j < 20; j++) {
865 if (TECH_PREREQS_KNOWN
873 if (TECH_PREREQS_KNOWN
880 return Qt::transparent;
893 if (dest_node ==
nullptr) {
911 for (i = 0; i < dest_node->
nprovide; ++i) {
985 QPixmap *pcanvas,
int canvas_x,
986 int canvas_y,
int tt_x,
int tt_y,
996 const QPixmap *sprite;
999 QList<req_tooltip_help *> *tt_help =
new QList<req_tooltip_help *>;
1000 QPainter p(pcanvas);
1002 p.setRenderHint(QPainter::Antialiasing);
1004 auto fm = p.fontMetrics();
1010 int startx, starty, endx, endy, width, height;
1019 p.setPen(QPen(
edge_color(node,
nullptr), 2));
1020 p.drawLine(startx, starty, startx + width, starty);
1029 p.drawRect(startx, starty, width - 2, height - 2);
1030 p.setBrush(Qt::NoBrush);
1036 auto rect = fm.boundingRect(text);
1037 text_w = rect.width();
1038 text_h = rect.height();
1042 QRect(startx + (width - text_w) / 2, starty + 4, text_w, text_h);
1044 tt_help->append(rttp);
1047 p.drawText(startx + (width - text_w) / 2 - rect.left(),
1048 starty + 4 + fm.ascent(), text);
1050 icon_startx = startx + 5;
1064 + (height - text_h - 4 - sprite->height()) / 2,
1065 sprite->width(), sprite->height());
1067 tt_help->append(rttp);
1068 p.drawPixmap(icon_startx,
1070 + (height - text_h - 4 - sprite->height()) / 2,
1072 icon_startx += sprite->width() + 2;
1080 if (VUT_ADVANCE == preq->source.kind
1090 + (height - text_h - 4 - sprite->height()) / 2,
1091 sprite->width(), sprite->height());
1092 rttp->
timpr = pimprove;
1093 tt_help->append(rttp);
1094 p.drawPixmap(icon_startx,
1096 + (height - text_h - 4 - sprite->height())
1099 icon_startx += sprite->width() + 2;
1110 if (VUT_ADVANCE == preq->source.kind
1118 + (height - text_h - 4 - sprite->height()) / 2,
1119 sprite->width(), sprite->height());
1121 tt_help->append(rttp);
1122 p.drawPixmap(icon_startx,
1124 + (height - text_h - 4 - sprite->height())
1127 icon_startx += sprite->width() + 2;
1139 for (k = 0; k < node->
nprovide; k++) {
1141 p.setPen(QPen(
edge_color(node, dest_node), 2));
1143 endx = dest_node->
node_x;
1149 path.moveTo(startx, starty);
1150 path.cubicTo((startx + endx) / 2., starty, startx,
1151 (starty + endy) / 2., endx, endy);
1154 p.drawLine(startx, starty, endx, endy);
1196 for (
int i = 0; i < tree->
num_nodes; i++) {
QFont get_font(client_font font)
Returns given font.
struct player * client_player()
Either controlling or observing.
QColor get_color(const struct tileset *t, enum color_std stdcolor)
Return a pointer to the given "standard" color.
QColor get_diag_color(color_std color)
Gets a diagram color.
std::vector< government > governments
#define improvement_iterate_end
#define improvement_iterate(_p)
#define fc_assert_ret(condition)
#define fc_assert(condition)
#define fc_assert_action(condition, action)
client_options * gui_options
#define requirement_vector_iterate_end
#define requirement_vector_iterate(req_vec, preq)
bool research_invention_reachable(const struct research *presearch, const Tech_type_id tech)
Returns TRUE iff the given tech is ever reachable via research by the players sharing the research by...
bool research_goal_tech_req(const struct research *presearch, Tech_type_id goal, Tech_type_id tech)
Returns if the given tech has to be researched to reach the goal.
struct research * research_get(const struct player *pplayer)
Returns the research structure associated with the player.
QString research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Store the translated name of the given tech (including A_FUTURE) in 'buf'.
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Returns state of the tech for current research.
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Returns TRUE iff the given tech can be given to the players sharing the research immediately.
bool reqtree_curved_lines
struct tree_node ** nodes
struct tree_node *** layers
struct tree_node ** provide
struct tree_node ** require
#define fc_realloc(ptr, sz)
Tech_type_id advance_required(const Tech_type_id tech, enum tech_req require)
Accessor for requirements.
struct advance * valid_advance_by_number(const Tech_type_id id)
Returns pointer when the advance "exists" in this game, returns nullptr otherwise.
Tech_type_id advance_count()
Return the number of advances/technologies.
Tech_type_id advance_number(const struct advance *padvance)
Return the advance index.
#define advance_index_iterate_end
#define advance_index_iterate(_start, _index)
const QPixmap * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum direction8 facing, const QColor &replace)
Return the sprite for the unit type (the base "unit" sprite).
const QPixmap * get_government_sprite(const struct tileset *t, const struct government *gov)
Return the sprite for the government.
const QPixmap * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Return the sprite for the building/improvement.
#define unit_type_iterate(_p)
#define unit_type_iterate_end
static QColor node_color(struct tree_node *node)
Return a background color of node's rectangle.
static struct reqtree * add_dummy_nodes(struct reqtree *tree)
Create new tree which has dummy nodes added.
static int max_provide_layer(struct tree_node *node)
Find the largest value of layer amongst children of the given node.
static int longest_path(struct tree_node *node)
Compute the longest path from this tree_node to the node with no requirements.
static void barycentric_sort(struct reqtree *tree, int layer)
Simple heuristic: Sort nodes on the given layer by the average x-value of its' parents.
void get_reqtree_dimensions(struct reqtree *reqtree, int *width, int *height)
Give the dimensions of the reqtree.
static void node_rectangle_minimum_size(struct tree_node *node, int *width, int *height)
Return minimum size of the rectangle in pixels on the diagram which corresponds to the given node.
static void add_requirement(struct tree_node *node, struct tree_node *req)
Add requirement edge to node and provide edge to req.
static struct reqtree * create_dummy_reqtree(struct player *pplayer, bool show_all)
Create a "dummy" tech tree from current ruleset.
static int count_crossings(struct reqtree *tree, int layer)
Calculate number of edge crossings beetwen layer and layer+1.
struct reqtree * create_reqtree(struct player *pplayer, bool show_all)
Generate optimized tech_tree from current ruleset.
static void improve(struct reqtree *tree)
Try to reduce the number of crossings by swapping two nodes and checking if it improves the situation...
static QColor edge_color(struct tree_node *node, struct tree_node *dest_node)
Return a stroke color for an edge between two nodes if node is a dummy, dest_node can be nullptr.
static void symmetrize(struct reqtree *tree)
Move nodes up and down without changing order but making it more symetrical.
static void set_layers(struct reqtree *tree)
Calculate layers[] and layer_size[] fields of tree.
static void longest_path_layering(struct reqtree *tree)
Compute longest_path for all nodes, thus prepare longest path layering.
static void calculate_diagram_layout(struct reqtree *tree)
Calculate rectangles position and size from the tree.
QList< req_tooltip_help * > * draw_reqtree(struct reqtree *tree, QPixmap *pcanvas, int canvas_x, int canvas_y, int tt_x, int tt_y, int w, int h)
Draw the reqtree diagram!
Tech_type_id get_tech_on_reqtree(struct reqtree *tree, int x, int y)
Return the tech ID at the given position of the reqtree (or A_NONE).
static void swap(struct reqtree *tree, int layer, int order1, int order2)
Swap positions of two nodes on the same layer.
static enum reqtree_edge_type get_edge_type(struct tree_node *node, struct tree_node *dest_node)
Return the type for an edge between two nodes if node is a dummy, dest_node can be nullptr.
void destroy_reqtree(struct reqtree *tree)
Free all memory used by tech_tree struct.
static int cmp_func(const node_and_float &a, const node_and_float &b)
Comparison function used by barycentric_sort.
static struct tree_node * new_tree_node()
Allocate and initialize new tree node.
bool get_position_on_reqtree(struct reqtree *tree, Tech_type_id tech, int *x, int *y)
Find the center of a node, identified by tech id in a given reqtree and return true if the node was f...
reqtree_edge_type
Edge types for coloring the edges by type in the tree.