Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
GitCode
Cataclysm DDA
提交
8d30d672
C
Cataclysm DDA
项目概览
GitCode
/
Cataclysm DDA
通知
4
Star
6383
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
Cataclysm DDA
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
8d30d672
编写于
1月 14, 2022
作者:
K
Kevin Granade
提交者:
GitHub
1月 14, 2022
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #54153 from wapcaplet/w-widget-overmap
Add widget for overmap
上级
9a43a658
31b58c30
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
510 addition
and
144 deletion
+510
-144
data/json/ui/overmap.json
data/json/ui/overmap.json
+20
-0
data/json/ui/sidebar.json
data/json/ui/sidebar.json
+2
-0
data/mods/TEST_DATA/widgets.json
data/mods/TEST_DATA/widgets.json
+8
-0
doc/SIDEBAR_MOD.md
doc/SIDEBAR_MOD.md
+3
-0
src/display.cpp
src/display.cpp
+295
-0
src/display.h
src/display.h
+42
-0
src/overmap_ui.cpp
src/overmap_ui.cpp
+3
-6
src/panels.cpp
src/panels.cpp
+29
-135
src/widget.cpp
src/widget.cpp
+25
-3
src/widget.h
src/widget.h
+2
-0
tests/widget_test.cpp
tests/widget_test.cpp
+81
-0
未找到文件。
data/json/ui/overmap.json
0 → 100644
浏览文件 @
8d30d672
[
{
"id"
:
"overmap_full_width"
,
"type"
:
"widget"
,
"label"
:
"Overmap"
,
"var"
:
"overmap_text"
,
"style"
:
"text"
,
"width"
:
0
,
"height"
:
7
,
"flags"
:
[
"W_LABEL_NONE"
]
},
{
"id"
:
"overmap_location_desc"
,
"type"
:
"widget"
,
"label"
:
"Location"
,
"var"
:
"overmap_loc_text"
,
"style"
:
"text"
,
"flags"
:
[
"W_LABEL_NONE"
]
}
]
data/json/ui/sidebar.json
浏览文件 @
8d30d672
...
...
@@ -17,6 +17,8 @@
"compass_all_layout"
,
"weapon_style_layout"
,
"place_date_time_layout"
,
"overmap_full_width"
,
"overmap_location_desc"
,
"light_moon_wind_temp_layout"
,
"vehicle_azimuth_cruise_fuel_layout"
,
"vital_numbers_layout"
,
...
...
data/mods/TEST_DATA/widgets.json
浏览文件 @
8d30d672
...
...
@@ -293,6 +293,14 @@
"bodypart"
:
"arm_l"
,
"style"
:
"text"
},
{
"id"
:
"test_overmap_3x3_text"
,
"type"
:
"widget"
,
"var"
:
"overmap_text"
,
"style"
:
"text"
,
"width"
:
3
,
"height"
:
3
},
{
"id"
:
"test_stat_panel"
,
"type"
:
"widget"
,
...
...
doc/SIDEBAR_MOD.md
浏览文件 @
8d30d672
...
...
@@ -168,6 +168,7 @@ next.
Variable widgets define a "var" field, with the name of a predefined widget variable. This tells the
widget what information it should show. Most of the time, these are attributes of the player
character, but they can also be attributes of the world, environment, or vehicle where they are.
See the
[
Variables
](
#variables
)
section for a list of them.
For example, a widget to show the current STR stat would define this "var":
...
...
@@ -551,6 +552,8 @@ Some vars refer to text descriptors. These must use style "text". Examples:
|
`moon_phase_text`
| Phase of the moon - "New moon", "Waxing gibbous", "Full moon" etc.
|
`move_mode_letter`
| Movement mode - "W": walking, "R": running, "C": crouching, "P": prone
|
`move_mode_text`
| Movement mode - "walking", "running", "crouching", "prone"
|
`overmap_loc_text`
| Overmap coordinates, same as shown in the lower corner of overmap screen
|
`overmap_text`
| Colored text rendering of the local overmap; may define "width" and "height"
|
`pain_text`
| "Mild pain", "Distracting pain", "Intense pain", etc.
|
`place_text`
| Location place name
|
`power_text`
| Bionic power available
...
...
src/display.cpp
浏览文件 @
8d30d672
...
...
@@ -3,6 +3,8 @@
#include "display.h"
#include "game.h"
#include "options.h"
#include "overmap.h"
#include "overmapbuffer.h"
#include "make_static.h"
#include "map.h"
#include "mood_face.h"
...
...
@@ -33,6 +35,15 @@ static const flag_id json_flag_THERMOMETER( "THERMOMETER" );
static
const
itype_id
fuel_type_muscle
(
"muscle"
);
// Cache for the overmap widget string
static
disp_overmap_cache
disp_om_cache
;
disp_overmap_cache
::
disp_overmap_cache
()
{
_center
=
overmap
::
invalid_tripoint
;
_mission
=
overmap
::
invalid_tripoint
;
}
// Get remotely controlled vehicle, or vehicle character is inside of
vehicle
*
display
::
vehicle_driven
(
const
Character
&
u
)
{
...
...
@@ -1078,3 +1089,287 @@ std::pair<std::string, nc_color> display::move_mode_text_color( const Character
return
std
::
make_pair
(
mm_text
,
mm_color
);
}
std
::
pair
<
std
::
string
,
nc_color
>
display
::
overmap_note_symbol_color
(
const
std
::
string
note_text
)
{
std
::
string
ter_sym
=
"N"
;
nc_color
ter_color
=
c_yellow
;
// Parse note text for : (symbol) and ; (color) separators
int
symbolIndex
=
note_text
.
find
(
':'
);
int
colorIndex
=
note_text
.
find
(
';'
);
bool
symbolFirst
=
symbolIndex
<
colorIndex
;
// Both color and symbol
if
(
colorIndex
>
-
1
&&
symbolIndex
>
-
1
)
{
if
(
symbolFirst
)
{
if
(
colorIndex
>
4
)
{
colorIndex
=
-
1
;
}
if
(
symbolIndex
>
1
)
{
symbolIndex
=
-
1
;
colorIndex
=
-
1
;
}
}
else
{
if
(
symbolIndex
>
4
)
{
symbolIndex
=
-
1
;
}
if
(
colorIndex
>
2
)
{
colorIndex
=
-
1
;
}
}
}
else
if
(
colorIndex
>
2
)
{
colorIndex
=
-
1
;
}
else
if
(
symbolIndex
>
1
)
{
symbolIndex
=
-
1
;
}
if
(
symbolIndex
>
-
1
)
{
int
symbolStart
=
0
;
if
(
colorIndex
>
-
1
&&
!
symbolFirst
)
{
symbolStart
=
colorIndex
+
1
;
}
ter_sym
=
note_text
.
substr
(
symbolStart
,
symbolIndex
-
symbolStart
);
}
if
(
colorIndex
>
-
1
)
{
int
colorStart
=
0
;
if
(
symbolIndex
>
-
1
&&
symbolFirst
)
{
colorStart
=
symbolIndex
+
1
;
}
std
::
string
sym
=
note_text
.
substr
(
colorStart
,
colorIndex
-
colorStart
);
if
(
sym
.
length
()
==
2
)
{
if
(
sym
==
"br"
)
{
ter_color
=
c_brown
;
}
else
if
(
sym
==
"lg"
)
{
ter_color
=
c_light_gray
;
}
else
if
(
sym
==
"dg"
)
{
ter_color
=
c_dark_gray
;
}
}
else
{
char
colorID
=
sym
.
c_str
()[
0
];
if
(
colorID
==
'r'
)
{
ter_color
=
c_light_red
;
}
else
if
(
colorID
==
'R'
)
{
ter_color
=
c_red
;
}
else
if
(
colorID
==
'g'
)
{
ter_color
=
c_light_green
;
}
else
if
(
colorID
==
'G'
)
{
ter_color
=
c_green
;
}
else
if
(
colorID
==
'b'
)
{
ter_color
=
c_light_blue
;
}
else
if
(
colorID
==
'B'
)
{
ter_color
=
c_blue
;
}
else
if
(
colorID
==
'W'
)
{
ter_color
=
c_white
;
}
else
if
(
colorID
==
'C'
)
{
ter_color
=
c_cyan
;
}
else
if
(
colorID
==
'c'
)
{
ter_color
=
c_light_cyan
;
}
else
if
(
colorID
==
'P'
)
{
ter_color
=
c_pink
;
}
else
if
(
colorID
==
'm'
)
{
ter_color
=
c_magenta
;
}
}
}
return
std
::
make_pair
(
ter_sym
,
ter_color
);
}
// Return an overmap tile symbol and color for an omt relatively near the avatar's position.
// The edge_tile flag says this omt is at the edge of the map and may point to an off-map mission.
// The found_mi (reference) is set to true to tell the calling function if a mission marker was found.
std
::
pair
<
std
::
string
,
nc_color
>
display
::
overmap_tile_symbol_color
(
const
avatar
&
u
,
const
tripoint_abs_omt
&
omt
,
const
bool
edge_tile
,
bool
&
found_mi
)
{
std
::
string
ter_sym
;
nc_color
ter_color
=
c_light_gray
;
// Terrain color and symbol to use for this point
const
bool
seen
=
overmap_buffer
.
seen
(
omt
);
const
bool
vehicle_here
=
overmap_buffer
.
has_vehicle
(
omt
);
if
(
overmap_buffer
.
has_note
(
omt
)
)
{
const
std
::
string
&
note_text
=
overmap_buffer
.
note
(
omt
);
std
::
pair
<
std
::
string
,
nc_color
>
sym_color
=
display
::
overmap_note_symbol_color
(
note_text
);
ter_sym
=
sym_color
.
first
;
ter_color
=
sym_color
.
second
;
}
else
if
(
!
seen
)
{
// Always grey # for unseen
ter_sym
=
"#"
;
ter_color
=
c_dark_gray
;
}
else
if
(
vehicle_here
)
{
// Always cyan c for vehicle
ter_color
=
c_cyan
;
ter_sym
=
"c"
;
}
else
{
// Otherwise, get symbol and color appropriate for the terrain
const
oter_id
&
cur_ter
=
overmap_buffer
.
ter
(
omt
);
ter_sym
=
cur_ter
->
get_symbol
();
if
(
overmap_buffer
.
is_explored
(
omt
)
)
{
ter_color
=
c_dark_gray
;
}
else
{
ter_color
=
cur_ter
->
get_color
();
}
}
const
tripoint_abs_omt
target
=
u
.
get_active_mission_target
();
const
tripoint_abs_omt
u_loc
=
u
.
global_omt_location
();
// Check if there is a valid mission target, and avatar is not there already
if
(
target
!=
overmap
::
invalid_tripoint
&&
target
.
xy
()
!=
u_loc
.
xy
()
)
{
// highlight it with a red background (if on-map)
// or point towards it with a red asterisk (if off-map)
if
(
target
.
xy
()
==
omt
.
xy
()
)
{
ter_color
=
red_background
(
ter_color
);
found_mi
=
true
;
}
else
if
(
edge_tile
)
{
std
::
vector
<
tripoint_abs_omt
>
plist
=
line_to
(
u_loc
,
target
);
if
(
std
::
find
(
plist
.
begin
(),
plist
.
end
(),
omt
)
!=
plist
.
end
()
)
{
ter_color
=
c_red
;
ter_sym
=
"*"
;
found_mi
=
true
;
}
}
}
// Show hordes on minimap, leaving a one-tile space around the player
if
(
std
::
abs
(
u_loc
.
x
()
-
omt
.
x
()
)
>
1
||
std
::
abs
(
u_loc
.
y
()
-
omt
.
y
()
)
>
1
)
{
const
int
horde_size
=
overmap_buffer
.
get_horde_size
(
omt
);
const
int
sight_points
=
u
.
overmap_sight_range
(
g
->
light_level
(
u
.
posz
()
)
);
if
(
horde_size
>=
HORDE_VISIBILITY_SIZE
&&
overmap_buffer
.
seen
(
omt
)
&&
u
.
overmap_los
(
omt
,
sight_points
)
)
{
// Draw green Z or z
ter_sym
=
horde_size
>
HORDE_VISIBILITY_SIZE
*
2
?
'Z'
:
'z'
;
ter_color
=
c_green
;
}
}
return
std
::
make_pair
(
ter_sym
,
ter_color
);
}
std
::
string
display
::
colorized_overmap_text
(
const
avatar
&
u
,
const
int
width
,
const
int
height
)
{
std
::
string
overmap_text
;
map
&
here
=
get_map
();
// Map is roughly centered around this point
const
tripoint_abs_omt
&
center_xyz
=
u
.
global_omt_location
();
const
tripoint_abs_omt
&
mission_xyz
=
u
.
get_active_mission_target
();
// Retrieve cached string instead of constantly rebuilding it
if
(
disp_om_cache
.
is_valid_for
(
center_xyz
,
mission_xyz
)
)
{
return
disp_om_cache
.
get_val
();
}
// Remember when mission indicator is found, so we don't draw it more than once
bool
found_mi
=
false
;
// Figure out extents of the map area, so we know where the edges are
const
int
left
=
-
(
width
/
2
);
const
int
right
=
width
+
left
-
1
;
const
int
top
=
-
(
height
/
2
);
const
int
bottom
=
height
+
top
-
1
;
// Scan each row of overmap tiles
for
(
int
row
=
top
;
row
<=
bottom
;
row
++
)
{
// Scan across the width of the row
for
(
int
col
=
left
;
col
<=
right
;
col
++
)
{
// Is this point along the border of the overmap text area we have to work wth?
// If so, overmap_tile_symbol_color may draw a mission indicator at this point.
const
bool
edge
=
!
found_mi
&&
!
(
mission_xyz
.
x
()
>=
center_xyz
.
x
()
+
left
&&
mission_xyz
.
x
()
<=
center_xyz
.
x
()
+
right
&&
mission_xyz
.
y
()
>=
center_xyz
.
y
()
+
top
&&
mission_xyz
.
y
()
<=
center_xyz
.
y
()
+
bottom
)
&&
(
row
==
top
||
row
==
bottom
||
col
==
left
||
col
==
right
);
// Get colorized symbol for this point
const
tripoint_abs_omt
omt
(
center_xyz
.
xy
()
+
point
(
col
,
row
),
here
.
get_abs_sub
().
z
);
std
::
pair
<
std
::
string
,
nc_color
>
sym_color
=
display
::
overmap_tile_symbol_color
(
u
,
omt
,
edge
,
found_mi
);
// Highlight player character location in the center
if
(
row
==
0
&&
col
==
0
)
{
sym_color
.
second
=
hilite
(
sym_color
.
second
);
}
// Append the colorized symbol for this point to the map
overmap_text
+=
colorize
(
sym_color
.
first
,
sym_color
.
second
);
}
overmap_text
+=
"
\n
"
;
}
// Rebuild the cache so we can reuse it if nothing changes
disp_om_cache
.
rebuild
(
center_xyz
,
mission_xyz
,
overmap_text
);
return
overmap_text
;
}
std
::
string
display
::
overmap_position_text
(
const
tripoint_abs_omt
&
loc
)
{
point_abs_omt
abs_omt
=
loc
.
xy
();
point_abs_om
om
;
point_om_omt
omt
;
std
::
tie
(
om
,
omt
)
=
project_remain
<
coords
::
om
>
(
abs_omt
);
return
string_format
(
_
(
"LEVEL %i, %d'%d, %d'%d"
),
loc
.
z
(),
om
.
x
(),
omt
.
x
(),
om
.
y
(),
omt
.
y
()
);
}
// Return (x, y) position of mission target, relative to avatar location, within an overmap of the
// given width and height.
point
display
::
mission_arrow_offset
(
const
avatar
&
you
,
int
width
,
int
height
)
{
// FIXME: Use tripoint for curs
const
point_abs_omt
curs
=
you
.
global_omt_location
().
xy
();
const
tripoint_abs_omt
targ
=
you
.
get_active_mission_target
();
const
point
mid
(
width
/
2
,
height
/
2
);
// If x-coordinates are the same, mission is either due north or due south
// Use an extreme slope rather than dividing by zero
double
slope
=
curs
.
x
()
==
targ
.
x
()
?
1000
:
static_cast
<
double
>
(
targ
.
y
()
-
curs
.
y
()
)
/
(
targ
.
x
()
-
curs
.
x
()
);
if
(
std
::
fabs
(
slope
)
>
12
)
{
// For any near-vertical slope, center the marker
if
(
targ
.
y
()
>
curs
.
y
()
)
{
// Target is due south
return
point
(
mid
.
x
,
height
-
1
);
//mvwputch( w_minimap, point( mid.x + start_x, height - 1 + start_y ), c_red, '*' );
}
else
if
(
targ
.
y
()
<
curs
.
y
()
)
{
// Target is due north
return
point
(
mid
.
x
,
1
);
//mvwputch( w_minimap, point( mid.x + start_x, 1 + start_y ), c_red, '*' );
}
else
{
// Target is right here
return
mid
;
}
}
else
{
// For non-vertical slope, calculate where it intersects the edge of the map
point
arrow
(
point_north_west
);
if
(
std
::
fabs
(
slope
)
>=
1.
)
{
// If target to the north or south, arrow on top or bottom edge of minimap
if
(
targ
.
y
()
>
curs
.
y
()
)
{
arrow
.
x
=
static_cast
<
int
>
(
(
1.
+
(
1.
/
slope
)
)
*
mid
.
x
);
arrow
.
y
=
height
-
1
;
}
else
{
arrow
.
x
=
static_cast
<
int
>
(
(
1.
-
(
1.
/
slope
)
)
*
mid
.
x
);
arrow
.
y
=
0
;
}
// Clip to left/right edges
arrow
.
x
=
std
::
max
(
arrow
.
x
,
0
);
arrow
.
x
=
std
::
min
(
arrow
.
x
,
width
-
1
);
}
else
{
// If target to the east or west, arrow on left or right edge of minimap
if
(
targ
.
x
()
>
curs
.
x
()
)
{
arrow
.
x
=
width
-
1
;
arrow
.
y
=
static_cast
<
int
>
(
(
1.
+
slope
)
*
mid
.
y
);
}
else
{
arrow
.
x
=
0
;
arrow
.
y
=
static_cast
<
int
>
(
(
1.
-
slope
)
*
mid
.
y
);
}
// Clip to top/bottom edges
arrow
.
y
=
std
::
max
(
arrow
.
y
,
0
);
arrow
.
y
=
std
::
min
(
arrow
.
y
,
height
-
1
);
}
return
arrow
;
//mvwputch( w_minimap, arrow + point( start_x, start_y ), c_red, glyph );
}
}
src/display.h
浏览文件 @
8d30d672
...
...
@@ -9,6 +9,36 @@
class
avatar
;
class
Character
;
struct
disp_overmap_cache
{
private:
tripoint_abs_omt
_center
;
tripoint_abs_omt
_mission
;
std
::
string
_om_wgt_str
;
public:
disp_overmap_cache
();
// Returns true if the stored overmap string can be used with the given
// center (player) position and mission target.
bool
is_valid_for
(
const
tripoint_abs_omt
&
center
,
const
tripoint_abs_omt
&
mission
)
const
{
return
_center
==
center
&&
_mission
==
mission
;
}
// Rebuild the cache using the validation parameters "center" and "mission"
// and store the associated widget string.
void
rebuild
(
const
tripoint_abs_omt
&
center
,
const
tripoint_abs_omt
&
mission
,
const
std
::
string
&
om_wgt_str
)
{
_center
=
center
;
_mission
=
mission
;
_om_wgt_str
=
om_wgt_str
;
}
// Retreive the cached widget string
const
std
::
string
&
get_val
()
const
{
return
_om_wgt_str
;
}
};
// The display namespace contains UI string output and colorization functions
// Some return plain strings or translations, some return a (string, color) pair,
// and some return a string with colorization tags embedded.
...
...
@@ -107,6 +137,18 @@ nc_color rad_badge_color( const int rad );
// Highlighted badge color for character's radiation badge, if they have one
std
::
pair
<
std
::
string
,
nc_color
>
rad_badge_text_color
(
const
Character
&
u
);
// Colorized symbol for the overmap tile at the given location
std
::
pair
<
std
::
string
,
nc_color
>
overmap_tile_symbol_color
(
const
avatar
&
u
,
const
tripoint_abs_omt
&
omt
,
const
bool
edge_tile
,
bool
&
found_mi
);
// Colorized symbol for an overmap note, given its full text
std
::
pair
<
std
::
string
,
nc_color
>
overmap_note_symbol_color
(
const
std
::
string
note_text
);
// Mission marker position as an offset within an overmap of given width and height
point
mission_arrow_offset
(
const
avatar
&
you
,
int
width
,
int
height
);
// Fully colorized newline-separated overmap string of the given size, centered on character
std
::
string
colorized_overmap_text
(
const
avatar
&
u
,
const
int
width
,
const
int
height
);
// Current overmap position (coordinates)
std
::
string
overmap_position_text
(
const
tripoint_abs_omt
&
loc
);
// Functions returning colorized string
// gets the string that describes your weight
std
::
string
weight_string
(
const
Character
&
u
);
...
...
src/overmap_ui.cpp
浏览文件 @
8d30d672
...
...
@@ -38,6 +38,7 @@
#include "cuboid_rectangle.h"
#include "cursesdef.h"
#include "cursesport.h"
#include "display.h"
#include "enums.h"
#include "game.h"
#include "game_constants.h"
...
...
@@ -1178,12 +1179,8 @@ static void draw_om_sidebar(
print_hint
(
"QUIT"
);
}
point_abs_omt
abs_omt
=
center
.
xy
();
point_abs_om
om
;
point_om_omt
omt
;
std
::
tie
(
om
,
omt
)
=
project_remain
<
coords
::
om
>
(
abs_omt
);
mvwprintz
(
wbar
,
point
(
1
,
getmaxy
(
wbar
)
-
1
),
c_red
,
_
(
"LEVEL %i, %d'%d, %d'%d"
),
center
.
z
(),
om
.
x
(),
omt
.
x
(),
om
.
y
(),
omt
.
y
()
);
const
std
::
string
coords
=
display
::
overmap_position_text
(
center
);
mvwprintz
(
wbar
,
point
(
1
,
getmaxy
(
wbar
)
-
1
),
c_red
,
coords
);
wnoutrefresh
(
wbar
);
}
...
...
src/panels.cpp
浏览文件 @
8d30d672
...
...
@@ -177,6 +177,7 @@ void overmap_ui::draw_overmap_chunk( const catacurses::window &w_minimap, const
const
tripoint_abs_omt
&
global_omt
,
const
point
&
start_input
,
const
int
width
,
const
int
height
)
{
// Map is centered on curs - typically player's global_omt_location
const
point_abs_omt
curs
=
global_omt
.
xy
();
const
tripoint_abs_omt
targ
=
you
.
get_active_mission_target
();
bool
drew_mission
=
targ
==
overmap
::
invalid_tripoint
;
...
...
@@ -186,108 +187,39 @@ void overmap_ui::draw_overmap_chunk( const catacurses::window &w_minimap, const
map
&
here
=
get_map
();
const
int
sight_points
=
you
.
overmap_sight_range
(
g
->
light_level
(
you
.
posz
()
)
);
// i scans across width, with 0 in the middle(ish)
// -(w/2) ... w-(w/2)-1
// w:9 -4 ... 4
// w:10 -5 ... 4
// w:11 -5 ... 5
// w:12 -6 ... 5
// w:13 -6 ... 6
for
(
int
i
=
-
(
width
/
2
);
i
<=
width
-
(
width
/
2
)
-
1
;
i
++
)
{
// j scans across height, with 0 in the middle(ish)
// (same algorithm)
for
(
int
j
=
-
(
height
/
2
);
j
<=
height
-
(
height
/
2
)
-
1
;
j
++
)
{
// omp is the current overmap point, at the current z-level
const
tripoint_abs_omt
omp
(
curs
+
point
(
i
,
j
),
here
.
get_abs_sub
().
z
);
// Terrain color and symbol to use for this point
nc_color
ter_color
;
std
::
string
ter_sym
;
const
bool
seen
=
overmap_buffer
.
seen
(
omp
);
const
bool
vehicle_here
=
overmap_buffer
.
has_vehicle
(
omp
);
if
(
overmap_buffer
.
has_note
(
omp
)
)
{
const
std
::
string
&
note_text
=
overmap_buffer
.
note
(
omp
);
ter_color
=
c_yellow
;
ter_sym
=
"N"
;
int
symbolIndex
=
note_text
.
find
(
':'
);
int
colorIndex
=
note_text
.
find
(
';'
);
bool
symbolFirst
=
symbolIndex
<
colorIndex
;
if
(
colorIndex
>
-
1
&&
symbolIndex
>
-
1
)
{
if
(
symbolFirst
)
{
if
(
colorIndex
>
4
)
{
colorIndex
=
-
1
;
}
if
(
symbolIndex
>
1
)
{
symbolIndex
=
-
1
;
colorIndex
=
-
1
;
}
}
else
{
if
(
symbolIndex
>
4
)
{
symbolIndex
=
-
1
;
}
if
(
colorIndex
>
2
)
{
colorIndex
=
-
1
;
}
}
}
else
if
(
colorIndex
>
2
)
{
colorIndex
=
-
1
;
}
else
if
(
symbolIndex
>
1
)
{
symbolIndex
=
-
1
;
}
if
(
symbolIndex
>
-
1
)
{
int
symbolStart
=
0
;
if
(
colorIndex
>
-
1
&&
!
symbolFirst
)
{
symbolStart
=
colorIndex
+
1
;
}
ter_sym
=
note_text
.
substr
(
symbolStart
,
symbolIndex
-
symbolStart
);
}
if
(
colorIndex
>
-
1
)
{
int
colorStart
=
0
;
if
(
symbolIndex
>
-
1
&&
symbolFirst
)
{
colorStart
=
symbolIndex
+
1
;
}
std
::
string
sym
=
note_text
.
substr
(
colorStart
,
colorIndex
-
colorStart
);
if
(
sym
.
length
()
==
2
)
{
if
(
sym
==
"br"
)
{
ter_color
=
c_brown
;
}
else
if
(
sym
==
"lg"
)
{
ter_color
=
c_light_gray
;
}
else
if
(
sym
==
"dg"
)
{
ter_color
=
c_dark_gray
;
}
}
else
{
char
colorID
=
sym
.
c_str
()[
0
];
if
(
colorID
==
'r'
)
{
ter_color
=
c_light_red
;
}
else
if
(
colorID
==
'R'
)
{
ter_color
=
c_red
;
}
else
if
(
colorID
==
'g'
)
{
ter_color
=
c_light_green
;
}
else
if
(
colorID
==
'G'
)
{
ter_color
=
c_green
;
}
else
if
(
colorID
==
'b'
)
{
ter_color
=
c_light_blue
;
}
else
if
(
colorID
==
'B'
)
{
ter_color
=
c_blue
;
}
else
if
(
colorID
==
'W'
)
{
ter_color
=
c_white
;
}
else
if
(
colorID
==
'C'
)
{
ter_color
=
c_cyan
;
}
else
if
(
colorID
==
'c'
)
{
ter_color
=
c_light_cyan
;
}
else
if
(
colorID
==
'P'
)
{
ter_color
=
c_pink
;
}
else
if
(
colorID
==
'm'
)
{
ter_color
=
c_magenta
;
}
}
}
std
::
pair
<
std
::
string
,
nc_color
>
sym_color
=
display
::
overmap_note_symbol_color
(
note_text
);
ter_sym
=
sym_color
.
first
;
ter_color
=
sym_color
.
second
;
}
else
if
(
!
seen
)
{
// Always grey # for unseen
ter_sym
=
"#"
;
ter_color
=
c_dark_gray
;
}
else
if
(
vehicle_here
)
{
// Always cyan c for vehicle
ter_color
=
c_cyan
;
ter_sym
=
"c"
;
}
else
{
// Otherwise, get symbol and color appropriate for the terrain
const
oter_id
&
cur_ter
=
overmap_buffer
.
ter
(
omp
);
ter_sym
=
cur_ter
->
get_symbol
();
if
(
overmap_buffer
.
is_explored
(
omp
)
)
{
...
...
@@ -305,6 +237,7 @@ void overmap_ui::draw_overmap_chunk( const catacurses::window &w_minimap, const
ter_color
=
red_background
(
ter_color
);
}
}
// TODO: Build colorized string instead of writing directly to window
if
(
i
==
0
&&
j
==
0
)
{
// Highlight player character position in center of minimap
mvwputch_hi
(
w_minimap
,
mid
+
point
(
start_x
,
start_y
),
ter_color
,
ter_sym
);
...
...
@@ -325,55 +258,18 @@ void overmap_ui::draw_overmap_chunk( const catacurses::window &w_minimap, const
}
}
// Print arrow to mission if we have one!
// When the mission marker is not visible within the current overmap extents,
// draw an arrow at the edge of the map pointing in the general mission direction.
// TODO: Replace `drew_mission` with a function like `is_mission_on_map`
if
(
!
drew_mission
)
{
// Use an extreme slope rather than dividing by zero
double
slope
=
curs
.
x
()
==
targ
.
x
()
?
1000
:
static_cast
<
double
>
(
targ
.
y
()
-
curs
.
y
()
)
/
(
targ
.
x
()
-
curs
.
x
()
);
if
(
std
::
fabs
(
slope
)
>
12
)
{
// For any near-vertical slope, center the marker
if
(
targ
.
y
()
>
curs
.
y
()
)
{
mvwputch
(
w_minimap
,
point
(
mid
.
x
+
start_x
,
height
-
1
+
start_y
),
c_red
,
'*'
);
}
else
{
mvwputch
(
w_minimap
,
point
(
mid
.
x
+
start_x
,
1
+
start_y
),
c_red
,
'*'
);
}
}
else
{
point
arrow
(
point_north_west
);
if
(
std
::
fabs
(
slope
)
>=
1.
)
{
// If target to the north or south, arrow on top or bottom edge of minimap
if
(
targ
.
y
()
>
curs
.
y
()
)
{
arrow
.
x
=
static_cast
<
int
>
(
(
1.
+
(
1.
/
slope
)
)
*
mid
.
x
);
arrow
.
y
=
height
-
1
;
}
else
{
arrow
.
x
=
static_cast
<
int
>
(
(
1.
-
(
1.
/
slope
)
)
*
mid
.
x
);
arrow
.
y
=
0
;
}
// Clip to left/right edges
arrow
.
x
=
std
::
max
(
arrow
.
x
,
0
);
arrow
.
x
=
std
::
min
(
arrow
.
x
,
width
-
1
);
}
else
{
// If target to the east or west, arrow on left or right edge of minimap
if
(
targ
.
x
()
>
curs
.
x
()
)
{
arrow
.
x
=
width
-
1
;
arrow
.
y
=
static_cast
<
int
>
(
(
1.
+
slope
)
*
mid
.
y
);
}
else
{
arrow
.
x
=
0
;
arrow
.
y
=
static_cast
<
int
>
(
(
1.
-
slope
)
*
mid
.
y
);
}
// Clip to top/bottom edges
arrow
.
y
=
std
::
max
(
arrow
.
y
,
0
);
arrow
.
y
=
std
::
min
(
arrow
.
y
,
height
-
1
);
}
char
glyph
=
'*'
;
if
(
targ
.
z
()
>
you
.
posz
()
)
{
glyph
=
'^'
;
}
else
if
(
targ
.
z
()
<
you
.
posz
()
)
{
glyph
=
'v'
;
}
mvwputch
(
w_minimap
,
arrow
+
point
(
start_x
,
start_y
),
c_red
,
glyph
);
char
glyph
=
'*'
;
if
(
targ
.
z
()
>
you
.
posz
()
)
{
glyph
=
'^'
;
}
else
if
(
targ
.
z
()
<
you
.
posz
()
)
{
glyph
=
'v'
;
}
const
point
arrow
=
display
::
mission_arrow_offset
(
you
,
width
,
height
);
mvwputch
(
w_minimap
,
arrow
+
point
(
start_x
,
start_y
),
c_red
,
glyph
);
}
}
...
...
@@ -2327,8 +2223,6 @@ static std::vector<window_panel> initialize_default_custom_panels( const widget
ret
.
emplace_back
(
window_panel
(
draw_compass_padding_compact
,
"Compass"
,
to_translation
(
"Compass"
),
5
,
width
,
false
)
);
ret
.
emplace_back
(
window_panel
(
draw_overmap
,
"Overmap"
,
to_translation
(
"Overmap"
),
7
,
width
,
false
)
);
return
ret
;
}
...
...
src/widget.cpp
浏览文件 @
8d30d672
...
...
@@ -141,6 +141,10 @@ std::string enum_to_string<widget_var>( widget_var data )
return
"move_mode_text"
;
case
widget_var
::
pain_text
:
return
"pain_text"
;
case
widget_var
::
overmap_loc_text
:
return
"overmap_loc_text"
;
case
widget_var
::
overmap_text
:
return
"overmap_text"
;
case
widget_var
::
place_text
:
return
"place_text"
;
case
widget_var
::
power_text
:
...
...
@@ -484,7 +488,7 @@ window_panel widget::get_window_panel( const int width, const int req_height )
for
(
const
widget_id
&
wid
:
_widgets
)
{
height
+=
wid
->
_height
>
0
?
wid
->
_height
:
1
;
}
}
else
if
(
_style
==
"widget"
)
{
}
else
if
(
_style
==
"widget"
||
_style
==
"text"
)
{
height
=
_height
>
1
?
_height
:
req_height
;
}
// Minimap and log do not have a predetermined height
...
...
@@ -515,6 +519,8 @@ bool widget::uses_text_function()
case
widget_var
::
move_mode_letter
:
case
widget_var
::
move_mode_text
:
case
widget_var
::
pain_text
:
case
widget_var
::
overmap_loc_text
:
case
widget_var
::
overmap_text
:
case
widget_var
::
place_text
:
case
widget_var
::
power_text
:
case
widget_var
::
rad_badge_text
:
...
...
@@ -541,10 +547,15 @@ bool widget::uses_text_function()
std
::
string
widget
::
color_text_function_string
(
const
avatar
&
ava
,
unsigned
int
max_width
)
{
std
::
string
ret
;
bool
apply_color
=
true
;
// Most text variables have both a string and a color.
// The string and color in `desc` will be converted to colorized text with markup.
std
::
pair
<
std
::
string
,
nc_color
>
desc
;
//
Give a default color (some widget_vars do not define one)
//
Set a default color
desc
.
second
=
c_light_gray
;
// By default, colorize the string in desc.first with the color in desc.second.
bool
apply_color
=
true
;
// Some helper display:: functions do their own internal colorization of the string.
// For those, desc.first is the already-colorized string, and apply_color is set to false.
switch
(
_var
)
{
case
widget_var
::
activity_text
:
desc
=
display
::
activity_text_color
(
ava
);
...
...
@@ -589,6 +600,13 @@ std::string widget::color_text_function_string( const avatar &ava, unsigned int
case
widget_var
::
pain_text
:
desc
=
display
::
pain_text_color
(
ava
);
break
;
case
widget_var
::
overmap_loc_text
:
desc
.
first
=
display
::
overmap_position_text
(
ava
.
global_omt_location
()
);
break
;
case
widget_var
::
overmap_text
:
desc
.
first
=
display
::
colorized_overmap_text
(
ava
,
_width
==
0
?
max_width
:
_width
,
_height
);
apply_color
=
false
;
break
;
case
widget_var
::
place_text
:
desc
.
first
=
overmap_buffer
.
ter
(
ava
.
global_omt_location
()
)
->
get_name
();
break
;
...
...
@@ -787,6 +805,10 @@ static std::string append_line( const std::string &line, bool first_row, unsigne
std
::
string
ret
;
// Width used by label, ": " and value, using utf8_width to ignore color tags
unsigned
int
used_width
=
utf8_width
(
line
,
true
);
// utf8_width subtracts 1 for each newline; add it back for multiline widgets
if
(
!
line
.
empty
()
&&
line
.
back
()
==
'\n'
)
{
used_width
+=
1
;
}
if
(
first_row
)
{
const
std
::
string
tlabel
=
label
.
translated
();
// If label is empty or omitted, don't reserve space for it
...
...
src/widget.h
浏览文件 @
8d30d672
...
...
@@ -59,6 +59,8 @@ enum class widget_var : int {
moon_phase_text
,
// Current phase of the moon
move_mode_letter
,
// Movement mode, color letter (W/R/C/P)
move_mode_text
,
// Movement mode, color text (walking/running/crouching/prone)
overmap_loc_text
,
// Local overmap position, pseudo latitude/longitude with Z-level
overmap_text
,
// Local overmap and mission marker, multi-line color string
pain_text
,
// Pain description text, color string
place_text
,
// Place name in world where character is
power_text
,
// Remaining power from bionics, color string
...
...
tests/widget_test.cpp
浏览文件 @
8d30d672
...
...
@@ -2,9 +2,13 @@
#include "game.h"
#include "player_helpers.h"
#include "map.h"
#include "map_helpers.h"
#include "mission.h"
#include "monster.h"
#include "morale.h"
#include "overmap.h"
#include "overmapbuffer.h"
#include "options_helpers.h"
#include "weather.h"
#include "weather_type.h"
...
...
@@ -77,6 +81,7 @@ static const widget_id widget_test_move_cost_num( "test_move_cost_num" );
static
const
widget_id
widget_test_move_mode_letter
(
"test_move_mode_letter"
);
static
const
widget_id
widget_test_move_mode_text
(
"test_move_mode_text"
);
static
const
widget_id
widget_test_move_num
(
"test_move_num"
);
static
const
widget_id
widget_test_overmap_3x3_text
(
"test_overmap_3x3_text"
);
static
const
widget_id
widget_test_per_num
(
"test_per_num"
);
static
const
widget_id
widget_test_pool_graph
(
"test_pool_graph"
);
static
const
widget_id
widget_test_rad_badge_text
(
"test_rad_badge_text"
);
...
...
@@ -946,6 +951,82 @@ TEST_CASE( "widgets showing weather conditions", "[widget][weather]" )
}
}
// Fill a 3x3 overmap area around the avatar with a given overmap terrain
static
void
fill_overmap_area
(
const
avatar
&
ava
,
const
oter_id
&
oter
)
{
const
tripoint_abs_omt
&
ava_pos
=
ava
.
global_omt_location
();
for
(
int
x
=
-
1
;
x
<=
1
;
++
x
)
{
for
(
int
y
=
-
1
;
y
<=
1
;
++
y
)
{
const
tripoint
offset
(
x
,
y
,
0
);
overmap_buffer
.
ter_set
(
ava_pos
+
offset
,
oter
);
overmap_buffer
.
set_seen
(
ava_pos
+
offset
,
true
);
}
}
}
TEST_CASE
(
"multi-line overmap text widget"
,
"[widget][overmap]"
)
{
widget
overmap_w
=
widget_test_overmap_3x3_text
.
obj
();
avatar
&
ava
=
get_avatar
();
mission
msn
;
// Use mission target to invalidate the om cache
msn
.
set_target
(
ava
.
global_omt_location
()
+
tripoint
(
5
,
0
,
0
)
);
clear_avatar
();
clear_map
();
ava
.
on_mission_assignment
(
msn
);
// Mission marker is a red asterisk when it's along the border
const
std
::
string
red_star
=
"<color_c_red>*</color>"
;
SECTION
(
"field"
)
{
const
std
::
string
brown_dot
=
"<color_c_brown>.</color>"
;
const
std
::
string
h_brown_dot
=
"<color_h_brown>.</color>"
;
fill_overmap_area
(
ava
,
oter_id
(
"field"
)
);
// Mission marker to the north of avatar position (y - 2)
msn
.
set_target
(
ava
.
global_omt_location
()
+
tripoint
(
0
,
-
2
,
0
)
);
// (red star in top center of the map)
const
std
::
vector
<
std
::
string
>
field_3x3
=
{
brown_dot
,
red_star
,
brown_dot
,
"
\n
"
,
brown_dot
,
h_brown_dot
,
brown_dot
,
"
\n
"
,
brown_dot
,
brown_dot
,
brown_dot
,
"
\n
"
};
CHECK
(
overmap_w
.
layout
(
ava
)
==
join
(
field_3x3
,
""
)
);
}
SECTION
(
"forest"
)
{
const
std
::
string
green_F
=
"<color_c_green>F</color>"
;
const
std
::
string
h_green_F
=
"<color_h_green>F</color>"
;
fill_overmap_area
(
ava
,
oter_id
(
"forest"
)
);
// Mission marker to the east of avatar position (x + 2)
msn
.
set_target
(
ava
.
global_omt_location
()
+
tripoint
(
2
,
0
,
0
)
);
// (red star on the right edge of the map)
const
std
::
vector
<
std
::
string
>
forest_3x3
=
{
green_F
,
green_F
,
green_F
,
"
\n
"
,
green_F
,
h_green_F
,
red_star
,
"
\n
"
,
green_F
,
green_F
,
green_F
,
"
\n
"
};
CHECK
(
overmap_w
.
layout
(
ava
)
==
join
(
forest_3x3
,
""
)
);
}
SECTION
(
"central lab"
)
{
const
std
::
string
blue_L
=
"<color_c_light_blue>L</color>"
;
const
std
::
string
h_blue_L
=
"<color_h_light_blue>L</color>"
;
//const std::string blue_L_red = "<color_c_light_blue_red>L</color>";
fill_overmap_area
(
ava
,
oter_id
(
"central_lab"
)
);
// Mission marker southwest of avatar position (x-2, y+2)
msn
.
set_target
(
ava
.
global_omt_location
()
+
tripoint
(
-
2
,
2
,
0
)
);
// (red star on lower left corner of map)
const
std
::
vector
<
std
::
string
>
lab_3x3
=
{
blue_L
,
blue_L
,
blue_L
,
"
\n
"
,
blue_L
,
h_blue_L
,
blue_L
,
"
\n
"
,
red_star
,
blue_L
,
blue_L
,
"
\n
"
};
CHECK
(
overmap_w
.
layout
(
ava
)
==
join
(
lab_3x3
,
""
)
);
}
// TODO: Horde indicators
}
TEST_CASE
(
"Custom widget height and multiline formatting"
,
"[widget]"
)
{
const
int
cols
=
32
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录