From 5cfeccea09b7fe34f457736b79e2168da1d04c82 Mon Sep 17 00:00:00 2001 From: historic_bruno Date: Tue, 17 Apr 2012 02:43:52 +0000 Subject: [PATCH] Adds eyedropper tool to Atlas terrain brush (Shift+Click to activate). Fixes #1122. Adds preview box showing currently selected terrain. This was SVN commit r11528. --- .../AtlasUI/ScenarioEditor/ScenarioEditor.cpp | 3 + .../Sections/Terrain/Terrain.cpp | 134 +++++++++++++-- .../ScenarioEditor/Sections/Terrain/Terrain.h | 6 +- .../ScenarioEditor/Tools/Common/MiscState.cpp | 4 +- .../ScenarioEditor/Tools/Common/MiscState.h | 2 +- .../ScenarioEditor/Tools/PaintTerrain.cpp | 74 +++++++- .../Handlers/TerrainHandlers.cpp | 159 +++++++++++------- source/tools/atlas/GameInterface/Messages.h | 20 ++- source/tools/atlas/GameInterface/Shareable.h | 2 +- 9 files changed, 325 insertions(+), 79 deletions(-) diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp index b80570841f..f402196019 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp @@ -373,6 +373,9 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent, ScriptInterface& scriptInterfac // wxLog::SetTraceMask(wxTraceMessages); + g_SelectedTexture = _T("grass1_spring"); + g_SelectedTexture.NotifyObservers(); + SetOpenFilename(_T("")); #if defined(__WXMSW__) diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp index 36148aada0..1b10b0a027 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Wildfire Games. +/* Copyright (C) 2012 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -45,7 +45,6 @@ private: TextureNotebook* m_Textures; }; - enum { ID_Passability = 1, @@ -60,6 +59,118 @@ static wxWindow* Tooltipped(wxWindow* window, const wxString& tip) return window; } +// Add spaces into the displayed name so there are more wrapping opportunities +static wxString FormatTextureName(wxString name) +{ + if (name.Len()) + name[0] = wxToupper(name[0]); + name.Replace(_T("_"), _T(" ")); + + return name; +} + +////////////////////////////////////////////////////////////////////////// + +class TexturePreviewPanel : public wxPanel +{ +private: + static const int imageWidth = 120; + static const int imageHeight = 40; + +public: + TexturePreviewPanel(wxWindow* parent) + : wxPanel(parent, wxID_ANY), m_Timer(this) + { + m_Conn = g_SelectedTexture.RegisterObserver(0, &TexturePreviewPanel::OnTerrainChange, this); + m_Sizer = new wxStaticBoxSizer(wxVERTICAL, this, _T("Texture")); + SetSizer(m_Sizer); + + // Use placeholder bitmap for now + m_Sizer->Add(new wxStaticBitmap(this, wxID_ANY, wxNullBitmap), wxSizerFlags(1).Expand()); + } + + void LoadPreview() + { + if (m_TextureName.IsEmpty()) + { + // If we haven't got a texture yet, copy the global + m_TextureName = g_SelectedTexture; + } + + Freeze(); + + m_Sizer->Clear(true); + + AtlasMessage::qGetTerrainTexturePreview qry(m_TextureName.wc_str(), imageWidth, imageHeight); + qry.Post(); + + AtlasMessage::sTerrainTexturePreview preview = qry.preview; + + // Check for invalid/missing texture - shouldn't happen + if (!wxString(qry.preview->name.c_str()).IsEmpty()) + { + // Construct the wrapped-text label + wxStaticText* label = new wxStaticText(this, wxID_ANY, FormatTextureName(*qry.preview->name), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER); + label->Wrap(m_Sizer->GetSize().GetX()); + + unsigned char* buf = (unsigned char*)(malloc(preview.imageData.GetSize())); + // imagedata.GetBuffer() gives a Shareable*, which + // is stored the same as a unsigned char*, so we can just copy it. + memcpy(buf, preview.imageData.GetBuffer(), preview.imageData.GetSize()); + wxImage img(qry.preview->imageWidth, qry.preview->imageHeight, buf); + + wxStaticBitmap* bitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(img), wxDefaultPosition, wxSize(qry.preview->imageWidth, qry.preview->imageHeight), wxBORDER_SIMPLE); + m_Sizer->Add(bitmap, wxSizerFlags(1).Align(wxALIGN_CENTRE)); + m_Sizer->Add(label, wxSizerFlags().Expand()); + + // We have to force the sidebar to layout manually + GetParent()->Layout(); + + if (preview.loaded && m_Timer.IsRunning()) + { + m_Timer.Stop(); + } + else if (!preview.loaded && !m_Timer.IsRunning()) + { + m_Timer.Start(2000); + } + } + + Layout(); + Thaw(); + } + + void OnTerrainChange(const wxString& texture) + { + // Check if texture really changed, to avoid doing this too often + if (texture != m_TextureName) + { + // Load new texture preview + m_TextureName = texture; + LoadPreview(); + } + } + + void OnTimer(wxTimerEvent& WXUNUSED(evt)) + { + LoadPreview(); + } + +private: + ObservableScopedConnection m_Conn; + wxSizer* m_Sizer; + wxTimer m_Timer; + wxString m_TextureName; + + DECLARE_EVENT_TABLE(); +}; + +BEGIN_EVENT_TABLE(TexturePreviewPanel, wxPanel) + EVT_TIMER(wxID_ANY, TexturePreviewPanel::OnTimer) +END_EVENT_TABLE(); + +////////////////////////////////////////////////////////////////////////// + TerrainSidebar::TerrainSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebarContainer, wxWindow* bottomBarContainer) : Sidebar(scenarioEditor, sidebarContainer, bottomBarContainer) { @@ -84,7 +195,7 @@ TerrainSidebar::TerrainSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebar wxSizer* sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Texture tools")); wxSizer* gridSizer = new wxGridSizer(3); gridSizer->Add(Tooltipped(new ToolButton(scenarioEditor.GetToolManager(), this, _("Paint"), _T("PaintTerrain")), - _("Brush with left mouse button to paint texture dominantly,\nright mouse button to paint submissively")), wxSizerFlags().Expand()); + _("Brush with left mouse button to paint texture dominantly,\nright mouse button to paint submissively.\nShift-left-click for eyedropper tool")), wxSizerFlags().Expand()); gridSizer->Add(Tooltipped(new ToolButton(scenarioEditor.GetToolManager(), this, _("Replace"), _T("ReplaceTerrain")), _("Replace all of a terrain texture with a new one")), wxSizerFlags().Expand()); gridSizer->Add(Tooltipped(new ToolButton(scenarioEditor.GetToolManager(), this, _("Fill"), _T("FillTerrain")), @@ -97,6 +208,10 @@ TerrainSidebar::TerrainSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebar ///////////////////////////////////////////////////////////////////////// // Brush settings wxSizer* sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Brush")); + + m_TexturePreview = new TexturePreviewPanel(this); + sizer->Add(m_TexturePreview, wxSizerFlags(1).Expand()); + g_Brush_Elevation.CreateUI(this, sizer); m_MainSizer->Add(sizer, wxSizerFlags().Expand().Border(wxTOP, 10)); } @@ -145,6 +260,7 @@ void TerrainSidebar::OnFirstDisplay() m_PassabilityChoice->Append(passClasses[i].c_str()); static_cast(m_BottomBar)->LoadTerrain(); + m_TexturePreview->LoadPreview(); } void TerrainSidebar::OnPassabilityChoice(wxCommandEvent& evt) @@ -245,7 +361,7 @@ public: AtlasMessage::qGetTerrainGroupPreviews qry((std::wstring)m_Name.wc_str(), imageWidth, imageHeight); qry.Post(); - std::vector previews = *qry.previews; + std::vector previews = *qry.previews; bool allLoaded = true; @@ -254,15 +370,10 @@ public: if (!previews[i].loaded) allLoaded = false; - // Construct the wrapped-text label wxString name = previews[i].name.c_str(); - // Add spaces into the displayed name so there are more wrapping opportunities - wxString labelText = name; - if (labelText.Len()) - labelText[0] = wxToupper(labelText[0]); - labelText.Replace(_T("_"), _T(" ")); - wxStaticText* label = new wxStaticText(m_ScrolledPanel, wxID_ANY, labelText, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER); + // Construct the wrapped-text label + wxStaticText* label = new wxStaticText(m_ScrolledPanel, wxID_ANY, FormatTextureName(name), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER); label->Wrap(imageWidth); unsigned char* buf = (unsigned char*)(malloc(previews[i].imageData.GetSize())); @@ -303,6 +414,7 @@ public: wxButton* button = wxDynamicCast(evt.GetEventObject(), wxButton); wxString name = static_cast(button->GetClientObject())->GetData(); g_SelectedTexture = name; + g_SelectedTexture.NotifyObservers(); if (m_LastTerrainSelection) m_LastTerrainSelection->SetBackgroundColour(wxNullColour); diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.h b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.h index eae1d7aa2c..3ef05df4f5 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.h +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Wildfire Games. +/* Copyright (C) 2012 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -17,6 +17,8 @@ #include "../Common/Sidebar.h" +class TexturePreviewPanel; + class TerrainSidebar : public Sidebar { public: @@ -31,6 +33,8 @@ private: void OnResizeMap(wxCommandEvent& evt); wxChoice* m_PassabilityChoice; + TexturePreviewPanel* m_TexturePreview; DECLARE_EVENT_TABLE(); }; + diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/MiscState.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/MiscState.cpp index 88e6ec8ebf..89fbfd0db0 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/MiscState.cpp +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/MiscState.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2012 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -19,6 +19,6 @@ #include "MiscState.h" -wxString g_SelectedTexture = _T("grass1_spring"); +Observable g_SelectedTexture; Observable > g_SelectedObjects; diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/MiscState.h b/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/MiscState.h index b1f6672803..60b9f89ac9 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/MiscState.h +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/MiscState.h @@ -25,7 +25,7 @@ namespace AtlasMessage typedef unsigned int ObjectID; } -extern wxString g_SelectedTexture; +extern Observable g_SelectedTexture; extern Observable > g_SelectedObjects; diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PaintTerrain.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PaintTerrain.cpp index d819234ccc..aca48f35ee 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PaintTerrain.cpp +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PaintTerrain.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2012 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -31,10 +31,18 @@ class PaintTerrain : public StateDrivenTool Position m_Pos; + // Brush for eyedropper preview + // (it's confusing if we use the arbitrarily sized paint brush) + Brush m_EyedropperBrush; + + static const wxKeyCode EYEDROPPER_HOTKEY = WXK_SHIFT; + public: PaintTerrain() { SetState(&Waiting); + + m_EyedropperBrush.SetSquare(2); } @@ -49,9 +57,21 @@ public: POST_MESSAGE(BrushPreview, (false, Position())); } - struct sWaiting : public State { + bool OnKey(PaintTerrain* obj, wxKeyEvent& evt, KeyEventType type) + { + if (type == KEY_DOWN && evt.GetKeyCode() == EYEDROPPER_HOTKEY) + { + SET_STATE(Eyedropper); + return true; + } + else + { + return false; + } + } + bool OnMouse(PaintTerrain* obj, wxMouseEvent& evt) { if (evt.LeftDown()) @@ -135,6 +155,56 @@ public: int GetPriority() { return AtlasMessage::ePaintTerrainPriority::LOW; } } PaintingLow; + + struct sEyedropper : public State + { + void OnEnter(PaintTerrain* obj) + { + obj->m_EyedropperBrush.MakeActive(); + } + + void OnLeave(PaintTerrain* WXUNUSED(obj)) + { + g_Brush_Elevation.MakeActive(); + } + + bool OnKey(PaintTerrain* obj, wxKeyEvent& evt, KeyEventType type) + { + if (type == KEY_UP && evt.GetKeyCode() == EYEDROPPER_HOTKEY) + { + SET_STATE(Waiting); + return true; + } + else + { + return false; + } + } + + bool OnMouse(PaintTerrain* WXUNUSED(obj), wxMouseEvent& evt) + { + if (evt.ButtonDown() || evt.Dragging()) + { + POST_MESSAGE(BrushPreview, (true, evt.GetPosition())); + AtlasMessage::qGetTerrainTexture qry(evt.GetPosition()); + qry.Post(); + + g_SelectedTexture = wxString(qry.texture.c_str()); + g_SelectedTexture.NotifyObservers(); + return true; + } + else if (evt.Moving()) + { + POST_MESSAGE(BrushPreview, (true, Position(evt.GetPosition()))); + return true; + } + else + { + return false; + } + } + } + Eyedropper; }; IMPLEMENT_DYNAMIC_CLASS(PaintTerrain, StateDrivenTool); diff --git a/source/tools/atlas/GameInterface/Handlers/TerrainHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/TerrainHandlers.cpp index bb9add4cc7..84ab80ed0e 100644 --- a/source/tools/atlas/GameInterface/Handlers/TerrainHandlers.cpp +++ b/source/tools/atlas/GameInterface/Handlers/TerrainHandlers.cpp @@ -51,74 +51,81 @@ QUERYHANDLER(GetTerrainGroups) msg->groupNames = groupNames; } -static bool CompareTerrain(const sTerrainGroupPreview& a, const sTerrainGroupPreview& b) +static bool CompareTerrain(const sTerrainTexturePreview& a, const sTerrainTexturePreview& b) { return (wcscmp(a.name.c_str(), b.name.c_str()) < 0); } +static sTerrainTexturePreview GetPreview(CTerrainTextureEntry* tex, int width, int height) +{ + sTerrainTexturePreview preview; + preview.name = tex->GetTag().FromUTF8(); + + std::vector buf (width*height*3); + +#if !CONFIG2_GLES + // It's not good to shrink the entire texture to fit the small preview + // window, since it's the fine details in the texture that are + // interesting; so just go down one mipmap level, then crop a chunk + // out of the middle. + + // Read the size of the texture. (Usually loads the texture from + // disk, which is slow.) + tex->GetTexture()->Bind(); + int level = 1; // level 0 is the original size + int w = std::max(1, (int)tex->GetTexture()->GetWidth() >> level); + int h = std::max(1, (int)tex->GetTexture()->GetHeight() >> level); + + if (w >= width && h >= height) + { + // Read the whole texture into a new buffer + unsigned char* texdata = new unsigned char[w*h*3]; + glGetTexImage(GL_TEXTURE_2D, level, GL_RGB, GL_UNSIGNED_BYTE, texdata); + + // Extract the middle section (as a representative preview), + // and copy into buf + unsigned char* texdata_ptr = texdata + (w*(h - height)/2 + (w - width)/2) * 3; + unsigned char* buf_ptr = &buf[0]; + for (ssize_t y = 0; y < height; ++y) + { + memcpy(buf_ptr, texdata_ptr, width*3); + buf_ptr += width*3; + texdata_ptr += w*3; + } + + delete[] texdata; + } + else +#endif + { + // Too small to preview, or glGetTexImage not supported (on GLES) + // Just use a flat color instead + u32 c = tex->GetBaseColor(); + for (ssize_t i = 0; i < width*height; ++i) + { + buf[i*3+0] = (c>>16) & 0xff; + buf[i*3+1] = (c>>8) & 0xff; + buf[i*3+2] = (c>>0) & 0xff; + } + } + + preview.loaded = tex->GetTexture()->IsLoaded(); + preview.imageWidth = width; + preview.imageHeight = height; + preview.imageData = buf; + + return preview; +} + QUERYHANDLER(GetTerrainGroupPreviews) { - std::vector previews; + std::vector previews; CTerrainGroup* group = g_TexMan.FindGroup(CStrW(*msg->groupName).ToUTF8()); for (std::vector::const_iterator it = group->GetTerrains().begin(); it != group->GetTerrains().end(); ++it) { - previews.push_back(sTerrainGroupPreview()); - previews.back().name = (*it)->GetTag().FromUTF8(); - - std::vector buf (msg->imageWidth*msg->imageHeight*3); - -#if !CONFIG2_GLES - // It's not good to shrink the entire texture to fit the small preview - // window, since it's the fine details in the texture that are - // interesting; so just go down one mipmap level, then crop a chunk - // out of the middle. - - // Read the size of the texture. (Usually loads the texture from - // disk, which is slow.) - (*it)->GetTexture()->Bind(); - int level = 1; // level 0 is the original size - int w = std::max(1, (int)(*it)->GetTexture()->GetWidth() >> level); - int h = std::max(1, (int)(*it)->GetTexture()->GetHeight() >> level); - - if (w >= msg->imageWidth && h >= msg->imageHeight) - { - // Read the whole texture into a new buffer - unsigned char* texdata = new unsigned char[w*h*3]; - glGetTexImage(GL_TEXTURE_2D, level, GL_RGB, GL_UNSIGNED_BYTE, texdata); - - // Extract the middle section (as a representative preview), - // and copy into buf - unsigned char* texdata_ptr = texdata + (w*(h - msg->imageHeight)/2 + (w - msg->imageWidth)/2) * 3; - unsigned char* buf_ptr = &buf[0]; - for (ssize_t y = 0; y < msg->imageHeight; ++y) - { - memcpy(buf_ptr, texdata_ptr, msg->imageWidth*3); - buf_ptr += msg->imageWidth*3; - texdata_ptr += w*3; - } - - delete[] texdata; - } - else -#endif - { - // Too small to preview, or glGetTexImage not supported (on GLES) - // Just use a flat color instead - u32 c = (*it)->GetBaseColor(); - for (ssize_t i = 0; i < msg->imageWidth*msg->imageHeight; ++i) - { - buf[i*3+0] = (c>>16) & 0xff; - buf[i*3+1] = (c>>8) & 0xff; - buf[i*3+2] = (c>>0) & 0xff; - } - } - - previews.back().loaded = (*it)->GetTexture()->IsLoaded(); - previews.back().imageWidth = msg->imageWidth; - previews.back().imageHeight = msg->imageHeight; - previews.back().imageData = buf; - } + previews.push_back(GetPreview(*it, msg->imageWidth, msg->imageHeight)); + } // Sort the list alphabetically by name std::sort(previews.begin(), previews.end(), CompareTerrain); @@ -139,6 +146,42 @@ QUERYHANDLER(GetTerrainPassabilityClasses) } } +QUERYHANDLER(GetTerrainTexture) +{ + ssize_t x, y; + g_CurrentBrush.m_Centre = msg->pos->GetWorldSpace(); + g_CurrentBrush.GetCentre(x, y); + + CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); + CMiniPatch* tile = terrain->GetTile(x, y); + if (tile) + { + CTerrainTextureEntry* tex = tile->GetTextureEntry(); + msg->texture = tex->GetTag().FromUTF8(); + } + else + { + msg->texture = std::wstring(); + } +} + +QUERYHANDLER(GetTerrainTexturePreview) +{ + CTerrainTextureEntry* tex = g_TexMan.FindTexture(CStrW(*msg->name).ToUTF8()); + if (tex) + { + msg->preview = GetPreview(tex, msg->imageWidth, msg->imageHeight); + } + else + { + sTerrainTexturePreview noPreview; + noPreview.name = std::wstring(); + noPreview.imageHeight = 0; + noPreview.imageWidth = 0; + msg->preview = noPreview; + } +} + ////////////////////////////////////////////////////////////////////////// namespace { diff --git a/source/tools/atlas/GameInterface/Messages.h b/source/tools/atlas/GameInterface/Messages.h index 983d13aedc..2cdcb72b38 100644 --- a/source/tools/atlas/GameInterface/Messages.h +++ b/source/tools/atlas/GameInterface/Messages.h @@ -260,7 +260,7 @@ QUERY(GetTerrainGroups, ); #ifndef MESSAGES_SKIP_STRUCTS -struct sTerrainGroupPreview +struct sTerrainTexturePreview { Shareable name; Shareable loaded; @@ -268,7 +268,7 @@ struct sTerrainGroupPreview Shareable imageHeight; Shareable > imageData; // RGB*width*height }; -SHAREABLE_STRUCT(sTerrainGroupPreview); +SHAREABLE_STRUCT(sTerrainTexturePreview); #endif QUERY(GetTerrainGroupPreviews, @@ -276,7 +276,7 @@ QUERY(GetTerrainGroupPreviews, ((int, imageWidth)) ((int, imageHeight)) , - ((std::vector, previews)) + ((std::vector, previews)) ); QUERY(GetTerrainPassabilityClasses, @@ -284,6 +284,14 @@ QUERY(GetTerrainPassabilityClasses, ((std::vector, classNames)) ); +QUERY(GetTerrainTexturePreview, + ((std::wstring, name)) + ((int, imageWidth)) + ((int, imageHeight)) + , + ((sTerrainTexturePreview, preview)) + ); + ////////////////////////////////////////////////////////////////////////// #ifndef MESSAGES_SKIP_STRUCTS @@ -483,6 +491,12 @@ COMMAND(FillTerrain, NOMERGE, ((std::wstring, texture)) ); +QUERY(GetTerrainTexture, + ((Position, pos)) + , + ((std::wstring, texture)) + ); + ////////////////////////////////////////////////////////////////////////// QUERY(PickObject, diff --git a/source/tools/atlas/GameInterface/Shareable.h b/source/tools/atlas/GameInterface/Shareable.h index 538191b640..337e44e8ec 100644 --- a/source/tools/atlas/GameInterface/Shareable.h +++ b/source/tools/atlas/GameInterface/Shareable.h @@ -118,7 +118,7 @@ SHAREABLE_PRIMITIVE(void*); // Shareable containers must have shareable contents - but it's easy to forget // to declare them, so make sure the errors are almost readable, like: // "use of undefined type 'REQUIRE_TYPE_TO_BE_SHAREABLE_FAILURE -// with [ T=AtlasMessage::sTerrainGroupPreview, __formal=false ]" +// with [ T=AtlasMessage::sTerrainTexturePreview, __formal=false ]" // // (Implementation based on boost/static_assert) template struct REQUIRE_TYPE_TO_BE_SHAREABLE_FAILURE;