osrs panel implementation

Guide for osrs panel implementation

OSRS-Style Permanent Right Panel Implementation

Purpose

This document describes the implementation of the OSRS-style permanent right panel UI redesign, including the issues encountered and lessons learned.

Implementation Overview

Goal

Replace the toggleable bottom-right menu with a permanent 250px-wide right panel matching OSRS's classic layout.

Panel Structure (Implemented)

┌─────────────────────┐
│ Minimap (150px)     │  ← Placeholder
├─────────────────────┤
│ ⚫ ⚫ ⚫             │  ← HP/Prayer/Energy orbs
├─────────────────────┤
│ [Icon] [Icon] ...   │  ← Top tabs (4)
├─────────────────────┤
│                     │
│   Content Area      │  ← Scrollable
│   (250px height)    │
│                     │
├─────────────────────┤
│ [Icon] [Icon] ...   │  ← Bottom tabs (4)
└─────────────────────┘

Code Changes

File: src/systems/ui/mod.rs

1. Panel Window Configuration

Lines 345-353:
egui::Window::new("GamePanel")
    .anchor(egui::Align2::RIGHT_TOP, egui::Vec2::new(-5.0, 5.0))
    .fixed_size(egui::Vec2::new(250.0, 600.0))
    .title_bar(false)
    .resizable(false)
    .frame(egui::Frame::none().fill(egui::Color32::from_rgb(62, 53, 41)))
    .show(ctx, |ui| {
        ui.vertical(|ui| {
            // Panel content
        });
    });
Key Decisions:
  • RIGHT_TOP anchor instead of RIGHT_BOTTOM (OSRS style)
  • Fixed 250px width, 600px height
  • No title bar or resize handles
  • Brown color scheme rgb(62, 53, 41)

2. Minimap Placeholder

Lines 355-365:
egui::Frame::none()
    .fill(egui::Color32::from_rgb(40, 35, 30))
    .inner_margin(5.0)
    .show(ui, |ui| {
        ui.set_height(150.0);
        ui.centered_and_justified(|ui| {
            ui.label(egui::RichText::new("Minimap")
                .color(egui::Color32::GRAY)
                .size(12.0));
        });
    });
Status: Placeholder only, actual minimap integration pending.

3. Orbs Implementation (BROKEN)

Lines 370-420:
ui.horizontal(|ui| {
    // Get player stats
    let (hp, max_hp, prayer, max_prayer) = if let Ok((player_entity, _, _)) = player_q.get_single() {
        if let Ok(skills) = skills_q.get(player_entity) {
            let hp = skills.get_level(SkillType::Hitpoints);
            let prayer = skills.get_level(SkillType::Prayer);
            (hp as f32, 10.0, prayer as f32, 1.0)
        } else {
            (10.0, 10.0, 1.0, 1.0)
        }
    } else {
        (10.0, 10.0, 1.0, 1.0)
    };
    
    ui.add_space(10.0);
    
    // HP Orb
    egui::Frame::none()
        .fill(egui::Color32::from_rgb(80, 20, 20))
        .rounding(25.0)
        .show(ui, |ui| {
            ui.allocate_space(egui::Vec2::new(50.0, 50.0));
            ui.centered_and_justified(|ui| {
                ui.label(egui::RichText::new(format!("{}", hp as i32))
                    .color(egui::Color32::WHITE)
                    .size(14.0));
            });
        }).response.on_hover_text(format!("HP: {}/{}", hp as i32, max_hp as i32));
    
    // ... Prayer and Energy orbs similar
});
Issue: allocate_space doesn't constrain the frame size properly, causing orbs to stretch horizontally instead of remaining circular.
Root Cause: allocate_space reserves space but doesn't enforce size constraints on the parent Frame. The frame expands to fill available horizontal space.

4. Tab Rows

Top Row (Lines 425-450):
ui.horizontal(|ui| {
    let icon_size = egui::Vec2::new(28.0, 28.0);
    let top_tabs = [
        (UiTab::Combat, combat_tex, "Combat"),
        (UiTab::Stats, stats_tex, "Stats"),
        (UiTab::Quests, quest_tex, "Quests"),
        (UiTab::Inventory, inv_tex, "Inventory"),
    ];
    
    ui.add_space(5.0);
    for (tab, tex, hint) in top_tabs {
        let is_active = ui_state.active_tab == tab;
        let btn = egui::ImageButton::new(egui::load::SizedTexture::new(tex, icon_size))
            .tint(if is_active { egui::Color32::WHITE } else { egui::Color32::from_white_alpha(150) })
            .frame(is_active);
        
        if ui.add(btn).on_hover_text(hint).clicked() {
            ui_state.active_tab = tab;
        }
        ui.add_space(10.0);
    }
});
Bottom Row (Lines 600-615): Similar structure with Equipment, Prayer, Magic, Settings tabs.
Status: Functional but lacks visual polish (no hover effects, transitions).

5. Content Area

Lines 455-595:
egui::ScrollArea::vertical().show(ui, |ui| {
    ui.set_min_height(250.0);
    
    egui::Frame::none()
        .inner_margin(8.0)
        .show(ui, |ui| {
            match ui_state.active_tab {
                UiTab::Combat => { /* Combat UI */ },
                UiTab::Stats => { /* Skills grid */ },
                UiTab::Quests => { /* Quest list */ },
                // ... other tabs
            }
        });
});
Status: Functional, displays correct content for each tab.

Issues Discovered

Critical Bugs

1. Broken Orb Layout

Symptom: Orbs appear stretched/elongated instead of circular
Cause: ui.allocate_space() doesn't constrain parent Frame size
Impact: Major visual bug, orbs look unprofessional
Fix Required:
// Instead of:
ui.allocate_space(egui::Vec2::new(50.0, 50.0));

// Use:
ui.set_min_width(50.0);
ui.set_max_width(50.0);
ui.set_min_height(50.0);
ui.set_max_height(50.0);
// OR use a different layout approach with fixed-size containers

2. Icon Loading Failures

Symptom: All 4 new skill icons fail to load with error:
ERROR Failed to load asset 'logos/Ranged_icon.png' with asset loader 
'bevy_render::texture::image_loader::ImageLoader': Could not load texture file: 
Error reading image file logos/Ranged_icon.png: failed to load an image: 
Format error decoding Png: Invalid PNG signature.
Cause: Generated images were saved as WebP (artifact system default) but referenced as .png files.
Impact: Skills tab shows missing icons, broken visual experience.
Fix Required: Re-generate icons and save as proper PNG format with correct headers.

UX/Design Issues

1. Poor Color Scheme

Issue: Brown/gray colors (rgb(62,53,41)) appear dull and muddy
User Feedback: "not enjoying the look and feel"

2. Lack of Visual Hierarchy

Issue: All elements have similar visual weight, no clear focus
Impact: UI feels flat and unpolished

3. No Interactive Feedback

Issue: Tabs lack hover effects, transitions, or clear selected states
Impact: UI feels unresponsive

4. Inconsistent Spacing

Issue: Spacing varies throughout the panel (5px, 8px, 10px, 15px)
Impact: Visual inconsistency

Lessons Learned

1. egui Sizing Constraints

Lesson: allocate_space reserves space but doesn't enforce size on parent containers.
Best Practice: For fixed-size circular elements, use:
  • set_min_size + set_max_size on the UI
  • OR wrap in a fixed-size container
  • OR use allocate_exact_size if available

2. Asset Generation Pipeline

Lesson: AI-generated images may not match expected file formats.
Best Practice:
  • Verify file format after generation (file command)
  • Use explicit format conversion if needed
  • Test asset loading before committing

3. Color Palette Selection

Lesson: Brown/gray colors work for OSRS nostalgia but may not suit all games.
Best Practice:
  • Consider game theme and aesthetic
  • Test colors in actual game environment
  • Get user feedback early

4. Incremental UI Changes

Lesson: Large UI rewrites can introduce multiple issues simultaneously.
Best Practice:
  • Implement in smaller increments
  • Test each component individually
  • Get feedback at each stage

Next Steps (Revamp Plan)

Phase 1: Critical Fixes

  1. Fix orb circular layout
  2. Regenerate skill icons as proper PNGs
  3. Move milestone tracker to top-left

Phase 2: Visual Redesign

  1. Update color palette (deep indigo + vibrant accents)
  2. Improve spacing consistency
  3. Add hover effects and transitions

Phase 3: Content Polish

  1. Skills tab XP bars
  2. Better tooltips
  3. Combat tab improvements