Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Body Graph UI #57222

Merged
merged 15 commits into from
Apr 29, 2022
Merged

Body Graph UI #57222

merged 15 commits into from
Apr 29, 2022

Conversation

dseguin
Copy link
Member

@dseguin dseguin commented Apr 28, 2022

Summary

None

Alternative summary: "Data driven body graphs"

Purpose of change

I really wanted to create some infrastructure for creating cool interactive body diagrams in ascii art. This includes a new UI for viewing body part status info.

Describe the solution

2022-04-28.04-16-57.mp4

JSON data

I've added a new JSON data type "body_graph":

 {
    "type": "body_graph",
    "id": "torso",
    "parent_bodypart": "torso",
    "fill_sym": "#",
    "fill_color": "white",
    "rows": [
      "                                        ",
      "          22222                22222    ",
      "         2222222                22222   ",
      "    11111122222111111          22###55  ",
      "  ###111111111111111###       44#####55 ",
      " ####111111111111111####     44######55 ",
      "     111111111111111         44######55 ",
      "      1111111111111          44######55 ",
      "      1111111111111           44####55  ",
      "      1111111111111           44####55  ",
      "      1133333333311           44####55  ",
      "      6333333333336           44666655  ",
      "      6333333333336           46666665  ",
      "     663333333333366          66666666  ",
      "     666333333333666          6666666## ",
      "    ######33333######        ########## ",
      "    ########3########        ########## ",
      "    ######## ########        #########  ",
      "    #######   #######         #######   ",
      "                                        "
    ],
    "parts": {
      "1": { "sub_body_parts": [ "torso_upper" ], "select_color": "red" },
      "2": { "sub_body_parts": [ "torso_neck" ], "select_color": "red" },
      "3": { "sub_body_parts": [ "torso_lower" ], "select_color": "red" },
      "4": { "sub_body_parts": [ "torso_hanging_front" ], "select_color": "red" },
      "5": { "sub_body_parts": [ "torso_hanging_back" ], "select_color": "red" },
      "6": { "sub_body_parts": [ "torso_waist" ], "select_color": "red" }
    }
  }

Each entry in "parts" can also define a "nested_graph" field which points to another body_graph, so when the player selects that part they are taken to the nested graph.

See the updated documentation for more details about these fields.


Body Graph UI

I created a new UI accessible from the @ menu (uses the s hotkey by default):

hand_graph

This UI shows the player's body in graph form using the body_graph objects. Each main body part has a nested graph that leads to a detailed view of its sub parts.

Currently the UI is used to show equipment stats for that body part in the right pane. (The right info pane was only possible thanks to @bombasticSlacks!)


Describe alternatives you've considered

Stay in the past, with boring text.

Testing

See video and screenshots.

Additional context

TODO:

@github-actions github-actions bot added [C++] Changes (can be) made in C++. Previously named `Code` [JSON] Changes (can be) made in JSON json-styled JSON lint passed, label assigned by github actions astyled astyled PR, label is assigned by github actions BasicBuildPassed This PR builds correctly, label assigned by github actions labels Apr 28, 2022
src/bodygraph.cpp Outdated Show resolved Hide resolved
src/bodygraph.cpp Outdated Show resolved Hide resolved
@bombasticSlacks
Copy link
Contributor

For body parts (not sub parts) the protection values are an average. Might be a decent idea to add "average" just for them.

@andrei8l
Copy link
Contributor

You can mirror the ASCII art at runtime instead of re-drawing it in JSON

quick and dirty deferred POC
diff --git a/data/json/bodypart_graphs/arms.json b/data/json/bodypart_graphs/arms.json
index 25fab8d52e..f0067f8415 100644
--- a/data/json/bodypart_graphs/arms.json
+++ b/data/json/bodypart_graphs/arms.json
@@ -5,28 +5,7 @@
     "parent_bodypart": "arm_r",
     "fill_sym": "#",
     "fill_color": "white",
-    "rows": [
-      "                                        ",
-      "                                 11111  ",
-      "                              11111111  ",
-      "                             111111111  ",
-      "                             111111111  ",
-      "                             211111111  ",
-      "                            2222221111  ",
-      "                            2222222211  ",
-      "    444                    2222222222   ",
-      "   444444                 2222222222    ",
-      "    444444444            22222222222    ",
-      "       444444444444     22222222222     ",
-      "         4444444444444422222222222      ",
-      "            444444444442222222222       ",
-      "              444444443333322222        ",
-      "                  444333333322          ",
-      "                     3333333            ",
-      "                        33              ",
-      "                                        ",
-      "                                        "
-    ],
+    "mirror" : "arm_l",
     "parts": {
       "1": { "sub_body_parts": [ "arm_shoulder_r" ], "select_color": "red" },
       "2": { "sub_body_parts": [ "arm_upper_r" ], "select_color": "red" },
diff --git a/src/bodygraph.cpp b/src/bodygraph.cpp
index af9763f90f..462b5bbb11 100644
--- a/src/bodygraph.cpp
+++ b/src/bodygraph.cpp
@@ -80,6 +80,8 @@ void bodygraph::load( const JsonObject &jo, const std::string & )
                 rows.emplace_back( row );
             }
         }
+    } else if( !was_loaded || jo.has_string( "mirror" ) ) {
+        mirror = jo.get_string( "mirror" );
     }
 
     if( !was_loaded || jo.has_object( "parts" ) ) {
@@ -344,6 +346,15 @@ void bodygraph_display::draw_graph()
 {
     werase( w_graph );
     const bodygraph_part *selected_graph = std::get<2>( partlist[sel_part] );
+
+    auto const &all = bodygraph_full_body->get_all();
+    bool const mirror = !id->mirror.empty();
+    auto const it =
+        !mirror ? all.cend()
+                : std::find_if( all.cbegin(), all.cend(), [&]( decltype( *all.cbegin() ) &el ) {
+                      return el.id->id.str() == id->mirror;
+                  } );
+
     std::string selected_sym;
     if( !!selected_graph ) {
         for( const auto &bgp : id->parts ) {
@@ -352,22 +363,27 @@ void bodygraph_display::draw_graph()
             }
         }
     }
-    for( unsigned i = 0; i < id->rows.size() && i < BPGRAPH_MAXROWS; i++ ) {
-        for( unsigned j = 0; j < id->rows[i].size() && j < BPGRAPH_MAXCOLS; j++ ) {
+    decltype( id->rows ) const &rows = mirror ? it->id->rows : id->rows;
+    int i = 0;
+    for( auto const &row : rows ) {
+        int x = mirror ? row.size() - 1 : 0;
+        for( auto const &col : row ) {
             std::string sym = id->fill_sym;
-            nc_color col = id->fill_color;
-            auto iter = id->parts.find( id->rows[i][j] );
+            nc_color color = id->fill_color;
+            auto  iter = id->parts.find( col );
             if( iter != id->parts.end() ) {
                 sym = iter->second.sym;
             }
-            if( id->rows[i][j] == " " ) {
-                col = c_unset;
+            if( col == " " ) {
+                color = c_unset;
                 sym = " ";
-            } else if( id->rows[i][j] == selected_sym ) {
-                col = id->parts.at( selected_sym ).sel_color;
+            } else if( col == selected_sym ) {
+                color = id->parts.at( selected_sym ).sel_color;
             }
-            mvwputch( w_graph, point( j, i ), col, sym );
+            mvwputch( w_graph, point( x, i ), color, sym );
+            x = mirror ? x - 1 : x + 1;
         }
+        i++;
     }
     wnoutrefresh( w_graph );
 }

Many other transformations can be done the same way.

src/bodygraph.cpp Outdated Show resolved Hide resolved
src/bodygraph.cpp Outdated Show resolved Hide resolved
src/bodygraph.cpp Outdated Show resolved Hide resolved
@Shodan14
Copy link

Going to be really fun drawing all the mutant parts.

@Theawesomeboophis
Copy link
Contributor

This is absolutely incredible, can't wait for this, love the ascii art.

src/bodygraph.cpp Outdated Show resolved Hide resolved
@github-actions github-actions bot added <Documentation> Design documents, internal info, guides and help. [Markdown] Markdown issues and PRs [Python] Code made in Python Translation I18n labels Apr 28, 2022
@dseguin dseguin added <Enhancement / Feature> New features, or enhancements on existing Info / User Interface Game - player communication, menus, etc. Mechanics: Character / Player Character / Player mechanics labels Apr 28, 2022
@github-actions

This comment was marked as resolved.

@dseguin dseguin marked this pull request as ready for review April 29, 2022 01:11
src/bodygraph.cpp Outdated Show resolved Hide resolved
dseguin and others added 11 commits April 29, 2022 02:07
Co-authored-by: andrei <68240139+andrei8l@users.noreply.github.com>
Co-authored-by: Dillon Matchett <dillon.matchett@gmail.com>
Co-authored-by: Binrui Dong <brett.browning.dong@gmail.com>
This implementation is simpler, but achieves the same goal.

Co-authored-by: andrei <68240139+andrei8l@users.noreply.github.com>
Co-authored-by: Qrox <qrox@sina.com>
Co-authored-by: Qrox <qrox@sina.com>
Co-authored-by: andrei <68240139+andrei8l@users.noreply.github.com>
@BrettDong BrettDong requested review from BrettDong and removed request for BrettDong April 29, 2022 07:12
@Shodan14
Copy link

Hopefully this will eventually be how wounds are shown as well.

@I-am-Erk I-am-Erk merged commit e874d48 into CleverRaven:master Apr 29, 2022
@dseguin dseguin deleted the bodygraph branch April 29, 2022 17:51
@perryprog
Copy link
Contributor

I'm wondering if there should be a merger (or at least unification) between this and the medical menu introduced in #54763 due to a fair bit of overlap between the two; in my opinion, it doesn't really make sense to keep this as two separate displays. (Reasons against merging them could be just down to personally preference on wanting / not wanting a large ascii art diagram for whatever a player is currently doing.)

I also wonder if the ascii art should be hidden or represented in text based on if ENABLE_ASCII_ART is set.

@I-am-Erk
Copy link
Member

Almost certainly the two will be integrated, but it might wait until after the wounds overhaul in 0.H-experimental.

@dseguin dseguin mentioned this pull request Apr 30, 2022
8 tasks
Drew4484 pushed a commit to Drew4484/Cataclysm-DDA that referenced this pull request May 1, 2022
* Body Graph: new jsonized body_graph objects

* Body Graph: basic UI functionality + full body and head graphs

* Body Graph: torso graph

* Body Graph: arm graphs

* Body Graph: hand graphs

* Body Graph: leg graphs

* Body Graph: foot graphs

* info construction works

* Body Graph: display armor data in right pane

* Body Graph: apply suggestions from code review

Co-authored-by: andrei <68240139+andrei8l@users.noreply.github.com>
Co-authored-by: Dillon Matchett <dillon.matchett@gmail.com>
Co-authored-by: Binrui Dong <brett.browning.dong@gmail.com>

* Body Graph: mirror opposite graphs as suggested by andrei8l

This implementation is simpler, but achieves the same goal.

Co-authored-by: andrei <68240139+andrei8l@users.noreply.github.com>

* Body Graph: extract strings and update documentation

* Body Graph: use border_helper to draw window borders

Co-authored-by: Qrox <qrox@sina.com>

* Body Graph: only init windows from resize call

Co-authored-by: Qrox <qrox@sina.com>

* Body Graph: apply suggestions from code review

Co-authored-by: andrei <68240139+andrei8l@users.noreply.github.com>

Co-authored-by: bombasticSlacks <dillon.matchett@gmail.com>
Co-authored-by: andrei <68240139+andrei8l@users.noreply.github.com>
Co-authored-by: Binrui Dong <brett.browning.dong@gmail.com>
Co-authored-by: Qrox <qrox@sina.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
astyled astyled PR, label is assigned by github actions BasicBuildPassed This PR builds correctly, label assigned by github actions [C++] Changes (can be) made in C++. Previously named `Code` <Documentation> Design documents, internal info, guides and help. <Enhancement / Feature> New features, or enhancements on existing Info / User Interface Game - player communication, menus, etc. [JSON] Changes (can be) made in JSON json-styled JSON lint passed, label assigned by github actions [Markdown] Markdown issues and PRs Mechanics: Character / Player Character / Player mechanics [Python] Code made in Python Translation I18n
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants