From ad67f4be71255a77df93afffe07a1ea5271224b2 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+tropicaaal@users.noreply.github.com> Date: Sun, 29 Mar 2026 15:41:46 -0500 Subject: [PATCH] refactor: configure classic panorama at compile-time --- Minecraft.Assets/Common/res/lang/en_US.lang | 1 - Minecraft.Client/GameState/Options.cpp | 18 +- Minecraft.Client/GameState/Options.h | 4 +- Minecraft.Client/UI/Screens/TitleScreen.cpp | 353 +++++++++--------- .../UI/Screens/VideoSettingsScreen.cpp | 3 +- Minecraft.Client/meson.build | 4 + meson.options | 5 + 7 files changed, 188 insertions(+), 200 deletions(-) diff --git a/Minecraft.Assets/Common/res/lang/en_US.lang b/Minecraft.Assets/Common/res/lang/en_US.lang index 890a2f576..44040b2b7 100644 --- a/Minecraft.Assets/Common/res/lang/en_US.lang +++ b/Minecraft.Assets/Common/res/lang/en_US.lang @@ -189,7 +189,6 @@ options.renderDistance.short=Short options.renderDistance.normal=Normal options.renderDistance.far=Far options.viewBobbing=View Bobbing -options.classicPanorama=Classic Panorama options.ao=Smooth Lighting options.anaglyph=3D Anaglyph options.framerateLimit=Performance diff --git a/Minecraft.Client/GameState/Options.cpp b/Minecraft.Client/GameState/Options.cpp index 3f6f4e4b1..07549b5c4 100644 --- a/Minecraft.Client/GameState/Options.cpp +++ b/Minecraft.Client/GameState/Options.cpp @@ -16,7 +16,7 @@ // 4J - the Option sub-class used to be an java enumerated type, trying to // emulate that functionality here -const Options::Option Options::Option::options[18] = { +const Options::Option Options::Option::options[17] = { Options::Option(L"options.music", true, false), Options::Option(L"options.sound", true, false), Options::Option(L"options.invertMouse", false, true), @@ -34,7 +34,6 @@ const Options::Option Options::Option::options[18] = { Options::Option(L"options.gamma", true, false), Options::Option(L"options.renderClouds", false, true), Options::Option(L"options.particles", false, false), - Options::Option(L"options.classicPanorama", false, true), }; const Options::Option* Options::Option::MUSIC = &Options::Option::options[0]; @@ -66,8 +65,6 @@ const Options::Option* Options::Option::RENDER_CLOUDS = &Options::Option::options[15]; const Options::Option* Options::Option::PARTICLES = &Options::Option::options[16]; -const Options::Option* Options::Option::CLASSIC_PANORAMA = - &(Options::Option::options[17]); const Options::Option* Options::Option::getItem(int id) { return &options[id]; } @@ -114,8 +111,6 @@ void Options::init() { invertYMouse = false; viewDistance = 0; bobView = true; - // 4jcraft - classicPanorama = false; anaglyph3d = false; advancedOpengl = false; @@ -245,10 +240,6 @@ void Options::toggle(const Options::Option* option, int dir) { // 4J-PB - changing // 4jcraft: uncommented this so that the view bobbing option works if (option == Option::VIEW_BOBBING) bobView = !bobView; - // 4jcraft - if (option == Option::CLASSIC_PANORAMA) { - classicPanorama = !classicPanorama; - } if (option == Option::RENDER_CLOUDS) renderClouds = !renderClouds; if (option == Option::ADVANCED_OPENGL) { advancedOpengl = !advancedOpengl; @@ -301,8 +292,6 @@ bool Options::getBooleanValue(const Options::Option* item) { // types if (item == Option::INVERT_MOUSE) return invertYMouse; if (item == Option::VIEW_BOBBING) return bobView; - // 4jcraft - if (item == Option::CLASSIC_PANORAMA) return classicPanorama; if (item == Option::ANAGLYPH) return anaglyph3d; if (item == Option::ADVANCED_OPENGL) return advancedOpengl; if (item == Option::AMBIENT_OCCLUSION) return ambientOcclusion; @@ -415,8 +404,6 @@ void Options::load() { if (cmds[0] == L"guiScale") guiScale = _fromString(cmds[1]); if (cmds[0] == L"particles") particles = _fromString(cmds[1]); if (cmds[0] == L"bobView") bobView = cmds[1] == L"true"; - // 4jcraft - if (cmds[0] == L"classicPanorama") classicPanorama = cmds[1] == L"true"; if (cmds[0] == L"anaglyph3d") anaglyph3d = cmds[1] == L"true"; if (cmds[0] == L"advancedOpengl") advancedOpengl = cmds[1] == L"true"; if (cmds[0] == L"fpsLimit") framerateLimit = _fromString(cmds[1]); @@ -471,9 +458,6 @@ void Options::save() { dos.writeChars(L"guiScale:" + _toString(guiScale)); dos.writeChars(L"particles:" + _toString(particles)); dos.writeChars(L"bobView:" + std::wstring(bobView ? L"true" : L"false")); - // 4jcraft - dos.writeChars(L"classicPanorama:" + - std::wstring(classicPanorama ? L"true" : L"false")); dos.writeChars(L"anaglyph3d:" + std::wstring(anaglyph3d ? L"true" : L"false")); dos.writeChars(L"advancedOpengl:" + diff --git a/Minecraft.Client/GameState/Options.h b/Minecraft.Client/GameState/Options.h index bb84fc759..b727da4a0 100644 --- a/Minecraft.Client/GameState/Options.h +++ b/Minecraft.Client/GameState/Options.h @@ -13,7 +13,7 @@ public: // 4J - this used to be an enum class Option { public: - static const Option options[18]; + static const Option options[17]; static const Option* MUSIC; static const Option* SOUND; static const Option* INVERT_MOUSE; @@ -31,7 +31,6 @@ public: static const Option* GAMMA; static const Option* RENDER_CLOUDS; static const Option* PARTICLES; - static const Option* CLASSIC_PANORAMA; private: const bool _isProgress; @@ -62,7 +61,6 @@ public: bool invertYMouse; int viewDistance; bool bobView; - bool classicPanorama; bool anaglyph3d; bool advancedOpengl; int framerateLimit; diff --git a/Minecraft.Client/UI/Screens/TitleScreen.cpp b/Minecraft.Client/UI/Screens/TitleScreen.cpp index 650d49af8..8aac613d5 100644 --- a/Minecraft.Client/UI/Screens/TitleScreen.cpp +++ b/Minecraft.Client/UI/Screens/TitleScreen.cpp @@ -164,204 +164,203 @@ void TitleScreen::buttonClicked(Button* button) { // method void TitleScreen::renderPanorama(float a) { #ifdef ENABLE_JAVA_GUIS + Tesselator* t = Tesselator::getInstance(); - if (minecraft->options->classicPanorama) { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - gluPerspective(120.0f, 1.0f, 0.05f, 10.0f); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - glRotatef(180.0f, 1.0f, 0.0f, 0.0f); - glEnable(GL_BLEND); - glDisable(GL_ALPHA_TEST); - glDisable(GL_CULL_FACE); - glDepthMask(false); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - char offsetPasses = 8; +#ifdef CLASSIC_PANORAMA + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + gluPerspective(120.0f, 1.0f, 0.05f, 10.0f); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glRotatef(180.0f, 1.0f, 0.0f, 0.0f); + glEnable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glDisable(GL_CULL_FACE); + glDepthMask(false); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + char offsetPasses = 8; - for (int i = 0; i < (offsetPasses * offsetPasses); i++) { + for (int i = 0; i < (offsetPasses * offsetPasses); i++) { + glPushMatrix(); + float x = + ((float)(i % offsetPasses) / (float)offsetPasses - 0.5f) / 64.0f; + float y = + ((float)(i / offsetPasses) / (float)offsetPasses - 0.5f) / 64.0f; + float z = 0.0f; + glTranslatef(x, y, z); + glRotatef(sin((vo + a) / 400.0f) * 25.0f + 20.0f, 1.0f, 0.0f, 0.0f); + glRotatef(-(vo + a) * 0.1f, 0.0f, 1.0f, 0.0f); + + for (int j = 0; j < 6; j++) { glPushMatrix(); - float x = ((float)(i % offsetPasses) / (float)offsetPasses - 0.5f) / - 64.0f; - float y = ((float)(i / offsetPasses) / (float)offsetPasses - 0.5f) / - 64.0f; - float z = 0.0f; - glTranslatef(x, y, z); - glRotatef(sin((vo + a) / 400.0f) * 25.0f + 20.0f, 1.0f, 0.0f, 0.0f); - glRotatef(-(vo + a) * 0.1f, 0.0f, 1.0f, 0.0f); - for (int j = 0; j < 6; j++) { - glPushMatrix(); - - switch (j) { - case 1: - glRotatef(90.0f, 0.0f, 1.0f, 0.0f); - break; - case 2: - glRotatef(180.0f, 0.0f, 1.0f, 0.0f); - break; - case 3: - glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); - break; - case 4: - glRotatef(90.0f, 1.0f, 0.0f, 0.0f); - break; - case 5: - glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); - break; - default: - break; - } - - glBindTexture(GL_TEXTURE_2D, minecraft->textures->loadTexture( - TN_TITLE_BG_PANORAMA0 + j)); - t->begin(); - t->color(16777215, 255 / (i + 1)); - t->vertexUV(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f); - t->vertexUV(1.0f, -1.0f, 1.0f, 1.0f, 0.0f); - t->vertexUV(1.0f, 1.0f, 1.0f, 1.0f, 1.0f); - t->vertexUV(-1.0f, 1.0f, 1.0f, 0.0f, 1.0f); - t->end(); - glPopMatrix(); + switch (j) { + case 1: + glRotatef(90.0f, 0.0f, 1.0f, 0.0f); + break; + case 2: + glRotatef(180.0f, 0.0f, 1.0f, 0.0f); + break; + case 3: + glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); + break; + case 4: + glRotatef(90.0f, 1.0f, 0.0f, 0.0f); + break; + case 5: + glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); + break; + default: + break; } + + glBindTexture(GL_TEXTURE_2D, minecraft->textures->loadTexture( + TN_TITLE_BG_PANORAMA0 + j)); + t->begin(); + t->color(16777215, 255 / (i + 1)); + t->vertexUV(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f); + t->vertexUV(1.0f, -1.0f, 1.0f, 1.0f, 0.0f); + t->vertexUV(1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + t->vertexUV(-1.0f, 1.0f, 1.0f, 0.0f, 1.0f); + t->end(); glPopMatrix(); - glColorMask(true, true, true, false); } - - t->offset(0.0f, 0.0f, 0.0f); - glColorMask(true, true, true, true); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glDepthMask(true); - glEnable(GL_CULL_FACE); - glEnable(GL_ALPHA_TEST); - glEnable(GL_DEPTH_TEST); - } else { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, width, height, 0, 1000, 3000); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glTranslatef(0, 0, -2000); - - glDisable(GL_LIGHTING); - glDisable(GL_FOG); - glEnable(GL_TEXTURE_2D); - glDisable(GL_ALPHA_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDepthMask(false); - - glBindTexture(GL_TEXTURE_2D, - minecraft->textures->loadTexture(TN_TITLE_BG_PANORAMA)); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - float off = vo * 0.0004f; - - float screenAspect = (float)width / (float)height; - float texAspect = 1748.0f / 144.0f; - float scale; - if (screenAspect > texAspect) { - scale = (float)width / 1748.0f; - } else { - scale = (float)height / 144.0f; - } - - float texWidth = 1748.0f * scale; - float texHeight = 144.0f * scale; - float yOff = (height - texHeight) / 2.0f; - - float uMax = off + (texWidth / 1748.0f); - - t->begin(GL_QUADS); - t->color(0xffffff, 255); - t->vertexUV(0, yOff + texHeight, 0, off, 1.0f); - t->vertexUV(texWidth, yOff + texHeight, 0, uMax, 1.0f); - t->vertexUV(texWidth, yOff, 0, uMax, 0.0f); - t->vertexUV(0, yOff, 0, off, 0.0f); - t->end(); - - glDepthMask(true); - glDisable(GL_BLEND); - glEnable(GL_ALPHA_TEST); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); glPopMatrix(); + glColorMask(true, true, true, false); } + + t->offset(0.0f, 0.0f, 0.0f); + glColorMask(true, true, true, true); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glDepthMask(true); + glEnable(GL_CULL_FACE); + glEnable(GL_ALPHA_TEST); + glEnable(GL_DEPTH_TEST); +#else + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, width, height, 0, 1000, 3000); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glTranslatef(0, 0, -2000); + + glDisable(GL_LIGHTING); + glDisable(GL_FOG); + glEnable(GL_TEXTURE_2D); + glDisable(GL_ALPHA_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(false); + + glBindTexture(GL_TEXTURE_2D, + minecraft->textures->loadTexture(TN_TITLE_BG_PANORAMA)); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + float off = vo * 0.0004f; + + float screenAspect = (float)width / (float)height; + float texAspect = 1748.0f / 144.0f; + float scale; + if (screenAspect > texAspect) { + scale = (float)width / 1748.0f; + } else { + scale = (float)height / 144.0f; + } + + float texWidth = 1748.0f * scale; + float texHeight = 144.0f * scale; + float yOff = (height - texHeight) / 2.0f; + + float uMax = off + (texWidth / 1748.0f); + + t->begin(GL_QUADS); + t->color(0xffffff, 255); + t->vertexUV(0, yOff + texHeight, 0, off, 1.0f); + t->vertexUV(texWidth, yOff + texHeight, 0, uMax, 1.0f); + t->vertexUV(texWidth, yOff, 0, uMax, 0.0f); + t->vertexUV(0, yOff, 0, off, 0.0f); + t->end(); + + glDepthMask(true); + glDisable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +#endif #endif } // 4jcraft void TitleScreen::renderSkybox(float a) { #ifdef ENABLE_JAVA_GUIS - if (minecraft->options->classicPanorama) { - glViewport(0, 0, 256, 256); - } +#ifdef CLASSIC_PANORAMA + glViewport(0, 0, 256, 256); +#endif renderPanorama(a); - if (minecraft->options->classicPanorama) { - glDisable(GL_TEXTURE_2D); - glEnable(GL_TEXTURE_2D); +#ifdef CLASSIC_PANORAMA + glDisable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_2D); - for (int i = 0; i < 8; i++) { - rotateAndBlur(a); - } - - glViewport(0, 0, minecraft->width, minecraft->height); - - Tesselator* t = Tesselator::getInstance(); - t->begin(); - float aspect = - width > height ? 120.0f / (float)width : 120.0f / (float)height; - float sWidth = (float)height * aspect / 256.0f; - float sHeight = (float)width * aspect / 256.0f; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - t->color(1.0f, 1.0f, 1.0f, 1.0f); - t->vertexUV(0.0f, height, 0.0f, (0.5f - sWidth), (0.5f + sHeight)); - t->vertexUV(width, height, 0.0f, (0.5f - sWidth), (0.5f - sHeight)); - t->vertexUV(width, 0.0f, 0.0f, (0.5f + sWidth), (0.5f - sHeight)); - t->vertexUV(0.0f, 0.0f, 0.0f, (0.5f + sWidth), (0.5f + sHeight)); - t->end(); + for (int i = 0; i < 8; i++) { + rotateAndBlur(a); } + + glViewport(0, 0, minecraft->width, minecraft->height); + + Tesselator* t = Tesselator::getInstance(); + t->begin(); + float aspect = + width > height ? 120.0f / (float)width : 120.0f / (float)height; + float sWidth = (float)height * aspect / 256.0f; + float sHeight = (float)width * aspect / 256.0f; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + t->color(1.0f, 1.0f, 1.0f, 1.0f); + t->vertexUV(0.0f, height, 0.0f, (0.5f - sWidth), (0.5f + sHeight)); + t->vertexUV(width, height, 0.0f, (0.5f - sWidth), (0.5f - sHeight)); + t->vertexUV(width, 0.0f, 0.0f, (0.5f + sWidth), (0.5f - sHeight)); + t->vertexUV(0.0f, 0.0f, 0.0f, (0.5f + sWidth), (0.5f + sHeight)); + t->end(); +#endif #endif } // 4jcraft void TitleScreen::rotateAndBlur(float a) { -#ifdef ENABLE_JAVA_GUIS - if (minecraft->options->classicPanorama) { - glBindTexture(GL_TEXTURE_2D, viewportTexture); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 256, 256); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColorMask(true, true, true, false); - Tesselator* t = Tesselator::getInstance(); - t->begin(); - char blurPasses = 3; +#if defined(ENABLE_JAVA_GUIS) && defined(CLASSIC_PANORAMA) + glBindTexture(GL_TEXTURE_2D, viewportTexture); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 256, 256); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColorMask(true, true, true, false); + Tesselator* t = Tesselator::getInstance(); + t->begin(); + char blurPasses = 3; - for (int i = 0; i < blurPasses; i++) { - t->color(1.0f, 1.0f, 1.0f, 1.0f / (float)(i + 1)); - float offset = (float)(i - blurPasses / 2) / 256.0f; - t->vertexUV(width, height, 0.0f, (0.0f + offset), 0.0f); - t->vertexUV(width, 0.0f, 0.0f, (1.0f + offset), 0.0f); - t->vertexUV(0.0f, 0.0f, 0.0f, (1.0f + offset), 1.0f); - t->vertexUV(0.0f, height, 0.0f, (0.0f + offset), 1.0f); - } - - t->end(); - glColorMask(true, true, true, true); + for (int i = 0; i < blurPasses; i++) { + t->color(1.0f, 1.0f, 1.0f, 1.0f / (float)(i + 1)); + float offset = (float)(i - blurPasses / 2) / 256.0f; + t->vertexUV(width, height, 0.0f, (0.0f + offset), 0.0f); + t->vertexUV(width, 0.0f, 0.0f, (1.0f + offset), 0.0f); + t->vertexUV(0.0f, 0.0f, 0.0f, (1.0f + offset), 1.0f); + t->vertexUV(0.0f, height, 0.0f, (0.0f + offset), 1.0f); } + + t->end(); + glColorMask(true, true, true, true); #endif } @@ -377,10 +376,10 @@ void TitleScreen::render(int xm, int ym, float a) { int logoY = 30; // 4jcraft: gradient for classic panorama - if (minecraft->options->classicPanorama) { - fillGradient(0, 0, width, height, -2130706433, 16777215); - fillGradient(0, 0, width, height, 0, INT_MIN); - } +#ifdef CLASSIC_PANORAMA + fillGradient(0, 0, width, height, -2130706433, 16777215); + fillGradient(0, 0, width, height, 0, INT_MIN); +#endif glBindTexture(GL_TEXTURE_2D, minecraft->textures->loadTexture(TN_TITLE_MCLOGO)); diff --git a/Minecraft.Client/UI/Screens/VideoSettingsScreen.cpp b/Minecraft.Client/UI/Screens/VideoSettingsScreen.cpp index 4a2777494..d445f0052 100644 --- a/Minecraft.Client/UI/Screens/VideoSettingsScreen.cpp +++ b/Minecraft.Client/UI/Screens/VideoSettingsScreen.cpp @@ -29,8 +29,7 @@ void VideoSettingsScreen::init() { Options::Option::GUI_SCALE, Options::Option::ADVANCED_OPENGL, Options::Option::GAMMA, - Options::Option::FOV, - Options::Option::CLASSIC_PANORAMA}; + Options::Option::FOV}; for (int i = 0; i < ITEM_COUNT; i++) { const Options::Option* item = items[i]; diff --git a/Minecraft.Client/meson.build b/Minecraft.Client/meson.build index 8bcc874b1..9bb614fc4 100644 --- a/Minecraft.Client/meson.build +++ b/Minecraft.Client/meson.build @@ -75,6 +75,10 @@ if get_option('enable_vsync') global_cpp_defs += '-DENABLE_VSYNC' endif +if get_option('classic_panorama') + global_cpp_defs += '-DCLASSIC_PANORAMA' +endif + if get_option('ui_backend') == 'shiggy' shiggy_dep = dependency( 'shiggy', diff --git a/meson.options b/meson.options index 545d2a159..68eb92598 100644 --- a/meson.options +++ b/meson.options @@ -4,6 +4,11 @@ option('ui_backend', value : 'shiggy', description : 'Specifies a backend implementation for the game UI.') +option('classic_panorama', + type : 'boolean', + value : false, + description : 'Enable classic java edition panorama (ui_backend=java ONLY).') + option('enable_vsync', type : 'boolean', value : true,