Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/about/Authors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Clayton Hughes
Clément Vuchener cvuchener
Corey CoreyJ87
daedsidog daedsidog
Dailton Filho notliad
Dan Amlund danamlund
Daniel Brooks db48x
David Nilsolm
Expand Down Expand Up @@ -121,6 +122,7 @@ Kurik Amudnil
Kévin Boissonneault KABoissonneault
Lethosor lethosor
LordGolias LordGolias
Magnus Anderson magnus-ISU
Mark Nielson pseudodragon
Mason11987 Mason11987
Matt Regul mattregul
Expand Down Expand Up @@ -261,6 +263,7 @@ Vitaly Pronkin pronvit mifki
ViTuRaS ViTuRaS
Vjek vjek
Vladimir Florov foxxelias
wala343 wala343
Warmist warmist
Wes Malone wesQ3
Will H TSM-EVO
Expand Down
1 change: 1 addition & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Template for new versions:
# Future

## New Tools
- `smooth-movement`: smoothly animate creature, item, and vehicle movement in the fortress viewport

## New Features

Expand Down
50 changes: 50 additions & 0 deletions docs/plugins/smooth-movement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
smooth-movement
===============

.. dfhack-tool::
:summary: Smoothly animate movement in the fortress viewport.
:tags: fort interface

This plugin makes creatures, hauled items, vehicles, and associated status
icons glide between tiles. It only changes rendering; gameplay, simulation
timing, and save data are unaffected.

The plugin requires the SDL 2D renderer.

Usage
-----

::

enable smooth-movement
smooth-movement
smooth-movement flip on|off
smooth-movement zlevel on|off

Running ``smooth-movement`` without arguments reports the plugin status and
current settings. Optional features are reset to their defaults whenever the
plugin is enabled.

Examples
--------

``enable smooth-movement``
Enable smooth movement on the main z-level.

``smooth-movement flip on``
Horizontally flip creatures so they face their direction of travel.

``smooth-movement zlevel on``
Also animate movement on visible z-levels below the main level.

Settings
--------

``flip`` (default: off)
Flip creature sprites horizontally according to their last horizontal
movement. Items, vehicles, and designation icons keep their normal
orientation.

``zlevel`` (default: off)
Animate movement on visible lower z-levels. Sprite flipping remains
independent of this setting.
1 change: 1 addition & 0 deletions plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ if(BUILD_SUPPORTED)
#dfhack_plugin(siege-engine siege-engine.cpp LINK_LIBRARIES lua)
dfhack_plugin(sort sort.cpp LINK_LIBRARIES lua)
#dfhack_plugin(steam-engine steam-engine.cpp)
add_subdirectory(smooth-movement)
dfhack_plugin(spectate spectate.cpp LINK_LIBRARIES lua)
#dfhack_plugin(stockflow stockflow.cpp LINK_LIBRARIES lua)
add_subdirectory(stockpiles)
Expand Down
4 changes: 4 additions & 0 deletions plugins/smooth-movement/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dfhack_plugin(smooth-movement smooth-movement.cpp visual_animation.cpp visual_renderer.cpp
LINK_LIBRARIES lua)
target_include_directories(smooth-movement PRIVATE ${SDL2_INCLUDE_DIRS})
dfhack_test(smooth-movement-test "test_visual_animation_manager.cpp;visual_animation.cpp")
108 changes: 108 additions & 0 deletions plugins/smooth-movement/smooth-movement.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// SPDX-License-Identifier: MIT

#include <string>
#include <vector>

#include "PluginManager.h"
#include "VTableInterpose.h"

#include "df/renderer_2d_base.h"

#include "visual_renderer.h"

using namespace DFHack;

DFHACK_PLUGIN("smooth-movement");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
REQUIRE_GLOBAL_NO_USE(gps);
REQUIRE_GLOBAL_NO_USE(window_x);
REQUIRE_GLOBAL_NO_USE(window_y);
REQUIRE_GLOBAL_NO_USE(window_z);

namespace {

struct renderer_hook : df::renderer_2d_base {
typedef df::renderer_2d_base interpose_base;
DEFINE_VMETHOD_INTERPOSE(void, update_all, ());
};

IMPLEMENT_VMETHOD_INTERPOSE(renderer_hook, update_all);

void renderer_hook::interpose_fn_update_all() {
smooth_movement::render(this);
INTERPOSE_NEXT(update_all)();
}

command_result status_command(color_ostream &out, std::vector<std::string> &parameters) {
if (parameters.empty()) {
out.print("smooth-movement: {}\n", is_enabled ? "enabled" : "disabled");
out.print("sprite flipping: {}\n", smooth_movement::flip_enabled() ? "on" : "off");
out.print("lower z-level animation: {}\n",
smooth_movement::zlevel_enabled() ? "on" : "off");
return CR_OK;
}
if (parameters[0] == "flip") {
if (parameters.size() == 1) {
out.print("sprite flipping: {}\n", smooth_movement::flip_enabled() ? "on" : "off");
return CR_OK;
}
if (parameters.size() == 2 && parameters[1] == "on")
smooth_movement::set_flip_enabled(true);
else if (parameters.size() == 2 && parameters[1] == "off")
smooth_movement::set_flip_enabled(false);
else
return CR_WRONG_USAGE;
out.print("smooth-movement: sprite flipping {}\n",
smooth_movement::flip_enabled() ? "enabled" : "disabled");
return CR_OK;
}
if (parameters[0] == "zlevel") {
if (parameters.size() == 1) {
out.print("lower z-level animation: {}\n",
smooth_movement::zlevel_enabled() ? "on" : "off");
return CR_OK;
}
if (parameters.size() == 2 && parameters[1] == "on")
smooth_movement::set_zlevel_enabled(true);
else if (parameters.size() == 2 && parameters[1] == "off")
smooth_movement::set_zlevel_enabled(false);
else
return CR_WRONG_USAGE;
out.print("smooth-movement: lower z-level animation {}\n",
smooth_movement::zlevel_enabled() ? "enabled" : "disabled");
return CR_OK;
}
return CR_WRONG_USAGE;
}

} // namespace

DFhackCExport command_result plugin_init(color_ostream &, std::vector<PluginCommand> &commands) {
commands.emplace_back("smooth-movement", "Smoothly animate movement in the fortress viewport.",
status_command);
return CR_OK;
}

DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) {
if (is_enabled == enable)
return CR_OK;
if (enable) {
if (!smooth_movement::initialize(out))
return CR_FAILURE;
if (!INTERPOSE_HOOK(renderer_hook, update_all).apply()) {
out.printerr("smooth-movement: could not hook the 2D renderer\n");
smooth_movement::shutdown();
return CR_FAILURE;
}
} else {
INTERPOSE_HOOK(renderer_hook, update_all).remove();
smooth_movement::shutdown();
}
is_enabled = enable;
out.print("smooth-movement: {}\n", enable ? "enabled" : "disabled");
return CR_OK;
}

DFhackCExport command_result plugin_shutdown(color_ostream &out) {
return plugin_enable(out, false);
}
Loading
Loading