| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Combat *
- * *
- * $Archive:: /Commando/Code/wwui/mapctrl.cpp $*
- * *
- * Author:: Patrick Smith *
- * *
- * $Modtime:: 1/10/02 6:39p $*
- * *
- * $Revision:: 15 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "mapctrl.h"
- #include "assetmgr.h"
- #include "refcount.h"
- #include "font3d.h"
- #include "mousemgr.h"
- #include "ww3d.h"
- #include "dialogmgr.h"
- #include "dialogbase.h"
- #include "stylemgr.h"
- #include "ffactory.h"
- ////////////////////////////////////////////////////////////////
- // Local constants
- ////////////////////////////////////////////////////////////////
- static const float ZOOM_RATE = 2.0F;
- static const float MARKER_WIDTH = 16.0F;
- static const float MARKER_HEIGHT = 16.0F;
- static const RectClass ZoomInUVRect (1, 33, 25, 57);
- static const RectClass ZoomOutUVRect (26, 33, 53, 57);
- static const Vector2 ButtonTextureSize (64, 64);
- static const RectClass EdgeTopUVRect (1, 2, 31, 30);
- static const RectClass EdgeRightUVRect (34, 1, 62, 31);
- static const RectClass EdgeLeftUVRect (2, 31, 30, 63);
- static const RectClass EdgeBottomUVRect (31, 34, 63, 62);
- ////////////////////////////////////////////////////////////////
- //
- // MapCtrlClass
- //
- ////////////////////////////////////////////////////////////////
- MapCtrlClass::MapCtrlClass (void) :
- Zoom (1.0F),
- ScrollPos (0, 0),
- MapSize (0, 0),
- IsDragging (false),
- IsZoomingIn (false),
- IsZoomingOut (false),
- IsUsingOverlay (false),
- InitialMousePos (0, 0),
- InitialScrollPos (0, 0),
- ZoomInButtonRect (0, 0, 0, 0),
- ZoomOutButtonRect (0, 0, 0, 0),
- MapCenterPoint (0, 0),
- MapScale (1, 1),
- CloudVector (NULL),
- CloudSize (0, 0),
- OverlayOpacity (1.0F),
- PulseDirection (-1.0F)
- {
- //
- // Configure the renderers
- //
- StyleMgrClass::Assign_Font (&TextRenderer, StyleMgrClass::FONT_CONTROLS);
- StyleMgrClass::Configure_Renderer (&ControlRenderer);
- StyleMgrClass::Configure_Renderer (&ButtonRenderer);
- StyleMgrClass::Configure_Renderer (&MapRenderer);
- StyleMgrClass::Configure_Renderer (&MapOverlayRenderer);
- StyleMgrClass::Configure_Renderer (&CloudRenderer);
- StyleMgrClass::Configure_Renderer (&EdgeRenderer);
- StyleMgrClass::Configure_Renderer (&IconRenderer);
- TextureClass *texture = WW3DAssetManager::Get_Instance ()->Get_Texture ("map_edges.tga", TextureClass::MIP_LEVELS_1);
- EdgeRenderer.Set_Texture (texture);
- REF_PTR_RELEASE (texture);
- texture = WW3DAssetManager::Get_Instance ()->Get_Texture ("mapicons.tga", TextureClass::MIP_LEVELS_1);
- ButtonRenderer.Set_Texture (texture);
- REF_PTR_RELEASE (texture);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // ~MapCtrlClass
- //
- ////////////////////////////////////////////////////////////////
- MapCtrlClass::~MapCtrlClass (void)
- {
- Free_Cloud_Data ();
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Create_Text_Renderers
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Create_Text_Renderers (void)
- {
- //
- // Start fresh
- //
- TextRenderer.Reset ();
- //
- // Draw the text
- //
- //StyleMgrClass::Render_Text (Title, &TextRenderer, TextRect, true, true);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Create_Control_Renderers
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Create_Control_Renderers (void)
- {
- Render2DClass &renderer = ControlRenderer;
- //
- // Configure this renderer
- //
- renderer.Reset ();
- renderer.Enable_Texturing (false);
- //
- // Determine which color to draw the outline in
- //
- int color = StyleMgrClass::Get_Line_Color ();
- int bkcolor = StyleMgrClass::Get_Bk_Color ();
- if (IsEnabled == false) {
- color = StyleMgrClass::Get_Disabled_Line_Color ();
- bkcolor = StyleMgrClass::Get_Disabled_Bk_Color ();
- }
- //
- // Draw the control's outline
- //
- renderer.Add_Outline (Rect, 1.0F, color);
- renderer.Add_Outline (ZoomInButtonRect, 1.0F, color);
- renderer.Add_Outline (ZoomOutButtonRect, 1.0F, color);
- //
- // Shrink the rectangle
- //
- RectClass rect = Rect;
- rect.Right -= 1;
- rect.Bottom -= 1;
- //
- // Calculate what the UV rectangle should be given the
- // current scroll and zoom factors.
- //
- RectClass map_uv_rect (0, 0, 1, 1);
- //
- // Calculate the center of the image
- //
- Vector2 center = (MapSize / 2) + ScrollPos;
- //
- // Calculate the 'zoomed' rectangle (in pixels)
- //
- float width = Rect.Width ();
- float height = Rect.Height ();
- map_uv_rect.Left = center.X - ((width / 2) / Zoom);
- map_uv_rect.Top = center.Y - ((height / 2) / Zoom);
- map_uv_rect.Right = center.X + ((width / 2) / Zoom);
- map_uv_rect.Bottom = center.Y + ((height / 2) / Zoom);
- //
- // Render any markers that are in view
- //
- IconRenderer.Reset ();
- for (int index = 0; index < MarkerList.Count (); index ++) {
- const MapMarkerClass &marker = MarkerList[index];
- //
- // Calculate what pixel position this marker is located at.
- //
- Vector2 map_pos;
- map_pos.X = MapCenterPoint.X + (marker.Get_Position ().X * MapScale.X);
- map_pos.Y = MapCenterPoint.Y - (marker.Get_Position ().Y * MapScale.Y);
- //
- // Is this marker currently visible?
- //
- if (map_uv_rect.Contains (map_pos)) {
-
- //
- // Calculate what percentage of the visible map the marker's position is
- //
- Vector2 percent;
- percent.X = (map_pos.X - map_uv_rect.Left) / map_uv_rect.Width ();
- percent.Y = (map_pos.Y - map_uv_rect.Top) / map_uv_rect.Height ();
- //
- // Convert the perctange into a screen position
- //
- Vector2 screen_pos;
- screen_pos.X = rect.Left + (percent.X * rect.Width ());
- screen_pos.Y = rect.Top + (percent.Y * rect.Height ());
- //
- // Build a screen rectangle we'll render into
- //
- RectClass screen_rect;
- screen_rect.Left = int(screen_pos.X - (marker.Get_Rect ().Width () / 2));
- screen_rect.Top = int(screen_pos.Y - (marker.Get_Rect ().Height () / 2));
- screen_rect.Right = int(screen_rect.Left + marker.Get_Rect ().Width ());
- screen_rect.Bottom = int(screen_rect.Top + marker.Get_Rect ().Height ());
- //
- // Convert the pixel coordinates into normalized UVs
- //
- RectClass marker_uv_rect = marker.Get_Rect ();
- marker_uv_rect.Inverse_Scale (Vector2 (IconTextureSize.X, IconTextureSize.Y));
- //
- // Clip the rectangle as necessary
- //
- RectClass clipped_rect;
- clipped_rect.Left = max (screen_rect.Left, Rect.Left);
- clipped_rect.Right = min (screen_rect.Right, Rect.Right);
- clipped_rect.Top = max (screen_rect.Top, Rect.Top);
- clipped_rect.Bottom = min (screen_rect.Bottom, Rect.Bottom);
- //
- // Clip the texture to the specified area
- //
- RectClass clipped_uv_rect;
- float clip_percent = ((clipped_rect.Left - screen_rect.Left) / screen_rect.Width ());
- clipped_uv_rect.Left = marker_uv_rect.Left + (marker_uv_rect.Width () * clip_percent);
- clip_percent = ((clipped_rect.Right - screen_rect.Left) / screen_rect.Width ());
- clipped_uv_rect.Right = marker_uv_rect.Left + (marker_uv_rect.Width () * clip_percent);
- clip_percent = ((clipped_rect.Top - screen_rect.Top) / screen_rect.Height ());
- clipped_uv_rect.Top = marker_uv_rect.Top + (marker_uv_rect.Height () * clip_percent);
- clip_percent = ((clipped_rect.Bottom - screen_rect.Top) / screen_rect.Height ());
- clipped_uv_rect.Bottom = marker_uv_rect.Top + (marker_uv_rect.Height () * clip_percent);
- //
- // Use the clipped rectangles to render
- //
- screen_rect = clipped_rect;
- marker_uv_rect = clipped_uv_rect;
- //
- // Render the marker
- //
- IconRenderer.Add_Quad (screen_rect, marker_uv_rect, marker.Get_Color ());
- }
- }
- //
- // Render the buttons
- //
- ButtonRenderer.Reset ();
- RectClass temp_rect1;
- temp_rect1.Left = int(ZoomInButtonRect.Center ().X - (ZoomInUVRect.Width () / 2));
- temp_rect1.Top = int(ZoomInButtonRect.Center ().Y - (ZoomInUVRect.Height () / 2));
- temp_rect1.Right = int(temp_rect1.Left + ZoomInUVRect.Width ());
- temp_rect1.Bottom = int(temp_rect1.Top + ZoomInUVRect.Height ());
-
- RectClass temp_rect2;
- temp_rect2.Left = int(ZoomOutButtonRect.Center ().X - (ZoomInUVRect.Width () / 2));
- temp_rect2.Top = int(ZoomOutButtonRect.Center ().Y - (ZoomInUVRect.Height () / 2));
- temp_rect2.Right = int(temp_rect2.Left + ZoomInUVRect.Width ());
- temp_rect2.Bottom = int(temp_rect2.Top + ZoomInUVRect.Height ());
- RectClass temp_uv_rect1 = ZoomInUVRect;
- RectClass temp_uv_rect2 = ZoomOutUVRect;
- temp_uv_rect1.Inverse_Scale (Vector2 (ButtonTextureSize.X, ButtonTextureSize.Y));
- temp_uv_rect2.Inverse_Scale (Vector2 (ButtonTextureSize.X, ButtonTextureSize.Y));
- ButtonRenderer.Add_Quad (temp_rect1, temp_uv_rect1);
- ButtonRenderer.Add_Quad (temp_rect2, temp_uv_rect2);
- //
- // Normalize the map UVs
- //
- map_uv_rect.Inverse_Scale (Vector2 (MapSize.X , MapSize.Y));
-
- //
- // Render the map
- //
- MapRenderer.Reset ();
- MapOverlayRenderer.Reset ();
- MapRenderer.Enable_Alpha (false);
- MapOverlayRenderer.Enable_Alpha (true);
- MapRenderer.Add_Quad (rect, map_uv_rect);
- MapOverlayRenderer.Add_Quad (rect, map_uv_rect);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Create_Cloud_Renderer
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Create_Cloud_Renderer (void)
- {
- CloudRenderer.Reset ();
- EdgeRenderer.Reset ();
- CloudRenderer.Enable_Texturing (false);
- //
- // Calculate the dimensions of the cloud at this zoom factor
- //
- float cloud_width = (MapSize.X / CloudSize.I) * Zoom;
- float cloud_height = (MapSize.Y / CloudSize.J) * Zoom;
- Vector2 center = (MapSize / 2) - ScrollPos;
- float delta_x = ((MapSize.X * Zoom) - Rect.Width ()) / 2;
- float delta_y = ((MapSize.Y * Zoom) - Rect.Height ()) / 2;
- float cloud_x_pos = Rect.Left - (delta_x + (ScrollPos.X * Zoom));
- float cloud_y_pos = Rect.Top - (delta_y + (ScrollPos.Y * Zoom));
- //
- // Loop over all the cells
- //
- for (int cell_y = 0; cell_y < CloudSize.J; cell_y ++) {
-
- //
- // Reset the x position
- //
- cloud_x_pos = Rect.Left - (delta_x + (ScrollPos.X * Zoom));
- for (int cell_x = 0; cell_x < CloudSize.I; cell_x ++) {
-
- //
- // Build the rectangle for this cloud section
- //
- RectClass cloud_rect;
- cloud_rect.Left = cloud_x_pos;
- cloud_rect.Top = cloud_y_pos;
- cloud_rect.Right = cloud_rect.Left + cloud_width;
- cloud_rect.Bottom = cloud_rect.Top + cloud_height;
-
- //
- // Clip the rectangle
- //
- cloud_rect.Left = max (cloud_rect.Left, Rect.Left);
- cloud_rect.Top = max (cloud_rect.Top, Rect.Top);
- cloud_rect.Right = min (cloud_rect.Right, Rect.Right);
- cloud_rect.Bottom = min (cloud_rect.Bottom, Rect.Bottom);
-
- //
- // Don't render anything if this cell is completely clipped.
- //
- if (cloud_rect.Width () > 0 && cloud_rect.Height () > 0) {
- //
- // Is this cell clouded?
- //
- if (Is_Cell_Shrouded (cell_x, cell_y)) {
- //
- // Render a black square in this cell
- //
- CloudRenderer.Add_Quad (cloud_rect, RGB_TO_INT32 (0, 0, 0));
- } else {
- RectClass delta_rect;
- delta_rect.Left = ((cloud_rect.Left - cloud_x_pos) / cloud_width);
- delta_rect.Top = ((cloud_rect.Top - cloud_y_pos) / cloud_height);
- delta_rect.Right = ((cloud_rect.Right - (cloud_x_pos + cloud_width)) / cloud_width);
- delta_rect.Bottom = ((cloud_rect.Bottom - (cloud_y_pos + cloud_height)) / cloud_height);
- if (Is_Cell_Shrouded (cell_x - 1, cell_y)) {
- RectClass uv_rect = EdgeLeftUVRect;
- //
- // Clip the uv-rectangle to fit the color rectangle
- //
- uv_rect.Left += uv_rect.Width () * delta_rect.Left;
- uv_rect.Right += uv_rect.Width () * delta_rect.Right;
- uv_rect.Top += uv_rect.Height () * delta_rect.Top;
- uv_rect.Bottom += uv_rect.Height () * delta_rect.Bottom;
- uv_rect.Inverse_Scale (Vector2 (64.0F, 64.0F));
- EdgeRenderer.Add_Quad (cloud_rect, uv_rect);
- }
- if (Is_Cell_Shrouded (cell_x + 1, cell_y)) {
- RectClass uv_rect = EdgeRightUVRect;
- //
- // Clip the uv-rectangle to fit the color rectangle
- //
- uv_rect.Left += uv_rect.Width () * delta_rect.Left;
- uv_rect.Right += uv_rect.Width () * delta_rect.Right;
- uv_rect.Top += uv_rect.Height () * delta_rect.Top;
- uv_rect.Bottom += uv_rect.Height () * delta_rect.Bottom;
- uv_rect.Inverse_Scale (Vector2 (64.0F, 64.0F));
- EdgeRenderer.Add_Quad (cloud_rect, uv_rect);
- }
- if (Is_Cell_Shrouded (cell_x, cell_y - 1)) {
- RectClass uv_rect = EdgeTopUVRect;
- //
- // Clip the uv-rectangle to fit the color rectangle
- //
- uv_rect.Left += uv_rect.Width () * delta_rect.Left;
- uv_rect.Right += uv_rect.Width () * delta_rect.Right;
- uv_rect.Top += uv_rect.Height () * delta_rect.Top;
- uv_rect.Bottom += uv_rect.Height () * delta_rect.Bottom;
- uv_rect.Inverse_Scale (Vector2 (64.0F, 64.0F));
- EdgeRenderer.Add_Quad (cloud_rect, uv_rect);
- }
- if (Is_Cell_Shrouded (cell_x, cell_y + 1)) {
- RectClass uv_rect = EdgeBottomUVRect;
- //
- // Clip the uv-rectangle to fit the color rectangle
- //
- uv_rect.Left += uv_rect.Width () * delta_rect.Left;
- uv_rect.Right += uv_rect.Width () * delta_rect.Right;
- uv_rect.Top += uv_rect.Height () * delta_rect.Top;
- uv_rect.Bottom += uv_rect.Height () * delta_rect.Bottom;
- uv_rect.Inverse_Scale (Vector2 (64.0F, 64.0F));
- EdgeRenderer.Add_Quad (cloud_rect, uv_rect);
- }
- }
- }
- //
- // Advance one column
- //
- cloud_x_pos += cloud_width;
- }
- //
- // Advance one row
- //
- cloud_y_pos += cloud_height;
- }
-
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Set_Cursor
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::On_Set_Cursor (const Vector2 &mouse_pos)
- {
- //
- // Change the mouse cursor
- //
- if ( ZoomInButtonRect.Contains (mouse_pos) ||
- ZoomOutButtonRect.Contains (mouse_pos) ||
- (::GetAsyncKeyState (VK_CONTROL) < 0) ||
- Marker_From_Pos (mouse_pos) != -1)
- {
- MouseMgrClass::Set_Cursor (MouseMgrClass::CURSOR_ACTION);
- } else {
- MouseMgrClass::Set_Cursor (MouseMgrClass::CURSOR_PAN_UP);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Update_Client_Rect
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Update_Client_Rect (void)
- {
- //
- // Set the client area
- //
- ClientRect = Rect;
- //
- // Build the zoom button rectangles
- //
- ZoomOutButtonRect;
- ZoomOutButtonRect.Left = int(Rect.Right - (ZoomInUVRect.Width () + 2));
- ZoomOutButtonRect.Top = int(Rect.Bottom - (ZoomInUVRect.Height () + 2));
- ZoomOutButtonRect.Right = int(Rect.Right);
- ZoomOutButtonRect.Bottom = int(Rect.Bottom);
- ZoomInButtonRect = ZoomOutButtonRect;
- ZoomInButtonRect.Left = int(ZoomInButtonRect.Left - (ZoomInUVRect.Width () + 2));
- ZoomInButtonRect.Right = int(ZoomInButtonRect.Right - (ZoomInUVRect.Width () + 2));
- Set_Dirty ();
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Render
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Render (void)
- {
- Update_Pulse ();
- //
- // Recreate the renderers (if necessary)
- //
- if (IsDirty) {
- Create_Cloud_Renderer ();
- Create_Control_Renderers ();
- Create_Text_Renderers ();
- }
- //
- // Render the background and text for the current state
- //
- TextRenderer.Render ();
- MapRenderer.Render ();
- if (IsUsingOverlay) {
- MapOverlayRenderer.Render ();
- }
- IconRenderer.Render ();
- CloudRenderer.Render ();
- EdgeRenderer.Render ();
- ButtonRenderer.Render ();
- ControlRenderer.Render ();
- DialogControlClass::Render ();
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_LButton_Down
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::On_LButton_Down (const Vector2 &mouse_pos)
- {
- IsDragging = false;
- IsZoomingIn = false;
- IsZoomingOut = false;
- if (ZoomInButtonRect.Contains (mouse_pos)) {
- IsZoomingIn = true;
- Set_Capture ();
- } else if (ZoomOutButtonRect.Contains (mouse_pos)) {
- IsZoomingOut = true;
- Set_Capture ();
- } else {
-
- //
- // If the user held the control as they clicked, then
- // notify the advise sinks that a position is being requested
- //
- if (::GetAsyncKeyState (VK_CONTROL) < 0) {
- Vector3 world_pos = Position_To_Coord (mouse_pos);
- ADVISE_NOTIFY (On_MapCtrl_Pos_Clicked (this, Get_ID (), world_pos));
- } else {
-
- //
- // Begin panning
- //
- IsDragging = true;
- Set_Capture ();
-
- InitialMousePos = mouse_pos;
- InitialScrollPos = ScrollPos;
- }
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_LButton_Up
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::On_LButton_Up (const Vector2 &mouse_pos)
- {
- Release_Capture ();
- IsDragging = false;
- IsZoomingIn = false;
- IsZoomingOut = false;
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Set_Map_Texture
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Set_Map_Texture (const char *filename)
- {
- //
- // Load the texture
- //
- TextureClass *texture = WW3DAssetManager::Get_Instance ()->Get_Texture (filename, TextureClass::MIP_LEVELS_1);
- if (texture != NULL) {
- //
- // Get the dimensions of the texture
- //
- MapSize.X = texture->Get_Width();
- MapSize.Y = texture->Get_Height();
- texture->Set_U_Addr_Mode (TextureClass::TEXTURE_ADDRESS_CLAMP);
- texture->Set_V_Addr_Mode (TextureClass::TEXTURE_ADDRESS_CLAMP);
- //
- // Set the texture for the map
- //
- MapRenderer.Set_Texture (texture);
- REF_PTR_RELEASE (texture);
- //
- // Force a repaint
- //
- Set_Dirty ();
- }
- //
- // Try to find a texture to use as an overlay...
- //
- StringClass overlay_texture_name = filename;
- int len = overlay_texture_name.Get_Length ();
- overlay_texture_name.Erase (len - 4, 4);
- overlay_texture_name += "a.tga";
- //
- // Check to see if the overlay exists
- //
- IsUsingOverlay = false;
- FileClass *file = _TheFileFactory->Get_File (overlay_texture_name);
- if (file != NULL) {
-
- bool is_valid = true;
- //
- // If the file doesn't exist as a TGA try to find it as a DDS
- //
- if (file->Is_Available () == false) {
- is_valid = false;
- _TheFileFactory->Return_File (file);
- len = overlay_texture_name.Get_Length ();
- overlay_texture_name.Erase (len - 3, 3);
- overlay_texture_name += "dds";
- file = _TheFileFactory->Get_File (overlay_texture_name);
- if (file != NULL && file->Is_Available ()) {
- is_valid = true;
- }
- }
- if (is_valid) {
- texture = WW3DAssetManager::Get_Instance ()->Get_Texture (overlay_texture_name, TextureClass::MIP_LEVELS_1);
- //
- // Configure the overlay renderer
- //
- if (texture != NULL) {
- texture->Set_U_Addr_Mode (TextureClass::TEXTURE_ADDRESS_CLAMP);
- texture->Set_V_Addr_Mode (TextureClass::TEXTURE_ADDRESS_CLAMP);
- MapOverlayRenderer.Set_Texture (texture);
- REF_PTR_RELEASE (texture);
- IsUsingOverlay = true;
- }
- }
- if (file != NULL) {
- _TheFileFactory->Return_File (file);
- }
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Set_Focus
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::On_Set_Focus (void)
- {
- DialogControlClass::On_Set_Focus ();
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Kill_Focus
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::On_Kill_Focus (DialogControlClass *focus)
- {
- IsDragging = false;
- IsZoomingIn = false;
- IsZoomingOut = false;
- DialogControlClass::On_Kill_Focus (focus);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Mouse_Move
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::On_Mouse_Move (const Vector2 &mouse_pos)
- {
- //
- // Is the user "dragging" inside the control
- //
- if (HasFocus) {
-
- if (IsDragging) {
- Vector2 delta = (InitialMousePos - mouse_pos);
- //
- // Update the scroll position
- //
- ScrollPos.X = InitialScrollPos.X + (delta.X / Zoom);
- ScrollPos.Y = InitialScrollPos.Y + (delta.Y / Zoom);
- Clamp_Scroll_Pos ();
- //
- // Force a repaint
- //
- Set_Dirty ();
- }
- }
- //
- // Notify the parent
- //
- if (IsDragging == false) {
- int index = Marker_From_Pos (mouse_pos);
- ADVISE_NOTIFY (On_MapCtrl_Marker_Hilighted (this, Get_ID (), index));
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Frame_Update
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::On_Frame_Update (void)
- {
- if (HasFocus) {
-
- if (IsZoomingIn) {
-
- //
- // Zoom-In
- //
- Zoom += (DialogMgrClass::Get_Frame_Time () / 1000.F) * ZOOM_RATE;
- Zoom = WWMath::Clamp (Zoom, 0.5F, 1.5F);
- Set_Dirty ();
- } else if (IsZoomingOut) {
-
- //
- // Zoom-Out
- //
- Zoom -= (DialogMgrClass::Get_Frame_Time () / 1000.0F) * ZOOM_RATE;
- Zoom = WWMath::Clamp (Zoom, 0.5F, 1.5F);
- Set_Dirty ();
- }
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Add_Marker
- //
- ////////////////////////////////////////////////////////////////
- int
- MapCtrlClass::Add_Marker
- (
- const WCHAR * name,
- const Vector3 & pos,
- const RectClass & uv_rect,
- int color
- )
- {
- //
- // Add this marker to our list
- //
- MapMarkerClass marker;
- marker.Set_Name (name);
- marker.Set_Position (pos);
- marker.Set_Rect (uv_rect);
- marker.Set_Color (color);
- MarkerList.Add (marker);
- //
- // Return the new marker's index
- //
- return (MarkerList.Count () - 1);
- }
- ////////////////////////////////////////////////////////////////
- //
- // Get_Marker_Data
- //
- ////////////////////////////////////////////////////////////////
- uint32
- MapCtrlClass::Get_Marker_Data (int index)
- {
- return MarkerList[index].Get_User_Data ();
- }
- ////////////////////////////////////////////////////////////////
- //
- // Set_Marker_Data
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Set_Marker_Data (int index, uint32 user_data)
- {
- MarkerList[index].Set_User_Data (user_data);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Remove_Marker
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Remove_Marker (int index)
- {
- MarkerList.Delete (index);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Set_Marker_Texture
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Set_Marker_Texture (const char *filename)
- {
- //
- // Load the texture
- //
- TextureClass *texture = WW3DAssetManager::Get_Instance ()->Get_Texture (filename, TextureClass::MIP_LEVELS_1);
- if (texture != NULL) {
- //
- // Get the dimensions of the texture
- //
- // SurfaceClass::SurfaceDescription surface_desc;
- // texture->Get_Level_Description (surface_desc);
- // IconTextureSize.X = surface_desc.Width;
- // IconTextureSize.Y = surface_desc.Height;
- IconTextureSize.X = texture->Get_Width ();
- IconTextureSize.Y = texture->Get_Height ();
- //
- // Set the texture for the map
- //
- IconRenderer.Set_Texture (texture);
- REF_PTR_RELEASE (texture);
- //
- // Force a repaint
- //
- Set_Dirty ();
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Center_View_About_Marker
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Center_View_About_Marker (int marker_index)
- {
- const MapMarkerClass &marker = MarkerList[marker_index];
- //
- // Calculate what pixel position this marker is located at.
- //
- Vector2 map_pos;
- map_pos.X = MapCenterPoint.X + (marker.Get_Position ().X * MapScale.X);
- map_pos.Y = MapCenterPoint.Y - (marker.Get_Position ().Y * MapScale.Y);
- //
- // Now calculate what scroll offset we'd need to be centered
- // about this position
- //
- ScrollPos = map_pos - (MapSize * 0.5F);
- Clamp_Scroll_Pos ();
- //
- // Force a repaint
- //
- Set_Dirty ();
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Marker_From_Pos
- //
- ////////////////////////////////////////////////////////////////
- int
- MapCtrlClass::Marker_From_Pos (const Vector2 &mouse_pos)
- {
- int retval = -1;
- Vector2 center = (MapSize / 2) + ScrollPos;
- //
- // Loop over all the markers in our list
- //
- for (int index = 0; index < MarkerList.Count (); index ++) {
- const MapMarkerClass &marker = MarkerList[index];
- //
- // Calculate what texel position this marker is located at.
- //
- Vector2 map_pos;
- map_pos.X = MapCenterPoint.X + (marker.Get_Position ().X * MapScale.X);
- map_pos.Y = MapCenterPoint.Y - (marker.Get_Position ().Y * MapScale.Y);
- //
- // Get the screen position of this objective
- //
- Vector2 screen_pos = Rect.Center () + ((map_pos - center) * Zoom);
- if (Rect.Contains (screen_pos)) {
-
- //
- // Build a screen rectangle of the marker
- //
- RectClass screen_rect;
- screen_rect.Left = screen_pos.X - (marker.Get_Rect ().Width () / 2);
- screen_rect.Top = screen_pos.Y - (marker.Get_Rect ().Height () / 2);
- screen_rect.Right = screen_rect.Left + marker.Get_Rect ().Width ();
- screen_rect.Bottom = screen_rect.Top + marker.Get_Rect ().Height ();
- //
- // Is the mouse over this marker?
- //
- if (screen_rect.Contains (mouse_pos)) {
- retval = index;
- break;
- }
- }
- }
- return retval;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Clamp_Scroll_Pos
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Clamp_Scroll_Pos (void)
- {
- float width = Rect.Width ();
- float height = Rect.Height ();
- //
- // Determine what our scroll offset should be
- // at this zoom factor
- //
- float max_x_offset = WWMath::Clamp (MapSize.X - width, 0, MapSize.X);
- float max_y_offset = WWMath::Clamp (MapSize.Y - height, 0, MapSize.Y);
- float offset_x = ScrollPos.X / Zoom;
- float offset_y = ScrollPos.Y / Zoom;
- offset_x = WWMath::Clamp (offset_x, -max_x_offset, max_x_offset);
- offset_y = WWMath::Clamp (offset_y, -max_y_offset, max_y_offset);
- //
- // Re-adjust our scroll position so it doesn't go off the page
- //
- ScrollPos.X = offset_x * Zoom;
- ScrollPos.Y = offset_y * Zoom;
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Initialize_Cloud
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Initialize_Cloud (int cells_x, int cells_y)
- {
- Free_Cloud_Data ();
- CloudSize.I = cells_x;
- CloudSize.J = cells_y;
- //
- // Allocate a bit vector large enough to hold the cells
- //
- CloudVector = new uint32[((CloudSize.I * CloudSize.J) / sizeof (uint32)) + 1];
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Reset_Cloud
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Reset_Cloud (void)
- {
- ::memset (CloudVector, 0xFF, sizeof (uint32) * ((CloudSize.I * CloudSize.J) / sizeof (uint32)) + 1);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Set_Cloud_Cell
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Set_Cloud_Cell (int cell_x, int cell_y, bool is_visible)
- {
- if (CloudVector == NULL) {
- return ;
- }
- //
- // Calculate where in our bit-vector the cell lies
- //
- int bit_offset = (cell_y * CloudSize.I) + cell_x;
- int index = bit_offset / 32;
- int bit = (bit_offset - (index * 32)) + 1;
- //
- // Set (or clear) the bit
- //
- if (is_visible) {
- CloudVector[index] &= ~(1 << bit);
- } else {
- CloudVector[index] |= (1 << bit);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Free_Cloud_Data
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Free_Cloud_Data (void)
- {
- if (CloudVector != NULL) {
- delete CloudVector;
- CloudVector = NULL;
- }
- CloudSize.Set (0, 0);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Position_To_Coord
- //
- ////////////////////////////////////////////////////////////////
- Vector3
- MapCtrlClass::Position_To_Coord (const Vector2 &mouse_pos)
- {
- Vector2 percent;
- percent.X = (mouse_pos.X - Rect.Left) / Rect.Width ();
- percent.Y = (mouse_pos.Y - Rect.Top) / Rect.Height ();
- //
- // Calculate the center of the image
- //
- RectClass map_uv_rect (0, 0, 1, 1);
- Vector2 center = (MapSize / 2) + ScrollPos;
- //
- // Calculate the 'zoomed' rectangle (in pixels)
- //
- float width = Rect.Width ();
- float height = Rect.Height ();
- map_uv_rect.Left = center.X - ((width / 2) / Zoom);
- map_uv_rect.Top = center.Y - ((height / 2) / Zoom);
- map_uv_rect.Right = center.X + ((width / 2) / Zoom);
- map_uv_rect.Bottom = center.Y + ((height / 2) / Zoom);
- Vector2 map_pos;
- map_pos.X = map_uv_rect.Left + (map_uv_rect.Width () * percent.X);
- map_pos.Y = map_uv_rect.Top + (map_uv_rect.Height () * percent.Y);
- //
- // Now convert the map position into a world-space position
- //
- Vector3 result;
- result.X = (map_pos.X - MapCenterPoint.X) / MapScale.X;
- result.Y = (MapCenterPoint.Y - map_pos.Y) / MapScale.Y;
- result.Z = 0;
- return result;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Update_Pulse
- //
- ////////////////////////////////////////////////////////////////
- void
- MapCtrlClass::Update_Pulse (void)
- {
- if (IsUsingOverlay == false) {
- return ;
- }
- const float PULSE_RATE = 0.7F;
- const float MIN_OPACITY = 0.5F;
- const float MAX_OPACITY = 1.0F;
- //
- // Pulse the bar
- //
- float delta = PULSE_RATE * (DialogMgrClass::Get_Frame_Time () / 1000.0F);
- OverlayOpacity += PulseDirection * delta;
- //
- // Clamp the opacity
- //
- if (OverlayOpacity <= MIN_OPACITY) {
- OverlayOpacity = MIN_OPACITY;
- PulseDirection = 1.0F;
- } else if (OverlayOpacity >= MAX_OPACITY) {
- OverlayOpacity = MAX_OPACITY;
- PulseDirection = -1.0F;
- }
- int overlay_color = VRGBA_TO_INT32 (Vector4 (1.0F, 1.0F, 1.0F, OverlayOpacity));
- //
- // Update the color vector array
- //
- DynamicVectorClass<unsigned long> &color_array = MapOverlayRenderer.Get_Color_Array ();
- for (int index = 0; index < color_array.Count (); index ++) {
- color_array[index] = overlay_color;
- }
- return ;
- }
|