Debug: Add mode to sprite dump window to show unoptimised
This commit is contained in:
@@ -3056,6 +3056,7 @@ DEF_CONSOLE_CMD(ConMiscDebug)
|
|||||||
IConsoleHelp(" 2: MDF_ZONING_RS_WATER_FLOOD_STATE");
|
IConsoleHelp(" 2: MDF_ZONING_RS_WATER_FLOOD_STATE");
|
||||||
IConsoleHelp(" 4: MDF_ZONING_RS_TROPIC_ZONE");
|
IConsoleHelp(" 4: MDF_ZONING_RS_TROPIC_ZONE");
|
||||||
IConsoleHelp(" 8: MDF_ZONING_RS_ANIMATED_TILE");
|
IConsoleHelp(" 8: MDF_ZONING_RS_ANIMATED_TILE");
|
||||||
|
IConsoleHelp(" 10: MDF_NEWGRF_SG_SAVE_RAW");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -45,6 +45,7 @@ enum MiscDebugFlags {
|
|||||||
MDF_ZONING_RS_WATER_FLOOD_STATE,
|
MDF_ZONING_RS_WATER_FLOOD_STATE,
|
||||||
MDF_ZONING_RS_TROPIC_ZONE,
|
MDF_ZONING_RS_TROPIC_ZONE,
|
||||||
MDF_ZONING_RS_ANIMATED_TILE,
|
MDF_ZONING_RS_ANIMATED_TILE,
|
||||||
|
MDF_NEWGRF_SG_SAVE_RAW,
|
||||||
};
|
};
|
||||||
extern uint32 _misc_debug_flags;
|
extern uint32 _misc_debug_flags;
|
||||||
|
|
||||||
|
@@ -4216,6 +4216,8 @@ STR_NEWGRF_INSPECT_DUPLICATE :{BLACK}D
|
|||||||
STR_NEWGRF_INSPECT_DUPLICATE_TOOLTIP :{BLACK}Duplicate this window
|
STR_NEWGRF_INSPECT_DUPLICATE_TOOLTIP :{BLACK}Duplicate this window
|
||||||
STR_NEWGRF_INSPECT_SPRITE_DUMP :{BLACK}S
|
STR_NEWGRF_INSPECT_SPRITE_DUMP :{BLACK}S
|
||||||
STR_NEWGRF_INSPECT_SPRITE_DUMP_TOOLTIP :{BLACK}Display current sprite chain
|
STR_NEWGRF_INSPECT_SPRITE_DUMP_TOOLTIP :{BLACK}Display current sprite chain
|
||||||
|
STR_NEWGRF_INSPECT_SPRITE_DUMP_UNOPT :{BLACK}U
|
||||||
|
STR_NEWGRF_INSPECT_SPRITE_DUMP_UNOPT_TOOLTIP :{BLACK}Display sprite groups without any optimisations applied.{}{}Requires reloading NewGRFs if not previously enabled (misc_debug 10).
|
||||||
STR_NEWGRF_INSPECT_SPRITE_DUMP_PANEL_TOOLTIP :{BLACK}Click to highlight sprite group{}Shift+Click to collapse sprite group{}Ctrl+Click to highlight temporary storage register
|
STR_NEWGRF_INSPECT_SPRITE_DUMP_PANEL_TOOLTIP :{BLACK}Click to highlight sprite group{}Shift+Click to collapse sprite group{}Ctrl+Click to highlight temporary storage register
|
||||||
|
|
||||||
STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT :{STRING1} at {HEX}
|
STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT :{STRING1} at {HEX}
|
||||||
|
144
src/newgrf.cpp
144
src/newgrf.cpp
@@ -5544,20 +5544,8 @@ static const CallbackResultSpriteGroup *NewCallbackResultSpriteGroup(uint16 grou
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function to either create a callback or link to a previously
|
static const SpriteGroup *PruneTargetSpriteGroup(const SpriteGroup *result)
|
||||||
* defined spritegroup. */
|
|
||||||
static const SpriteGroup *GetGroupFromGroupID(byte setid, byte type, uint16 groupid)
|
|
||||||
{
|
{
|
||||||
if (HasBit(groupid, 15)) {
|
|
||||||
return NewCallbackResultSpriteGroup(groupid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groupid > MAX_SPRITEGROUP || _cur.spritegroups[groupid] == nullptr) {
|
|
||||||
grfmsg(1, "GetGroupFromGroupID(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty", setid, type, groupid);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SpriteGroup *result = _cur.spritegroups[groupid];
|
|
||||||
if (HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2) || HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2_GROUP_PRUNE)) return result;
|
if (HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2) || HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2_GROUP_PRUNE)) return result;
|
||||||
while (result != nullptr) {
|
while (result != nullptr) {
|
||||||
if (result->type == SGT_DETERMINISTIC) {
|
if (result->type == SGT_DETERMINISTIC) {
|
||||||
@@ -5580,6 +5568,24 @@ static const SpriteGroup *GetGroupFromGroupID(byte setid, byte type, uint16 grou
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper function to either create a callback or link to a previously
|
||||||
|
* defined spritegroup. */
|
||||||
|
static const SpriteGroup *GetGroupFromGroupID(byte setid, byte type, uint16 groupid)
|
||||||
|
{
|
||||||
|
if (HasBit(groupid, 15)) {
|
||||||
|
return NewCallbackResultSpriteGroup(groupid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupid > MAX_SPRITEGROUP || _cur.spritegroups[groupid] == nullptr) {
|
||||||
|
grfmsg(1, "GetGroupFromGroupID(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty", setid, type, groupid);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SpriteGroup *result = _cur.spritegroups[groupid];
|
||||||
|
if (likely(!HasBit(_misc_debug_flags, MDF_NEWGRF_SG_SAVE_RAW))) result = PruneTargetSpriteGroup(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static const SpriteGroup *GetGroupByID(uint16 groupid)
|
static const SpriteGroup *GetGroupByID(uint16 groupid)
|
||||||
{
|
{
|
||||||
const SpriteGroup *result = _cur.spritegroups[groupid];
|
const SpriteGroup *result = _cur.spritegroups[groupid];
|
||||||
@@ -6793,6 +6799,46 @@ static void HandleVarAction2OptimisationPasses()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ProcessDeterministicSpriteGroupRanges(const std::vector<DeterministicSpriteGroupRange> &ranges, std::vector<DeterministicSpriteGroupRange> &ranges_out, const SpriteGroup *default_group)
|
||||||
|
{
|
||||||
|
/* Sort ranges ascending. When ranges overlap, this may required clamping or splitting them */
|
||||||
|
std::vector<uint32> bounds;
|
||||||
|
for (uint i = 0; i < ranges.size(); i++) {
|
||||||
|
bounds.push_back(ranges[i].low);
|
||||||
|
if (ranges[i].high != UINT32_MAX) bounds.push_back(ranges[i].high + 1);
|
||||||
|
}
|
||||||
|
std::sort(bounds.begin(), bounds.end());
|
||||||
|
bounds.erase(std::unique(bounds.begin(), bounds.end()), bounds.end());
|
||||||
|
|
||||||
|
std::vector<const SpriteGroup *> target;
|
||||||
|
for (uint j = 0; j < bounds.size(); ++j) {
|
||||||
|
uint32 v = bounds[j];
|
||||||
|
const SpriteGroup *t = default_group;
|
||||||
|
for (uint i = 0; i < ranges.size(); i++) {
|
||||||
|
if (ranges[i].low <= v && v <= ranges[i].high) {
|
||||||
|
t = ranges[i].group;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target.push_back(t);
|
||||||
|
}
|
||||||
|
assert(target.size() == bounds.size());
|
||||||
|
|
||||||
|
for (uint j = 0; j < bounds.size(); ) {
|
||||||
|
if (target[j] != default_group) {
|
||||||
|
DeterministicSpriteGroupRange &r = ranges_out.emplace_back();
|
||||||
|
r.group = target[j];
|
||||||
|
r.low = bounds[j];
|
||||||
|
while (j < bounds.size() && target[j] == r.group) {
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
r.high = j < bounds.size() ? bounds[j] - 1 : UINT32_MAX;
|
||||||
|
} else {
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Action 0x02 */
|
/* Action 0x02 */
|
||||||
static void NewSpriteGroup(ByteReader *buf)
|
static void NewSpriteGroup(ByteReader *buf)
|
||||||
{
|
{
|
||||||
@@ -6849,6 +6895,11 @@ static void NewSpriteGroup(ByteReader *buf)
|
|||||||
case 2: group->size = DSG_SIZE_DWORD; varsize = 4; break;
|
case 2: group->size = DSG_SIZE_DWORD; varsize = 4; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeterministicSpriteGroupShadowCopy *shadow = nullptr;
|
||||||
|
if (unlikely(HasBit(_misc_debug_flags, MDF_NEWGRF_SG_SAVE_RAW))) {
|
||||||
|
shadow = &(_deterministic_sg_shadows[group]);
|
||||||
|
}
|
||||||
|
|
||||||
VarAction2OptimiseState va2_opt_state;
|
VarAction2OptimiseState va2_opt_state;
|
||||||
/* The initial value is always the constant 0 */
|
/* The initial value is always the constant 0 */
|
||||||
va2_opt_state.inference = VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO | VA2AIF_HAVE_CONSTANT;
|
va2_opt_state.inference = VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO | VA2AIF_HAVE_CONSTANT;
|
||||||
@@ -6904,6 +6955,11 @@ static void NewSpriteGroup(ByteReader *buf)
|
|||||||
adjust.add_val = 0;
|
adjust.add_val = 0;
|
||||||
adjust.divmod_val = 0;
|
adjust.divmod_val = 0;
|
||||||
}
|
}
|
||||||
|
if (unlikely(shadow != nullptr)) {
|
||||||
|
shadow->adjusts.push_back(adjust);
|
||||||
|
/* Pruning was turned off so that the unpruned target could be saved in the shadow, prune now */
|
||||||
|
if (adjust.subroutine != nullptr) adjust.subroutine = PruneTargetSpriteGroup(adjust.subroutine);
|
||||||
|
}
|
||||||
|
|
||||||
OptimiseVarAction2Adjust(va2_opt_state, feature, varsize, group, adjust);
|
OptimiseVarAction2Adjust(va2_opt_state, feature, varsize, group, adjust);
|
||||||
|
|
||||||
@@ -6919,46 +6975,23 @@ static void NewSpriteGroup(ByteReader *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
group->default_group = GetGroupFromGroupID(setid, type, buf->ReadWord());
|
group->default_group = GetGroupFromGroupID(setid, type, buf->ReadWord());
|
||||||
|
|
||||||
|
if (unlikely(shadow != nullptr)) {
|
||||||
|
ProcessDeterministicSpriteGroupRanges(ranges, shadow->ranges, group->default_group);
|
||||||
|
shadow->default_group = group->default_group;
|
||||||
|
|
||||||
|
/* Pruning was turned off so that the unpruned targets could be saved in the shadow ranges, prune now */
|
||||||
|
for (DeterministicSpriteGroupRange &range : ranges) {
|
||||||
|
range.group = PruneTargetSpriteGroup(range.group);
|
||||||
|
}
|
||||||
|
group->default_group = PruneTargetSpriteGroup(group->default_group);
|
||||||
|
}
|
||||||
|
|
||||||
group->error_group = ranges.size() > 0 ? ranges[0].group : group->default_group;
|
group->error_group = ranges.size() > 0 ? ranges[0].group : group->default_group;
|
||||||
/* nvar == 0 is a special case -- we turn our value into a callback result */
|
/* nvar == 0 is a special case -- we turn our value into a callback result */
|
||||||
group->calculated_result = ranges.size() == 0;
|
group->calculated_result = ranges.size() == 0;
|
||||||
|
|
||||||
/* Sort ranges ascending. When ranges overlap, this may required clamping or splitting them */
|
ProcessDeterministicSpriteGroupRanges(ranges, group->ranges, group->default_group);
|
||||||
std::vector<uint32> bounds;
|
|
||||||
for (uint i = 0; i < ranges.size(); i++) {
|
|
||||||
bounds.push_back(ranges[i].low);
|
|
||||||
if (ranges[i].high != UINT32_MAX) bounds.push_back(ranges[i].high + 1);
|
|
||||||
}
|
|
||||||
std::sort(bounds.begin(), bounds.end());
|
|
||||||
bounds.erase(std::unique(bounds.begin(), bounds.end()), bounds.end());
|
|
||||||
|
|
||||||
std::vector<const SpriteGroup *> target;
|
|
||||||
for (uint j = 0; j < bounds.size(); ++j) {
|
|
||||||
uint32 v = bounds[j];
|
|
||||||
const SpriteGroup *t = group->default_group;
|
|
||||||
for (uint i = 0; i < ranges.size(); i++) {
|
|
||||||
if (ranges[i].low <= v && v <= ranges[i].high) {
|
|
||||||
t = ranges[i].group;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target.push_back(t);
|
|
||||||
}
|
|
||||||
assert(target.size() == bounds.size());
|
|
||||||
|
|
||||||
for (uint j = 0; j < bounds.size(); ) {
|
|
||||||
if (target[j] != group->default_group) {
|
|
||||||
DeterministicSpriteGroupRange &r = group->ranges.emplace_back();
|
|
||||||
r.group = target[j];
|
|
||||||
r.low = bounds[j];
|
|
||||||
while (j < bounds.size() && target[j] == r.group) {
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
r.high = j < bounds.size() ? bounds[j] - 1 : UINT32_MAX;
|
|
||||||
} else {
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OptimiseVarAction2DeterministicSpriteGroup(va2_opt_state, feature, varsize, group);
|
OptimiseVarAction2DeterministicSpriteGroup(va2_opt_state, feature, varsize, group);
|
||||||
break;
|
break;
|
||||||
@@ -6994,6 +7027,16 @@ static void NewSpriteGroup(ByteReader *buf)
|
|||||||
group->groups.push_back(GetGroupFromGroupID(setid, type, buf->ReadWord()));
|
group->groups.push_back(GetGroupFromGroupID(setid, type, buf->ReadWord()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely(HasBit(_misc_debug_flags, MDF_NEWGRF_SG_SAVE_RAW))) {
|
||||||
|
RandomizedSpriteGroupShadowCopy *shadow = &(_randomized_sg_shadows[group]);
|
||||||
|
shadow->groups = group->groups;
|
||||||
|
|
||||||
|
/* Pruning was turned off so that the unpruned targets could be saved in the shadow groups, prune now */
|
||||||
|
for (const SpriteGroup *&group : group->groups) {
|
||||||
|
group = PruneTargetSpriteGroup(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11289,6 +11332,9 @@ void ResetNewGRFData()
|
|||||||
InitializeSoundPool();
|
InitializeSoundPool();
|
||||||
_spritegroup_pool.CleanPool();
|
_spritegroup_pool.CleanPool();
|
||||||
_callback_result_cache.clear();
|
_callback_result_cache.clear();
|
||||||
|
_deterministic_sg_shadows.clear();
|
||||||
|
_randomized_sg_shadows.clear();
|
||||||
|
_grfs_loaded_with_sg_shadow_enable = HasBit(_misc_debug_flags, MDF_NEWGRF_SG_SAVE_RAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#include "vehicle_gui.h"
|
#include "vehicle_gui.h"
|
||||||
#include "zoom_func.h"
|
#include "zoom_func.h"
|
||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
|
#include "debug_settings.h"
|
||||||
|
|
||||||
#include "engine_base.h"
|
#include "engine_base.h"
|
||||||
#include "industry.h"
|
#include "industry.h"
|
||||||
@@ -317,6 +318,7 @@ struct NewGRFInspectWindow : Window {
|
|||||||
bool auto_refresh = false;
|
bool auto_refresh = false;
|
||||||
bool log_console = false;
|
bool log_console = false;
|
||||||
bool sprite_dump = false;
|
bool sprite_dump = false;
|
||||||
|
bool sprite_dump_unopt = false;
|
||||||
|
|
||||||
uint32 extra_info_flags = 0;
|
uint32 extra_info_flags = 0;
|
||||||
btree::btree_map<int, uint> extra_info_click_flag_toggles;
|
btree::btree_map<int, uint> extra_info_click_flag_toggles;
|
||||||
@@ -389,7 +391,10 @@ struct NewGRFInspectWindow : Window {
|
|||||||
{
|
{
|
||||||
this->CreateNestedTree();
|
this->CreateNestedTree();
|
||||||
this->vscroll = this->GetScrollbar(WID_NGRFI_SCROLLBAR);
|
this->vscroll = this->GetScrollbar(WID_NGRFI_SCROLLBAR);
|
||||||
this->GetWidget<NWidgetStacked>(WID_NGRFI_SPRITE_DUMP_SEL)->SetDisplayedPlane(GetFeatureHelper(wno)->ShowSpriteDumpButton(::GetFeatureIndex(wno)) ? 0 : SZSP_NONE);
|
bool show_sprite_dump_button = GetFeatureHelper(wno)->ShowSpriteDumpButton(::GetFeatureIndex(wno));
|
||||||
|
this->GetWidget<NWidgetStacked>(WID_NGRFI_SPRITE_DUMP_SEL)->SetDisplayedPlane(show_sprite_dump_button ? 0 : SZSP_NONE);
|
||||||
|
this->GetWidget<NWidgetStacked>(WID_NGRFI_SPRITE_DUMP_UNOPT_SEL)->SetDisplayedPlane(show_sprite_dump_button ? 0 : SZSP_NONE);
|
||||||
|
this->SetWidgetDisabledState(WID_NGRFI_SPRITE_DUMP_UNOPT, true);
|
||||||
this->FinishInitNested(wno);
|
this->FinishInitNested(wno);
|
||||||
|
|
||||||
this->vscroll->SetCount(0);
|
this->vscroll->SetCount(0);
|
||||||
@@ -535,6 +540,7 @@ struct NewGRFInspectWindow : Window {
|
|||||||
};
|
};
|
||||||
const_cast<NewGRFInspectWindow *>(this)->sprite_group_lines.clear();
|
const_cast<NewGRFInspectWindow *>(this)->sprite_group_lines.clear();
|
||||||
if (this->sprite_dump) {
|
if (this->sprite_dump) {
|
||||||
|
SpriteGroupDumper::use_shadows = this->sprite_dump_unopt;
|
||||||
bool collapsed = false;
|
bool collapsed = false;
|
||||||
const SpriteGroup *collapse_group = nullptr;
|
const SpriteGroup *collapse_group = nullptr;
|
||||||
uint collapse_lines = 0;
|
uint collapse_lines = 0;
|
||||||
@@ -572,6 +578,7 @@ struct NewGRFInspectWindow : Window {
|
|||||||
if (highlight_tag != 0 && this->selected_highlight_tag == highlight_tag) colour = TC_YELLOW;
|
if (highlight_tag != 0 && this->selected_highlight_tag == highlight_tag) colour = TC_YELLOW;
|
||||||
::DrawString(r.left + LEFT_OFFSET, r.right - RIGHT_OFFSET, r.top + TOP_OFFSET + (scroll_offset * this->resize.step_height), buf, colour);
|
::DrawString(r.left + LEFT_OFFSET, r.right - RIGHT_OFFSET, r.top + TOP_OFFSET + (scroll_offset * this->resize.step_height), buf, colour);
|
||||||
});
|
});
|
||||||
|
SpriteGroupDumper::use_shadows = false;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
NewGRFInspectWindow *this_mutable = const_cast<NewGRFInspectWindow *>(this);
|
NewGRFInspectWindow *this_mutable = const_cast<NewGRFInspectWindow *>(this);
|
||||||
@@ -731,6 +738,20 @@ struct NewGRFInspectWindow : Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UnOptimisedSpriteDumpOK() const
|
||||||
|
{
|
||||||
|
if (_grfs_loaded_with_sg_shadow_enable) return true;
|
||||||
|
|
||||||
|
if (_networking && !_network_server) return false;
|
||||||
|
|
||||||
|
extern uint NetworkClientCount();
|
||||||
|
if (_networking && NetworkClientCount() > 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void OnClick(Point pt, int widget, int click_count) override
|
void OnClick(Point pt, int widget, int click_count) override
|
||||||
{
|
{
|
||||||
switch (widget) {
|
switch (widget) {
|
||||||
@@ -847,8 +868,34 @@ struct NewGRFInspectWindow : Window {
|
|||||||
case WID_NGRFI_SPRITE_DUMP: {
|
case WID_NGRFI_SPRITE_DUMP: {
|
||||||
this->sprite_dump = !this->sprite_dump;
|
this->sprite_dump = !this->sprite_dump;
|
||||||
this->SetWidgetLoweredState(WID_NGRFI_SPRITE_DUMP, this->sprite_dump);
|
this->SetWidgetLoweredState(WID_NGRFI_SPRITE_DUMP, this->sprite_dump);
|
||||||
|
this->SetWidgetDisabledState(WID_NGRFI_SPRITE_DUMP_UNOPT, !this->sprite_dump || !UnOptimisedSpriteDumpOK());
|
||||||
this->GetWidget<NWidgetCore>(WID_NGRFI_MAINPANEL)->SetToolTip(this->sprite_dump ? STR_NEWGRF_INSPECT_SPRITE_DUMP_PANEL_TOOLTIP : STR_NULL);
|
this->GetWidget<NWidgetCore>(WID_NGRFI_MAINPANEL)->SetToolTip(this->sprite_dump ? STR_NEWGRF_INSPECT_SPRITE_DUMP_PANEL_TOOLTIP : STR_NULL);
|
||||||
this->SetWidgetDirty(WID_NGRFI_SPRITE_DUMP);
|
this->SetWidgetDirty(WID_NGRFI_SPRITE_DUMP);
|
||||||
|
this->SetWidgetDirty(WID_NGRFI_SPRITE_DUMP_UNOPT);
|
||||||
|
this->SetWidgetDirty(WID_NGRFI_MAINPANEL);
|
||||||
|
this->SetWidgetDirty(WID_NGRFI_SCROLLBAR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_NGRFI_SPRITE_DUMP_UNOPT: {
|
||||||
|
if (!this->sprite_dump_unopt) {
|
||||||
|
if (!UnOptimisedSpriteDumpOK()) {
|
||||||
|
this->SetWidgetDisabledState(WID_NGRFI_SPRITE_DUMP_UNOPT, true);
|
||||||
|
this->SetWidgetDirty(WID_NGRFI_SPRITE_DUMP_UNOPT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!_grfs_loaded_with_sg_shadow_enable) {
|
||||||
|
SetBit(_misc_debug_flags, MDF_NEWGRF_SG_SAVE_RAW);
|
||||||
|
|
||||||
|
ReloadNewGRFData();
|
||||||
|
|
||||||
|
extern void PostCheckNewGRFLoadWarnings();
|
||||||
|
PostCheckNewGRFLoadWarnings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->sprite_dump_unopt = !this->sprite_dump_unopt;
|
||||||
|
this->SetWidgetLoweredState(WID_NGRFI_SPRITE_DUMP_UNOPT, this->sprite_dump_unopt);
|
||||||
|
this->SetWidgetDirty(WID_NGRFI_SPRITE_DUMP_UNOPT);
|
||||||
this->SetWidgetDirty(WID_NGRFI_MAINPANEL);
|
this->SetWidgetDirty(WID_NGRFI_MAINPANEL);
|
||||||
this->SetWidgetDirty(WID_NGRFI_SCROLLBAR);
|
this->SetWidgetDirty(WID_NGRFI_SCROLLBAR);
|
||||||
break;
|
break;
|
||||||
@@ -904,6 +951,9 @@ static const NWidgetPart _nested_newgrf_inspect_chain_widgets[] = {
|
|||||||
NWidget(NWID_HORIZONTAL),
|
NWidget(NWID_HORIZONTAL),
|
||||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_NGRFI_CAPTION), SetDataTip(STR_NEWGRF_INSPECT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
NWidget(WWT_CAPTION, COLOUR_GREY, WID_NGRFI_CAPTION), SetDataTip(STR_NEWGRF_INSPECT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||||
|
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NGRFI_SPRITE_DUMP_UNOPT_SEL),
|
||||||
|
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_NGRFI_SPRITE_DUMP_UNOPT), SetDataTip(STR_NEWGRF_INSPECT_SPRITE_DUMP_UNOPT, STR_NEWGRF_INSPECT_SPRITE_DUMP_UNOPT_TOOLTIP),
|
||||||
|
EndContainer(),
|
||||||
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NGRFI_SPRITE_DUMP_SEL),
|
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NGRFI_SPRITE_DUMP_SEL),
|
||||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_NGRFI_SPRITE_DUMP), SetDataTip(STR_NEWGRF_INSPECT_SPRITE_DUMP, STR_NEWGRF_INSPECT_SPRITE_DUMP_TOOLTIP),
|
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_NGRFI_SPRITE_DUMP), SetDataTip(STR_NEWGRF_INSPECT_SPRITE_DUMP, STR_NEWGRF_INSPECT_SPRITE_DUMP_TOOLTIP),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
@@ -935,6 +985,9 @@ static const NWidgetPart _nested_newgrf_inspect_widgets[] = {
|
|||||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_NGRFI_CAPTION), SetDataTip(STR_NEWGRF_INSPECT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
NWidget(WWT_CAPTION, COLOUR_GREY, WID_NGRFI_CAPTION), SetDataTip(STR_NEWGRF_INSPECT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NGRFI_PARENT), SetDataTip(STR_NEWGRF_INSPECT_PARENT_BUTTON, STR_NEWGRF_INSPECT_PARENT_TOOLTIP),
|
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NGRFI_PARENT), SetDataTip(STR_NEWGRF_INSPECT_PARENT_BUTTON, STR_NEWGRF_INSPECT_PARENT_TOOLTIP),
|
||||||
|
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NGRFI_SPRITE_DUMP_UNOPT_SEL),
|
||||||
|
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_NGRFI_SPRITE_DUMP_UNOPT), SetDataTip(STR_NEWGRF_INSPECT_SPRITE_DUMP_UNOPT, STR_NEWGRF_INSPECT_SPRITE_DUMP_UNOPT_TOOLTIP),
|
||||||
|
EndContainer(),
|
||||||
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NGRFI_SPRITE_DUMP_SEL),
|
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NGRFI_SPRITE_DUMP_SEL),
|
||||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_NGRFI_SPRITE_DUMP), SetDataTip(STR_NEWGRF_INSPECT_SPRITE_DUMP, STR_NEWGRF_INSPECT_SPRITE_DUMP_TOOLTIP),
|
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_NGRFI_SPRITE_DUMP), SetDataTip(STR_NEWGRF_INSPECT_SPRITE_DUMP, STR_NEWGRF_INSPECT_SPRITE_DUMP_TOOLTIP),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
|
@@ -26,6 +26,10 @@ INSTANTIATE_POOL_METHODS(SpriteGroup)
|
|||||||
|
|
||||||
TemporaryStorageArray<int32, 0x110> _temp_store;
|
TemporaryStorageArray<int32, 0x110> _temp_store;
|
||||||
|
|
||||||
|
std::map<const DeterministicSpriteGroup *, DeterministicSpriteGroupShadowCopy> _deterministic_sg_shadows;
|
||||||
|
std::map<const RandomizedSpriteGroup *, RandomizedSpriteGroupShadowCopy> _randomized_sg_shadows;
|
||||||
|
bool _grfs_loaded_with_sg_shadow_enable = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ResolverObject (re)entry point.
|
* ResolverObject (re)entry point.
|
||||||
@@ -702,6 +706,8 @@ static char *GetAdjustOperationName(char *str, const char *last, DeterministicSp
|
|||||||
return str + seprintf(str, last, "\?\?\?(0x%X)", operation);
|
return str + seprintf(str, last, "\?\?\?(0x%X)", operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SpriteGroupDumper::use_shadows = false;
|
||||||
|
|
||||||
void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint flags)
|
void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint flags)
|
||||||
{
|
{
|
||||||
uint32 highlight_tag = 0;
|
uint32 highlight_tag = 0;
|
||||||
@@ -748,8 +754,22 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint
|
|||||||
}
|
}
|
||||||
case SGT_DETERMINISTIC: {
|
case SGT_DETERMINISTIC: {
|
||||||
const DeterministicSpriteGroup *dsg = (const DeterministicSpriteGroup*)sg;
|
const DeterministicSpriteGroup *dsg = (const DeterministicSpriteGroup*)sg;
|
||||||
if (padding == 0 && !dsg->calculated_result && dsg->default_group != nullptr) {
|
|
||||||
this->top_default_group = dsg->default_group;
|
const SpriteGroup *default_group = dsg->default_group;
|
||||||
|
const std::vector<DeterministicSpriteGroupAdjust> *adjusts = &(dsg->adjusts);
|
||||||
|
const std::vector<DeterministicSpriteGroupRange> *ranges = &(dsg->ranges);
|
||||||
|
|
||||||
|
if (SpriteGroupDumper::use_shadows) {
|
||||||
|
auto iter = _deterministic_sg_shadows.find(dsg);
|
||||||
|
if (iter != _deterministic_sg_shadows.end()) {
|
||||||
|
default_group = iter->second.default_group;
|
||||||
|
adjusts = &(iter->second.adjusts);
|
||||||
|
ranges = &(iter->second.ranges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding == 0 && !dsg->calculated_result && default_group != nullptr) {
|
||||||
|
this->top_default_group = default_group;
|
||||||
}
|
}
|
||||||
if (dsg == this->top_default_group && !(padding == 4 && (flags & SGDF_DEFAULT))) {
|
if (dsg == this->top_default_group && !(padding == 4 && (flags & SGDF_DEFAULT))) {
|
||||||
seprintf(this->buffer, lastof(this->buffer), "%*sTOP LEVEL DEFAULT GROUP: Deterministic (%s, %s), [%u]",
|
seprintf(this->buffer, lastof(this->buffer), "%*sTOP LEVEL DEFAULT GROUP: Deterministic (%s, %s), [%u]",
|
||||||
@@ -769,7 +789,7 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint
|
|||||||
print();
|
print();
|
||||||
emit_start();
|
emit_start();
|
||||||
padding += 2;
|
padding += 2;
|
||||||
for (const auto &adjust : dsg->adjusts) {
|
for (const auto &adjust : (*adjusts)) {
|
||||||
char *p = this->buffer;
|
char *p = this->buffer;
|
||||||
if (adjust.variable == 0x7D) {
|
if (adjust.variable == 0x7D) {
|
||||||
/* Temp storage load */
|
/* Temp storage load */
|
||||||
@@ -832,27 +852,37 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint
|
|||||||
seprintf(this->buffer, lastof(this->buffer), "%*scalculated_result", padding, "");
|
seprintf(this->buffer, lastof(this->buffer), "%*scalculated_result", padding, "");
|
||||||
print();
|
print();
|
||||||
} else {
|
} else {
|
||||||
for (const auto &range : dsg->ranges) {
|
for (const auto &range : (*ranges)) {
|
||||||
seprintf(this->buffer, lastof(this->buffer), "%*srange: %X -> %X", padding, "", range.low, range.high);
|
seprintf(this->buffer, lastof(this->buffer), "%*srange: %X -> %X", padding, "", range.low, range.high);
|
||||||
print();
|
print();
|
||||||
this->DumpSpriteGroup(range.group, padding + 2, 0);
|
this->DumpSpriteGroup(range.group, padding + 2, 0);
|
||||||
}
|
}
|
||||||
if (dsg->default_group != nullptr) {
|
if (default_group != nullptr) {
|
||||||
seprintf(this->buffer, lastof(this->buffer), "%*sdefault", padding, "");
|
seprintf(this->buffer, lastof(this->buffer), "%*sdefault", padding, "");
|
||||||
print();
|
print();
|
||||||
this->DumpSpriteGroup(dsg->default_group, padding + 2, SGDF_DEFAULT);
|
this->DumpSpriteGroup(default_group, padding + 2, SGDF_DEFAULT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SGT_RANDOMIZED: {
|
case SGT_RANDOMIZED: {
|
||||||
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
|
const RandomizedSpriteGroup *rsg = (const RandomizedSpriteGroup*)sg;
|
||||||
|
|
||||||
|
const std::vector<const SpriteGroup *> *groups = &(rsg->groups);
|
||||||
|
|
||||||
|
if (SpriteGroupDumper::use_shadows) {
|
||||||
|
auto iter = _randomized_sg_shadows.find(rsg);
|
||||||
|
if (iter != _randomized_sg_shadows.end()) {
|
||||||
|
groups = &(iter->second.groups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
seprintf(this->buffer, lastof(this->buffer), "%*sRandom (%s, %s, triggers: %X, count: %X, lowest_randbit: %X, groups: %u) [%u]",
|
seprintf(this->buffer, lastof(this->buffer), "%*sRandom (%s, %s, triggers: %X, count: %X, lowest_randbit: %X, groups: %u) [%u]",
|
||||||
padding, "", _sg_scope_names[rsg->var_scope], rsg->cmp_mode == RSG_CMP_ANY ? "ANY" : "ALL",
|
padding, "", _sg_scope_names[rsg->var_scope], rsg->cmp_mode == RSG_CMP_ANY ? "ANY" : "ALL",
|
||||||
rsg->triggers, rsg->count, rsg->lowest_randbit, (uint)rsg->groups.size(), rsg->nfo_line);
|
rsg->triggers, rsg->count, rsg->lowest_randbit, (uint)rsg->groups.size(), rsg->nfo_line);
|
||||||
print();
|
print();
|
||||||
emit_start();
|
emit_start();
|
||||||
for (const auto &group : rsg->groups) {
|
for (const auto &group : (*groups)) {
|
||||||
this->DumpSpriteGroup(group, padding + 2, 0);
|
this->DumpSpriteGroup(group, padding + 2, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include "3rdparty/cpp-btree/btree_set.h"
|
#include "3rdparty/cpp-btree/btree_set.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of a so-called newgrf "register".
|
* Gets the value of a so-called newgrf "register".
|
||||||
* @param i index of the register
|
* @param i index of the register
|
||||||
@@ -360,6 +362,12 @@ enum DeterministicSpriteGroupFlags : uint8 {
|
|||||||
};
|
};
|
||||||
DECLARE_ENUM_AS_BIT_SET(DeterministicSpriteGroupFlags)
|
DECLARE_ENUM_AS_BIT_SET(DeterministicSpriteGroupFlags)
|
||||||
|
|
||||||
|
struct DeterministicSpriteGroupShadowCopy {
|
||||||
|
std::vector<DeterministicSpriteGroupAdjust> adjusts;
|
||||||
|
std::vector<DeterministicSpriteGroupRange> ranges;
|
||||||
|
const SpriteGroup *default_group;
|
||||||
|
};
|
||||||
|
|
||||||
struct DeterministicSpriteGroup : SpriteGroup {
|
struct DeterministicSpriteGroup : SpriteGroup {
|
||||||
DeterministicSpriteGroup() : SpriteGroup(SGT_DETERMINISTIC) {}
|
DeterministicSpriteGroup() : SpriteGroup(SGT_DETERMINISTIC) {}
|
||||||
|
|
||||||
@@ -387,6 +395,10 @@ enum RandomizedSpriteGroupCompareMode {
|
|||||||
RSG_CMP_ALL,
|
RSG_CMP_ALL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RandomizedSpriteGroupShadowCopy {
|
||||||
|
std::vector<const SpriteGroup *> groups;
|
||||||
|
};
|
||||||
|
|
||||||
struct RandomizedSpriteGroup : SpriteGroup {
|
struct RandomizedSpriteGroup : SpriteGroup {
|
||||||
RandomizedSpriteGroup() : SpriteGroup(SGT_RANDOMIZED) {}
|
RandomizedSpriteGroup() : SpriteGroup(SGT_RANDOMIZED) {}
|
||||||
|
|
||||||
@@ -406,6 +418,9 @@ protected:
|
|||||||
const SpriteGroup *Resolve(ResolverObject &object) const override;
|
const SpriteGroup *Resolve(ResolverObject &object) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern std::map<const DeterministicSpriteGroup *, DeterministicSpriteGroupShadowCopy> _deterministic_sg_shadows;
|
||||||
|
extern std::map<const RandomizedSpriteGroup *, RandomizedSpriteGroupShadowCopy> _randomized_sg_shadows;
|
||||||
|
extern bool _grfs_loaded_with_sg_shadow_enable;
|
||||||
|
|
||||||
/* This contains a callback result. A failed callback has a value of
|
/* This contains a callback result. A failed callback has a value of
|
||||||
* CALLBACK_FAILED */
|
* CALLBACK_FAILED */
|
||||||
@@ -631,6 +646,8 @@ enum DumpSpriteGroupPrintOp {
|
|||||||
using DumpSpriteGroupPrinter = std::function<void(const SpriteGroup *, DumpSpriteGroupPrintOp, uint32, const char *)>;
|
using DumpSpriteGroupPrinter = std::function<void(const SpriteGroup *, DumpSpriteGroupPrintOp, uint32, const char *)>;
|
||||||
|
|
||||||
struct SpriteGroupDumper {
|
struct SpriteGroupDumper {
|
||||||
|
static bool use_shadows;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
DumpSpriteGroupPrinter print_fn;
|
DumpSpriteGroupPrinter print_fn;
|
||||||
|
@@ -24,6 +24,8 @@ enum NewGRFInspectWidgets {
|
|||||||
WID_NGRFI_DUPLICATE, ///< Duplicate window
|
WID_NGRFI_DUPLICATE, ///< Duplicate window
|
||||||
WID_NGRFI_SPRITE_DUMP, ///< Dump current sprite group
|
WID_NGRFI_SPRITE_DUMP, ///< Dump current sprite group
|
||||||
WID_NGRFI_SPRITE_DUMP_SEL, ///< Selection widget for WID_NGRFI_SPRITE_DUMP
|
WID_NGRFI_SPRITE_DUMP_SEL, ///< Selection widget for WID_NGRFI_SPRITE_DUMP
|
||||||
|
WID_NGRFI_SPRITE_DUMP_UNOPT, ///< Dump unoptimised sprite group
|
||||||
|
WID_NGRFI_SPRITE_DUMP_UNOPT_SEL, ///< Selection widget for WID_NGRFI_SPRITE_DUMP_UNOPT
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Widgets of the #SpriteAlignerWindow class. */
|
/** Widgets of the #SpriteAlignerWindow class. */
|
||||||
|
Reference in New Issue
Block a user