#ifdef INTERFACE CLASS(InputBox) EXTENDS(Label) METHOD(InputBox, configureInputBox, void(entity, string, float, float, string)) METHOD(InputBox, draw, void(entity)) METHOD(InputBox, setText, void(entity, string)) METHOD(InputBox, enterText, void(entity, string)) METHOD(InputBox, keyDown, float(entity, float, float, float)) METHOD(InputBox, mouseMove, float(entity, vector)) METHOD(InputBox, mouseRelease, float(entity, vector)) METHOD(InputBox, mousePress, float(entity, vector)) METHOD(InputBox, mouseDrag, float(entity, vector)) METHOD(InputBox, showNotify, void(entity)) METHOD(InputBox, resizeNotify, void(entity, vector, vector, vector, vector)) ATTRIB(InputBox, src, string, string_null) ATTRIB(InputBox, cursorPos, float, 0) // characters ATTRIB(InputBox, scrollPos, float, 0) // widths ATTRIB(InputBox, focusable, float, 1) ATTRIB(InputBox, allowFocusSound, float, 1) ATTRIB(InputBox, disabled, float, 0) ATTRIB(InputBox, lastChangeTime, float, 0) ATTRIB(InputBox, dragScrollTimer, float, 0) ATTRIB(InputBox, dragScrollPos, vector, '0 0 0') ATTRIB(InputBox, pressed, float, 0) ATTRIB(InputBox, editColorCodes, float, 1) ATTRIB(InputBox, forbiddenCharacters, string, "") ATTRIB(InputBox, color, vector, '1 1 1') ATTRIB(InputBox, colorF, vector, '1 1 1') ATTRIB(InputBox, maxLength, float, 255) // if negative, it counts bytes, not chars ATTRIB(InputBox, enableClearButton, float, 1) ATTRIB(InputBox, clearButton, entity, NULL) ATTRIB(InputBox, cb_width, float, 0) ATTRIB(InputBox, cb_pressed, float, 0) ATTRIB(InputBox, cb_focused, float, 0) ATTRIB(InputBox, cb_color, vector, '1 1 1') ATTRIB(InputBox, cb_colorF, vector, '1 1 1') ATTRIB(InputBox, cb_colorC, vector, '1 1 1') ENDCLASS(InputBox) #endif #ifdef IMPLEMENTATION void InputBox_configureInputBox(entity me, string theText, float theCursorPos, float theFontSize, string gfx) { SUPER(InputBox).configureLabel(me, theText, theFontSize, 0.0); me.src = gfx; me.cursorPos = theCursorPos; } void InputBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize) { SUPER(InputBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize); if (me.enableClearButton) { me.cb_width = absSize.y / absSize.x; me.cb_offset = bound(-1, me.cb_offset, 0) * me.cb_width; // bound to range -1, 0 me.keepspaceRight = me.keepspaceRight - me.cb_offset + me.cb_width; } } void InputBox_setText(entity me, string txt) { if(me.text) strunzone(me.text); SUPER(InputBox).setText(me, strzone(txt)); } float over_ClearButton(entity me, vector pos) { if (pos.x >= 1 + me.cb_offset - me.cb_width) if (pos.x < 1 + me.cb_offset) if (pos.y >= 0) if (pos.y < 1) return 1; return 0; } float InputBox_mouseMove(entity me, vector pos) { if (me.enableClearButton) { if (over_ClearButton(me, pos)) { me.cb_focused = 1; return 1; } me.cb_focused = 0; } return 1; } float InputBox_mouseDrag(entity me, vector pos) { float p; if(me.pressed) { me.dragScrollPos = pos; p = me.scrollPos + pos.x - me.keepspaceLeft; me.cursorPos = draw_TextLengthUpToWidth(me.text, p, 0, me.realFontSize); me.lastChangeTime = time; } else if (me.enableClearButton) { if (over_ClearButton(me, pos)) { me.cb_pressed = 1; return 1; } } me.cb_pressed = 0; return 1; } float InputBox_mousePress(entity me, vector pos) { if (me.enableClearButton) if (over_ClearButton(me, pos)) { me.cb_pressed = 1; return 1; } me.dragScrollTimer = time; me.pressed = 1; return InputBox_mouseDrag(me, pos); } float InputBox_mouseRelease(entity me, vector pos) { if(me.cb_pressed) if (over_ClearButton(me, pos)) { m_play_click_sound(MENU_SOUND_CLEAR); me.setText(me, ""); me.cb_pressed = 0; return 1; } float r = InputBox_mouseDrag(me, pos); //reset cb_pressed after mouseDrag, mouseDrag could set cb_pressed in this case: //mouse press out of the clear button, drag and then mouse release over the clear button me.cb_pressed = 0; me.pressed = 0; return r; } void InputBox_enterText(entity me, string ch) { float i; for(i = 0; i < strlen(ch); ++i) if(strstrofs(me.forbiddenCharacters, substring(ch, i, 1), 0) > -1) return; if(me.maxLength > 0) { if(strlen(ch) + strlen(me.text) > me.maxLength) return; } else if(me.maxLength < 0) { if(u8_strsize(ch) + u8_strsize(me.text) > -me.maxLength) return; } me.setText(me, strcat(substring(me.text, 0, me.cursorPos), ch, substring(me.text, me.cursorPos, strlen(me.text) - me.cursorPos))); me.cursorPos += strlen(ch); } float InputBox_keyDown(entity me, float key, float ascii, float shift) { me.lastChangeTime = time; me.dragScrollTimer = time; if(ascii >= 32 && ascii != 127) { me.enterText(me, chr(ascii)); return 1; } switch(key) { case K_KP_LEFTARROW: case K_LEFTARROW: me.cursorPos -= 1; return 1; case K_KP_RIGHTARROW: case K_RIGHTARROW: me.cursorPos += 1; return 1; case K_KP_HOME: case K_HOME: me.cursorPos = 0; return 1; case K_KP_END: case K_END: me.cursorPos = strlen(me.text); return 1; case K_BACKSPACE: if(me.cursorPos > 0) { me.cursorPos -= 1; me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1))); } return 1; case K_KP_DEL: case K_DEL: if(shift & S_CTRL) { m_play_click_sound(MENU_SOUND_CLEAR); me.setText(me, ""); } else me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1))); return 1; } return 0; } void InputBox_draw(entity me) { string CURSOR = "_"; float cursorPosInWidths, totalSizeInWidths; if(me.pressed) me.mouseDrag(me, me.dragScrollPos); // simulate mouseDrag event if(me.recalcPos) me.recalcPositionWithText(me, me.text); me.focusable = !me.disabled; if(me.disabled) draw_alpha *= me.disabledAlpha; if(me.src) { if(me.focused && !me.disabled) draw_ButtonPicture('0 0 0', strcat(me.src, "_f"), '1 1 0', me.colorF, 1); else draw_ButtonPicture('0 0 0', strcat(me.src, "_n"), '1 1 0', me.color, 1); } me.cursorPos = bound(0, me.cursorPos, strlen(me.text)); cursorPosInWidths = draw_TextWidth(substring(me.text, 0, me.cursorPos), 0, me.realFontSize); totalSizeInWidths = draw_TextWidth(strcat(me.text, CURSOR), 0, me.realFontSize); if(me.dragScrollTimer < time) { float save; save = me.scrollPos; me.scrollPos = bound(cursorPosInWidths - (0.875 - me.keepspaceLeft - me.keepspaceRight), me.scrollPos, cursorPosInWidths - 0.125); if(me.scrollPos != save) me.dragScrollTimer = time + 0.2; } me.scrollPos = min(me.scrollPos, totalSizeInWidths - (1 - me.keepspaceRight - me.keepspaceLeft)); me.scrollPos = max(0, me.scrollPos); draw_SetClipRect(eX * me.keepspaceLeft, eX * (1 - me.keepspaceLeft - me.keepspaceRight) + eY); if(me.editColorCodes) { string ch, ch2; float i, n; vector theColor; float theAlpha; //float theVariableAlpha; vector p; vector theTempColor; float component; p = me.realOrigin - eX * me.scrollPos; theColor = '1 1 1'; theAlpha = 1; //theVariableAlpha = 1; // changes when ^ax found n = strlen(me.text); for(i = 0; i < n; ++i) { ch = substring(me.text, i, 1); if(ch == "^") { float w; ch2 = substring(me.text, i+1, 1); w = draw_TextWidth(strcat(ch, ch2), 0, me.realFontSize); if(ch2 == "^") { draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5); draw_Text(p + eX * 0.25 * w, "^", me.realFontSize, theColor, theAlpha, 0); } else if(ch2 == "0" || stof(ch2)) // digit? { switch(stof(ch2)) { case 0: theColor = '0 0 0'; theAlpha = 1; break; case 1: theColor = '1 0 0'; theAlpha = 1; break; case 2: theColor = '0 1 0'; theAlpha = 1; break; case 3: theColor = '1 1 0'; theAlpha = 1; break; case 4: theColor = '0 0 1'; theAlpha = 1; break; case 5: theColor = '0 1 1'; theAlpha = 1; break; case 6: theColor = '1 0 1'; theAlpha = 1; break; case 7: theColor = '1 1 1'; theAlpha = 1; break; case 8: theColor = '1 1 1'; theAlpha = 0.5; break; case 9: theColor = '0.5 0.5 0.5'; theAlpha = 1; break; } draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5); draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0); } else if(ch2 == "x") // ^x found { theColor = '1 1 1'; component = HEXDIGIT_TO_DEC(substring(me.text, i+2, 1)); if (component >= 0) // ^xr found { theTempColor.x = component/15; component = HEXDIGIT_TO_DEC(substring(me.text, i+3, 1)); if (component >= 0) // ^xrg found { theTempColor.y = component/15; component = HEXDIGIT_TO_DEC(substring(me.text, i+4, 1)); if (component >= 0) // ^xrgb found { theTempColor.z = component/15; theColor = theTempColor; w = draw_TextWidth(substring(me.text, i, 5), 0, me.realFontSize); draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5); draw_Text(p, substring(me.text, i, 5), me.realFontSize, theColor, 1, 0); // theVariableAlpha instead of 1 using alpha tags ^ax i += 3; } else { // blue missing w = draw_TextWidth(substring(me.text, i, 4), 0, me.realFontSize); draw_Fill(p, eX * w + eY * me.realFontSize.y, eZ, 0.5); draw_Text(p, substring(me.text, i, 4), me.realFontSize, '1 1 1', theAlpha, 0); i += 2; } } else { // green missing w = draw_TextWidth(substring(me.text, i, 3), 0, me.realFontSize); draw_Fill(p, eX * w + eY * me.realFontSize.y, eY, 0.5); draw_Text(p, substring(me.text, i, 3), me.realFontSize, '1 1 1', theAlpha, 0); i += 1; } } else { // red missing //w = draw_TextWidth(substring(me.text, i, 2), 0) * me.realFontSize_x; draw_Fill(p, eX * w + eY * me.realFontSize.y, eX, 0.5); draw_Text(p, substring(me.text, i, 2), me.realFontSize, '1 1 1', theAlpha, 0); } } else { draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5); draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0); } p += w * eX; ++i; continue; } draw_Text(p, ch, me.realFontSize, theColor, theAlpha, 0); // TODO theVariableAlpha p += eX * draw_TextWidth(ch, 0, me.realFontSize); } } else draw_Text(me.realOrigin - eX * me.scrollPos, me.text, me.realFontSize, '1 1 1', 1, 0); if(!me.focused || (time - me.lastChangeTime) < floor(time - me.lastChangeTime) + 0.5) draw_Text(me.realOrigin + eX * (cursorPosInWidths - me.scrollPos), CURSOR, me.realFontSize, '1 1 1', 1, 0); draw_ClearClip(); if (me.enableClearButton) if (me.text != "") { if(me.focused && me.cb_pressed) draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_c"), eX * me.cb_width + eY, me.cb_colorC, 1); else if(me.focused && me.cb_focused) draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_f"), eX * me.cb_width + eY, me.cb_colorF, 1); else draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_n"), eX * me.cb_width + eY, me.cb_color, 1); } // skipping SUPER(InputBox).draw(me); Item_draw(me); } void InputBox_showNotify(entity me) { me.focusable = !me.disabled; } #endif