Mukund Pareek / mukund pareek
  • Projects
  • Blog
  • Notes
  • Resume

MP Mukund Pareek

Unreal Engine C++ Developer

  • Projects
  • Blog
  • Notes
  • Resume

© 2026 Mukund Pareek. Built with Next.js and Tailwind CSS.

Projects
Repository Commits
January 20, 2026
Editor Tools

Quick Facts

Engine
Unreal Engine 5
Language
C++
System
Unreal Editor API
Type
Editor Tools
Status
Prototype
GeoTracker Editor Plugin thumbnail
Editor Tools

GeoTracker Editor Plugin

Custom Unreal Editor Mode plugin that adds spatial distance measurement tools to the viewport with click-drag interaction and an extensible toolkit panel.

unreal
editor-mode
plugin
c++
viewport

TL;DR

GeoTracker is a custom FEdMode-based Unreal Editor plugin that lets designers click and drag inside the viewport to measure distances between world-space points. Built entirely in C++ using the Editor Mode API, it demonstrates custom toolbar toolkit integration, viewport input interception, and hit-testing against world geometry.

Role & Scope

  • Role: Solo developer
  • Duration: 2 weeks
  • Responsibilities: Editor Mode registration, viewport input pipeline, hit test implementation, Slate toolkit panel, plugin module structure

Problem

The built-in measurement tools in the Unreal Editor are limited. Designers on the project needed a lightweight, persistent distance measurement overlay without leaving editor context or opening external tools. The goal was a click-drag measuring tape that shows 3D distance in world units.

Architecture

[Inference] GeoTracker plugin architecture - editor mode registration to viewport overlay rendering.

Implementation - Key Classes & Flow

FGeoTrackerEdMode - Core Editor Mode

Inherits FEdMode. Overrides HandleClick() to intercept left-mouse viewport events and perform a line trace against the world. First click stores the start point; second click stores the end, computes distance, and resets for the next measurement.

FGeoTrackerToolkit - Left-Side Panel

Inherits FModeToolkit. Returns a custom SWidget via GetInlineContent() that displays the current measurement list. Integrated into the editor's mode toolbar via RegisterTabSpawner.

SGeoTrackerPanel - Slate Widget

Displays a scrollable list of measured distances. Each entry shows start/end world coordinates and the computed distance in cm and m. Clears on mode deactivation.

FGeoTrackerDrawHelper - Viewport Overlay

Uses FPrimitiveDrawInterface in Render() to draw lines and distance labels over the 3D viewport. Labels use DrawString() at the midpoint of each measurement.

Code Snippet

cppGeoTrackerEdMode.cpp
bool FGeoTrackerEdMode::HandleClick(
  FEditorViewportClient* ViewportClient,
  HHitProxy* HitProxy,
  const FViewportClick& Click)
{
  FVector WorldOrigin, WorldDir;
  ViewportClient->DeprojectFVector2D(Click.GetClickPos(), WorldOrigin, WorldDir);

  FHitResult Hit;
  const bool bHit = GetWorld()->LineTraceSingleByChannel(
      Hit, WorldOrigin, WorldOrigin + WorldDir * 100000.f, ECC_Visibility);

  if (bHit)
  {
      if (!bHasStartPoint)
      {
          StartPoint = Hit.ImpactPoint;
          bHasStartPoint = true;
      }
      else
      {
          EndPoint = Hit.ImpactPoint;
          const float Dist = FVector::Dist(StartPoint, EndPoint);
          Measurements.Add({ StartPoint, EndPoint, Dist });
          bHasStartPoint = false;
      }
  }
  return true;
}

Video Demo

Demo: activating GeoTracker mode, placing start/end measurement points in the viewport, and reading distances in the toolkit panel.

Challenges & Solutions

Challenge: Click events not reaching the editor mode

Editor modes only receive input when the viewport has focus AND the mode is active. Initially, clicks were consumed by the selection system before reaching HandleClick.

Fix: Override FEdMode::IsCompatibleWith() to return false for FBuiltinEditorModes::EM_Default and use FEditorModeTools::ActivateMode() to correctly transition to GeoTracker mode, preventing the default selection handler from running.

Challenge: World-space line trace from screen position

FViewportClick::GetClickPos() returns 2D screen coordinates. Converting to world ray requires FEditorViewportClient::DeprojectFVector2D() which isn't exposed in all editor mode contexts.

Fix: Cache the FEditorViewportClient* from Enter() and call DeprojectFVector2D directly. Verified the pointer is valid before use.

Performance, Replication & Edge Cases

  • Performance: Measurements list is bounded to 50 entries; excess entries are dropped (FIFO) to avoid unbounded Slate widget growth.
  • Replication: Editor-only - no runtime replication needed. All state lives in the editor mode class and is cleared on Exit().
  • Edge cases: If the line trace misses (open sky, no geometry), the click is silently ignored and bHasStartPoint stays unchanged.

What I Would Change / Next Steps

  • Persist measurement sessions to a USaveGame-style asset for recall between editor sessions
  • Add angle measurement mode (three-point arc)
  • Replace manual DrawString with a proper FCanvas-based overlay for HiDPI scaling

Artifacts

ArtifactLink
RepositoryGitHub
Diagram/images/diagrams/geotracker-editor-plugin.svg