add more improvements

This commit is contained in:
vld_voiculescu
2026-06-21 22:12:04 +03:00
parent 506ce1a455
commit 8ebe37083a
9 changed files with 268 additions and 113 deletions
+25 -7
View File
@@ -5,7 +5,6 @@
#include "ientity.h"
#include "ieclass.h"
#include "iscenegraph.h"
#include "iundo.h"
#include "qerplugin.h"
#include "scenelib.h"
@@ -39,6 +38,17 @@ static scene::Node& create_func_group(){
return entity;
}
// Select a generated func_group so the user can immediately move it. For a group
// node Entity_setSelected selects its child brushes (what the manipulator acts
// on), which is how Radiant makes a group movable — selecting the entity instance
// directly leaves it unmovable.
static void select_generated( scene::Node& node ){
scene::Path path( makeReference( GlobalSceneGraph().root() ) );
path.push( makeReference( node ) );
if ( scene::Instance* instance = GlobalSceneGraph().find( path ) )
Entity_setSelected( *instance, true );
}
static void insert_brush_into( scene::Node& entity,
double x, double y, double min_z,
double mx, double my, double base_max_z,
@@ -141,8 +151,7 @@ static void insert_brush_into( scene::Node& entity,
void build_terrain_brushes( const BrushData& target, double step_x, double step_y,
const HeightMap& height_map, const char* top_texture,
bool split_diagonally ){
UndoableCommand undo( "terrainGenerator.generateTerrain" );
// Undo is started by the caller so deletion + generation form one step.
scene::Node& entity = create_func_group();
const char* caulk = "textures/common/caulk";
@@ -176,6 +185,8 @@ void build_terrain_brushes( const BrushData& target, double step_x, double step_
}
}
select_generated( entity );
GlobalRadiant().Brush_setDetail( entity );
SceneChangeNotify();
}
@@ -354,8 +365,7 @@ static void insert_wall_brush( scene::Node& entity,
void build_tunnel_brushes( const BrushData& target, double step_x, double step_y,
const TunnelMaps& maps, const char* top_texture,
double cave_height, double slope_height ){
UndoableCommand undo( "terrainGenerator.generateTunnel" );
// Undo is started by the caller so deletion + generation form one step.
scene::Node& floor_entity = create_func_group();
scene::Node& ceil_entity = create_func_group();
scene::Node& lwall_entity = create_func_group();
@@ -382,7 +392,7 @@ void build_tunnel_brushes( const BrushData& target, double step_x, double step_y
auto it = m.find( { r2( kx ), r2( ky ) } );
if ( it == m.end() ) {
globalErrorStream() << "TerrainGenerator: height map missing key ("
<< kx << ", " << ky << ") — using fallback\n";
<< kx << ", " << ky << ") - using fallback\n";
return fallback;
}
return it->second;
@@ -428,7 +438,7 @@ void build_tunnel_brushes( const BrushData& target, double step_x, double step_y
auto it = m.find( { r2( kx ), r2( ky ) } );
if ( it == m.end() ) {
globalErrorStream() << "TerrainGenerator: wall map missing key ("
<< kx << ", " << ky << ") — using fallback\n";
<< kx << ", " << ky << ") - using fallback\n";
return fallback;
}
return it->second;
@@ -453,5 +463,13 @@ void build_tunnel_brushes( const BrushData& target, double step_x, double step_y
}
}
select_generated( floor_entity );
select_generated( ceil_entity );
select_generated( lwall_entity );
select_generated( rwall_entity );
GlobalRadiant().Brush_setDetail( floor_entity );
GlobalRadiant().Brush_setDetail( ceil_entity );
GlobalRadiant().Brush_setDetail( lwall_entity );
GlobalRadiant().Brush_setDetail( rwall_entity );
SceneChangeNotify();
}
+217 -90
View File
@@ -1,6 +1,7 @@
#include "terrain_generator.h"
#include <algorithm>
#include <cstdio>
#include "debugging/debugging.h"
#include "iplugin.h"
#include "string/string.h"
@@ -58,6 +59,17 @@ const char* getCommandTitleList(){
return "";
}
// The entity carrying terrain metadata for a selected instance: the instance's
// node if it is an entity, otherwise its parent (a selected brush's func_group).
static Entity* instance_entity( scene::Instance& instance ){
const scene::Path& p = instance.path();
if ( Node_isEntity( p.top() ) )
return Node_getEntity( p.top().get() );
if ( p.size() > 1 && Node_isEntity( p.parent() ) )
return Node_getEntity( p.parent().get() );
return nullptr;
}
void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush ){
if ( string_equal( command, "About" ) ) {
GlobalRadiant().m_pfnMessageBox( main_window,
@@ -69,6 +81,15 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
return;
}
if ( string_equal( command, "Generate Terrain" ) ) {
// Only one generator dialog at a time. Re-running the command while
// it's open just raises the existing window instead of stacking new ones.
static QDialog* s_active_dialog = nullptr;
if ( s_active_dialog ) {
s_active_dialog->raise();
s_active_dialog->activateWindow();
return;
}
// Query the live selection bounds from the selection system.
// Called at dialog-open time, on mode switch, and on OK — so the
// user can make a selection while the dialog is open and retry.
@@ -90,6 +111,7 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
// --- Build dialog ---
QDialog dialog( main_window, Qt::Dialog | Qt::WindowCloseButtonHint );
dialog.setWindowTitle( "Terrain Generator" );
s_active_dialog = &dialog;
dialog.setMinimumWidth( 420 );
auto *form = new QFormLayout( &dialog );
@@ -101,30 +123,10 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
target_combo->setCurrentIndex( init_sel.valid ? 0 : 1 );
form->addRow( "Target:", target_combo );
// Selection size — live labels (left) + frozen reference labels (right).
// Reference is captured on the first Generate click and stays fixed.
// Helper: build one inline row widget with [current | ref: value]
auto make_sel_row = []( QLabel*& cur_lbl, QLabel*& ref_lbl ) -> QWidget* {
auto *w = new QWidget;
auto *layout = new QHBoxLayout( w );
layout->setContentsMargins( 0, 0, 0, 0 );
layout->setSpacing( 6 );
cur_lbl = new QLabel;
ref_lbl = new QLabel;
ref_lbl->setStyleSheet( "color: gray;" );
ref_lbl->hide();
layout->addWidget( cur_lbl );
layout->addWidget( ref_lbl );
layout->addStretch();
return w;
};
QLabel *sel_w_label, *ref_w_label;
QLabel *sel_l_label, *ref_l_label;
QLabel *sel_h_label, *ref_h_label;
auto *sel_w_row = make_sel_row( sel_w_label, ref_w_label );
auto *sel_l_row = make_sel_row( sel_l_label, ref_l_label );
auto *sel_h_row = make_sel_row( sel_h_label, ref_h_label );
// Selection size — live, read-only labels showing the current selection.
auto *sel_w_label = new QLabel;
auto *sel_l_label = new QLabel;
auto *sel_h_label = new QLabel;
auto refresh_sel_labels = [&](){
const SelBounds s = query_sel();
@@ -134,19 +136,9 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
};
refresh_sel_labels();
// Reference state — captured once on first Generate, frozen after that.
SelBounds ref_bounds{};
bool ref_captured = false;
// "Use reference" checkbox — hidden until first Generate populates it.
auto *use_ref_cb = new QCheckBox( "Use reference for regeneration" );
use_ref_cb->setChecked( true );
use_ref_cb->hide();
form->addRow( "Width (X):", sel_w_row );
form->addRow( "Length (Y):", sel_l_row );
form->addRow( "Height (Z):", sel_h_row );
form->addRow( "", use_ref_cb );
form->addRow( "Width (X):", sel_w_label );
form->addRow( "Length (Y):", sel_l_label );
form->addRow( "Height (Z):", sel_h_label );
// Manual size inputs (shown in Manual Size mode)
auto *manual_w_spin = new SpinBox( 64, 131072, 1024, 0, 64 );
@@ -236,10 +228,9 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
} );
sel_timer->start();
// Poll the texture browser every 100ms; auto-update the field and
// (if the browser was closed before Pick opened it) auto-close it.
// Poll the texture browser every 100ms so picking a shader in it
// updates the texture field automatically.
QString last_polled_shader = texture_edit->text();
bool close_browser_on_pick = false;
auto *pick_timer = new QTimer( &dialog );
pick_timer->setInterval( 100 );
@@ -248,16 +239,18 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
if ( current != last_polled_shader ) {
last_polled_shader = current;
texture_edit->setText( current );
if ( close_browser_on_pick ) {
close_browser_on_pick = false;
GlobalRadiant().TextureBrowser_close();
}
}
} );
pick_timer->start();
// Surface the texture browser and leave it open so the user can keep
// picking. Closing it automatically proved fragile and is poor UX.
// A tooltip covers the embedded-layout case, where there is no separate
// browser window to raise (it's always visible in the main window).
tex_pick->setToolTip( "Open the texture browser to pick a shader.\n"
"If the browser is docked in the main window layout,\n"
"select a texture there and it fills in here automatically." );
QObject::connect( tex_pick, &QPushButton::clicked, [&](){
close_browser_on_pick = !GlobalRadiant().TextureBrowser_isShown();
GlobalRadiant().TextureBrowser_show();
} );
form->addRow( "Texture:", tex_widget );
@@ -284,24 +277,88 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
lbl->setVisible( visible );
};
// --- Per-entity persisted footprint size ------------------------------
// Generated terrain records the footprint SIZE it was built from as a key
// on its func_group(s). On regeneration we reuse that stored size (so the
// terrain stops growing) but take the position from the live selection (so
// it follows wherever the terrain was moved). The size lives on each piece
// of terrain, so a second brush never picks up the first one's size.
const char* const TERRAINGEN_KEY = "_terraingen_size";
// Fills w/l/h and returns true if any selected node (or its parent entity)
// carries a stored footprint size.
auto read_stored_size = [&]( double& w, double& l, double& h ) -> bool {
struct Reader : public SelectionSystem::Visitor {
const char* key;
double *w, *l, *h;
mutable bool found = false;
Reader( const char* k, double* a, double* b, double* c ) : key( k ), w( a ), l( b ), h( c ){}
void visit( scene::Instance& instance ) const override {
if ( found )
return;
Entity* e = instance_entity( instance );
if ( e == nullptr )
return;
const char* v = e->getKeyValue( key );
if ( v != nullptr && v[0] != '\0'
&& std::sscanf( v, "%lf %lf %lf", w, l, h ) == 3
&& *w >= 1.0 && *l >= 1.0 )
found = true;
}
} reader( TERRAINGEN_KEY, &w, &l, &h );
GlobalSelectionSystem().foreachSelected( reader );
return reader.found;
};
// Writes the footprint size onto the entity of every selected node (the
// freshly generated func_group(s), whose brushes the build step selects).
auto write_stored_size = [&]( const SelBounds& s ){
char buf[128];
std::snprintf( buf, sizeof( buf ), "%g %g %g",
s.x1 - s.x0, s.y1 - s.y0, s.z1 - s.z0 );
struct Writer : public SelectionSystem::Visitor {
const char* key;
const char* value;
Writer( const char* k, const char* v ) : key( k ), value( v ){}
void visit( scene::Instance& instance ) const override {
if ( Entity* e = instance_entity( instance ) )
e->setKeyValue( key, value );
}
} writer( TERRAINGEN_KEY, buf );
GlobalSelectionSystem().foreachSelected( writer );
};
// ----------------------------------------------------------------------
// Shared validation + generation — returns true on success.
// Called by both Generate and OK.
auto do_generate = [&]() -> bool {
if ( target_combo->currentIndex() == 0 && !query_sel().valid ) {
GlobalRadiant().m_pfnMessageBox( main_window,
"No valid brush is selected.\n\n"
"Please select a brush in the viewport first,\n"
"or switch the Target to \"Manual Size\".",
"Terrain Generator — No Selection",
EMessageBoxType::Error, 0 );
return false;
if ( target_combo->currentIndex() == 0 ) {
if ( GlobalSelectionSystem().countSelected() == 0 ) {
GlobalRadiant().m_pfnMessageBox( main_window,
"No brush is selected.\n\n"
"Please select a brush in the viewport first,\n"
"or switch the Target to \"Manual Size\".",
"Terrain Generator - No Selection",
EMessageBoxType::Error, 0 );
return false;
}
if ( !query_sel().valid ) {
GlobalRadiant().m_pfnMessageBox( main_window,
"The selected brush is too small.\n\n"
"The terrain area must be at least 64 x 64 units.\n"
"Please select a larger brush,\n"
"or switch the Target to \"Manual Size\".",
"Terrain Generator - Brush Too Small",
EMessageBoxType::Error, 0 );
return false;
}
}
if ( texture_edit->text().trimmed().isEmpty() ) {
GlobalRadiant().m_pfnMessageBox( main_window,
"No texture specified.\n\n"
"Please enter a texture path or use the Pick button\n"
"to select one from the texture browser.",
"Terrain Generator — No Texture",
"Terrain Generator - No Texture",
EMessageBoxType::Error, 0 );
return false;
}
@@ -323,39 +380,61 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
// --- Determine bounds (must happen before deleting the selection brush) ---
BrushData target;
// Footprint to record on the generated entities, so a later
// regeneration reuses it instead of growing.
SelBounds used_bounds{};
bool used_bounds_valid = false;
if ( use_manual ) {
target = make_manual_brush_data( manual_w_spin->value(), manual_l_spin->value(), manual_h_spin->value() );
}
else {
// Use the frozen reference bounds if captured and checkbox is on,
// otherwise sample the live selection.
const bool use_ref = ref_captured && use_ref_cb->isChecked();
const SelBounds s = use_ref ? ref_bounds : query_sel( step_x < step_y ? step_x : step_y );
// Reuse the stored footprint size (so regeneration doesn't grow),
// but take the position from the live selection (so it follows the
// terrain if it was moved). Peaks and walls extend symmetrically,
// so the live center equals the footprint center; the floor sits at
// the live minimum Z. A fresh brush has no stored size and uses its
// own bounds directly.
double sw, sl, sh;
SelBounds s{};
if ( read_stored_size( sw, sl, sh ) ) {
const SelBounds live = query_sel();
if ( live.valid ) {
const double cx = ( live.x0 + live.x1 ) * 0.5;
const double cy = ( live.y0 + live.y1 ) * 0.5;
s.x0 = cx - sw * 0.5; s.x1 = cx + sw * 0.5;
s.y0 = cy - sl * 0.5; s.y1 = cy + sl * 0.5;
s.z0 = live.z0; s.z1 = live.z0 + sh;
s.valid = true;
}
}
else {
s = query_sel( step_x < step_y ? step_x : step_y );
}
if ( s.valid ) {
target.min_x = s.x0;
target.max_x = s.x1;
target.min_y = s.y0;
target.max_y = s.y1;
target.min_z = s.z0;
target.max_z = s.z0 + std::max( s.z1 - s.z0, 64.0 );
// Base level the terrain builds up from. Slopes use the slope
// height so the ramp's top rises with it while its low edge
// stays at the floor (z0 + 64); otherwise a steep slope sinks
// the low edge below the floor, clips away geometry and makes
// regeneration drift sideways. Other shapes use the selection
// height.
const bool is_slope = ( shape == ShapeType::Slope || shape == ShapeType::SlopeTunnel );
const double top_h = is_slope ? std::max( shape_height_spin->value(), 64.0 )
: std::max( s.z1 - s.z0, 64.0 );
target.max_z = s.z0 + top_h;
target.width_x = target.max_x - target.min_x;
target.length_y = target.max_y - target.min_y;
target.height_z = target.max_z - target.min_z;
// Capture reference on first generation (live bounds only, not ref replay).
if ( !ref_captured && !use_ref ) {
ref_bounds = s;
ref_captured = true;
ref_w_label->setText( " Ref (X): " + QString::number( (int)( s.x1 - s.x0 ) ) );
ref_l_label->setText( " Ref (Y): " + QString::number( (int)( s.y1 - s.y0 ) ) );
ref_h_label->setText( " Ref (Z): " + QString::number( (int)std::max( s.z1 - s.z0, 64.0 ) ) );
ref_w_label->show();
ref_l_label->show();
ref_h_label->show();
use_ref_cb->show();
if ( target_combo->currentIndex() == 0 )
set_row_visible( use_ref_cb, true );
}
// Remember the footprint to record on the generated entities
// once the build step completes.
used_bounds = s;
used_bounds_valid = true;
}
else {
target = make_manual_brush_data( manual_w_spin->value(), manual_l_spin->value(), manual_h_spin->value() );
@@ -379,22 +458,47 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
? -( shape_height_spin->value() - 64.0 )
: shape_height_spin->value();
// One undo step covering both removing the source brush and creating
// the generated geometry, so a single Undo restores the original
// brush and removes everything we added.
UndoableCommand undo( "terrainGenerator.generate" );
// --- Delete the selection brush now that its bounds are captured ---
if ( !use_manual ) {
const int sel_count = (int)GlobalSelectionSystem().countSelected();
for ( int i = 0; i < sel_count && GlobalSelectionSystem().countSelected() > 0; ++i )
Path_deleteTop( GlobalSelectionSystem().ultimateSelected().path() );
while ( GlobalSelectionSystem().countSelected() > 0 ) {
scene::Path path( GlobalSelectionSystem().ultimateSelected().path() );
scene::Path parent_path( path );
parent_path.pop();
Path_deleteTop( path );
// Remove a group entity left empty by the deletion, mirroring
// Radiant's own delete behavior (never the worldspawn or root).
if ( parent_path.size() > 1
&& Node_isEntity( parent_path.top() )
&& !parent_path.top().get().isRoot() ) {
Entity* entity = Node_getEntity( parent_path.top() );
scene::Traversable* children = Node_getTraversable( parent_path.top() );
const bool worldspawn = entity != 0 && string_equal( entity->getClassName(), "worldspawn" );
if ( !worldspawn && children != 0 && children->empty() )
Path_deleteTop( parent_path );
}
}
SceneChangeNotify();
}
adjust_bounds_to_fit_grid( target, step_x, step_y );
// Clear any leftover selection so that only the geometry we are
// about to generate ends up selected (the build step selects it).
GlobalSelectionSystem().setSelectedAll( false );
// --- Generate ---
const bool is_tunnel = ( shape == ShapeType::Tunnel || shape == ShapeType::SlopeTunnel );
globalOutputStream() << "TerrainGenerator: generating "
<< ( is_tunnel ? "tunnel" : "terrain" )
<< " — bounds ("
<< " - bounds ("
<< target.width_x << " x " << target.length_y << " x " << target.height_z
<< "), step (" << step_x << " x " << step_y << ")"
<< ", texture: " << texture << "\n";
@@ -413,6 +517,12 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
}
globalOutputStream() << "TerrainGenerator: generation complete\n";
// Record the footprint size on the generated (now selected) entities so
// a future regeneration reuses it instead of the grown geometry's size.
if ( used_bounds_valid )
write_stored_size( used_bounds );
return true;
};
@@ -448,21 +558,27 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
if ( use_sel ) {
refresh_sel_labels();
if ( slope_derived() ) {
const SelBounds s = query_sel();
if ( s.valid )
shape_height_spin->setValue( s.z1 - s.z0 );
// Derive the slope height from the stored footprint height when
// the selection has one, so it stays consistent with the size
// used for generation. Using the live (grown) selection here
// over-steepens the slope and pushes the floor below the base.
double sw, sl, sh;
if ( read_stored_size( sw, sl, sh ) ) {
shape_height_spin->setValue( sh );
}
else {
const SelBounds s = query_sel();
if ( s.valid )
shape_height_spin->setValue( s.z1 - s.z0 );
}
}
}
set_row_visible( sel_w_row, use_sel );
set_row_visible( sel_l_row, use_sel );
set_row_visible( sel_h_row, use_sel );
set_row_visible( sel_w_label, use_sel );
set_row_visible( sel_l_label, use_sel );
set_row_visible( sel_h_label, use_sel );
set_row_visible( manual_w_spin, !use_sel );
set_row_visible( manual_l_spin, !use_sel );
set_row_visible( manual_h_spin, !use_sel );
// Only toggle the checkbox row once a reference has been captured
// (it must never appear in Manual Size mode).
if ( ref_captured )
set_row_visible( use_ref_cb, use_sel );
};
// Advanced sub-square toggle
@@ -484,9 +600,19 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
lbl->setText( shape_height_label[idx] );
// Auto-fill slope height from selection when applicable
if ( slope_derived() ) {
const SelBounds s = query_sel();
if ( s.valid )
shape_height_spin->setValue( s.z1 - s.z0 );
// Derive the slope height from the stored footprint height when
// the selection has one, so it stays consistent with the size
// used for generation. Using the live (grown) selection here
// over-steepens the slope and pushes the floor below the base.
double sw, sl, sh;
if ( read_stored_size( sw, sl, sh ) ) {
shape_height_spin->setValue( sh );
}
else {
const SelBounds s = query_sel();
if ( s.valid )
shape_height_spin->setValue( s.z1 - s.z0 );
}
}
}
set_row_visible( tunnel_height_spin, is_slope_tunnel );
@@ -514,6 +640,7 @@ void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush
QObject::connect( &dialog, &QDialog::finished, &loop, &QEventLoop::quit );
loop.exec();
}
s_active_dialog = nullptr;
}
}
+1 -2
View File
@@ -153,8 +153,7 @@ struct _QERFuncTable_1
// Plugin extensions — always append new members here to preserve ABI
void ( *TextureBrowser_show )( );
bool ( *TextureBrowser_isShown )( );
void ( *TextureBrowser_close )( );
void ( *Brush_setDetail )( scene::Node& node );
};
#include "modulesystem.h"
+20
View File
@@ -658,6 +658,26 @@ void Scene_BrushSetDetail_Selected( scene::Graph& graph, bool detail ){
SceneChangeNotify();
}
class BrushSetDetailWalker : public scene::Traversable::Walker
{
public:
bool pre( scene::Node& node ) const override {
if ( Brush* brush = Node_getBrush( node ) ) {
Brush_forEachFace( *brush, []( Face& face ){ face.setDetail( true ); } );
}
return true;
}
};
void Brush_setDetail( scene::Node& node ){
if ( Brush* brush = Node_getBrush( node ) ) {
Brush_forEachFace( *brush, []( Face& face ){ face.setDetail( true ); } );
}
else if ( scene::Traversable* traversable = Node_getTraversable( node ) ) {
traversable->traverse( BrushSetDetailWalker() );
}
}
bool Face_FindReplaceShader( Face& face, const char* find, const char* replace ){
if ( shader_equal( face.GetShader(), find ) ) {
face.SetShader( replace );
+3
View File
@@ -45,6 +45,9 @@ class Graph;
class Node;
}
void Scene_BrushConstructPrefab( scene::Graph& graph, EBrushPrefab type, std::size_t sides, bool option, const char* shader );
// Flag every brush in 'node' (a brush, or any node whose subgraph contains
// brushes, e.g. a group entity) as detail.
void Brush_setDetail( scene::Node& node );
class AABB;
void Scene_BrushResize_Cuboid( scene::Node*& node, const AABB& bounds );
void Brush_ConstructPlacehoderCuboid( scene::Node& node, const AABB& bounds );
-1
View File
@@ -40,7 +40,6 @@ typedef ConstPointerCaller<char, void(const StringImportCallback&), RawStringExp
QWidget* GroupDialog_addPage( const char* tabLabel, QWidget* widget, const StringExportCallback& title );
bool GroupDialog_isShown();
void GroupDialog_setShown( bool shown );
QWidget* GroupDialog_getPage();
void GroupDialog_showPage( QWidget* page );
void GroupDialog_updatePageTitle( QWidget* page );
+2 -2
View File
@@ -58,6 +58,7 @@
#include "texwindow.h"
#include "modelwindow.h"
#include "mainframe.h"
#include "brushmanip.h"
#include "build.h"
#include "mru.h"
#include "surfacedialog.h"
@@ -152,8 +153,7 @@ public:
m_radiantcore.TextureBrowser_getSelectedShader = TextureBrowser_GetSelectedShader;
m_radiantcore.TextureBrowser_show = TextureBrowser_show;
m_radiantcore.TextureBrowser_isShown = TextureBrowser_isShown;
m_radiantcore.TextureBrowser_close = TextureBrowser_close;
m_radiantcore.Brush_setDetail = Brush_setDetail;
m_radiantcore.m_pfnMessageBox = &qt_MessageBox;
m_radiantcore.m_pfnFileDialog = &file_dialog;
-9
View File
@@ -633,15 +633,6 @@ void TextureBrowser_show(){
GroupDialog_showPage( g_page_textures ); // switch to textures tab and show
}
bool TextureBrowser_isShown(){
return g_page_textures && GroupDialog_isShown() && GroupDialog_getPage() == g_page_textures;
}
void TextureBrowser_close(){
GroupDialog_setShown( false );
}
void TextureBrowser_updateTitle(){
GroupDialog_updatePageTitle( g_page_textures );
}
-2
View File
@@ -32,8 +32,6 @@ void TextureBrowser_destroyWindow();
const char* TextureBrowser_GetSelectedShader();
void TextureBrowser_show();
bool TextureBrowser_isShown();
void TextureBrowser_close();
void TextureBrowser_Construct();
void TextureBrowser_Destroy();