feat: Enhance intro splash screen with retail warning and dynamic slide management
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -184,6 +184,7 @@ class WolfEngine {
|
|||||||
initialEpisodeIndex: _currentEpisodeIndex,
|
initialEpisodeIndex: _currentEpisodeIndex,
|
||||||
initialDifficulty: difficulty,
|
initialDifficulty: difficulty,
|
||||||
hasResumableGame: false,
|
hasResumableGame: false,
|
||||||
|
initialGameIsRetail: data.version == GameVersion.retail,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (_availableGames.length == 1) {
|
if (_availableGames.length == 1) {
|
||||||
@@ -373,7 +374,9 @@ class WolfEngine {
|
|||||||
_currentEpisodeIndex = 0;
|
_currentEpisodeIndex = 0;
|
||||||
onEpisodeSelected?.call(null);
|
onEpisodeSelected?.call(null);
|
||||||
menuManager.clearEpisodeSelection();
|
menuManager.clearEpisodeSelection();
|
||||||
menuManager.beginIntroSplash();
|
menuManager.beginIntroSplash(
|
||||||
|
includeRetailWarning: data.version == GameVersion.retail,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ enum WolfMenuScreen {
|
|||||||
difficultySelect,
|
difficultySelect,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum WolfIntroSlide { retailWarning, pg13, title }
|
||||||
|
|
||||||
enum _WolfIntroPhase { fadeIn, hold, fadeOut }
|
enum _WolfIntroPhase { fadeIn, hold, fadeOut }
|
||||||
|
|
||||||
enum WolfMenuMainAction {
|
enum WolfMenuMainAction {
|
||||||
@@ -61,7 +63,7 @@ bool _isWiredMainMenuAction(WolfMenuMainAction action) {
|
|||||||
class MenuManager {
|
class MenuManager {
|
||||||
static const int transitionDurationMs = 280;
|
static const int transitionDurationMs = 280;
|
||||||
static const int introFadeDurationMs = 280;
|
static const int introFadeDurationMs = 280;
|
||||||
static const int _introSlideCount = 2;
|
static const int _introRetailBackgroundRgb = 0xA00000;
|
||||||
static const int _introPg13BackgroundRgb = 0x33A2E8;
|
static const int _introPg13BackgroundRgb = 0x33A2E8;
|
||||||
static const int _introTitleBackgroundRgb = 0x000000;
|
static const int _introTitleBackgroundRgb = 0x000000;
|
||||||
|
|
||||||
@@ -74,6 +76,10 @@ class MenuManager {
|
|||||||
int _introElapsedMs = 0;
|
int _introElapsedMs = 0;
|
||||||
_WolfIntroPhase _introPhase = _WolfIntroPhase.fadeIn;
|
_WolfIntroPhase _introPhase = _WolfIntroPhase.fadeIn;
|
||||||
bool _introAdvanceRequested = false;
|
bool _introAdvanceRequested = false;
|
||||||
|
List<WolfIntroSlide> _introSlides = <WolfIntroSlide>[
|
||||||
|
WolfIntroSlide.pg13,
|
||||||
|
WolfIntroSlide.title,
|
||||||
|
];
|
||||||
|
|
||||||
int _selectedMainIndex = 0;
|
int _selectedMainIndex = 0;
|
||||||
int _selectedGameIndex = 0;
|
int _selectedGameIndex = 0;
|
||||||
@@ -93,10 +99,31 @@ class MenuManager {
|
|||||||
|
|
||||||
bool get isIntroSplashActive => _activeMenu == WolfMenuScreen.introSplash;
|
bool get isIntroSplashActive => _activeMenu == WolfMenuScreen.introSplash;
|
||||||
|
|
||||||
bool get isIntroPg13Slide => _introSlideIndex == 0;
|
WolfIntroSlide get currentIntroSlide {
|
||||||
|
if (_introSlides.isEmpty) {
|
||||||
|
return WolfIntroSlide.title;
|
||||||
|
}
|
||||||
|
final int index = _introSlideIndex.clamp(0, _introSlides.length - 1);
|
||||||
|
return _introSlides[index];
|
||||||
|
}
|
||||||
|
|
||||||
int get introBackgroundRgb =>
|
bool get isIntroRetailWarningSlide =>
|
||||||
isIntroPg13Slide ? _introPg13BackgroundRgb : _introTitleBackgroundRgb;
|
currentIntroSlide == WolfIntroSlide.retailWarning;
|
||||||
|
|
||||||
|
bool get isIntroPg13Slide => currentIntroSlide == WolfIntroSlide.pg13;
|
||||||
|
|
||||||
|
bool get isIntroTitleSlide => currentIntroSlide == WolfIntroSlide.title;
|
||||||
|
|
||||||
|
int get introBackgroundRgb {
|
||||||
|
switch (currentIntroSlide) {
|
||||||
|
case WolfIntroSlide.retailWarning:
|
||||||
|
return _introRetailBackgroundRgb;
|
||||||
|
case WolfIntroSlide.pg13:
|
||||||
|
return _introPg13BackgroundRgb;
|
||||||
|
case WolfIntroSlide.title:
|
||||||
|
return _introTitleBackgroundRgb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
double get introOverlayAlpha {
|
double get introOverlayAlpha {
|
||||||
if (!isIntroSplashActive) {
|
if (!isIntroSplashActive) {
|
||||||
@@ -189,6 +216,7 @@ class MenuManager {
|
|||||||
int initialEpisodeIndex = 0,
|
int initialEpisodeIndex = 0,
|
||||||
Difficulty? initialDifficulty,
|
Difficulty? initialDifficulty,
|
||||||
bool hasResumableGame = false,
|
bool hasResumableGame = false,
|
||||||
|
bool initialGameIsRetail = false,
|
||||||
}) {
|
}) {
|
||||||
_gameCount = gameCount;
|
_gameCount = gameCount;
|
||||||
_showResumeOption = hasResumableGame;
|
_showResumeOption = hasResumableGame;
|
||||||
@@ -206,8 +234,12 @@ class MenuManager {
|
|||||||
_introElapsedMs = 0;
|
_introElapsedMs = 0;
|
||||||
_introPhase = _WolfIntroPhase.fadeIn;
|
_introPhase = _WolfIntroPhase.fadeIn;
|
||||||
_introSlideIndex = 0;
|
_introSlideIndex = 0;
|
||||||
|
_introSlides = <WolfIntroSlide>[
|
||||||
|
WolfIntroSlide.pg13,
|
||||||
|
WolfIntroSlide.title,
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
_startIntroSequence();
|
_startIntroSequence(includeRetailWarning: initialGameIsRetail);
|
||||||
}
|
}
|
||||||
_transitionTarget = null;
|
_transitionTarget = null;
|
||||||
_transitionElapsedMs = 0;
|
_transitionElapsedMs = 0;
|
||||||
@@ -218,12 +250,13 @@ class MenuManager {
|
|||||||
/// Starts the intro splash sequence and lands on [landingMenu] when done.
|
/// Starts the intro splash sequence and lands on [landingMenu] when done.
|
||||||
void beginIntroSplash({
|
void beginIntroSplash({
|
||||||
WolfMenuScreen landingMenu = WolfMenuScreen.mainMenu,
|
WolfMenuScreen landingMenu = WolfMenuScreen.mainMenu,
|
||||||
|
bool includeRetailWarning = false,
|
||||||
}) {
|
}) {
|
||||||
_introLandingMenu = landingMenu;
|
_introLandingMenu = landingMenu;
|
||||||
_transitionTarget = null;
|
_transitionTarget = null;
|
||||||
_transitionElapsedMs = 0;
|
_transitionElapsedMs = 0;
|
||||||
_transitionSwappedMenu = false;
|
_transitionSwappedMenu = false;
|
||||||
_startIntroSequence();
|
_startIntroSequence(includeRetailWarning: includeRetailWarning);
|
||||||
_resetEdgeState();
|
_resetEdgeState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,8 +345,15 @@ class MenuManager {
|
|||||||
_consumeEdgeState(input);
|
_consumeEdgeState(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startIntroSequence() {
|
void _startIntroSequence({required bool includeRetailWarning}) {
|
||||||
_activeMenu = WolfMenuScreen.introSplash;
|
_activeMenu = WolfMenuScreen.introSplash;
|
||||||
|
_introSlides = includeRetailWarning
|
||||||
|
? <WolfIntroSlide>[
|
||||||
|
WolfIntroSlide.retailWarning,
|
||||||
|
WolfIntroSlide.pg13,
|
||||||
|
WolfIntroSlide.title,
|
||||||
|
]
|
||||||
|
: <WolfIntroSlide>[WolfIntroSlide.pg13, WolfIntroSlide.title];
|
||||||
_introSlideIndex = 0;
|
_introSlideIndex = 0;
|
||||||
_introElapsedMs = 0;
|
_introElapsedMs = 0;
|
||||||
_introPhase = _WolfIntroPhase.fadeIn;
|
_introPhase = _WolfIntroPhase.fadeIn;
|
||||||
@@ -356,7 +396,7 @@ class MenuManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _advanceIntroSlide() {
|
void _advanceIntroSlide() {
|
||||||
if (_introSlideIndex < _introSlideCount - 1) {
|
if (_introSlideIndex < _introSlides.length - 1) {
|
||||||
_introSlideIndex += 1;
|
_introSlideIndex += 1;
|
||||||
_introElapsedMs = 0;
|
_introElapsedMs = 0;
|
||||||
_introPhase = _WolfIntroPhase.fadeIn;
|
_introPhase = _WolfIntroPhase.fadeIn;
|
||||||
|
|||||||
@@ -420,7 +420,7 @@ class AsciiRenderer extends CliRendererBackend<dynamic> {
|
|||||||
final art = WolfClassicMenuArt(engine.data);
|
final art = WolfClassicMenuArt(engine.data);
|
||||||
|
|
||||||
if (engine.menuManager.activeMenu == WolfMenuScreen.introSplash) {
|
if (engine.menuManager.activeMenu == WolfMenuScreen.introSplash) {
|
||||||
_drawIntroSplash(engine, art);
|
_drawIntroSplash(engine, art, menuTypography);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,10 +708,16 @@ class AsciiRenderer extends CliRendererBackend<dynamic> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _drawIntroSplash(WolfEngine engine, WolfClassicMenuArt art) {
|
void _drawIntroSplash(
|
||||||
final image = engine.menuManager.isIntroPg13Slide
|
WolfEngine engine,
|
||||||
? art.mappedPic(WolfMenuPic.pg13)
|
WolfClassicMenuArt art,
|
||||||
: art.mappedPic(WolfMenuPic.title);
|
_AsciiMenuTypography menuTypography,
|
||||||
|
) {
|
||||||
|
final image = switch (engine.menuManager.currentIntroSlide) {
|
||||||
|
WolfIntroSlide.retailWarning => null,
|
||||||
|
WolfIntroSlide.pg13 => art.mappedPic(WolfMenuPic.pg13),
|
||||||
|
WolfIntroSlide.title => art.mappedPic(WolfMenuPic.title),
|
||||||
|
};
|
||||||
|
|
||||||
int splashBg = _rgbToPaletteColor(engine.menuManager.introBackgroundRgb);
|
int splashBg = _rgbToPaletteColor(engine.menuManager.introBackgroundRgb);
|
||||||
if (engine.menuManager.isIntroPg13Slide &&
|
if (engine.menuManager.isIntroPg13Slide &&
|
||||||
@@ -726,6 +732,10 @@ class AsciiRenderer extends CliRendererBackend<dynamic> {
|
|||||||
_fillRect(0, 0, width, height, activeTheme.solid, splashBg);
|
_fillRect(0, 0, width, height, activeTheme.solid, splashBg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (engine.menuManager.isIntroRetailWarningSlide) {
|
||||||
|
_drawRetailWarningIntro(splashBg, menuTypography);
|
||||||
|
}
|
||||||
|
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
final int x = engine.menuManager.isIntroPg13Slide
|
final int x = engine.menuManager.isIntroPg13Slide
|
||||||
? (320 - image.width).clamp(0, 319)
|
? (320 - image.width).clamp(0, 319)
|
||||||
@@ -742,6 +752,58 @@ class AsciiRenderer extends CliRendererBackend<dynamic> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _drawRetailWarningIntro(
|
||||||
|
int backgroundColor,
|
||||||
|
_AsciiMenuTypography menuTypography,
|
||||||
|
) {
|
||||||
|
final int black = ColorPalette.vga32Bit[0];
|
||||||
|
final int yellow = ColorPalette.vga32Bit[14];
|
||||||
|
final int white = ColorPalette.vga32Bit[15];
|
||||||
|
final int lineColor = ColorPalette.vga32Bit[4];
|
||||||
|
|
||||||
|
_fillRect320(0, 0, 320, 22, black);
|
||||||
|
_drawMenuTextCentered(
|
||||||
|
'Attention',
|
||||||
|
6,
|
||||||
|
yellow,
|
||||||
|
scale: menuTypography.headingScale,
|
||||||
|
);
|
||||||
|
_fillRect320(0, 23, 320, 1, lineColor);
|
||||||
|
|
||||||
|
if (menuTypography.usesCompactRows) {
|
||||||
|
final int textLeft = _menuX320ToColumn(40);
|
||||||
|
final int textRight = _menuX320ToColumn(280);
|
||||||
|
final int textWidth = math.max(1, textRight - textLeft);
|
||||||
|
|
||||||
|
void writeCenteredLine(int y200, String text) {
|
||||||
|
final String clipped = _clipWithEllipsis(text, textWidth);
|
||||||
|
final int centeredLeft =
|
||||||
|
textLeft + math.max(0, ((textWidth - clipped.length) ~/ 2));
|
||||||
|
_writeLeftClipped(
|
||||||
|
_menuY200ToRow(y200),
|
||||||
|
clipped,
|
||||||
|
white,
|
||||||
|
backgroundColor,
|
||||||
|
clipped.length,
|
||||||
|
centeredLeft,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeCenteredLine(62, 'THIS GAME IS NOT SHAREWARE.');
|
||||||
|
writeCenteredLine(74, 'PLEASE DO NOT DISTRIBUTE IT.');
|
||||||
|
writeCenteredLine(86, 'THANKS.');
|
||||||
|
|
||||||
|
writeCenteredLine(112, 'ID SOFTWARE');
|
||||||
|
} else {
|
||||||
|
_drawMenuText('This game is NOT shareware.', 40, 56, white, scale: 1);
|
||||||
|
_drawMenuText('Please do not distribute it.', 40, 68, white, scale: 1);
|
||||||
|
_drawMenuText('Thanks.', 40, 80, white, scale: 1);
|
||||||
|
_drawMenuTextCentered('Id Software', 106, white, scale: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fillRect320(0, 196, 320, 4, backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
int _dominantPaletteIndex(VgaImage image) {
|
int _dominantPaletteIndex(VgaImage image) {
|
||||||
final List<int> histogram = List<int>.filled(256, 0);
|
final List<int> histogram = List<int>.filled(256, 0);
|
||||||
for (final int colorIndex in image.pixels) {
|
for (final int colorIndex in image.pixels) {
|
||||||
@@ -767,6 +829,18 @@ class AsciiRenderer extends CliRendererBackend<dynamic> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final int threshold = (alpha * 3).round().clamp(1, 3);
|
final int threshold = (alpha * 3).round().clamp(1, 3);
|
||||||
|
|
||||||
|
if (_usesTerminalLayout) {
|
||||||
|
for (int y = 0; y < _terminalPixelHeight; y++) {
|
||||||
|
for (int x = 0; x < _terminalSceneWidth; x++) {
|
||||||
|
if (((x + y) % 3) < threshold) {
|
||||||
|
_scenePixels[y][x] = fadeColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (int y = 0; y < _screen.length; y++) {
|
for (int y = 0; y < _screen.length; y++) {
|
||||||
final row = _screen[y];
|
final row = _screen[y];
|
||||||
for (int x = 0; x < row.length; x++) {
|
for (int x = 0; x < row.length; x++) {
|
||||||
|
|||||||
@@ -561,9 +561,11 @@ class SixelRenderer extends CliRendererBackend<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _drawIntroSplash(WolfEngine engine, WolfClassicMenuArt art) {
|
void _drawIntroSplash(WolfEngine engine, WolfClassicMenuArt art) {
|
||||||
final image = engine.menuManager.isIntroPg13Slide
|
final image = switch (engine.menuManager.currentIntroSlide) {
|
||||||
? art.mappedPic(WolfMenuPic.pg13)
|
WolfIntroSlide.retailWarning => null,
|
||||||
: art.mappedPic(WolfMenuPic.title);
|
WolfIntroSlide.pg13 => art.mappedPic(WolfMenuPic.pg13),
|
||||||
|
WolfIntroSlide.title => art.mappedPic(WolfMenuPic.title),
|
||||||
|
};
|
||||||
|
|
||||||
int splashBg = _rgbToPaletteIndex(engine.menuManager.introBackgroundRgb);
|
int splashBg = _rgbToPaletteIndex(engine.menuManager.introBackgroundRgb);
|
||||||
if (engine.menuManager.isIntroPg13Slide &&
|
if (engine.menuManager.isIntroPg13Slide &&
|
||||||
@@ -576,6 +578,10 @@ class SixelRenderer extends CliRendererBackend<String> {
|
|||||||
_screen[i] = splashBg;
|
_screen[i] = splashBg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (engine.menuManager.isIntroRetailWarningSlide) {
|
||||||
|
_drawRetailWarningIntro(splashBg);
|
||||||
|
}
|
||||||
|
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
final int x = engine.menuManager.isIntroPg13Slide
|
final int x = engine.menuManager.isIntroPg13Slide
|
||||||
? (320 - image.width).clamp(0, 319)
|
? (320 - image.width).clamp(0, 319)
|
||||||
@@ -592,6 +598,24 @@ class SixelRenderer extends CliRendererBackend<String> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _drawRetailWarningIntro(int backgroundColor) {
|
||||||
|
const int black = 0;
|
||||||
|
const int yellow = 14;
|
||||||
|
const int white = 15;
|
||||||
|
const int lineColor = 4;
|
||||||
|
|
||||||
|
_fillRect320(0, 0, 320, 22, black);
|
||||||
|
_drawMenuTextCentered('Attention', 6, yellow, scale: 2);
|
||||||
|
_fillRect320(0, 23, 320, 1, lineColor);
|
||||||
|
|
||||||
|
_drawMenuText('This game is NOT shareware.', 40, 56, white, scale: 1);
|
||||||
|
_drawMenuText('Please do not distribute it.', 40, 68, white, scale: 1);
|
||||||
|
_drawMenuText('Thanks.', 40, 80, white, scale: 1);
|
||||||
|
_drawMenuTextCentered('Id Software', 106, white, scale: 1);
|
||||||
|
|
||||||
|
_fillRect320(0, 196, 320, 4, backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
int _dominantPaletteIndex(VgaImage image) {
|
int _dominantPaletteIndex(VgaImage image) {
|
||||||
final List<int> histogram = List<int>.filled(256, 0);
|
final List<int> histogram = List<int>.filled(256, 0);
|
||||||
for (final int colorIndex in image.pixels) {
|
for (final int colorIndex in image.pixels) {
|
||||||
|
|||||||
@@ -209,9 +209,11 @@ class SoftwareRenderer extends RendererBackend<FrameBuffer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _drawIntroSplash(WolfEngine engine, WolfClassicMenuArt art) {
|
void _drawIntroSplash(WolfEngine engine, WolfClassicMenuArt art) {
|
||||||
final image = engine.menuManager.isIntroPg13Slide
|
final image = switch (engine.menuManager.currentIntroSlide) {
|
||||||
? art.mappedPic(WolfMenuPic.pg13)
|
WolfIntroSlide.retailWarning => null,
|
||||||
: art.mappedPic(WolfMenuPic.title);
|
WolfIntroSlide.pg13 => art.mappedPic(WolfMenuPic.pg13),
|
||||||
|
WolfIntroSlide.title => art.mappedPic(WolfMenuPic.title),
|
||||||
|
};
|
||||||
|
|
||||||
int splashBgColor = _rgbToFrameColor(engine.menuManager.introBackgroundRgb);
|
int splashBgColor = _rgbToFrameColor(engine.menuManager.introBackgroundRgb);
|
||||||
int? matteIndex;
|
int? matteIndex;
|
||||||
@@ -227,6 +229,10 @@ class SoftwareRenderer extends RendererBackend<FrameBuffer> {
|
|||||||
_buffer.pixels[i] = splashBgColor;
|
_buffer.pixels[i] = splashBgColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (engine.menuManager.isIntroRetailWarningSlide) {
|
||||||
|
_drawRetailWarningIntro(splashBgColor);
|
||||||
|
}
|
||||||
|
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
final int x = engine.menuManager.isIntroPg13Slide
|
final int x = engine.menuManager.isIntroPg13Slide
|
||||||
? (320 - image.width).clamp(0, 319)
|
? (320 - image.width).clamp(0, 319)
|
||||||
@@ -247,6 +253,36 @@ class SoftwareRenderer extends RendererBackend<FrameBuffer> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _drawRetailWarningIntro(int backgroundColor) {
|
||||||
|
final int black = ColorPalette.vga32Bit[0];
|
||||||
|
final int yellow = ColorPalette.vga32Bit[14];
|
||||||
|
final int white = ColorPalette.vga32Bit[15];
|
||||||
|
final int lineColor = ColorPalette.vga32Bit[4];
|
||||||
|
|
||||||
|
_fillCanonicalRect(0, 0, 320, 22, black);
|
||||||
|
_drawCanonicalMenuTextCentered('Attention', 6, yellow, scale: 2);
|
||||||
|
_fillCanonicalRect(0, 23, 320, 1, lineColor);
|
||||||
|
|
||||||
|
_drawCanonicalMenuText(
|
||||||
|
'This game is NOT shareware.',
|
||||||
|
40,
|
||||||
|
56,
|
||||||
|
white,
|
||||||
|
scale: 1,
|
||||||
|
);
|
||||||
|
_drawCanonicalMenuText(
|
||||||
|
'Please do not distribute it.',
|
||||||
|
40,
|
||||||
|
68,
|
||||||
|
white,
|
||||||
|
scale: 1,
|
||||||
|
);
|
||||||
|
_drawCanonicalMenuText('Thanks.', 40, 80, white, scale: 1);
|
||||||
|
_drawCanonicalMenuTextCentered('Id Software', 106, white, scale: 1);
|
||||||
|
|
||||||
|
_fillCanonicalRect(0, 196, 320, 4, backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
int _dominantPaletteIndex(VgaImage image) {
|
int _dominantPaletteIndex(VgaImage image) {
|
||||||
final List<int> histogram = List<int>.filled(256, 0);
|
final List<int> histogram = List<int>.filled(256, 0);
|
||||||
for (final int colorIndex in image.pixels) {
|
for (final int colorIndex in image.pixels) {
|
||||||
|
|||||||
Reference in New Issue
Block a user