mirror of
https://github.com/holub/mame
synced 2025-07-04 17:38:08 +03:00
Merge pull request #1073 from ajrhacker/render_crosshair
Crosshair refactoring (nw)
This commit is contained in:
commit
bc33ee65c4
@ -95,6 +95,183 @@ static const rgb_t crosshair_colors[] =
|
|||||||
rgb_t(0xff,0xff,0xff)
|
rgb_t(0xff,0xff,0xff)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// RENDER CROSSHAIR
|
||||||
|
//**************************************************************************
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// render_crosshair - constructor
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
render_crosshair::render_crosshair(running_machine &machine, int player)
|
||||||
|
: m_machine(machine)
|
||||||
|
, m_player(player)
|
||||||
|
, m_used(false)
|
||||||
|
, m_mode(CROSSHAIR_VISIBILITY_OFF)
|
||||||
|
, m_visible(false)
|
||||||
|
, m_texture(nullptr)
|
||||||
|
, m_x(0.0f)
|
||||||
|
, m_y(0.0f)
|
||||||
|
, m_last_x(0.0f)
|
||||||
|
, m_last_y(0.0f)
|
||||||
|
, m_time(0)
|
||||||
|
{
|
||||||
|
// for now, use the main screen
|
||||||
|
m_screen = machine.first_screen();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// render_crosshair - destructor
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
render_crosshair::~render_crosshair()
|
||||||
|
{
|
||||||
|
m_machine.render().texture_free(m_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// set_bitmap_name - change the bitmap name
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void render_crosshair::set_bitmap_name(const char *name)
|
||||||
|
{
|
||||||
|
// update bitmap if name has changed
|
||||||
|
bool changed = name != m_name;
|
||||||
|
m_name = name;
|
||||||
|
if (changed)
|
||||||
|
create_bitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// set_default_bitmap - reset to default bitmap
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void render_crosshair::set_default_bitmap()
|
||||||
|
{
|
||||||
|
// update bitmap if name has changed
|
||||||
|
bool changed = !m_name.empty();
|
||||||
|
m_name.clear();
|
||||||
|
if (changed || m_bitmap == nullptr)
|
||||||
|
create_bitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// create_bitmap - create the rendering
|
||||||
|
// structures for the given player
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void render_crosshair::create_bitmap()
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
rgb_t color = m_player < ARRAY_LENGTH(crosshair_colors) ? crosshair_colors[m_player] : rgb_t::white;
|
||||||
|
|
||||||
|
// if we have a bitmap and texture for this player, kill it
|
||||||
|
if (m_bitmap == nullptr)
|
||||||
|
{
|
||||||
|
m_bitmap = std::make_unique<bitmap_argb32>();
|
||||||
|
m_texture = m_machine.render().texture_alloc(render_texture::hq_scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
emu_file crossfile(m_machine.options().crosshair_path(), OPEN_FLAG_READ);
|
||||||
|
if (!m_name.empty())
|
||||||
|
{
|
||||||
|
// look for user specified file
|
||||||
|
std::string filename = m_name + ".png";
|
||||||
|
render_load_png(*m_bitmap, crossfile, nullptr, filename.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// look for default cross?.png in crsshair/game dir
|
||||||
|
std::string filename = string_format("cross%d.png", m_player + 1);
|
||||||
|
render_load_png(*m_bitmap, crossfile, m_machine.system().name, filename.c_str());
|
||||||
|
|
||||||
|
// look for default cross?.png in crsshair dir
|
||||||
|
if (!m_bitmap->valid())
|
||||||
|
render_load_png(*m_bitmap, crossfile, nullptr, filename.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if that didn't work, use the built-in one */
|
||||||
|
if (!m_bitmap->valid())
|
||||||
|
{
|
||||||
|
/* allocate a blank bitmap to start with */
|
||||||
|
m_bitmap->allocate(CROSSHAIR_RAW_SIZE, CROSSHAIR_RAW_SIZE);
|
||||||
|
m_bitmap->fill(rgb_t(0x00,0xff,0xff,0xff));
|
||||||
|
|
||||||
|
/* extract the raw source data to it */
|
||||||
|
for (y = 0; y < CROSSHAIR_RAW_SIZE / 2; y++)
|
||||||
|
{
|
||||||
|
/* assume it is mirrored vertically */
|
||||||
|
UINT32 *dest0 = &m_bitmap->pix32(y);
|
||||||
|
UINT32 *dest1 = &m_bitmap->pix32(CROSSHAIR_RAW_SIZE - 1 - y);
|
||||||
|
|
||||||
|
/* extract to two rows simultaneously */
|
||||||
|
for (x = 0; x < CROSSHAIR_RAW_SIZE; x++)
|
||||||
|
if ((crosshair_raw_top[y * CROSSHAIR_RAW_ROWBYTES + x / 8] << (x % 8)) & 0x80)
|
||||||
|
dest0[x] = dest1[x] = rgb_t(0xff,0x00,0x00,0x00) | color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reference the new bitmap */
|
||||||
|
m_texture->set_bitmap(*m_bitmap, m_bitmap->cliprect(), TEXFORMAT_ARGB32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// animate - update the crosshair state
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void render_crosshair::animate(UINT16 auto_time)
|
||||||
|
{
|
||||||
|
// read all the port values
|
||||||
|
if (m_used)
|
||||||
|
m_machine.ioport().crosshair_position(m_player, m_x, m_y);
|
||||||
|
|
||||||
|
// auto visibility
|
||||||
|
if (m_mode == CROSSHAIR_VISIBILITY_AUTO)
|
||||||
|
{
|
||||||
|
if ((m_x != m_last_x) || (m_y != m_last_y))
|
||||||
|
{
|
||||||
|
// crosshair has moved, keep crosshair visible
|
||||||
|
m_visible = true;
|
||||||
|
m_last_x = m_x;
|
||||||
|
m_last_y = m_y;
|
||||||
|
m_time = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// see if the player has been motionless for time specified
|
||||||
|
// slightly confusing formula, but the effect is:
|
||||||
|
// auto_time = 0 makes the crosshair barely visible while moved
|
||||||
|
// every increment in auto_time is about .2s at 60Hz
|
||||||
|
if (m_time > auto_time * 12 + 2)
|
||||||
|
// time exceeded so turn crosshair invisible
|
||||||
|
m_visible = false;
|
||||||
|
|
||||||
|
// increment player visibility time
|
||||||
|
m_time++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// draw - render the crosshair to the container
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void render_crosshair::draw(render_container &container, UINT8 fade)
|
||||||
|
{
|
||||||
|
// add a quad assuming a 4:3 screen (this is not perfect)
|
||||||
|
container.add_quad(m_x - 0.03f, m_y - 0.04f, m_x + 0.03f, m_y + 0.04f,
|
||||||
|
rgb_t(0xc0, fade, fade, fade),
|
||||||
|
m_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
// CROSSHAIR MANAGER
|
// CROSSHAIR MANAGER
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
@ -105,12 +282,15 @@ static const rgb_t crosshair_colors[] =
|
|||||||
|
|
||||||
crosshair_manager::crosshair_manager(running_machine &machine)
|
crosshair_manager::crosshair_manager(running_machine &machine)
|
||||||
: m_machine(machine)
|
: m_machine(machine)
|
||||||
|
, m_usage(false)
|
||||||
|
, m_animation_counter(0)
|
||||||
|
, m_auto_time(CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT)
|
||||||
{
|
{
|
||||||
/* request a callback upon exiting */
|
/* request a callback upon exiting */
|
||||||
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(crosshair_manager::exit), this));
|
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(crosshair_manager::exit), this));
|
||||||
|
|
||||||
/* setup the default auto visibility time */
|
for (int player = 0; player < MAX_PLAYERS; player++)
|
||||||
m_auto_time = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
|
m_crosshair[player] = std::make_unique<render_crosshair>(machine, player);
|
||||||
|
|
||||||
/* determine who needs crosshairs */
|
/* determine who needs crosshairs */
|
||||||
for (auto &port : machine.ioport().ports())
|
for (auto &port : machine.ioport().ports())
|
||||||
@ -122,15 +302,11 @@ crosshair_manager::crosshair_manager(running_machine &machine)
|
|||||||
assert(player < MAX_PLAYERS);
|
assert(player < MAX_PLAYERS);
|
||||||
|
|
||||||
/* mark as used and set the default visibility and mode */
|
/* mark as used and set the default visibility and mode */
|
||||||
m_usage = TRUE;
|
m_usage = true;
|
||||||
m_used[player] = TRUE;
|
m_crosshair[player]->set_used(true);
|
||||||
m_mode[player] = CROSSHAIR_VISIBILITY_DEFAULT;
|
m_crosshair[player]->set_mode(CROSSHAIR_VISIBILITY_DEFAULT);
|
||||||
m_visible[player] = (CROSSHAIR_VISIBILITY_DEFAULT == CROSSHAIR_VISIBILITY_OFF) ? FALSE : TRUE;
|
m_crosshair[player]->set_visible(CROSSHAIR_VISIBILITY_DEFAULT != CROSSHAIR_VISIBILITY_OFF);
|
||||||
|
m_crosshair[player]->set_default_bitmap();
|
||||||
/* for now, use the main screen */
|
|
||||||
m_screen[player] = machine.first_screen();
|
|
||||||
|
|
||||||
create_bitmap(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* register callbacks for when we load/save configurations */
|
/* register callbacks for when we load/save configurations */
|
||||||
@ -151,109 +327,7 @@ void crosshair_manager::exit()
|
|||||||
{
|
{
|
||||||
/* free bitmaps and textures for each player */
|
/* free bitmaps and textures for each player */
|
||||||
for (int player = 0; player < MAX_PLAYERS; player++)
|
for (int player = 0; player < MAX_PLAYERS; player++)
|
||||||
{
|
m_crosshair[player] = nullptr;
|
||||||
machine().render().texture_free(m_texture[player]);
|
|
||||||
m_texture[player] = nullptr;
|
|
||||||
m_bitmap[player] = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
|
||||||
create_bitmap - create the rendering
|
|
||||||
structures for the given player
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
void crosshair_manager::create_bitmap(int player)
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
char filename[20];
|
|
||||||
rgb_t color = crosshair_colors[player];
|
|
||||||
|
|
||||||
/* if we have a bitmap and texture for this player, kill it */
|
|
||||||
if (m_bitmap[player] == nullptr) {
|
|
||||||
m_bitmap[player] = std::make_unique<bitmap_argb32>();
|
|
||||||
m_texture[player] = machine().render().texture_alloc(render_texture::hq_scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
emu_file crossfile(machine().options().crosshair_path(), OPEN_FLAG_READ);
|
|
||||||
if (m_name[player][0] != 0)
|
|
||||||
{
|
|
||||||
/* look for user specified file */
|
|
||||||
sprintf(filename, "%s.png", m_name[player]);
|
|
||||||
render_load_png(*m_bitmap[player], crossfile, nullptr, filename);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* look for default cross?.png in crsshair\game dir */
|
|
||||||
sprintf(filename, "cross%d.png", player + 1);
|
|
||||||
render_load_png(*m_bitmap[player], crossfile, machine().system().name, filename);
|
|
||||||
|
|
||||||
/* look for default cross?.png in crsshair dir */
|
|
||||||
if (!m_bitmap[player]->valid())
|
|
||||||
render_load_png(*m_bitmap[player], crossfile, nullptr, filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if that didn't work, use the built-in one */
|
|
||||||
if (!m_bitmap[player]->valid())
|
|
||||||
{
|
|
||||||
/* allocate a blank bitmap to start with */
|
|
||||||
m_bitmap[player]->allocate(CROSSHAIR_RAW_SIZE, CROSSHAIR_RAW_SIZE);
|
|
||||||
m_bitmap[player]->fill(rgb_t(0x00,0xff,0xff,0xff));
|
|
||||||
|
|
||||||
/* extract the raw source data to it */
|
|
||||||
for (y = 0; y < CROSSHAIR_RAW_SIZE / 2; y++)
|
|
||||||
{
|
|
||||||
/* assume it is mirrored vertically */
|
|
||||||
UINT32 *dest0 = &m_bitmap[player]->pix32(y);
|
|
||||||
UINT32 *dest1 = &m_bitmap[player]->pix32(CROSSHAIR_RAW_SIZE - 1 - y);
|
|
||||||
|
|
||||||
/* extract to two rows simultaneously */
|
|
||||||
for (x = 0; x < CROSSHAIR_RAW_SIZE; x++)
|
|
||||||
if ((crosshair_raw_top[y * CROSSHAIR_RAW_ROWBYTES + x / 8] << (x % 8)) & 0x80)
|
|
||||||
dest0[x] = dest1[x] = rgb_t(0xff,0x00,0x00,0x00) | color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reference the new bitmap */
|
|
||||||
m_texture[player]->set_bitmap(*m_bitmap[player], m_bitmap[player]->cliprect(), TEXFORMAT_ARGB32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
|
||||||
get_user_settings - return the
|
|
||||||
current crosshair settings for a player
|
|
||||||
Note: auto_time is common for all players
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
void crosshair_manager::get_user_settings(UINT8 player, crosshair_user_settings *settings)
|
|
||||||
{
|
|
||||||
settings->auto_time = m_auto_time;
|
|
||||||
settings->used = m_used[player];
|
|
||||||
settings->mode = m_mode[player];
|
|
||||||
strcpy(settings->name, m_name[player]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
|
||||||
set_user_settings - modify the
|
|
||||||
current crosshair settings for a player
|
|
||||||
Note: auto_time is common for all players
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
void crosshair_manager::set_user_settings(UINT8 player, crosshair_user_settings *settings)
|
|
||||||
{
|
|
||||||
m_auto_time = settings->auto_time;
|
|
||||||
m_used[player] = settings->used;
|
|
||||||
m_mode[player] = settings->mode;
|
|
||||||
|
|
||||||
/* set visibility as specified by mode */
|
|
||||||
/* auto mode starts with visibility off */
|
|
||||||
m_visible[player] = (settings->mode == CROSSHAIR_VISIBILITY_ON) ? TRUE : FALSE;
|
|
||||||
|
|
||||||
/* update bitmap if name has changed */
|
|
||||||
int changed = strcmp(settings->name, m_name[player]);
|
|
||||||
strcpy(m_name[player], settings->name);
|
|
||||||
if (changed != 0)
|
|
||||||
create_bitmap(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -279,37 +353,7 @@ void crosshair_manager::animate(screen_device &device, bool vblank_state)
|
|||||||
m_fade = 0xa0 + (0x60 * (~m_animation_counter & 0x7f) / 0x80);
|
m_fade = 0xa0 + (0x60 * (~m_animation_counter & 0x7f) / 0x80);
|
||||||
|
|
||||||
for (player = 0; player < MAX_PLAYERS; player++)
|
for (player = 0; player < MAX_PLAYERS; player++)
|
||||||
{
|
m_crosshair[player]->animate(m_auto_time);
|
||||||
/* read all the lightgun values */
|
|
||||||
if (m_used[player])
|
|
||||||
device.machine().ioport().crosshair_position(player, m_x[player], m_y[player]);
|
|
||||||
|
|
||||||
/* auto visibility */
|
|
||||||
if (m_mode[player] == CROSSHAIR_VISIBILITY_AUTO)
|
|
||||||
{
|
|
||||||
if ((m_x[player] != m_last_x[player]) || (m_y[player] != m_last_y[player]))
|
|
||||||
{
|
|
||||||
/* crosshair has moved, keep crosshair visible */
|
|
||||||
m_visible[player] = TRUE;
|
|
||||||
m_last_x[player] = m_x[player];
|
|
||||||
m_last_y[player] = m_y[player];
|
|
||||||
m_time[player] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* see if the player has been motionless for time specified */
|
|
||||||
/* slightly confusing formula, but the effect is: */
|
|
||||||
/* auto_time = 0 makes the crosshair barely visible while moved */
|
|
||||||
/* every increment in auto_time is about .2s at 60Hz */
|
|
||||||
if (m_time[player] > m_auto_time * 12 + 2)
|
|
||||||
/* time exceeded so turn crosshair invisible */
|
|
||||||
m_visible[player] = FALSE;
|
|
||||||
|
|
||||||
/* increment player visibility time */
|
|
||||||
m_time[player]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -323,15 +367,12 @@ void crosshair_manager::render(screen_device &screen)
|
|||||||
int player;
|
int player;
|
||||||
|
|
||||||
for (player = 0; player < MAX_PLAYERS; player++)
|
for (player = 0; player < MAX_PLAYERS; player++)
|
||||||
/* draw if visible and the right screen */
|
|
||||||
if (m_visible[player] &&
|
|
||||||
((m_screen[player] == &screen) || (m_screen[player] == CROSSHAIR_SCREEN_ALL)))
|
|
||||||
{
|
{
|
||||||
/* add a quad assuming a 4:3 screen (this is not perfect) */
|
render_crosshair &crosshair = *m_crosshair[player];
|
||||||
screen.container().add_quad(m_x[player] - 0.03f, m_y[player] - 0.04f,
|
|
||||||
m_x[player] + 0.03f, m_y[player] + 0.04f,
|
// draw if visible and the right screen
|
||||||
rgb_t(0xc0, m_fade, m_fade, m_fade),
|
if (crosshair.is_visible() && ((crosshair.screen() == &screen) || (crosshair.screen() == CROSSHAIR_SCREEN_ALL)))
|
||||||
m_texture[player], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
crosshair.draw(screen.container(), m_fade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,24 +403,26 @@ void crosshair_manager::config_load(config_type cfg_type, xml_data_node *parentn
|
|||||||
|
|
||||||
player = xml_get_attribute_int(crosshairnode, "player", -1);
|
player = xml_get_attribute_int(crosshairnode, "player", -1);
|
||||||
|
|
||||||
/* check to make sure we have a valid player */
|
// check to make sure we have a valid player
|
||||||
/* also check if the player really uses a crosshair */
|
if (player >= 0 && player < MAX_PLAYERS)
|
||||||
if (player >=0 && player < MAX_PLAYERS && m_used[player])
|
|
||||||
{
|
{
|
||||||
/* get, check, and store visibility mode */
|
// check if the player really uses a crosshair
|
||||||
|
render_crosshair &crosshair = *m_crosshair[player];
|
||||||
|
if (crosshair.is_used())
|
||||||
|
{
|
||||||
|
// get, check, and store visibility mode
|
||||||
mode = xml_get_attribute_int(crosshairnode, "mode", CROSSHAIR_VISIBILITY_DEFAULT);
|
mode = xml_get_attribute_int(crosshairnode, "mode", CROSSHAIR_VISIBILITY_DEFAULT);
|
||||||
if (mode >= CROSSHAIR_VISIBILITY_OFF && mode <= CROSSHAIR_VISIBILITY_AUTO)
|
if (mode >= CROSSHAIR_VISIBILITY_OFF && mode <= CROSSHAIR_VISIBILITY_AUTO)
|
||||||
{
|
{
|
||||||
m_mode[player] = (UINT8)mode;
|
crosshair.set_mode((UINT8)mode);
|
||||||
/* set visibility as specified by mode */
|
/* set visibility as specified by mode */
|
||||||
/* auto mode starts with visibility off */
|
/* auto mode starts with visibility off */
|
||||||
m_visible[player] = (mode == CROSSHAIR_VISIBILITY_ON) ? TRUE : FALSE;
|
crosshair.set_visible(mode == CROSSHAIR_VISIBILITY_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get and store crosshair pic name, truncate name to max length */
|
// get and store crosshair pic name
|
||||||
strncpy(m_name[player], xml_get_attribute_string(crosshairnode, "pic", ""), CROSSHAIR_PIC_NAME_LENGTH);
|
crosshair.set_bitmap_name(xml_get_attribute_string(crosshairnode, "pic", ""));
|
||||||
/* update bitmap */
|
}
|
||||||
create_bitmap(player);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,28 +455,30 @@ void crosshair_manager::config_save(config_type cfg_type, xml_data_node *parentn
|
|||||||
|
|
||||||
for (player = 0; player < MAX_PLAYERS; player++)
|
for (player = 0; player < MAX_PLAYERS; player++)
|
||||||
{
|
{
|
||||||
if (m_used[player])
|
const render_crosshair &crosshair = *m_crosshair[player];
|
||||||
|
|
||||||
|
if (crosshair.is_used())
|
||||||
{
|
{
|
||||||
/* create a node */
|
/* create a node */
|
||||||
crosshairnode = xml_add_child(parentnode, "crosshair", nullptr);
|
crosshairnode = xml_add_child(parentnode, "crosshair", nullptr);
|
||||||
|
|
||||||
if (crosshairnode != nullptr)
|
if (crosshairnode != nullptr)
|
||||||
{
|
{
|
||||||
int changed = FALSE;
|
bool changed = false;
|
||||||
|
|
||||||
xml_set_attribute_int(crosshairnode, "player", player);
|
xml_set_attribute_int(crosshairnode, "player", player);
|
||||||
|
|
||||||
if (m_visible[player] != CROSSHAIR_VISIBILITY_DEFAULT)
|
if (crosshair.mode() != CROSSHAIR_VISIBILITY_DEFAULT)
|
||||||
{
|
{
|
||||||
xml_set_attribute_int(crosshairnode, "mode", m_mode[player]);
|
xml_set_attribute_int(crosshairnode, "mode", crosshair.mode());
|
||||||
changed = TRUE;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the default graphic name is "", so only save if not */
|
// only save graphic name if not the default
|
||||||
if (*(m_name[player]) != 0)
|
if (*crosshair.bitmap_name() != '\0')
|
||||||
{
|
{
|
||||||
xml_set_attribute(crosshairnode, "pic", m_name[player]);
|
xml_set_attribute(crosshairnode, "pic", crosshair.bitmap_name());
|
||||||
changed = TRUE;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if nothing changed, kill the node */
|
/* if nothing changed, kill the node */
|
||||||
|
@ -31,22 +31,64 @@
|
|||||||
#define CROSSHAIR_VISIBILITY_AUTOTIME_MAX 50
|
#define CROSSHAIR_VISIBILITY_AUTOTIME_MAX 50
|
||||||
#define CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT 15
|
#define CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT 15
|
||||||
|
|
||||||
/* maximum crosshair pic filename size */
|
|
||||||
#define CROSSHAIR_PIC_NAME_LENGTH 12
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
TYPE DEFINITIONS
|
TYPE DEFINITIONS
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/* user-controllable settings for a player */
|
// ======================> render_crosshair
|
||||||
struct crosshair_user_settings
|
|
||||||
|
class render_crosshair
|
||||||
{
|
{
|
||||||
UINT8 used; /* is used */
|
public:
|
||||||
UINT8 mode; /* visibility mode */
|
// construction/destruction
|
||||||
UINT8 auto_time; /* time in seconds to blank crosshair if no movement */
|
render_crosshair(running_machine &machine, int player);
|
||||||
char name[CROSSHAIR_PIC_NAME_LENGTH + 1]; /* bitmap name */
|
~render_crosshair();
|
||||||
|
|
||||||
|
// getters
|
||||||
|
running_machine &machine() const { return m_machine; }
|
||||||
|
int player() const { return m_player; }
|
||||||
|
bool is_used() const { return m_used; }
|
||||||
|
UINT8 mode() const { return m_mode; }
|
||||||
|
bool is_visible() const { return m_visible; }
|
||||||
|
screen_device *screen() const { return m_screen; }
|
||||||
|
float x() const { return m_x; }
|
||||||
|
float y() const { return m_y; }
|
||||||
|
const char *bitmap_name() const { return m_name.c_str(); }
|
||||||
|
|
||||||
|
// setters
|
||||||
|
void set_used(bool used) { m_used = used; }
|
||||||
|
void set_mode(UINT8 mode) { m_mode = mode; }
|
||||||
|
void set_visible(bool visible) { m_visible = visible; }
|
||||||
|
void set_screen(screen_device *screen) { m_screen = screen; }
|
||||||
|
//void setxy(float x, float y);
|
||||||
|
void set_bitmap_name(const char *name);
|
||||||
|
void set_default_bitmap();
|
||||||
|
|
||||||
|
// updates
|
||||||
|
void animate(UINT16 auto_time);
|
||||||
|
void draw(render_container &container, UINT8 fade);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// private helpers
|
||||||
|
void create_bitmap();
|
||||||
|
|
||||||
|
// private state
|
||||||
|
running_machine & m_machine; // reference to our machine
|
||||||
|
int m_player; // player number
|
||||||
|
bool m_used; // usage for this crosshair
|
||||||
|
UINT8 m_mode; // visibility mode for this crosshair
|
||||||
|
bool m_visible; // visibility for this crosshair
|
||||||
|
std::unique_ptr<bitmap_argb32> m_bitmap; // bitmap for this crosshair
|
||||||
|
render_texture * m_texture; // texture for this crosshair
|
||||||
|
screen_device * m_screen; // the screen on which this crosshair is drawn
|
||||||
|
float m_x; // current X position
|
||||||
|
float m_y; // current Y position
|
||||||
|
float m_last_x; // last X position
|
||||||
|
float m_last_y; // last Y position
|
||||||
|
UINT16 m_time; // time since last movement
|
||||||
|
std::string m_name; // name of png file
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -61,21 +103,16 @@ public:
|
|||||||
/* draws crosshair(s) in a given screen, if necessary */
|
/* draws crosshair(s) in a given screen, if necessary */
|
||||||
void render(screen_device &screen);
|
void render(screen_device &screen);
|
||||||
|
|
||||||
/* sets the screen(s) for a given player's crosshair */
|
// return true if any crosshairs are used
|
||||||
void set_screen(int player, screen_device *screen) { m_screen[player] = screen; }
|
bool get_usage() const { return m_usage; }
|
||||||
|
|
||||||
/* return TRUE if any crosshairs are used */
|
|
||||||
int get_usage() const { return m_usage; }
|
|
||||||
|
|
||||||
/* return the current crosshair settings for the given player */
|
|
||||||
void get_user_settings(UINT8 player, crosshair_user_settings *settings);
|
|
||||||
|
|
||||||
/* modify the current crosshair settings for the given player */
|
|
||||||
void set_user_settings(UINT8 player, crosshair_user_settings *settings);
|
|
||||||
// getters
|
// getters
|
||||||
running_machine &machine() const { return m_machine; }
|
running_machine &machine() const { return m_machine; }
|
||||||
|
render_crosshair &get_crosshair(int player) const { assert(player >= 0 && player < MAX_PLAYERS); assert(m_crosshair[player] != nullptr); return *m_crosshair[player]; }
|
||||||
|
UINT16 auto_time() const { return m_auto_time; }
|
||||||
|
void set_auto_time(UINT16 auto_time) { m_auto_time = auto_time; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void create_bitmap(int player);
|
|
||||||
void exit();
|
void exit();
|
||||||
void animate(screen_device &device, bool vblank_state);
|
void animate(screen_device &device, bool vblank_state);
|
||||||
|
|
||||||
@ -85,22 +122,11 @@ private:
|
|||||||
// internal state
|
// internal state
|
||||||
running_machine & m_machine; // reference to our machine
|
running_machine & m_machine; // reference to our machine
|
||||||
|
|
||||||
UINT8 m_usage; /* true if any crosshairs are used */
|
bool m_usage; // true if any crosshairs are used
|
||||||
UINT8 m_used[MAX_PLAYERS]; /* usage per player */
|
std::unique_ptr<render_crosshair> m_crosshair[MAX_PLAYERS]; // per-player crosshair state
|
||||||
UINT8 m_mode[MAX_PLAYERS]; /* visibility mode per player */
|
UINT8 m_fade; // color fading factor
|
||||||
UINT8 m_visible[MAX_PLAYERS]; /* visibility per player */
|
UINT8 m_animation_counter; // animation frame index
|
||||||
std::unique_ptr<bitmap_argb32> m_bitmap[MAX_PLAYERS]; /* bitmap per player */
|
UINT16 m_auto_time; // time in seconds to turn invisible
|
||||||
render_texture * m_texture[MAX_PLAYERS]; /* texture per player */
|
|
||||||
screen_device * m_screen[MAX_PLAYERS]; /* the screen on which this player's crosshair is drawn */
|
|
||||||
float m_x[MAX_PLAYERS]; /* current X position */
|
|
||||||
float m_y[MAX_PLAYERS]; /* current Y position */
|
|
||||||
float m_last_x[MAX_PLAYERS]; /* last X position */
|
|
||||||
float m_last_y[MAX_PLAYERS]; /* last Y position */
|
|
||||||
UINT8 m_fade; /* color fading factor */
|
|
||||||
UINT8 m_animation_counter; /* animation frame index */
|
|
||||||
UINT16 m_auto_time; /* time in seconds to turn invisible */
|
|
||||||
UINT16 m_time[MAX_PLAYERS]; /* time since last movement */
|
|
||||||
char m_name[MAX_PLAYERS][CROSSHAIR_PIC_NAME_LENGTH + 1]; /* name of crosshair png file */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __CRSSHAIR_H__ */
|
#endif /* __CRSSHAIR_H__ */
|
||||||
|
@ -280,14 +280,13 @@ void menu_crosshair::handle()
|
|||||||
/* handle events */
|
/* handle events */
|
||||||
if (menu_event != nullptr && menu_event->itemref != nullptr)
|
if (menu_event != nullptr && menu_event->itemref != nullptr)
|
||||||
{
|
{
|
||||||
crosshair_user_settings settings;
|
|
||||||
crosshair_item_data *data = (crosshair_item_data *)menu_event->itemref;
|
crosshair_item_data *data = (crosshair_item_data *)menu_event->itemref;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
//int set_def = false;
|
//int set_def = false;
|
||||||
int newval = data->cur;
|
int newval = data->cur;
|
||||||
|
|
||||||
/* retreive the user settings */
|
/* retreive the user settings */
|
||||||
machine().crosshair().get_user_settings(data->player, &settings);
|
render_crosshair &crosshair = machine().crosshair().get_crosshair(data->player);
|
||||||
|
|
||||||
switch (menu_event->iptkey)
|
switch (menu_event->iptkey)
|
||||||
{
|
{
|
||||||
@ -321,13 +320,15 @@ void menu_crosshair::handle()
|
|||||||
{
|
{
|
||||||
/* visibility state */
|
/* visibility state */
|
||||||
case CROSSHAIR_ITEM_VIS:
|
case CROSSHAIR_ITEM_VIS:
|
||||||
settings.mode = newval;
|
crosshair.set_mode(newval);
|
||||||
|
// set visibility as specified by mode - auto mode starts with visibility off
|
||||||
|
crosshair.set_visible(newval == CROSSHAIR_VISIBILITY_ON);
|
||||||
changed = true;
|
changed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* auto time */
|
/* auto time */
|
||||||
case CROSSHAIR_ITEM_AUTO_TIME:
|
case CROSSHAIR_ITEM_AUTO_TIME:
|
||||||
settings.auto_time = newval;
|
machine().crosshair().set_auto_time(newval);
|
||||||
changed = true;
|
changed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -339,18 +340,17 @@ void menu_crosshair::handle()
|
|||||||
switch (menu_event->iptkey)
|
switch (menu_event->iptkey)
|
||||||
{
|
{
|
||||||
case IPT_UI_SELECT:
|
case IPT_UI_SELECT:
|
||||||
/* clear the name string to reset to default crosshair */
|
crosshair.set_default_bitmap();
|
||||||
settings.name[0] = 0;
|
|
||||||
changed = true;
|
changed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPT_UI_LEFT:
|
case IPT_UI_LEFT:
|
||||||
strcpy(settings.name, data->last_name);
|
crosshair.set_bitmap_name(data->last_name);
|
||||||
changed = true;
|
changed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPT_UI_RIGHT:
|
case IPT_UI_RIGHT:
|
||||||
strcpy(settings.name, data->next_name);
|
crosshair.set_bitmap_name(data->next_name);
|
||||||
changed = true;
|
changed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -358,9 +358,6 @@ void menu_crosshair::handle()
|
|||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
/* save the user settings */
|
|
||||||
machine().crosshair().set_user_settings(data->player, &settings);
|
|
||||||
|
|
||||||
/* rebuild the menu */
|
/* rebuild the menu */
|
||||||
reset(reset_options::REMEMBER_POSITION);
|
reset(reset_options::REMEMBER_POSITION);
|
||||||
}
|
}
|
||||||
@ -379,7 +376,6 @@ menu_crosshair::menu_crosshair(mame_ui_manager &mui, render_container &container
|
|||||||
|
|
||||||
void menu_crosshair::populate()
|
void menu_crosshair::populate()
|
||||||
{
|
{
|
||||||
crosshair_user_settings settings;
|
|
||||||
crosshair_item_data *data;
|
crosshair_item_data *data;
|
||||||
char temp_text[16];
|
char temp_text[16];
|
||||||
int player;
|
int player;
|
||||||
@ -390,16 +386,16 @@ void menu_crosshair::populate()
|
|||||||
for (player = 0; player < MAX_PLAYERS; player++)
|
for (player = 0; player < MAX_PLAYERS; player++)
|
||||||
{
|
{
|
||||||
/* get the user settings */
|
/* get the user settings */
|
||||||
machine().crosshair().get_user_settings(player, &settings);
|
render_crosshair &crosshair = machine().crosshair().get_crosshair(player);
|
||||||
|
|
||||||
/* add menu items for usable crosshairs */
|
/* add menu items for usable crosshairs */
|
||||||
if (settings.used)
|
if (crosshair.is_used())
|
||||||
{
|
{
|
||||||
/* Make sure to keep these matched to the CROSSHAIR_VISIBILITY_xxx types */
|
/* Make sure to keep these matched to the CROSSHAIR_VISIBILITY_xxx types */
|
||||||
static const char *const vis_text[] = { "Off", "On", "Auto" };
|
static const char *const vis_text[] = { "Off", "On", "Auto" };
|
||||||
|
|
||||||
/* track if we need the auto time menu */
|
/* track if we need the auto time menu */
|
||||||
if (settings.mode == CROSSHAIR_VISIBILITY_AUTO) use_auto = true;
|
if (crosshair.mode() == CROSSHAIR_VISIBILITY_AUTO) use_auto = true;
|
||||||
|
|
||||||
/* CROSSHAIR_ITEM_VIS - allocate a data item and fill it */
|
/* CROSSHAIR_ITEM_VIS - allocate a data item and fill it */
|
||||||
data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
|
data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
|
||||||
@ -408,7 +404,7 @@ void menu_crosshair::populate()
|
|||||||
data->min = CROSSHAIR_VISIBILITY_OFF;
|
data->min = CROSSHAIR_VISIBILITY_OFF;
|
||||||
data->max = CROSSHAIR_VISIBILITY_AUTO;
|
data->max = CROSSHAIR_VISIBILITY_AUTO;
|
||||||
data->defvalue = CROSSHAIR_VISIBILITY_DEFAULT;
|
data->defvalue = CROSSHAIR_VISIBILITY_DEFAULT;
|
||||||
data->cur = settings.mode;
|
data->cur = crosshair.mode();
|
||||||
|
|
||||||
/* put on arrows */
|
/* put on arrows */
|
||||||
if (data->cur > data->min)
|
if (data->cur > data->min)
|
||||||
@ -418,7 +414,7 @@ void menu_crosshair::populate()
|
|||||||
|
|
||||||
/* add CROSSHAIR_ITEM_VIS menu */
|
/* add CROSSHAIR_ITEM_VIS menu */
|
||||||
sprintf(temp_text, "P%d Visibility", player + 1);
|
sprintf(temp_text, "P%d Visibility", player + 1);
|
||||||
item_append(temp_text, vis_text[settings.mode], flags, data);
|
item_append(temp_text, vis_text[crosshair.mode()], flags, data);
|
||||||
|
|
||||||
/* CROSSHAIR_ITEM_PIC - allocate a data item and fill it */
|
/* CROSSHAIR_ITEM_PIC - allocate a data item and fill it */
|
||||||
data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
|
data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
|
||||||
@ -438,7 +434,7 @@ void menu_crosshair::populate()
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
/* if we are using the default, then we just need to find the first in the list */
|
/* if we are using the default, then we just need to find the first in the list */
|
||||||
if (*(settings.name) == 0)
|
if (*crosshair.bitmap_name() == '\0')
|
||||||
using_default = true;
|
using_default = true;
|
||||||
|
|
||||||
/* look for the current name, then remember the name before */
|
/* look for the current name, then remember the name before */
|
||||||
@ -460,7 +456,7 @@ void menu_crosshair::populate()
|
|||||||
data->next_name[length] = 0;
|
data->next_name[length] = 0;
|
||||||
finished = true;
|
finished = true;
|
||||||
}
|
}
|
||||||
else if (!strncmp(dir->name, settings.name, length))
|
else if (!strncmp(dir->name, crosshair.bitmap_name(), length))
|
||||||
{
|
{
|
||||||
/* we found the current name */
|
/* we found the current name */
|
||||||
/* so loop once more to find the next name */
|
/* so loop once more to find the next name */
|
||||||
@ -490,21 +486,18 @@ void menu_crosshair::populate()
|
|||||||
|
|
||||||
/* add CROSSHAIR_ITEM_PIC menu */
|
/* add CROSSHAIR_ITEM_PIC menu */
|
||||||
sprintf(temp_text, "P%d Crosshair", player + 1);
|
sprintf(temp_text, "P%d Crosshair", player + 1);
|
||||||
item_append(temp_text, using_default ? "DEFAULT" : settings.name, flags, data);
|
item_append(temp_text, using_default ? "DEFAULT" : crosshair.bitmap_name(), flags, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (use_auto)
|
if (use_auto)
|
||||||
{
|
{
|
||||||
/* any player can be used to get the autotime */
|
|
||||||
machine().crosshair().get_user_settings(0, &settings);
|
|
||||||
|
|
||||||
/* CROSSHAIR_ITEM_AUTO_TIME - allocate a data item and fill it */
|
/* CROSSHAIR_ITEM_AUTO_TIME - allocate a data item and fill it */
|
||||||
data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
|
data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
|
||||||
data->type = CROSSHAIR_ITEM_AUTO_TIME;
|
data->type = CROSSHAIR_ITEM_AUTO_TIME;
|
||||||
data->min = CROSSHAIR_VISIBILITY_AUTOTIME_MIN;
|
data->min = CROSSHAIR_VISIBILITY_AUTOTIME_MIN;
|
||||||
data->max = CROSSHAIR_VISIBILITY_AUTOTIME_MAX;
|
data->max = CROSSHAIR_VISIBILITY_AUTOTIME_MAX;
|
||||||
data->defvalue = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
|
data->defvalue = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
|
||||||
data->cur = settings.auto_time;
|
data->cur = machine().crosshair().auto_time();
|
||||||
|
|
||||||
/* put on arrows in visible menu */
|
/* put on arrows in visible menu */
|
||||||
if (data->cur > data->min)
|
if (data->cur > data->min)
|
||||||
@ -513,7 +506,7 @@ void menu_crosshair::populate()
|
|||||||
flags |= FLAG_RIGHT_ARROW;
|
flags |= FLAG_RIGHT_ARROW;
|
||||||
|
|
||||||
/* add CROSSHAIR_ITEM_AUTO_TIME menu */
|
/* add CROSSHAIR_ITEM_AUTO_TIME menu */
|
||||||
sprintf(temp_text, "%d", settings.auto_time);
|
sprintf(temp_text, "%d", machine().crosshair().auto_time());
|
||||||
item_append(_("Visible Delay"), temp_text, flags, data);
|
item_append(_("Visible Delay"), temp_text, flags, data);
|
||||||
}
|
}
|
||||||
// else
|
// else
|
||||||
|
@ -69,6 +69,9 @@ private:
|
|||||||
CROSSHAIR_ITEM_AUTO_TIME
|
CROSSHAIR_ITEM_AUTO_TIME
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// FIXME: use std::string instead of fixed-length arrays
|
||||||
|
constexpr static int CROSSHAIR_PIC_NAME_LENGTH = 12;
|
||||||
|
|
||||||
/* internal crosshair menu item data */
|
/* internal crosshair menu item data */
|
||||||
struct crosshair_item_data
|
struct crosshair_item_data
|
||||||
{
|
{
|
||||||
|
@ -1324,7 +1324,7 @@ VIDEO_START_MEMBER(sms_state,sms1)
|
|||||||
save_item(NAME(m_frame_sscope_state));
|
save_item(NAME(m_frame_sscope_state));
|
||||||
|
|
||||||
// Allow sscope screens to have crosshair, useful for the game missil3d
|
// Allow sscope screens to have crosshair, useful for the game missil3d
|
||||||
machine().crosshair().set_screen(0, CROSSHAIR_SCREEN_ALL);
|
machine().crosshair().get_crosshair(0).set_screen(CROSSHAIR_SCREEN_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1715,11 +1715,11 @@ UINT32 cave_state::screen_update_ppsatan_top(screen_device &screen, bitmap_rgb32
|
|||||||
}
|
}
|
||||||
UINT32 cave_state::screen_update_ppsatan_left(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
UINT32 cave_state::screen_update_ppsatan_left(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||||
{
|
{
|
||||||
machine().crosshair().set_screen(1, &screen);
|
machine().crosshair().get_crosshair(1).set_screen(&screen);
|
||||||
return screen_update_ppsatan_core(screen, bitmap, cliprect, 1);
|
return screen_update_ppsatan_core(screen, bitmap, cliprect, 1);
|
||||||
}
|
}
|
||||||
UINT32 cave_state::screen_update_ppsatan_right(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
UINT32 cave_state::screen_update_ppsatan_right(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||||
{
|
{
|
||||||
machine().crosshair().set_screen(0, &screen);
|
machine().crosshair().get_crosshair(0).set_screen(&screen);
|
||||||
return screen_update_ppsatan_core(screen, bitmap, cliprect, 2);
|
return screen_update_ppsatan_core(screen, bitmap, cliprect, 2);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user