mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-23 14:02:20 -04:00
Add full color extension to messages
This commit is contained in:
@@ -121,6 +121,25 @@ struct jmessage_tReference : public JMessage::TReference {
|
||||
void setDemoFrame(u32 i_frame) { mDemoFrame = i_frame; }
|
||||
void setTopColorType(u8 i_colorType) { mTopColorType = i_colorType; }
|
||||
void setNowColorType(u8 i_colorType) { mNowColorType = i_colorType; }
|
||||
#if TARGET_PC
|
||||
void resetColors() {
|
||||
mNowCCColor = 0xFFFFFFFF;
|
||||
mNowGCColor = 0xFFFFFFFF;
|
||||
mTopCCColor = 0xFFFFFFFF;
|
||||
mTopGCColor = 0xFFFFFFFF;
|
||||
mNowFullColor = false;
|
||||
mTopFullColor = false;
|
||||
}
|
||||
void setFullColor(u32 ccColor, u32 gcColor) {
|
||||
mNowCCColor = ccColor;
|
||||
mNowGCColor = gcColor;
|
||||
mNowFullColor = true;
|
||||
}
|
||||
void clearNowFullColor() { mNowFullColor = false; }
|
||||
bool hasTopFullColor() { return mTopFullColor; }
|
||||
u32 getTopCCColor() { return mTopCCColor; }
|
||||
u32 getTopGCColor() { return mTopGCColor; }
|
||||
#endif
|
||||
void setTopTagScale(u16 i_tagScale) { mTopTagScale = i_tagScale; }
|
||||
void setNowTagScale(u16 i_tagScale) { mNowTagScale = i_tagScale; }
|
||||
void setRevoMessageID(u32 i_msgID) { mRevoMessageID = i_msgID; }
|
||||
@@ -365,6 +384,14 @@ struct jmessage_tReference : public JMessage::TReference {
|
||||
/* 0x1274 */ bool mSelectSetCancelFlag;
|
||||
/* 0x1275 */ bool mBombNameUseFlag;
|
||||
/* 0x1276 */ u8 mBatchColorFlag;
|
||||
#if TARGET_PC
|
||||
u32 mNowCCColor;
|
||||
u32 mNowGCColor;
|
||||
u32 mTopCCColor;
|
||||
u32 mTopGCColor;
|
||||
bool mNowFullColor;
|
||||
bool mTopFullColor;
|
||||
#endif
|
||||
}; // Size: 0x1278
|
||||
|
||||
struct jmessage_tMeasureProcessor : public JMessage::TRenderingProcessor {
|
||||
@@ -462,6 +489,9 @@ struct jmessage_tRenderingProcessor : public JMessage::TRenderingProcessor {
|
||||
void do_selwidthcenter(int);
|
||||
void do_heightcenter();
|
||||
void do_color(u8);
|
||||
#if TARGET_PC
|
||||
void do_fullcolor(u32 ccColor, u32 gcColor);
|
||||
#endif
|
||||
void do_scale(f32);
|
||||
void do_linedown(s16);
|
||||
void do_transY(s16, bool);
|
||||
@@ -640,6 +670,9 @@ struct jmessage_string_tRenderingProcessor : public JMessage::TRenderingProcesso
|
||||
void do_rubystrcat(char*);
|
||||
void do_outfont(u8);
|
||||
void do_color(u8);
|
||||
#if TARGET_PC
|
||||
void do_fullcolor(u32 ccColor, u32 gcColor);
|
||||
#endif
|
||||
void do_scale(f32);
|
||||
void do_linedown(s16);
|
||||
void do_numset(s16);
|
||||
|
||||
@@ -177,18 +177,20 @@ MOD_EXPORT ModResult mod_initialize(ModError* outError) {
|
||||
if (result == MOD_OK) {
|
||||
result = add_message(mods::flow::MessageBuilder{kResponseStyle}
|
||||
.text_color(MESSAGE_COLOR_DEFAULT)
|
||||
.text("Hello from ")
|
||||
.text_color(MESSAGE_COLOR_RED)
|
||||
.text("FlowService")
|
||||
.text("Custom ")
|
||||
.text_color(0xFF0000FF)
|
||||
.text("colors")
|
||||
.text_color(MESSAGE_COLOR_DEFAULT)
|
||||
.text(" and even ")
|
||||
.text_color(0x00FF00FF, 0x00FFFFFF)
|
||||
.text("gradients")
|
||||
.text_color(MESSAGE_COLOR_DEFAULT)
|
||||
.text(", ")
|
||||
.player_name()
|
||||
.text("!\n")
|
||||
.character_delay(3)
|
||||
.text("This text is slow. ")
|
||||
.character_delay(0)
|
||||
.pause(12)
|
||||
.text_scale(125)
|
||||
.text_scale(150)
|
||||
.text("Big")
|
||||
.text_scale(100)
|
||||
.text(" text too.")
|
||||
|
||||
@@ -459,7 +459,20 @@ public:
|
||||
}
|
||||
MessageBuilder& text_color(MessageTextColor color) {
|
||||
const auto index = static_cast<uint8_t>(color);
|
||||
return raw_tag(255, 0, {&index, 1});
|
||||
return raw_tag(0xFF, 0, {&index, 1});
|
||||
}
|
||||
/* Full 32-bit text color (Dusklight extension) */
|
||||
MessageBuilder& text_color(uint32_t rgba) {
|
||||
std::array<uint8_t, 4> arguments{};
|
||||
write_bits(arguments.data(), rgba);
|
||||
return raw_tag(0xFF, 0, arguments);
|
||||
}
|
||||
/* Full 32-bit text vertical gradient colors (Dusklight extension) */
|
||||
MessageBuilder& text_color(uint32_t upperRgba, uint32_t lowerRgba) {
|
||||
std::array<uint8_t, 8> arguments{};
|
||||
write_bits(arguments.data(), upperRgba);
|
||||
write_bits(arguments.data() + sizeof(upperRgba), lowerRgba);
|
||||
return raw_tag(0xFF, 0, arguments);
|
||||
}
|
||||
MessageBuilder& text_scale(uint16_t percent) { return timed_tag(255, 1, percent); }
|
||||
MessageBuilder& character_delay(uint16_t frames) { return timed_tag(0, 6, frames); }
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#define MESSAGE_SERVICE_ID "dev.twilitrealm.dusklight.message"
|
||||
#define MESSAGE_SERVICE_MAJOR 1u
|
||||
#define MESSAGE_SERVICE_MINOR 0u
|
||||
#define MESSAGE_SERVICE_MINOR 1u
|
||||
|
||||
typedef uint16_t MessageId;
|
||||
typedef uint64_t MessageHandle;
|
||||
|
||||
+93
-3
@@ -16,6 +16,21 @@
|
||||
#if TARGET_PC
|
||||
#include "dusk/menu_pointer.h"
|
||||
#include "dusk/scope_guard.hpp"
|
||||
#include "helpers/bits.hpp"
|
||||
|
||||
static bool read_full_color(const void* data, u32 size, u32& ccColor, u32& gcColor) {
|
||||
if (size == 4) {
|
||||
ccColor = dusk::read_bits<u32>(data);
|
||||
gcColor = ccColor;
|
||||
return true;
|
||||
}
|
||||
if (size == 8) {
|
||||
ccColor = dusk::read_bits<u32>(data);
|
||||
gcColor = dusk::read_bits<u32>(static_cast<const u8*>(data) + sizeof(ccColor));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
@@ -400,6 +415,9 @@ jmessage_tReference::jmessage_tReference() {
|
||||
resetCharCountBuffer();
|
||||
mNowColorType = 0;
|
||||
mTopColorType = 0;
|
||||
#if TARGET_PC
|
||||
resetColors();
|
||||
#endif
|
||||
mButtonTagStopFlag = 0;
|
||||
mPageEndCount = 0;
|
||||
mSelectNum = 0;
|
||||
@@ -594,6 +612,13 @@ void jmessage_tReference::pageSend() {
|
||||
if (mNowColorType != mTopColorType) {
|
||||
mTopColorType = mNowColorType;
|
||||
}
|
||||
#if TARGET_PC
|
||||
mTopFullColor = mNowFullColor;
|
||||
if (mNowFullColor) {
|
||||
mTopCCColor = mNowCCColor;
|
||||
mTopGCColor = mNowGCColor;
|
||||
}
|
||||
#endif
|
||||
|
||||
mTopWordCount = mNowWordCount;
|
||||
mCharAlpha = 0.0f;
|
||||
@@ -1917,6 +1942,9 @@ void jmessage_tSequenceProcessor::do_begin(void const* pEntry, char const* pszTe
|
||||
pReference->resetCharCnt();
|
||||
pReference->setNowColorType(0);
|
||||
pReference->setTopColorType(0);
|
||||
#if TARGET_PC
|
||||
pReference->resetColors();
|
||||
#endif
|
||||
pReference->setNowWordCount(0);
|
||||
pReference->setTopWordCount(0);
|
||||
pReference->setBatchColorFlag(0);
|
||||
@@ -2280,9 +2308,21 @@ bool jmessage_tSequenceProcessor::do_tag(u32 i_tag, void const* i_data, u32 i_si
|
||||
return true;
|
||||
case MSGTAG_GROUP(255):
|
||||
switch (i_tag) {
|
||||
case MSGTAG_COLOR:
|
||||
case MSGTAG_COLOR: {
|
||||
#if TARGET_PC
|
||||
u32 ccColor;
|
||||
u32 gcColor;
|
||||
if (read_full_color(i_data, i_size, ccColor, gcColor)) {
|
||||
pReference->setFullColor(ccColor, gcColor);
|
||||
} else if (i_size == 1) {
|
||||
pReference->clearNowFullColor();
|
||||
pReference->setNowColorType(*(u8*)i_data & 0xFF);
|
||||
}
|
||||
#else
|
||||
pReference->setNowColorType(*(u8*)i_data & 0xFF);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
case MSGTAG_SCALE:
|
||||
pReference->setNowTagScale(*(BE(u16)*)i_data & 0xFFFF);
|
||||
return true;
|
||||
@@ -2863,7 +2903,15 @@ void jmessage_tRenderingProcessor::do_begin(void const* pEntry, char const* pszT
|
||||
do_scale(field_0x44);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
if (pReference->hasTopFullColor()) {
|
||||
do_fullcolor(pReference->getTopCCColor(), pReference->getTopGCColor());
|
||||
} else {
|
||||
do_color(pReference->getTopColorType());
|
||||
}
|
||||
#else
|
||||
do_color(pReference->getTopColorType());
|
||||
#endif
|
||||
pReference->resetDrawLightCount();
|
||||
|
||||
do_widthcenter();
|
||||
@@ -3017,9 +3065,20 @@ bool jmessage_tRenderingProcessor::do_tag(u32 i_tag, void const* i_data, u32 i_s
|
||||
return 1;
|
||||
case MSGTAG_GROUP(255):
|
||||
switch (i_tag) {
|
||||
case MSGTAG_COLOR:
|
||||
case MSGTAG_COLOR: {
|
||||
#if TARGET_PC
|
||||
u32 ccColor;
|
||||
u32 gcColor;
|
||||
if (read_full_color(i_data, i_size, ccColor, gcColor)) {
|
||||
do_fullcolor(ccColor, gcColor);
|
||||
} else if (i_size == 1) {
|
||||
do_color(*(u8*)i_data & 0xFF);
|
||||
}
|
||||
#else
|
||||
do_color(*(u8*)i_data & 0xFF);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
case MSGTAG_SCALE:
|
||||
field_0x13c = *(BE(u16)*)i_data & 0xFFFF;
|
||||
do_scale(field_0x13c / 100.0f);
|
||||
@@ -3630,6 +3689,18 @@ void jmessage_tRenderingProcessor::do_color(u8 i_colorNo) {
|
||||
do_strcat(buffer, false, false, false);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
void jmessage_tRenderingProcessor::do_fullcolor(u32 ccColor, u32 gcColor) {
|
||||
mColorNo = 0xFF;
|
||||
mCCColor = ccColor;
|
||||
mGCColor = gcColor;
|
||||
|
||||
char buffer[40];
|
||||
SAFE_SPRINTF(buffer, "\x1B" "CC[%08x]" "\x1B" "GC[%08x]", mCCColor, mGCColor);
|
||||
do_strcat(buffer, false, false, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
void jmessage_tRenderingProcessor::do_scale(f32 param_1) {
|
||||
jmessage_tReference* pReference = (jmessage_tReference*)getReference();
|
||||
|
||||
@@ -4684,9 +4755,20 @@ bool jmessage_string_tRenderingProcessor::do_tag(u32 i_tag, void const* i_data,
|
||||
switch(i_tag & 0xFF0000) {
|
||||
case MSGTAG_GROUP(255):
|
||||
switch(i_tag) {
|
||||
case MSGTAG_COLOR:
|
||||
case MSGTAG_COLOR: {
|
||||
#if TARGET_PC
|
||||
u32 ccColor;
|
||||
u32 gcColor;
|
||||
if (read_full_color(i_data, i_size, ccColor, gcColor)) {
|
||||
do_fullcolor(ccColor, gcColor);
|
||||
} else if (i_size == 1) {
|
||||
do_color(*(u8*)i_data & 0xFF);
|
||||
}
|
||||
#else
|
||||
do_color(*(u8*)i_data & 0xFF);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case MSGTAG_SCALE:
|
||||
do_scale(*(BE(u16)*)i_data / 100.0f);
|
||||
break;
|
||||
@@ -5336,6 +5418,14 @@ void jmessage_string_tRenderingProcessor::do_color(u8 i_colorNo) {
|
||||
do_strcat(buffer);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
void jmessage_string_tRenderingProcessor::do_fullcolor(u32 ccColor, u32 gcColor) {
|
||||
char buffer[32];
|
||||
SAFE_SPRINTF(buffer, "\x1b" "CC[%08x]" "\x1b" "GC[%08x]", ccColor, gcColor);
|
||||
do_strcat(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
void jmessage_string_tRenderingProcessor::do_scale(f32 i_scale) {
|
||||
J2DTextBox::TFontSize fontSize;
|
||||
mpReference->getPanePtr()->getFontSize(fontSize);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "JSystem/JMessage/control.h"
|
||||
#include "JSystem/JMessage/processor.h"
|
||||
#include "JSystem/JMessage/resource.h"
|
||||
#include "d/d_msg_class.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -467,11 +468,19 @@ bool valid_encoded_text(const uint8_t* text, size_t size) {
|
||||
if (text[offset] == 0) {
|
||||
return offset + 1 == size;
|
||||
}
|
||||
if (text[offset] == 0x1a) {
|
||||
if (text[offset] == JMessage::data::gcTagBegin) {
|
||||
if (offset + 2 > size || text[offset + 1] < 5 || text[offset + 1] > size - offset) {
|
||||
return false;
|
||||
}
|
||||
offset += text[offset + 1];
|
||||
const size_t tagSize = text[offset + 1];
|
||||
const uint32_t tag =
|
||||
MSGTAG_GROUP(text[offset + 2]) | read_bits<uint16_t>(text + offset + 3);
|
||||
const size_t argumentSize = tagSize - 5;
|
||||
if (tag == MSGTAG_COLOR && argumentSize != 1 && argumentSize != 4 && argumentSize != 8)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
offset += tagSize;
|
||||
} else {
|
||||
++offset;
|
||||
}
|
||||
@@ -490,7 +499,7 @@ size_t encoded_text_size(const ResourceInfo& resource, const char* text) {
|
||||
if (bytes[offset] == 0) {
|
||||
return offset + 1;
|
||||
}
|
||||
if (bytes[offset] == 0x1a) {
|
||||
if (bytes[offset] == JMessage::data::gcTagBegin) {
|
||||
if (offset + 2 > maximum || bytes[offset + 1] < 5 ||
|
||||
bytes[offset + 1] > maximum - offset)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user