Skip to content
Open
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
4 changes: 4 additions & 0 deletions ImguiMapEditor/Application/CallbackMediator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ void CallbackMediator::wireTabCallbacks(Context &ctx) {
state.current_floor = ctx.map_panel->getCurrentFloor();
state.lighting_enabled = ctx.view_settings->map_lighting_enabled;
state.ambient_light = ctx.view_settings->map_ambient_light;
state.server_light_intensity = ctx.view_settings->server_light_intensity;
state.server_light_color = ctx.view_settings->server_light_color;
state.show_ingame_box = ctx.view_settings->show_ingame_box;
state.show_minimap = ctx.view_settings->show_minimap_window;

Expand All @@ -238,6 +240,8 @@ void CallbackMediator::wireTabCallbacks(Context &ctx) {
ctx.map_panel->setCurrentFloor(static_cast<int16_t>(state.current_floor));
ctx.view_settings->map_lighting_enabled = state.lighting_enabled;
ctx.view_settings->map_ambient_light = state.ambient_light;
ctx.view_settings->server_light_intensity = state.server_light_intensity;
ctx.view_settings->server_light_color = state.server_light_color;
ctx.view_settings->show_ingame_box = state.show_ingame_box;
ctx.view_settings->show_minimap_window = state.show_minimap;
ctx.minimap->setMap(session->getMap(),
Expand Down
4 changes: 3 additions & 1 deletion ImguiMapEditor/Application/EditorSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ class EditorSession {
int current_floor = 7;
// Per-map lighting settings
bool lighting_enabled = false;
int ambient_light = 128;
int ambient_light = 0;
uint8_t server_light_intensity = 200;
uint8_t server_light_color = 215;
// Per-map window visibility
bool show_ingame_box = false;
bool show_minimap = false;
Expand Down
1 change: 1 addition & 0 deletions ImguiMapEditor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ set(UI_SOURCES
UI/Ribbon/RibbonController.cpp
UI/Widgets/Properties/PropertyPanelRenderer.cpp
UI/Widgets/Properties/PropertyWidgets.cpp
UI/Widgets/LightColorPalettePicker.cpp
UI/Widgets/QuickSearchPopup.cpp
UI/Widgets/SearchResultsWidget.cpp
UI/Widgets/TilesetWidget.cpp
Expand Down
13 changes: 13 additions & 0 deletions ImguiMapEditor/Core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ inline constexpr int GROUND_LAYER = 7;
inline constexpr uint16_t DEFAULT_MAP_SIZE = 16384;
} // namespace Map

// ============================================================================
// LIGHTING CONFIGURATION
// ============================================================================
namespace Lighting {
inline constexpr int LIGHT_COLOR_COUNT = 216;
inline constexpr uint8_t MAX_SERVER_LIGHT_COLOR = 215;
inline constexpr uint8_t DEFAULT_SERVER_LIGHT_INTENSITY = 200;
inline constexpr uint8_t DEFAULT_SERVER_LIGHT_COLOR = 215;
inline constexpr uint8_t DEFAULT_MINIMUM_AMBIENT = 0;
inline constexpr uint8_t DEFAULT_PLAYER_LIGHT_INTENSITY = 2;
inline constexpr uint8_t TRANSLUCENT_PROPAGATION_INTENSITY = 1;
} // namespace Lighting

// ============================================================================
// PERFORMANCE CONFIGURATION
// ============================================================================
Expand Down
4 changes: 4 additions & 0 deletions ImguiMapEditor/Domain/CreatureType.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ struct CreatureType {
std::string name;
bool is_npc = false;
Outfit outfit;

// Light properties (from DAT or creatures.xml)
uint8_t light_level = 0; // 0 = no light, >0 = light radius
uint8_t light_color = 0; // 8-bit Tibia palette index

// Default constructor
CreatureType() = default;
Expand Down
3 changes: 3 additions & 0 deletions ImguiMapEditor/Domain/ItemType.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ class ItemType {
// Translucency (from DAT)
bool is_translucent = false;

// Lens help (from DAT) — items with value > 0 are "see-through" for light propagation
uint16_t lens_help = 0;

// Elevation (from DAT) - items on this raise subsequent items visually
uint16_t elevation = 0;

Expand Down
33 changes: 30 additions & 3 deletions ImguiMapEditor/Domain/LightTypes.h
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
#pragma once

#include "Core/Config.h"

#include <cstdint>

namespace MapEditor {
namespace Domain {

/**
* Global world light (mimics server WorldLight protocol message).
* Defines the ambient light level for above-ground floors.
*/
struct GlobalLight {
uint8_t intensity = 0; // Server ambient level (0-255)
uint8_t color = Config::Lighting::DEFAULT_SERVER_LIGHT_COLOR;
};

/**
* A light source extracted from a tile item.
* Contains position, color (8-bit palette index), and intensity.
*/
struct LightSource {
int32_t x = 0; // Tile X position
int32_t y = 0; // Tile Y position
uint8_t color = 215; // 8-bit palette index (default: white-ish)
uint8_t color = Config::Lighting::DEFAULT_SERVER_LIGHT_COLOR;
uint8_t intensity = 0; // 0-255 (affects light radius)
int16_t source_floor = 0; // Floor this light originates from (for blocking)
};

/**
Expand All @@ -22,8 +34,23 @@ struct LightSource {
*/
struct LightConfig {
bool enabled = false; // Master enable for this viewport
uint8_t ambient_level = 255; // 0 = complete darkness, 255 = full bright
uint8_t ambient_color = 215; // 8-bit palette index for ambient
GlobalLight global_light; // Server global light (above-ground ambient)
uint8_t client_slider = Config::Lighting::DEFAULT_MINIMUM_AMBIENT;
int16_t camera_floor = Config::Map::GROUND_LAYER;
// Deprecated compatibility fields. Rendering computes final ambient from
// global_light, client_slider, and camera_floor elsewhere.
uint8_t ambient_color = Config::Lighting::DEFAULT_SERVER_LIGHT_COLOR;
uint8_t ambient_level = 255;

/**
* Hash fields that affect generated lighting.
*/
[[nodiscard]] uint32_t computeHash() const {
return static_cast<uint32_t>(global_light.intensity) |
(static_cast<uint32_t>(global_light.color) << 8) |
(static_cast<uint32_t>(client_slider) << 16) |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 The computeHash function currently excludes the enabled field. While LightingPass checks this field before calling render, it might be safer to include it in the hash to ensure the cache is invalidated if the master toggle is changed, or add a comment explaining why it's omitted.

(static_cast<uint32_t>(camera_floor & 0xFF) << 24);
}
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 The comment says ambient_level is "computed from global_light + slider", but the code only assigns global_light.intensity. The actual combined computation happens in LightManager::computeViewportLight. The comment should be updated to reflect that these are now purely for backward compatibility and might not reflect the final rendered intensity.

} // namespace Domain
Expand Down
5 changes: 4 additions & 1 deletion ImguiMapEditor/Domain/Tile.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ enum class TileFlag : uint16_t {
NoPvp = 1 << 2, // 0x0004
NoLogout = 1 << 3, // 0x0008
PvpZone = 1 << 4, // 0x0010
Refresh = 1 << 5 // 0x0020
Refresh = 1 << 5, // 0x0020
// TranslucentLight marks an underground tile lit by translucent ground above;
// the current RME/OTClient propagation rule applies at z == GROUND_LAYER + 1.
TranslucentLight = 1 << 6
};

inline TileFlag operator|(TileFlag a, TileFlag b) {
Expand Down
19 changes: 19 additions & 0 deletions ImguiMapEditor/IO/CreatureXmlReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,25 @@ CreatureXmlReader::parseCreatureNode(const pugi::xml_node &node, bool isNpc,
creature->outfit.lookMountFeet = static_cast<uint16_t>(attr.as_uint());
}

// Light properties (optional)
const auto read_light_u8 = [&](const char *attribute_name) -> uint8_t {
const auto attr = node.attribute(attribute_name);
if (!attr) return 0;

const unsigned int raw_value = attr.as_uint();
if (raw_value > 255U) {
warnings.push_back(std::string("Creature '") + creature->name +

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Using attr.as_uint() and then checking > 255 is safe, but ensure that the warning message (which was truncated in the diff) clearly identifies which creature has the invalid light property to help users fix their creatures.xml.

"' has " + attribute_name + "=" +
std::to_string(raw_value) + "; clamped to 255");
return 255;
}

return static_cast<uint8_t>(raw_value);
};

creature->light_level = read_light_u8("lightlevel");
creature->light_color = read_light_u8("lightcolor");

return creature;
}

Expand Down
27 changes: 23 additions & 4 deletions ImguiMapEditor/Presentation/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "Rendering/Frame/RenderingManager.h"
#include "Services/ClipboardService.h"
#include "UI/Core/Theme.h"
#include "UI/Widgets/LightColorPalettePicker.h"
#include <cmath>
#include <imgui.h>
#include <spdlog/spdlog.h>
Expand Down Expand Up @@ -134,10 +135,28 @@ void MainWindow::renderEditor(Domain::ChunkedMap *current_map,
// Lighting controls toolbar (per-map)
ImGui::Checkbox("Enable Lighting",
&view_settings_.map_lighting_enabled);
ImGui::SameLine();
ImGui::SetNextItemWidth(120);
ImGui::SliderInt("Ambient", &view_settings_.map_ambient_light, 0,
255);
if (view_settings_.map_lighting_enabled) {
ImGui::SameLine();
ImGui::SetNextItemWidth(120);
int intensity = static_cast<int>(view_settings_.server_light_intensity);
if (ImGui::SliderInt("Intensity", &intensity, 0, 255)) {
view_settings_.server_light_intensity = static_cast<uint8_t>(intensity);
}
ImGui::SameLine();
ImGui::TextUnformatted("Color");
ImGui::SameLine();
uint8_t color = view_settings_.server_light_color;
if (UI::LightColorPalettePicker(
"##serverLightColor",
color,
true,
"Server Color: world light color from the Tibia 8-bit palette")) {
view_settings_.server_light_color = color;
}
ImGui::SameLine();
ImGui::SetNextItemWidth(120);
ImGui::SliderInt("Min Ambient", &view_settings_.map_ambient_light, 0, 255);
}
ImGui::Separator();

// Render the map panel with explicit animation ticks
Expand Down
5 changes: 5 additions & 0 deletions ImguiMapEditor/Rendering/Core/IRenderPass.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#pragma once

#include "Domain/ChunkedMap.h"
#include "Domain/Position.h"
#include "Rendering/Animation/AnimationTicks.h"
#include "Rendering/Camera/ViewCamera.h"
#include "Rendering/Frame/RenderState.h"
#include "Rendering/Visibility/VisibleBounds.h"
#include <glm/glm.hpp>
#include <optional>

Check warning on line 10 in ImguiMapEditor/Rendering/Core/IRenderPass.h

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

ImguiMapEditor/Rendering/Core/IRenderPass.h#L10

Include file: <optional> not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace MapEditor {
namespace Services {
Expand Down Expand Up @@ -44,6 +46,9 @@

// View settings (optional, can be nullptr)
const Services::ViewSettings *view_settings;

// RME light-mode floor visibility origin, set from the last map click.
std::optional<Domain::Position> light_visibility_origin;
};

/**
Expand Down
1 change: 1 addition & 0 deletions ImguiMapEditor/Rendering/Frame/RenderState.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class RenderState {
// === State tracking for cache invalidation ===
float last_zoom = 0.0f;
uint8_t last_ambient_light = 255;
uint32_t last_config_hash = 0; // Hash of LightConfig fields affecting lighting

// === Invalidation methods ===

Expand Down
Loading
Loading