Repository navigation
Conversation
Embed per-monitor DPI awareness and maintain the verified OGRE 13.6.5 renderer patch required for context-safe window replacement, runtime GL options and correct fullscreen client geometry. Validation: clean Release build, DPI and 3440x1440 fullscreen probes, three GL3Plus variants and the patch reverse check passed; version 0.7.1 remains unchanged because this is unreleased work and the project has no changelog.
Apply display, input, audio, gameplay, minimap, shadow and negotiated nickname changes to the running session while preserving rollback for failed window or input transitions and keeping the 3440x1440 navigation visible. Validation: clean Release and Debug builds, packet tests, DPI, layout and GL3Plus probes passed; the user confirmed the reported resolution, fullscreen, cursor, flicker and navigation failures are fixed. Version 0.7.1 remains unchanged because this is unreleased work and the project has no changelog.
The spells tab put its ten buttons in a single row of 60 pixel squares running out to x=700. The pane they live in is the window width minus the 200 pixels of minimap, so at the 800 wide minimum window it is 600 pixels across, and the last two spells, Weakness and the Eye of Evil, hung past its right edge where they could be neither seen nor clicked. Only a window at least 900 wide showed the whole row, and nothing said so. The rooms tab solved the same problem long ago: two rows of 40 pixel buttons. The spells tab now uses the same shape, five spells to a row, ending at x=300 with room to spare at any size the game accepts. The cooldown bar inside each button now covers exactly its button too, instead of overhanging 20 pixels on both sides, which with narrower buttons would have bled half way across the neighbours. The rooms tab had the tail of the same bug: the temple and portal buttons the editor uses sat at x=570 to 690, past the same edge. They join the end of the second row instead. (cherry picked from commit 10db1cb)
Remove depleted fills and borders while preserving surviving health segments and the centre. Update player guidance and add the 200-check texture regression. No release version or protocol change is needed; the existing PR documents this unreleased feature correction.
# Conflicts: # source/entities/Creature.cpp
Replace the hardcoded dependency, Python and Visual Studio locations in the Windows scripts with a shared windows-paths.ps1. The defaults derive from the current user profile and can be overridden with OD_DEPS_ROOT, OD_PYTHON_ROOT and OD_VS_PATH.
Replace the auto declarations introduced by this branch with explicit types, as requested in issue tomluchowski#42 and required by CLAUDE.md. No behavioural change.
|
Comment from the original #108 by @tomluchowski (source):
|
|
Comment from the original #108 by @tomluchowski (source):
|
|
Comment from the original #108 by @tomluchowski (source):
|
|
Comment from the original #108 by @tomluchowski (source): |
|
Comment from the original #108 by @tomluchowski (source):
|
| continue; | ||
| renderer->setConfigOption(option.first, option.second); | ||
| } | ||
|
|
There was a problem hiding this comment.
strange that FULL_SCREEN and VIDEO_MODE have to be treated separatly , but that's a digression
There was a problem hiding this comment.
In this code the two options are simply applied first and explicitly (FULL_SCREEN, then VIDEO_MODE), and the loop after them applies every other saved option while skipping those two. The code does not document why this order is needed; it was settled by testing on the fullscreen/resolution switching cases, so I do not want to claim a deeper reason here.
| { | ||
| replacementWindow->setFullscreen(false, description.width, description.height); | ||
| replacementWindow->setFullscreen(true, description.width, description.height); | ||
| } |
There was a problem hiding this comment.
Intresting , that setFullscreen has to be done like that , first as 'false' , then as 'true'
There was a problem hiding this comment.
Yes, that is what the code does: when the old window was fullscreen and the new configuration is fullscreen too, the replacement window gets setFullscreen(false) followed by setFullscreen(true) with the target size. It is only done in that case (fullscreen to fullscreen); the code does not document the reason for the two steps, so I am not adding a claim about it.
| root.destroyRenderTarget(mWindow); | ||
| mWindow = mPrimaryWindow; | ||
| } | ||
| Ogre::WindowEventUtilities::_removeRenderWindow(mPrimaryWindow); |
There was a problem hiding this comment.
My editor says methods from Ogre::WindowEventUtilities are deprecated .......and I trust it ;)
Doesn't sound optimistic if we want to move up later to higher Ogre ( say 14 ;))
There was a problem hiding this comment.
Fair point. The base branch already uses Ogre::WindowEventUtilities (addWindowEventListener/removeWindowEventListener in ODFrameListener.cpp, _addRenderWindow and messagePump in ODApplication.cpp); this PR only reuses the same calls for the replacement window. A move to a newer Ogre would have to replace that windowing/event code as a whole, so it is out of scope for this change.
| const double rightIntensity = mouseOverGui ? 0.0 : getAutoscrollIntensity(arg.state.X.abs, arg.state.width, false); | ||
| const double topIntensity = mouseOverGui ? 0.0 : getAutoscrollIntensity(arg.state.Y.abs, arg.state.height, true); | ||
| const double bottomIntensity = mouseOverGui ? 0.0 : getAutoscrollIntensity(arg.state.Y.abs, arg.state.height, false); | ||
|
|
There was a problem hiding this comment.
OKI this commit is NO NO , because
const double bottomIntensity = mouseOverGui ? 0.0 : getAutoscrollIntensity(arg.state.Y.abs, arg.state.height, false);
This will never trigger bottomIntensity to be above 0, because when pointing downwards in our game , you have always mouse over GUI !!!
There was a problem hiding this comment.
Fixed: the bottom edge is no longer blocked by the GUI hit test, so it scrolls again (left, right and top keep the check). Rokk001@da16d6d
| bool playButtonClickSound(const CEGUI::EventArgs& e = {}); | ||
|
|
||
| private: | ||
| struct WindowScaleData |
There was a problem hiding this comment.
I know those are private parts of a class, but a comment or two on what's what would be welcomed.
There was a problem hiding this comment.
Added short comments to the private members and the WindowScaleData struct of Gui: Rokk001@4599865 (follow-up fixing the Doxygen tags: Rokk001@d01fd56)
| const float LAYOUT_DESIGN_HEIGHT = 768.0f; | ||
| const float FONT_DESIGN_WIDTH = 800.0f; | ||
| const float FONT_DESIGN_HEIGHT = 600.0f; | ||
|
|
There was a problem hiding this comment.
So you decided to represent the widgets only by their pixel sizes -- the offset value.
That is when scaling CEGUI::UDim "Scale" is preserved, Offset is scaled.
Strange that CEGUI does not offer that functionality, and we have to code it by hand.
There was a problem hiding this comment.
Ahh not only by offset , "SettingsWindow" seems to be a honourable counterexample.....
There was a problem hiding this comment.
The Scale part of a UDim is indeed used by the layouts, but the scaling code only ever changes the Offset. scaleDimension multiplies d_offset and leaves d_scale unchanged, and it is applied to the area, min size and max size of every registered window (plus the TabControl tab height). Fonts and images are handled separately in updateResourceScaling via CEGUI's auto-scaling.
SettingsWindow is a mixed case, not an exception: its area is {{0.5,-272.5},{0.5,-250},{0.5,272.5},{0.5,250}}, so the 0.5 Scale part (centering) stays as it is and only the +-272.5 / +-250 pixel offsets are scaled. The window therefore stays centered and its pixel size follows the UI scale.
| || name.compare(0, 17, "ODMainMenuButton/") == 0 | ||
| || name.compare(0, 7, "ODLogo/") == 0; | ||
| } | ||
|
|
There was a problem hiding this comment.
and (std::string scaleFormattedImageSizes(const CEGUI::String& ceguiText, float scale)) funtion what does it do ?
There was a problem hiding this comment.
It rescales the pixel sizes inside CEGUI formatted-text image tags. In a window text such as [image-size='w:32 h:32'], it finds each w: and h: value, multiplies it by scale, rounds it (minimum 1) and writes it back, so inline images in labels grow and shrink together with the rest of the UI. It returns the modified copy of the text; the original is kept in WindowScaleData::text and re-scaled from there on every scale change.
There was a problem hiding this comment.
Follow-up: the doc comment above scaleFormattedImageSizes is now in Rokk001@5f26921
| ++valueEnd; | ||
|
|
||
| float value = 0.0f; | ||
| std::istringstream valueParser(text.substr(valueStart, valueEnd - valueStart)); |
There was a problem hiding this comment.
atof is passe these days ? or actually it should be array to double .....
#include
double atof( const char * str ); but I haven't wrote a parser long time , so maybe I am mistaken :)
Anyway: one can read out what does that function do , but please write above it what does it do...
There was a problem hiding this comment.
atof would work for the parse itself, but on invalid input it silently returns 0 (no error), whereas the istringstream extraction lets us skip a malformed value and leave the tag untouched, so I kept it. Added a comment above the function describing what it does: Rokk001@5f26921
| ++font; | ||
| } | ||
|
|
||
| const CEGUI::Sizef imageNativeResolution(LAYOUT_DESIGN_WIDTH / mUserScale, |
There was a problem hiding this comment.
Strange that here we divide , not multiply by mUserScale .... ?
There was a problem hiding this comment.
Widget offsets are multiplied by the scale (applyScale), but fonts and images are scaled by CEGUI itself: with ASM_Min auto-scaling the rendered size is displaySize / nativeResolution. To make fonts and images grow by mUserScale, the native resolution therefore has to shrink by the same factor, so FONT_DESIGN_WIDTH / mUserScale is the matching operation. Multiplying would make the fonts and images smaller as the user scale increases, while the widgets get larger.
| { | ||
| struct PortraitScene | ||
| { | ||
| Ogre::SceneManager* scene = Ogre::Root::getSingleton().createSceneManager("DefaultSceneManager"); |
There was a problem hiding this comment.
Shouldn't that be in ctor, as God commanded ?
There was a problem hiding this comment.
Agreed, the scene manager is now created in the PortraitScene constructor's initializer list instead of a default member initializer: Rokk001@f94d8d0ef
| mCarriedEntity (nullptr), | ||
| mMoodCooldownTurns (0), | ||
| mMoodValue (CreatureMoodLevel::Neutral), | ||
| mMoodValue (gameMap->isServerGameMap() ? CreatureMoodLevel::Neutral : CreatureMoodLevel::Unknown), |
There was a problem hiding this comment.
So why two diffrent moods for Creature , one neutral when starting on server , and one unkown when on local side of the game ?
There was a problem hiding this comment.
On the server map the mood is real and starts at Neutral until the mood logic updates it. A client copy only knows a mood if the server sent one: importMoodFromPacket resets it to Unknown, and enemy creatures are exported as Unknown. So Unknown on the client means "not known here" rather than a wrong Neutral.
|
|
||
| void Creature::exportMoodToPacket(ODPacket& os, const Seat* seat) const | ||
| { | ||
| if(!ODServer::getSingleton().supportsCreatureMood(seat->getPlayer())) |
There was a problem hiding this comment.
I could increase the OD version , and assume that from now on every version supports CreatureMoods. THat's the option, what do you think ?
There was a problem hiding this comment.
The flags are optional trailing fields in the nick/start-game packets: a client that does not send them is treated as not supporting them, and the server then omits the mood data for it, so older clients and servers keep working. If you prefer to drop the flags, I can bump the version and assume mood support from then on - just say so.
| if(!mActions.empty()) | ||
| activity.action = mActions.back()->getType(); | ||
|
|
||
| for(auto it = mActions.rbegin(); it != mActions.rend(); ++it) |
There was a problem hiding this comment.
Ahh thats a reverse iterator, so activity.action is what creature currently does and activity.task is the first ( from back :) ) meaningful action apart from walkToTile and parkToTile. Naahh there is "break; " ... Can you in comments of CreatureActivity explain what are those two fields ?
There was a problem hiding this comment.
[Yeah somehow the ](std::vector<std::unique_ptr> mActions;) back is front , front is back. So the insertion removal goes by the end of this vector. I just noticed.
There was a problem hiding this comment.
Documented the CreatureActivity fields (action, task, back-to-front processing of mActions); this also covers the follow-up 4172677835: Rokk001@f777975
| } | ||
| return activity; | ||
| } | ||
|
|
There was a problem hiding this comment.
So it seems that this function method can end up with activity.task == activity.action ??? ( when creature does something meaningful ... )
There was a problem hiding this comment.
Yes. If the top action is not walkToTile/parkToTile (for example useRoom or an attack), action and task hold the same type. They only differ while the creature is walking or parking towards something. The field comments I am adding to CreatureActivity.h will state this.
Explain action, task and the back-to-front processing of mActions.
| switch(criterion) | ||
| { | ||
| case CreaturePanelCriterion::Idle: return idle; | ||
| case CreaturePanelCriterion::Working: |
There was a problem hiding this comment.
What a strange way of grouping bool flags, either all formulas after every return OR create another boolean flag 'working' :)
There was a problem hiding this comment.
Good point, thanks: the Working condition is now a named const bool next to the other flags, behaviour unchanged. Rokk001@bf5b732

Show visible creatures' owner-coloured segmented health rings and alternating level and needs display. Indicators are enabled by default; Alt toggles the chosen state, zoom enlarges the overlay, and depleted segments disappear without obscuring creature details.
The overlay now also shows experience toward the next level and attack-recovery progress. Capability negotiation keeps mismatched clients and servers from reading unsupported progress fields.
Depends on #225 for synchronized creature data. Review the progress follow-up.
Validation: progress and packet checks pass 377 assertions, level-caption rendering passes 557, and Alt handling passes 130. No new full-game, multiplayer or other-platform run is claimed; matching endpoints are required for the new optional fields.
Related to #216 and #6 without claiming either broader issue is fully resolved.
Supersedes #108, closed and force-pushed by mistake; recreated with the same content and cleaned-up commit trailers.