clang-format AngleScript source files

Unsurprisingly it doesn't support AngelScript, so the Java language mode
is used instead. The overall result seems good, but there's one problem:
Long statements starting with `@something = ` (object handle assignment)
are broken after the `@`. To work-around this, I had to set
`ColumnLimit` to `100`.
master
yvt 2019-07-13 23:40:42 +09:00
parent cb89824f32
commit c37a013157
64 changed files with 7364 additions and 6958 deletions

View File

@ -18,3 +18,15 @@ PointerAlignment: Right
AllowShortFunctionsOnASingleLine: Inline
AllowShortCaseLabelsOnASingleLine: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
---
# The style for AngelScript source files
Language: Java
UseTab: Never
ColumnLimit: 100
NamespaceIndentation: All
IndentCaseLabels: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortCaseLabelsOnASingleLine: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true

View File

@ -1,22 +1,21 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Utils.as"
*/
#include "Utils.as"

View File

@ -19,133 +19,117 @@
*/
namespace spades {
// AngelScript doesn't seem to support user-defined template functions...
// AngelScript doesn't seem to support user-defined template functions...
uint Min(uint a, uint b) {
return (a < b) ? a : b;
}
uint Min(uint a, uint b) { return (a < b) ? a : b; }
uint Max(uint a, uint b) {
return (a > b) ? a : b;
}
uint Max(uint a, uint b) { return (a > b) ? a : b; }
int Min(int a, int b) {
return (a < b) ? a : b;
}
int Min(int a, int b) { return (a < b) ? a : b; }
int Max(int a, int b) {
return (a > b) ? a : b;
}
int Max(int a, int b) { return (a > b) ? a : b; }
float Min(float a, float b) {
return (a < b) ? a : b;
}
float Min(float a, float b) { return (a < b) ? a : b; }
float Max(float a, float b) {
return (a > b) ? a : b;
}
float Max(float a, float b) { return (a > b) ? a : b; }
float Clamp(float val, float lower, float upper) {
return Min(Max(val, lower), upper);
}
float Clamp(float val, float lower, float upper) { return Min(Max(val, lower), upper); }
int Clamp(int val, int lower, int upper) {
return Min(Max(val, lower), upper);
}
int Clamp(int val, int lower, int upper) { return Min(Max(val, lower), upper); }
uint Clamp(uint val, uint lower, uint upper) {
return Min(Max(val, lower), upper);
}
uint Clamp(uint val, uint lower, uint upper) { return Min(Max(val, lower), upper); }
/** Renders an image in the way CSS border-image does. */
void DrawSliceImage(Renderer@ renderer, Image@ image, float x, float y, float w, float h, float border) {
float iw = image.Width;
float ih = image.Height;
renderer.DrawImage(image, AABB2(x, y, border, border),
AABB2(0.f, 0.f, border, border));
renderer.DrawImage(image, AABB2(x + w - border, y, border, border),
AABB2(iw - border, 0.f, border, border));
renderer.DrawImage(image, AABB2(x, y + h - border, border, border),
AABB2(0.f, ih - border, border, border));
renderer.DrawImage(image, AABB2(x + w - border, y + h - border, border, border),
AABB2(iw - border, ih - border, border, border));
renderer.DrawImage(image, AABB2(x + border, y, w - border - border, border),
AABB2(border, 0.f, iw - border - border, border));
renderer.DrawImage(image, AABB2(x + border, y + h - border, w - border - border, border),
AABB2(border, ih - border, iw - border - border, border));
renderer.DrawImage(image, AABB2(x, y + border, border, h - border - border),
AABB2(0.f, border, border, ih - border - border));
renderer.DrawImage(image, AABB2(x + w - border, y + border, border, h - border - border),
AABB2(iw - border, border, border, ih - border - border));
renderer.DrawImage(image, AABB2(x + border, y + border, w - border - border, h - border - border),
AABB2(border, border, iw - border - border, ih - border - border));
}
/** Renders an image in the way CSS border-image does. */
void DrawSliceImage(Renderer @renderer, Image @image, float x, float y, float w, float h,
float border) {
float iw = image.Width;
float ih = image.Height;
renderer.DrawImage(image, AABB2(x, y, border, border), AABB2(0.f, 0.f, border, border));
renderer.DrawImage(image, AABB2(x + w - border, y, border, border),
AABB2(iw - border, 0.f, border, border));
renderer.DrawImage(image, AABB2(x, y + h - border, border, border),
AABB2(0.f, ih - border, border, border));
renderer.DrawImage(image, AABB2(x + w - border, y + h - border, border, border),
AABB2(iw - border, ih - border, border, border));
renderer.DrawImage(image, AABB2(x + border, y, w - border - border, border),
AABB2(border, 0.f, iw - border - border, border));
renderer.DrawImage(image, AABB2(x + border, y + h - border, w - border - border, border),
AABB2(border, ih - border, iw - border - border, border));
renderer.DrawImage(image, AABB2(x, y + border, border, h - border - border),
AABB2(0.f, border, border, ih - border - border));
renderer.DrawImage(image, AABB2(x + w - border, y + border, border, h - border - border),
AABB2(iw - border, border, border, ih - border - border));
renderer.DrawImage(image,
AABB2(x + border, y + border, w - border - border, h - border - border),
AABB2(border, border, iw - border - border, ih - border - border));
}
/** Returns the byte index for a certain character index. */
int GetByteIndexForString(string s, int charIndex, int start = 0) {
int len = s.length;
while(start < len && charIndex > 0) {
int c = s[start];
if((c & 0x80) == 0) {
charIndex--;
start += 1;
} else if((c & 0xe0) == 0xc0) {
charIndex--;
start += 2;
} else if((c & 0xf0) == 0xe0) {
charIndex--;
start += 3;
} else if((c & 0xf8) == 0xf0) {
charIndex--;
start += 4;
} else if((c & 0xfc) == 0xf8) {
charIndex--;
start += 5;
} else if((c & 0xfe) == 0xfc) {
charIndex--;
start += 6;
} else{
// invalid!
charIndex--;
start++;
}
}
/** Returns the byte index for a certain character index. */
int GetByteIndexForString(string s, int charIndex, int start = 0) {
int len = s.length;
while (start < len && charIndex > 0) {
int c = s[start];
if ((c & 0x80) == 0) {
charIndex--;
start += 1;
} else if ((c & 0xe0) == 0xc0) {
charIndex--;
start += 2;
} else if ((c & 0xf0) == 0xe0) {
charIndex--;
start += 3;
} else if ((c & 0xf8) == 0xf0) {
charIndex--;
start += 4;
} else if ((c & 0xfc) == 0xf8) {
charIndex--;
start += 5;
} else if ((c & 0xfe) == 0xfc) {
charIndex--;
start += 6;
} else {
// invalid!
charIndex--;
start++;
}
}
if(start > len) start = len;
return start;
}
if (start > len)
start = len;
return start;
}
/** Returns the byte index for a certain character index. */
int GetCharIndexForString(string s, int byteIndex, int start = 0) {
int len = s.length;
int charIndex = 0;
while(start < len && start < byteIndex && byteIndex > 0) {
int c = s[start];
if((c & 0x80) == 0) {
charIndex++;
start += 1;
} else if((c & 0xe0) == 0xc0) {
charIndex++;
start += 2;
} else if((c & 0xf0) == 0xe0) {
charIndex++;
start += 3;
} else if((c & 0xf8) == 0xf0) {
charIndex++;
start += 4;
} else if((c & 0xfc) == 0xf8) {
charIndex++;
start += 5;
} else if((c & 0xfe) == 0xfc) {
charIndex++;
start += 6;
} else {
// invalid!
charIndex++;
start++;
}
}
/** Returns the byte index for a certain character index. */
int GetCharIndexForString(string s, int byteIndex, int start = 0) {
int len = s.length;
int charIndex = 0;
while (start < len && start < byteIndex && byteIndex > 0) {
int c = s[start];
if ((c & 0x80) == 0) {
charIndex++;
start += 1;
} else if ((c & 0xe0) == 0xc0) {
charIndex++;
start += 2;
} else if ((c & 0xf0) == 0xe0) {
charIndex++;
start += 3;
} else if ((c & 0xf8) == 0xf0) {
charIndex++;
start += 4;
} else if ((c & 0xfc) == 0xf8) {
charIndex++;
start += 5;
} else if ((c & 0xfe) == 0xfc) {
charIndex++;
start += 6;
} else {
// invalid!
charIndex++;
start++;
}
}
return charIndex;
}
return charIndex;
}
}

View File

@ -21,10 +21,10 @@
namespace spades {
class ChatLogSayWindow: ClientChatWindow {
ChatLogWindow@ owner;
class ChatLogSayWindow : ClientChatWindow {
ChatLogWindow @owner;
ChatLogSayWindow(ChatLogWindow@ own, bool isTeamChat) {
ChatLogSayWindow(ChatLogWindow @own, bool isTeamChat) {
super(own.ui, isTeamChat);
@owner = own;
}
@ -35,20 +35,20 @@ namespace spades {
}
}
class ChatLogWindow: spades::ui::UIElement {
class ChatLogWindow : spades::ui::UIElement {
float contentsTop, contentsHeight;
ClientUI@ ui;
private ClientUIHelper@ helper;
ClientUI @ui;
private ClientUIHelper @helper;
private spades::ui::TextViewer@ viewer;
ChatLogSayWindow@ sayWindow;
private spades::ui::TextViewer @viewer;
ChatLogSayWindow @sayWindow;
private spades::ui::UIElement@ sayButton1;
private spades::ui::UIElement@ sayButton2;
private spades::ui::UIElement @sayButton1;
private spades::ui::UIElement @sayButton2;
ChatLogWindow(ClientUI@ ui) {
ChatLogWindow(ClientUI @ui) {
super(ui.manager);
@this.ui = ui;
@this.helper = ui.helper;
@ -75,20 +75,16 @@ namespace spades {
{
spades::ui::Button button(Manager);
button.Caption = _Tr("Client", "Close");
button.Bounds = AABB2(
contentsLeft + contentsWidth - 150.f,
contentsTop + contentsHeight - 30.f
, 150.f, 30.f);
button.Bounds = AABB2(contentsLeft + contentsWidth - 150.f,
contentsTop + contentsHeight - 30.f, 150.f, 30.f);
@button.Activated = spades::ui::EventHandler(this.OnOkPressed);
AddChild(button);
}
{
spades::ui::Button button(Manager);
button.Caption = _Tr("Client", "Say Global");
button.Bounds = AABB2(
contentsLeft,
contentsTop + contentsHeight - 30.f
, 150.f, 30.f);
button.Bounds =
AABB2(contentsLeft, contentsTop + contentsHeight - 30.f, 150.f, 30.f);
@button.Activated = spades::ui::EventHandler(this.OnGlobalChat);
AddChild(button);
@this.sayButton1 = button;
@ -96,10 +92,8 @@ namespace spades {
{
spades::ui::Button button(Manager);
button.Caption = _Tr("Client", "Say Team");
button.Bounds = AABB2(
contentsLeft + 155.f,
contentsTop + contentsHeight - 30.f
, 150.f, 30.f);
button.Bounds =
AABB2(contentsLeft + 155.f, contentsTop + contentsHeight - 30.f, 150.f, 30.f);
@button.Activated = spades::ui::EventHandler(this.OnTeamChat);
AddChild(button);
@this.sayButton2 = button;
@ -107,7 +101,8 @@ namespace spades {
{
spades::ui::TextViewer viewer(Manager);
AddChild(viewer);
viewer.Bounds = AABB2(contentsLeft, contentsTop, contentsWidth, contentsHeight - 40.f);
viewer.Bounds =
AABB2(contentsLeft, contentsTop, contentsWidth, contentsHeight - 40.f);
@this.viewer = viewer;
}
}
@ -117,9 +112,7 @@ namespace spades {
viewer.ScrollToEnd();
}
void Close() {
@ui.ActiveUI = null;
}
void Close() { @ui.ActiveUI = null; }
void SayWindowClosed() {
@sayWindow = null;
@ -127,12 +120,10 @@ namespace spades {
sayButton2.Enable = true;
}
private void OnOkPressed(spades::ui::UIElement@ sender) {
Close();
}
private void OnOkPressed(spades::ui::UIElement @sender) { Close(); }
private void OnTeamChat(spades::ui::UIElement@ sender) {
if(sayWindow !is null) {
private void OnTeamChat(spades::ui::UIElement @sender) {
if (sayWindow !is null) {
sayWindow.IsTeamChat = true;
return;
}
@ -145,8 +136,8 @@ namespace spades {
@Manager.ActiveElement = wnd.field;
}
private void OnGlobalChat(spades::ui::UIElement@ sender) {
if(sayWindow !is null) {
private void OnGlobalChat(spades::ui::UIElement @sender) {
if (sayWindow !is null) {
sayWindow.IsTeamChat = false;
return;
}
@ -160,45 +151,40 @@ namespace spades {
}
void HotKey(string key) {
if(sayWindow !is null) {
if (sayWindow !is null) {
UIElement::HotKey(key);
return;
}
if(IsEnabled and (key == "Escape")) {
if (IsEnabled and(key == "Escape")) {
Close();
} else if(IsEnabled and (key == "y")) {
} else if (IsEnabled and(key == "y")) {
OnTeamChat(this);
} else if(IsEnabled and (key == "t")) {
} else if (IsEnabled and(key == "t")) {
OnGlobalChat(this);
} else {
UIElement::HotKey(key);
}
}
void Record(string text, Vector4 color) {
viewer.AddLine(text, this.IsVisible, color);
}
void Record(string text, Vector4 color) { viewer.AddLine(text, this.IsVisible, color); }
void Render() {
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Renderer@ r = Manager.Renderer;
Image@ img = r.RegisterImage("Gfx/White.tga");
Renderer @r = Manager.Renderer;
Image @img = r.RegisterImage("Gfx/White.tga");
r.ColorNP = Vector4(1, 1, 1, 0.08f);
r.DrawImage(img, AABB2(pos.x, pos.y + contentsTop - 15.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop - 15.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 15.f, size.x, 1.f));
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 15.f, size.x, 1.f));
r.ColorNP = Vector4(1, 1, 1, 0.2f);
r.DrawImage(img, AABB2(pos.x, pos.y + contentsTop - 14.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop - 14.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 14.f, size.x, 1.f));
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 14.f, size.x, 1.f));
UIElement::Render();
}
}
}

View File

@ -22,19 +22,20 @@
namespace spades {
uint StringCommonPrefixLength(string a, string b) {
for(uint i = 0, ln = Min(a.length, b.length); i < ln; i++) {
if(ToLower(a[i]) != ToLower(b[i])) return i;
for (uint i = 0, ln = Min(a.length, b.length); i < ln; i++) {
if (ToLower(a[i]) != ToLower(b[i]))
return i;
}
return Min(a.length, b.length);
}
/** Shows cvar's current value when user types something like "/cg_foobar" */
class CommandFieldConfigValueView: spades::ui::UIElement {
string[]@ configNames;
class CommandFieldConfigValueView : spades::ui::UIElement {
string[] @configNames;
string[] configValues;
CommandFieldConfigValueView(spades::ui::UIManager@ manager, string[] configNames) {
CommandFieldConfigValueView(spades::ui::UIManager @manager, string[] configNames) {
super(manager);
for(uint i = 0, len = configNames.length; i < len; i++) {
for (uint i = 0, len = configNames.length; i < len; i++) {
configValues.insertLast(ConfigItem(configNames[i]).StringValue);
}
@this.configNames = configNames;
@ -42,11 +43,11 @@ namespace spades {
void Render() {
float maxNameLen = 0.f;
float maxValueLen = 20.f;
Font@ font = this.Font;
Renderer@ renderer = this.Manager.Renderer;
Font @font = this.Font;
Renderer @renderer = this.Manager.Renderer;
float rowHeight = 25.f;
for(uint i = 0, len = configNames.length; i < len; i++) {
for (uint i = 0, len = configNames.length; i < len; i++) {
maxNameLen = Max(maxNameLen, font.Measure(configNames[i]).x);
maxValueLen = Max(maxValueLen, font.Measure(configValues[i]).x);
}
@ -54,60 +55,54 @@ namespace spades {
pos.y -= float(configNames.length) * rowHeight + 10.f;
renderer.ColorNP = Vector4(0.f, 0.f, 0.f, 0.5f);
renderer.DrawImage(null,
AABB2(pos.x, pos.y, maxNameLen + maxValueLen + 20.f,
float(configNames.length) * rowHeight + 10.f));
renderer.DrawImage(null, AABB2(pos.x, pos.y, maxNameLen + maxValueLen + 20.f,
float(configNames.length) * rowHeight + 10.f));
for(uint i = 0, len = configNames.length; i < len; i++) {
font.DrawShadow(configNames[i],
pos + Vector2(5.f, 8.f + float(i) * rowHeight),
1.f, Vector4(1,1,1,0.7), Vector4(0,0,0,0.3f));
for (uint i = 0, len = configNames.length; i < len; i++) {
font.DrawShadow(configNames[i], pos + Vector2(5.f, 8.f + float(i) * rowHeight), 1.f,
Vector4(1, 1, 1, 0.7), Vector4(0, 0, 0, 0.3f));
font.DrawShadow(configValues[i],
pos + Vector2(15.f + maxNameLen, 8.f + float(i) * rowHeight),
1.f, Vector4(1,1,1,1), Vector4(0,0,0,0.4f));
pos + Vector2(15.f + maxNameLen, 8.f + float(i) * rowHeight), 1.f,
Vector4(1, 1, 1, 1), Vector4(0, 0, 0, 0.4f));
}
}
}
class CommandField: FieldWithHistory {
CommandFieldConfigValueView@ valueView;
class CommandField : FieldWithHistory {
CommandFieldConfigValueView @valueView;
CommandField(spades::ui::UIManager@ manager, array<spades::ui::CommandHistoryItem@>@ history) {
CommandField(spades::ui::UIManager @manager,
array<spades::ui::CommandHistoryItem @> @history) {
super(manager, history);
}
void OnChanged() {
FieldWithHistory::OnChanged();
if(valueView !is null) {
if (valueView !is null) {
@valueView.Parent = null;
}
if(Text.substr(0, 1) == "/" &&
Text.substr(1, 1) != " ") {
if (Text.substr(0, 1) == "/" && Text.substr(1, 1) != " ") {
int whitespace = Text.findFirst(" ");
if(whitespace < 0) {
if (whitespace < 0) {
whitespace = int(Text.length);
}
string input = Text.substr(1, whitespace - 1);
if(input.length >= 2) {
string[]@ names = GetAllConfigNames();
if (input.length >= 2) {
string[] @names = GetAllConfigNames();
string[] filteredNames;
for(uint i = 0, len = names.length; i < len; i++) {
if (
StringCommonPrefixLength(input, names[i]) == input.length &&
!ConfigItem(names[i]).IsUnknown
) {
for (uint i = 0, len = names.length; i < len; i++) {
if (StringCommonPrefixLength(input, names[i]) == input.length &&
!ConfigItem(names[i]).IsUnknown) {
filteredNames.insertLast(names[i]);
if(filteredNames.length >= 8) {
if (filteredNames.length >= 8) {
// too many
break;
}
}
}
if(filteredNames.length > 0) {
if (filteredNames.length > 0) {
@valueView = CommandFieldConfigValueView(this.Manager, filteredNames);
valueView.Bounds = AABB2(0.f, -15.f, 0.f, 0.f);
@valueView.Parent = this;
@ -117,22 +112,18 @@ namespace spades {
}
void KeyDown(string key) {
if(key == "Tab") {
if(SelectionLength == 0 &&
SelectionStart == int(Text.length) &&
Text.substr(0, 1) == "/" &&
Text.findFirst(" ") < 0) {
if (key == "Tab") {
if (SelectionLength == 0 && SelectionStart == int(Text.length) &&
Text.substr(0, 1) == "/" && Text.findFirst(" ") < 0) {
// config variable auto completion
string input = Text.substr(1);
string[]@ names = GetAllConfigNames();
string[] @names = GetAllConfigNames();
string commonPart;
bool foundOne = false;
for(uint i = 0, len = names.length; i < len; i++) {
if (
StringCommonPrefixLength(input, names[i]) == input.length &&
!ConfigItem(names[i]).IsUnknown
) {
if(!foundOne) {
for (uint i = 0, len = names.length; i < len; i++) {
if (StringCommonPrefixLength(input, names[i]) == input.length &&
!ConfigItem(names[i]).IsUnknown) {
if (!foundOne) {
commonPart = names[i];
foundOne = true;
}
@ -142,30 +133,29 @@ namespace spades {
}
}
if(commonPart.length > input.length) {
if (commonPart.length > input.length) {
Text = "/" + commonPart;
Select(Text.length, 0);
}
}
}else{
} else {
FieldWithHistory::KeyDown(key);
}
}
}
class ClientChatWindow: spades::ui::UIElement {
private ClientUI@ ui;
private ClientUIHelper@ helper;
class ClientChatWindow : spades::ui::UIElement {
private ClientUI @ui;
private ClientUIHelper @helper;
CommandField@ field;
spades::ui::Button@ sayButton;
spades::ui::SimpleButton@ teamButton;
spades::ui::SimpleButton@ globalButton;
CommandField @field;
spades::ui::Button @sayButton;
spades::ui::SimpleButton @teamButton;
spades::ui::SimpleButton @globalButton;
bool isTeamChat;
ClientChatWindow(ClientUI@ ui, bool isTeamChat) {
ClientChatWindow(ClientUI @ui, bool isTeamChat) {
super(ui.manager);
@this.ui = ui;
@this.helper = ui.helper;
@ -230,14 +220,13 @@ namespace spades {
}
}
void UpdateState() {
sayButton.Enable = field.Text.length > 0;
}
void UpdateState() { sayButton.Enable = field.Text.length > 0; }
bool IsTeamChat {
get final { return isTeamChat; }
set {
if(isTeamChat == value) return;
if (isTeamChat == value)
return;
isTeamChat = value;
teamButton.Toggled = isTeamChat;
globalButton.Toggled = not isTeamChat;
@ -245,39 +234,33 @@ namespace spades {
}
}
private void OnSetGlobal(spades::ui::UIElement@ sender) {
IsTeamChat = false;
}
private void OnSetTeam(spades::ui::UIElement@ sender) {
IsTeamChat = true;
}
private void OnSetGlobal(spades::ui::UIElement @sender) { IsTeamChat = false; }
private void OnSetTeam(spades::ui::UIElement @sender) { IsTeamChat = true; }
private void OnFieldChanged(spades::ui::UIElement@ sender) {
UpdateState();
}
private void OnFieldChanged(spades::ui::UIElement @sender) { UpdateState(); }
private void Close() {
@ui.ActiveUI = null;
}
private void Close() { @ui.ActiveUI = null; }
private void OnCancel(spades::ui::UIElement@ sender) {
private void OnCancel(spades::ui::UIElement @sender) {
field.Cancelled();
Close();
}
private bool CheckAndSetConfigVariable() {
string text = field.Text;
if(text.substr(0, 1) != "/") return false;
if (text.substr(0, 1) != "/")
return false;
int idx = text.findFirst(" ");
if(idx < 2) return false;
if (idx < 2)
return false;
// find variable
string varname = text.substr(1, idx - 1);
string[] vars = GetAllConfigNames();
for(uint i = 0, len = vars.length; i < len; i++) {
if(vars[i].length == varname.length &&
StringCommonPrefixLength(vars[i], varname) == vars[i].length) {
for (uint i = 0, len = vars.length; i < len; i++) {
if (vars[i].length == varname.length &&
StringCommonPrefixLength(vars[i], varname) == vars[i].length) {
// match
string val = text.substr(idx + 1);
ConfigItem item(vars[i]);
@ -289,10 +272,10 @@ namespace spades {
return false;
}
private void OnSay(spades::ui::UIElement@ sender) {
private void OnSay(spades::ui::UIElement @sender) {
field.CommandSent();
if(!CheckAndSetConfigVariable()) {
if(isTeamChat)
if (!CheckAndSetConfigVariable()) {
if (isTeamChat)
ui.helper.SayTeam(field.Text);
else
ui.helper.SayGlobal(field.Text);
@ -301,12 +284,12 @@ namespace spades {
}
void HotKey(string key) {
if(IsEnabled and key == "Escape") {
if (IsEnabled and key == "Escape") {
OnCancel(this);
}else if(IsEnabled and key == "Enter") {
if(field.Text.length == 0) {
} else if (IsEnabled and key == "Enter") {
if (field.Text.length == 0) {
OnCancel(this);
}else{
} else {
OnSay(this);
}
} else {

View File

@ -24,25 +24,26 @@
namespace spades {
class ClientUI {
private Renderer@ renderer;
private AudioDevice@ audioDevice;
FontManager@ fontManager;
ClientUIHelper@ helper;
private Renderer @renderer;
private AudioDevice @audioDevice;
FontManager @fontManager;
ClientUIHelper @helper;
spades::ui::UIManager@ manager;
spades::ui::UIElement@ activeUI;
spades::ui::UIManager @manager;
spades::ui::UIElement @activeUI;
ChatLogWindow@ chatLogWindow;
ChatLogWindow @chatLogWindow;
ClientMenu@ clientMenu;
ClientMenu @clientMenu;
array<spades::ui::CommandHistoryItem@> chatHistory;
array<spades::ui::CommandHistoryItem @> chatHistory;
bool shouldExit = false;
private float time = -1.f;
ClientUI(Renderer@ renderer, AudioDevice@ audioDevice, FontManager@ fontManager, ClientUIHelper@ helper) {
ClientUI(Renderer @renderer, AudioDevice @audioDevice, FontManager @fontManager,
ClientUIHelper @helper) {
@this.renderer = renderer;
@this.audioDevice = audioDevice;
@this.fontManager = fontManager;
@ -57,77 +58,55 @@ namespace spades {
@chatLogWindow = ChatLogWindow(this);
}
void MouseEvent(float x, float y) {
manager.MouseEvent(x, y);
}
void MouseEvent(float x, float y) { manager.MouseEvent(x, y); }
void WheelEvent(float x, float y) {
manager.WheelEvent(x, y);
}
void WheelEvent(float x, float y) { manager.WheelEvent(x, y); }
void KeyEvent(string key, bool down) {
manager.KeyEvent(key, down);
}
void KeyEvent(string key, bool down) { manager.KeyEvent(key, down); }
void TextInputEvent(string text) {
manager.TextInputEvent(text);
}
void TextInputEvent(string text) { manager.TextInputEvent(text); }
void TextEditingEvent(string text, int start, int len) {
manager.TextEditingEvent(text, start, len);
}
bool AcceptsTextInput() {
return manager.AcceptsTextInput;
}
bool AcceptsTextInput() { return manager.AcceptsTextInput; }
AABB2 GetTextInputRect() {
return manager.TextInputRect;
}
AABB2 GetTextInputRect() { return manager.TextInputRect; }
void RunFrame(float dt) {
if(time < 0.f) {
if (time < 0.f) {
time = 0.f;
}
manager.RunFrame(dt);
if(activeUI !is null){
if (activeUI !is null) {
manager.Render();
}
time += Min(dt, 0.05f);
}
void Closing() {
void Closing() {}
}
bool WantsClientToBeClosed() { return shouldExit; }
bool WantsClientToBeClosed() {
return shouldExit;
}
bool NeedsInput() { return activeUI !is null; }
bool NeedsInput() {
return activeUI !is null;
}
void set_ActiveUI(spades::ui::UIElement@ value) {
if(activeUI !is null) {
void set_ActiveUI(spades::ui::UIElement @value) {
if (activeUI !is null) {
manager.RootElement.RemoveChild(activeUI);
}
@activeUI = value;
if(activeUI !is null) {
if (activeUI !is null) {
activeUI.Bounds = manager.RootElement.Bounds;
manager.RootElement.AddChild(activeUI);
}
manager.KeyPanic();
}
spades::ui::UIElement@ get_ActiveUI(){
return activeUI;
}
spades::ui::UIElement @get_ActiveUI() { return activeUI; }
void EnterClientMenu() {
@ActiveUI = clientMenu;
}
void EnterClientMenu() { @ActiveUI = clientMenu; }
void EnterTeamChatWindow() {
ClientChatWindow wnd(this, true);
@ -147,17 +126,13 @@ namespace spades {
@ActiveUI = wnd;
@manager.ActiveElement = wnd.field;
}
void CloseUI() {
@ActiveUI = null;
}
void CloseUI() { @ActiveUI = null; }
void RecordChatLog(string text, Vector4 color) {
chatLogWindow.Record(text, color);
}
void RecordChatLog(string text, Vector4 color) { chatLogWindow.Record(text, color); }
}
ClientUI@ CreateClientUI(Renderer@ renderer, AudioDevice@ audioDevice,
FontManager@ fontManager, ClientUIHelper@ helper) {
ClientUI @CreateClientUI(Renderer @renderer, AudioDevice @audioDevice, FontManager @fontManager,
ClientUIHelper @helper) {
return ClientUI(renderer, audioDevice, fontManager, helper);
}

View File

@ -34,12 +34,13 @@ namespace spades {
}
// Field with bash-like history support
class FieldWithHistory: spades::ui::Field {
array<spades::ui::CommandHistoryItem@>@ cmdhistory;
CommandHistoryItem@ temporalLastHistory;
class FieldWithHistory : spades::ui::Field {
array<spades::ui::CommandHistoryItem @> @cmdhistory;
CommandHistoryItem @temporalLastHistory;
uint currentHistoryIndex;
FieldWithHistory(spades::ui::UIManager@ manager, array<spades::ui::CommandHistoryItem@>@ history) {
FieldWithHistory(spades::ui::UIManager @manager,
array<spades::ui::CommandHistoryItem @> @history) {
super(manager);
@this.cmdhistory = history;
@ -47,10 +48,8 @@ namespace spades {
@temporalLastHistory = this.CommandHistoryItemRep;
}
private CommandHistoryItem@ CommandHistoryItemRep {
get {
return CommandHistoryItem(this.Text, this.SelectionStart, this.SelectionEnd);
}
private CommandHistoryItem @CommandHistoryItemRep {
get { return CommandHistoryItem(this.Text, this.SelectionStart, this.SelectionEnd); }
set {
this.Text = value.text;
this.Select(value.selStart, value.selEnd - value.selStart);
@ -58,35 +57,35 @@ namespace spades {
}
private void OverwriteItem() {
if(currentHistoryIndex < cmdhistory.length) {
if (currentHistoryIndex < cmdhistory.length) {
@cmdhistory[currentHistoryIndex] = this.CommandHistoryItemRep;
}else if(currentHistoryIndex == cmdhistory.length) {
} else if (currentHistoryIndex == cmdhistory.length) {
@temporalLastHistory = this.CommandHistoryItemRep;
}
}
private void LoadItem() {
if(currentHistoryIndex < cmdhistory.length) {
if (currentHistoryIndex < cmdhistory.length) {
@this.CommandHistoryItemRep = cmdhistory[currentHistoryIndex];
}else if(currentHistoryIndex == cmdhistory.length) {
} else if (currentHistoryIndex == cmdhistory.length) {
@this.CommandHistoryItemRep = temporalLastHistory;
}
}
void KeyDown(string key) {
if(key == "Up") {
if(currentHistoryIndex > 0) {
if (key == "Up") {
if (currentHistoryIndex > 0) {
OverwriteItem();
currentHistoryIndex--;
LoadItem();
}
}else if(key == "Down") {
if(currentHistoryIndex < cmdhistory.length) {
} else if (key == "Down") {
if (currentHistoryIndex < cmdhistory.length) {
OverwriteItem();
currentHistoryIndex++;
LoadItem();
}
}else{
} else {
Field::KeyDown(key);
}
}
@ -96,9 +95,7 @@ namespace spades {
currentHistoryIndex = cmdhistory.length - 1;
}
void Cancelled() {
OverwriteItem();
}
void Cancelled() { OverwriteItem(); }
};
}

View File

@ -21,11 +21,11 @@
namespace spades {
class ClientMenu: spades::ui::UIElement {
private ClientUI@ ui;
private ClientUIHelper@ helper;
class ClientMenu : spades::ui::UIElement {
private ClientUI @ui;
private ClientUIHelper @helper;
ClientMenu(ClientUI@ ui) {
ClientMenu(ClientUI @ui) {
super(ui.manager);
@this.ui = ui;
@this.helper = ui.helper;
@ -37,8 +37,8 @@ namespace spades {
{
spades::ui::Label label(Manager);
label.BackgroundColor = Vector4(0, 0, 0, 0.5f);
label.Bounds = AABB2(0.f, 0.f,
Manager.Renderer.ScreenWidth, Manager.Renderer.ScreenHeight);
label.Bounds =
AABB2(0.f, 0.f, Manager.Renderer.ScreenWidth, Manager.Renderer.ScreenHeight);
AddChild(label);
}
@ -78,26 +78,22 @@ namespace spades {
}
}
private void OnBackToGame(spades::ui::UIElement@ sender) {
@ui.ActiveUI = null;
}
private void OnSetup(spades::ui::UIElement@ sender) {
private void OnBackToGame(spades::ui::UIElement @sender) { @ui.ActiveUI = null; }
private void OnSetup(spades::ui::UIElement @sender) {
PreferenceViewOptions opt;
opt.GameActive = true;
PreferenceView al(this, opt, ui.fontManager);
al.Run();
}
private void OnChatLog(spades::ui::UIElement@ sender) {
private void OnChatLog(spades::ui::UIElement @sender) {
@ui.ActiveUI = @ui.chatLogWindow;
ui.chatLogWindow.ScrollToEnd();
}
private void OnDisconnect(spades::ui::UIElement@ sender) {
ui.shouldExit = true;
}
private void OnDisconnect(spades::ui::UIElement @sender) { ui.shouldExit = true; }
void HotKey(string key) {
if(IsEnabled and key == "Escape") {
if (IsEnabled and key == "Escape") {
@ui.ActiveUI = null;
} else {
UIElement::HotKey(key);

File diff suppressed because it is too large Load Diff

View File

@ -19,19 +19,19 @@
*/
namespace spades {
class CreateProfileScreen: spades::ui::UIElement {
class CreateProfileScreen : spades::ui::UIElement {
private float contentsTop, contentsHeight;
spades::ui::EventHandler@ Closed;
private spades::ui::UIElement@ owner;
private spades::ui::Field@ nameField;
private spades::ui::Button@ okButton;
spades::ui::EventHandler @Closed;
private spades::ui::UIElement @owner;
private spades::ui::Field @nameField;
private spades::ui::Button @okButton;
private ConfigItem cg_playerName("cg_playerName", "Deuce");
private ConfigItem cg_playerNameIsSet("cg_playerNameIsSet", "0");
CreateProfileScreen(spades::ui::UIElement@ owner) {
CreateProfileScreen(spades::ui::UIElement @owner) {
super(owner.Manager);
@this.owner = owner;
@Font = Manager.RootElement.Font;
@ -56,10 +56,8 @@ namespace spades {
{
spades::ui::Button button(Manager);
button.Caption = _Tr("CreateProfileScreen", "OK");
button.Bounds = AABB2(
contentsLeft + contentsWidth - 140.f,
contentsTop + contentsHeight - 40.f
, 140.f, 30.f);
button.Bounds = AABB2(contentsLeft + contentsWidth - 140.f,
contentsTop + contentsHeight - 40.f, 140.f, 30.f);
@button.Activated = spades::ui::EventHandler(this.OnOkPressed);
button.Enable = false;
AddChild(button);
@ -68,10 +66,8 @@ namespace spades {
{
spades::ui::Button button(Manager);
button.Caption = _Tr("CreateProfileScreen", "Decide later");
button.Bounds = AABB2(
contentsLeft,
contentsTop + contentsHeight - 40.f
, 140.f, 30.f);
button.Bounds =
AABB2(contentsLeft, contentsTop + contentsHeight - 40.f, 140.f, 30.f);
@button.Activated = spades::ui::EventHandler(this.OnChooseLater);
AddChild(button);
}
@ -101,7 +97,8 @@ namespace spades {
}
{
spades::ui::Label label(Manager);
label.Text = _Tr("CreateProfileScreen", "You can change it later in the Setup dialog.");
label.Text =
_Tr("CreateProfileScreen", "You can change it later in the Setup dialog.");
label.Bounds = AABB2(contentsLeft, contentsTop + 106.f, contentsWidth, 32.f);
label.Alignment = Vector2(0.f, 0.5f);
AddChild(label);
@ -109,7 +106,7 @@ namespace spades {
}
private void OnClosed() {
if(Closed !is null) {
if (Closed !is null) {
Closed(this);
}
}
@ -126,7 +123,7 @@ namespace spades {
@Manager.ActiveElement = nameField;
}
private void OnOkPressed(spades::ui::UIElement@ sender) {
private void OnOkPressed(spades::ui::UIElement @sender) {
if (nameField.Text.length == 0) {
return;
}
@ -135,16 +132,14 @@ namespace spades {
Close();
}
private void OnChooseLater(spades::ui::UIElement@ sender) {
Close();
}
private void OnChooseLater(spades::ui::UIElement @sender) { Close(); }
private void OnNameChanged(spades::ui::UIElement@ sender) {
private void OnNameChanged(spades::ui::UIElement @sender) {
okButton.Enable = nameField.Text.length > 0;
}
void HotKey(string key) {
if(IsEnabled and (key == "Enter" or key == "Escape")) {
if (IsEnabled and(key == "Enter" or key == "Escape")) {
if (key == "Enter") {
OnOkPressed(this);
} else if (key == "Escape") {
@ -158,22 +153,19 @@ namespace spades {
void Render() {
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Renderer@ r = Manager.Renderer;
Image@ img = r.RegisterImage("Gfx/White.tga");
Renderer @r = Manager.Renderer;
Image @img = r.RegisterImage("Gfx/White.tga");
r.ColorNP = Vector4(1, 1, 1, 0.08f);
r.DrawImage(img, AABB2(pos.x, pos.y + contentsTop - 15.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop - 15.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 15.f, size.x, 1.f));
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 15.f, size.x, 1.f));
r.ColorNP = Vector4(1, 1, 1, 0.2f);
r.DrawImage(img, AABB2(pos.x, pos.y + contentsTop - 14.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop - 14.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 14.f, size.x, 1.f));
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 14.f, size.x, 1.f));
UIElement::Render();
}
}
}

View File

@ -23,68 +23,66 @@
namespace spades {
class RefreshButton: spades::ui::SimpleButton {
RefreshButton(spades::ui::UIManager@ manager){
super(manager);
}
class RefreshButton : spades::ui::SimpleButton {
RefreshButton(spades::ui::UIManager @manager) { super(manager); }
void Render() {
SimpleButton::Render();
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/UI/Refresh.png");
Image @img = renderer.RegisterImage("Gfx/UI/Refresh.png");
renderer.DrawImage(img, pos + (size - Vector2(16.f, 16.f)) * 0.5f);
}
}
class ProtocolButton: spades::ui::SimpleButton {
ProtocolButton(spades::ui::UIManager@ manager){
class ProtocolButton : spades::ui::SimpleButton {
ProtocolButton(spades::ui::UIManager @manager) {
super(manager);
Toggle = true;
}
}
uint8 ToLower(uint8 c) {
if(c >= uint8(0x41) and c <= uint8(0x5a)) {
if (c >= uint8(0x41) and c <= uint8(0x5a)) {
return uint8(c - 0x41 + 0x61);
} else {
return c;
}
}
bool StringContainsCaseInsensitive(string text, string pattern) {
for(int i = text.length - 1; i >= 0; i--)
for (int i = text.length - 1; i >= 0; i--)
text[i] = ToLower(text[i]);
for(int i = pattern.length - 1; i >= 0; i--)
for (int i = pattern.length - 1; i >= 0; i--)
pattern[i] = ToLower(pattern[i]);
return text.findFirst(pattern) >= 0;
}
class MainScreenMainMenu: spades::ui::UIElement {
class MainScreenMainMenu : spades::ui::UIElement {
MainScreenUI@ ui;
MainScreenHelper@ helper;
spades::ui::Field@ addressField;
MainScreenUI @ui;
MainScreenHelper @helper;
spades::ui::Field @addressField;
spades::ui::Button@ protocol3Button;
spades::ui::Button@ protocol4Button;
spades::ui::Button @protocol3Button;
spades::ui::Button @protocol4Button;
spades::ui::Button@ filterProtocol3Button;
spades::ui::Button@ filterProtocol4Button;
spades::ui::Button@ filterEmptyButton;
spades::ui::Button@ filterFullButton;
spades::ui::Field@ filterField;
spades::ui::Button @filterProtocol3Button;
spades::ui::Button @filterProtocol4Button;
spades::ui::Button @filterEmptyButton;
spades::ui::Button @filterFullButton;
spades::ui::Field @filterField;
spades::ui::ListView@ serverList;
MainScreenServerListLoadingView@ loadingView;
MainScreenServerListErrorView@ errorView;
spades::ui::ListView @serverList;
MainScreenServerListLoadingView @loadingView;
MainScreenServerListErrorView @errorView;
bool loading = false, loaded = false;
private ConfigItem cg_protocolVersion("cg_protocolVersion", "3");
private ConfigItem cg_lastQuickConnectHost("cg_lastQuickConnectHost", "127.0.0.1");
private ConfigItem cg_serverlistSort("cg_serverlistSort", "16385");
MainScreenMainMenu(MainScreenUI@ ui) {
MainScreenMainMenu(MainScreenUI @ui) {
super(ui.manager);
@this.ui = ui;
@this.helper = ui.helper;
@ -109,8 +107,8 @@ namespace spades {
}
{
@protocol3Button = ProtocolButton(Manager);
protocol3Button.Bounds = AABB2(contentsLeft + contentsWidth - 240.f + 6.f, 200,
40.f, 30.f);
protocol3Button.Bounds =
AABB2(contentsLeft + contentsWidth - 240.f + 6.f, 200, 40.f, 30.f);
protocol3Button.Caption = _Tr("MainScreen", "0.75");
@protocol3Button.Activated = spades::ui::EventHandler(this.OnProtocol3Pressed);
protocol3Button.Toggle = true;
@ -119,8 +117,8 @@ namespace spades {
}
{
@protocol4Button = ProtocolButton(Manager);
protocol4Button.Bounds = AABB2(contentsLeft + contentsWidth - 200.f + 6.f, 200,
40.f, 30.f);
protocol4Button.Bounds =
AABB2(contentsLeft + contentsWidth - 200.f + 6.f, 200, 40.f, 30.f);
protocol4Button.Caption = _Tr("MainScreen", "0.76");
@protocol4Button.Activated = spades::ui::EventHandler(this.OnProtocol4Pressed);
protocol4Button.Toggle = true;
@ -163,26 +161,25 @@ namespace spades {
}
{
@filterProtocol3Button = ProtocolButton(Manager);
filterProtocol3Button.Bounds = AABB2(contentsLeft + 50.f, footerPos,
40.f, 30.f);
filterProtocol3Button.Bounds = AABB2(contentsLeft + 50.f, footerPos, 40.f, 30.f);
filterProtocol3Button.Caption = _Tr("MainScreen", "0.75");
@filterProtocol3Button.Activated = spades::ui::EventHandler(this.OnFilterProtocol3Pressed);
@filterProtocol3Button.Activated
= spades::ui::EventHandler(this.OnFilterProtocol3Pressed);
filterProtocol3Button.Toggle = true;
AddChild(filterProtocol3Button);
}
{
@filterProtocol4Button = ProtocolButton(Manager);
filterProtocol4Button.Bounds = AABB2(contentsLeft + 90.f, footerPos,
40.f, 30.f);
filterProtocol4Button.Bounds = AABB2(contentsLeft + 90.f, footerPos, 40.f, 30.f);
filterProtocol4Button.Caption = _Tr("MainScreen", "0.76");
@filterProtocol4Button.Activated = spades::ui::EventHandler(this.OnFilterProtocol4Pressed);
@filterProtocol4Button.Activated
= spades::ui::EventHandler(this.OnFilterProtocol4Pressed);
filterProtocol4Button.Toggle = true;
AddChild(filterProtocol4Button);
}
{
@filterEmptyButton = ProtocolButton(Manager);
filterEmptyButton.Bounds = AABB2(contentsLeft + 135.f, footerPos,
50.f, 30.f);
filterEmptyButton.Bounds = AABB2(contentsLeft + 135.f, footerPos, 50.f, 30.f);
filterEmptyButton.Caption = _Tr("MainScreen", "Empty");
@filterEmptyButton.Activated = spades::ui::EventHandler(this.OnFilterEmptyPressed);
filterEmptyButton.Toggle = true;
@ -190,8 +187,7 @@ namespace spades {
}
{
@filterFullButton = ProtocolButton(Manager);
filterFullButton.Bounds = AABB2(contentsLeft + 185.f, footerPos,
70.f, 30.f);
filterFullButton.Bounds = AABB2(contentsLeft + 185.f, footerPos, 70.f, 30.f);
filterFullButton.Caption = _Tr("MainScreen", "Not Full");
@filterFullButton.Activated = spades::ui::EventHandler(this.OnFilterFullPressed);
filterFullButton.Toggle = true;
@ -267,7 +263,7 @@ namespace spades {
}
void LoadServerList() {
if(loading) {
if (loading) {
return;
}
loaded = false;
@ -278,54 +274,42 @@ namespace spades {
helper.StartQuery();
}
void ServerListItemActivated(ServerListModel@ sender, MainScreenServerItem@ item) {
void ServerListItemActivated(ServerListModel @sender, MainScreenServerItem @item) {
addressField.Text = item.Address;
cg_lastQuickConnectHost = addressField.Text;
if(item.Protocol == "0.75") {
if (item.Protocol == "0.75") {
SetProtocolVersion(3);
}else if(item.Protocol == "0.76") {
} else if (item.Protocol == "0.76") {
SetProtocolVersion(4);
}
addressField.SelectAll();
}
void ServerListItemDoubleClicked(ServerListModel@ sender, MainScreenServerItem@ item) {
void ServerListItemDoubleClicked(ServerListModel @sender, MainScreenServerItem @item) {
ServerListItemActivated(sender, item);
// Double-click to connect
Connect();
}
void ServerListItemRightClicked(ServerListModel@ sender, MainScreenServerItem@ item) {
void ServerListItemRightClicked(ServerListModel @sender, MainScreenServerItem @item) {
helper.SetServerFavorite(item.Address, !item.Favorite);
UpdateServerList();
}
private void SortServerListByPing(spades::ui::UIElement@ sender) {
SortServerList(0);
}
private void SortServerListByNumPlayers(spades::ui::UIElement@ sender) {
private void SortServerListByPing(spades::ui::UIElement @sender) { SortServerList(0); }
private void SortServerListByNumPlayers(spades::ui::UIElement @sender) {
SortServerList(1);
}
private void SortServerListByName(spades::ui::UIElement@ sender) {
SortServerList(2);
}
private void SortServerListByMapName(spades::ui::UIElement@ sender) {
SortServerList(3);
}
private void SortServerListByGameMode(spades::ui::UIElement@ sender) {
SortServerList(4);
}
private void SortServerListByProtocol(spades::ui::UIElement@ sender) {
SortServerList(5);
}
private void SortServerListByCountry(spades::ui::UIElement@ sender) {
SortServerList(6);
}
private void SortServerListByName(spades::ui::UIElement @sender) { SortServerList(2); }
private void SortServerListByMapName(spades::ui::UIElement @sender) { SortServerList(3); }
private void SortServerListByGameMode(spades::ui::UIElement @sender) { SortServerList(4); }
private void SortServerListByProtocol(spades::ui::UIElement @sender) { SortServerList(5); }
private void SortServerListByCountry(spades::ui::UIElement @sender) { SortServerList(6); }
private void SortServerList(int keyId) {
int sort = cg_serverlistSort.IntValue;
if(int(sort & 0xfff) == keyId) {
if (int(sort & 0xfff) == keyId) {
sort ^= int(0x4000);
} else {
sort = keyId;
@ -336,7 +320,7 @@ namespace spades {
private void UpdateServerList() {
string key = "";
switch(cg_serverlistSort.IntValue & 0xfff) {
switch (cg_serverlistSort.IntValue & 0xfff) {
case 0: key = "Ping"; break;
case 1: key = "NumPlayers"; break;
case 2: key = "Name"; break;
@ -345,9 +329,9 @@ namespace spades {
case 5: key = "Protocol"; break;
case 6: key = "Country"; break;
}
MainScreenServerItem@[]@ list = helper.GetServerList(key,
(cg_serverlistSort.IntValue & 0x4000) != 0);
if((list is null) or (loading)){
MainScreenServerItem @[] @list =
helper.GetServerList(key, (cg_serverlistSort.IntValue & 0x4000) != 0);
if ((list is null)or(loading)) {
@serverList.Model = spades::ui::ListViewModel(); // empty
return;
}
@ -358,25 +342,25 @@ namespace spades {
bool filterEmpty = filterEmptyButton.Toggled;
bool filterFull = filterFullButton.Toggled;
string filterText = filterField.Text;
MainScreenServerItem@[]@ list2 = array<spades::MainScreenServerItem@>();
for(int i = 0, count = list.length; i < count; i++) {
MainScreenServerItem@ item = list[i];
if(filterProtocol3 and (item.Protocol != "0.75")) {
MainScreenServerItem @[] @list2 = array<spades::MainScreenServerItem @>();
for (int i = 0, count = list.length; i < count; i++) {
MainScreenServerItem @item = list[i];
if (filterProtocol3 and(item.Protocol != "0.75")) {
continue;
}
if(filterProtocol4 and (item.Protocol != "0.76")) {
if (filterProtocol4 and(item.Protocol != "0.76")) {
continue;
}
if(filterEmpty and (item.NumPlayers > 0)) {
if (filterEmpty and(item.NumPlayers > 0)) {
continue;
}
if(filterFull and (item.NumPlayers >= item.MaxPlayers)) {
if (filterFull and(item.NumPlayers >= item.MaxPlayers)) {
continue;
}
if(filterText.length > 0) {
if(not (StringContainsCaseInsensitive(item.Name, filterText) or
StringContainsCaseInsensitive(item.MapName, filterText) or
StringContainsCaseInsensitive(item.GameMode, filterText))) {
if (filterText.length > 0) {
if (not(StringContainsCaseInsensitive(item.Name, filterText)
or StringContainsCaseInsensitive(item.MapName, filterText)
or StringContainsCaseInsensitive(item.GameMode, filterText))) {
continue;
}
}
@ -392,12 +376,13 @@ namespace spades {
}
private void CheckServerList() {
if(helper.PollServerListState()) {
MainScreenServerItem@[]@ list = helper.GetServerList("", false);
if(list is null or list.length == 0) {
if (helper.PollServerListState()) {
MainScreenServerItem @[] @list = helper.GetServerList("", false);
if (list is null or list.length == 0) {
// failed.
// FIXME: show error message?
loaded = false; loading = false;
loaded = false;
loading = false;
errorView.Visible = true;
loadingView.Visible = false;
@serverList.Model = spades::ui::ListViewModel(); // empty
@ -411,7 +396,7 @@ namespace spades {
}
}
private void OnAddressChanged(spades::ui::UIElement@ sender) {
private void OnAddressChanged(spades::ui::UIElement @sender) {
cg_lastQuickConnectHost = addressField.Text;
}
@ -421,69 +406,58 @@ namespace spades {
cg_protocolVersion = ver;
}
private void OnProtocol3Pressed(spades::ui::UIElement@ sender) {
SetProtocolVersion(3);
}
private void OnProtocol3Pressed(spades::ui::UIElement @sender) { SetProtocolVersion(3); }
private void OnProtocol4Pressed(spades::ui::UIElement@ sender) {
SetProtocolVersion(4);
}
private void OnProtocol4Pressed(spades::ui::UIElement @sender) { SetProtocolVersion(4); }
private void OnFilterProtocol3Pressed(spades::ui::UIElement@ sender) {
private void OnFilterProtocol3Pressed(spades::ui::UIElement @sender) {
filterProtocol4Button.Toggled = false;
UpdateServerList();
}
private void OnFilterProtocol4Pressed(spades::ui::UIElement@ sender) {
private void OnFilterProtocol4Pressed(spades::ui::UIElement @sender) {
filterProtocol3Button.Toggled = false;
UpdateServerList();
}
private void OnFilterFullPressed(spades::ui::UIElement@ sender) {
private void OnFilterFullPressed(spades::ui::UIElement @sender) {
filterEmptyButton.Toggled = false;
UpdateServerList();
}
private void OnFilterEmptyPressed(spades::ui::UIElement@ sender) {
private void OnFilterEmptyPressed(spades::ui::UIElement @sender) {
filterFullButton.Toggled = false;
UpdateServerList();
}
private void OnFilterTextChanged(spades::ui::UIElement@ sender) {
UpdateServerList();
}
private void OnFilterTextChanged(spades::ui::UIElement @sender) { UpdateServerList(); }
private void OnRefreshServerListPressed(spades::ui::UIElement@ sender) {
LoadServerList();
}
private void OnRefreshServerListPressed(spades::ui::UIElement @sender) { LoadServerList(); }
private void OnQuitPressed(spades::ui::UIElement@ sender) {
ui.shouldExit = true;
}
private void OnQuitPressed(spades::ui::UIElement @sender) { ui.shouldExit = true; }
private void OnCreditsPressed(spades::ui::UIElement@ sender) {
AlertScreen al(this, ui.helper.Credits, Min(500.f, Manager.Renderer.ScreenHeight - 100.f));
private void OnCreditsPressed(spades::ui::UIElement @sender) {
AlertScreen al(this, ui.helper.Credits,
Min(500.f, Manager.Renderer.ScreenHeight - 100.f));
al.Run();
}
private void OnSetupPressed(spades::ui::UIElement@ sender) {
private void OnSetupPressed(spades::ui::UIElement @sender) {
PreferenceView al(this, PreferenceViewOptions(), ui.fontManager);
al.Run();
}
private void Connect() {
string msg = helper.ConnectServer(addressField.Text, cg_protocolVersion.IntValue);
if(msg.length > 0) {
if (msg.length > 0) {
// failde to initialize client.
AlertScreen al(this, msg);
al.Run();
}
}
private void OnConnectPressed(spades::ui::UIElement@ sender) {
Connect();
}
private void OnConnectPressed(spades::ui::UIElement @sender) { Connect(); }
void HotKey(string key) {
if(IsEnabled and key == "Enter") {
if (IsEnabled and key == "Enter") {
Connect();
} else if(IsEnabled and key == "Escape") {
} else if (IsEnabled and key == "Escape") {
ui.shouldExit = true;
} else {
UIElement::HotKey(key);
@ -495,17 +469,21 @@ namespace spades {
UIElement::Render();
// check for client error message.
if(IsEnabled) {
if (IsEnabled) {
string msg = helper.GetPendingErrorMessage();
if(msg.length > 0) {
if (msg.length > 0) {
// try to maek the "disconnected" message more friendly.
if(msg.findFirst("Disconnected:") >= 0) {
if (msg.findFirst("Disconnected:") >= 0) {
int ind1 = msg.findFirst("Disconnected:");
int ind2 = msg.findFirst("\n", ind1);
if(ind2 < 0) ind2 = msg.length;
if (ind2 < 0)
ind2 = msg.length;
ind1 += "Disconnected:".length;
msg = msg.substr(ind1, ind2 - ind1);
msg = _Tr("MainScreen", "You were disconnected from the server because of the following reason:\n\n{0}", msg);
msg = _Tr(
"MainScreen",
"You were disconnected from the server because of the following reason:\n\n{0}",
msg);
}
// failed to connect.

View File

@ -24,14 +24,14 @@
namespace spades {
class MainScreenUI {
private Renderer@ renderer;
private AudioDevice@ audioDevice;
FontManager@ fontManager;
MainScreenHelper@ helper;
private Renderer @renderer;
private AudioDevice @audioDevice;
FontManager @fontManager;
MainScreenHelper @helper;
spades::ui::UIManager@ manager;
spades::ui::UIManager @manager;
MainScreenMainMenu@ mainMenu;
MainScreenMainMenu @mainMenu;
bool shouldExit = false;
@ -40,7 +40,8 @@ namespace spades {
private ConfigItem cg_playerName("cg_playerName");
private ConfigItem cg_playerNameIsSet("cg_playerNameIsSet", "0");
MainScreenUI(Renderer@ renderer, AudioDevice@ audioDevice, FontManager@ fontManager, MainScreenHelper@ helper) {
MainScreenUI(Renderer @renderer, AudioDevice @audioDevice, FontManager @fontManager,
MainScreenHelper @helper) {
@this.renderer = renderer;
@this.audioDevice = audioDevice;
@this.fontManager = fontManager;
@ -56,15 +57,13 @@ namespace spades {
manager.RootElement.AddChild(mainMenu);
// Let the new player choose their IGN
if (cg_playerName.StringValue != "" &&
cg_playerName.StringValue != "Deuce") {
if (cg_playerName.StringValue != "" && cg_playerName.StringValue != "Deuce") {
cg_playerNameIsSet.IntValue = 1;
}
if (cg_playerNameIsSet.IntValue == 0) {
CreateProfileScreen al(mainMenu);
al.Run();
}
}
void SetupRenderer() {
@ -75,43 +74,31 @@ namespace spades {
time = -1.f;
// returned from the client game, so reload the server list.
if(mainMenu !is null)
if (mainMenu !is null)
mainMenu.LoadServerList();
if(manager !is null)
if (manager !is null)
manager.KeyPanic();
}
void MouseEvent(float x, float y) {
manager.MouseEvent(x, y);
}
void MouseEvent(float x, float y) { manager.MouseEvent(x, y); }
void WheelEvent(float x, float y) {
manager.WheelEvent(x, y);
}
void WheelEvent(float x, float y) { manager.WheelEvent(x, y); }
void KeyEvent(string key, bool down) {
manager.KeyEvent(key, down);
}
void KeyEvent(string key, bool down) { manager.KeyEvent(key, down); }
void TextInputEvent(string text) {
manager.TextInputEvent(text);
}
void TextInputEvent(string text) { manager.TextInputEvent(text); }
void TextEditingEvent(string text, int start, int len) {
manager.TextEditingEvent(text, start, len);
}
bool AcceptsTextInput() {
return manager.AcceptsTextInput;
}
bool AcceptsTextInput() { return manager.AcceptsTextInput; }
AABB2 GetTextInputRect() {
return manager.TextInputRect;
}
AABB2 GetTextInputRect() { return manager.TextInputRect; }
private SceneDefinition SetupCamera(SceneDefinition sceneDef,
Vector3 eye, Vector3 at, Vector3 up, float fov) {
private SceneDefinition SetupCamera(SceneDefinition sceneDef, Vector3 eye, Vector3 at,
Vector3 up, float fov) {
Vector3 dir = (at - eye).Normalized;
Vector3 side = Cross(dir, up).Normalized;
up = -Cross(dir, side);
@ -120,12 +107,14 @@ namespace spades {
sceneDef.viewAxisY = up;
sceneDef.viewAxisZ = dir;
sceneDef.fovY = fov * 3.141592654f / 180.f;
sceneDef.fovX = atan(tan(sceneDef.fovY * 0.5f) * renderer.ScreenWidth / renderer.ScreenHeight) * 2.f;
sceneDef.fovX =
atan(tan(sceneDef.fovY * 0.5f) * renderer.ScreenWidth / renderer.ScreenHeight) *
2.f;
return sceneDef;
}
void RunFrame(float dt) {
if(time < 0.f) {
if (time < 0.f) {
time = 0.f;
}
@ -133,9 +122,9 @@ namespace spades {
float cameraX = time;
cameraX -= floor(cameraX / 512.f) * 512.f;
cameraX = 512.f - cameraX;
sceneDef = SetupCamera(sceneDef,
Vector3(cameraX, 256.f, 12.f), Vector3(cameraX + .1f, 257.f, 12.5f), Vector3(0.f, 0.f, -1.f),
30.f);
sceneDef =
SetupCamera(sceneDef, Vector3(cameraX, 256.f, 12.f),
Vector3(cameraX + .1f, 257.f, 12.5f), Vector3(0.f, 0.f, -1.f), 30.f);
sceneDef.zNear = 0.1f;
sceneDef.zFar = 222.f;
sceneDef.time = int(time * 1000.f);
@ -148,7 +137,7 @@ namespace spades {
// fade the map
float fade = Clamp((time - 1.f) / 2.2f, 0.f, 1.f);
sceneDef.globalBlur = Clamp((1.f - (time - 1.f) / 2.5f), 0.f, 1.f);
if(!mainMenu.IsEnabled) {
if (!mainMenu.IsEnabled) {
sceneDef.globalBlur = Max(sceneDef.globalBlur, 0.5f);
}
@ -156,14 +145,14 @@ namespace spades {
renderer.EndScene();
// fade the map (draw)
if(fade < 1.f) {
if (fade < 1.f) {
renderer.ColorNP = Vector4(0.f, 0.f, 0.f, 1.f - fade);
renderer.DrawImage(renderer.RegisterImage("Gfx/White.tga"),
AABB2(0.f, 0.f, renderer.ScreenWidth, renderer.ScreenHeight));
AABB2(0.f, 0.f, renderer.ScreenWidth, renderer.ScreenHeight));
}
// draw title logo
Image@ img = renderer.RegisterImage("Gfx/Title/Logo.png");
Image @img = renderer.RegisterImage("Gfx/Title/Logo.png");
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 1.f);
renderer.DrawImage(img, Vector2((renderer.ScreenWidth - img.Width) * 0.5f, 64.f));
@ -175,20 +164,16 @@ namespace spades {
time += Min(dt, 0.05f);
}
void Closing() {
shouldExit = true;
}
void Closing() { shouldExit = true; }
bool WantsToBeClosed() {
return shouldExit;
}
bool WantsToBeClosed() { return shouldExit; }
}
/**
* The entry point of the main screen.
*/
MainScreenUI@ CreateMainScreenUI(Renderer@ renderer, AudioDevice@ audioDevice,
FontManager@ fontManager, MainScreenHelper@ helper) {
MainScreenUI @CreateMainScreenUI(Renderer @renderer, AudioDevice @audioDevice,
FontManager @fontManager, MainScreenHelper @helper) {
return MainScreenUI(renderer, audioDevice, fontManager, helper);
}

View File

@ -22,29 +22,29 @@
namespace spades {
class ServerListItem: spades::ui::ButtonBase {
MainScreenServerItem@ item;
FlagIconRenderer@ flagIconRenderer;
ServerListItem(spades::ui::UIManager@ manager, MainScreenServerItem@ item){
class ServerListItem : spades::ui::ButtonBase {
MainScreenServerItem @item;
FlagIconRenderer @flagIconRenderer;
ServerListItem(spades::ui::UIManager @manager, MainScreenServerItem @item) {
super(manager);
@this.item = item;
@flagIconRenderer = FlagIconRenderer(manager.Renderer);
}
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
Image @img = renderer.RegisterImage("Gfx/White.tga");
Vector4 bgcolor = Vector4(1.f, 1.f, 1.f, 0.0f);
Vector4 fgcolor = Vector4(1.f, 1.f, 1.f, 1.f);
if(item.Favorite) {
if (item.Favorite) {
bgcolor = Vector4(0.3f, 0.3f, 1.f, 0.1f);
fgcolor = Vector4(220.f/255.f,220.f/255.f,0,1);
fgcolor = Vector4(220.f / 255.f, 220.f / 255.f, 0, 1);
}
if(Pressed && Hover) {
if (Pressed && Hover) {
bgcolor.w += 0.3;
} else if(Hover) {
} else if (Hover) {
bgcolor.w += 0.15;
}
renderer.ColorNP = bgcolor;
@ -52,125 +52,125 @@ namespace spades {
Font.Draw(item.Name, ScreenPosition + Vector2(4.f, 2.f), 1.f, fgcolor);
string playersStr = ToString(item.NumPlayers) + "/" + ToString(item.MaxPlayers);
Vector4 col(1,1,1,1);
if(item.NumPlayers >= item.MaxPlayers) col = Vector4(1,0.7f,0.7f,1);
else if(item.NumPlayers >= item.MaxPlayers * 3 / 4) col = Vector4(1,1,0.7f,1);
else if(item.NumPlayers == 0) col = Vector4(0.7f,0.7f,1,1);
Font.Draw(playersStr, ScreenPosition + Vector2(340.f-Font.Measure(playersStr).x * 0.5f, 2.f), 1.f, col);
Font.Draw(item.MapName, ScreenPosition + Vector2(400.f, 2.f), 1.f, Vector4(1,1,1,1));
Font.Draw(item.GameMode, ScreenPosition + Vector2(550.f, 2.f), 1.f, Vector4(1,1,1,1));
Font.Draw(item.Protocol, ScreenPosition + Vector2(630.f, 2.f), 1.f, Vector4(1,1,1,1));
if(not flagIconRenderer.DrawIcon(item.Country, ScreenPosition + Vector2(700.f, size.y * 0.5f))) {
Font.Draw(item.Country, ScreenPosition + Vector2(680.f, 2.f), 1.f, Vector4(1,1,1,1));
Vector4 col(1, 1, 1, 1);
if (item.NumPlayers >= item.MaxPlayers)
col = Vector4(1, 0.7f, 0.7f, 1);
else if (item.NumPlayers >= item.MaxPlayers * 3 / 4)
col = Vector4(1, 1, 0.7f, 1);
else if (item.NumPlayers == 0)
col = Vector4(0.7f, 0.7f, 1, 1);
Font.Draw(playersStr,
ScreenPosition + Vector2(340.f - Font.Measure(playersStr).x * 0.5f, 2.f), 1.f,
col);
Font.Draw(item.MapName, ScreenPosition + Vector2(400.f, 2.f), 1.f, Vector4(1, 1, 1, 1));
Font.Draw(item.GameMode, ScreenPosition + Vector2(550.f, 2.f), 1.f,
Vector4(1, 1, 1, 1));
Font.Draw(item.Protocol, ScreenPosition + Vector2(630.f, 2.f), 1.f,
Vector4(1, 1, 1, 1));
if (not flagIconRenderer.DrawIcon(item.Country,
ScreenPosition + Vector2(700.f, size.y * 0.5f))) {
Font.Draw(item.Country, ScreenPosition + Vector2(680.f, 2.f), 1.f,
Vector4(1, 1, 1, 1));
}
}
}
funcdef void ServerListItemEventHandler(ServerListModel@ sender, MainScreenServerItem@ item);
funcdef void ServerListItemEventHandler(ServerListModel @sender, MainScreenServerItem @item);
class ServerListModel: spades::ui::ListViewModel {
spades::ui::UIManager@ manager;
MainScreenServerItem@[]@ list;
class ServerListModel : spades::ui::ListViewModel {
spades::ui::UIManager @manager;
MainScreenServerItem @[] @list;
ServerListItemEventHandler@ ItemActivated;
ServerListItemEventHandler@ ItemDoubleClicked;
ServerListItemEventHandler@ ItemRightClicked;
ServerListItemEventHandler @ItemActivated;
ServerListItemEventHandler @ItemDoubleClicked;
ServerListItemEventHandler @ItemRightClicked;
ServerListModel(spades::ui::UIManager@ manager, MainScreenServerItem@[]@ list) {
ServerListModel(spades::ui::UIManager @manager, MainScreenServerItem @[] @list) {
@this.manager = manager;
@this.list = list;
}
int NumRows {
get { return int(list.length); }
}
private void OnItemClicked(spades::ui::UIElement@ sender){
ServerListItem@ item = cast<ServerListItem>(sender);
if(ItemActivated !is null) {
private void OnItemClicked(spades::ui::UIElement @sender) {
ServerListItem @item = cast<ServerListItem>(sender);
if (ItemActivated !is null) {
ItemActivated(this, item.item);
}
}
private void OnItemDoubleClicked(spades::ui::UIElement@ sender){
ServerListItem@ item = cast<ServerListItem>(sender);
if(ItemDoubleClicked !is null) {
private void OnItemDoubleClicked(spades::ui::UIElement @sender) {
ServerListItem @item = cast<ServerListItem>(sender);
if (ItemDoubleClicked !is null) {
ItemDoubleClicked(this, item.item);
}
}
private void OnItemRightClicked(spades::ui::UIElement@ sender){
ServerListItem@ item = cast<ServerListItem>(sender);
if(ItemRightClicked !is null) {
private void OnItemRightClicked(spades::ui::UIElement @sender) {
ServerListItem @item = cast<ServerListItem>(sender);
if (ItemRightClicked !is null) {
ItemRightClicked(this, item.item);
}
}
spades::ui::UIElement@ CreateElement(int row) {
spades::ui::UIElement @CreateElement(int row) {
ServerListItem i(manager, list[row]);
@i.Activated = spades::ui::EventHandler(this.OnItemClicked);
@i.DoubleClicked = spades::ui::EventHandler(this.OnItemDoubleClicked);
@i.RightClicked = spades::ui::EventHandler(this.OnItemRightClicked);
return i;
}
void RecycleElement(spades::ui::UIElement@ elem) {}
void RecycleElement(spades::ui::UIElement @elem) {}
}
class ServerListHeader: spades::ui::ButtonBase {
class ServerListHeader : spades::ui::ButtonBase {
string Text;
ServerListHeader(spades::ui::UIManager@ manager){
super(manager);
}
void OnActivated() {
ButtonBase::OnActivated();
}
ServerListHeader(spades::ui::UIManager @manager) { super(manager); }
void OnActivated() { ButtonBase::OnActivated(); }
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
if(Pressed && Hover) {
Image @img = renderer.RegisterImage("Gfx/White.tga");
if (Pressed && Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.3f);
} else if(Hover) {
} else if (Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.15f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.0f);
}
renderer.DrawImage(img, AABB2(pos.x - 2.f, pos.y, size.x, size.y));
Font.Draw(Text, ScreenPosition + Vector2(0.f, 2.f), 1.f, Vector4(1,1,1,1));
Font.Draw(Text, ScreenPosition + Vector2(0.f, 2.f), 1.f, Vector4(1, 1, 1, 1));
}
}
class MainScreenServerListLoadingView: spades::ui::UIElement {
MainScreenServerListLoadingView(spades::ui::UIManager@ manager) {
super(manager);
}
class MainScreenServerListLoadingView : spades::ui::UIElement {
MainScreenServerListLoadingView(spades::ui::UIManager @manager) { super(manager); }
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Font@ font = this.Font;
Font @font = this.Font;
string text = _Tr("MainScreen", "Loading...");
Vector2 txtSize = font.Measure(text);
Vector2 txtPos;
txtPos = pos + (size - txtSize) * 0.5f;
font.Draw(text, txtPos, 1.f, Vector4(1,1,1,0.8));
font.Draw(text, txtPos, 1.f, Vector4(1, 1, 1, 0.8));
}
}
class MainScreenServerListErrorView: spades::ui::UIElement {
MainScreenServerListErrorView(spades::ui::UIManager@ manager) {
super(manager);
}
class MainScreenServerListErrorView : spades::ui::UIElement {
MainScreenServerListErrorView(spades::ui::UIManager @manager) { super(manager); }
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Font@ font = this.Font;
Font @font = this.Font;
string text = _Tr("MainScreen", "Failed to fetch the server list.");
Vector2 txtSize = font.Measure(text);
Vector2 txtPos;
txtPos = pos + (size - txtSize) * 0.5f;
font.Draw(text, txtPos, 1.f, Vector4(1,1,1,0.8));
font.Draw(text, txtPos, 1.f, Vector4(1, 1, 1, 0.8));
}
}

View File

@ -19,143 +19,138 @@
*/
namespace spades {
class MessageBoxScreen: spades::ui::UIElement {
class MessageBoxScreen : spades::ui::UIElement {
private float contentsTop, contentsHeight;
private float contentsTop, contentsHeight;
spades::ui::EventHandler@ Closed;
int ResultIndex = -1;
spades::ui::EventHandler @Closed;
int ResultIndex = -1;
private spades::ui::UIElement@ owner;
private spades::ui::UIElement @owner;
MessageBoxScreen(spades::ui::UIElement@ owner, string text, string[]@ buttons, float height = 200.f) {
super(owner.Manager);
@this.owner = owner;
@Font = Manager.RootElement.Font;
this.Bounds = owner.Bounds;
MessageBoxScreen(spades::ui::UIElement @owner, string text, string[] @buttons,
float height = 200.f) {
super(owner.Manager);
@this.owner = owner;
@Font = Manager.RootElement.Font;
this.Bounds = owner.Bounds;
float contentsWidth = 700.f;
float contentsLeft = (Manager.Renderer.ScreenWidth - contentsWidth) * 0.5f;
contentsHeight = height;
contentsTop = (Manager.Renderer.ScreenHeight - contentsHeight) * 0.5f;
{
spades::ui::Label label(Manager);
label.BackgroundColor = Vector4(0, 0, 0, 0.4f);
label.Bounds = Bounds;
AddChild(label);
}
{
spades::ui::Label label(Manager);
label.BackgroundColor = Vector4(0, 0, 0, 0.8f);
label.Bounds = AABB2(0.f, contentsTop - 13.f, Size.x, contentsHeight + 27.f);
AddChild(label);
}
for (uint i = 0; i < buttons.length; ++i) {
spades::ui::Button button(Manager);
button.Caption = buttons[i];
button.Bounds = AABB2(
contentsLeft + contentsWidth - (150.f + 10.f) * (buttons.length - i) + 10.f,
contentsTop + contentsHeight - 30.f
, 150.f, 30.f);
float contentsWidth = 700.f;
float contentsLeft = (Manager.Renderer.ScreenWidth - contentsWidth) * 0.5f;
contentsHeight = height;
contentsTop = (Manager.Renderer.ScreenHeight - contentsHeight) * 0.5f;
{
spades::ui::Label label(Manager);
label.BackgroundColor = Vector4(0, 0, 0, 0.4f);
label.Bounds = Bounds;
AddChild(label);
}
{
spades::ui::Label label(Manager);
label.BackgroundColor = Vector4(0, 0, 0, 0.8f);
label.Bounds = AABB2(0.f, contentsTop - 13.f, Size.x, contentsHeight + 27.f);
AddChild(label);
}
for (uint i = 0; i < buttons.length; ++i) {
spades::ui::Button button(Manager);
button.Caption = buttons[i];
button.Bounds = AABB2(contentsLeft + contentsWidth -
(150.f + 10.f) * (buttons.length - i) + 10.f,
contentsTop + contentsHeight - 30.f, 150.f, 30.f);
MessageBoxScreenButtonHandler handler;
@handler.screen = this;
handler.resultIndex = int(i);
@button.Activated = spades::ui::EventHandler(handler.OnPressed);
AddChild(button);
}
{
spades::ui::TextViewer viewer(Manager);
AddChild(viewer);
viewer.Bounds = AABB2(contentsLeft, contentsTop, contentsWidth, contentsHeight - 40.f);
viewer.Text = text;
}
}
MessageBoxScreenButtonHandler handler;
@handler.screen = this;
handler.resultIndex = int(i);
@button.Activated = spades::ui::EventHandler(handler.OnPressed);
AddChild(button);
}
{
spades::ui::TextViewer viewer(Manager);
AddChild(viewer);
viewer.Bounds =
AABB2(contentsLeft, contentsTop, contentsWidth, contentsHeight - 40.f);
viewer.Text = text;
}
}
private void OnClosed() {
if(Closed !is null) {
Closed(this);
}
}
private void OnClosed() {
if (Closed !is null) {
Closed(this);
}
}
void EndDialog(int result) {
ResultIndex = result;
Close();
}
void EndDialog(int result) {
ResultIndex = result;
Close();
}
void Close() {
owner.Enable = true;
owner.Parent.RemoveChild(this);
OnClosed();
}
void Close() {
owner.Enable = true;
owner.Parent.RemoveChild(this);
OnClosed();
}
void Run() {
owner.Enable = false;
owner.Parent.AddChild(this);
}
void Run() {
owner.Enable = false;
owner.Parent.AddChild(this);
}
void Render() {
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Renderer@ r = Manager.Renderer;
Image@ img = r.RegisterImage("Gfx/White.tga");
void Render() {
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Renderer @r = Manager.Renderer;
Image @img = r.RegisterImage("Gfx/White.tga");
r.ColorNP = Vector4(1, 1, 1, 0.08f);
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop - 15.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 15.f, size.x, 1.f));
r.ColorNP = Vector4(1, 1, 1, 0.2f);
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop - 14.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 14.f, size.x, 1.f));
r.ColorNP = Vector4(1, 1, 1, 0.08f);
r.DrawImage(img, AABB2(pos.x, pos.y + contentsTop - 15.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 15.f, size.x, 1.f));
r.ColorNP = Vector4(1, 1, 1, 0.2f);
r.DrawImage(img, AABB2(pos.x, pos.y + contentsTop - 14.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + contentsTop + contentsHeight + 14.f, size.x, 1.f));
UIElement::Render();
}
UIElement::Render();
}
}
}
class MessageBoxScreenButtonHandler {
MessageBoxScreen @screen;
int resultIndex;
class MessageBoxScreenButtonHandler {
MessageBoxScreen@ screen;
int resultIndex;
void OnPressed(spades::ui::UIElement @) { screen.EndDialog(resultIndex); }
}
void OnPressed(spades::ui::UIElement@) {
screen.EndDialog(resultIndex);
}
}
class AlertScreen : MessageBoxScreen {
AlertScreen(spades::ui::UIElement @owner, string text, float height = 200.f) {
super(owner, text, array<string> = {_Tr("MessageBox", "OK")}, height);
}
class AlertScreen: MessageBoxScreen {
AlertScreen(spades::ui::UIElement@ owner, string text, float height = 200.f) {
super(owner, text, array<string> = {_Tr("MessageBox", "OK")}, height);
}
void HotKey(string key) {
if (IsEnabled and(key == "Enter" or key == "Escape")) {
EndDialog(0);
} else {
UIElement::HotKey(key);
}
}
}
void HotKey(string key) {
if(IsEnabled and (key == "Enter" or key == "Escape")) {
EndDialog(0);
} else {
UIElement::HotKey(key);
}
}
}
class ConfirmScreen : MessageBoxScreen {
ConfirmScreen(spades::ui::UIElement @owner, string text, float height = 200.f) {
super(owner, text,
array<string> = {_Tr("MessageBox", "OK"), _Tr("MessageBox", "Cancel")}, height);
}
class ConfirmScreen: MessageBoxScreen {
ConfirmScreen(spades::ui::UIElement@ owner, string text, float height = 200.f) {
super(owner, text, array<string> = {_Tr("MessageBox", "OK"), _Tr("MessageBox", "Cancel")}, height);
}
bool get_Result() { return ResultIndex == 0; }
bool get_Result() {
return ResultIndex == 0;
}
void HotKey(string key) {
if(IsEnabled and key == "Enter") {
EndDialog(0);
} else if(IsEnabled and key == "Escape") {
EndDialog(1);
} else {
UIElement::HotKey(key);
}
}
}
void HotKey(string key) {
if (IsEnabled and key == "Enter") {
EndDialog(0);
} else if (IsEnabled and key == "Escape") {
EndDialog(1);
} else {
UIElement::HotKey(key);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -24,48 +24,50 @@ namespace spades {
funcdef void HelpTextHandler(string text);
class ChainedEventHandler {
spades::ui::EventHandler@ h;
spades::ui::EventHandler@ h2;
ChainedEventHandler(spades::ui::EventHandler@ h, spades::ui::EventHandler@ h2) {
spades::ui::EventHandler @h;
spades::ui::EventHandler @h2;
ChainedEventHandler(spades::ui::EventHandler @h, spades::ui::EventHandler @h2) {
@this.h = h;
@this.h2 = h2;
}
void Handler(spades::ui::UIElement@ e) {
h(e); h2(e);
void Handler(spades::ui::UIElement @e) {
h(e);
h2(e);
}
}
class HelpHandler {
private HelpTextHandler@ handler;
private spades::ui::TextViewer@ helpView;
private HelpTextHandler @handler;
private spades::ui::TextViewer @helpView;
private string text;
HelpHandler(spades::ui::TextViewer@ helpView, string text) {
HelpHandler(spades::ui::TextViewer @helpView, string text) {
this.text = text;
@this.helpView = helpView;
}
HelpHandler(HelpTextHandler@ handler, string text) {
HelpHandler(HelpTextHandler @handler, string text) {
this.text = text;
@this.handler = handler;
}
private void OnMouseHover(spades::ui::UIElement@ elm) {
if(helpView !is null) {
private void OnMouseHover(spades::ui::UIElement @elm) {
if (helpView !is null) {
helpView.Text = text;
}
if(handler !is null) {
if (handler !is null) {
handler(text);
}
}
void Watch(spades::ui::UIElement@ elm) {
void Watch(spades::ui::UIElement @elm) {
@elm.MouseEntered = spades::ui::EventHandler(this.OnMouseHover);
}
void WatchDeep(spades::ui::UIElement@ elm) {
if(elm.MouseEntered !is null) {
ChainedEventHandler chain(elm.MouseEntered, spades::ui::EventHandler(this.OnMouseHover));
void WatchDeep(spades::ui::UIElement @elm) {
if (elm.MouseEntered !is null) {
ChainedEventHandler chain(elm.MouseEntered,
spades::ui::EventHandler(this.OnMouseHover));
@elm.MouseEntered = spades::ui::EventHandler(chain.Handler);
}else{
} else {
Watch(elm);
}
spades::ui::UIElementIterator it(elm);
while(it.MoveNext()) {
while (it.MoveNext()) {
WatchDeep(it.Current);
}
}
@ -75,53 +77,51 @@ namespace spades {
private void AddLabel(float x, float y, float h, string text) {
spades::ui::Label label(Manager);
Font@ font = ui.fontManager.GuiFont;
Font @font = ui.fontManager.GuiFont;
Vector2 siz = font.Measure(text);
label.Text = text;
label.Alignment = Vector2(0.f, 0.5f);
label.Bounds = AABB2(x, y, siz.x, h);
AddChild(label);
}
}
class StartupScreenConfigViewModel: spades::ui::ListViewModel {
spades::ui::UIElement@[] items;
spades::ui::UIElement@[]@ items2;
StartupScreenConfigViewModel() {
}
class StartupScreenConfigViewModel : spades::ui::ListViewModel {
spades::ui::UIElement @[] items;
spades::ui::UIElement @[] @items2;
StartupScreenConfigViewModel() {}
int NumRows {
get {
if(items2 !is null)
if (items2 !is null)
return int(items2.length);
return int(items.length);
}
}
void Filter(string text) {
if(text.length == 0) {
if (text.length == 0) {
@items2 = null;
return;
}
spades::ui::UIElement@[] newItems;
for(uint i = 0, count = items.length; i < count; i++) {
StartupScreenConfigItemEditor@ editor =
spades::ui::UIElement @[] newItems;
for (uint i = 0, count = items.length; i < count; i++) {
StartupScreenConfigItemEditor @editor =
cast<StartupScreenConfigItemEditor>(items[i]);
if(editor is null) continue;
if (editor is null)
continue;
string label = editor.GetLabel();
if(StringContainsCaseInsensitive(label, text)) {
if (StringContainsCaseInsensitive(label, text)) {
newItems.insertLast(items[i]);
}
}
@items2 = newItems;
}
spades::ui::UIElement@ CreateElement(int row) {
if(items2 !is null)
spades::ui::UIElement @CreateElement(int row) {
if (items2 !is null)
return items2[row];
return items[row];
}
void RecycleElement(spades::ui::UIElement@ elem) {
}
void RecycleElement(spades::ui::UIElement @elem) {}
}
interface StartupScreenGenericConfig {
@ -131,58 +131,53 @@ namespace spades {
string CheckValueCapability(string);
}
class StartupScreenConfig: StartupScreenGenericConfig {
private StartupScreenUI@ ui;
private ConfigItem@ cfg;
class StartupScreenConfig : StartupScreenGenericConfig {
private StartupScreenUI @ui;
private ConfigItem @cfg;
private string cfgName;
StartupScreenConfig(StartupScreenUI@ ui, string cfg) {
StartupScreenConfig(StartupScreenUI @ui, string cfg) {
@this.ui = ui;
@this.cfg = ConfigItem(cfg);
cfgName = cfg;
}
string GetValue() {
return cfg.StringValue;
}
void SetValue(string v) {
cfg.StringValue = v;
}
string GetValue() { return cfg.StringValue; }
void SetValue(string v) { cfg.StringValue = v; }
string CheckValueCapability(string v) {
return ui.helper.CheckConfigCapability(cfgName, v);
}
}
class StartupScreenConfigSetter {
StartupScreenGenericConfig@ c;
StartupScreenGenericConfig @c;
string value;
StartupScreenConfigSetter(StartupScreenGenericConfig@ c, string value) {
StartupScreenConfigSetter(StartupScreenGenericConfig @c, string value) {
@this.c = c;
this.value = value;
}
void Set(spades::ui::UIElement@) {
c.SetValue(this.value);
}
void Set(spades::ui::UIElement @) { c.SetValue(this.value); }
}
interface StartupScreenConfigItemEditor {
void LoadConfig();
StartupScreenGenericConfig@ GetConfig();
void SetHelpTextHandler(HelpTextHandler@);
StartupScreenGenericConfig @GetConfig();
void SetHelpTextHandler(HelpTextHandler @);
string GetLabel();
}
class StartupScreenConfigSelectItemEditor : spades::ui::UIElement,
LabelAddable,
StartupScreenConfigItemEditor,
StartupScreenConfigItemEditor {
class StartupScreenConfigSelectItemEditor: spades::ui::UIElement, LabelAddable, StartupScreenConfigItemEditor, StartupScreenConfigItemEditor {
protected StartupScreenUI@ ui;
private string[]@ descs;
private string[]@ values;
protected StartupScreenGenericConfig@ config;
protected spades::ui::RadioButton@[] buttons;
protected StartupScreenUI @ui;
private string[] @descs;
private string[] @values;
protected StartupScreenGenericConfig @config;
protected spades::ui::RadioButton @[] buttons;
private string label;
StartupScreenConfigSelectItemEditor(StartupScreenUI@ ui,
StartupScreenGenericConfig@ cfg,
string values, string descs) {
StartupScreenConfigSelectItemEditor(StartupScreenUI @ui, StartupScreenGenericConfig @cfg,
string values, string descs) {
super(ui.manager);
@this.ui = ui;
@this.descs = descs.split("|");
@ -192,19 +187,18 @@ namespace spades {
{
string desc = this.descs[0];
int idx = desc.findFirst(":");
if(idx >= 0) {
if (idx >= 0) {
desc = desc.substr(0, idx);
}
AddLabel(0, 0, 24.f, desc);
this.label = desc;
}
for(uint i = 0; i < this.values.length; i++) {
for (uint i = 0; i < this.values.length; i++) {
spades::ui::RadioButton b(Manager);
string desc = this.descs[i + 1];
int idx = desc.findFirst(":");
if(idx >= 0) {
if (idx >= 0) {
desc = desc.substr(0, idx);
}
b.Caption = desc;
@ -217,28 +211,22 @@ namespace spades {
}
}
string GetLabel() {
return label;
}
string GetLabel() { return label; }
void LoadConfig() {
string val = config.GetValue();
for(uint i = 0, count = values.length; i < count; i++) {
for (uint i = 0, count = values.length; i < count; i++) {
buttons[i].Toggled = (values[i] == val);
buttons[i].Enable = CheckValueCapability(values[i]).length == 0;
}
}
string CheckValueCapability(string v) {
return config.CheckValueCapability(v);
}
StartupScreenGenericConfig@ GetConfig() {
return config;
}
void SetHelpTextHandler(HelpTextHandler@ handler) {
for(uint i = 0, count = values.length; i < count; i++) {
string CheckValueCapability(string v) { return config.CheckValueCapability(v); }
StartupScreenGenericConfig @GetConfig() { return config; }
void SetHelpTextHandler(HelpTextHandler @handler) {
for (uint i = 0, count = values.length; i < count; i++) {
string desc = descs[i + 1];
int idx = desc.findFirst(":");
if(idx < 0) {
if (idx < 0) {
desc = descs[0];
idx = desc.findFirst(":");
}
@ -252,8 +240,8 @@ namespace spades {
Vector2 size = this.Size;
float h = 24.f;
float x = size.x;
for(uint i = buttons.length; i > 0; i--) {
spades::ui::RadioButton@ b = buttons[i - 1];
for (uint i = buttons.length; i > 0; i--) {
spades::ui::RadioButton @b = buttons[i - 1];
float w = ui.fontManager.GuiFont.Measure(b.Caption).x + 26.f;
x -= w + 2.f;
b.Bounds = AABB2(x, 0.f, w, h);
@ -261,19 +249,20 @@ namespace spades {
}
}
class StartupScreenConfigCheckItemEditor: spades::ui::UIElement, StartupScreenConfigItemEditor {
class StartupScreenConfigCheckItemEditor : spades::ui::UIElement,
StartupScreenConfigItemEditor {
protected StartupScreenUI@ ui;
protected StartupScreenUI @ui;
private string desc;
private string valueOff;
private string valueOn;
private StartupScreenGenericConfig@ config;
private spades::ui::CheckBox@ button;
private StartupScreenGenericConfig @config;
private spades::ui::CheckBox @button;
private string label;
StartupScreenConfigCheckItemEditor(StartupScreenUI@ ui,
StartupScreenGenericConfig@ cfg,
string valueOff, string valueOn, string label, string desc) {
StartupScreenConfigCheckItemEditor(StartupScreenUI @ui, StartupScreenGenericConfig @cfg,
string valueOff, string valueOn, string label,
string desc) {
super(ui.manager);
@this.ui = ui;
@config = cfg;
@ -289,25 +278,19 @@ namespace spades {
this.AddChild(b);
}
string GetLabel() {
return label;
}
string GetLabel() { return label; }
void LoadConfig() {
string val = config.GetValue();
button.Toggled = (val != valueOff);
button.Enable = CheckValueCapability(valueOn).length == 0;
}
string CheckValueCapability(string v) {
return config.CheckValueCapability(v);
}
StartupScreenGenericConfig@ GetConfig() {
return config;
}
private void StateChanged(spades::ui::UIElement@) {
string CheckValueCapability(string v) { return config.CheckValueCapability(v); }
StartupScreenGenericConfig @GetConfig() { return config; }
private void StateChanged(spades::ui::UIElement @) {
config.SetValue(button.Toggled ? valueOn : valueOff);
}
void SetHelpTextHandler(HelpTextHandler@ handler) {
void SetHelpTextHandler(HelpTextHandler @handler) {
HelpHandler(handler, desc).Watch(button);
}
@ -319,21 +302,23 @@ namespace spades {
}
}
class StartupScreenConfigSliderItemEditor: spades::ui::UIElement, StartupScreenConfigItemEditor, LabelAddable {
class StartupScreenConfigSliderItemEditor : spades::ui::UIElement,
StartupScreenConfigItemEditor,
LabelAddable {
private StartupScreenUI@ ui;
private StartupScreenUI @ui;
private string desc;
private double stepSize;
private StartupScreenGenericConfig@ config;
private spades::ui::Slider@ slider;
private spades::ui::Label@ valueLabel;
private ConfigNumberFormatter@ formatter;
private StartupScreenGenericConfig @config;
private spades::ui::Slider @slider;
private spades::ui::Label @valueLabel;
private ConfigNumberFormatter @formatter;
private string label;
StartupScreenConfigSliderItemEditor(StartupScreenUI@ ui,
StartupScreenGenericConfig@ cfg,
double minValue, double maxValue, double stepSize, string label, string desc,
ConfigNumberFormatter@ formatter) {
StartupScreenConfigSliderItemEditor(StartupScreenUI @ui, StartupScreenGenericConfig @cfg,
double minValue, double maxValue, double stepSize,
string label, string desc,
ConfigNumberFormatter @formatter) {
super(ui.manager);
@this.ui = ui;
@config = cfg;
@ -371,9 +356,7 @@ namespace spades {
valueLabel.Text = s;
}
string GetLabel() {
return label;
}
string GetLabel() { return label; }
void LoadConfig() {
string val = config.GetValue();
@ -385,11 +368,9 @@ namespace spades {
UpdateLabel();
}
string CheckValueCapability(string v) {
return ""; //FIXME: config.CheckValueCapability(v);
}
StartupScreenGenericConfig@ GetConfig() {
return config;
return ""; // FIXME: config.CheckValueCapability(v);
}
StartupScreenGenericConfig @GetConfig() { return config; }
void DoRounding() {
double v = double(slider.Value - slider.MinValue);
@ -397,12 +378,12 @@ namespace spades {
v += double(slider.MinValue);
slider.Value = v;
}
private void StateChanged(spades::ui::UIElement@) {
private void StateChanged(spades::ui::UIElement @) {
DoRounding();
config.SetValue(ToString(slider.Value));
UpdateLabel();
}
void SetHelpTextHandler(HelpTextHandler@ handler) {
void SetHelpTextHandler(HelpTextHandler @handler) {
HelpHandler(handler, desc).WatchDeep(slider);
}
@ -415,19 +396,19 @@ namespace spades {
}
}
class StartupScreenConfigFieldItemEditor : spades::ui::UIElement,
StartupScreenConfigItemEditor,
LabelAddable {
class StartupScreenConfigFieldItemEditor: spades::ui::UIElement, StartupScreenConfigItemEditor, LabelAddable {
private StartupScreenUI@ ui;
private StartupScreenUI @ui;
private string desc;
private double stepSize;
private StartupScreenGenericConfig@ config;
private spades::ui::Field@ field;
private StartupScreenGenericConfig @config;
private spades::ui::Field @field;
private string label;
StartupScreenConfigFieldItemEditor(StartupScreenUI@ ui,
StartupScreenGenericConfig@ cfg,
string label, string desc) {
StartupScreenConfigFieldItemEditor(StartupScreenUI @ui, StartupScreenGenericConfig @cfg,
string label, string desc) {
super(ui.manager);
@this.ui = ui;
@config = cfg;
@ -441,28 +422,19 @@ namespace spades {
@b.Changed = spades::ui::EventHandler(this.StateChanged);
@field = b;
this.AddChild(b);
}
string GetLabel() {
return label;
}
string GetLabel() { return label; }
void LoadConfig() {
string val = config.GetValue();
field.Text = val;
}
string CheckValueCapability(string v) {
return config.CheckValueCapability(v);
}
StartupScreenGenericConfig@ GetConfig() {
return config;
}
string CheckValueCapability(string v) { return config.CheckValueCapability(v); }
StartupScreenGenericConfig @GetConfig() { return config; }
private void StateChanged(spades::ui::UIElement@) {
config.SetValue(field.Text);
}
void SetHelpTextHandler(HelpTextHandler@ handler) {
private void StateChanged(spades::ui::UIElement @) { config.SetValue(field.Text); }
void SetHelpTextHandler(HelpTextHandler @handler) {
HelpHandler(handler, desc).WatchDeep(field);
}
@ -475,15 +447,15 @@ namespace spades {
}
// Maps multiple configs to {"0", "1", ...} or "custom"
class StartupScreenComplexConfig: StartupScreenGenericConfig {
StartupScreenConfigItemEditor@[] editors;
StartupScreenComplexConfigPreset@[] presets;
class StartupScreenComplexConfig : StartupScreenGenericConfig {
StartupScreenConfigItemEditor @[] editors;
StartupScreenComplexConfigPreset @[] presets;
void AddEditor(StartupScreenConfigItemEditor@ editor) {
void AddEditor(StartupScreenConfigItemEditor @editor) {
Assert(presets.length == 0);
editors.insertLast(editor);
}
void AddPreset(StartupScreenComplexConfigPreset@ preset) {
void AddPreset(StartupScreenComplexConfigPreset @preset) {
Assert(preset.Values.length == editors.length);
presets.insertLast(preset);
}
@ -491,42 +463,42 @@ namespace spades {
string GetValue() {
string[] values;
for(uint i = 0; i < editors.length; i++) {
for (uint i = 0; i < editors.length; i++) {
values.insertLast(editors[i].GetConfig().GetValue());
}
for(uint i = 0; i < presets.length; i++) {
string[]@ pval = presets[i].Values;
for (uint i = 0; i < presets.length; i++) {
string[] @pval = presets[i].Values;
uint j = 0;
uint jc = pval.length;
for(; j < jc; j++) {
if(values[j] != pval[j]) {
for (; j < jc; j++) {
if (values[j] != pval[j]) {
break;
}
}
if(j == jc) {
if (j == jc) {
return ToString(int(i));
}
}
return "custom";
}
void SetValue(string v) {
if(v == "custom") {
if (v == "custom") {
return;
}
uint pId = uint(ParseInt(v));
string[]@ pval = presets[pId].Values;
for(uint i = 0; i < pval.length; i++) {
string[] @pval = presets[pId].Values;
for (uint i = 0; i < pval.length; i++) {
editors[i].GetConfig().SetValue(pval[i]);
}
}
string CheckValueCapability(string v) {
if(v == "custom") {
if (v == "custom") {
return "";
}
uint pId = uint(ParseInt(v));
string[]@ pval = presets[pId].Values;
string[] @pval = presets[pId].Values;
string ret = "";
for(uint i = 0; i < pval.length; i++) {
for (uint i = 0; i < pval.length; i++) {
ret += editors[i].GetConfig().CheckValueCapability(pval[i]);
}
return ret;
@ -535,7 +507,7 @@ namespace spades {
// used for StartupScreenConfigSelectItemEditor's ctor param
string GetValuesString() {
string[] lst;
for(uint i = 0; i < presets.length; i++) {
for (uint i = 0; i < presets.length; i++) {
lst.insertLast(ToString(int(i)));
}
lst.insertLast("custom");
@ -544,7 +516,7 @@ namespace spades {
// used for StartupScreenConfigSelectItemEditor's ctor param
string GetDescriptionsString() {
string[] lst;
for(uint i = 0; i < presets.length; i++) {
for (uint i = 0; i < presets.length; i++) {
lst.insertLast(presets[i].Name);
}
lst.insertLast(_Tr("StartupScreen", "Custom"));
@ -561,88 +533,80 @@ namespace spades {
}
}
class StartupScreenConfigComplexItemEditor: StartupScreenConfigSelectItemEditor {
class StartupScreenConfigComplexItemEditor : StartupScreenConfigSelectItemEditor {
private string dlgTitle;
StartupScreenConfigComplexItemEditor(StartupScreenUI@ ui,
StartupScreenComplexConfig@ cfg,
string label, string desc) {
StartupScreenConfigComplexItemEditor(StartupScreenUI @ui, StartupScreenComplexConfig @cfg,
string label, string desc) {
super(ui, cfg, cfg.GetValuesString(),
label + ":" + desc + "|" + cfg.GetDescriptionsString());
label + ":" + desc + "|" + cfg.GetDescriptionsString());
dlgTitle = label;
@buttons[buttons.length - 1].Activated = spades::ui::EventHandler(this.CustomClicked);
}
private void CustomClicked(spades::ui::UIElement@) {
RunDialog();
}
private void CustomClicked(spades::ui::UIElement @) { RunDialog(); }
private void DialogDone(spades::ui::UIElement@) {
LoadConfig();
}
private void DialogDone(spades::ui::UIElement @) { LoadConfig(); }
private void RunDialog() {
StartupScreenComplexConfigDialog dlg(ui.manager, cast<StartupScreenComplexConfig>(config));
StartupScreenComplexConfigDialog dlg(ui.manager,
cast<StartupScreenComplexConfig>(config));
@dlg.DialogDone = spades::ui::EventHandler(this.DialogDone);
dlg.Title = dlgTitle;
dlg.RunDialog();
}
}
class StartupScreenConfigView: spades::ui::ListViewBase {
class StartupScreenConfigView : spades::ui::ListViewBase {
private StartupScreenConfigViewModel vmodel;
StartupScreenConfigView(spades::ui::UIManager@ manager) {
StartupScreenConfigView(spades::ui::UIManager @manager) {
super(manager);
this.RowHeight = 30.f;
}
void Finalize() {
@this.Model = vmodel;
}
void AddRow(spades::ui::UIElement@ elm) {
vmodel.items.insertLast(elm);
}
void Finalize() { @this.Model = vmodel; }
void AddRow(spades::ui::UIElement @elm) { vmodel.items.insertLast(elm); }
void Filter(string text) {
vmodel.Filter(text);
Reload();
}
void SetHelpTextHandler(HelpTextHandler@ handler) {
spades::ui::UIElement@[]@ elms = vmodel.items;
for(uint i = 0; i < elms.length; i++) {
StartupScreenConfigItemEditor@ item = cast<StartupScreenConfigItemEditor>(elms[i]);
if(item !is null) {
void SetHelpTextHandler(HelpTextHandler @handler) {
spades::ui::UIElement @[] @elms = vmodel.items;
for (uint i = 0; i < elms.length; i++) {
StartupScreenConfigItemEditor @item = cast<StartupScreenConfigItemEditor>(elms[i]);
if (item !is null) {
item.SetHelpTextHandler(handler);
}
}
}
void LoadConfig() {
spades::ui::UIElement@[]@ elms = vmodel.items;
for(uint i = 0; i < elms.length; i++) {
StartupScreenConfigItemEditor@ item = cast<StartupScreenConfigItemEditor>(elms[i]);
if(item !is null) {
spades::ui::UIElement @[] @elms = vmodel.items;
for (uint i = 0; i < elms.length; i++) {
StartupScreenConfigItemEditor @item = cast<StartupScreenConfigItemEditor>(elms[i]);
if (item !is null) {
item.LoadConfig();
}
}
}
}
class StartupScreenComplexConfigDialog: spades::ui::UIElement {
StartupScreenComplexConfig@ config;
class StartupScreenComplexConfigDialog : spades::ui::UIElement {
StartupScreenComplexConfig @config;
float ContentsTop = 50.f;
float ContentsHeight;
string Title;
spades::ui::TextViewer@ helpView;
StartupScreenConfigView@ configView;
spades::ui::TextViewer @helpView;
StartupScreenConfigView @configView;
spades::ui::EventHandler@ DialogDone;
spades::ui::EventHandler @DialogDone;
private spades::ui::UIElement@ oldRoot;
private spades::ui::UIElement @oldRoot;
StartupScreenComplexConfigDialog(spades::ui::UIManager@ manager,
StartupScreenComplexConfig@ config) {
StartupScreenComplexConfigDialog(spades::ui::UIManager @manager,
StartupScreenComplexConfig @config) {
super(manager);
@this.config = config;
Vector2 size = manager.RootElement.Size;
@ -651,7 +615,8 @@ namespace spades {
float mainWidth = size.x - 250.f;
{
spades::ui::TextViewer e(Manager);
e.Bounds = AABB2(mainWidth, ContentsTop + 30.f, size.x - mainWidth - 10.f, ContentsHeight - 60.f);
e.Bounds = AABB2(mainWidth, ContentsTop + 30.f, size.x - mainWidth - 10.f,
ContentsHeight - 60.f);
AddChild(e);
@helpView = e;
}
@ -659,14 +624,15 @@ namespace spades {
{
StartupScreenConfigView cfg(Manager);
StartupScreenConfigItemEditor@[]@ editors = config.editors;
StartupScreenConfigItemEditor @[] @editors = config.editors;
for(uint i = 0; i < editors.length; i++)
for (uint i = 0; i < editors.length; i++)
cfg.AddRow(cast<spades::ui::UIElement>(editors[i]));
cfg.Finalize();
cfg.SetHelpTextHandler(HelpTextHandler(this.HandleHelpText));
cfg.Bounds = AABB2(10.f, ContentsTop + 30.f, mainWidth - 20.f, ContentsHeight - 60.f);
cfg.Bounds =
AABB2(10.f, ContentsTop + 30.f, mainWidth - 20.f, ContentsHeight - 60.f);
AddChild(cfg);
@configView = cfg;
}
@ -674,15 +640,15 @@ namespace spades {
{
spades::ui::Button button(Manager);
button.Caption = _Tr("StartupScreen", "Close");
button.Bounds = AABB2(size.x - 160.f, ContentsTop + ContentsHeight - 30.f, 150.f, 30.f);
button.Bounds =
AABB2(size.x - 160.f, ContentsTop + ContentsHeight - 30.f, 150.f, 30.f);
@button.Activated = spades::ui::EventHandler(this.CloseActivated);
AddChild(button);
}
}
private void CloseActivated(spades::ui::UIElement@) {
if(oldRoot !is null) {
private void CloseActivated(spades::ui::UIElement @) {
if (oldRoot !is null) {
oldRoot.Enable = true;
@oldRoot = null;
}
@ -690,17 +656,15 @@ namespace spades {
DialogDone(this);
}
private void HandleHelpText(string s) {
helpView.Text = s;
}
private void HandleHelpText(string s) { helpView.Text = s; }
void RunDialog() {
spades::ui::UIElement@ root = Manager.RootElement;
spades::ui::UIElement @root = Manager.RootElement;
spades::ui::UIElementIterator iterator(root);
while(iterator.MoveNext()) {
spades::ui::UIElement@ e = iterator.Current;
if(e.Enable and e.Visible) {
while (iterator.MoveNext()) {
spades::ui::UIElement @e = iterator.Current;
if (e.Enable and e.Visible) {
@oldRoot = e;
e.Enable = false;
break;
@ -716,39 +680,34 @@ namespace spades {
void Render() {
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Renderer@ r = Manager.Renderer;
Image@ img = r.RegisterImage("Gfx/White.tga");
Renderer @r = Manager.Renderer;
Image @img = r.RegisterImage("Gfx/White.tga");
r.ColorNP = Vector4(0, 0, 0, 0.8f);
r.DrawImage(img,
AABB2(pos.x, pos.y, size.x, ContentsTop - 15.f));
r.DrawImage(img,
AABB2(pos.x, ContentsTop + ContentsHeight + 15.f, size.x, ContentsTop - 15.f));
r.DrawImage(img, AABB2(pos.x, pos.y, size.x, ContentsTop - 15.f));
r.DrawImage(
img, AABB2(pos.x, ContentsTop + ContentsHeight + 15.f, size.x, ContentsTop - 15.f));
r.ColorNP = Vector4(0, 0, 0, 0.95f);
r.DrawImage(img,
AABB2(pos.x, ContentsTop - 15.f, size.x, ContentsHeight + 30.f));
r.DrawImage(img, AABB2(pos.x, ContentsTop - 15.f, size.x, ContentsHeight + 30.f));
r.ColorNP = Vector4(1, 1, 1, 0.08f);
r.DrawImage(img, AABB2(pos.x, pos.y + ContentsTop - 15.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + ContentsTop - 15.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + ContentsTop + ContentsHeight + 15.f, size.x, 1.f));
AABB2(pos.x, pos.y + ContentsTop + ContentsHeight + 15.f, size.x, 1.f));
r.ColorNP = Vector4(1, 1, 1, 0.2f);
r.DrawImage(img, AABB2(pos.x, pos.y + ContentsTop - 14.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + ContentsTop - 14.f, size.x, 1.f));
r.DrawImage(img,
AABB2(pos.x, pos.y + ContentsTop + ContentsHeight + 14.f, size.x, 1.f));
AABB2(pos.x, pos.y + ContentsTop + ContentsHeight + 14.f, size.x, 1.f));
Font@ font = Font;
Font @font = Font;
r.ColorNP = Vector4(0.8f, 0.8f, 0.8f, 1.f);
r.DrawImage(img,
AABB2(pos.x, pos.y + ContentsTop, size.x, 20.f));
font.Draw(Title, Vector2(pos.x + 10.f, pos.y + ContentsTop), 1.f, Vector4(0.f, 0.f, 0.f, 1.f));
r.DrawImage(img, AABB2(pos.x, pos.y + ContentsTop, size.x, 20.f));
font.Draw(Title, Vector2(pos.x + 10.f, pos.y + ContentsTop), 1.f,
Vector4(0.f, 0.f, 0.f, 1.f));
UIElement::Render();
}
}
}

View File

@ -25,24 +25,24 @@
namespace spades {
class StartupScreenGraphicsTab: spades::ui::UIElement, LabelAddable {
StartupScreenUI@ ui;
StartupScreenHelper@ helper;
class StartupScreenGraphicsTab : spades::ui::UIElement, LabelAddable {
StartupScreenUI @ui;
StartupScreenHelper @helper;
StartupScreenGraphicsDisplayResolutionEditor@ resEdit;
StartupScreenGraphicsDisplayResolutionEditor @resEdit;
spades::ui::CheckBox@ fullscreenCheck;
spades::ui::RadioButton@ driverOpenGL;
spades::ui::RadioButton@ driverSoftware;
spades::ui::CheckBox @fullscreenCheck;
spades::ui::RadioButton @driverOpenGL;
spades::ui::RadioButton @driverSoftware;
spades::ui::TextViewer@ helpView;
StartupScreenConfigView@ configViewGL;
StartupScreenConfigView@ configViewSoftware;
spades::ui::TextViewer @helpView;
StartupScreenConfigView @configViewGL;
StartupScreenConfigView @configViewSoftware;
private ConfigItem r_renderer("r_renderer");
private ConfigItem r_fullscreen("r_fullscreen");
StartupScreenGraphicsTab(StartupScreenUI@ ui, Vector2 size) {
StartupScreenGraphicsTab(StartupScreenUI @ui, Vector2 size) {
super(ui.manager);
@this.ui = ui;
@helper = ui.helper;
@ -70,9 +70,11 @@ namespace spades {
spades::ui::CheckBox e(Manager);
e.Caption = _Tr("StartupScreen", "Fullscreen Mode");
e.Bounds = AABB2(230.f, 0.f, 200.f, 24.f);
HelpHandler(helpView,
_Tr("StartupScreen", "By running in fullscreen mode OpenSpades occupies the "
"screen, making it easier for you to concentrate on playing the game.")).Watch(e);
HelpHandler(
helpView,
_Tr("StartupScreen",
"By running in fullscreen mode OpenSpades occupies the " "screen, making it easier for you to concentrate on playing the game."))
.Watch(e);
@e.Activated = spades::ui::EventHandler(this.OnFullscreenCheck);
AddChild(e);
@fullscreenCheck = e;
@ -84,9 +86,11 @@ namespace spades {
e.Caption = _Tr("StartupScreen", "OpenGL");
e.Bounds = AABB2(100.f, 30.f, 140.f, 24.f);
e.GroupName = "driver";
HelpHandler(helpView,
_Tr("StartupScreen", "OpenGL renderer uses your computer's graphics "
"accelerator to generate the game screen.")).Watch(e);
HelpHandler(
helpView,
_Tr("StartupScreen",
"OpenGL renderer uses your computer's graphics " "accelerator to generate the game screen."))
.Watch(e);
@e.Activated = spades::ui::EventHandler(this.OnDriverOpenGL);
AddChild(e);
@driverOpenGL = e;
@ -96,10 +100,11 @@ namespace spades {
e.Caption = _Tr("StartupScreen", "Software");
e.Bounds = AABB2(250.f, 30.f, 140.f, 24.f);
e.GroupName = "driver";
HelpHandler(helpView,
_Tr("StartupScreen", "Software renderer uses CPU to generate the game "
"screen. Its quality and performance might be inferior to OpenGL "
"renderer, but it works even with an unsupported GPU.")).Watch(e);
HelpHandler(
helpView,
_Tr("StartupScreen",
"Software renderer uses CPU to generate the game " "screen. Its quality and performance might be inferior to OpenGL " "renderer, but it works even with an unsupported GPU."))
.Watch(e);
@e.Activated = spades::ui::EventHandler(this.OnDriverSoftware);
AddChild(e);
@driverSoftware = e;
@ -108,126 +113,142 @@ namespace spades {
{
StartupScreenConfigView cfg(Manager);
cfg.AddRow(StartupScreenConfigSelectItemEditor(ui,
StartupScreenGraphicsAntialiasConfig(ui), "0|2|4|fxaa",
cfg.AddRow(StartupScreenConfigSelectItemEditor(
ui, StartupScreenGraphicsAntialiasConfig(ui), "0|2|4|fxaa",
_Tr("StartupScreen",
"Antialias:Enables a technique to improve the appearance of high-contrast edges.\n\n"
"MSAA: Performs antialiasing by generating an intermediate high-resolution image. "
"Looks best, but doesn't cope with some settings.\n\n"
"FXAA: Performs antialiasing by smoothing artifacts out as a post-process.|"
"Off|MSAA 2x|4x|FXAA")));
"Antialias:Enables a technique to improve the appearance of high-contrast edges.\n\n" "MSAA: Performs antialiasing by generating an intermediate high-resolution image. " "Looks best, but doesn't cope with some settings.\n\n" "FXAA: Performs antialiasing by smoothing artifacts out as a post-process.|" "Off|MSAA 2x|4x|FXAA")));
cfg.AddRow(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_radiosity"), "0", "1", _Tr("StartupScreen", "Global Illumination"),
cfg.AddRow(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_radiosity"), "0", "1",
_Tr("StartupScreen", "Global Illumination"),
_Tr("StartupScreen",
"Enables a physically based simulation of light path for more realistic lighting.")));
"Enables a physically based simulation of light path for more realistic lighting.")));
cfg.AddRow(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_hdr"), "0", "1", _Tr("StartupScreen", "Linear HDR Rendering"),
cfg.AddRow(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_hdr"), "0", "1",
_Tr("StartupScreen", "Linear HDR Rendering"),
_Tr("StartupScreen",
"Uses a number representation which allows wider dynamic range during rendering process. "
"Additionally, this allows color calculation whose value is in linear correspondence with actual energy, "
"that is, physically accurate blending can be achieved.")));
"Uses a number representation which allows wider dynamic range during rendering process. " "Additionally, this allows color calculation whose value is in linear correspondence with actual energy, " "that is, physically accurate blending can be achieved.")));
{
StartupScreenComplexConfig cplx;
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_cameraBlur"), "0", "1", _Tr("StartupScreen", "Camera Blur"),
_Tr("StartupScreen", "Blurs the screen when you turn quickly.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_lens"), "0", "1", _Tr("StartupScreen", "Lens Effect"),
_Tr("StartupScreen", "Simulates distortion caused by a real camera lens.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_bloom"), "0", "1", _Tr("StartupScreen", "Lens Scattering Filter"),
_Tr("StartupScreen", "Simulates light being scattered by dust on the camera lens.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_cameraBlur"), "0", "1",
_Tr("StartupScreen", "Camera Blur"),
_Tr("StartupScreen", "Blurs the screen when you turn quickly.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_lens"), "0", "1",
_Tr("StartupScreen", "Lens Effect"),
_Tr("StartupScreen",
"Simulates distortion caused by a real camera lens.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_bloom"), "0", "1",
_Tr("StartupScreen", "Lens Scattering Filter"),
_Tr("StartupScreen",
"Simulates light being scattered by dust on the camera lens.")));
// r_lens is currently no-op
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_lensFlare"), "0", "1", _Tr("StartupScreen", "Lens Flare"),
_Tr("StartupScreen", "The Sun causes lens flare.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_lensFlareDynamic"), "0", "1", _Tr("StartupScreen", "Flares for Dynamic Lights"),
_Tr("StartupScreen", "Enables lens flare for light sources other than the Sun.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_colorCorrection"), "0", "1", _Tr("StartupScreen", "Color Correction"),
_Tr("StartupScreen", "Applies cinematic color correction to make the image look better.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_depthOfField"), "0", "1", _Tr("StartupScreen", "Depth of Field"),
_Tr("StartupScreen", "Blurs out-of-focus objects.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_ssao"), "0", "1", _Tr("StartupScreen", "Screen Space Ambient Occlusion"),
_Tr("StartupScreen", "Simulates soft shadows that occur between nearby objects.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_lensFlare"), "0", "1",
_Tr("StartupScreen", "Lens Flare"),
_Tr("StartupScreen", "The Sun causes lens flare.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_lensFlareDynamic"), "0", "1",
_Tr("StartupScreen", "Flares for Dynamic Lights"),
_Tr("StartupScreen",
"Enables lens flare for light sources other than the Sun.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_colorCorrection"), "0", "1",
_Tr("StartupScreen", "Color Correction"),
_Tr("StartupScreen",
"Applies cinematic color correction to make the image look better.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_depthOfField"), "0", "1",
_Tr("StartupScreen", "Depth of Field"),
_Tr("StartupScreen", "Blurs out-of-focus objects.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_ssao"), "0", "1",
_Tr("StartupScreen", "Screen Space Ambient Occlusion"),
_Tr("StartupScreen",
"Simulates soft shadows that occur between nearby objects.")));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Low"), "0|0|0|0|0|0|0|0"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Medium"), "1|0|0|1|0|1|0|0"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "High"), "1|1|1|1|1|1|1|0"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Ultra"), "1|1|1|1|1|1|1|1"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Low"),
"0|0|0|0|0|0|0|0"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Medium"),
"1|0|0|1|0|1|0|0"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "High"),
"1|1|1|1|1|1|1|0"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Ultra"),
"1|1|1|1|1|1|1|1"));
cfg.AddRow(StartupScreenConfigComplexItemEditor(ui, cplx,
_Tr("StartupScreen", "Post-process"),
_Tr("StartupScreen", "Post-process modifies the image to make it look better and "
"more realistic.")));
cfg.AddRow(StartupScreenConfigComplexItemEditor(
ui, cplx, _Tr("StartupScreen", "Post-process"),
_Tr("StartupScreen",
"Post-process modifies the image to make it look better and " "more realistic.")));
}
cfg.AddRow(StartupScreenConfigSelectItemEditor(ui,
StartupScreenConfig(ui, "r_softParticles"), "0|1|2",
cfg.AddRow(StartupScreenConfigSelectItemEditor(
ui, StartupScreenConfig(ui, "r_softParticles"), "0|1|2",
_Tr("StartupScreen",
"Particles|"
"Low:Artifact occurs when a particle intersects other objects.|"
"Medium:Particle intersects objects smoothly.|"
"High:Particle intersects objects smoothly, and some objects casts "
"their shadow to particles.")));
"Particles|" "Low:Artifact occurs when a particle intersects other objects.|" "Medium:Particle intersects objects smoothly.|" "High:Particle intersects objects smoothly, and some objects casts " "their shadow to particles.")));
{
StartupScreenComplexConfig cplx;
// r_mapSoftShadow is currently no-op
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_dlights"), "0", "1", _Tr("StartupScreen", "Dynamic Lights"),
_Tr("StartupScreen",
"Gives some objects an ability to emit light to give them "
"an energy-emitting impression.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_modelShadows"), "0", "1", _Tr("StartupScreen", "Shadows"),
_Tr("StartupScreen", "Non-static object casts a shadow.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_fogShadow"), "0", "1", _Tr("StartupScreen", "Volumetric Fog"),
_Tr("StartupScreen", "Simulates shadow being casted to the fog particles using a "
"super highly computationally demanding algorithm. ")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "r_physicalLighting"), "0", "1", _Tr("StartupScreen", "Physically Based Lighting"),
_Tr("StartupScreen", "Uses more accurate approximation techniques to decide the brightness of objects.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_dlights"), "0", "1",
_Tr("StartupScreen", "Dynamic Lights"),
_Tr("StartupScreen",
"Gives some objects an ability to emit light to give them " "an energy-emitting impression.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_modelShadows"), "0", "1",
_Tr("StartupScreen", "Shadows"),
_Tr("StartupScreen", "Non-static object casts a shadow.")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_fogShadow"), "0", "1",
_Tr("StartupScreen", "Volumetric Fog"),
_Tr("StartupScreen",
"Simulates shadow being casted to the fog particles using a " "super highly computationally demanding algorithm. ")));
cplx.AddEditor(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "r_physicalLighting"), "0", "1",
_Tr("StartupScreen", "Physically Based Lighting"),
_Tr("StartupScreen",
"Uses more accurate approximation techniques to decide the brightness of objects.")));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Low"), "1|0|0|0"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Medium"), "1|1|0|0"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "High"), "1|1|0|1"));
cplx.AddPreset(
StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Low"), "1|0|0|0"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Medium"),
"1|1|0|0"));
cplx.AddPreset(
StartupScreenComplexConfigPreset(_Tr("StartupScreen", "High"), "1|1|0|1"));
cfg.AddRow(StartupScreenConfigComplexItemEditor(ui, cplx,
_Tr("StartupScreen", "Direct Lights"),
_Tr("StartupScreen", "Controls how light encounting a material and atmosphere directly "
"affects its appearance.")));
cfg.AddRow(StartupScreenConfigComplexItemEditor(
ui, cplx, _Tr("StartupScreen", "Direct Lights"),
_Tr("StartupScreen",
"Controls how light encounting a material and atmosphere directly " "affects its appearance.")));
}
{
StartupScreenComplexConfig cplx;
cplx.AddEditor(StartupScreenConfigSelectItemEditor(ui,
StartupScreenConfig(ui, "r_water"), "0|1|2|3",
cplx.AddEditor(StartupScreenConfigSelectItemEditor(
ui, StartupScreenConfig(ui, "r_water"), "0|1|2|3",
_Tr("StartupScreen",
"Water Shader|"
"None:Water is rendered in the same way that normal blocks are done.|"
"Level 1:Refraction and the reflected Sun are simulated.|"
"Level 2:Waving water is simulated as well as reflection and refraction.|"
"Level 3:Reflections and refractions are rendered at the highest quality using screen-space techniques.")));
"Water Shader|" "None:Water is rendered in the same way that normal blocks are done.|" "Level 1:Refraction and the reflected Sun are simulated.|" "Level 2:Waving water is simulated as well as reflection and refraction.|" "Level 3:Reflections and refractions are rendered at the highest quality using screen-space techniques.")));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Low"), "0"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Med"), "1"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "High"), "2"));
cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Ultra"), "3"));
cplx.AddPreset(
StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Low"), "0"));
cplx.AddPreset(
StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Med"), "1"));
cplx.AddPreset(
StartupScreenComplexConfigPreset(_Tr("StartupScreen", "High"), "2"));
cplx.AddPreset(
StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Ultra"), "3"));
cfg.AddRow(StartupScreenConfigComplexItemEditor(ui, cplx,
_Tr("StartupScreen", "Shader Effects"), _Tr("StartupScreen", "Special effects.")));
cfg.AddRow(StartupScreenConfigComplexItemEditor(
ui, cplx, _Tr("StartupScreen", "Shader Effects"),
_Tr("StartupScreen", "Special effects.")));
}
cfg.Finalize();
cfg.SetHelpTextHandler(HelpTextHandler(this.HandleHelpText));
cfg.Bounds = AABB2(0.f, 60.f, mainWidth, size.y - 60.f);
@ -238,12 +259,10 @@ namespace spades {
{
StartupScreenConfigView cfg(Manager);
cfg.AddRow(StartupScreenConfigSelectItemEditor(ui,
StartupScreenConfig(ui, "r_swUndersampling"), "0|1|2",
cfg.AddRow(StartupScreenConfigSelectItemEditor(
ui, StartupScreenConfig(ui, "r_swUndersampling"), "0|1|2",
_Tr("StartupScreen",
"Fast Mode:Reduces the image resolution to make the rendering faster.|"
"Off|2x|4x")));
"Fast Mode:Reduces the image resolution to make the rendering faster.|" "Off|2x|4x")));
cfg.Finalize();
cfg.SetHelpTextHandler(HelpTextHandler(this.HandleHelpText));
@ -251,26 +270,30 @@ namespace spades {
AddChild(cfg);
@configViewSoftware = cfg;
}
}
private void HandleHelpText(string text) {
helpView.Text = text;
private void HandleHelpText(string text) { helpView.Text = text; }
private void OnDriverOpenGL(spades::ui::UIElement @) {
r_renderer.StringValue = "gl";
LoadConfig();
}
private void OnDriverSoftware(spades::ui::UIElement @) {
r_renderer.StringValue = "sw";
LoadConfig();
}
private void OnDriverOpenGL(spades::ui::UIElement@){ r_renderer.StringValue = "gl"; LoadConfig(); }
private void OnDriverSoftware(spades::ui::UIElement@){ r_renderer.StringValue = "sw"; LoadConfig(); }
private void OnFullscreenCheck(spades::ui::UIElement@)
{ r_fullscreen.IntValue = fullscreenCheck.Toggled ? 1 : 0; }
private void OnFullscreenCheck(spades::ui::UIElement @) {
r_fullscreen.IntValue = fullscreenCheck.Toggled ? 1 : 0;
}
void LoadConfig() {
resEdit.LoadConfig();
if(r_renderer.StringValue == "sw") {
if (r_renderer.StringValue == "sw") {
driverSoftware.Check();
configViewGL.Visible = false;
configViewSoftware.Visible = true;
}else{
} else {
driverOpenGL.Check();
configViewGL.Visible = true;
configViewSoftware.Visible = false;
@ -283,30 +306,28 @@ namespace spades {
}
}
class StartupScreenComboBoxDropdownButton: spades::ui::SimpleButton {
StartupScreenComboBoxDropdownButton(spades::ui::UIManager@ manager) {
super(manager);
}
class StartupScreenComboBoxDropdownButton : spades::ui::SimpleButton {
StartupScreenComboBoxDropdownButton(spades::ui::UIManager @manager) { super(manager); }
void Render() {
SimpleButton::Render();
Renderer@ renderer = Manager.Renderer;
Image@ image = renderer.RegisterImage("Gfx/UI/ScrollArrow.png");
Renderer @renderer = Manager.Renderer;
Image @image = renderer.RegisterImage("Gfx/UI/ScrollArrow.png");
AABB2 bnd = ScreenBounds;
Vector2 p = (bnd.min + bnd.max) * 0.5f + Vector2(-8.f, 8.f);
renderer.DrawImage(image, AABB2(p.x, p.y, 16.f, -16.f));
}
}
class StartupScreenGraphicsDisplayResolutionEditor: spades::ui::UIElement {
spades::ui::Field@ widthField;
spades::ui::Field@ heightField;
spades::ui::Button@ dropdownButton;
class StartupScreenGraphicsDisplayResolutionEditor : spades::ui::UIElement {
spades::ui::Field @widthField;
spades::ui::Field @heightField;
spades::ui::Button @dropdownButton;
private ConfigItem r_videoWidth("r_videoWidth");
private ConfigItem r_videoHeight("r_videoHeight");
StartupScreenHelper@ helper;
StartupScreenHelper @helper;
StartupScreenGraphicsDisplayResolutionEditor(StartupScreenUI@ ui) {
StartupScreenGraphicsDisplayResolutionEditor(StartupScreenUI @ui) {
super(ui.manager);
@helper = ui.helper;
{
@ -342,17 +363,16 @@ namespace spades {
void SaveConfig() {
int w = ParseInt(widthField.Text);
int h = ParseInt(heightField.Text);
if(w < 640 or h < 480 or w > 8192 or h > 8192) return;
if (w<640 or h<480 or w> 8192 or h> 8192)
return;
r_videoWidth.IntValue = w;
r_videoHeight.IntValue = h;
}
private void ValueEditHandler(spades::ui::UIElement@) {
SaveConfig();
}
private void ValueEditHandler(spades::ui::UIElement @) { SaveConfig(); }
private void DropdownHandler(int index) {
if(index >= 0) {
if (index >= 0) {
widthField.Text = ToString(helper.GetVideoModeWidth(index));
heightField.Text = ToString(helper.GetVideoModeHeight(index));
@ -360,44 +380,47 @@ namespace spades {
}
}
private void ShowDropdown(spades::ui::UIElement@) {
private void ShowDropdown(spades::ui::UIElement @) {
string[] items = {};
int cnt = helper.GetNumVideoModes();
for(int i = 0; i < cnt; i++) {
for (int i = 0; i < cnt; i++) {
int w = helper.GetVideoModeWidth(i);
int h = helper.GetVideoModeHeight(i);
string s = ToString(w) + "x" + ToString(h);
items.insertLast(s);
}
spades::ui::ShowDropDownList(this, items, spades::ui::DropDownListHandler(this.DropdownHandler));
spades::ui::ShowDropDownList(this, items,
spades::ui::DropDownListHandler(this.DropdownHandler));
}
void Render() {
Font@ font = this.Font;
Font @font = this.Font;
font.Draw("x", Vector2(45.f, 0.f) + ScreenPosition, 1.f, Vector4(1.f, 1.f, 1.f, 1.f));
UIElement::Render();
}
}
class StartupScreenGraphicsAntialiasConfig: StartupScreenGenericConfig {
private StartupScreenUI@ ui;
private ConfigItem@ msaaConfig;
private ConfigItem@ fxaaConfig;
StartupScreenGraphicsAntialiasConfig(StartupScreenUI@ ui) {
class StartupScreenGraphicsAntialiasConfig : StartupScreenGenericConfig {
private StartupScreenUI @ui;
private ConfigItem @msaaConfig;
private ConfigItem @fxaaConfig;
StartupScreenGraphicsAntialiasConfig(StartupScreenUI @ui) {
@this.ui = ui;
@msaaConfig = ConfigItem("r_multisamples");
@fxaaConfig = ConfigItem("r_fxaa");
}
string GetValue() {
if(fxaaConfig.IntValue != 0) {
if (fxaaConfig.IntValue != 0) {
return "fxaa";
}else{
} else {
int v = msaaConfig.IntValue;
if(v < 2) return "0";
else return msaaConfig.StringValue;
if (v < 2)
return "0";
else
return msaaConfig.StringValue;
}
}
void SetValue(string v) {
if(v == "fxaa") {
if (v == "fxaa") {
msaaConfig.StringValue = "0";
fxaaConfig.StringValue = "1";
} else if (v == "0" || v == "1") {
@ -409,37 +432,35 @@ namespace spades {
}
}
string CheckValueCapability(string v) {
if(v == "fxaa") {
if (v == "fxaa") {
return ui.helper.CheckConfigCapability("r_multisamples", "0") +
ui.helper.CheckConfigCapability("r_fxaa", "1");
ui.helper.CheckConfigCapability("r_fxaa", "1");
} else if (v == "0" || v == "1") {
return ui.helper.CheckConfigCapability("r_multisamples", "0") +
ui.helper.CheckConfigCapability("r_fxaa", "0");
ui.helper.CheckConfigCapability("r_fxaa", "0");
} else {
return ui.helper.CheckConfigCapability("r_multisamples", v) +
ui.helper.CheckConfigCapability("r_fxaa", "0");
ui.helper.CheckConfigCapability("r_fxaa", "0");
}
}
}
class StartupScreenAudioTab : spades::ui::UIElement, LabelAddable {
StartupScreenUI @ui;
StartupScreenHelper @helper;
class StartupScreenAudioTab: spades::ui::UIElement, LabelAddable {
StartupScreenUI@ ui;
StartupScreenHelper@ helper;
spades::ui::RadioButton @driverOpenAL;
spades::ui::RadioButton @driverYSR;
spades::ui::RadioButton @driverNull;
spades::ui::RadioButton@ driverOpenAL;
spades::ui::RadioButton@ driverYSR;
spades::ui::RadioButton@ driverNull;
spades::ui::TextViewer@ helpView;
StartupScreenConfigView@ configViewOpenAL;
StartupScreenConfigView@ configViewYSR;
spades::ui::TextViewer @helpView;
StartupScreenConfigView @configViewOpenAL;
StartupScreenConfigView @configViewYSR;
private ConfigItem s_audioDriver("s_audioDriver");
private ConfigItem s_eax("s_eax");
StartupScreenAudioTab(StartupScreenUI@ ui, Vector2 size) {
StartupScreenAudioTab(StartupScreenUI @ui, Vector2 size) {
super(ui.manager);
@this.ui = ui;
@helper = ui.helper;
@ -455,17 +476,17 @@ namespace spades {
@helpView = e;
}
AddLabel(0.f, 0.f, 24.f, _Tr("StartupScreen", "Backend"));
{
spades::ui::RadioButton e(Manager);
e.Caption = _Tr("StartupScreen", "OpenAL");
e.Bounds = AABB2(100.f, 0.f, 100.f, 24.f);
e.GroupName = "driver";
HelpHandler(helpView,
_Tr("StartupScreen", "Uses an OpenAL-capable sound card to process sound. "
"In most cases where there isn't such a sound card, software emulation is "
"used.")).Watch(e);
HelpHandler(
helpView,
_Tr("StartupScreen",
"Uses an OpenAL-capable sound card to process sound. " "In most cases where there isn't such a sound card, software emulation is " "used."))
.Watch(e);
@e.Activated = spades::ui::EventHandler(this.OnDriverOpenAL);
AddChild(e);
@driverOpenAL = e;
@ -475,11 +496,11 @@ namespace spades {
e.Caption = _Tr("StartupScreen", "YSR");
e.Bounds = AABB2(210.f, 0.f, 100.f, 24.f);
e.GroupName = "driver";
HelpHandler(helpView,
_Tr("StartupScreen", "YSR is an experimental 3D HDR sound engine optimized "
"for OpenSpades. It features several enhanced features including "
"automatic load control, dynamics compressor, HRTF-based "
"3D audio, and high quality reverb.")).Watch(e);
HelpHandler(
helpView,
_Tr("StartupScreen",
"YSR is an experimental 3D HDR sound engine optimized " "for OpenSpades. It features several enhanced features including " "automatic load control, dynamics compressor, HRTF-based " "3D audio, and high quality reverb."))
.Watch(e);
@e.Activated = spades::ui::EventHandler(this.OnDriverYSR);
AddChild(e);
@driverYSR = e;
@ -490,8 +511,7 @@ namespace spades {
e.Caption = _Tr("StartupScreen", "Null");
e.Bounds = AABB2(320.f, 0.f, 100.f, 24.f);
e.GroupName = "driver";
HelpHandler(helpView,
_Tr("StartupScreen", "Disables audio output.")).Watch(e);
HelpHandler(helpView, _Tr("StartupScreen", "Disables audio output.")).Watch(e);
@e.Activated = spades::ui::EventHandler(this.OnDriverNull);
AddChild(e);
@driverNull = e;
@ -500,19 +520,17 @@ namespace spades {
{
StartupScreenConfigView cfg(Manager);
cfg.AddRow(StartupScreenConfigSliderItemEditor(ui,
StartupScreenConfig(ui, "s_maxPolyphonics"), 16.0, 256.0, 8.0,
_Tr("StartupScreen", "Polyphonics"), _Tr("StartupScreen",
"Specifies how many sounds can be played simultaneously. "
"Higher value needs more processing power, so setting this too high might "
"cause an overload (especially with a software emulation)."),
cfg.AddRow(StartupScreenConfigSliderItemEditor(
ui, StartupScreenConfig(ui, "s_maxPolyphonics"), 16.0, 256.0, 8.0,
_Tr("StartupScreen", "Polyphonics"),
_Tr("StartupScreen",
"Specifies how many sounds can be played simultaneously. " "Higher value needs more processing power, so setting this too high might " "cause an overload (especially with a software emulation)."),
ConfigNumberFormatter(0, " poly")));
cfg.AddRow(StartupScreenConfigCheckItemEditor(ui,
StartupScreenConfig(ui, "s_eax"), "0", "1",
_Tr("StartupScreen", "EAX"), _Tr("StartupScreen",
"Enables extended features provided by the OpenAL driver to create "
"more ambience.")));
cfg.AddRow(StartupScreenConfigCheckItemEditor(
ui, StartupScreenConfig(ui, "s_eax"), "0", "1", _Tr("StartupScreen", "EAX"),
_Tr("StartupScreen",
"Enables extended features provided by the OpenAL driver to create " "more ambience.")));
cfg.Finalize();
cfg.SetHelpTextHandler(HelpTextHandler(this.HandleHelpText));
@ -524,65 +542,67 @@ namespace spades {
{
StartupScreenConfigView cfg(Manager);
cfg.AddRow(StartupScreenConfigSliderItemEditor(ui,
StartupScreenConfig(ui, "s_maxPolyphonics"), 16.0, 256.0, 8.0,
_Tr("StartupScreen", "Polyphonics"), _Tr("StartupScreen",
"Specifies how many sounds can be played simultaneously. "
"No matter what value is set, YSR might reduce the number of sounds "
"when an overload is detected."),
cfg.AddRow(StartupScreenConfigSliderItemEditor(
ui, StartupScreenConfig(ui, "s_maxPolyphonics"), 16.0, 256.0, 8.0,
_Tr("StartupScreen", "Polyphonics"),
_Tr("StartupScreen",
"Specifies how many sounds can be played simultaneously. " "No matter what value is set, YSR might reduce the number of sounds " "when an overload is detected."),
ConfigNumberFormatter(0, " poly")));
cfg.Finalize();
cfg.SetHelpTextHandler(HelpTextHandler(this.HandleHelpText));
cfg.Bounds = AABB2(0.f, 30.f, mainWidth, size.y - 30.f);
AddChild(cfg);
@configViewYSR = cfg;
}
}
private void HandleHelpText(string text) {
helpView.Text = text;
}
private void HandleHelpText(string text) { helpView.Text = text; }
private void OnDriverOpenAL(spades::ui::UIElement@){ s_audioDriver.StringValue = "openal"; LoadConfig(); }
private void OnDriverYSR(spades::ui::UIElement@){ s_audioDriver.StringValue = "ysr"; LoadConfig(); }
private void OnDriverNull(spades::ui::UIElement@){ s_audioDriver.StringValue = "null"; LoadConfig(); }
private void OnDriverOpenAL(spades::ui::UIElement @) {
s_audioDriver.StringValue = "openal";
LoadConfig();
}
private void OnDriverYSR(spades::ui::UIElement @) {
s_audioDriver.StringValue = "ysr";
LoadConfig();
}
private void OnDriverNull(spades::ui::UIElement @) {
s_audioDriver.StringValue = "null";
LoadConfig();
}
void LoadConfig() {
if(s_audioDriver.StringValue == "ysr") {
if (s_audioDriver.StringValue == "ysr") {
driverYSR.Check();
configViewOpenAL.Visible = false;
configViewYSR.Visible = true;
}else if(s_audioDriver.StringValue == "openal"){
} else if (s_audioDriver.StringValue == "openal") {
driverOpenAL.Check();
configViewOpenAL.Visible = true;
configViewYSR.Visible = false;
}else if(s_audioDriver.StringValue == "null"){
} else if (s_audioDriver.StringValue == "null") {
driverNull.Check();
configViewOpenAL.Visible = false;
configViewYSR.Visible = false;
}
driverOpenAL.Enable = ui.helper.CheckConfigCapability("s_audioDriver", "openal").length == 0;
driverOpenAL.Enable =
ui.helper.CheckConfigCapability("s_audioDriver", "openal").length == 0;
driverYSR.Enable = ui.helper.CheckConfigCapability("s_audioDriver", "ysr").length == 0;
driverNull.Enable = ui.helper.CheckConfigCapability("s_audioDriver", "null").length == 0;
driverNull.Enable =
ui.helper.CheckConfigCapability("s_audioDriver", "null").length == 0;
configViewOpenAL.LoadConfig();
configViewYSR.LoadConfig();
}
}
class StartupScreenGenericTab: spades::ui::UIElement, LabelAddable {
StartupScreenUI@ ui;
StartupScreenHelper@ helper;
class StartupScreenGenericTab : spades::ui::UIElement, LabelAddable {
StartupScreenUI @ui;
StartupScreenHelper @helper;
StartupScreenLocaleEditor@ locale;
StartupScreenLocaleEditor @locale;
StartupScreenGenericTab(StartupScreenUI@ ui, Vector2 size) {
StartupScreenGenericTab(StartupScreenUI @ui, Vector2 size) {
super(ui.manager);
@this.ui = ui;
@helper = ui.helper;
@ -623,33 +643,37 @@ namespace spades {
}
}
void LoadConfig() {
locale.LoadConfig();
}
void LoadConfig() { locale.LoadConfig(); }
private void OnBrowseUserDirectoryPressed(spades::ui::UIElement@) {
private void OnBrowseUserDirectoryPressed(spades::ui::UIElement @) {
if (helper.BrowseUserDirectory()) {
return;
}
string msg = _Tr("StartupScreen", "An unknown error has occurred while opening the config directory.");
string msg = _Tr("StartupScreen",
"An unknown error has occurred while opening the config directory.");
AlertScreen al(Parent, msg, 100.f);
al.Run();
}
private void OnResetSettingsPressed(spades::ui::UIElement@) {
string msg = _Tr("StartupScreen", "Are you sure to reset all settings? They include (but are not limited to):") + "\n" +
"- " + _Tr("StartupScreen", "All graphics/audio settings") + "\n" +
"- " + _Tr("StartupScreen", "All key bindings") + "\n" +
"- " + _Tr("StartupScreen", "Your player name") + "\n" +
"- " + _Tr("StartupScreen", "Other advanced settings only accessible through '{0}' tab and in-game commands",
private void OnResetSettingsPressed(spades::ui::UIElement @) {
string msg =
_Tr("StartupScreen",
"Are you sure to reset all settings? They include (but are not limited to):") +
"\n"
+ "- " + _Tr("StartupScreen", "All graphics/audio settings") + "\n"
+ "- " + _Tr("StartupScreen", "All key bindings") + "\n"
+ "- " + _Tr("StartupScreen", "Your player name") + "\n"
+ "- " +
_Tr("StartupScreen",
"Other advanced settings only accessible through '{0}' tab and in-game commands",
_Tr("StartupScreen", "Advanced"));
ConfirmScreen al(Parent, msg, 200.f);
@al.Closed = spades::ui::EventHandler(OnResetSettingsConfirmed);
al.Run();
}
private void OnResetSettingsConfirmed(spades::ui::UIElement@ sender) {
private void OnResetSettingsConfirmed(spades::ui::UIElement @sender) {
if (!cast<ConfirmScreen>(sender).Result) {
return;
}
@ -661,9 +685,9 @@ namespace spades {
}
private void ResetAllSettings() {
string[]@ names = GetAllConfigNames();
string[] @names = GetAllConfigNames();
for(uint i = 0, count = names.length; i < count; i++) {
for (uint i = 0, count = names.length; i < count; i++) {
ConfigItem item(names[i]);
item.StringValue = item.DefaultValue;
}
@ -671,19 +695,18 @@ namespace spades {
// Some of default values may be infeasible for the user's system.
helper.FixConfigs();
}
}
class StartupScreenDropdownListDropdownButton: spades::ui::SimpleButton {
StartupScreenDropdownListDropdownButton(spades::ui::UIManager@ manager) {
class StartupScreenDropdownListDropdownButton : spades::ui::SimpleButton {
StartupScreenDropdownListDropdownButton(spades::ui::UIManager @manager) {
super(manager);
Alignment = Vector2(0.f, 0.5f);
}
void Render() {
SimpleButton::Render();
Renderer@ renderer = Manager.Renderer;
Image@ arrowImg = renderer.RegisterImage("Gfx/UI/ScrollArrow.png");
Renderer @renderer = Manager.Renderer;
Image @arrowImg = renderer.RegisterImage("Gfx/UI/ScrollArrow.png");
AABB2 bnd = ScreenBounds;
Vector2 p = (bnd.min + bnd.max) * 0.5f + Vector2(-8.f, 8.f);
@ -691,13 +714,14 @@ namespace spades {
}
}
class StartupScreenLocaleEditor: spades::ui::UIElement, LabelAddable {StartupScreenUI@ ui;
StartupScreenHelper@ helper;
class StartupScreenLocaleEditor : spades::ui::UIElement, LabelAddable {
StartupScreenUI @ui;
StartupScreenHelper @helper;
private ConfigItem core_locale("core_locale");
spades::ui::Button@ dropdownButton;
spades::ui::Button @dropdownButton;
StartupScreenLocaleEditor(StartupScreenUI@ ui) {
StartupScreenLocaleEditor(StartupScreenUI @ui) {
super(ui.manager);
@this.ui = ui;
@helper = ui.helper;
@ -718,27 +742,30 @@ namespace spades {
}
int cnt = helper.GetNumLocales();
for(int i = 0; i < cnt; i++) {
for (int i = 0; i < cnt; i++) {
if (locale == helper.GetLocale(i)) {
name = helper.GetLocaleDescriptionNative(i) + " / " + helper.GetLocaleDescriptionEnglish(i);
name = helper.GetLocaleDescriptionNative(i) + " / " +
helper.GetLocaleDescriptionEnglish(i);
}
}
dropdownButton.Caption = name;
}
private void ShowDropdown(spades::ui::UIElement@) {
private void ShowDropdown(spades::ui::UIElement @) {
string[] items = {_Tr("StartupScreen", "System default")};
int cnt = helper.GetNumLocales();
for(int i = 0; i < cnt; i++) {
string s = helper.GetLocaleDescriptionNative(i) + " / " + helper.GetLocaleDescriptionEnglish(i);
for (int i = 0; i < cnt; i++) {
string s = helper.GetLocaleDescriptionNative(i) + " / " +
helper.GetLocaleDescriptionEnglish(i);
items.insertLast(s);
}
spades::ui::ShowDropDownList(this, items, spades::ui::DropDownListHandler(this.DropdownHandler));
spades::ui::ShowDropDownList(this, items,
spades::ui::DropDownListHandler(this.DropdownHandler));
}
private void DropdownHandler(int index) {
if(index >= 0) {
if (index >= 0) {
if (index == 0) {
core_locale = "";
} else {
@ -751,13 +778,13 @@ namespace spades {
}
}
class StartupScreenSystemInfoTab: spades::ui::UIElement, LabelAddable {
StartupScreenUI@ ui;
StartupScreenHelper@ helper;
class StartupScreenSystemInfoTab : spades::ui::UIElement, LabelAddable {
StartupScreenUI @ui;
StartupScreenHelper @helper;
spades::ui::TextViewer@ helpView;
spades::ui::TextViewer @helpView;
StartupScreenSystemInfoTab(StartupScreenUI@ ui, Vector2 size) {
StartupScreenSystemInfoTab(StartupScreenUI @ui, Vector2 size) {
super(ui.manager);
@this.ui = ui;
@helper = ui.helper;
@ -767,7 +794,7 @@ namespace spades {
e.Bounds = AABB2(0.f, 0.f, size.x, size.y - 30.f);
@e.Font = ui.fontManager.GuiFont;
AddChild(e);
for(int i = 0, count = helper.GetNumReportLines(); i < count; i++) {
for (int i = 0, count = helper.GetNumReportLines(); i < count; i++) {
string text = helper.GetReportLineText(i);
Vector4 col = helper.GetReportLineColor(i);
e.AddLine(text, true, col);
@ -782,27 +809,20 @@ namespace spades {
@button.Activated = spades::ui::EventHandler(this.OnCopyReport);
AddChild(button);
}
}
private void OnCopyReport(spades::ui::UIElement@){
Manager.Copy(helper.GetReport());
}
private void OnCopyReport(spades::ui::UIElement @) { Manager.Copy(helper.GetReport()); }
}
class StartupScreenAdvancedTab : spades::ui::UIElement, LabelAddable {
StartupScreenUI @ui;
StartupScreenHelper @helper;
class StartupScreenAdvancedTab: spades::ui::UIElement, LabelAddable {
StartupScreenUI@ ui;
StartupScreenHelper@ helper;
spades::ui::Field @filter;
spades::ui::Field@ filter;
spades::ui::TextViewer @helpView;
StartupScreenConfigView @configView;
spades::ui::TextViewer@ helpView;
StartupScreenConfigView@ configView;
StartupScreenAdvancedTab(StartupScreenUI@ ui, Vector2 size) {
StartupScreenAdvancedTab(StartupScreenUI @ui, Vector2 size) {
super(ui.manager);
@this.ui = ui;
@helper = ui.helper;
@ -819,7 +839,6 @@ namespace spades {
@helpView = e;
}
{
spades::ui::Field e(Manager);
e.Placeholder = _Tr("StartupScreen", "Filter");
@ -832,12 +851,12 @@ namespace spades {
{
StartupScreenConfigView cfg(Manager);
string[]@ names = GetAllConfigNames();
string[] @names = GetAllConfigNames();
for(uint i = 0, count = names.length; i < count; i++) {
for (uint i = 0, count = names.length; i < count; i++) {
cfg.AddRow(StartupScreenConfigFieldItemEditor(ui,
StartupScreenConfig(ui, names[i]), names[i], ""));
cfg.AddRow(StartupScreenConfigFieldItemEditor(
ui, StartupScreenConfig(ui, names[i]), names[i], ""));
}
cfg.Finalize();
@ -848,21 +867,11 @@ namespace spades {
}
}
private void HandleHelpText(string text) {
helpView.Text = text;
}
private void OnFilterChanged(spades::ui::UIElement@){
configView.Filter(filter.Text);
}
void LoadConfig() {
configView.LoadConfig();
}
private void HandleHelpText(string text) { helpView.Text = text; }
private void OnFilterChanged(spades::ui::UIElement @) { configView.Filter(filter.Text); }
void LoadConfig() { configView.LoadConfig(); }
}
}

View File

@ -27,24 +27,24 @@ namespace spades {
int ActiveTabIndex;
}
class StartupScreenMainMenu: spades::ui::UIElement {
class StartupScreenMainMenu : spades::ui::UIElement {
StartupScreenUI@ ui;
StartupScreenHelper@ helper;
StartupScreenUI @ui;
StartupScreenHelper @helper;
spades::ui::ListView@ serverList;
spades::ui::CheckBox@ bypassStartupWindowCheck;
spades::ui::ListView @serverList;
spades::ui::CheckBox @bypassStartupWindowCheck;
StartupScreenGraphicsTab@ graphicsTab;
StartupScreenAudioTab@ audioTab;
StartupScreenGenericTab@ genericTab;
StartupScreenSystemInfoTab@ systemInfoTab;
StartupScreenAdvancedTab@ advancedTab;
StartupScreenGraphicsTab @graphicsTab;
StartupScreenAudioTab @audioTab;
StartupScreenGenericTab @genericTab;
StartupScreenSystemInfoTab @systemInfoTab;
StartupScreenAdvancedTab @advancedTab;
private ConfigItem cl_showStartupWindow("cl_showStartupWindow", "-1");
private bool advancedTabVisible = false;
StartupScreenMainMenu(StartupScreenUI@ ui) {
StartupScreenMainMenu(StartupScreenUI @ui) {
super(ui.manager);
@this.ui = ui;
@this.helper = ui.helper;
@ -63,10 +63,12 @@ namespace spades {
{
spades::ui::CheckBox button(Manager);
button.Caption = _Tr("StartupScreen", "Skip this screen next time");
button.Bounds = AABB2(360.f, 62.f, width - 380.f, 20.f); // note: this is updated later soon
button.Bounds = AABB2(360.f, 62.f, width - 380.f,
20.f); // note: this is updated later soon
AddChild(button);
@bypassStartupWindowCheck = button;
@button.Activated = spades::ui::EventHandler(this.OnBypassStartupWindowCheckChanged);
@button.Activated
= spades::ui::EventHandler(this.OnBypassStartupWindowCheckChanged);
}
{
UpdateCheckView view(Manager, ui.helper.PackageUpdateManager);
@ -114,34 +116,28 @@ namespace spades {
@tabStrip.Changed = spades::ui::EventHandler(this.OnTabChanged);
// Reposition the "Skip this screen next time" check box
spades::ui::UIElement@[]@ tabStripItems = tabStrip.GetChildren();
spades::ui::UIElement @[] @tabStripItems = tabStrip.GetChildren();
float right = tabStripItems[tabStripItems.length - 1].Bounds.max.x +
tabStrip.Bounds.min.x + 10.f;
tabStrip.Bounds.min.x + 10.f;
bypassStartupWindowCheck.Bounds = AABB2(right, 62.f, width - right - 20.f, 20.f);
}
LoadConfig();
}
private void OnTabChanged(spades::ui::UIElement@) {
private void OnTabChanged(spades::ui::UIElement @) {
bool v = advancedTab.Visible;
if(advancedTabVisible and not v) {
if (advancedTabVisible and not v) {
LoadConfig();
}
advancedTabVisible = v;
}
void LoadConfig() {
switch(cl_showStartupWindow.IntValue) {
case -1:
bypassStartupWindowCheck.Toggled = false;
break;
case 0:
bypassStartupWindowCheck.Toggled = true;
break;
default:
bypassStartupWindowCheck.Toggled = false;
break;
switch (cl_showStartupWindow.IntValue) {
case -1: bypassStartupWindowCheck.Toggled = false; break;
case 0: bypassStartupWindowCheck.Toggled = true; break;
default: bypassStartupWindowCheck.Toggled = false; break;
}
this.graphicsTab.LoadConfig();
@ -150,7 +146,7 @@ namespace spades {
this.advancedTab.LoadConfig();
}
StartupScreenMainMenuState@ GetState() {
StartupScreenMainMenuState @GetState() {
StartupScreenMainMenuState state;
if (this.graphicsTab.Visible) {
state.ActiveTabIndex = 0;
@ -166,7 +162,7 @@ namespace spades {
return state;
}
void SetState(StartupScreenMainMenuState@ state) {
void SetState(StartupScreenMainMenuState @state) {
this.graphicsTab.Visible = state.ActiveTabIndex == 0;
this.audioTab.Visible = state.ActiveTabIndex == 1;
this.genericTab.Visible = state.ActiveTabIndex == 2;
@ -174,26 +170,26 @@ namespace spades {
this.advancedTab.Visible = state.ActiveTabIndex == 4;
}
private void OnBypassStartupWindowCheckChanged(spades::ui::UIElement@ sender) {
private void OnBypassStartupWindowCheckChanged(spades::ui::UIElement @sender) {
cl_showStartupWindow.IntValue = (bypassStartupWindowCheck.Toggled ? 0 : 1);
}
private void OnShowUpdateDetailsPressed(spades::ui::UIElement@ sender) {
private void OnShowUpdateDetailsPressed(spades::ui::UIElement @sender) {
if (ui.helper.OpenUpdateInfoURL()) {
return;
}
string msg = _Tr("StartupScreen", "An unknown error has occurred while opening the update info website.");
string msg =
_Tr("StartupScreen",
"An unknown error has occurred while opening the update info website.");
msg += "\n\n" + ui.helper.PackageUpdateManager.LatestVersionInfoPageURL;
AlertScreen al(Parent, msg, 100.f);
al.Run();
}
private void OnQuitPressed(spades::ui::UIElement@ sender) {
ui.shouldExit = true;
}
private void OnQuitPressed(spades::ui::UIElement @sender) { ui.shouldExit = true; }
private void OnSetupPressed(spades::ui::UIElement@ sender) {
private void OnSetupPressed(spades::ui::UIElement @sender) {
PreferenceView al(this, PreferenceViewOptions(), ui.fontManager);
al.Run();
}
@ -203,24 +199,19 @@ namespace spades {
ui.shouldExit = true; // we have to exit from the startup screen to start the game
}
private void OnStartPressed(spades::ui::UIElement@ sender) {
Start();
}
private void OnStartPressed(spades::ui::UIElement @sender) { Start(); }
void HotKey(string key) {
if(IsEnabled and key == "Enter") {
if (IsEnabled and key == "Enter") {
Start();
} else if(IsEnabled and key == "Escape") {
} else if (IsEnabled and key == "Escape") {
ui.shouldExit = true;
} else {
UIElement::HotKey(key);
}
}
void Render() {
UIElement::Render();
}
void Render() { UIElement::Render(); }
}
}

View File

@ -22,20 +22,20 @@
namespace spades {
class StartupScreenUI {
private Renderer@ renderer;
private AudioDevice@ audioDevice;
FontManager@ fontManager;
StartupScreenHelper@ helper;
private Renderer @renderer;
private AudioDevice @audioDevice;
FontManager @fontManager;
StartupScreenHelper @helper;
spades::ui::UIManager@ manager;
spades::ui::UIManager @manager;
StartupScreenMainMenu@ mainMenu;
StartupScreenMainMenu @mainMenu;
bool shouldExit = false;
StartupScreenUI(Renderer@ renderer, AudioDevice@ audioDevice, FontManager@ fontManager, StartupScreenHelper@ helper) {
StartupScreenUI(Renderer @renderer, AudioDevice @audioDevice, FontManager @fontManager,
StartupScreenHelper @helper) {
@this.renderer = renderer;
@this.audioDevice = audioDevice;
@this.fontManager = fontManager;
@ -58,52 +58,41 @@ namespace spades {
// Delete StartupScreenMainMenu
@manager.RootElement.GetChildren()[0].Parent = null;
// Reload entire the startup screen while preserving the state as much as possible
auto@ state = mainMenu.GetState();
// Reload entire the startup screen while preserving the state as much
// as possible
auto @state = mainMenu.GetState();
Init();
mainMenu.SetState(state);
}
void SetupRenderer() {
if(manager !is null)
if (manager !is null)
manager.KeyPanic();
}
void MouseEvent(float x, float y) {
manager.MouseEvent(x, y);
}
void MouseEvent(float x, float y) { manager.MouseEvent(x, y); }
void WheelEvent(float x, float y) {
manager.WheelEvent(x, y);
}
void WheelEvent(float x, float y) { manager.WheelEvent(x, y); }
void KeyEvent(string key, bool down) {
manager.KeyEvent(key, down);
}
void KeyEvent(string key, bool down) { manager.KeyEvent(key, down); }
void TextInputEvent(string text) {
manager.TextInputEvent(text);
}
void TextInputEvent(string text) { manager.TextInputEvent(text); }
void TextEditingEvent(string text, int start, int len) {
manager.TextEditingEvent(text, start, len);
}
bool AcceptsTextInput() {
return manager.AcceptsTextInput;
}
bool AcceptsTextInput() { return manager.AcceptsTextInput; }
AABB2 GetTextInputRect() {
return manager.TextInputRect;
}
AABB2 GetTextInputRect() { return manager.TextInputRect; }
void RunFrame(float dt) {
renderer.ColorNP = Vector4(0.f, 0.f, 0.f, 1.f);
renderer.DrawImage(renderer.RegisterImage("Gfx/White.tga"),
AABB2(0.f, 0.f, renderer.ScreenWidth, renderer.ScreenHeight));
AABB2(0.f, 0.f, renderer.ScreenWidth, renderer.ScreenHeight));
// draw title logo
Image@ img = renderer.RegisterImage("Gfx/Title/LogoSmall.png");
Image @img = renderer.RegisterImage("Gfx/Title/LogoSmall.png");
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 1.f);
renderer.DrawImage(img, AABB2(10.f, 10.f, img.Width, img.Height));
@ -114,17 +103,13 @@ namespace spades {
renderer.Flip();
}
void Closing() {
shouldExit = true;
}
void Closing() { shouldExit = true; }
bool WantsToBeClosed() {
return shouldExit;
}
bool WantsToBeClosed() { return shouldExit; }
}
StartupScreenUI@ CreateStartupScreenUI(Renderer@ renderer, AudioDevice@ audioDevice,
FontManager@ fontManager, StartupScreenHelper@ helper) {
StartupScreenUI @CreateStartupScreenUI(Renderer @renderer, AudioDevice @audioDevice,
FontManager @fontManager, StartupScreenHelper @helper) {
return StartupScreenUI(renderer, audioDevice, fontManager, helper);
}

View File

@ -21,17 +21,18 @@
#include "../UIFramework/UIControls.as"
namespace spades {
class UpdateCheckView: spades::ui::UIElement {
spades::ui::EventHandler@ OpenUpdateInfoURL;
class UpdateCheckView : spades::ui::UIElement {
spades::ui::EventHandler @OpenUpdateInfoURL;
private PackageUpdateManager@ packageUpdateManager;
private PackageUpdateManager @packageUpdateManager;
private spades::ui::Button@ enableCheckButton;
private spades::ui::Button@ showDetailsButton;
private spades::ui::Button @enableCheckButton;
private spades::ui::Button @showDetailsButton;
private ConfigItem cl_checkForUpdates("cl_checkForUpdates");
UpdateCheckView(spades::ui::UIManager@ manager, PackageUpdateManager@ packageUpdateManager) {
UpdateCheckView(spades::ui::UIManager @manager,
PackageUpdateManager @packageUpdateManager) {
super(manager);
@this.packageUpdateManager = packageUpdateManager;
@ -56,15 +57,15 @@ namespace spades {
float viewWidth = Size.x;
float viewHeight = Size.y;
enableCheckButton.Bounds = AABB2(
viewWidth - 160.f, (viewHeight - 30.f) * 0.5f, 150.f, 30.f);
showDetailsButton.Bounds = AABB2(
viewWidth - 160.f, (viewHeight - 30.f) * 0.5f, 150.f, 30.f);
enableCheckButton.Bounds =
AABB2(viewWidth - 160.f, (viewHeight - 30.f) * 0.5f, 150.f, 30.f);
showDetailsButton.Bounds =
AABB2(viewWidth - 160.f, (viewHeight - 30.f) * 0.5f, 150.f, 30.f);
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ white = renderer.RegisterImage("Gfx/White.tga");
Image @white = renderer.RegisterImage("Gfx/White.tga");
Vector4 background = Vector4(0.0f, 0.0f, 0.0f, 1.0f);
switch (state) {
@ -89,8 +90,8 @@ namespace spades {
float phase = fraction(Manager.Time) * 80.0f;
renderer.ColorNP = Vector4(0.15f, 0.15f, 0.15f, 1.0f);
for (float x = phase - 160.0f; x < size.x + 160.0f; x += 80.0f) {
renderer.DrawImage(white, Vector2(x, pos.y), Vector2(x + 40.f, pos.y), Vector2(x - 20.f, pos.y + size.y),
AABB2(0, 0, 0, 0));
renderer.DrawImage(white, Vector2(x, pos.y), Vector2(x + 40.f, pos.y),
Vector2(x - 20.f, pos.y + size.y), AABB2(0, 0, 0, 0));
}
}
@ -99,11 +100,14 @@ namespace spades {
switch (state) {
case PackageUpdateManagerReadyState::Loaded:
if (packageUpdateManager.UpdateAvailable) {
text = _Tr("UpdateCheck", "Version {0} is available! (You currently have {1})",
packageUpdateManager.LatestVersionInfo.Text, packageUpdateManager.CurrentVersionInfo.Text);
text =
_Tr("UpdateCheck", "Version {0} is available! (You currently have {1})",
packageUpdateManager.LatestVersionInfo.Text,
packageUpdateManager.CurrentVersionInfo.Text);
} else {
text = _Tr("UpdateCheck", "You're using the latest version of OpenSpades. ({0})",
packageUpdateManager.CurrentVersionInfo.Text);
text = _Tr("UpdateCheck",
"You're using the latest version of OpenSpades. ({0})",
packageUpdateManager.CurrentVersionInfo.Text);
}
break;
case PackageUpdateManagerReadyState::Loading:
@ -120,7 +124,7 @@ namespace spades {
break;
}
Font@ font = this.Font;
Font @font = this.Font;
Vector2 txtSize = font.Measure(text);
Vector2 txtPos = pos + (size - txtSize) * Vector2(0.0f, 0.5f) + Vector2(10.0f, 0.0f);
font.Draw(text, txtPos, 1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
@ -142,12 +146,10 @@ namespace spades {
UIElement::Render();
}
private void OnEnableCheckPressed(spades::ui::UIElement@) {
private void OnEnableCheckPressed(spades::ui::UIElement @) {
cl_checkForUpdates.IntValue = 1;
packageUpdateManager.CheckForUpdate();
}
private void OnShowDetailsPressed(spades::ui::UIElement@) {
OpenUpdateInfoURL(this);
}
private void OnShowDetailsPressed(spades::ui::UIElement @) { OpenUpdateInfoURL(this); }
}
}

View File

@ -23,7 +23,7 @@
namespace spades {
namespace ui {
class ButtonBase: UIElement {
class ButtonBase : UIElement {
bool Pressed = false;
bool Hover = false;
bool Toggled = false;
@ -32,59 +32,55 @@ namespace spades {
bool Repeat = false;
bool ActivateOnMouseDown = false;
EventHandler@ Activated;
EventHandler@ DoubleClicked;
EventHandler@ RightClicked;
EventHandler @Activated;
EventHandler @DoubleClicked;
EventHandler @RightClicked;
string Caption;
string ActivateHotKey;
private Timer@ repeatTimer;
private Timer @repeatTimer;
// for double click detection
private float lastActivate = -1.f;
private Vector2 lastActivatePosition = Vector2();
ButtonBase(UIManager@ manager) {
ButtonBase(UIManager @manager) {
super(manager);
IsMouseInteractive = true;
@repeatTimer = Timer(Manager);
@repeatTimer.Tick = TimerTickEventHandler(this.RepeatTimerFired);
}
void PlayMouseEnterSound() {
Manager.PlaySound("Sounds/Feedback/Limbo/Hover.opus");
}
void PlayMouseEnterSound() { Manager.PlaySound("Sounds/Feedback/Limbo/Hover.opus"); }
void PlayActivateSound() {
Manager.PlaySound("Sounds/Feedback/Limbo/Select.opus");
}
void PlayActivateSound() { Manager.PlaySound("Sounds/Feedback/Limbo/Select.opus"); }
void OnActivated() {
if(Activated !is null) {
if (Activated !is null) {
Activated(this);
}
}
void OnDoubleClicked() {
if(DoubleClicked !is null) {
if (DoubleClicked !is null) {
DoubleClicked(this);
}
}
void OnRightClicked() {
if(RightClicked !is null) {
if (RightClicked !is null) {
RightClicked(this);
}
}
private void RepeatTimerFired(Timer@ timer) {
private void RepeatTimerFired(Timer @timer) {
OnActivated();
timer.Interval = 0.1f;
}
void MouseDown(MouseButton button, Vector2 clientPosition) {
if(button != spades::ui::MouseButton::LeftMouseButton &&
button != spades::ui::MouseButton::RightMouseButton) {
if (button != spades::ui::MouseButton::LeftMouseButton &&
button != spades::ui::MouseButton::RightMouseButton) {
return;
}
@ -97,20 +93,20 @@ namespace spades {
Pressed = true;
Hover = true;
if(Repeat or ActivateOnMouseDown) {
if (Repeat or ActivateOnMouseDown) {
OnActivated();
if(Repeat) {
if (Repeat) {
repeatTimer.Interval = 0.3f;
repeatTimer.Start();
}
}
}
void MouseMove(Vector2 clientPosition) {
if(Pressed) {
if (Pressed) {
bool newHover = AABB2(Vector2(0.f, 0.f), Size).Contains(clientPosition);
if(newHover != Hover) {
if(Repeat) {
if(newHover) {
if (newHover != Hover) {
if (Repeat) {
if (newHover) {
OnActivated();
repeatTimer.Interval = 0.3f;
repeatTimer.Start();
@ -123,14 +119,14 @@ namespace spades {
}
}
void MouseUp(MouseButton button, Vector2 clientPosition) {
if(button != spades::ui::MouseButton::LeftMouseButton &&
button != spades::ui::MouseButton::RightMouseButton) {
if (button != spades::ui::MouseButton::LeftMouseButton &&
button != spades::ui::MouseButton::RightMouseButton) {
return;
}
if(Pressed) {
if (Pressed) {
Pressed = false;
if(Hover and not (Repeat or ActivateOnMouseDown)) {
if(Toggle) {
if (Hover and not(Repeat or ActivateOnMouseDown)) {
if (Toggle) {
Toggled = not Toggled;
}
OnActivated();
@ -142,14 +138,14 @@ namespace spades {
lastActivatePosition = clientPosition;
}
if(Repeat and Hover){
if (Repeat and Hover) {
repeatTimer.Stop();
}
}
}
void MouseEnter() {
Hover = true;
if(not Pressed) {
if (not Pressed) {
PlayMouseEnterSound();
}
UIElement::MouseEnter();
@ -160,96 +156,91 @@ namespace spades {
}
void KeyDown(string key) {
if(key == " ") {
if (key == " ") {
OnActivated();
}
UIElement::KeyDown(key);
}
void KeyUp(string key) {
UIElement::KeyUp(key);
}
void KeyUp(string key) { UIElement::KeyUp(key); }
void HotKey(string key) {
if(key == ActivateHotKey) {
if (key == ActivateHotKey) {
OnActivated();
}
}
}
class SimpleButton: spades::ui::Button {
SimpleButton(spades::ui::UIManager@ manager){
super(manager);
}
class SimpleButton : spades::ui::Button {
SimpleButton(spades::ui::UIManager @manager) { super(manager); }
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
if((Pressed && Hover) || Toggled) {
Image @img = renderer.RegisterImage("Gfx/White.tga");
if ((Pressed && Hover) || Toggled) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.2f);
} else if(Hover) {
} else if (Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.12f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.07f);
}
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, size.y));
if((Pressed && Hover) || Toggled) {
if ((Pressed && Hover) || Toggled) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.1f);
} else if(Hover) {
} else if (Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.07f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.03f);
}
renderer.DrawImage(img, AABB2(pos.x, pos.y, 1.f, size.y));
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, 1.f));
renderer.DrawImage(img, AABB2(pos.x+size.x-1.f, pos.y, 1.f, size.y));
renderer.DrawImage(img, AABB2(pos.x, pos.y+size.y-1.f, size.x, 1.f));
renderer.DrawImage(img, AABB2(pos.x + size.x - 1.f, pos.y, 1.f, size.y));
renderer.DrawImage(img, AABB2(pos.x, pos.y + size.y - 1.f, size.x, 1.f));
Vector2 txtSize = Font.Measure(Caption);
float margin = 4.f;
Font.DrawShadow(Caption, pos + Vector2(margin, margin) +
(size - txtSize - Vector2(margin * 2.f, margin * 2.f)) * Alignment,
1.f, Vector4(1,1,1,1), Vector4(0,0,0,0.4f));
Font.DrawShadow(Caption,
pos + Vector2(margin, margin) +
(size - txtSize - Vector2(margin * 2.f, margin * 2.f)) *
Alignment,
1.f, Vector4(1, 1, 1, 1), Vector4(0, 0, 0, 0.4f));
}
}
class CheckBox: spades::ui::Button {
CheckBox(spades::ui::UIManager@ manager){
class CheckBox : spades::ui::Button {
CheckBox(spades::ui::UIManager @manager) {
super(manager);
this.Toggle = true;
}
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
if(Pressed && Hover) {
Image @img = renderer.RegisterImage("Gfx/White.tga");
if (Pressed && Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.2f);
} else if(Hover) {
} else if (Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.12f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.00f);
}
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, size.y));
Vector2 txtSize = Font.Measure(Caption);
Font.DrawShadow(Caption, pos + (size - txtSize) * Vector2(0.f, 0.5f) + Vector2(16.f, 0.f),
1.f, Vector4(1,1,1,1), Vector4(0,0,0,0.2f));
Font.DrawShadow(Caption,
pos + (size - txtSize) * Vector2(0.f, 0.5f) + Vector2(16.f, 0.f),
1.f, Vector4(1, 1, 1, 1), Vector4(0, 0, 0, 0.2f));
@img = renderer.RegisterImage("Gfx/UI/CheckBox.png");
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, Toggled ? .9f : 0.6f);
renderer.DrawImage(img, AABB2(pos.x, pos.y + (size.y - 16.f) * 0.5f, 16.f, 16.f),
AABB2(Toggled ? 16.f : 0.f, 0.f, 16.f, 16.f));
AABB2(Toggled ? 16.f : 0.f, 0.f, 16.f, 16.f));
}
}
class RadioButton: spades::ui::Button {
class RadioButton : spades::ui::Button {
string GroupName;
RadioButton(spades::ui::UIManager@ manager){
RadioButton(spades::ui::UIManager @manager) {
super(manager);
this.Toggle = true;
}
@ -257,13 +248,14 @@ namespace spades {
this.Toggled = true;
// uncheck others
if(GroupName.length > 0) {
UIElement@[]@ children = this.Parent.GetChildren();
for(uint i = 0, count = children.length; i < children.length; i++) {
RadioButton@ btn = cast<RadioButton>(children[i]);
if(btn is this) continue;
if(btn !is null) {
if(GroupName == btn.GroupName) {
if (GroupName.length > 0) {
UIElement @[] @children = this.Parent.GetChildren();
for (uint i = 0, count = children.length; i < children.length; i++) {
RadioButton @btn = cast<RadioButton>(children[i]);
if (btn is this)
continue;
if (btn !is null) {
if (GroupName == btn.GroupName) {
btn.Toggled = false;
}
}
@ -276,76 +268,76 @@ namespace spades {
Button::OnActivated();
}
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
if(!this.Enable) {
Image @img = renderer.RegisterImage("Gfx/White.tga");
if (!this.Enable) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.07f);
} else if((Pressed && Hover) || Toggled) {
} else if ((Pressed && Hover) || Toggled) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.2f);
} else if(Hover) {
} else if (Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.12f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.07f);
}
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, size.y));
if(!this.Enable) {
if (!this.Enable) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.03f);
} if((Pressed && Hover) || Toggled) {
}
if ((Pressed && Hover) || Toggled) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.1f);
} else if(Hover) {
} else if (Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.07f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.03f);
}
renderer.DrawImage(img, AABB2(pos.x, pos.y, 1.f, size.y));
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, 1.f));
renderer.DrawImage(img, AABB2(pos.x+size.x-1.f, pos.y, 1.f, size.y));
renderer.DrawImage(img, AABB2(pos.x, pos.y+size.y-1.f, size.x, 1.f));
renderer.DrawImage(img, AABB2(pos.x + size.x - 1.f, pos.y, 1.f, size.y));
renderer.DrawImage(img, AABB2(pos.x, pos.y + size.y - 1.f, size.x, 1.f));
Vector2 txtSize = Font.Measure(Caption);
Font.DrawShadow(Caption, pos + (size - txtSize) * 0.5f + Vector2(8.f, 0.f), 1.f,
Vector4(1,1,1,this.Enable ? 1.f : 0.4f), Vector4(0,0,0,0.4f));
Vector4(1, 1, 1, this.Enable ? 1.f : 0.4f), Vector4(0, 0, 0, 0.4f));
if(Toggled) {
if (Toggled) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.6f);
renderer.DrawImage(img, AABB2(pos.x + 4.f, pos.y + (size.y - 8.f) * 0.5f, 8.f, 8.f));
renderer.DrawImage(img,
AABB2(pos.x + 4.f, pos.y + (size.y - 8.f) * 0.5f, 8.f, 8.f));
}
}
}
class Button: ButtonBase {
private Image@ image;
class Button : ButtonBase {
private Image @image;
Vector2 Alignment = Vector2(0.5f, 0.5f);
Button(UIManager@ manager) {
Button(UIManager @manager) {
super(manager);
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
@image = renderer.RegisterImage("Gfx/UI/Button.png");
}
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Vector4 color = Vector4(0.2f, 0.2f, 0.2f, 0.5f);
if(Toggled or (Pressed and Hover)) {
if (Toggled or(Pressed and Hover)) {
color = Vector4(0.7f, 0.7f, 0.7f, 0.9f);
}else if(Hover) {
} else if (Hover) {
color = Vector4(0.4f, 0.4f, 0.4f, 0.7f);
}
if(!IsEnabled) {
if (!IsEnabled) {
color.w *= 0.5f;
}
renderer.ColorNP = color;
DrawSliceImage(renderer, image, pos.x, pos.y, size.x, size.y, 12.f);
Font@ font = this.Font;
Font @font = this.Font;
string text = this.Caption;
Vector2 txtSize = font.Measure(text);
Vector2 txtPos;
@ -353,15 +345,14 @@ namespace spades {
size -= Vector2(16.f, 16.f);
txtPos = pos + (size - txtSize) * Alignment;
if(IsEnabled){
font.DrawShadow(text, txtPos, 1.f,
Vector4(1.f, 1.f, 1.f, 1.f), Vector4(0.f, 0.f, 0.f, 0.4f));
}else{
font.DrawShadow(text, txtPos, 1.f,
Vector4(1.f, 1.f, 1.f, 0.5f), Vector4(0.f, 0.f, 0.f, 0.1f));
if (IsEnabled) {
font.DrawShadow(text, txtPos, 1.f, Vector4(1.f, 1.f, 1.f, 1.f),
Vector4(0.f, 0.f, 0.f, 0.4f));
} else {
font.DrawShadow(text, txtPos, 1.f, Vector4(1.f, 1.f, 1.f, 0.5f),
Vector4(0.f, 0.f, 0.f, 0.1f));
}
}
}
}

View File

@ -1,174 +1,167 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
namespace ui {
class DropDownViewItem: spades::ui::Button {
int index;
DropDownViewItem(spades::ui::UIManager@ manager){
super(manager);
}
void Render() {
Renderer@ renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
if(Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.12f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.00f);
}
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, size.y));
if(Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.07f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.00f);
}
renderer.DrawImage(img, AABB2(pos.x, pos.y, 1.f, size.y));
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, 1.f));
renderer.DrawImage(img, AABB2(pos.x+size.x-1.f, pos.y, 1.f, size.y));
renderer.DrawImage(img, AABB2(pos.x, pos.y+size.y-1.f, size.x, 1.f));
Vector2 txtSize = Font.Measure(Caption);
Font.DrawShadow(Caption, pos + (size - txtSize) * Vector2(0.f, 0.5f) +
Vector2(4.f, 0.f), 1.f, Vector4(1,1,1,1), Vector4(0,0,0,0.4f));
}
}
class DropDownViewModel: spades::ui::ListViewModel {
spades::ui::UIManager@ manager;
string[]@ list;
DropDownListHandler@ Handler;
DropDownViewModel(spades::ui::UIManager@ manager, string[]@ list) {
@this.manager = manager;
@this.list = list;
}
int NumRows {
get { return int(list.length); }
}
private void ItemClicked(spades::ui::UIElement@ sender){
Handler(cast<DropDownViewItem>(sender).index);
}
spades::ui::UIElement@ CreateElement(int row) {
DropDownViewItem i(manager);
i.Caption = list[row];
i.index = row;
@i.Activated = spades::ui::EventHandler(this.ItemClicked);
return i;
}
void RecycleElement(spades::ui::UIElement@ elem) {}
}
class DropDownBackground: UIElement {
DropDownView@ view;
UIElement@ oldRoot;
DropDownBackground(UIManager@ manager, DropDownView@ view) {
super(manager);
IsMouseInteractive = true;
@this.view = view;
}
void Destroy() {
@Parent = null;
if(oldRoot !is null) {
oldRoot.Enable = true;
}
}
void MouseDown(MouseButton button, Vector2 clientPosition) {
view.Destroy();
view.handler(-1);
}
void Render() {
Renderer@ renderer = Manager.Renderer;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
renderer.ColorNP = Vector4(0.f, 0.f, 0.f, 0.5f);
renderer.DrawImage(img, ScreenBounds);
UIElement::Render();
}
}
class DropDownView: ListView {
DropDownListHandler@ handler;
DropDownBackground@ bg;
DropDownView(UIManager@ manager,
DropDownListHandler@ handler,
string[]@ items) {
super(manager);
@this.handler = handler;
DropDownViewModel model(manager, items);
@model.Handler = DropDownListHandler(this.ItemActivated);
@this.Model = model;
}
void Destroy() {
bg.Destroy();
}
private void ItemActivated(int index) {
Destroy();
handler(index);
}
}
funcdef void DropDownListHandler(int index);
void ShowDropDownList(UIManager@ manager, float x, float y, float width,
string[]@ items, DropDownListHandler@ handler) {
DropDownView view(manager, handler, items);
DropDownBackground bg(manager, view);
@view.bg = bg;
UIElement@ root = manager.RootElement;
Vector2 size = root.Size;
float maxHeight = size.y - y;
float height = 24.f * float(items.length);
if(height > maxHeight) height = maxHeight;
bg.Bounds = AABB2(0.f, 0.f, size.x, size.y);
view.Bounds = AABB2(x, y, width, height);
UIElement@[]@ roots = root.GetChildren();
/*for(uint i = 0; i < roots.length; i++) {
UIElement@ r = roots[i];
if(r.Enable) {
@bg.oldRoot = r;
r.Enable = false;
break;
}
}*/
root.AddChild(bg);
bg.AddChild(view);
}
void ShowDropDownList(UIElement@ e,
string[]@ items, DropDownListHandler@ handler) {
AABB2 b = e.ScreenBounds;
ShowDropDownList(e.Manager, b.min.x, b.max.y, b.max.x - b.min.x,
items, handler);
}
}
namespace ui {
class DropDownViewItem : spades::ui::Button {
int index;
DropDownViewItem(spades::ui::UIManager @manager) { super(manager); }
void Render() {
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image @img = renderer.RegisterImage("Gfx/White.tga");
if (Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.12f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.00f);
}
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, size.y));
if (Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.07f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.00f);
}
renderer.DrawImage(img, AABB2(pos.x, pos.y, 1.f, size.y));
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, 1.f));
renderer.DrawImage(img, AABB2(pos.x + size.x - 1.f, pos.y, 1.f, size.y));
renderer.DrawImage(img, AABB2(pos.x, pos.y + size.y - 1.f, size.x, 1.f));
Vector2 txtSize = Font.Measure(Caption);
Font.DrawShadow(Caption,
pos + (size - txtSize) * Vector2(0.f, 0.5f) + Vector2(4.f, 0.f),
1.f, Vector4(1, 1, 1, 1), Vector4(0, 0, 0, 0.4f));
}
}
class DropDownViewModel : spades::ui::ListViewModel {
spades::ui::UIManager @manager;
string[] @list;
DropDownListHandler @Handler;
DropDownViewModel(spades::ui::UIManager @manager, string[] @list) {
@this.manager = manager;
@this.list = list;
}
int NumRows {
get { return int(list.length); }
}
private void ItemClicked(spades::ui::UIElement @sender) {
Handler(cast<DropDownViewItem>(sender).index);
}
spades::ui::UIElement @CreateElement(int row) {
DropDownViewItem i(manager);
i.Caption = list[row];
i.index = row;
@i.Activated = spades::ui::EventHandler(this.ItemClicked);
return i;
}
void RecycleElement(spades::ui::UIElement @elem) {}
}
class DropDownBackground : UIElement {
DropDownView @view;
UIElement @oldRoot;
DropDownBackground(UIManager @manager, DropDownView @view) {
super(manager);
IsMouseInteractive = true;
@this.view = view;
}
void Destroy() {
@Parent = null;
if (oldRoot !is null) {
oldRoot.Enable = true;
}
}
void MouseDown(MouseButton button, Vector2 clientPosition) {
view.Destroy();
view.handler(-1);
}
void Render() {
Renderer @renderer = Manager.Renderer;
Image @img = renderer.RegisterImage("Gfx/White.tga");
renderer.ColorNP = Vector4(0.f, 0.f, 0.f, 0.5f);
renderer.DrawImage(img, ScreenBounds);
UIElement::Render();
}
}
class DropDownView : ListView {
DropDownListHandler @handler;
DropDownBackground @bg;
DropDownView(UIManager @manager, DropDownListHandler @handler, string[] @items) {
super(manager);
@this.handler = handler;
DropDownViewModel model(manager, items);
@model.Handler = DropDownListHandler(this.ItemActivated);
@this.Model = model;
}
void Destroy() { bg.Destroy(); }
private void ItemActivated(int index) {
Destroy();
handler(index);
}
}
funcdef void DropDownListHandler(int index);
void ShowDropDownList(UIManager @manager, float x, float y, float width, string[] @items,
DropDownListHandler @handler) {
DropDownView view(manager, handler, items);
DropDownBackground bg(manager, view);
@view.bg = bg;
UIElement @root = manager.RootElement;
Vector2 size = root.Size;
float maxHeight = size.y - y;
float height = 24.f * float(items.length);
if (height > maxHeight)
height = maxHeight;
bg.Bounds = AABB2(0.f, 0.f, size.x, size.y);
view.Bounds = AABB2(x, y, width, height);
UIElement @[] @roots = root.GetChildren();
/*for(uint i = 0; i < roots.length; i++) {
UIElement@ r = roots[i];
if(r.Enable) {
@bg.oldRoot = r;
r.Enable = false;
break;
}
}*/
root.AddChild(bg);
bg.AddChild(view);
}
void ShowDropDownList(UIElement @e, string[] @items, DropDownListHandler @handler) {
AABB2 b = e.ScreenBounds;
ShowDropDownList(e.Manager, b.min.x, b.max.y, b.max.x - b.min.x, items, handler);
}
}
}

View File

@ -29,9 +29,9 @@ namespace spades {
string newString;
}
class FieldBase: UIElement {
class FieldBase : UIElement {
bool Dragging = false;
EventHandler@ Changed;
EventHandler @Changed;
string Placeholder;
int MarkPosition = 0;
int CursorPosition = 0;
@ -39,7 +39,7 @@ namespace spades {
bool DenyNonAscii = false;
private string text;
private FieldCommand@[] history;
private FieldCommand @[] history;
private int historyPos = 0; // index to insert next command
Vector4 TextColor = Vector4(1.f, 1.f, 1.f, 1.f);
@ -50,11 +50,13 @@ namespace spades {
Vector2 TextOrigin = Vector2(0.f, 0.f);
float TextScale = 1.f;
FieldBase(UIManager@ manager) {
FieldBase(UIManager @manager) {
super(manager);
IsMouseInteractive = true;
AcceptsFocus = true;
@this.Cursor = Cursor(Manager, manager.Renderer.RegisterImage("Gfx/UI/IBeam.png"), Vector2(16.f, 16.f));
@this.Cursor
= Cursor(Manager, manager.Renderer.RegisterImage("Gfx/UI/IBeam.png"),
Vector2(16.f, 16.f));
}
string Text {
@ -62,7 +64,7 @@ namespace spades {
set {
text = value;
EraseUndoHistory();
}
}
}
private void EraseUndoHistory() {
@ -71,10 +73,10 @@ namespace spades {
}
private bool CheckCharType(string s) {
if(DenyNonAscii) {
for(uint i = 0, len = s.length; i < len; i++) {
if (DenyNonAscii) {
for (uint i = 0, len = s.length; i < len; i++) {
int c = s[i];
if((c & 0x80) != 0) {
if ((c & 0x80) != 0) {
return false;
}
}
@ -83,84 +85,71 @@ namespace spades {
}
void OnChanged() {
if(Changed !is null) {
if (Changed !is null) {
Changed(this);
}
}
int SelectionStart {
get final { return Min(MarkPosition, CursorPosition); }
set {
Select(value, SelectionEnd - value);
}
set { Select(value, SelectionEnd - value); }
}
int SelectionEnd {
get final {
return Max(MarkPosition, CursorPosition);
}
set {
Select(SelectionStart, value - SelectionStart);
}
get final { return Max(MarkPosition, CursorPosition); }
set { Select(SelectionStart, value - SelectionStart); }
}
int SelectionLength {
get final {
return SelectionEnd - SelectionStart;
}
set {
Select(SelectionStart, value);
}
get final { return SelectionEnd - SelectionStart; }
set { Select(SelectionStart, value); }
}
string SelectedText {
get final {
return Text.substr(SelectionStart, SelectionLength);
}
get final { return Text.substr(SelectionStart, SelectionLength); }
set {
if(!CheckCharType(value)) {
if (!CheckCharType(value)) {
return;
}
FieldCommand cmd;
cmd.oldString = this.SelectedText;
if(cmd.oldString == value) return; // no change
if (cmd.oldString == value)
return; // no change
cmd.newString = value;
cmd.index = this.SelectionStart;
RunFieldCommand(cmd, true, true);
}
}
private void RunFieldCommand(FieldCommand@ cmd, bool autoSelect, bool addHistory) {
private void RunFieldCommand(FieldCommand @cmd, bool autoSelect, bool addHistory) {
text = text.substr(0, cmd.index) + cmd.newString +
text.substr(cmd.index + cmd.oldString.length);
if(autoSelect)
text.substr(cmd.index + cmd.oldString.length);
if (autoSelect)
Select(cmd.index, cmd.newString.length);
if(addHistory) {
if (addHistory) {
history.length = historyPos;
history.insertLast(cmd);
historyPos += 1;
// limit history length
}
}
private void UndoFieldCommand(FieldCommand@ cmd, bool autoSelect) {
private void UndoFieldCommand(FieldCommand @cmd, bool autoSelect) {
text = text.substr(0, cmd.index) + cmd.oldString +
text.substr(cmd.index + cmd.newString.length);
if(autoSelect)
text.substr(cmd.index + cmd.newString.length);
if (autoSelect)
Select(cmd.index, cmd.oldString.length);
}
private void SetHistoryPos(int index) {
int p = historyPos;
FieldCommand@[]@ h = history;
while(p < index) {
FieldCommand @[] @h = history;
while (p < index) {
RunFieldCommand(h[p], true, false);
p++;
}
while(p > index) {
while (p > index) {
p--;
UndoFieldCommand(h[p], true);
}
@ -168,13 +157,15 @@ namespace spades {
}
bool Undo() {
if(historyPos == 0) return false;
if (historyPos == 0)
return false;
SetHistoryPos(historyPos - 1);
return true;
}
bool Redo() {
if(historyPos >= int(history.length)) return false;
if (historyPos >= int(history.length))
return false;
SetHistoryPos(historyPos + 1);
return true;
}
@ -185,61 +176,56 @@ namespace spades {
Vector2 siz = this.Size;
string text = Text;
int cursorPos = CursorPosition;
Font@ font = this.Font;
Font @font = this.Font;
float width = font.Measure(text.substr(0, cursorPos)).x;
float fontHeight = font.Measure("A").y;
return AABB2(textPos.x + width, textPos.y,
siz.x - textPos.x - width, fontHeight);
return AABB2(textPos.x + width, textPos.y, siz.x - textPos.x - width,
fontHeight);
}
}
private int PointToCharIndex(float x) {
x -= TextOrigin.x;
if(x < 0.f) return 0;
if (x < 0.f)
return 0;
x /= TextScale;
string text = Text;
int len = text.length;
float lastWidth = 0.f;
Font@ font = this.Font;
Font @font = this.Font;
// FIXME: use binary search for better performance?
int idx = 0;
for(int i = 1; i <= len; i++) {
for (int i = 1; i <= len; i++) {
int lastIdx = idx;
idx = GetByteIndexForString(text, 1, idx);
float width = font.Measure(text.substr(0, idx)).x;
if(width > x) {
if(x < (lastWidth + width) * 0.5f) {
if (width > x) {
if (x < (lastWidth + width) * 0.5f) {
return lastIdx;
} else {
return idx;
}
}
lastWidth = width;
if(idx >= len) {
if (idx >= len) {
return len;
}
}
return len;
}
int PointToCharIndex(Vector2 pt) {
return PointToCharIndex(pt.x);
}
int PointToCharIndex(Vector2 pt) { return PointToCharIndex(pt.x); }
int ClampCursorPosition(int pos) {
return Clamp(pos, 0, Text.length);
}
int ClampCursorPosition(int pos) { return Clamp(pos, 0, Text.length); }
void Select(int start, int length = 0) {
MarkPosition = ClampCursorPosition(start);
CursorPosition = ClampCursorPosition(start + length);
}
void SelectAll() {
Select(0, Text.length);
}
void SelectAll() { Select(0, Text.length); }
void BackSpace() {
if(SelectionLength > 0) {
if (SelectionLength > 0) {
SelectedText = "";
} else {
int pos = CursorPosition;
@ -252,9 +238,9 @@ namespace spades {
}
void Delete() {
if(SelectionLength > 0) {
if (SelectionLength > 0) {
SelectedText = "";
} else if(CursorPosition < int(Text.length)) {
} else if (CursorPosition < int(Text.length)) {
int pos = CursorPosition;
int cIdx = GetCharIndexForString(Text, CursorPosition);
int bIdx = GetByteIndexForString(Text, cIdx + 1);
@ -265,14 +251,14 @@ namespace spades {
}
void Insert(string text) {
if(!CheckCharType(text)) {
if (!CheckCharType(text)) {
return;
}
string oldText = SelectedText;
SelectedText = text;
// if text overflows, deny the insertion
if((not FitsInBox(Text)) or (int(Text.length) > MaxLength)) {
if ((not FitsInBox(Text))or(int(Text.length) > MaxLength)) {
SelectedText = oldText;
return;
}
@ -282,16 +268,16 @@ namespace spades {
}
void KeyDown(string key) {
if(key == "BackSpace") {
if (key == "BackSpace") {
BackSpace();
}else if(key == "Delete") {
} else if (key == "Delete") {
Delete();
}else if(key == "Left") {
if(Manager.IsShiftPressed) {
} else if (key == "Left") {
if (Manager.IsShiftPressed) {
int cIdx = GetCharIndexForString(Text, CursorPosition);
CursorPosition = ClampCursorPosition(GetByteIndexForString(Text, cIdx - 1));
}else {
if(SelectionLength == 0) {
} else {
if (SelectionLength == 0) {
int cIdx = GetCharIndexForString(Text, CursorPosition);
Select(GetByteIndexForString(Text, cIdx - 1));
} else {
@ -299,12 +285,12 @@ namespace spades {
}
}
return;
}else if(key == "Right") {
if(Manager.IsShiftPressed) {
} else if (key == "Right") {
if (Manager.IsShiftPressed) {
int cIdx = GetCharIndexForString(Text, CursorPosition);
CursorPosition = ClampCursorPosition(GetByteIndexForString(Text, cIdx + 1));
}else {
if(SelectionLength == 0) {
} else {
if (SelectionLength == 0) {
int cIdx = GetCharIndexForString(Text, CursorPosition);
Select(GetByteIndexForString(Text, cIdx + 1));
} else {
@ -313,60 +299,59 @@ namespace spades {
}
return;
}
if(Manager.IsControlPressed or
Manager.IsMetaPressed /* for OSX; Cmd + [a-z] */) {
if(key == "A") {
if (Manager.IsControlPressed or Manager.IsMetaPressed /* for OSX; Cmd + [a-z] */) {
if (key == "A") {
SelectAll();
return;
}else if(key == "V") {
} else if (key == "V") {
Manager.Paste(PasteClipboardEventHandler(this.Insert));
}else if(key == "C") {
} else if (key == "C") {
Manager.Copy(this.SelectedText);
}else if(key == "X") {
} else if (key == "X") {
Manager.Copy(this.SelectedText);
this.SelectedText = "";
OnChanged();
}else if(key == "Z") {
if(Manager.IsShiftPressed){
if(Redo()) OnChanged();
}else{
if(Undo()) OnChanged();
} else if (key == "Z") {
if (Manager.IsShiftPressed) {
if (Redo())
OnChanged();
} else {
if (Undo())
OnChanged();
}
}else if(key == "W") {
if(Redo()) {
} else if (key == "W") {
if (Redo()) {
OnChanged();
}
}
}
Manager.ProcessHotKey(key);
}
void KeyUp(string key) {
}
void KeyUp(string key) {}
void KeyPress(string text) {
if(!(Manager.IsControlPressed or
Manager.IsMetaPressed)) {
if (!(Manager.IsControlPressed or Manager.IsMetaPressed)) {
Insert(text);
}
}
void MouseDown(MouseButton button, Vector2 clientPosition) {
if(button != spades::ui::MouseButton::LeftMouseButton) {
if (button != spades::ui::MouseButton::LeftMouseButton) {
return;
}
Dragging = true;
if(Manager.IsShiftPressed) {
if (Manager.IsShiftPressed) {
MouseMove(clientPosition);
} else {
Select(PointToCharIndex(clientPosition));
}
}
void MouseMove(Vector2 clientPosition) {
if(Dragging) {
if (Dragging) {
CursorPosition = PointToCharIndex(clientPosition);
}
}
void MouseUp(MouseButton button, Vector2 clientPosition) {
if(button != spades::ui::MouseButton::LeftMouseButton) {
if (button != spades::ui::MouseButton::LeftMouseButton) {
return;
}
Dragging = false;
@ -377,36 +362,36 @@ namespace spades {
}
void DrawHighlight(float x, float y, float w, float h) {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.2f);
Image@ img = renderer.RegisterImage("Gfx/White.tga");
Image @img = renderer.RegisterImage("Gfx/White.tga");
renderer.DrawImage(img, AABB2(x, y, w, h));
}
void DrawBeam(float x, float y, float h) {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
float pulse = sin(Manager.Time * 5.f);
pulse = abs(pulse);
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, pulse);
Image@ img = renderer.RegisterImage("Gfx/White.tga");
Image @img = renderer.RegisterImage("Gfx/White.tga");
renderer.DrawImage(img, AABB2(x - 1.f, y, 2, h));
}
void DrawEditingLine(float x, float y, float w, float h) {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, .3f);
Image@ img = renderer.RegisterImage("Gfx/White.tga");
Image @img = renderer.RegisterImage("Gfx/White.tga");
renderer.DrawImage(img, AABB2(x, y + h, w, 2.f));
}
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Font@ font = this.Font;
Font @font = this.Font;
Vector2 textPos = TextOrigin + pos;
string text = Text;
@ -417,28 +402,29 @@ namespace spades {
int markStart = SelectionStart;
int markEnd = SelectionEnd;
if(composition.length > 0){
if (composition.length > 0) {
this.SelectedText = "";
markStart = SelectionStart + editStart;
markEnd = markStart + editLen;
text = text.substr(0, SelectionStart) + composition + text.substr(SelectionStart);
text =
text.substr(0, SelectionStart) + composition + text.substr(SelectionStart);
}
if(text.length == 0){
if(IsEnabled) {
if (text.length == 0) {
if (IsEnabled) {
font.Draw(Placeholder, textPos, TextScale, PlaceholderColor);
}
}else{
} else {
font.Draw(text, textPos, TextScale, IsEnabled ? TextColor : DisabledTextColor);
}
if(IsFocused){
if (IsFocused) {
float fontHeight = font.Measure("A").y;
// draw selection
int start = markStart;
int end = markEnd;
if(end == start) {
if (end == start) {
float x = font.Measure(text.substr(0, start)).x;
DrawBeam(x + textPos.x, textPos.y, fontHeight);
} else {
@ -448,7 +434,7 @@ namespace spades {
}
// draw composition underline
if(composition.length > 0) {
if (composition.length > 0) {
start = SelectionStart;
end = start + composition.length;
float x1 = font.Measure(text.substr(0, start)).x;
@ -461,9 +447,9 @@ namespace spades {
}
}
class Field: FieldBase {
class Field : FieldBase {
private bool hover;
Field(UIManager@ manager) {
Field(UIManager @manager) {
super(manager);
TextOrigin = Vector2(2.f, 2.f);
}
@ -477,16 +463,16 @@ namespace spades {
}
void Render() {
// render background
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
Image @img = renderer.RegisterImage("Gfx/White.tga");
renderer.ColorNP = Vector4(0.f, 0.f, 0.f, IsFocused ? 0.3f : 0.1f);
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, size.y));
if(IsFocused) {
if (IsFocused) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.2f);
}else if(hover) {
} else if (hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.1f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.06f);
@ -494,7 +480,8 @@ namespace spades {
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, 1.f));
renderer.DrawImage(img, AABB2(pos.x, pos.y + size.y - 1.f, size.x, 1.f));
renderer.DrawImage(img, AABB2(pos.x, pos.y + 1.f, 1.f, size.y - 2.f));
renderer.DrawImage(img, AABB2(pos.x + size.x - 1.f, pos.y + 1.f, 1.f, size.y - 2.f));
renderer.DrawImage(img,
AABB2(pos.x + size.x - 1.f, pos.y + 1.f, 1.f, size.y - 2.f));
FieldBase::Render();
}

View File

@ -23,29 +23,27 @@
namespace spades {
namespace ui {
class Label: UIElement {
class Label : UIElement {
string Text;
Vector4 BackgroundColor = Vector4(0, 0, 0, 0);
Vector4 TextColor = Vector4(1, 1, 1, 1);
Vector2 Alignment = Vector2(0.f, 0.0f);
float TextScale = 1.f;
Label(UIManager@ manager) {
super(manager);
}
Label(UIManager @manager) { super(manager); }
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
if(BackgroundColor.w > 0.f) {
Image@ img = renderer.RegisterImage("Gfx/White.tga");
if (BackgroundColor.w > 0.f) {
Image @img = renderer.RegisterImage("Gfx/White.tga");
renderer.ColorNP = BackgroundColor;
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, size.y));
}
if(Text.length > 0) {
Font@ font = this.Font;
if (Text.length > 0) {
Font @font = this.Font;
string text = this.Text;
Vector2 txtSize = font.Measure(text) * TextScale;
Vector2 txtPos;

View File

@ -24,21 +24,23 @@ namespace spades {
namespace ui {
class ListViewModel {
int NumRows { get { return 0; } }
UIElement@ CreateElement(int row) { return null; }
void RecycleElement(UIElement@ elem) {}
int NumRows {
get { return 0; }
}
UIElement @CreateElement(int row) { return null; }
void RecycleElement(UIElement @elem) {}
}
/** Simple virtual stack panel implementation. */
class ListViewBase: UIElement {
private ScrollBar@ scrollBar;
private ListViewModel@ model;
class ListViewBase : UIElement {
private ScrollBar @scrollBar;
private ListViewModel @model;
float RowHeight = 24.f;
float ScrollBarWidth = 16.f;
private UIElementDeque items;
private int loadedStartIndex = 0;
ListViewBase(UIManager@ manager) {
ListViewBase(UIManager @manager) {
super(manager);
@scrollBar = ScrollBar(Manager);
scrollBar.Bounds = AABB2();
@ -49,20 +51,14 @@ namespace spades {
@model = ListViewModel();
}
private void OnScrolled(UIElement@ sender) {
Layout();
}
private void OnScrolled(UIElement @sender) { Layout(); }
int NumVisibleRows {
get final {
return int(floor(Size.y / RowHeight));
}
get final { return int(floor(Size.y / RowHeight)); }
}
int MaxTopRowIndex {
get final {
return Max(0, model.NumRows - NumVisibleRows);
}
get final { return Max(0, model.NumRows - NumVisibleRows); }
}
int TopRowIndex {
@ -90,33 +86,33 @@ namespace spades {
int loadedStart = loadedStartIndex;
int loadedEnd = loadedStartIndex + items.Count;
if(items.Count == 0 or visibleStart >= loadedEnd or visibleEnd <= loadedStart) {
if (items.Count == 0 or visibleStart >= loadedEnd or visibleEnd <= loadedStart) {
// full reload
UnloadAll();
for(int i = visibleStart; i < visibleEnd; i++) {
for (int i = visibleStart; i < visibleEnd; i++) {
items.PushBack(model.CreateElement(i));
AddChild(items.Back);
}
loadedStartIndex = visibleStart;
} else {
while(loadedStart < visibleStart) {
while (loadedStart < visibleStart) {
RemoveChild(items.Front);
model.RecycleElement(items.Front);
items.PopFront();
loadedStart++;
}
while(loadedEnd > visibleEnd) {
while (loadedEnd > visibleEnd) {
RemoveChild(items.Back);
model.RecycleElement(items.Back);
items.PopBack();
loadedEnd--;
}
while(visibleStart < loadedStart) {
while (visibleStart < loadedStart) {
loadedStart--;
items.PushFront(model.CreateElement(loadedStart));
AddChild(items.Front);
}
while(visibleEnd > loadedEnd) {
while (visibleEnd > loadedEnd) {
items.PushBack(model.CreateElement(loadedEnd));
AddChild(items.Back);
loadedEnd++;
@ -125,11 +121,11 @@ namespace spades {
}
// relayout items
UIElementDeque@ items = this.items;
UIElementDeque @items = this.items;
int count = items.Count;
float y = 0.f;
float w = ItemWidth;
for(int i = 0; i < count; i++){
for (int i = 0; i < count; i++) {
items[i].Bounds = AABB2(0.f, y, w, RowHeight);
y += RowHeight;
}
@ -139,14 +135,10 @@ namespace spades {
}
float ItemWidth {
get {
return Size.x - ScrollBarWidth;
}
get { return Size.x - ScrollBarWidth; }
}
void MouseWheel(float delta) {
scrollBar.ScrollBy(delta);
}
void MouseWheel(float delta) { scrollBar.ScrollBy(delta); }
void Reload() {
UnloadAll();
@ -154,19 +146,19 @@ namespace spades {
}
private void UnloadAll() {
UIElementDeque@ items = this.items;
UIElementDeque @items = this.items;
int count = items.Count;
for(int i = 0; i < count; i++){
for (int i = 0; i < count; i++) {
RemoveChild(items[i]);
model.RecycleElement(items[i]);
}
items.Clear();
}
ListViewModel@ Model {
ListViewModel @Model {
get final { return model; }
set {
if(model is value) {
if (model is value) {
return;
}
UnloadAll();
@ -175,26 +167,19 @@ namespace spades {
}
}
void ScrollToTop() {
scrollBar.ScrollTo(0.0);
}
void ScrollToTop() { scrollBar.ScrollTo(0.0); }
void ScrollToEnd() {
scrollBar.ScrollTo(scrollBar.MaxValue);
}
void ScrollToEnd() { scrollBar.ScrollTo(scrollBar.MaxValue); }
}
class ListView: ListViewBase {
ListView(UIManager@ manager) {
super(manager);
}
class ListView : ListViewBase {
ListView(UIManager @manager) { super(manager); }
void Render() {
// render background
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
Image @img = renderer.RegisterImage("Gfx/White.tga");
renderer.ColorNP = Vector4(0.f, 0.f, 0.f, 0.2f);
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, size.y));
@ -202,7 +187,8 @@ namespace spades {
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, 1.f));
renderer.DrawImage(img, AABB2(pos.x, pos.y + size.y - 1.f, size.x, 1.f));
renderer.DrawImage(img, AABB2(pos.x, pos.y + 1.f, 1.f, size.y - 2.f));
renderer.DrawImage(img, AABB2(pos.x + size.x - 1.f, pos.y + 1.f, 1.f, size.y - 2.f));
renderer.DrawImage(img,
AABB2(pos.x + size.x - 1.f, pos.y + 1.f, 1.f, size.y - 2.f));
ListViewBase::Render();
}

View File

@ -23,30 +23,23 @@
namespace spades {
namespace ui {
enum ScrollBarOrientation {
Horizontal,
Vertical
}
enum ScrollBarOrientation { Horizontal, Vertical }
class ScrollBarBase: UIElement {
class ScrollBarBase : UIElement {
double MinValue = 0.0;
double MaxValue = 100.0;
double Value = 0.0;
double SmallChange = 1.0;
double LargeChange = 20.0;
EventHandler@ Changed;
EventHandler @Changed;
ScrollBarBase(UIManager@ manager) {
super(manager);
}
ScrollBarBase(UIManager @manager) { super(manager); }
void ScrollBy(double delta) {
ScrollTo(Value + delta);
}
void ScrollBy(double delta) { ScrollTo(Value + delta); }
void ScrollTo(double val) {
val = Clamp(val, MinValue, MaxValue);
if(val == Value) {
if (val == Value) {
return;
}
Value = val;
@ -54,39 +47,37 @@ namespace spades {
}
void OnChanged() {
if(Changed !is null) {
if (Changed !is null) {
Changed(this);
}
}
ScrollBarOrientation Orientation {
get {
if(Size.x > Size.y) {
if (Size.x > Size.y) {
return spades::ui::ScrollBarOrientation::Horizontal;
} else {
return spades::ui::ScrollBarOrientation::Vertical;
}
}
}
}
class ScrollBarTrackBar: UIElement {
private ScrollBar@ scrollBar;
class ScrollBarTrackBar : UIElement {
private ScrollBar @scrollBar;
private bool dragging = false;
private double startValue;
private float startCursorPos;
private bool hover = false;
ScrollBarTrackBar(ScrollBar@ scrollBar) {
ScrollBarTrackBar(ScrollBar @scrollBar) {
super(scrollBar.Manager);
@this.scrollBar = scrollBar;
IsMouseInteractive = true;
}
private float GetCursorPos(Vector2 pos) {
if(scrollBar.Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
if (scrollBar.Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
return pos.x + Position.x;
} else {
return pos.y + Position.y;
@ -94,10 +85,10 @@ namespace spades {
}
void MouseDown(MouseButton button, Vector2 clientPosition) {
if(button != spades::ui::MouseButton::LeftMouseButton) {
if (button != spades::ui::MouseButton::LeftMouseButton) {
return;
}
if(scrollBar.TrackBarMovementRange < 0.0001f) {
if (scrollBar.TrackBarMovementRange < 0.0001f) {
// immobile
return;
}
@ -106,16 +97,16 @@ namespace spades {
startCursorPos = GetCursorPos(clientPosition);
}
void MouseMove(Vector2 clientPosition) {
if(dragging) {
if (dragging) {
double val = startValue;
float delta = GetCursorPos(clientPosition) - startCursorPos;
val += delta * (scrollBar.MaxValue - scrollBar.MinValue) /
double(scrollBar.TrackBarMovementRange);
double(scrollBar.TrackBarMovementRange);
scrollBar.ScrollTo(val);
}
}
void MouseUp(MouseButton button, Vector2 clientPosition) {
if(button != spades::ui::MouseButton::LeftMouseButton) {
if (button != spades::ui::MouseButton::LeftMouseButton) {
return;
}
dragging = false;
@ -130,18 +121,20 @@ namespace spades {
}
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
Image @img = renderer.RegisterImage("Gfx/White.tga");
if(scrollBar.Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
pos.y += 4.f; size.y -= 8.f;
if (scrollBar.Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
pos.y += 4.f;
size.y -= 8.f;
} else {
pos.x += 4.f; size.x -= 8.f;
pos.x += 4.f;
size.x -= 8.f;
}
if(dragging) {
if (dragging) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.4f);
} else if (hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.2f);
@ -152,11 +145,11 @@ namespace spades {
}
}
class ScrollBarFill: ButtonBase {
private ScrollBarBase@ scrollBar;
class ScrollBarFill : ButtonBase {
private ScrollBarBase @scrollBar;
private bool up;
ScrollBarFill(ScrollBarBase@ scrollBar, bool up) {
ScrollBarFill(ScrollBarBase @scrollBar, bool up) {
super(scrollBar.Manager);
@this.scrollBar = scrollBar;
IsMouseInteractive = true;
@ -177,12 +170,12 @@ namespace spades {
}
}
class ScrollBarButton: ButtonBase {
private ScrollBar@ scrollBar;
class ScrollBarButton : ButtonBase {
private ScrollBar @scrollBar;
private bool up;
private Image@ image;
private Image @image;
ScrollBarButton(ScrollBar@ scrollBar, bool up) {
ScrollBarButton(ScrollBar @scrollBar, bool up) {
super(scrollBar.Manager);
@this.scrollBar = scrollBar;
IsMouseInteractive = true;
@ -200,14 +193,14 @@ namespace spades {
}
void Render() {
Renderer@ r = Manager.Renderer;
Renderer @r = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
pos += size * 0.5f;
float siz = image.Width * 0.5f;
AABB2 srcRect(0.f, 0.f, image.Width, image.Height);
if(Pressed and Hover) {
if (Pressed and Hover) {
r.ColorNP = Vector4(1.f, 1.f, 1.f, 0.6f);
} else if (Hover) {
r.ColorNP = Vector4(1.f, 1.f, 1.f, 0.4f);
@ -215,41 +208,41 @@ namespace spades {
r.ColorNP = Vector4(1.f, 1.f, 1.f, 0.2f);
}
if(scrollBar.Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
if(up) {
r.DrawImage(image,
Vector2(pos.x + siz, pos.y - siz), Vector2(pos.x + siz, pos.y + siz), Vector2(pos.x - siz, pos.y - siz),
srcRect);
if (scrollBar.Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
if (up) {
r.DrawImage(image, Vector2(pos.x + siz, pos.y - siz),
Vector2(pos.x + siz, pos.y + siz),
Vector2(pos.x - siz, pos.y - siz), srcRect);
} else {
r.DrawImage(image,
Vector2(pos.x - siz, pos.y + siz), Vector2(pos.x - siz, pos.y - siz), Vector2(pos.x + siz, pos.y + siz),
srcRect);
r.DrawImage(image, Vector2(pos.x - siz, pos.y + siz),
Vector2(pos.x - siz, pos.y - siz),
Vector2(pos.x + siz, pos.y + siz), srcRect);
}
} else {
if(up) {
r.DrawImage(image,
Vector2(pos.x + siz, pos.y + siz), Vector2(pos.x - siz, pos.y + siz), Vector2(pos.x + siz, pos.y - siz),
srcRect);
if (up) {
r.DrawImage(image, Vector2(pos.x + siz, pos.y + siz),
Vector2(pos.x - siz, pos.y + siz),
Vector2(pos.x + siz, pos.y - siz), srcRect);
} else {
r.DrawImage(image,
Vector2(pos.x - siz, pos.y - siz), Vector2(pos.x + siz, pos.y - siz), Vector2(pos.x - siz, pos.y + siz),
srcRect);
r.DrawImage(image, Vector2(pos.x - siz, pos.y - siz),
Vector2(pos.x + siz, pos.y - siz),
Vector2(pos.x - siz, pos.y + siz), srcRect);
}
}
}
}
class ScrollBar: ScrollBarBase {
class ScrollBar : ScrollBarBase {
private ScrollBarTrackBar@ trackBar;
private ScrollBarFill@ fill1;
private ScrollBarFill@ fill2;
private ScrollBarButton@ button1;
private ScrollBarButton@ button2;
private ScrollBarTrackBar @trackBar;
private ScrollBarFill @fill1;
private ScrollBarFill @fill2;
private ScrollBarButton @button1;
private ScrollBarButton @button2;
private float ButtonSize = 16.f;
ScrollBar(UIManager@ manager) {
ScrollBar(UIManager @manager) {
super(manager);
@trackBar = ScrollBarTrackBar(this);
@ -270,18 +263,10 @@ namespace spades {
AddChild(button2);
}
private void LargeDown(UIElement@ e) {
ScrollBy(-LargeChange);
}
private void LargeUp(UIElement@ e) {
ScrollBy(LargeChange);
}
private void SmallDown(UIElement@ e) {
ScrollBy(-SmallChange);
}
private void SmallUp(UIElement@ e) {
ScrollBy(SmallChange);
}
private void LargeDown(UIElement @e) { ScrollBy(-LargeChange); }
private void LargeUp(UIElement @e) { ScrollBy(LargeChange); }
private void SmallDown(UIElement @e) { ScrollBy(-SmallChange); }
private void SmallUp(UIElement @e) { ScrollBy(SmallChange); }
void OnChanged() {
Layout();
@ -293,17 +278,19 @@ namespace spades {
Vector2 size = Size;
float tPos = TrackBarPosition;
float tLen = TrackBarLength;
if(Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
if (Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
button1.Bounds = AABB2(0.f, 0.f, ButtonSize, size.y);
button2.Bounds = AABB2(size.x - ButtonSize, 0.f, ButtonSize, size.y);
fill1.Bounds = AABB2(ButtonSize, 0.f, tPos - ButtonSize, size.y);
fill2.Bounds = AABB2(tPos + tLen, 0.f, size.x - ButtonSize - tPos - tLen, size.y);
fill2.Bounds =
AABB2(tPos + tLen, 0.f, size.x - ButtonSize - tPos - tLen, size.y);
trackBar.Bounds = AABB2(tPos, 0.f, tLen, size.y);
} else {
button1.Bounds = AABB2(0.f, 0.f, size.x, ButtonSize);
button2.Bounds = AABB2(0.f, size.y - ButtonSize, size.x, ButtonSize);
fill1.Bounds = AABB2(0.f, ButtonSize, size.x, tPos - ButtonSize);
fill2.Bounds = AABB2(0.f, tPos + tLen, size.x, size.y - ButtonSize - tPos - tLen);
fill2.Bounds =
AABB2(0.f, tPos + tLen, size.x, size.y - ButtonSize - tPos - tLen);
trackBar.Bounds = AABB2(0.f, tPos, size.x, tLen);
}
}
@ -315,7 +302,7 @@ namespace spades {
float Length {
get {
if(Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
if (Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
return Size.x;
} else {
return Size.y;
@ -324,30 +311,29 @@ namespace spades {
}
float TrackBarAreaLength {
get {
return Length - ButtonSize - ButtonSize;
}
get { return Length - ButtonSize - ButtonSize; }
}
float TrackBarLength {
get {
return Max(TrackBarAreaLength *
(LargeChange / (MaxValue - MinValue + LargeChange)), 40.f);
(LargeChange / (MaxValue - MinValue + LargeChange)),
40.f);
}
}
float TrackBarMovementRange {
get {
return TrackBarAreaLength - TrackBarLength;
}
get { return TrackBarAreaLength - TrackBarLength; }
}
float TrackBarPosition {
get {
if(MaxValue == MinValue) {
if (MaxValue == MinValue) {
return ButtonSize;
}
return float((Value - MinValue) / (MaxValue - MinValue) * TrackBarMovementRange) + ButtonSize;
return float((Value - MinValue) / (MaxValue - MinValue) *
TrackBarMovementRange) +
ButtonSize;
}
}

View File

@ -23,25 +23,23 @@
namespace spades {
namespace ui {
class SliderKnob: UIElement {
private Slider@ slider;
class SliderKnob : UIElement {
private Slider @slider;
private bool dragging = false;
private double startValue;
private float startCursorPos;
private bool hover = false;
SliderKnob(Slider@ slider) {
SliderKnob(Slider @slider) {
super(slider.Manager);
@this.slider = slider;
IsMouseInteractive = true;
}
private float GetCursorPos(Vector2 pos) {
return pos.x + Position.x;
}
private float GetCursorPos(Vector2 pos) { return pos.x + Position.x; }
void MouseDown(MouseButton button, Vector2 clientPosition) {
if(button != spades::ui::MouseButton::LeftMouseButton) {
if (button != spades::ui::MouseButton::LeftMouseButton) {
return;
}
dragging = true;
@ -49,16 +47,16 @@ namespace spades {
startCursorPos = GetCursorPos(clientPosition);
}
void MouseMove(Vector2 clientPosition) {
if(dragging) {
if (dragging) {
double val = startValue;
float delta = GetCursorPos(clientPosition) - startCursorPos;
val += delta * (slider.MaxValue - slider.MinValue) /
double(slider.TrackBarMovementRange);
double(slider.TrackBarMovementRange);
slider.ScrollTo(val);
}
}
void MouseUp(MouseButton button, Vector2 clientPosition) {
if(button != spades::ui::MouseButton::LeftMouseButton) {
if (button != spades::ui::MouseButton::LeftMouseButton) {
return;
}
dragging = false;
@ -73,34 +71,31 @@ namespace spades {
}
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
Image @img = renderer.RegisterImage("Gfx/White.tga");
if (hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.5f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.3f);
}
renderer.DrawImage(img,
AABB2(pos.x + size.x * 0.5f - 3.f, pos.y,
6.f, size.y));
renderer.DrawImage(img, AABB2(pos.x + size.x * 0.5f - 3.f, pos.y, 6.f, size.y));
renderer.ColorNP = Vector4(0.f, 0.f, 0.f, 0.6f);
renderer.DrawImage(img,
AABB2(pos.x + size.x * 0.5f - 2.f, pos.y + 1.f,
4.f, size.y - 2.f));
renderer.DrawImage(
img, AABB2(pos.x + size.x * 0.5f - 2.f, pos.y + 1.f, 4.f, size.y - 2.f));
}
}
class Slider: ScrollBarBase {
class Slider : ScrollBarBase {
private SliderKnob@ knob;
private ScrollBarFill@ fill1;
private ScrollBarFill@ fill2;
private SliderKnob @knob;
private ScrollBarFill @fill1;
private ScrollBarFill @fill2;
Slider(UIManager@ manager) {
Slider(UIManager @manager) {
super(manager);
@knob = SliderKnob(this);
@ -112,21 +107,18 @@ namespace spades {
@fill2 = ScrollBarFill(this, true);
@fill2.Activated = EventHandler(this.LargeUp);
AddChild(fill2);
}
private void LargeDown(UIElement@ e) {
ScrollBy(-LargeChange);
}
private void LargeUp(UIElement@ e) {
private void LargeDown(UIElement @e) { ScrollBy(-LargeChange); }
private void LargeUp(UIElement @e) {
ScrollBy(LargeChange);
}/*
private void SmallDown(UIElement@ e) {
ScrollBy(-SmallChange);
}
private void SmallUp(UIElement@ e) {
ScrollBy(SmallChange);
}*/
} /*
private void SmallDown(UIElement@ e) {
ScrollBy(-SmallChange);
}
private void SmallUp(UIElement@ e) {
ScrollBy(SmallChange);
}*/
void OnChanged() {
Layout();
@ -150,7 +142,7 @@ namespace spades {
float Length {
get {
if(Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
if (Orientation == spades::ui::ScrollBarOrientation::Horizontal) {
return Size.x;
} else {
return Size.y;
@ -159,46 +151,38 @@ namespace spades {
}
float TrackBarAreaLength {
get {
return Length;
}
get { return Length; }
}
float TrackBarLength {
get {
return 16.f;
}
get { return 16.f; }
}
float TrackBarMovementRange {
get {
return TrackBarAreaLength - TrackBarLength;
}
get { return TrackBarAreaLength - TrackBarLength; }
}
float TrackBarPosition {
get {
return float((Value - MinValue) / (MaxValue - MinValue) * TrackBarMovementRange);
return float((Value - MinValue) / (MaxValue - MinValue) *
TrackBarMovementRange);
}
}
void Render() {
Layout();
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
Image @img = renderer.RegisterImage("Gfx/White.tga");
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.1f);
renderer.DrawImage(img,
AABB2(pos.x, pos.y + size.y * 0.5f - 3.f,
size.x, 6.f));
renderer.DrawImage(img, AABB2(pos.x, pos.y + size.y * 0.5f - 3.f, size.x, 6.f));
renderer.ColorNP = Vector4(0.f, 0.f, 0.f, 0.2f);
renderer.DrawImage(img,
AABB2(pos.x + 1.f, pos.y + size.y * 0.5f - 2.f,
size.x - 2.f, 4.f));
renderer.DrawImage(
img, AABB2(pos.x + 1.f, pos.y + size.y * 0.5f - 2.f, size.x - 2.f, 4.f));
ScrollBarBase::Render();
}

View File

@ -23,10 +23,10 @@
namespace spades {
namespace ui {
class SimpleTabStripItem: ButtonBase {
UIElement@ linkedElement;
class SimpleTabStripItem : ButtonBase {
UIElement @linkedElement;
SimpleTabStripItem(UIManager@ manager, UIElement@ linkedElement) {
SimpleTabStripItem(UIManager @manager, UIElement @linkedElement) {
super(manager);
@this.linkedElement = linkedElement;
}
@ -39,15 +39,15 @@ namespace spades {
void Render() {
this.Toggled = linkedElement.Visible;
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Vector4 textColor(0.9f, 0.9f, 0.9f, 1.0f);
Image@ img = renderer.RegisterImage("Gfx/White.tga");
if(Toggled) {
Image @img = renderer.RegisterImage("Gfx/White.tga");
if (Toggled) {
renderer.ColorNP = Vector4(0.9f, 0.9f, 0.9f, 1.0f);
textColor = Vector4(0.0f, 0.0f, 0.0f, 1.0f);
} else if(Hover) {
} else if (Hover) {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.3f);
} else {
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.0f);
@ -59,33 +59,31 @@ namespace spades {
}
}
class SimpleTabStrip: UIElement {
class SimpleTabStrip : UIElement {
private float nextX = 0.f;
EventHandler@ Changed;
EventHandler @Changed;
SimpleTabStrip(UIManager@ manager) {
super(manager);
}
SimpleTabStrip(UIManager @manager) { super(manager); }
private void OnChanged() {
if(Changed !is null) {
if (Changed !is null) {
Changed(this);
}
}
private void OnItemActivated(UIElement@ sender) {
SimpleTabStripItem@ item = cast<SimpleTabStripItem>(sender);
UIElement@ linked = item.linkedElement;
UIElement@[]@ children = this.GetChildren();
for(uint i = 0, count = children.length; i < count; i++) {
SimpleTabStripItem@ otherItem = cast<SimpleTabStripItem>(children[i]);
private void OnItemActivated(UIElement @sender) {
SimpleTabStripItem @item = cast<SimpleTabStripItem>(sender);
UIElement @linked = item.linkedElement;
UIElement @[] @children = this.GetChildren();
for (uint i = 0, count = children.length; i < count; i++) {
SimpleTabStripItem @otherItem = cast<SimpleTabStripItem>(children[i]);
otherItem.linkedElement.Visible = (otherItem.linkedElement is linked);
}
OnChanged();
}
void AddItem(string title, UIElement@ linkedElement) {
void AddItem(string title, UIElement @linkedElement) {
SimpleTabStripItem item(this.Manager, linkedElement);
item.Caption = title;
float w = this.Font.Measure(title).x + 18.f;
@ -95,20 +93,18 @@ namespace spades {
@item.Activated = EventHandler(this.OnItemActivated);
this.AddChild(item);
}
void Render() {
UIElement::Render();
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
Image@ img = renderer.RegisterImage("Gfx/White.tga");
Image @img = renderer.RegisterImage("Gfx/White.tga");
renderer.ColorNP = Vector4(0.9f, 0.9f, 0.9f, 1.0f);
renderer.DrawImage(img, AABB2(pos.x, pos.y + 24.f, size.x, 1.f));
}
}
}

View File

@ -23,31 +23,28 @@
namespace spades {
namespace ui {
class TextViewerSelectionState {
UIElement@ FocusElement;
UIElement @FocusElement;
int MarkPosition = 0;
int CursorPosition = 0;
int SelectionStart {
get final {
return Min(MarkPosition, CursorPosition);
}
get final { return Min(MarkPosition, CursorPosition); }
}
int SelectionEnd {
get final {
return Max(MarkPosition, CursorPosition);
}
get final { return Max(MarkPosition, CursorPosition); }
}
}
class TextViewerItemUI: UIElement {
class TextViewerItemUI : UIElement {
private string text;
private Vector4 textColor;
private int index;
private TextViewerSelectionState@ selection;
private TextViewerSelectionState @selection;
TextViewerItemUI(UIManager@ manager, TextViewerItem@ item, TextViewerSelectionState@ selection) {
TextViewerItemUI(UIManager @manager, TextViewerItem @item,
TextViewerSelectionState @selection) {
super(manager);
text = item.Text;
@ -57,21 +54,21 @@ namespace spades {
}
void DrawHighlight(float x, float y, float w, float h) {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.2f);
Image@ img = renderer.RegisterImage("Gfx/White.tga");
Image @img = renderer.RegisterImage("Gfx/White.tga");
renderer.DrawImage(img, AABB2(x, y, w, h));
}
void Render() {
Renderer@ renderer = Manager.Renderer;
Renderer @renderer = Manager.Renderer;
Vector2 pos = ScreenPosition;
Vector2 size = Size;
float textScale = 1.0f;
Font@ font = this.Font;
Font @font = this.Font;
if(text.length > 0) {
if (text.length > 0) {
Vector2 txtSize = font.Measure(text) * textScale;
Vector2 txtPos;
txtPos = pos + (size - txtSize) * Vector2(0.0f, 0.0f);
@ -89,7 +86,7 @@ namespace spades {
if (end > int(text.length) + 1) {
end = int(text.length) + 1;
}
if(end > start) {
if (end > start) {
float x1 = font.Measure(text.substr(0, start)).x;
float x2 = font.Measure(text.substr(0, end)).x;
@ -115,12 +112,12 @@ namespace spades {
}
}
class TextViewerModel: ListViewModel {
UIManager@ manager;
TextViewerItem@[] lines = {};
Font@ font;
class TextViewerModel : ListViewModel {
UIManager @manager;
TextViewerItem @[] lines = {};
Font @font;
float width;
TextViewerSelectionState@ selection;
TextViewerSelectionState @selection;
int contentLength;
void AddLine(string text, Vector4 color) {
@ -136,13 +133,13 @@ namespace spades {
bool charMode = false;
while (startPos < len) {
int nextPos = pos + 1;
if(charMode) {
if (charMode) {
// skip to the next UTF-8 character boundary
while(nextPos < len && ((text[nextPos] & 0x80) != 0) &&
((text[nextPos] & 0xc0) != 0xc0))
while (nextPos < len && ((text[nextPos] & 0x80) != 0) &&
((text[nextPos] & 0xc0) != 0xc0))
nextPos++;
} else {
while(nextPos < len && text[nextPos] != 0x20)
while (nextPos < len && text[nextPos] != 0x20)
nextPos++;
}
if (font.Measure(text.substr(startPos, nextPos - startPos)).x > width) {
@ -154,7 +151,8 @@ namespace spades {
}
continue;
} else {
lines.insertLast(TextViewerItem(text.substr(startPos, pos - startPos), color, contentLength));
lines.insertLast(TextViewerItem(text.substr(startPos, pos - startPos),
color, contentLength));
contentLength += pos - startPos;
startPos = pos;
while (startPos < len && text[startPos] == 0x20) {
@ -167,50 +165,58 @@ namespace spades {
} else {
pos = nextPos;
if (nextPos >= len) {
lines.insertLast(TextViewerItem(text.substr(startPos, nextPos - startPos), color, contentLength));
lines.insertLast(TextViewerItem(
text.substr(startPos, nextPos - startPos), color, contentLength));
contentLength += nextPos - startPos + 1;
break;
}
}
}
}
TextViewerModel(UIManager@ manager, string text, Font@ font, float width, TextViewerSelectionState@ selection) {
TextViewerModel(UIManager @manager, string text, Font @font, float width,
TextViewerSelectionState @selection) {
@this.manager = manager;
@this.font = font;
this.width = width;
@this.selection = selection;
string[]@ lines = text.split("\n");
string[] @lines = text.split("\n");
for (uint i = 0; i < lines.length; i++)
AddLine(lines[i], Vector4(1.f, 1.f, 1.f, 1.f));
}
int NumRows { get { return int(lines.length); } }
int NumRows {
get { return int(lines.length); }
}
UIElement@ CreateElement(int row) {
UIElement @CreateElement(int row) {
return TextViewerItemUI(manager, lines[row], selection);
}
void RecycleElement(UIElement@ elem) {}
void RecycleElement(UIElement @elem) {}
}
class TextViewer: ListViewBase {
class TextViewer : ListViewBase {
private string text;
private TextViewerModel@ textmodel;
private TextViewerModel @textmodel;
private TextViewerSelectionState selection;
private bool dragging = false;
TextViewer(UIManager@ manager) {
TextViewer(UIManager @manager) {
super(manager);
@selection.FocusElement = this;
AcceptsFocus = true;
IsMouseInteractive = true;
@this.Cursor = Cursor(Manager, manager.Renderer.RegisterImage("Gfx/UI/IBeam.png"), Vector2(16.f, 16.f));
@this.Cursor
= Cursor(Manager, manager.Renderer.RegisterImage("Gfx/UI/IBeam.png"),
Vector2(16.f, 16.f));
}
/** Sets the displayed text. Ensure TextViewer.Font is not null before setting this proeprty. */
/**
* Sets the displayed text. Ensure TextViewer.Font is not null before
* setting this proeprty.
*/
string Text {
get final { return text; }
set {
@ -232,27 +238,27 @@ namespace spades {
float x = clientPosition.x;
string text = textmodel.lines[line].Text;
int lineStartIndex = textmodel.lines[line].Index;
if(x < 0.f) {
if (x < 0.f) {
return lineStartIndex;
}
int len = text.length;
float lastWidth = 0.f;
Font@ font = this.Font;
Font @font = this.Font;
// FIXME: use binary search for better performance?
int idx = 0;
for(int i = 1; i <= len; i++) {
for (int i = 1; i <= len; i++) {
int lastIdx = idx;
idx = GetByteIndexForString(text, 1, idx);
float width = font.Measure(text.substr(0, idx)).x;
if(width > x) {
if(x < (lastWidth + width) * 0.5f) {
if (width > x) {
if (x < (lastWidth + width) * 0.5f) {
return lastIdx + lineStartIndex;
} else {
return idx + lineStartIndex;
}
}
lastWidth = width;
if(idx >= len) {
if (idx >= len) {
return len + lineStartIndex;
}
}
@ -260,33 +266,33 @@ namespace spades {
}
void MouseDown(MouseButton button, Vector2 clientPosition) {
if(button != spades::ui::MouseButton::LeftMouseButton) {
if (button != spades::ui::MouseButton::LeftMouseButton) {
return;
}
dragging = true;
if(Manager.IsShiftPressed) {
if (Manager.IsShiftPressed) {
MouseMove(clientPosition);
} else {
selection.MarkPosition = selection.CursorPosition = PointToCharIndex(clientPosition);
selection.MarkPosition = selection.CursorPosition =
PointToCharIndex(clientPosition);
}
}
void MouseMove(Vector2 clientPosition) {
if(dragging) {
if (dragging) {
selection.CursorPosition = PointToCharIndex(clientPosition);
}
}
void MouseUp(MouseButton button, Vector2 clientPosition) {
if(button != spades::ui::MouseButton::LeftMouseButton) {
if (button != spades::ui::MouseButton::LeftMouseButton) {
return;
}
dragging = false;
}
void KeyDown(string key) {
if(Manager.IsControlPressed or
Manager.IsMetaPressed /* for OSX; Cmd + [a-z] */) {
if (Manager.IsControlPressed or Manager.IsMetaPressed /* for OSX; Cmd + [a-z] */) {
if (key == "C" && this.selection.SelectionEnd > this.selection.SelectionStart) {
Manager.Copy(this.SelectedText);
return;
@ -305,7 +311,7 @@ namespace spades {
int start = this.selection.SelectionStart;
int end = this.selection.SelectionEnd;
auto@ lines = textmodel.lines;
auto @lines = textmodel.lines;
for (uint i = 0, count = lines.length; i < count; ++i) {
string line = lines[i].Text;
@ -330,18 +336,19 @@ namespace spades {
}
}
void AddLine(string line, bool autoscroll = false, Vector4 color = Vector4(1.f, 1.f, 1.f, 1.f)) {
if(textmodel is null) {
void AddLine(string line, bool autoscroll = false,
Vector4 color = Vector4(1.f, 1.f, 1.f, 1.f)) {
if (textmodel is null) {
this.Text = "";
}
if(autoscroll){
if (autoscroll) {
this.Layout();
if(this.scrollBar.Value < this.scrollBar.MaxValue) {
if (this.scrollBar.Value < this.scrollBar.MaxValue) {
autoscroll = false;
}
}
textmodel.AddLine(line, color);
if(autoscroll) {
if (autoscroll) {
this.Layout();
this.ScrollToEnd();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +1,29 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** AudioChunk is an opaque type which can be passed to an audio device to
* play sounds. */
class AudioChunk {
}
}
/**
* AudioChunk is an opaque type which can be passed to an audio device to
* play sounds.
*/
class AudioChunk {}
}

View File

@ -1,64 +1,67 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** AudioDevice is an interface to the audio device. */
class AudioDevice {
/** Loads an audio data from the specified path or load one from
* the cache, if exists.
* @param path file-system path. */
AudioChunk@ RegisterSound(const string@ path) {}
/** Sets a game world map. */
GameMap@ GameMap {
set {}
}
/** Plays a sound. */
void Play(AudioChunk@, const Vector3@ origin, const AudioParam@ params);
/** Plays a sound, with the source position specified in the view
* coordinate space. */
void PlayLocal(AudioChunk@, const Vector3@ origin, const AudioParam@ params);
/** Plays a non-spatialized sound. */
void PlayLocal(AudioChunk@, const AudioParam@ params);
/** Updates the position of the listener. */
void Respatialize(const Vector3@ eye,
const Vector3@ frontVector,
const Vector3@ upVector);
}
class AudioParam {
/** Linear gain of the sound. */
float volume;
/** Playback speed of the sound. Doubling this value makes the sound
* played twice faster. */
float pitch;
float referenceDistance;
}
}
/** AudioDevice is an interface to the audio device. */
class AudioDevice {
/**
* Loads an audio data from the specified path or load one from
* the cache, if exists.
* @param path file-system path.
*/
AudioChunk @RegisterSound(const string @path) {}
/** Sets a game world map. */
GameMap @GameMap {
set {}
}
/** Plays a sound. */
void Play(AudioChunk @, const Vector3 @origin, const AudioParam @params);
/**
* Plays a sound, with the source position specified in the view
* coordinate space.
*/
void PlayLocal(AudioChunk @, const Vector3 @origin, const AudioParam @params);
/** Plays a non-spatialized sound. */
void PlayLocal(AudioChunk @, const AudioParam @params);
/** Updates the position of the listener. */
void Respatialize(const Vector3 @eye, const Vector3 @frontVector, const Vector3 @upVector);
}
class AudioParam {
/** Linear gain of the sound. */
float volume;
/**
* Playback speed of the sound. Doubling this value makes the sound
* played twice faster.
*/
float pitch;
float referenceDistance;
}
}

View File

@ -1,49 +1,48 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** Represents a 32-bit RGBA bitmap. */
class Bitmap {
/** Creates a new bitmap. */
GameMap(int width, int height) {}
/** Loads a bitmap from the specified file. */
GameMap(const string@ path) {}
/** Gets the color of the specified pixel. */
uint GetPixel(int x, int y) {}
/** Sets the color of the specified pixel. */
void SetPixel(int x, int y, uint color) {}
/** Retrieves the width of the bitmap. */
int Width {
get { }
}
/** Retrieves the height of the bitmap. */
int Height {
get { }
}
}
}
/** Represents a 32-bit RGBA bitmap. */
class Bitmap {
/** Creates a new bitmap. */
GameMap(int width, int height) {}
/** Loads a bitmap from the specified file. */
GameMap(const string @path) {}
/** Gets the color of the specified pixel. */
uint GetPixel(int x, int y) {}
/** Sets the color of the specified pixel. */
void SetPixel(int x, int y, uint color) {}
/** Retrieves the width of the bitmap. */
int Width {
get {}
}
/** Retrieves the height of the bitmap. */
int Height {
get {}
}
}
}

View File

@ -1,36 +1,35 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** Represents a bitmap-based font. */
class Font {
/** Measures the size of the given string. */
Vector2 Measure(const string@ text);
/** Renders the string. */
void Draw(const string@ text, Vector2 origin, float scale, Vector4 color);
/** Renders the string with a shadow. */
void DrawShadow(const string@ text, Vector2 origin, float scale, Vector4 color);
}
}
/** Represents a bitmap-based font. */
class Font {
/** Measures the size of the given string. */
Vector2 Measure(const string @text);
/** Renders the string. */
void Draw(const string @text, Vector2 origin, float scale, Vector4 color);
/** Renders the string with a shadow. */
void DrawShadow(const string @text, Vector2 origin, float scale, Vector4 color);
}
}

View File

@ -1,99 +1,98 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** Represents a game world map. */
class GameMap {
/** Creates a new map.
* @param width You must specify 512.
* @param height You must specify 512.
* @param depth You must specify 64.
*/
GameMap(int width, int height, int depth) {}
/** Loads a map from the specified file. */
GameMap(const string@ path) {}
/** Gets the color of the specified voxel. */
uint GetColor(int x, int y, int z) {}
/** Returns if the specified voxel is solid (or air). */
bool IsSolid(int x, int y, int z) {}
/** Gets the color of the specified voxel. */
uint GetColorWrapped(int x, int y, int z) {}
/** Returns if the specified voxel is solid (or air). */
bool IsSolidWrapped(int x, int y, int z) {}
/** Makes the specified voxel non-solid. */
void SetAir(int x, int y, int z) {}
/** Makes the specified voxel solid, and sets its color. */
void SetSolid(int x, int y, int z, uint color) {}
/** Retrieves the width of the map. */
int Width {
get { }
}
/** Retrieves the height of the map. */
int Height {
get { }
}
/** Retrieves the depth of the map. */
int Depth {
get { }
}
bool ClipBox(int x, int y, int z) {}
bool ClipWorld(int x, int y, int z) {}
bool ClipBox(float x, float y, float z) {}
bool ClipWorld(float x, float y, float z) {}
/** Casts a ray. */
GameMapRayCastResult CastRay(Vector3 start, Vector3 direction,
int maxScanSteps);
}
/** GameMapRayCastResult contains the result of the ray-cast. */
class GameMapRayCastResult {
/** true when the ray hit a solid voxel. */
bool hit;
/** true when the start position is in a solid voxel. */
bool startSolid;
/** Position where the ray hit a solid voxel. */
Vector3 hitPos;
/** Coordinate of the voxel that the ray hit. */
IntVector3 hitBlock;
/** Normal of the face that the ray hit. */
IntVector3 normal;
}
}
/** Represents a game world map. */
class GameMap {
/**
* Creates a new map.
* @param width You must specify 512.
* @param height You must specify 512.
* @param depth You must specify 64.
*/
GameMap(int width, int height, int depth) {}
/** Loads a map from the specified file. */
GameMap(const string @path) {}
/** Gets the color of the specified voxel. */
uint GetColor(int x, int y, int z) {}
/** Returns if the specified voxel is solid (or air). */
bool IsSolid(int x, int y, int z) {}
/** Gets the color of the specified voxel. */
uint GetColorWrapped(int x, int y, int z) {}
/** Returns if the specified voxel is solid (or air). */
bool IsSolidWrapped(int x, int y, int z) {}
/** Makes the specified voxel non-solid. */
void SetAir(int x, int y, int z) {}
/** Makes the specified voxel solid, and sets its color. */
void SetSolid(int x, int y, int z, uint color) {}
/** Retrieves the width of the map. */
int Width {
get {}
}
/** Retrieves the height of the map. */
int Height {
get {}
}
/** Retrieves the depth of the map. */
int Depth {
get {}
}
bool ClipBox(int x, int y, int z) {}
bool ClipWorld(int x, int y, int z) {}
bool ClipBox(float x, float y, float z) {}
bool ClipWorld(float x, float y, float z) {}
/** Casts a ray. */
GameMapRayCastResult CastRay(Vector3 start, Vector3 direction, int maxScanSteps);
}
/** GameMapRayCastResult contains the result of the ray-cast. */
class GameMapRayCastResult {
/** true when the ray hit a solid voxel. */
bool hit;
/** true when the start position is in a solid voxel. */
bool startSolid;
/** Position where the ray hit a solid voxel. */
Vector3 hitPos;
/** Coordinate of the voxel that the ray hit. */
IntVector3 hitBlock;
/** Normal of the face that the ray hit. */
IntVector3 normal;
}
}

View File

@ -1,37 +1,39 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** Image is an opaque type which can be passed to rendering methods to
* draw an image quickly. */
class Image {
/** Retrieves the width of the image, in pixels. */
float Width {
get {}
}
/** Retrieves the width of the image, in pixels. */
float Height {
get {}
}
}
}
/**
* Image is an opaque type which can be passed to rendering methods to
* draw an image quickly.
*/
class Image {
/** Retrieves the width of the image, in pixels. */
float Width {
get {}
}
/** Retrieves the width of the image, in pixels. */
float Height {
get {}
}
}
}

View File

@ -1,451 +1,488 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
// FIXME: should be written about math functions of AngelScript add-on
// FIXME: should be written about math functions of AngelScript add-on
namespace spades {
/** Does a linear interpolation. */
float Mix(float a, float b, float f) {}
/** Does a linear interpolation. */
Vector2 Mix(Vector2 a, Vector2 b, float f) {}
/** Does a linear interpolation. */
Vector3 Mix(Vector3 a, Vector3 b, float f) {}
/** Applies an smooth-step function. */
float SmoothStep(float value) {}
/** Retrieves a random value that lies in [0, 1]. */
float GetRandom() {}
/** Represents a 3-component integral vector. */
class IntVector3 {
int x, y, z;
/** Default constructor. */
IntVector3() {}
/** Initializes new instance of IntVector3 with default values given. */
IntVector3(const IntVector3@ other) {}
/** Initializes new instance of IntVector3 with default values given. */
IntVector3(int x, int y, int z) {}
/** Initializes new instance of IntVector3 with default values given. */
IntVector3(const Vector3@ other) {}
/** Adds the given vector to this one, and returns this. */
IntVector3 @opAddAssign(const IntVector3@ other) {}
/** Subtracts the given vector from this one, and returns this. */
IntVector3 @opSubAssign(const IntVector3@ other) {}
/** Multiplies this vector by the given one, and returns this one. */
IntVector3 @opMulAssign(const IntVector3@ other) {}
/** Divides this vector by the given one, and returns this one. */
IntVector3 @opDivAssign(const IntVector3@ other) {}
/** Adds the given vector to this one, and returns a new vector. */
IntVector3 opAdd(const IntVector3@ other) const {}
/** Subtracts the given vector from this one, and returns a new vector. */
IntVector3 opSub(const IntVector3@ other) const {}
/** Multiplies this vector by the given one, and returns a new vector. */
IntVector3 opMul(const IntVector3@ other) const {}
/** Divides this vector by the given one, and returns a new vector. */
IntVector3 opDiv(const IntVector3@ other) const {}
/** Returns the negated vector of this. */
IntVector3 opNeg() const {}
/** Computes a manhattan length of this vector. */
int ManhattanLength {
get const { }
}
/** Computes a chebyshev length of this vector. */
int ChebyshevLength {
get const { }
}
}
/** Computes a dot-product of two vectors. */
int Dot(const IntVector3@, const IntVector3@);
/** Represents a 2-component real vector. */
class Vector2 {
float x, y;
/** Default constructor. */
Vector2() {}
/** Initializes new instance of Vector2 with default values given. */
Vector2(const Vector2@ other) {}
/** Initializes new instance of Vector2 with default values given. */
Vector2(float x, float y) {}
/** Adds the given vector to this one, and returns this. */
Vector2 @opAddAssign(const Vector2@ other) {}
/** Subtracts the given vector from this one, and returns this. */
Vector2 @opSubAssign(const Vector2@ other) {}
/** Multiplies this vector by the given one, and returns this one. */
Vector2 @opMulAssign(const Vector2@ other) {}
/** Divides this vector by the given one, and returns this one. */
Vector2 @opDivAssign(const Vector2@ other) {}
/** Adds the given vector to this one, and returns a new vector. */
Vector2 opAdd(const Vector2@ other) const {}
/** Subtracts the given vector from this one, and returns a new vector. */
Vector2 opSub(const Vector2@ other) const {}
/** Multiplies this vector by the given one, and returns a new vector. */
Vector2 opMul(const Vector2@ other) const {}
/** Divides this vector by the given one, and returns a new vector. */
Vector2 opDiv(const Vector2@ other) const {}
/** Returns the negated vector of this. */
Vector2 opNeg() const {}
/** Returns the normalized vector of this. */
Vector2 Normalized {
get const {}
}
/** Computes a manhattan length of this vector. */
float ManhattanLength {
get const { }
}
/** Computes a chebyshev length of this vector. */
float ChebyshevLength {
get const { }
}
/** Computes an euclidean length of this vector. */
float Length {
get const { }
}
/** Computes the second power of an euclidean length of this vector. */
float LengthPowered {
get const { }
}
}
/** Computes a dot-product of two vectors. */
float Dot(const Vector2@, const Vector2@);
/** Represents a 3-component real vector. */
class Vector3 {
float x, y, z;
/** Default constructor. */
Vector3() {}
/** Initializes new instance of Vector3 with default values given. */
Vector3(const Vector3@ other) {}
/** Initializes new instance of Vector3 with default values given. */
Vector3(float x, float y, float z) {}
/** Initializes new instance of Vector3 with default values given. */
Vector3(const IntVector3@ other) {}
/** Adds the given vector to this one, and returns this. */
Vector3 @opAddAssign(const Vector3@ other) {}
/** Subtracts the given vector from this one, and returns this. */
Vector3 @opSubAssign(const Vector3@ other) {}
/** Multiplies this vector by the given one, and returns this one. */
Vector3 @opMulAssign(const Vector3@ other) {}
/** Divides this vector by the given one, and returns this one. */
Vector3 @opDivAssign(const Vector3@ other) {}
/** Adds the given vector to this one, and returns a new vector. */
Vector3 opAdd(const Vector3@ other) const {}
/** Subtracts the given vector from this one, and returns a new vector. */
Vector3 opSub(const Vector3@ other) const {}
/** Multiplies this vector by the given one, and returns a new vector. */
Vector3 opMul(const Vector3@ other) const {}
/** Divides this vector by the given one, and returns a new vector. */
Vector3 opDiv(const Vector3@ other) const {}
/** Returns the negated vector of this. */
Vector3 opNeg() const {}
/** Returns the normalized vector of this. */
Vector3 Normalized {
get const {}
}
/** Computes a manhattan length of this vector. */
float ManhattanLength {
get const { }
}
/** Computes a chebyshev length of this vector. */
float ChebyshevLength {
get const { }
}
/** Computes an euclidean length of this vector. */
float Length {
get const { }
}
/** Computes the second power of an euclidean length of this vector. */
float LengthPowered {
get const { }
}
}
/** Computes a dot-product of two vectors. */
float Dot(const Vector3@, const Vector3@);
/** Computes a cross-product of two vectors. */
Vector3 Cross(const Vector3@, const Vector3@);
/** Applies the floor function to the given vector, and
* returns the computed one. */
Vector3 Floor(const Vector3@);
/** Applies the ceiling function to the given vector, and
* returns the computed one. */
Vector3 Ceil(const Vector3@);
/** Represents a 4-component real vector. */
class Vector4 {
float x, y, z, w;
/** Default constructor. */
Vector4() {}
/** Initializes new instance of Vector4 with default values given. */
Vector4(const Vector4@ other) {}
/** Initializes new instance of Vector4 with default values given. */
Vector4(float x, float y, float z, float w) {}
/** Initializes new instance of Vector4 with default values given. */
Vector4(const IntVector4@ other) {}
/** Adds the given vector to this one, and returns this. */
Vector4 @opAddAssign(const Vector4@ other) {}
/** Subtracts the given vector from this one, and returns this. */
Vector4 @opSubAssign(const Vector4@ other) {}
/** Multiplies this vector by the given one, and returns this one. */
Vector4 @opMulAssign(const Vector4@ other) {}
/** Divides this vector by the given one, and returns this one. */
Vector4 @opDivAssign(const Vector4@ other) {}
/** Adds the given vector to this one, and returns a new vector. */
Vector4 opAdd(const Vector4@ other) const {}
/** Subtracts the given vector from this one, and returns a new vector. */
Vector4 opSub(const Vector4@ other) const {}
/** Multiplies this vector by the given one, and returns a new vector. */
Vector4 opMul(const Vector4@ other) const {}
/** Divides this vector by the given one, and returns a new vector. */
Vector4 opDiv(const Vector4@ other) const {}
/** Returns the negated vector of this. */
Vector4 opNeg() const {}
/** Returns the normalized vector of this. */
Vector4 Normalized {
get const {}
}
/** Computes a manhattan length of this vector. */
float ManhattanLength {
get const { }
}
/** Computes a chebyshev length of this vector. */
float ChebyshevLength {
get const { }
}
/** Computes an euclidean length of this vector. */
float Length {
get const { }
}
/** Computes the second power of an euclidean length of this vector. */
float LengthPowered {
get const { }
}
}
/** Computes a dot-product of two vectors. */
float Dot(const Vector4@, const Vector4@);
/** Applies the floor function to the given vector, and
* returns the computed one. */
Vector4 Floor(const Vector4@);
/** Applies the ceiling function to the given vector, and
* returns the computed one. */
Vector4 Ceil(const Vector4@);
/** Represents column-major 4x4 matrix. */
class Matrix4 {
private float m00, m10, m20, m30;
private float m01, m11, m21, m31;
private float m02, m12, m22, m32;
private float m03, m13, m23, m33;
/** Default constructor. */
Matrix4() {}
/** Copy constructor. */
Matrix4(const Matrix4@ other) {}
/** Initializes Matrix4 with the given values. */
Matrix4(float m00, float m10, float m20, float m30,
float m01, float m11, float m21, float m31,
float m02, float m12, float m22, float m32,
float m03, float m13, float m23, float m33) {}
/** Multiplies this matrix by the given one, and returns this one. */
Matrix4 @opMulAssign(const Matrix4@ other) {}
/** Multiplies this matrix by the given one, and returns a matrix. */
Matrix4 opMul(const Matrix4@ other) {}
/** Multiplies this matrix by the given vector, and returns a vector. */
Vector4 opMul(const Vector4@ other) {}
/** Multiplies this matrix by the vector [x, y, z, 1], and returns
* a 3-component vector, discarding the fourth component. */
Vector3 opMul(const Vector3@ other) {}
/** Returns the transformed position of the vector [0, 0, 0]. */
Vector3 GetOrigin() const {}
/** Returns the transformed orientation of the specified axis.
* @param axis 0 for X-axis, 1 for Y-axis, and 2 for Z-axis. */
Vector3 GetAxis(int axis) const {}
/** Returns the transposed matrix. */
Matrix4 Transposed {
get const {}
}
/** Returns the inverted matrix.
* This operation works in O(N^3). */
Matrix4 Inverted {
get const {}
}
/** Returns the inverted matrix of an orthogonal one. */
Matrix4 InvertedFast {
get const {}
}
}
/** Creates an matrix that can be used to translate points by the
* specified displacement vector. */
Matrix4 CreateTranslateMatrix(Vector3 displacement) {}
/** Creates an matrix that can be used to translate points by the
* specified displacement vector. */
Matrix4 CreateTranslateMatrix(float x, float y, float z) {}
/** Creates an matrix that can be used to rotate points by the
* specified axis and rotation angle. */
Matrix4 CreateRotateMatrix(Vector3 axis, float radians) {}
/** Creates an matrix that can be used to scale points by the
* specified vector. */
Matrix4 CreateScaleMatrix(Vector3 factor) {}
/** Creates an matrix that can be used to scale points by the
* specified vector. */
Matrix4 CreateScaleMatrix(float x, float y, float z) {}
/** Creates an matrix that can be used to scale points by the
* specified factor. */
Matrix4 CreateScaleMatrix(float factor) {}
/** Creates an matrix using the given axis vector. */
Matirx4 CreateMatrixFromAxes(Vector3 axisX, Vector3 axisY, Vector3 axisZ,
Vector3 origin);
/** Represents a two-dimensional AABB (axis-aligned bounding box). */
class AABB2 {
Vector2 min, max;
float minX { get const {} set {} }
float maxX { get const {} set {} }
float minY { get const {} set {} }
float maxY { get const {} set {} }
/** Default constructor. */
AABB2() {}
/** Copy constructor. */
AABB2(const AABB2@) {}
/** Initializes AABB2 with the top-left coordinate and the
* dimensions of the bounding box. */
AABB2(float left, float top, float width, float height) {}
/** Initializes AABB2 with the top-left coordinate and the
* bottom-right one. */
AABB2(Vector2 min, Vector2 max) {}
/** Checks if the given vector is in the bounding box. */
bool Contains(const Vector2@ point) {}
/** Checks if the given box intersects with this one. */
bool Intersects(const AABB2@ box) {}
/** Extends this bounding box to include the given point. */
void Add(const Vector2@ point) {}
/** Extends this bounding box to include the given one. */
void Add(const AABB2@ box) {}
}
/** Does a linear interpolation. */
float Mix(float a, float b, float f) {}
/** Does a linear interpolation. */
Vector2 Mix(Vector2 a, Vector2 b, float f) {}
/** Does a linear interpolation. */
Vector3 Mix(Vector3 a, Vector3 b, float f) {}
/** Applies an smooth-step function. */
float SmoothStep(float value) {}
/** Retrieves a random value that lies in [0, 1]. */
float GetRandom() {}
/** Represents a 3-component integral vector. */
class IntVector3 {
int x, y, z;
/** Default constructor. */
IntVector3() {}
/** Initializes new instance of IntVector3 with default values given. */
IntVector3(const IntVector3 @other) {}
/** Initializes new instance of IntVector3 with default values given. */
IntVector3(int x, int y, int z) {}
/** Initializes new instance of IntVector3 with default values given. */
IntVector3(const Vector3 @other) {}
/** Adds the given vector to this one, and returns this. */
IntVector3 @opAddAssign(const IntVector3 @other) {}
/** Subtracts the given vector from this one, and returns this. */
IntVector3 @opSubAssign(const IntVector3 @other) {}
/** Multiplies this vector by the given one, and returns this one. */
IntVector3 @opMulAssign(const IntVector3 @other) {}
/** Divides this vector by the given one, and returns this one. */
IntVector3 @opDivAssign(const IntVector3 @other) {}
/** Adds the given vector to this one, and returns a new vector. */
IntVector3 opAdd(const IntVector3 @other) const {}
/** Subtracts the given vector from this one, and returns a new vector. */
IntVector3 opSub(const IntVector3 @other) const {}
/** Multiplies this vector by the given one, and returns a new vector. */
IntVector3 opMul(const IntVector3 @other) const {}
/** Divides this vector by the given one, and returns a new vector. */
IntVector3 opDiv(const IntVector3 @other) const {}
/** Returns the negated vector of this. */
IntVector3 opNeg() const {}
/** Computes a manhattan length of this vector. */
int ManhattanLength {
get const {}
}
/** Computes a chebyshev length of this vector. */
int ChebyshevLength {
get const {}
}
}
/** Computes a dot-product of two vectors. */
int Dot(const IntVector3 @, const IntVector3 @);
/** Represents a 2-component real vector. */
class Vector2 {
float x, y;
/** Default constructor. */
Vector2() {}
/** Initializes new instance of Vector2 with default values given. */
Vector2(const Vector2 @other) {}
/** Initializes new instance of Vector2 with default values given. */
Vector2(float x, float y) {}
/** Adds the given vector to this one, and returns this. */
Vector2 @opAddAssign(const Vector2 @other) {}
/** Subtracts the given vector from this one, and returns this. */
Vector2 @opSubAssign(const Vector2 @other) {}
/** Multiplies this vector by the given one, and returns this one. */
Vector2 @opMulAssign(const Vector2 @other) {}
/** Divides this vector by the given one, and returns this one. */
Vector2 @opDivAssign(const Vector2 @other) {}
/** Adds the given vector to this one, and returns a new vector. */
Vector2 opAdd(const Vector2 @other) const {}
/** Subtracts the given vector from this one, and returns a new vector. */
Vector2 opSub(const Vector2 @other) const {}
/** Multiplies this vector by the given one, and returns a new vector. */
Vector2 opMul(const Vector2 @other) const {}
/** Divides this vector by the given one, and returns a new vector. */
Vector2 opDiv(const Vector2 @other) const {}
/** Returns the negated vector of this. */
Vector2 opNeg() const {}
/** Returns the normalized vector of this. */
Vector2 Normalized {
get const {}
}
/** Computes a manhattan length of this vector. */
float ManhattanLength {
get const {}
}
/** Computes a chebyshev length of this vector. */
float ChebyshevLength {
get const {}
}
/** Computes an euclidean length of this vector. */
float Length {
get const {}
}
/** Computes the second power of an euclidean length of this vector. */
float LengthPowered {
get const {}
}
}
/** Computes a dot-product of two vectors. */
float Dot(const Vector2 @, const Vector2 @);
/** Represents a 3-component real vector. */
class Vector3 {
float x, y, z;
/** Default constructor. */
Vector3() {}
/** Initializes new instance of Vector3 with default values given. */
Vector3(const Vector3 @other) {}
/** Initializes new instance of Vector3 with default values given. */
Vector3(float x, float y, float z) {}
/** Initializes new instance of Vector3 with default values given. */
Vector3(const IntVector3 @other) {}
/** Adds the given vector to this one, and returns this. */
Vector3 @opAddAssign(const Vector3 @other) {}
/** Subtracts the given vector from this one, and returns this. */
Vector3 @opSubAssign(const Vector3 @other) {}
/** Multiplies this vector by the given one, and returns this one. */
Vector3 @opMulAssign(const Vector3 @other) {}
/** Divides this vector by the given one, and returns this one. */
Vector3 @opDivAssign(const Vector3 @other) {}
/** Adds the given vector to this one, and returns a new vector. */
Vector3 opAdd(const Vector3 @other) const {}
/** Subtracts the given vector from this one, and returns a new vector. */
Vector3 opSub(const Vector3 @other) const {}
/** Multiplies this vector by the given one, and returns a new vector. */
Vector3 opMul(const Vector3 @other) const {}
/** Divides this vector by the given one, and returns a new vector. */
Vector3 opDiv(const Vector3 @other) const {}
/** Returns the negated vector of this. */
Vector3 opNeg() const {}
/** Returns the normalized vector of this. */
Vector3 Normalized {
get const {}
}
/** Computes a manhattan length of this vector. */
float ManhattanLength {
get const {}
}
/** Computes a chebyshev length of this vector. */
float ChebyshevLength {
get const {}
}
/** Computes an euclidean length of this vector. */
float Length {
get const {}
}
/** Computes the second power of an euclidean length of this vector. */
float LengthPowered {
get const {}
}
}
/** Computes a dot-product of two vectors. */
float Dot(const Vector3 @, const Vector3 @);
/** Computes a cross-product of two vectors. */
Vector3 Cross(const Vector3 @, const Vector3 @);
/**
* Applies the floor function to the given vector, and
* returns the computed one.
*/
Vector3 Floor(const Vector3 @);
/**
* Applies the ceiling function to the given vector, and
* returns the computed one.
*/
Vector3 Ceil(const Vector3 @);
/** Represents a 4-component real vector. */
class Vector4 {
float x, y, z, w;
/** Default constructor. */
Vector4() {}
/** Initializes new instance of Vector4 with default values given. */
Vector4(const Vector4 @other) {}
/** Initializes new instance of Vector4 with default values given. */
Vector4(float x, float y, float z, float w) {}
/** Initializes new instance of Vector4 with default values given. */
Vector4(const IntVector4 @other) {}
/** Adds the given vector to this one, and returns this. */
Vector4 @opAddAssign(const Vector4 @other) {}
/** Subtracts the given vector from this one, and returns this. */
Vector4 @opSubAssign(const Vector4 @other) {}
/** Multiplies this vector by the given one, and returns this one. */
Vector4 @opMulAssign(const Vector4 @other) {}
/** Divides this vector by the given one, and returns this one. */
Vector4 @opDivAssign(const Vector4 @other) {}
/** Adds the given vector to this one, and returns a new vector. */
Vector4 opAdd(const Vector4 @other) const {}
/** Subtracts the given vector from this one, and returns a new vector. */
Vector4 opSub(const Vector4 @other) const {}
/** Multiplies this vector by the given one, and returns a new vector. */
Vector4 opMul(const Vector4 @other) const {}
/** Divides this vector by the given one, and returns a new vector. */
Vector4 opDiv(const Vector4 @other) const {}
/** Returns the negated vector of this. */
Vector4 opNeg() const {}
/** Returns the normalized vector of this. */
Vector4 Normalized {
get const {}
}
/** Computes a manhattan length of this vector. */
float ManhattanLength {
get const {}
}
/** Computes a chebyshev length of this vector. */
float ChebyshevLength {
get const {}
}
/** Computes an euclidean length of this vector. */
float Length {
get const {}
}
/** Computes the second power of an euclidean length of this vector. */
float LengthPowered {
get const {}
}
}
/** Computes a dot-product of two vectors. */
float Dot(const Vector4 @, const Vector4 @);
/**
* Applies the floor function to the given vector, and
* returns the computed one.
*/
Vector4 Floor(const Vector4 @);
/**
* Applies the ceiling function to the given vector, and
* returns the computed one.
*/
Vector4 Ceil(const Vector4 @);
/** Represents column-major 4x4 matrix. */
class Matrix4 {
private float m00, m10, m20, m30;
private float m01, m11, m21, m31;
private float m02, m12, m22, m32;
private float m03, m13, m23, m33;
/** Default constructor. */
Matrix4() {}
/** Copy constructor. */
Matrix4(const Matrix4 @other) {}
/** Initializes Matrix4 with the given values. */
Matrix4(float m00, float m10, float m20, float m30, float m01, float m11, float m21,
float m31, float m02, float m12, float m22, float m32, float m03, float m13,
float m23, float m33) {}
/** Multiplies this matrix by the given one, and returns this one. */
Matrix4 @opMulAssign(const Matrix4 @other) {}
/** Multiplies this matrix by the given one, and returns a matrix. */
Matrix4 opMul(const Matrix4 @other) {}
/** Multiplies this matrix by the given vector, and returns a vector. */
Vector4 opMul(const Vector4 @other) {}
/**
* Multiplies this matrix by the vector [x, y, z, 1], and returns
* a 3-component vector, discarding the fourth component.
*/
Vector3 opMul(const Vector3 @other) {}
/** Returns the transformed position of the vector [0, 0, 0]. */
Vector3 GetOrigin() const {}
/**
* Returns the transformed orientation of the specified axis.
* @param axis 0 for X-axis, 1 for Y-axis, and 2 for Z-axis.
*/
Vector3 GetAxis(int axis) const {}
/** Returns the transposed matrix. */
Matrix4 Transposed {
get const {}
}
/**
* Returns the inverted matrix.
* This operation works in O(N^3).
*/
Matrix4 Inverted {
get const {}
}
/** Returns the inverted matrix of an orthogonal one. */
Matrix4 InvertedFast {
get const {}
}
}
/**
* Creates an matrix that can be used to translate points by the
* specified displacement vector.
*/
Matrix4 CreateTranslateMatrix(Vector3 displacement) {}
/**
* Creates an matrix that can be used to translate points by the
* specified displacement vector.
*/
Matrix4 CreateTranslateMatrix(float x, float y, float z) {}
/**
* Creates an matrix that can be used to rotate points by the
* specified axis and rotation angle.
*/
Matrix4 CreateRotateMatrix(Vector3 axis, float radians) {}
/**
* Creates an matrix that can be used to scale points by the
* specified vector.
*/
Matrix4 CreateScaleMatrix(Vector3 factor) {}
/**
* Creates an matrix that can be used to scale points by the
* specified vector.
*/
Matrix4 CreateScaleMatrix(float x, float y, float z) {}
/**
* Creates an matrix that can be used to scale points by the
* specified factor.
*/
Matrix4 CreateScaleMatrix(float factor) {}
/** Creates an matrix using the given axis vector. */
Matirx4 CreateMatrixFromAxes(Vector3 axisX, Vector3 axisY, Vector3 axisZ, Vector3 origin);
/** Represents a two-dimensional AABB (axis-aligned bounding box). */
class AABB2 {
Vector2 min, max;
float minX {
get const {}
set {}
}
float maxX {
get const {}
set {}
}
float minY {
get const {}
set {}
}
float maxY {
get const {}
set {}
}
/** Default constructor. */
AABB2() {}
/** Copy constructor. */
AABB2(const AABB2 @) {}
/**
* Initializes AABB2 with the top-left coordinate and the
* dimensions of the bounding box.
*/
AABB2(float left, float top, float width, float height) {}
/**
* Initializes AABB2 with the top-left coordinate and the
* bottom-right one.
*/
AABB2(Vector2 min, Vector2 max) {}
/** Checks if the given vector is in the bounding box. */
bool Contains(const Vector2 @point) {}
/** Checks if the given box intersects with this one. */
bool Intersects(const AABB2 @box) {}
/** Extends this bounding box to include the given point. */
void Add(const Vector2 @point) {}
/** Extends this bounding box to include the given one. */
void Add(const AABB2 @box) {}
}
}

View File

@ -1,29 +1,29 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** Model is an opaque type which can be passed to rendering methods to
* draw an three-dimensional model. */
class Model {
}
}
/**
* Model is an opaque type which can be passed to rendering methods to
* draw an three-dimensional model.
*/
class Model {}
}

View File

@ -1,208 +1,235 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** Renderer is an interface to the display device. */
class Renderer {
/** Initializes the renderer for 3D scene rendering. */
void Init() {}
/** Shuts down the renderer. */
void Shutdown() {}
/** Loads an image from the specified path or load one from
* the cache, if exists.
* @param path file-system path. */
Image@ RegisterImage(const string@ path) {}
/** Loads an model from the specified path or load one from
* the cache, if exists.
* @param path file-system path. */
Model@ RegisterModel(const string@ path) {}
/** Creates an image from the specified bitmap. */
Image@ CreateImage(Bitmap@ bitmap) {}
/** Creates an model from the specified voxel model. */
Model@ CreateModel(VoxelModel@ voxelmap) {}
/** Sets a game world map. */
GameMap@ GameMap {
set {}
}
/** Changes the fog end distance (not supported). */
float FogDistance {
set {}
}
/** Changes the color of fog. */
Vector3 FogColor {
set {}
}
/** Sets a color that is used for drawing.
* @deprecated Do not use this virtual property.
* Some methods treat this value as an alpha premultiplied,
* while others treat this value has a straight alpha. */
Vector4 Color {
set { }
}
/** Sets a opaque color that is used for drawing. */
Vector3 ColorOpaque {
set { }
}
/** Sets a color that is used for drawing. The color value is
* alpha premultiplied. */
Vector4 ColorP {
set { }
}
/** Sets a color that is used for drawing. The color value is
* alpha non-premultiplied (straight alpha). */
Vector4 ColorNP {
set { }
}
/** Starts a 3D scene rendering. */
void StartScene(const SceneDefinition@) {}
/** Adds a dynamic light to the scene.
* This should be called between StartScene and EndScene. */
void AddLight(const DynamicLightParam@) {}
/** Adds a model to the scene.
* This should be called between StartScene and EndScene. */
void AddModel(Model@, const ModelRenderParam@) {}
/** Adds a line for debugging.
* This should be called between StartScene and EndScene. */
void AddDebugLine(const Vector3@ pt1, const Vector3@ pt2,
const Vector4@ color) {}
/** Adds a sprite.
* This should be called between StartScene and EndScene.
* The color is specified using the property `Color` with
* alpha values premultiplied. */
void AddSprite(Image@, const Vector3@ origin, float radius,
float rotateRadians) {}
/** Adds a long-sprite.
* This should be called between StartScene and EndScene.
* The color is specified using the property `Color` with
* alpha values premultiplied. */
void AddLongSprite(Image@, const Vector3@ pt1, const Vector3@ pt2, float radius) {}
/** Ends a 3D scene rendering. */
void EndScene() {}
/** Multiplies color of the screen by the specified color.
* This should never be called between StartScene and EndScene. */
void MultiplyScreenColor(Vector3 color) {}
/** Draws a 2D image.
* This should never be called between StartScene and EndScene. */
void DrawImage(Image@, const Vector2@ topLeft) {}
/** Draws a 2D image.
* This should never be called between StartScene and EndScene. */
void DrawImage(Image@, const AABB2@ outRect) {}
/** Draws a 2D image.
* This should never be called between StartScene and EndScene. */
void DrawImage(Image@, const AABB2@ outRect, const AABB2@ inRect) {}
/** Draws a 2D image.
* This should never be called between StartScene and EndScene. */
void DrawImage(Image@,
const Vector2@ outTopLeft, const Vector2@ outTopRight,
const Vector2@ outBottomLeft, const AABB2@ inRect) {}
/** Finalizes the drawing. */
void FrameDone();
/** Transfers the rendered image to the user's display. */
void Flip();
/** Reads the rendered image to a bitmap. */
Bitmap@ ReadBitmap();
/** Retrieves the width of the screen, in pixels. */
float ScreenWidth {
get {}
}
/** Retrieves the height of the screen, in pixels. */
float ScreenHeight {
get {}
}
}
class SceneDefinition {
int viewportLeft, viewportTop;
int viewportWidth, viewportHeight;
float fovX, fovY;
Vector3 viewOrigin;
Vector3 viewAxisX;
Vector3 viewAxisY;
Vector3 viewAxisZ;
float zNear, zFar;
bool skipWorld;
uint time;
float depthOfFieldFocalLength;
float depthOfFieldNearBlurStrength;
float depthOfFieldFarBlurStrength;
bool denyCameraBlur;
float blurVignette;
}
class ModelRenderParam {
Matrix4 matrix;
Vector3 customColor;
bool depthHack;
bool castShadow;
bool unlit;
}
class DynamicLightParam {
DynamicLightType type;
Vector3 origin;
float radius;
Vector3 color;
Vector3 spotAxisX;
Vector3 spotAxisY;
Vector3 spotAxisZ;
Image@ image;
float spotAngle;
bool useLensFlare;
}
}
/** Renderer is an interface to the display device. */
class Renderer {
/** Initializes the renderer for 3D scene rendering. */
void Init() {}
/** Shuts down the renderer. */
void Shutdown() {}
/**
* Loads an image from the specified path or load one from
* the cache, if exists.
* @param path file-system path.
*/
Image @RegisterImage(const string @path) {}
/**
* Loads an model from the specified path or load one from
* the cache, if exists.
* @param path file-system path.
*/
Model @RegisterModel(const string @path) {}
/** Creates an image from the specified bitmap. */
Image @CreateImage(Bitmap @bitmap) {}
/** Creates an model from the specified voxel model. */
Model @CreateModel(VoxelModel @voxelmap) {}
/** Sets a game world map. */
GameMap @GameMap {
set {}
}
/** Changes the fog end distance (not supported). */
float FogDistance {
set {}
}
/** Changes the color of fog. */
Vector3 FogColor {
set {}
}
/**
* Sets a color that is used for drawing.
* @deprecated Do not use this virtual property.
* Some methods treat this value as an alpha premultiplied,
* while others treat this value has a straight alpha.
*/
Vector4 Color {
set {}
}
/** Sets a opaque color that is used for drawing. */
Vector3 ColorOpaque {
set {}
}
/**
* Sets a color that is used for drawing. The color value is
* alpha premultiplied.
*/
Vector4 ColorP {
set {}
}
/**
* Sets a color that is used for drawing. The color value is
* alpha non-premultiplied (straight alpha).
*/
Vector4 ColorNP {
set {}
}
/** Starts a 3D scene rendering. */
void StartScene(const SceneDefinition @) {}
/**
* Adds a dynamic light to the scene.
* This should be called between StartScene and EndScene.
*/
void AddLight(const DynamicLightParam @) {}
/**
* Adds a model to the scene.
* This should be called between StartScene and EndScene.
*/
void AddModel(Model @, const ModelRenderParam @) {}
/**
* Adds a line for debugging.
* This should be called between StartScene and EndScene.
*/
void AddDebugLine(const Vector3 @pt1, const Vector3 @pt2, const Vector4 @color) {}
/**
* Adds a sprite.
* This should be called between StartScene and EndScene.
* The color is specified using the property `Color` with
* alpha values premultiplied.
*/
void AddSprite(Image @, const Vector3 @origin, float radius, float rotateRadians) {}
/**
* Adds a long-sprite.
* This should be called between StartScene and EndScene.
* The color is specified using the property `Color` with
* alpha values premultiplied.
*/
void AddLongSprite(Image @, const Vector3 @pt1, const Vector3 @pt2, float radius) {}
/** Ends a 3D scene rendering. */
void EndScene() {}
/**
* Multiplies color of the screen by the specified color.
* This should never be called between StartScene and EndScene.
*/
void MultiplyScreenColor(Vector3 color) {}
/**
* Draws a 2D image.
* This should never be called between StartScene and EndScene.
*/
void DrawImage(Image @, const Vector2 @topLeft) {}
/**
* Draws a 2D image.
* This should never be called between StartScene and EndScene.
*/
void DrawImage(Image @, const AABB2 @outRect) {}
/**
* Draws a 2D image.
* This should never be called between StartScene and EndScene.
*/
void DrawImage(Image @, const AABB2 @outRect, const AABB2 @inRect) {}
/**
* Draws a 2D image.
* This should never be called between StartScene and EndScene.
*/
void DrawImage(Image @, const Vector2 @outTopLeft, const Vector2 @outTopRight,
const Vector2 @outBottomLeft, const AABB2 @inRect) {}
/** Finalizes the drawing. */
void FrameDone();
/** Transfers the rendered image to the user's display. */
void Flip();
/** Reads the rendered image to a bitmap. */
Bitmap @ReadBitmap();
/** Retrieves the width of the screen, in pixels. */
float ScreenWidth {
get {}
}
/** Retrieves the height of the screen, in pixels. */
float ScreenHeight {
get {}
}
}
class SceneDefinition {
int viewportLeft, viewportTop;
int viewportWidth, viewportHeight;
float fovX, fovY;
Vector3 viewOrigin;
Vector3 viewAxisX;
Vector3 viewAxisY;
Vector3 viewAxisZ;
float zNear, zFar;
bool skipWorld;
uint time;
float depthOfFieldFocalLength;
float depthOfFieldNearBlurStrength;
float depthOfFieldFarBlurStrength;
bool denyCameraBlur;
float blurVignette;
}
class ModelRenderParam {
Matrix4 matrix;
Vector3 customColor;
bool depthHack;
bool castShadow;
bool unlit;
}
class DynamicLightParam {
DynamicLightType type;
Vector3 origin;
float radius;
Vector3 color;
Vector3 spotAxisX;
Vector3 spotAxisY;
Vector3 spotAxisZ;
Image @image;
float spotAngle;
bool useLensFlare;
}
}

View File

@ -1,32 +1,32 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** Raises an exception, usually resulting a program crash. */
void Raise(const string& description) {}
/** Asserts the expression is true. */
void Assert(bool cond) {}
/** Raises 'not implemented' exception. */
void NotImplemented() {}
}
/** Raises an exception, usually resulting a program crash. */
void Raise(const string &description) {}
/** Asserts the expression is true. */
void Assert(bool cond) {}
/** Raises 'not implemented' exception. */
void NotImplemented() {}
}

View File

@ -1,36 +1,33 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** Replaces any occurrence of the pattern string with another string. */
string Replace(const string@ str,
const string@ pattern,
const string@ after) {}
/** Removes preceding/following white-spaces. */
string TrimSpaces(const string@ input) {}
string ToString(int) {}
string ToString(double) {}
}
/** Replaces any occurrence of the pattern string with another string. */
string Replace(const string @str, const string @pattern, const string @after) {}
/** Removes preceding/following white-spaces. */
string TrimSpaces(const string @input) {}
string ToString(int) {}
string ToString(double) {}
}

View File

@ -1,65 +1,65 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** Represents a small voxel model. */
class VoxelModel {
/** Creates a new voxel model.
* @param width Width of the voxel model.
* @param height Height of the voxel model.
* @param depth Depth of the voxel model, which must be <= 64.
*/
GameMap(int width, int height, int depth) {}
/** Loads a voxel model from the specified file. */
GameMap(const string@ path) {}
/** Gets the color of the specified voxel. */
uint GetColor(int x, int y, int z) {}
/** Returns if the specified voxel is solid (or air). */
bool IsSolid(int x, int y, int z) {}
/** Makes the specified voxel non-solid. */
void SetAir(int x, int y, int z) {}
/** Makes the specified voxel solid, and sets its color. */
void SetSolid(int x, int y, int z, uint color) {}
/** Retrieves the width of the voxel model. */
int Width {
get { }
}
/** Retrieves the height of the voxel model. */
int Height {
get { }
}
/** Retrieves the depth of the voxel model. */
int Depth {
get { }
}
}
}
/** Represents a small voxel model. */
class VoxelModel {
/**
* Creates a new voxel model.
* @param width Width of the voxel model.
* @param height Height of the voxel model.
* @param depth Depth of the voxel model, which must be <= 64.
*/
GameMap(int width, int height, int depth) {}
/** Loads a voxel model from the specified file. */
GameMap(const string @path) {}
/** Gets the color of the specified voxel. */
uint GetColor(int x, int y, int z) {}
/** Returns if the specified voxel is solid (or air). */
bool IsSolid(int x, int y, int z) {}
/** Makes the specified voxel non-solid. */
void SetAir(int x, int y, int z) {}
/** Makes the specified voxel solid, and sets its color. */
void SetSolid(int x, int y, int z, uint color) {}
/** Retrieves the width of the voxel model. */
int Width {
get {}
}
/** Retrieves the height of the voxel model. */
int Height {
get {}
}
/** Retrieves the depth of the voxel model. */
int Depth {
get {}
}
}
}

View File

@ -1,34 +1,38 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** A skin of blocks held in hands. A class that implements
* this might also have to implement either IThirdPersonToolSkin
* or IViewToolSkin. */
interface IBlockSkin {
/** Receives a ready state. 0 = soon after placing a block,
* >=1 = ready to place a block. */
float ReadyState { set; }
Vector3 BlockColor { set; }
}
/**
* A skin of blocks held in hands. A class that implements
* this might also have to implement either IThirdPersonToolSkin
* or IViewToolSkin.
*/
interface IBlockSkin {
/**
* Receives a ready state. 0 = soon after placing a block,
* >=1 = ready to place a block.
*/
float ReadyState { set; }
Vector3 BlockColor { set; }
}
}

View File

@ -1,36 +1,42 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** A skin of grenades. A class that implements
* this might also have to implement either IThirdPersonToolSkin
* or IViewToolSkin. */
interface IGrenadeSkin {
/** Receives a ready state. 0 = soon after placing a block,
* >=1 = ready to place a block. */
float ReadyState { set; }
/** Receives how long a player is cooking the grenade.
* 0 if the player isn't cooking a grenade. */
float CookTime { set; }
}
/**
* A skin of grenades. A class that implements
* this might also have to implement either IThirdPersonToolSkin
* or IViewToolSkin.
*/
interface IGrenadeSkin {
/**
* Receives a ready state. 0 = soon after placing a block,
* >=1 = ready to place a block.
*/
float ReadyState { set; }
/**
* Receives how long a player is cooking the grenade.
* 0 if the player isn't cooking a grenade.
*/
float CookTime { set; }
}
}

View File

@ -1,41 +1,40 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** Action what a user doing with his/her spade. */
enum SpadeActionType {
Idle,
Bash,
Dig,
DigStart
}
/** A skin of spades. A class that implements this might also have to
* implement either IThirdPersonToolSkin or IViewToolSkin. */
interface ISpadeSkin {
SpadeActionType ActionType { set; }
/** Receives an action progress. 0 = soon after swinging,
* 1 = ready for the next swing. */
float ActionProgress { set; }
}
/** Action what a user doing with his/her spade. */
enum SpadeActionType { Idle, Bash, Dig, DigStart }
/**
* A skin of spades. A class that implements this might also have to
* implement either IThirdPersonToolSkin or IViewToolSkin.
*/
interface ISpadeSkin {
SpadeActionType ActionType { set; }
/**
* Receives an action progress. 0 = soon after swinging,
* 1 = ready for the next swing.
*/
float ActionProgress { set; }
}
}

View File

@ -1,34 +1,35 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** A skin of all tools for third-person view. A class that implements
* this might also have to implement IToolSkin. */
interface IThirdPersonToolSkin {
/** Receives a transform matrix from tool coordinate to world one. */
Matrix4 OriginMatrix { set; }
float PitchBias { get; }
}
/**
* A skin of all tools for third-person view. A class that implements
* this might also have to implement IToolSkin.
*/
interface IThirdPersonToolSkin {
/** Receives a transform matrix from tool coordinate to world one. */
Matrix4 OriginMatrix { set; }
float PitchBias { get; }
}
}

View File

@ -1,48 +1,51 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** A skin of all tools for third-person view. */
interface IToolSkin {
/** Receives a value that indicates whether the owner of the tool is sprinting.
* 0 = not sprinting, 1 = sprinting. */
float SprintState { set; }
/** Receives a value that indicates whether this tool is raised.
* 0 = brought down, 1 = raised. */
float RaiseState { set; }
/** Receives the team color. */
Vector3 TeamColor { set; }
/** Receives whether this skin should play a sound. */
bool IsMuted { set; }
/** Advances the animation by the specified time span. */
void Update(float dt);
/** Issues draw commands to add models of this tool to the scene. */
void AddToScene();
}
/** A skin of all tools for third-person view. */
interface IToolSkin {
/**
* Receives a value that indicates whether the owner of the tool is
* sprinting. 0 = not sprinting, 1 = sprinting.
*/
float SprintState { set; }
/**
* Receives a value that indicates whether this tool is raised.
* 0 = brought down, 1 = raised.
*/
float RaiseState { set; }
/** Receives the team color. */
Vector3 TeamColor { set; }
/** Receives whether this skin should play a sound. */
bool IsMuted { set; }
/** Advances the animation by the specified time span. */
void Update(float dt);
/** Issues draw commands to add models of this tool to the scene. */
void AddToScene();
}
}

View File

@ -1,41 +1,43 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** A skin of all tools for first-person view. A class that implements
* this might also have to implement IToolSkin. */
interface IViewToolSkin {
/** Receives a transform matrix from view coordinate to world one. */
Matrix4 EyeMatrix { set; }
/** Receives a swing offset that varies with a player movement. */
Vector3 Swing { set; }
/** Returns positions for player hands in view coordinate. */
Vector3 LeftHandPosition { get; }
Vector3 RightHandPosition { get; }
/** Issues draw commands to draw 2d images, such as HUD and crosshair. */
void Draw2D();
}
/**
* A skin of all tools for first-person view. A class that implements
* this might also have to implement IToolSkin.
*/
interface IViewToolSkin {
/** Receives a transform matrix from view coordinate to world one. */
Matrix4 EyeMatrix { set; }
/** Receives a swing offset that varies with a player movement. */
Vector3 Swing { set; }
/** Returns positions for player hands in view coordinate. */
Vector3 LeftHandPosition { get; }
Vector3 RightHandPosition { get; }
/** Issues draw commands to draw 2d images, such as HUD and crosshair. */
void Draw2D();
}
}

View File

@ -1,55 +1,63 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
/** A skin of weapons. A class that implements
* this might also have to implement either IThirdPersonToolSkin
* or IViewToolSkin. */
interface IWeaponSkin {
/** Receives a ready state. 0 = soon after firing,
* >=1 = ready to fire the next bullet. */
float ReadyState { set; }
/** 0 = normal, 1 = aiming down the sight. */
float AimDownSightState { set; }
/** true if player is reloading a weapon */
bool IsReloading { set; }
/** 0 = reload has started, 1 = done */
float ReloadProgress { set; }
int Ammo { set; }
int ClipSize { set; }
/** Called when a player fired the weapon. */
void WeaponFired();
/** Called when a player started reloading the weapon.
* For shotgun, this is called for every pellets. */
void ReloadingWeapon();
/** Called when a played reloaded the weapon.
* For shotgun, this is called for every pellets. */
void ReloadedWeapon();
}
/**
* A skin of weapons. A class that implements
* this might also have to implement either IThirdPersonToolSkin
* or IViewToolSkin.
*/
interface IWeaponSkin {
/**
* Receives a ready state. 0 = soon after firing,
* >=1 = ready to fire the next bullet.
*/
float ReadyState { set; }
/** 0 = normal, 1 = aiming down the sight. */
float AimDownSightState { set; }
/** true if player is reloading a weapon */
bool IsReloading { set; }
/** 0 = reload has started, 1 = done */
float ReloadProgress { set; }
int Ammo { set; }
int ClipSize { set; }
/** Called when a player fired the weapon. */
void WeaponFired();
/**
* Called when a player started reloading the weapon.
* For shotgun, this is called for every pellets.
*/
void ReloadingWeapon();
/**
* Called when a played reloaded the weapon.
* For shotgun, this is called for every pellets.
*/
void ReloadedWeapon();
}
}

View File

@ -19,228 +19,197 @@
*/
namespace spades {
class BasicViewWeapon:
IToolSkin, IViewToolSkin, IWeaponSkin, IWeaponSkin2 {
// IToolSkin
protected float sprintState;
protected float raiseState;
protected Vector3 teamColor;
protected bool muted;
class BasicViewWeapon : IToolSkin, IViewToolSkin, IWeaponSkin, IWeaponSkin2 {
// IToolSkin
protected float sprintState;
protected float raiseState;
protected Vector3 teamColor;
protected bool muted;
float SprintState {
set { sprintState = value; }
get { return sprintState; }
}
float SprintState {
set { sprintState = value; }
get { return sprintState; }
}
float RaiseState {
set { raiseState = value; }
get { return raiseState; }
}
float RaiseState {
set { raiseState = value; }
get { return raiseState; }
}
Vector3 TeamColor {
set { teamColor = value; }
get { return teamColor; }
}
Vector3 TeamColor {
set { teamColor = value; }
get { return teamColor; }
}
bool IsMuted {
set { muted = value; }
get { return muted; }
}
bool IsMuted {
set { muted = value; }
get { return muted; }
}
// IWeaponSkin
// IWeaponSkin
protected float aimDownSightState;
protected float aimDownSightStateSmooth;
protected float readyState;
protected bool reloading;
protected float reloadProgress;
protected int ammo, clipSize;
protected float localFireVibration;
protected float aimDownSightState;
protected float aimDownSightStateSmooth;
protected float readyState;
protected bool reloading;
protected float reloadProgress;
protected int ammo, clipSize;
protected float localFireVibration;
protected float sprintStateSmooth;
protected float sprintStateSmooth;
float AimDownSightState {
set {
aimDownSightState = value;
aimDownSightStateSmooth = SmoothStep(value);
}
get {
return aimDownSightState;
}
}
float AimDownSightState {
set {
aimDownSightState = value;
aimDownSightStateSmooth = SmoothStep(value);
}
get { return aimDownSightState; }
}
float AimDownSightStateSmooth {
get { return aimDownSightStateSmooth; }
}
float AimDownSightStateSmooth {
get { return aimDownSightStateSmooth; }
}
bool IsReloading {
get { return reloading; }
set { reloading = value; }
}
float ReloadProgress {
get { return reloadProgress; }
set { reloadProgress = value; }
}
int Ammo {
set { ammo = value; }
get { return ammo; }
}
int ClipSize {
set { clipSize = value; }
get { return clipSize; }
}
bool IsReloading {
get { return reloading; }
set { reloading = value; }
}
float ReloadProgress {
get { return reloadProgress; }
set { reloadProgress = value; }
}
int Ammo {
set { ammo = value; }
get { return ammo; }
}
int ClipSize {
set { clipSize = value; }
get { return clipSize; }
}
float ReadyState {
set { readyState = value; }
get { return readyState; }
}
float ReadyState {
set { readyState = value; }
get { return readyState; }
}
// IViewToolSkin
// IViewToolSkin
protected Matrix4 eyeMatrix;
protected Vector3 swing;
protected Vector3 leftHand;
protected Vector3 rightHand;
protected Matrix4 eyeMatrix;
protected Vector3 swing;
protected Vector3 leftHand;
protected Vector3 rightHand;
Matrix4 EyeMatrix {
set { eyeMatrix = value; }
get { return eyeMatrix; }
}
Matrix4 EyeMatrix {
set { eyeMatrix = value; }
get { return eyeMatrix; }
}
Vector3 Swing {
set { swing = value; }
get { return swing; }
}
Vector3 Swing {
set { swing = value; }
get { return swing; }
}
Vector3 LeftHandPosition {
get {
return leftHand;
}
set {
leftHand = value;
}
}
Vector3 RightHandPosition {
get {
return rightHand;
}
set {
rightHand = value;
}
}
Vector3 LeftHandPosition {
get { return leftHand; }
set { leftHand = value; }
}
Vector3 RightHandPosition {
get { return rightHand; }
set { rightHand = value; }
}
// IWeaponSkin2
protected float environmentRoom;
protected float environmentSize;
// IWeaponSkin2
protected float environmentRoom;
protected float environmentSize;
void SetSoundEnvironment(float room, float size, float distance) {
environmentRoom = room;
environmentSize = size;
}
// set_SoundOrigin is not called for first-person skin scripts
Vector3 SoundOrigin {
set { }
}
void SetSoundEnvironment(float room, float size, float distance) {
environmentRoom = room;
environmentSize = size;
}
// set_SoundOrigin is not called for first-person skin scripts
Vector3 SoundOrigin {
set {}
}
protected Renderer@ renderer;
protected Image@ sightImage;
protected Renderer @renderer;
protected Image @sightImage;
BasicViewWeapon(Renderer@ renderer) {
@this.renderer = renderer;
localFireVibration = 0.f;
@sightImage = renderer.RegisterImage
("Gfx/Sight.tga");
}
BasicViewWeapon(Renderer @renderer) {
@this.renderer = renderer;
localFireVibration = 0.f;
@sightImage = renderer.RegisterImage("Gfx/Sight.tga");
}
float GetLocalFireVibration() {
return localFireVibration;
}
float GetLocalFireVibration() { return localFireVibration; }
float GetMotionGain() {
return 1.f - AimDownSightStateSmooth * 0.4f;
}
float GetMotionGain() { return 1.f - AimDownSightStateSmooth * 0.4f; }
float GetZPos() {
return 0.2f - AimDownSightStateSmooth * 0.05f;
}
float GetZPos() { return 0.2f - AimDownSightStateSmooth * 0.05f; }
Vector3 GetLocalFireVibrationOffset() {
float vib = GetLocalFireVibration();
float motion = GetMotionGain();
Vector3 hip = Vector3(
sin(vib * PiF * 2.f) * 0.008f * motion,
vib * (vib - 1.f) * 0.14f * motion,
vib * (1.f - vib) * 0.03f * motion);
Vector3 ads = Vector3(0.f, vib * (vib - 1.f) * vib * 0.3f * motion, 0.f);
return Mix(hip, ads, AimDownSightStateSmooth);
}
Vector3 GetLocalFireVibrationOffset() {
float vib = GetLocalFireVibration();
float motion = GetMotionGain();
Vector3 hip =
Vector3(sin(vib * PiF * 2.f) * 0.008f * motion, vib * (vib - 1.f) * 0.14f * motion,
vib * (1.f - vib) * 0.03f * motion);
Vector3 ads = Vector3(0.f, vib * (vib - 1.f) * vib * 0.3f * motion, 0.f);
return Mix(hip, ads, AimDownSightStateSmooth);
}
Matrix4 GetViewWeaponMatrix() {
Matrix4 mat;
if(sprintStateSmooth > 0.f) {
mat = CreateRotateMatrix(Vector3(0.f, 1.f, 0.f),
sprintStateSmooth * -0.1f) * mat;
mat = CreateRotateMatrix(Vector3(1.f, 0.f, 0.f),
sprintStateSmooth * 0.3f) * mat;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f),
sprintStateSmooth * -0.55f) * mat;
mat = CreateTranslateMatrix(Vector3(0.23f, -0.05f, 0.15f)
* sprintStateSmooth) * mat;
}
Matrix4 GetViewWeaponMatrix() {
Matrix4 mat;
if (sprintStateSmooth > 0.f) {
mat = CreateRotateMatrix(Vector3(0.f, 1.f, 0.f), sprintStateSmooth * -0.1f) * mat;
mat = CreateRotateMatrix(Vector3(1.f, 0.f, 0.f), sprintStateSmooth * 0.3f) * mat;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), sprintStateSmooth * -0.55f) * mat;
mat =
CreateTranslateMatrix(Vector3(0.23f, -0.05f, 0.15f) * sprintStateSmooth) * mat;
}
if(raiseState < 1.f) {
float putdown = 1.f - raiseState;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f),
putdown * -1.3f) * mat;
mat = CreateRotateMatrix(Vector3(0.f, 1.f, 0.f),
putdown * 0.2f) * mat;
mat = CreateTranslateMatrix(Vector3(0.1f, -0.3f, 0.1f)
* putdown) * mat;
}
if (raiseState < 1.f) {
float putdown = 1.f - raiseState;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), putdown * -1.3f) * mat;
mat = CreateRotateMatrix(Vector3(0.f, 1.f, 0.f), putdown * 0.2f) * mat;
mat = CreateTranslateMatrix(Vector3(0.1f, -0.3f, 0.1f) * putdown) * mat;
}
Vector3 trans(0.f, 0.f, 0.f);
trans += Vector3(-0.13f * (1.f - AimDownSightStateSmooth),
0.5f, GetZPos());
trans += swing * GetMotionGain();
trans += GetLocalFireVibrationOffset();
mat = CreateTranslateMatrix(trans) * mat;
Vector3 trans(0.f, 0.f, 0.f);
trans += Vector3(-0.13f * (1.f - AimDownSightStateSmooth), 0.5f, GetZPos());
trans += swing * GetMotionGain();
trans += GetLocalFireVibrationOffset();
mat = CreateTranslateMatrix(trans) * mat;
return mat;
}
return mat;
}
void Update(float dt) {
localFireVibration -= dt * 10.f;
if(localFireVibration < 0.f){
localFireVibration = 0.f;
}
void Update(float dt) {
localFireVibration -= dt * 10.f;
if (localFireVibration < 0.f) {
localFireVibration = 0.f;
}
float sprintStateSS = sprintState * sprintState;
if (sprintStateSS > sprintStateSmooth) {
sprintStateSmooth += (sprintStateSS - sprintStateSmooth) * (1.f - pow(0.001, dt));
} else {
sprintStateSmooth = sprintStateSS;
}
}
float sprintStateSS = sprintState * sprintState;
if (sprintStateSS > sprintStateSmooth) {
sprintStateSmooth += (sprintStateSS - sprintStateSmooth) * (1.f - pow(0.001, dt));
} else {
sprintStateSmooth = sprintStateSS;
}
}
void WeaponFired(){
localFireVibration = 1.f;
}
void WeaponFired() { localFireVibration = 1.f; }
void AddToScene() {
}
void AddToScene() {}
void ReloadingWeapon() {
}
void ReloadingWeapon() {}
void ReloadedWeapon() {
}
void ReloadedWeapon() {}
void Draw2D() {
renderer.ColorNP = (Vector4(1.f, 1.f, 1.f, 1.f));
renderer.DrawImage(sightImage,
Vector2((renderer.ScreenWidth - sightImage.Width) * 0.5f,
(renderer.ScreenHeight - sightImage.Height) * 0.5f));
}
}
void Draw2D() {
renderer.ColorNP = (Vector4(1.f, 1.f, 1.f, 1.f));
renderer.DrawImage(sightImage,
Vector2((renderer.ScreenWidth - sightImage.Width) * 0.5f,
(renderer.ScreenHeight - sightImage.Height) * 0.5f));
}
}
}

View File

@ -1,94 +1,91 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
class ThirdPersonBlockSkin:
IToolSkin, IThirdPersonToolSkin, IBlockSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 originMatrix;
private Vector3 blockColor;
private float readyState;
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
bool IsMuted {
set {
// nothing to do; building sound is not related to skin.
}
}
Vector3 TeamColor {
set { teamColor = value; }
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
float PitchBias {
get { return 0.f; }
}
Vector3 BlockColor {
set { blockColor = value; }
}
float ReadyState {
set { readyState = value; }
}
private Renderer@ renderer;
private AudioDevice@ audioDevice;
private Model@ model;
ThirdPersonBlockSkin(Renderer@ r, AudioDevice@ dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel
("Models/Weapons/Block/Block2.kv6");
}
void Update(float dt) {
}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = CreateTranslateMatrix(0.35f, -1.f, 0.0f) * mat;
ModelRenderParam param;
param.matrix = originMatrix * mat;
param.customColor = blockColor;
renderer.AddModel(model, param);
}
}
IBlockSkin@ CreateThirdPersonBlockSkin(Renderer@ r, AudioDevice@ dev) {
return ThirdPersonBlockSkin(r, dev);
}
namespace spades {
class ThirdPersonBlockSkin : IToolSkin, IThirdPersonToolSkin, IBlockSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 originMatrix;
private Vector3 blockColor;
private float readyState;
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
bool IsMuted {
set {
// nothing to do; building sound is not related to skin.
}
}
Vector3 TeamColor {
set { teamColor = value; }
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
float PitchBias {
get { return 0.f; }
}
Vector3 BlockColor {
set { blockColor = value; }
}
float ReadyState {
set { readyState = value; }
}
private Renderer @renderer;
private AudioDevice @audioDevice;
private Model @model;
ThirdPersonBlockSkin(Renderer @r, AudioDevice @dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel("Models/Weapons/Block/Block2.kv6");
}
void Update(float dt) {}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = CreateTranslateMatrix(0.35f, -1.f, 0.0f) * mat;
ModelRenderParam param;
param.matrix = originMatrix * mat;
param.customColor = blockColor;
renderer.AddModel(model, param);
}
}
IBlockSkin @CreateThirdPersonBlockSkin(Renderer @r, AudioDevice @dev) {
return ThirdPersonBlockSkin(r, dev);
}
}

View File

@ -18,131 +18,119 @@
*/
namespace spades {
class ViewBlockSkin:
IToolSkin, IViewToolSkin, IBlockSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 eyeMatrix;
private Vector3 swing;
private Vector3 leftHand;
private Vector3 rightHand;
private Vector3 blockColor;
private float readyState;
namespace spades {
class ViewBlockSkin : IToolSkin, IViewToolSkin, IBlockSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 eyeMatrix;
private Vector3 swing;
private Vector3 leftHand;
private Vector3 rightHand;
private Vector3 blockColor;
private float readyState;
private float sprintStateSmooth;
private float sprintStateSmooth;
float SprintState {
set { sprintState = value; }
}
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
float RaiseState {
set { raiseState = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
bool IsMuted {
set {
// nothing to do
}
}
bool IsMuted {
set {
// nothing to do
}
}
Matrix4 EyeMatrix {
set { eyeMatrix = value; }
}
Matrix4 EyeMatrix {
set { eyeMatrix = value; }
}
Vector3 Swing {
set { swing = value; }
}
Vector3 Swing {
set { swing = value; }
}
Vector3 LeftHandPosition {
get {
return leftHand;
}
}
Vector3 RightHandPosition {
get {
return rightHand;
}
}
Vector3 LeftHandPosition {
get { return leftHand; }
}
Vector3 RightHandPosition {
get { return rightHand; }
}
Vector3 BlockColor {
set { blockColor = value; }
}
Vector3 BlockColor {
set { blockColor = value; }
}
float ReadyState {
set { readyState = value; }
}
float ReadyState {
set { readyState = value; }
}
private Renderer@ renderer;
private AudioDevice@ audioDevice;
private Model@ model;
private Image@ sightImage;
private Renderer @renderer;
private AudioDevice @audioDevice;
private Model @model;
private Image @sightImage;
ViewBlockSkin(Renderer@ r, AudioDevice@ dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel
("Models/Weapons/Block/Block2.kv6");
@sightImage = renderer.RegisterImage
("Gfx/Sight.tga");
}
ViewBlockSkin(Renderer @r, AudioDevice @dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel("Models/Weapons/Block/Block2.kv6");
@sightImage = renderer.RegisterImage("Gfx/Sight.tga");
}
void Update(float dt) {
float sprintStateSS = sprintState * sprintState;
if (sprintStateSS > sprintStateSmooth) {
sprintStateSmooth += (sprintStateSS - sprintStateSmooth) * (1.f - pow(0.001, dt));
} else {
sprintStateSmooth = sprintStateSS;
}
}
void Update(float dt) {
float sprintStateSS = sprintState * sprintState;
if (sprintStateSS > sprintStateSmooth) {
sprintStateSmooth += (sprintStateSS - sprintStateSmooth) * (1.f - pow(0.001, dt));
} else {
sprintStateSmooth = sprintStateSS;
}
}
void AddToScene() {
if(readyState < .99f){
// not ready
leftHand = Vector3(0.5f, 0.5f, 0.6f);
rightHand = Vector3(-0.5f, 0.5f, 0.6f);
return;
}
void AddToScene() {
if (readyState < .99f) {
// not ready
leftHand = Vector3(0.5f, 0.5f, 0.6f);
rightHand = Vector3(-0.5f, 0.5f, 0.6f);
return;
}
Matrix4 mat = CreateScaleMatrix(0.033f);
Matrix4 mat = CreateScaleMatrix(0.033f);
if(sprintStateSmooth > 0.f) {
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f),
sprintStateSmooth * -0.3f) * mat;
mat = CreateTranslateMatrix(Vector3(0.1f, -0.4f, -0.05f) * sprintStateSmooth)
* mat;
}
if (sprintStateSmooth > 0.f) {
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), sprintStateSmooth * -0.3f) * mat;
mat = CreateTranslateMatrix(Vector3(0.1f, -0.4f, -0.05f) * sprintStateSmooth) * mat;
}
mat = CreateTranslateMatrix(-0.3f, 0.7f, 0.3f) * mat;
mat = CreateTranslateMatrix(swing) * mat;
mat = CreateTranslateMatrix(-0.3f, 0.7f, 0.3f) * mat;
mat = CreateTranslateMatrix(swing) * mat;
mat = CreateTranslateMatrix(Vector3(-0.1f, -0.3f, 0.2f) * (1.f - raiseState))
* mat;
mat = CreateTranslateMatrix(Vector3(-0.1f, -0.3f, 0.2f) * (1.f - raiseState)) * mat;
leftHand = mat * Vector3(5.f, -1.f, 4.f);
rightHand = mat * Vector3(-5.5f, 3.f, -5.f);
leftHand = mat * Vector3(5.f, -1.f, 4.f);
rightHand = mat * Vector3(-5.5f, 3.f, -5.f);
ModelRenderParam param;
param.matrix = eyeMatrix * mat;
param.customColor = blockColor;
param.depthHack = true;
renderer.AddModel(model, param);
}
ModelRenderParam param;
param.matrix = eyeMatrix * mat;
param.customColor = blockColor;
param.depthHack = true;
renderer.AddModel(model, param);
}
void Draw2D() {
renderer.ColorNP = (Vector4(1.f, 1.f, 1.f, 1.f));
renderer.DrawImage(sightImage,
Vector2((renderer.ScreenWidth - sightImage.Width) * 0.5f,
(renderer.ScreenHeight - sightImage.Height) * 0.5f));
}
}
void Draw2D() {
renderer.ColorNP = (Vector4(1.f, 1.f, 1.f, 1.f));
renderer.DrawImage(sightImage,
Vector2((renderer.ScreenWidth - sightImage.Width) * 0.5f,
(renderer.ScreenHeight - sightImage.Height) * 0.5f));
}
}
IBlockSkin@ CreateViewBlockSkin(Renderer@ r, AudioDevice@ dev) {
return ViewBlockSkin(r, dev);
}
IBlockSkin @CreateViewBlockSkin(Renderer @r, AudioDevice @dev) { return ViewBlockSkin(r, dev); }
}

View File

@ -1,93 +1,90 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
class ThirdPersonGrenadeSkin:
IToolSkin, IThirdPersonToolSkin, IGrenadeSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 originMatrix;
private float cookTime;
private float readyState;
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
bool IsMuted {
set {
// nothing to do
}
}
Vector3 TeamColor {
set { teamColor = value; }
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
float PitchBias {
get { return 0.f; }
}
float CookTime {
set { cookTime = value; }
}
float ReadyState {
set { readyState = value; }
}
private Renderer@ renderer;
private AudioDevice@ audioDevice;
private Model@ model;
ThirdPersonGrenadeSkin(Renderer@ r, AudioDevice@ dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel
("Models/Weapons/Grenade/Grenade.kv6");
}
void Update(float dt) {
}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = CreateTranslateMatrix(0.35f, -1.f, 0.0f) * mat;
ModelRenderParam param;
param.matrix = originMatrix * mat;
renderer.AddModel(model, param);
}
}
IGrenadeSkin@ CreateThirdPersonGrenadeSkin(Renderer@ r, AudioDevice@ dev) {
return ThirdPersonGrenadeSkin(r, dev);
}
namespace spades {
class ThirdPersonGrenadeSkin : IToolSkin, IThirdPersonToolSkin, IGrenadeSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 originMatrix;
private float cookTime;
private float readyState;
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
bool IsMuted {
set {
// nothing to do
}
}
Vector3 TeamColor {
set { teamColor = value; }
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
float PitchBias {
get { return 0.f; }
}
float CookTime {
set { cookTime = value; }
}
float ReadyState {
set { readyState = value; }
}
private Renderer @renderer;
private AudioDevice @audioDevice;
private Model @model;
ThirdPersonGrenadeSkin(Renderer @r, AudioDevice @dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel("Models/Weapons/Grenade/Grenade.kv6");
}
void Update(float dt) {}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = CreateTranslateMatrix(0.35f, -1.f, 0.0f) * mat;
ModelRenderParam param;
param.matrix = originMatrix * mat;
renderer.AddModel(model, param);
}
}
IGrenadeSkin @CreateThirdPersonGrenadeSkin(Renderer @r, AudioDevice @dev) {
return ThirdPersonGrenadeSkin(r, dev);
}
}

View File

@ -18,163 +18,155 @@
*/
namespace spades {
class ViewGrenadeSkin:
IToolSkin, IViewToolSkin, IGrenadeSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 eyeMatrix;
private Vector3 swing;
private Vector3 leftHand;
private Vector3 rightHand;
private float cookTime;
private float readyState;
namespace spades {
class ViewGrenadeSkin : IToolSkin, IViewToolSkin, IGrenadeSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 eyeMatrix;
private Vector3 swing;
private Vector3 leftHand;
private Vector3 rightHand;
private float cookTime;
private float readyState;
private float sprintStateSmooth;
private float sprintStateSmooth;
float SprintState {
set { sprintState = value; }
}
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
float RaiseState {
set { raiseState = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
bool IsMuted {
set {
// nothing to do
}
}
bool IsMuted {
set {
// nothing to do
}
}
Matrix4 EyeMatrix {
set { eyeMatrix = value; }
}
Matrix4 EyeMatrix {
set { eyeMatrix = value; }
}
Vector3 Swing {
set { swing = value; }
}
Vector3 Swing {
set { swing = value; }
}
Vector3 LeftHandPosition {
get {
return leftHand;
}
}
Vector3 RightHandPosition {
get {
return rightHand;
}
}
Vector3 LeftHandPosition {
get { return leftHand; }
}
Vector3 RightHandPosition {
get { return rightHand; }
}
float CookTime {
set { cookTime = value; }
}
float CookTime {
set { cookTime = value; }
}
float ReadyState {
set { readyState = value; }
}
float ReadyState {
set { readyState = value; }
}
private Renderer@ renderer;
private AudioDevice@ audioDevice;
private Model@ model;
private Image@ sightImage;
private Renderer @renderer;
private AudioDevice @audioDevice;
private Model @model;
private Image @sightImage;
ViewGrenadeSkin(Renderer@ r, AudioDevice@ dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel
("Models/Weapons/Grenade/Grenade.kv6");
@sightImage = renderer.RegisterImage
("Gfx/Sight.tga");
}
ViewGrenadeSkin(Renderer @r, AudioDevice @dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel("Models/Weapons/Grenade/Grenade.kv6");
@sightImage = renderer.RegisterImage("Gfx/Sight.tga");
}
void Update(float dt) {
float sprintStateSS = sprintState * sprintState;
if (sprintStateSS > sprintStateSmooth) {
sprintStateSmooth += (sprintStateSS - sprintStateSmooth) * (1.f - pow(0.001, dt));
} else {
sprintStateSmooth = sprintStateSS;
}
}
void Update(float dt) {
float sprintStateSS = sprintState * sprintState;
if (sprintStateSS > sprintStateSmooth) {
sprintStateSmooth += (sprintStateSS - sprintStateSmooth) * (1.f - pow(0.001, dt));
} else {
sprintStateSmooth = sprintStateSS;
}
}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.033f);
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.033f);
if(readyState > 0.9999) {
float bring = 0.f;
float pin = 0.f;
float side = 0.f;
if (readyState > 0.9999) {
float bring = 0.f;
float pin = 0.f;
float side = 0.f;
bring = Min((readyState - 1.f) * 2.f, 1.f);
bring = 1.f - bring;
bring = 1.f - bring * bring;
bring = Min((readyState - 1.f) * 2.f, 1.f);
bring = 1.f - bring;
bring = 1.f - bring * bring;
if(cookTime > 0.0001f) {
pin = Min(cookTime * 8.f, 2.f);
if (cookTime > 0.0001f) {
pin = Min(cookTime * 8.f, 2.f);
if(pin > 1.f) {
side += pin - 1.f;
bring -= (pin - 1.f) * 2.f;
}
}
if (pin > 1.f) {
side += pin - 1.f;
bring -= (pin - 1.f) * 2.f;
}
}
if(sprintStateSmooth > 0.f){
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f),
sprintStateSmooth * -0.3f) * mat;
mat = CreateTranslateMatrix(Vector3(0.1f, -0.2f, -0.05f)
* sprintStateSmooth) * mat;
}
mat = CreateTranslateMatrix(-0.3f - side * 0.8f,
0.8f - bring * 0.1f, 0.45f - bring * 0.15f) * mat;
if (sprintStateSmooth > 0.f) {
mat =
CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), sprintStateSmooth * -0.3f) * mat;
mat = CreateTranslateMatrix(Vector3(0.1f, -0.2f, -0.05f) * sprintStateSmooth) *
mat;
}
mat = CreateTranslateMatrix(-0.3f - side * 0.8f, 0.8f - bring * 0.1f,
0.45f - bring * 0.15f) *
mat;
mat = CreateTranslateMatrix(Vector3(-0.1f, -0.3f, 0.1f) * (1.f - raiseState))
* mat;
mat = CreateTranslateMatrix(Vector3(-0.1f, -0.3f, 0.1f) * (1.f - raiseState)) * mat;
mat = CreateTranslateMatrix(swing) * mat;
mat = CreateTranslateMatrix(swing) * mat;
leftHand = mat * Vector3(10.f, -1.f, 10.f);
rightHand = mat * Vector3(-3.f, 1.f, 5.f);
leftHand = mat * Vector3(10.f, -1.f, 10.f);
rightHand = mat * Vector3(-3.f, 1.f, 5.f);
Vector3 leftHand2 = mat * Vector3(2.f, 1.f, -2.f);
Vector3 leftHand3 = mat * Vector3(8.f, -1.f, 10.f);
Vector3 leftHand2 = mat * Vector3(2.f, 1.f, -2.f);
Vector3 leftHand3 = mat * Vector3(8.f, -1.f, 10.f);
if(pin < 1.f){
leftHand = Mix(leftHand, leftHand2, pin);
}else{
leftHand = Mix(leftHand2, leftHand3, pin - 1.f);
}
if (pin < 1.f) {
leftHand = Mix(leftHand, leftHand2, pin);
} else {
leftHand = Mix(leftHand2, leftHand3, pin - 1.f);
}
ModelRenderParam param;
param.matrix = eyeMatrix * mat;
param.depthHack = true;
renderer.AddModel(model, param);
} else {
// throwing
float per = readyState;
per = Min(per * 3.f, 1.f);
ModelRenderParam param;
param.matrix = eyeMatrix * mat;
param.depthHack = true;
renderer.AddModel(model, param);
} else {
// throwing
float per = readyState;
per = Min(per * 3.f, 1.f);
// left hand shouldn't be visible
leftHand = Vector3(0.5f, 0.5f, 0.6f);
// left hand shouldn't be visible
leftHand = Vector3(0.5f, 0.5f, 0.6f);
float p2 = per - 0.6f;
p2 = 0.9f - p2 * p2 * 2.5f;
rightHand = Vector3(-0.2f, p2, -0.9f + per * 1.8f);
}
float p2 = per - 0.6f;
p2 = 0.9f - p2 * p2 * 2.5f;
rightHand = Vector3(-0.2f, p2, -0.9f + per * 1.8f);
}
}
void Draw2D() {
renderer.ColorNP = (Vector4(1.f, 1.f, 1.f, 1.f));
renderer.DrawImage(sightImage,
Vector2((renderer.ScreenWidth - sightImage.Width) * 0.5f,
(renderer.ScreenHeight - sightImage.Height) * 0.5f));
}
}
}
void Draw2D() {
renderer.ColorNP = (Vector4(1.f, 1.f, 1.f, 1.f));
renderer.DrawImage(sightImage,
Vector2((renderer.ScreenWidth - sightImage.Width) * 0.5f,
(renderer.ScreenHeight - sightImage.Height) * 0.5f));
}
}
IGrenadeSkin@ CreateViewGrenadeSkin(Renderer@ r, AudioDevice@ dev) {
return ViewGrenadeSkin(r, dev);
}
IGrenadeSkin @CreateViewGrenadeSkin(Renderer @r, AudioDevice @dev) {
return ViewGrenadeSkin(r, dev);
}
}

View File

@ -18,165 +18,153 @@
*/
namespace spades {
class ThirdPersonRifleSkin:
IToolSkin, IThirdPersonToolSkin, IWeaponSkin, IWeaponSkin2 {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private bool muted = true;
private Matrix4 originMatrix;
private float aimDownSightState;
private float readyState;
private bool reloading;
private float reloadProgress;
private int ammo, clipSize;
namespace spades {
class ThirdPersonRifleSkin : IToolSkin, IThirdPersonToolSkin, IWeaponSkin, IWeaponSkin2 {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private bool muted = true;
private Matrix4 originMatrix;
private float aimDownSightState;
private float readyState;
private bool reloading;
private float reloadProgress;
private int ammo, clipSize;
private float environmentRoom;
private float environmentSize;
private float environmentDistance;
private Vector3 soundOrigin;
private float environmentRoom;
private float environmentSize;
private float environmentDistance;
private Vector3 soundOrigin;
float SprintState {
set { sprintState = value; }
}
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
float RaiseState {
set { raiseState = value; }
}
bool IsMuted {
set { muted = value; }
}
bool IsMuted {
set { muted = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
float PitchBias {
get { return 0.f; }
}
float PitchBias {
get { return 0.f; }
}
float AimDownSightState {
set { aimDownSightState = value; }
}
float AimDownSightState {
set { aimDownSightState = value; }
}
bool IsReloading {
set { reloading = value; }
}
float ReloadProgress {
set { reloadProgress = value; }
}
int Ammo {
set { ammo = value; }
}
int ClipSize {
set { clipSize = value; }
}
bool IsReloading {
set { reloading = value; }
}
float ReloadProgress {
set { reloadProgress = value; }
}
int Ammo {
set { ammo = value; }
}
int ClipSize {
set { clipSize = value; }
}
float ReadyState {
set { readyState = value; }
}
float ReadyState {
set { readyState = value; }
}
// IWeaponSkin2
void SetSoundEnvironment(float room, float size, float distance) {
environmentRoom = room;
environmentSize = size;
environmentDistance = distance;
}
Vector3 SoundOrigin {
set { soundOrigin = value; }
}
// IWeaponSkin2
void SetSoundEnvironment(float room, float size, float distance) {
environmentRoom = room;
environmentSize = size;
environmentDistance = distance;
}
Vector3 SoundOrigin {
set { soundOrigin = value; }
}
private Renderer@ renderer;
private AudioDevice@ audioDevice;
private Model@ model;
private AudioChunk@[] fireSounds(3);
private AudioChunk@ fireFarSound;
private AudioChunk@ fireStereoSound;
private AudioChunk@ fireSmallReverbSound;
private AudioChunk@ fireLargeReverbSound;
private AudioChunk@ reloadSound;
private Renderer @renderer;
private AudioDevice @audioDevice;
private Model @model;
private AudioChunk @[] fireSounds(3);
private AudioChunk @fireFarSound;
private AudioChunk @fireStereoSound;
private AudioChunk @fireSmallReverbSound;
private AudioChunk @fireLargeReverbSound;
private AudioChunk @reloadSound;
ThirdPersonRifleSkin(Renderer@ r, AudioDevice@ dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel
("Models/Weapons/Rifle/Weapon.kv6");
ThirdPersonRifleSkin(Renderer @r, AudioDevice @dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel("Models/Weapons/Rifle/Weapon.kv6");
@fireSounds[0] = dev.RegisterSound
("Sounds/Weapons/Rifle/Fire1.opus");
@fireSounds[1] = dev.RegisterSound
("Sounds/Weapons/Rifle/Fire2.opus");
@fireSounds[2] = dev.RegisterSound
("Sounds/Weapons/Rifle/Fire3.opus");
@fireFarSound = dev.RegisterSound
("Sounds/Weapons/Rifle/FireFar.opus");
@fireStereoSound = dev.RegisterSound
("Sounds/Weapons/Rifle/FireStereo.opus");
@reloadSound = dev.RegisterSound
("Sounds/Weapons/Rifle/Reload.opus");
@fireSounds[0] = dev.RegisterSound("Sounds/Weapons/Rifle/Fire1.opus");
@fireSounds[1] = dev.RegisterSound("Sounds/Weapons/Rifle/Fire2.opus");
@fireSounds[2] = dev.RegisterSound("Sounds/Weapons/Rifle/Fire3.opus");
@fireFarSound = dev.RegisterSound("Sounds/Weapons/Rifle/FireFar.opus");
@fireStereoSound = dev.RegisterSound("Sounds/Weapons/Rifle/FireStereo.opus");
@reloadSound = dev.RegisterSound("Sounds/Weapons/Rifle/Reload.opus");
@fireSmallReverbSound = dev.RegisterSound
("Sounds/Weapons/Rifle/V2AmbienceSmall.opus");
@fireLargeReverbSound = dev.RegisterSound
("Sounds/Weapons/Rifle/V2AmbienceLarge.opus");
}
@fireSmallReverbSound = dev.RegisterSound("Sounds/Weapons/Rifle/V2AmbienceSmall.opus");
@fireLargeReverbSound = dev.RegisterSound("Sounds/Weapons/Rifle/V2AmbienceLarge.opus");
}
void Update(float dt) {
}
void Update(float dt) {}
void WeaponFired(){
if(!muted){
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 20.f;
audioDevice.Play(fireSounds[GetRandom(fireSounds.length)], origin, param);
void WeaponFired() {
if (!muted) {
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 20.f;
audioDevice.Play(fireSounds[GetRandom(fireSounds.length)], origin, param);
param.volume = 20.f * environmentRoom;
if (environmentSize < 0.5f) {
audioDevice.Play(fireSmallReverbSound, origin, param);
} else {
audioDevice.Play(fireLargeReverbSound, origin, param);
}
param.volume = 20.f * environmentRoom;
if (environmentSize < 0.5f) {
audioDevice.Play(fireSmallReverbSound, origin, param);
} else {
audioDevice.Play(fireLargeReverbSound, origin, param);
}
param.volume = 1.f;
param.referenceDistance = 26.f;
audioDevice.Play(fireFarSound, origin, param);
param.referenceDistance = 4.f;
param.volume = 1.f;
audioDevice.Play(fireStereoSound, origin, param);
}
}
param.volume = 1.f;
param.referenceDistance = 26.f;
audioDevice.Play(fireFarSound, origin, param);
param.referenceDistance = 4.f;
param.volume = 1.f;
audioDevice.Play(fireStereoSound, origin, param);
}
}
void ReloadingWeapon() {
if(!muted){
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 0.2f;
audioDevice.Play(reloadSound, origin, param);
}
}
void ReloadingWeapon() {
if (!muted) {
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 0.2f;
audioDevice.Play(reloadSound, origin, param);
}
}
void ReloadedWeapon() {
}
void ReloadedWeapon() {}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = mat * CreateScaleMatrix(-1.f, -1.f, 1.f);
mat = CreateTranslateMatrix(0.35f, -1.f, 0.0f) * mat;
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = mat * CreateScaleMatrix(-1.f, -1.f, 1.f);
mat = CreateTranslateMatrix(0.35f, -1.f, 0.0f) * mat;
ModelRenderParam param;
param.matrix = originMatrix * mat;
renderer.AddModel(model, param);
}
}
ModelRenderParam param;
param.matrix = originMatrix * mat;
renderer.AddModel(model, param);
}
}
IWeaponSkin@ CreateThirdPersonRifleSkin(Renderer@ r, AudioDevice@ dev) {
return ThirdPersonRifleSkin(r, dev);
}
IWeaponSkin @CreateThirdPersonRifleSkin(Renderer @r, AudioDevice @dev) {
return ThirdPersonRifleSkin(r, dev);
}
}

View File

@ -18,213 +18,198 @@
*/
namespace spades {
class ViewRifleSkin:
IToolSkin, IViewToolSkin, IWeaponSkin,
BasicViewWeapon {
namespace spades {
class ViewRifleSkin : IToolSkin, IViewToolSkin, IWeaponSkin, BasicViewWeapon {
private AudioDevice@ audioDevice;
private Model@ gunModel;
private Model@ magazineModel;
private AudioDevice @audioDevice;
private Model @gunModel;
private Model @magazineModel;
private AudioChunk@ fireSound;
private AudioChunk@ fireFarSound;
private AudioChunk@ fireStereoSound;
private AudioChunk@ fireSmallReverbSound;
private AudioChunk@ fireLargeReverbSound;
private AudioChunk@ reloadSound;
private Model@ sightModel1;
private Model@ sightModel2;
private AudioChunk @fireSound;
private AudioChunk @fireFarSound;
private AudioChunk @fireStereoSound;
private AudioChunk @fireSmallReverbSound;
private AudioChunk @fireLargeReverbSound;
private AudioChunk @reloadSound;
private Model @sightModel1;
private Model @sightModel2;
ViewRifleSkin(Renderer@ r, AudioDevice@ dev){
super(r);
@audioDevice = dev;
@gunModel = renderer.RegisterModel
("Models/Weapons/Rifle/WeaponNoMagazine.kv6");
@magazineModel = renderer.RegisterModel
("Models/Weapons/Rifle/Magazine.kv6");
@sightModel1 = renderer.RegisterModel
("Models/Weapons/Rifle/Sight1.kv6");
@sightModel2 = renderer.RegisterModel
("Models/Weapons/Rifle/Sight2.kv6");
ViewRifleSkin(Renderer @r, AudioDevice @dev) {
super(r);
@audioDevice = dev;
@gunModel = renderer.RegisterModel("Models/Weapons/Rifle/WeaponNoMagazine.kv6");
@magazineModel = renderer.RegisterModel("Models/Weapons/Rifle/Magazine.kv6");
@sightModel1 = renderer.RegisterModel("Models/Weapons/Rifle/Sight1.kv6");
@sightModel2 = renderer.RegisterModel("Models/Weapons/Rifle/Sight2.kv6");
@fireSound = dev.RegisterSound
("Sounds/Weapons/Rifle/FireLocal.opus");
@fireFarSound = dev.RegisterSound
("Sounds/Weapons/Rifle/FireFar.opus");
@fireStereoSound = dev.RegisterSound
("Sounds/Weapons/Rifle/FireStereo.opus");
@reloadSound = dev.RegisterSound
("Sounds/Weapons/Rifle/ReloadLocal.opus");
@fireSound = dev.RegisterSound("Sounds/Weapons/Rifle/FireLocal.opus");
@fireFarSound = dev.RegisterSound("Sounds/Weapons/Rifle/FireFar.opus");
@fireStereoSound = dev.RegisterSound("Sounds/Weapons/Rifle/FireStereo.opus");
@reloadSound = dev.RegisterSound("Sounds/Weapons/Rifle/ReloadLocal.opus");
@fireSmallReverbSound = dev.RegisterSound
("Sounds/Weapons/Rifle/V2AmbienceSmall.opus");
@fireLargeReverbSound = dev.RegisterSound
("Sounds/Weapons/Rifle/V2AmbienceLarge.opus");
}
@fireSmallReverbSound = dev.RegisterSound("Sounds/Weapons/Rifle/V2AmbienceSmall.opus");
@fireLargeReverbSound = dev.RegisterSound("Sounds/Weapons/Rifle/V2AmbienceLarge.opus");
}
void Update(float dt) {
BasicViewWeapon::Update(dt);
}
void Update(float dt) { BasicViewWeapon::Update(dt); }
void WeaponFired(){
BasicViewWeapon::WeaponFired();
void WeaponFired() {
BasicViewWeapon::WeaponFired();
if(!IsMuted){
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 8.f;
audioDevice.PlayLocal(fireSound, origin, param);
if (!IsMuted) {
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 8.f;
audioDevice.PlayLocal(fireSound, origin, param);
param.volume = 8.f * environmentRoom;
if (environmentSize < 0.5f) {
audioDevice.PlayLocal(fireSmallReverbSound, origin, param);
} else {
audioDevice.PlayLocal(fireLargeReverbSound, origin, param);
}
param.volume = 8.f * environmentRoom;
if (environmentSize < 0.5f) {
audioDevice.PlayLocal(fireSmallReverbSound, origin, param);
} else {
audioDevice.PlayLocal(fireLargeReverbSound, origin, param);
}
param.referenceDistance = 4.f;
param.volume = 1.f;
audioDevice.PlayLocal(fireFarSound, origin, param);
param.referenceDistance = 1.f;
audioDevice.PlayLocal(fireStereoSound, origin, param);
}
}
param.referenceDistance = 4.f;
param.volume = 1.f;
audioDevice.PlayLocal(fireFarSound, origin, param);
param.referenceDistance = 1.f;
audioDevice.PlayLocal(fireStereoSound, origin, param);
}
}
void ReloadingWeapon() {
if(!IsMuted){
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 0.2f;
audioDevice.PlayLocal(reloadSound, origin, param);
}
}
void ReloadingWeapon() {
if (!IsMuted) {
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 0.2f;
audioDevice.PlayLocal(reloadSound, origin, param);
}
}
float GetZPos() {
return 0.2f - AimDownSightStateSmooth * 0.0520f;
}
float GetZPos() { return 0.2f - AimDownSightStateSmooth * 0.0520f; }
// rotates gun matrix to ensure the sight is in
// the center of screen (0, ?, 0).
Matrix4 AdjustToAlignSight(Matrix4 mat, Vector3 sightPos, float fade) {
Vector3 p = mat * sightPos;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), atan(p.x / p.y) * fade) * mat;
mat = CreateRotateMatrix(Vector3(-1.f, 0.f, 0.f), atan(p.z / p.y) * fade) * mat;
return mat;
}
// rotates gun matrix to ensure the sight is in
// the center of screen (0, ?, 0).
Matrix4 AdjustToAlignSight(Matrix4 mat, Vector3 sightPos, float fade) {
Vector3 p = mat * sightPos;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), atan(p.x / p.y) * fade) * mat;
mat = CreateRotateMatrix(Vector3(-1.f, 0.f, 0.f), atan(p.z / p.y) * fade) * mat;
return mat;
}
void Draw2D() {
if(AimDownSightState > 0.6)
return;
BasicViewWeapon::Draw2D();
}
void Draw2D() {
if (AimDownSightState > 0.6)
return;
BasicViewWeapon::Draw2D();
}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.033f);
mat = GetViewWeaponMatrix() * mat;
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.033f);
mat = GetViewWeaponMatrix() * mat;
bool reloading = IsReloading;
float reload = ReloadProgress;
Vector3 leftHand, rightHand;
bool reloading = IsReloading;
float reload = ReloadProgress;
Vector3 leftHand, rightHand;
leftHand = mat * Vector3(1.f, 6.f, 1.f);
rightHand = mat * Vector3(0.f, -8.f, 2.f);
leftHand = mat * Vector3(1.f, 6.f, 1.f);
rightHand = mat * Vector3(0.f, -8.f, 2.f);
Vector3 leftHand2 = mat * Vector3(5.f, -10.f, 4.f);
Vector3 rightHand3 = mat * Vector3(-2.f, -7.f, -4.f);
Vector3 rightHand4 = mat * Vector3(-3.f, -4.f, -6.f);
Vector3 leftHand2 = mat * Vector3(5.f, -10.f, 4.f);
Vector3 rightHand3 = mat * Vector3(-2.f, -7.f, -4.f);
Vector3 rightHand4 = mat * Vector3(-3.f, -4.f, -6.f);
if(AimDownSightStateSmooth > 0.8f){
mat = AdjustToAlignSight(mat, Vector3(0.f, 16.f, -4.6f), (AimDownSightStateSmooth - 0.8f) / 0.2f);
}
if (AimDownSightStateSmooth > 0.8f) {
mat = AdjustToAlignSight(mat, Vector3(0.f, 16.f, -4.6f),
(AimDownSightStateSmooth - 0.8f) / 0.2f);
}
ModelRenderParam param;
Matrix4 weapMatrix = eyeMatrix * mat;
param.matrix = weapMatrix * CreateScaleMatrix(0.5f) *
CreateTranslateMatrix(-0.5f, 0.f, 0.f);
param.depthHack = true;
renderer.AddModel(gunModel, param);
ModelRenderParam param;
Matrix4 weapMatrix = eyeMatrix * mat;
param.matrix =
weapMatrix * CreateScaleMatrix(0.5f) * CreateTranslateMatrix(-0.5f, 0.f, 0.f);
param.depthHack = true;
renderer.AddModel(gunModel, param);
// draw sights
Matrix4 sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.0125f, -8.f, -4.5f);
sightMat *= CreateScaleMatrix(0.025f);
param.matrix = sightMat;
renderer.AddModel(sightModel1, param); // rear
// draw sights
Matrix4 sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.0125f, -8.f, -4.5f);
sightMat *= CreateScaleMatrix(0.025f);
param.matrix = sightMat;
renderer.AddModel(sightModel1, param); // rear
sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.025f, 16.f, -4.575f);
sightMat *= CreateScaleMatrix(0.05f);
param.matrix = sightMat;
renderer.AddModel(sightModel2, param); // front pin
sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.025f, 16.f, -4.575f);
sightMat *= CreateScaleMatrix(0.05f);
param.matrix = sightMat;
renderer.AddModel(sightModel2, param); // front pin
// magazine/reload action
mat *= CreateTranslateMatrix(0.f, 1.f, 1.f);
reload *= 2.5f;
if(reloading) {
if(reload < 0.1f){
// move hand to magazine
float per = reload / 0.1f;
leftHand = Mix(leftHand,
mat * Vector3(0.f, 0.f, 4.f),
SmoothStep(per));
}else if(reload < 0.7f){
// magazine release
float per = (reload - 0.1f) / 0.6f;
if(per < 0.2f){
// non-smooth pull out
per *= 4.0f; per -= 0.4f;
per = Clamp(per, 0.0f, 0.2f);
}
if(per > 0.5f) {
// when per = 0.5f, the hand no longer holds the magazine,
// so the free fall starts
per += per - 0.5f;
}
mat *= CreateTranslateMatrix(0.f, 0.f, per*per*10.f);
// magazine/reload action
mat *= CreateTranslateMatrix(0.f, 1.f, 1.f);
reload *= 2.5f;
if (reloading) {
if (reload < 0.1f) {
// move hand to magazine
float per = reload / 0.1f;
leftHand = Mix(leftHand, mat * Vector3(0.f, 0.f, 4.f), SmoothStep(per));
} else if (reload < 0.7f) {
// magazine release
float per = (reload - 0.1f) / 0.6f;
if (per < 0.2f) {
// non-smooth pull out
per *= 4.0f;
per -= 0.4f;
per = Clamp(per, 0.0f, 0.2f);
}
if (per > 0.5f) {
// when per = 0.5f, the hand no longer holds the magazine,
// so the free fall starts
per += per - 0.5f;
}
mat *= CreateTranslateMatrix(0.f, 0.f, per * per * 10.f);
leftHand = mat * Vector3(0.f, 0.f, 4.f);
if(per > 0.5f){
per = (per - 0.5f);
leftHand = Mix(leftHand, leftHand2, SmoothStep(per));
}
}else if(reload < 1.4f) {
// insert magazine
float per = (1.4f - reload) / 0.7f;
if(per < 0.3f) {
// non-smooth insertion
per *= 4.f; per -= 0.4f;
per = Clamp(per, 0.0f, 0.3f);
}
leftHand = mat * Vector3(0.f, 0.f, 4.f);
if (per > 0.5f) {
per = (per - 0.5f);
leftHand = Mix(leftHand, leftHand2, SmoothStep(per));
}
} else if (reload < 1.4f) {
// insert magazine
float per = (1.4f - reload) / 0.7f;
if (per < 0.3f) {
// non-smooth insertion
per *= 4.f;
per -= 0.4f;
per = Clamp(per, 0.0f, 0.3f);
}
mat *= CreateTranslateMatrix(0.f, 0.f, per*per*10.f);
leftHand = mat * Vector3(0.f, 0.f, 4.f);
}else if(reload < 1.9f){
// move the left hand to the original position
// and start doing something with the right hand
float per = (reload - 1.4f) / 0.5f;
Vector3 orig = leftHand;
leftHand = mat * Vector3(0.f, 0.f, 4.f);
leftHand = Mix(leftHand, orig, SmoothStep(per));
rightHand = Mix(rightHand, rightHand3, SmoothStep(per));
}else if(reload < 2.2f){
float per = (reload - 1.9f) / 0.3f;
rightHand = Mix(rightHand3, rightHand4, SmoothStep(per));
}else{
float per = (reload - 2.2f) / 0.3f;
rightHand = Mix(rightHand4, rightHand, SmoothStep(per));
}
}
mat *= CreateTranslateMatrix(0.f, 0.f, per * per * 10.f);
leftHand = mat * Vector3(0.f, 0.f, 4.f);
} else if (reload < 1.9f) {
// move the left hand to the original position
// and start doing something with the right hand
float per = (reload - 1.4f) / 0.5f;
Vector3 orig = leftHand;
leftHand = mat * Vector3(0.f, 0.f, 4.f);
leftHand = Mix(leftHand, orig, SmoothStep(per));
rightHand = Mix(rightHand, rightHand3, SmoothStep(per));
} else if (reload < 2.2f) {
float per = (reload - 1.9f) / 0.3f;
rightHand = Mix(rightHand3, rightHand4, SmoothStep(per));
} else {
float per = (reload - 2.2f) / 0.3f;
rightHand = Mix(rightHand4, rightHand, SmoothStep(per));
}
}
param.matrix = eyeMatrix * mat;
renderer.AddModel(magazineModel, param);
param.matrix = eyeMatrix * mat;
renderer.AddModel(magazineModel, param);
LeftHandPosition = leftHand;
RightHandPosition = rightHand;
}
}
LeftHandPosition = leftHand;
RightHandPosition = rightHand;
}
}
IWeaponSkin@ CreateViewRifleSkin(Renderer@ r, AudioDevice@ dev) {
return ViewRifleSkin(r, dev);
}
IWeaponSkin @CreateViewRifleSkin(Renderer @r, AudioDevice @dev) {
return ViewRifleSkin(r, dev);
}
}

View File

@ -18,184 +18,173 @@
*/
namespace spades {
class ThirdPersonSMGSkin:
IToolSkin, IThirdPersonToolSkin, IWeaponSkin, IWeaponSkin2 {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private bool muted;
private Matrix4 originMatrix;
private float aimDownSightState;
private float readyState;
private bool reloading;
private float reloadProgress;
private int ammo, clipSize;
namespace spades {
class ThirdPersonSMGSkin : IToolSkin, IThirdPersonToolSkin, IWeaponSkin, IWeaponSkin2 {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private bool muted;
private Matrix4 originMatrix;
private float aimDownSightState;
private float readyState;
private bool reloading;
private float reloadProgress;
private int ammo, clipSize;
private float environmentRoom;
private float environmentSize;
private float environmentDistance;
private Vector3 soundOrigin;
private float environmentRoom;
private float environmentSize;
private float environmentDistance;
private Vector3 soundOrigin;
float SprintState {
set { sprintState = value; }
}
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
float RaiseState {
set { raiseState = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
bool IsMuted {
set { muted = value; }
}
bool IsMuted {
set { muted = value; }
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
float PitchBias {
get { return 0.f; }
}
float PitchBias {
get { return 0.f; }
}
float AimDownSightState {
set { aimDownSightState = value; }
}
float AimDownSightState {
set { aimDownSightState = value; }
}
bool IsReloading {
set { reloading = value; }
}
float ReloadProgress {
set { reloadProgress = value; }
}
int Ammo {
set { ammo = value; }
}
int ClipSize {
set { clipSize = value; }
}
bool IsReloading {
set { reloading = value; }
}
float ReloadProgress {
set { reloadProgress = value; }
}
int Ammo {
set { ammo = value; }
}
int ClipSize {
set { clipSize = value; }
}
float ReadyState {
set { readyState = value; }
}
float ReadyState {
set { readyState = value; }
}
// IWeaponSkin2
void SetSoundEnvironment(float room, float size, float distance) {
environmentRoom = room;
environmentSize = size;
environmentDistance = distance;
}
Vector3 SoundOrigin {
set { soundOrigin = value; }
}
// IWeaponSkin2
void SetSoundEnvironment(float room, float size, float distance) {
environmentRoom = room;
environmentSize = size;
environmentDistance = distance;
}
Vector3 SoundOrigin {
set { soundOrigin = value; }
}
private Renderer@ renderer;
private AudioDevice@ audioDevice;
private Model@ model;
private Renderer @renderer;
private AudioDevice @audioDevice;
private Model @model;
private AudioChunk@[] fireMediumSounds(4);
private AudioChunk@ fireFarSound;
private AudioChunk@ fireStereoSound;
private AudioChunk@[] fireSmallReverbSounds(4);
private AudioChunk@[] fireLargeReverbSounds(4);
private AudioChunk@ reloadSound;
private AudioChunk @[] fireMediumSounds(4);
private AudioChunk @fireFarSound;
private AudioChunk @fireStereoSound;
private AudioChunk @[] fireSmallReverbSounds(4);
private AudioChunk @[] fireLargeReverbSounds(4);
private AudioChunk @reloadSound;
ThirdPersonSMGSkin(Renderer@ r, AudioDevice@ dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel
("Models/Weapons/SMG/Weapon.kv6");
ThirdPersonSMGSkin(Renderer @r, AudioDevice @dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel("Models/Weapons/SMG/Weapon.kv6");
@fireMediumSounds[0] = dev.RegisterSound("Sounds/Weapons/SMG/V2Third1.opus");
@fireMediumSounds[1] = dev.RegisterSound("Sounds/Weapons/SMG/V2Third2.opus");
@fireMediumSounds[2] = dev.RegisterSound("Sounds/Weapons/SMG/V2Third3.opus");
@fireMediumSounds[3] = dev.RegisterSound("Sounds/Weapons/SMG/V2Third4.opus");
@fireMediumSounds[0] = dev.RegisterSound
("Sounds/Weapons/SMG/V2Third1.opus");
@fireMediumSounds[1] = dev.RegisterSound
("Sounds/Weapons/SMG/V2Third2.opus");
@fireMediumSounds[2] = dev.RegisterSound
("Sounds/Weapons/SMG/V2Third3.opus");
@fireMediumSounds[3] = dev.RegisterSound
("Sounds/Weapons/SMG/V2Third4.opus");
@fireSmallReverbSounds
[0] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceSmall1.opus");
@fireSmallReverbSounds
[1] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceSmall2.opus");
@fireSmallReverbSounds
[2] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceSmall3.opus");
@fireSmallReverbSounds
[3] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceSmall4.opus");
@fireSmallReverbSounds[0] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceSmall1.opus");
@fireSmallReverbSounds[1] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceSmall2.opus");
@fireSmallReverbSounds[2] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceSmall3.opus");
@fireSmallReverbSounds[3] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceSmall4.opus");
@fireLargeReverbSounds
[0] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceLarge1.opus");
@fireLargeReverbSounds
[1] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceLarge2.opus");
@fireLargeReverbSounds
[2] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceLarge3.opus");
@fireLargeReverbSounds
[3] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceLarge4.opus");
@fireLargeReverbSounds[0] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceLarge1.opus");
@fireLargeReverbSounds[1] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceLarge2.opus");
@fireLargeReverbSounds[2] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceLarge3.opus");
@fireLargeReverbSounds[3] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceLarge4.opus");
@fireFarSound = dev.RegisterSound("Sounds/Weapons/SMG/FireFar.opus");
@fireStereoSound = dev.RegisterSound("Sounds/Weapons/SMG/FireStereo.opus");
@reloadSound = dev.RegisterSound("Sounds/Weapons/SMG/Reload.opus");
}
@fireFarSound = dev.RegisterSound
("Sounds/Weapons/SMG/FireFar.opus");
@fireStereoSound = dev.RegisterSound
("Sounds/Weapons/SMG/FireStereo.opus");
@reloadSound = dev.RegisterSound
("Sounds/Weapons/SMG/Reload.opus");
void Update(float dt) {}
}
void WeaponFired() {
if (!muted) {
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 9.f;
audioDevice.Play(fireMediumSounds[GetRandom(fireMediumSounds.length)], origin,
param);
void Update(float dt) {
}
param.volume = 8.f * environmentRoom;
param.referenceDistance = 10.f;
if (environmentSize < 0.5f) {
audioDevice.Play(fireSmallReverbSounds[GetRandom(fireSmallReverbSounds.length)],
origin, param);
} else {
audioDevice.Play(fireLargeReverbSounds[GetRandom(fireLargeReverbSounds.length)],
origin, param);
}
void WeaponFired(){
if(!muted){
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 9.f;
audioDevice.Play(fireMediumSounds[GetRandom(fireMediumSounds.length)], origin, param);
param.volume = .4f;
param.referenceDistance = 10.f;
audioDevice.Play(fireFarSound, origin, param);
param.referenceDistance = 1.f;
audioDevice.Play(fireStereoSound, origin, param);
}
}
void ReloadingWeapon() {
if (!muted) {
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 0.2f;
audioDevice.Play(reloadSound, origin, param);
}
}
param.volume = 8.f * environmentRoom;
param.referenceDistance = 10.f;
if (environmentSize < 0.5f) {
audioDevice.Play(fireSmallReverbSounds[GetRandom(fireSmallReverbSounds.length)], origin, param);
} else {
audioDevice.Play(fireLargeReverbSounds[GetRandom(fireLargeReverbSounds.length)], origin, param);
}
void ReloadedWeapon() {}
param.volume = .4f;
param.referenceDistance = 10.f;
audioDevice.Play(fireFarSound, origin, param);
param.referenceDistance = 1.f;
audioDevice.Play(fireStereoSound, origin, param);
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = mat * CreateScaleMatrix(-1.f, -1.f, 1.f);
mat = CreateTranslateMatrix(0.35f, -1.f, 0.0f) * mat;
}
}
void ReloadingWeapon() {
if(!muted){
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 0.2f;
audioDevice.Play(reloadSound, origin, param);
}
}
ModelRenderParam param;
param.matrix = originMatrix * mat;
renderer.AddModel(model, param);
}
}
void ReloadedWeapon() {
}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = mat * CreateScaleMatrix(-1.f, -1.f, 1.f);
mat = CreateTranslateMatrix(0.35f, -1.f, 0.0f) * mat;
ModelRenderParam param;
param.matrix = originMatrix * mat;
renderer.AddModel(model, param);
}
}
IWeaponSkin@ CreateThirdPersonSMGSkin(Renderer@ r, AudioDevice@ dev) {
return ThirdPersonSMGSkin(r, dev);
}
IWeaponSkin @CreateThirdPersonSMGSkin(Renderer @r, AudioDevice @dev) {
return ThirdPersonSMGSkin(r, dev);
}
}

View File

@ -18,213 +18,197 @@
*/
namespace spades {
class ViewSMGSkin:
IToolSkin, IViewToolSkin, IWeaponSkin, IWeaponSkin2,
BasicViewWeapon {
namespace spades {
class ViewSMGSkin : IToolSkin, IViewToolSkin, IWeaponSkin, IWeaponSkin2, BasicViewWeapon {
private AudioDevice@ audioDevice;
private Model@ gunModel;
private Model@ magazineModel;
private Model@ sightModel1;
private Model@ sightModel2;
private Model@ sightModel3;
private AudioDevice @audioDevice;
private Model @gunModel;
private Model @magazineModel;
private Model @sightModel1;
private Model @sightModel2;
private Model @sightModel3;
private AudioChunk@[] fireSounds(4);
private AudioChunk@ fireFarSound;
private AudioChunk@ fireStereoSound;
private AudioChunk@[] fireSmallReverbSounds(4);
private AudioChunk@[] fireLargeReverbSounds(4);
private AudioChunk@ reloadSound;
private AudioChunk @[] fireSounds(4);
private AudioChunk @fireFarSound;
private AudioChunk @fireStereoSound;
private AudioChunk @[] fireSmallReverbSounds(4);
private AudioChunk @[] fireLargeReverbSounds(4);
private AudioChunk @reloadSound;
ViewSMGSkin(Renderer@ r, AudioDevice@ dev){
super(r);
@audioDevice = dev;
@gunModel = renderer.RegisterModel
("Models/Weapons/SMG/WeaponNoMagazine.kv6");
@magazineModel = renderer.RegisterModel
("Models/Weapons/SMG/Magazine.kv6");
@sightModel1 = renderer.RegisterModel
("Models/Weapons/SMG/Sight1.kv6");
@sightModel2 = renderer.RegisterModel
("Models/Weapons/SMG/Sight2.kv6");
@sightModel3 = renderer.RegisterModel
("Models/Weapons/SMG/Sight3.kv6");
ViewSMGSkin(Renderer @r, AudioDevice @dev) {
super(r);
@audioDevice = dev;
@gunModel = renderer.RegisterModel("Models/Weapons/SMG/WeaponNoMagazine.kv6");
@magazineModel = renderer.RegisterModel("Models/Weapons/SMG/Magazine.kv6");
@sightModel1 = renderer.RegisterModel("Models/Weapons/SMG/Sight1.kv6");
@sightModel2 = renderer.RegisterModel("Models/Weapons/SMG/Sight2.kv6");
@sightModel3 = renderer.RegisterModel("Models/Weapons/SMG/Sight3.kv6");
@fireSmallReverbSounds[0] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceSmall1.opus");
@fireSmallReverbSounds[1] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceSmall2.opus");
@fireSmallReverbSounds[2] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceSmall3.opus");
@fireSmallReverbSounds[3] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceSmall4.opus");
@fireSmallReverbSounds
[0] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceSmall1.opus");
@fireSmallReverbSounds
[1] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceSmall2.opus");
@fireSmallReverbSounds
[2] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceSmall3.opus");
@fireSmallReverbSounds
[3] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceSmall4.opus");
@fireLargeReverbSounds[0] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceLarge1.opus");
@fireLargeReverbSounds[1] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceLarge2.opus");
@fireLargeReverbSounds[2] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceLarge3.opus");
@fireLargeReverbSounds[3] = dev.RegisterSound
("Sounds/Weapons/SMG/V2AmbienceLarge4.opus");
@fireLargeReverbSounds
[0] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceLarge1.opus");
@fireLargeReverbSounds
[1] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceLarge2.opus");
@fireLargeReverbSounds
[2] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceLarge3.opus");
@fireLargeReverbSounds
[3] = dev.RegisterSound("Sounds/Weapons/SMG/V2AmbienceLarge4.opus");
@fireSounds[0] = dev.RegisterSound
("Sounds/Weapons/SMG/V2Local1.opus");
@fireSounds[1] = dev.RegisterSound
("Sounds/Weapons/SMG/V2Local2.opus");
@fireSounds[2] = dev.RegisterSound
("Sounds/Weapons/SMG/V2Local3.opus");
@fireSounds[3] = dev.RegisterSound
("Sounds/Weapons/SMG/V2Local4.opus");
@fireFarSound = dev.RegisterSound
("Sounds/Weapons/SMG/FireFar.opus");
@fireStereoSound = dev.RegisterSound
("Sounds/Weapons/SMG/FireStereo.opus");
@reloadSound = dev.RegisterSound
("Sounds/Weapons/SMG/ReloadLocal.opus");
@fireSounds[0] = dev.RegisterSound("Sounds/Weapons/SMG/V2Local1.opus");
@fireSounds[1] = dev.RegisterSound("Sounds/Weapons/SMG/V2Local2.opus");
@fireSounds[2] = dev.RegisterSound("Sounds/Weapons/SMG/V2Local3.opus");
@fireSounds[3] = dev.RegisterSound("Sounds/Weapons/SMG/V2Local4.opus");
@fireFarSound = dev.RegisterSound("Sounds/Weapons/SMG/FireFar.opus");
@fireStereoSound = dev.RegisterSound("Sounds/Weapons/SMG/FireStereo.opus");
@reloadSound = dev.RegisterSound("Sounds/Weapons/SMG/ReloadLocal.opus");
}
}
void Update(float dt) { BasicViewWeapon::Update(dt); }
void Update(float dt) {
BasicViewWeapon::Update(dt);
}
void WeaponFired() {
BasicViewWeapon::WeaponFired();
void WeaponFired(){
BasicViewWeapon::WeaponFired();
if (!IsMuted) {
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 8.f;
audioDevice.PlayLocal(fireSounds[GetRandom(fireSounds.length)], origin, param);
if(!IsMuted){
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 8.f;
audioDevice.PlayLocal(fireSounds[GetRandom(fireSounds.length)], origin, param);
param.volume = 8.f * environmentRoom;
if (environmentSize < 0.5f) {
audioDevice.PlayLocal(
fireSmallReverbSounds[GetRandom(fireSmallReverbSounds.length)], origin,
param);
} else {
audioDevice.PlayLocal(
fireLargeReverbSounds[GetRandom(fireLargeReverbSounds.length)], origin,
param);
}
}
}
param.volume = 8.f * environmentRoom;
if (environmentSize < 0.5f) {
audioDevice.PlayLocal(fireSmallReverbSounds[GetRandom(fireSmallReverbSounds.length)], origin, param);
} else {
audioDevice.PlayLocal(fireLargeReverbSounds[GetRandom(fireLargeReverbSounds.length)], origin, param);
}
}
}
void ReloadingWeapon() {
if (!IsMuted) {
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 0.2f;
audioDevice.PlayLocal(reloadSound, origin, param);
}
}
void ReloadingWeapon() {
if(!IsMuted){
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 0.2f;
audioDevice.PlayLocal(reloadSound, origin, param);
}
}
float GetZPos() { return 0.2f - AimDownSightStateSmooth * 0.038f; }
float GetZPos() {
return 0.2f - AimDownSightStateSmooth * 0.038f;
}
// rotates gun matrix to ensure the sight is in
// the center of screen (0, ?, 0).
Matrix4 AdjustToAlignSight(Matrix4 mat, Vector3 sightPos, float fade) {
Vector3 p = mat * sightPos;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), atan(p.x / p.y) * fade) * mat;
mat = CreateRotateMatrix(Vector3(-1.f, 0.f, 0.f), atan(p.z / p.y) * fade) * mat;
return mat;
}
// rotates gun matrix to ensure the sight is in
// the center of screen (0, ?, 0).
Matrix4 AdjustToAlignSight(Matrix4 mat, Vector3 sightPos, float fade) {
Vector3 p = mat * sightPos;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), atan(p.x / p.y) * fade) * mat;
mat = CreateRotateMatrix(Vector3(-1.f, 0.f, 0.f), atan(p.z / p.y) * fade) * mat;
return mat;
}
void Draw2D() {
if (AimDownSightState > 0.6)
return;
BasicViewWeapon::Draw2D();
}
void Draw2D() {
if(AimDownSightState > 0.6)
return;
BasicViewWeapon::Draw2D();
}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.033f);
mat = GetViewWeaponMatrix() * mat;
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.033f);
mat = GetViewWeaponMatrix() * mat;
bool reloading = IsReloading;
float reload = ReloadProgress;
Vector3 leftHand, rightHand;
bool reloading = IsReloading;
float reload = ReloadProgress;
Vector3 leftHand, rightHand;
leftHand = mat * Vector3(1.f, 6.f, 1.f);
rightHand = mat * Vector3(0.f, -8.f, 4.f);
leftHand = mat * Vector3(1.f, 6.f, 1.f);
rightHand = mat * Vector3(0.f, -8.f, 4.f);
Vector3 leftHand2 = mat * Vector3(5.f, -10.f, 4.f);
Vector3 leftHand3 = mat * Vector3(1.f, 6.f, -4.f);
Vector3 leftHand4 = mat * Vector3(1.f, 9.f, -6.f);
Vector3 leftHand2 = mat * Vector3(5.f, -10.f, 4.f);
Vector3 leftHand3 = mat * Vector3(1.f, 6.f, -4.f);
Vector3 leftHand4 = mat * Vector3(1.f, 9.f, -6.f);
if (AimDownSightStateSmooth > 0.8f) {
mat = AdjustToAlignSight(mat, Vector3(0.f, 5.f, -4.9f),
(AimDownSightStateSmooth - 0.8f) / 0.2f);
}
if(AimDownSightStateSmooth > 0.8f){
mat = AdjustToAlignSight(mat, Vector3(0.f, 5.f, -4.9f), (AimDownSightStateSmooth - 0.8f) / 0.2f);
}
ModelRenderParam param;
Matrix4 weapMatrix = eyeMatrix * mat;
param.matrix = weapMatrix;
param.depthHack = true;
renderer.AddModel(gunModel, param);
ModelRenderParam param;
Matrix4 weapMatrix = eyeMatrix * mat;
param.matrix = weapMatrix;
param.depthHack = true;
renderer.AddModel(gunModel, param);
// draw sights
Matrix4 sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.05f, 5.f, -4.85f);
sightMat *= CreateScaleMatrix(0.1f);
param.matrix = sightMat;
renderer.AddModel(sightModel1, param); // front
// draw sights
Matrix4 sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.05f, 5.f, -4.85f);
sightMat *= CreateScaleMatrix(0.1f);
param.matrix = sightMat;
renderer.AddModel(sightModel1, param); // front
sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.025f, 5.f, -4.875f);
sightMat *= CreateScaleMatrix(0.05f);
param.matrix = sightMat;
renderer.AddModel(sightModel3, param); // front pin
sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.025f, 5.f, -4.875f);
sightMat *= CreateScaleMatrix(0.05f);
param.matrix = sightMat;
renderer.AddModel(sightModel3, param); // front pin
sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.04f, -9.f, -4.9f);
sightMat *= CreateScaleMatrix(0.08f);
param.matrix = sightMat;
renderer.AddModel(sightModel2, param); // rear
sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.04f, -9.f, -4.9f);
sightMat *= CreateScaleMatrix(0.08f);
param.matrix = sightMat;
renderer.AddModel(sightModel2, param); // rear
// magazine/reload action
mat *= CreateTranslateMatrix(0.f, 3.f, 1.f);
reload *= 2.5f;
if (reloading) {
if (reload < 0.7f) {
// magazine release
float per = reload / 0.7f;
mat *= CreateTranslateMatrix(0.f, 0.f, per * per * 50.f);
leftHand = Mix(leftHand, leftHand2, SmoothStep(per));
} else if (reload < 1.4f) {
// insert magazine
float per = (1.4f - reload) / 0.7f;
if (per < 0.3f) {
// non-smooth insertion
per *= 4.f;
per -= 0.4f;
per = Clamp(per, 0.0f, 0.3f);
}
// magazine/reload action
mat *= CreateTranslateMatrix(0.f, 3.f, 1.f);
reload *= 2.5f;
if(reloading) {
if(reload < 0.7f){
// magazine release
float per = reload / 0.7f;
mat *= CreateTranslateMatrix(0.f, 0.f, per*per*50.f);
leftHand = Mix(leftHand, leftHand2, SmoothStep(per));
}else if(reload < 1.4f) {
// insert magazine
float per = (1.4f - reload) / 0.7f;
if(per < 0.3f) {
// non-smooth insertion
per *= 4.f; per -= 0.4f;
per = Clamp(per, 0.0f, 0.3f);
}
mat *= CreateTranslateMatrix(0.f, 0.f, per * per * 10.f);
leftHand = mat * Vector3(0.f, 0.f, 4.f);
} else if (reload < 1.9f) {
// move the left hand to the original position
// and start doing something with the right hand
float per = (reload - 1.4f) / 0.5f;
leftHand = mat * Vector3(0.f, 0.f, 4.f);
leftHand = Mix(leftHand, leftHand3, SmoothStep(per));
} else if (reload < 2.2f) {
float per = (reload - 1.9f) / 0.3f;
leftHand = Mix(leftHand3, leftHand4, SmoothStep(per));
} else {
float per = (reload - 2.2f) / 0.3f;
leftHand = Mix(leftHand4, leftHand, SmoothStep(per));
}
}
mat *= CreateTranslateMatrix(0.f, 0.f, per*per*10.f);
leftHand = mat * Vector3(0.f, 0.f, 4.f);
}else if(reload < 1.9f){
// move the left hand to the original position
// and start doing something with the right hand
float per = (reload - 1.4f) / 0.5f;
leftHand = mat * Vector3(0.f, 0.f, 4.f);
leftHand = Mix(leftHand, leftHand3, SmoothStep(per));
}else if(reload < 2.2f){
float per = (reload - 1.9f) / 0.3f;
leftHand = Mix(leftHand3, leftHand4, SmoothStep(per));
}else{
float per = (reload - 2.2f) / 0.3f;
leftHand = Mix(leftHand4, leftHand, SmoothStep(per));
}
}
param.matrix = eyeMatrix * mat;
renderer.AddModel(magazineModel, param);
param.matrix = eyeMatrix * mat;
renderer.AddModel(magazineModel, param);
LeftHandPosition = leftHand;
RightHandPosition = rightHand;
}
}
LeftHandPosition = leftHand;
RightHandPosition = rightHand;
}
}
IWeaponSkin@ CreateViewSMGSkin(Renderer@ r, AudioDevice@ dev) {
return ViewSMGSkin(r, dev);
}
IWeaponSkin @CreateViewSMGSkin(Renderer @r, AudioDevice @dev) { return ViewSMGSkin(r, dev); }
}

View File

@ -18,170 +18,161 @@
*/
namespace spades {
class ThirdPersonShotgunSkin:
IToolSkin, IThirdPersonToolSkin, IWeaponSkin, IWeaponSkin2 {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private bool muted;
private Matrix4 originMatrix;
private float aimDownSightState;
private float readyState;
private bool reloading;
private float reloadProgress;
private int ammo, clipSize;
namespace spades {
class ThirdPersonShotgunSkin : IToolSkin, IThirdPersonToolSkin, IWeaponSkin, IWeaponSkin2 {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private bool muted;
private Matrix4 originMatrix;
private float aimDownSightState;
private float readyState;
private bool reloading;
private float reloadProgress;
private int ammo, clipSize;
private float environmentRoom;
private float environmentSize;
private float environmentDistance;
private Vector3 soundOrigin;
private float environmentRoom;
private float environmentSize;
private float environmentDistance;
private Vector3 soundOrigin;
float SprintState {
set { sprintState = value; }
}
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
float RaiseState {
set { raiseState = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
bool IsMuted {
set { muted = value; }
}
bool IsMuted {
set { muted = value; }
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
float PitchBias {
get { return 0.f; }
}
float PitchBias {
get { return 0.f; }
}
float AimDownSightState {
set { aimDownSightState = value; }
}
float AimDownSightState {
set { aimDownSightState = value; }
}
bool IsReloading {
set { reloading = value; }
}
float ReloadProgress {
set { reloadProgress = value; }
}
int Ammo {
set { ammo = value; }
}
int ClipSize {
set { clipSize = value; }
}
bool IsReloading {
set { reloading = value; }
}
float ReloadProgress {
set { reloadProgress = value; }
}
int Ammo {
set { ammo = value; }
}
int ClipSize {
set { clipSize = value; }
}
float ReadyState {
set { readyState = value; }
}
float ReadyState {
set { readyState = value; }
}
// IWeaponSkin2
void SetSoundEnvironment(float room, float size, float distance) {
environmentRoom = room;
environmentSize = size;
environmentDistance = distance;
}
Vector3 SoundOrigin {
set { soundOrigin = value; }
}
// IWeaponSkin2
void SetSoundEnvironment(float room, float size, float distance) {
environmentRoom = room;
environmentSize = size;
environmentDistance = distance;
}
Vector3 SoundOrigin {
set { soundOrigin = value; }
}
private Renderer@ renderer;
private AudioDevice@ audioDevice;
private Model@ model;
private Renderer @renderer;
private AudioDevice @audioDevice;
private Model @model;
private AudioChunk@ fireSound;
private AudioChunk@ fireFarSound;
private AudioChunk@ fireStereoSound;
private AudioChunk@ fireSmallReverbSound;
private AudioChunk@ fireLargeReverbSound;
private AudioChunk@ reloadSound;
private AudioChunk@ cockSound;
private AudioChunk @fireSound;
private AudioChunk @fireFarSound;
private AudioChunk @fireStereoSound;
private AudioChunk @fireSmallReverbSound;
private AudioChunk @fireLargeReverbSound;
private AudioChunk @reloadSound;
private AudioChunk @cockSound;
ThirdPersonShotgunSkin(Renderer@ r, AudioDevice@ dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel
("Models/Weapons/Shotgun/Weapon.kv6");
ThirdPersonShotgunSkin(Renderer @r, AudioDevice @dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel("Models/Weapons/Shotgun/Weapon.kv6");
@fireSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/Fire.opus");
@fireFarSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/FireFar.opus");
@fireStereoSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/FireStereo.opus");
@reloadSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/Reload.opus");
@cockSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/Cock.opus");
@fireSound = dev.RegisterSound("Sounds/Weapons/Shotgun/Fire.opus");
@fireFarSound = dev.RegisterSound("Sounds/Weapons/Shotgun/FireFar.opus");
@fireStereoSound = dev.RegisterSound("Sounds/Weapons/Shotgun/FireStereo.opus");
@reloadSound = dev.RegisterSound("Sounds/Weapons/Shotgun/Reload.opus");
@cockSound = dev.RegisterSound("Sounds/Weapons/Shotgun/Cock.opus");
@fireSmallReverbSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/V2AmbienceSmall.opus");
@fireLargeReverbSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/V2AmbienceLarge.opus");
}
@fireSmallReverbSound
= dev.RegisterSound("Sounds/Weapons/Shotgun/V2AmbienceSmall.opus");
@fireLargeReverbSound
= dev.RegisterSound("Sounds/Weapons/Shotgun/V2AmbienceLarge.opus");
}
void Update(float dt) {
}
void Update(float dt) {}
void WeaponFired(){
if(!muted){
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 8.f;
audioDevice.Play(fireSound, origin, param);
void WeaponFired() {
if (!muted) {
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 8.f;
audioDevice.Play(fireSound, origin, param);
param.volume = 8.f * environmentRoom;
if (environmentSize < 0.5f) {
audioDevice.Play(fireSmallReverbSound, origin, param);
} else {
audioDevice.Play(fireLargeReverbSound, origin, param);
}
param.volume = 8.f * environmentRoom;
if (environmentSize < 0.5f) {
audioDevice.Play(fireSmallReverbSound, origin, param);
} else {
audioDevice.Play(fireLargeReverbSound, origin, param);
}
param.volume = 2.f;
param.referenceDistance = 4.f;
audioDevice.Play(fireFarSound, origin, param);
param.referenceDistance = 1.f;
audioDevice.Play(fireStereoSound, origin, param);
param.volume = 2.f;
param.referenceDistance = 4.f;
audioDevice.Play(fireFarSound, origin, param);
param.referenceDistance = 1.f;
audioDevice.Play(fireStereoSound, origin, param);
}
}
void ReloadingWeapon() {
if (!muted) {
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 0.2f;
audioDevice.Play(reloadSound, origin, param);
}
}
}
}
void ReloadingWeapon() {
if(!muted){
Vector3 origin = soundOrigin;
AudioParam param;
param.volume = 0.2f;
audioDevice.Play(reloadSound, origin, param);
}
}
void ReloadedWeapon() {
if (!muted) {
Vector3 origin = originMatrix * Vector3(0.f, 0.f, 0.f);
AudioParam param;
param.volume = 0.2f;
audioDevice.Play(cockSound, origin, param);
}
}
void ReloadedWeapon() {
if(!muted){
Vector3 origin = originMatrix * Vector3(0.f, 0.f, 0.f);
AudioParam param;
param.volume = 0.2f;
audioDevice.Play(cockSound, origin, param);
}
}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = mat * CreateScaleMatrix(-1.f, -1.f, 1.f);
mat = CreateTranslateMatrix(0.35f, -1.f, 0.0f) * mat;
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = mat * CreateScaleMatrix(-1.f, -1.f, 1.f);
mat = CreateTranslateMatrix(0.35f, -1.f, 0.0f) * mat;
ModelRenderParam param;
param.matrix = originMatrix * mat;
renderer.AddModel(model, param);
}
}
ModelRenderParam param;
param.matrix = originMatrix * mat;
renderer.AddModel(model, param);
}
}
IWeaponSkin@ CreateThirdPersonShotgunSkin(Renderer@ r, AudioDevice@ dev) {
return ThirdPersonShotgunSkin(r, dev);
}
IWeaponSkin @CreateThirdPersonShotgunSkin(Renderer @r, AudioDevice @dev) {
return ThirdPersonShotgunSkin(r, dev);
}
}

View File

@ -18,231 +18,211 @@
*/
namespace spades {
class ViewShotgunSkin:
IToolSkin, IViewToolSkin, IWeaponSkin,
BasicViewWeapon {
namespace spades {
class ViewShotgunSkin : IToolSkin, IViewToolSkin, IWeaponSkin, BasicViewWeapon {
private AudioDevice@ audioDevice;
private Model@ gunModel;
private Model@ pumpModel;
private Model@ sightModel1;
private Model@ sightModel2;
private AudioDevice @audioDevice;
private Model @gunModel;
private Model @pumpModel;
private Model @sightModel1;
private Model @sightModel2;
private AudioChunk@ fireSound;
private AudioChunk@ fireFarSound;
private AudioChunk@ fireStereoSound;
private AudioChunk@ fireSmallReverbSound;
private AudioChunk@ fireLargeReverbSound;
private AudioChunk@ reloadSound;
private AudioChunk@ cockSound;
private AudioChunk @fireSound;
private AudioChunk @fireFarSound;
private AudioChunk @fireStereoSound;
private AudioChunk @fireSmallReverbSound;
private AudioChunk @fireLargeReverbSound;
private AudioChunk @reloadSound;
private AudioChunk @cockSound;
ViewShotgunSkin(Renderer@ r, AudioDevice@ dev){
super(r);
@audioDevice = dev;
@gunModel = renderer.RegisterModel
("Models/Weapons/Shotgun/WeaponNoPump.kv6");
@pumpModel = renderer.RegisterModel
("Models/Weapons/Shotgun/Pump.kv6");
@sightModel1 = renderer.RegisterModel
("Models/Weapons/Shotgun/Sight1.kv6");
@sightModel2 = renderer.RegisterModel
("Models/Weapons/Shotgun/Sight2.kv6");
ViewShotgunSkin(Renderer @r, AudioDevice @dev) {
super(r);
@audioDevice = dev;
@gunModel = renderer.RegisterModel("Models/Weapons/Shotgun/WeaponNoPump.kv6");
@pumpModel = renderer.RegisterModel("Models/Weapons/Shotgun/Pump.kv6");
@sightModel1 = renderer.RegisterModel("Models/Weapons/Shotgun/Sight1.kv6");
@sightModel2 = renderer.RegisterModel("Models/Weapons/Shotgun/Sight2.kv6");
@fireSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/FireLocal.opus");
@fireFarSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/FireFar.opus");
@fireStereoSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/FireStereo.opus");
@reloadSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/ReloadLocal.opus");
@cockSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/CockLocal.opus");
@fireSound = dev.RegisterSound("Sounds/Weapons/Shotgun/FireLocal.opus");
@fireFarSound = dev.RegisterSound("Sounds/Weapons/Shotgun/FireFar.opus");
@fireStereoSound = dev.RegisterSound("Sounds/Weapons/Shotgun/FireStereo.opus");
@reloadSound = dev.RegisterSound("Sounds/Weapons/Shotgun/ReloadLocal.opus");
@cockSound = dev.RegisterSound("Sounds/Weapons/Shotgun/CockLocal.opus");
@fireSmallReverbSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/V2AmbienceSmall.opus");
@fireLargeReverbSound = dev.RegisterSound
("Sounds/Weapons/Shotgun/V2AmbienceLarge.opus");
}
@fireSmallReverbSound
= dev.RegisterSound("Sounds/Weapons/Shotgun/V2AmbienceSmall.opus");
@fireLargeReverbSound
= dev.RegisterSound("Sounds/Weapons/Shotgun/V2AmbienceLarge.opus");
}
void Update(float dt) {
BasicViewWeapon::Update(dt);
}
void Update(float dt) { BasicViewWeapon::Update(dt); }
void WeaponFired(){
BasicViewWeapon::WeaponFired();
void WeaponFired() {
BasicViewWeapon::WeaponFired();
if(!IsMuted){
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 8.f;
audioDevice.PlayLocal(fireSound, origin, param);
if (!IsMuted) {
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 8.f;
audioDevice.PlayLocal(fireSound, origin, param);
param.volume = 8.f * environmentRoom;
if (environmentSize < 0.5f) {
audioDevice.PlayLocal(fireSmallReverbSound, origin, param);
} else {
audioDevice.PlayLocal(fireLargeReverbSound, origin, param);
}
param.volume = 8.f * environmentRoom;
if (environmentSize < 0.5f) {
audioDevice.PlayLocal(fireSmallReverbSound, origin, param);
} else {
audioDevice.PlayLocal(fireLargeReverbSound, origin, param);
}
param.volume = 2.f;
audioDevice.PlayLocal(fireFarSound, origin, param);
audioDevice.PlayLocal(fireStereoSound, origin, param);
}
}
param.volume = 2.f;
audioDevice.PlayLocal(fireFarSound, origin, param);
audioDevice.PlayLocal(fireStereoSound, origin, param);
}
}
void ReloadingWeapon() {
if(!IsMuted){
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 0.2f;
audioDevice.PlayLocal(reloadSound, origin, param);
}
}
void ReloadingWeapon() {
if (!IsMuted) {
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 0.2f;
audioDevice.PlayLocal(reloadSound, origin, param);
}
}
void ReloadedWeapon() {
if(!IsMuted){
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 0.2f;
audioDevice.PlayLocal(cockSound, origin, param);
}
}
void ReloadedWeapon() {
if (!IsMuted) {
Vector3 origin = Vector3(0.4f, -0.3f, 0.5f);
AudioParam param;
param.volume = 0.2f;
audioDevice.PlayLocal(cockSound, origin, param);
}
}
float GetZPos() {
return 0.2f - AimDownSightStateSmooth * 0.0535f;
}
float GetZPos() { return 0.2f - AimDownSightStateSmooth * 0.0535f; }
// rotates gun matrix to ensure the sight is in
// the center of screen (0, ?, 0).
Matrix4 AdjustToAlignSight(Matrix4 mat, Vector3 sightPos, float fade) {
Vector3 p = mat * sightPos;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), atan(p.x / p.y) * fade) * mat;
mat = CreateRotateMatrix(Vector3(-1.f, 0.f, 0.f), atan(p.z / p.y) * fade) * mat;
return mat;
}
// rotates gun matrix to ensure the sight is in
// the center of screen (0, ?, 0).
Matrix4 AdjustToAlignSight(Matrix4 mat, Vector3 sightPos, float fade) {
Vector3 p = mat * sightPos;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), atan(p.x / p.y) * fade) * mat;
mat = CreateRotateMatrix(Vector3(-1.f, 0.f, 0.f), atan(p.z / p.y) * fade) * mat;
return mat;
}
void Draw2D() {
if(AimDownSightState > 0.6)
return;
BasicViewWeapon::Draw2D();
}
void Draw2D() {
if (AimDownSightState > 0.6)
return;
BasicViewWeapon::Draw2D();
}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.033f);
mat = GetViewWeaponMatrix() * mat;
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.033f);
mat = GetViewWeaponMatrix() * mat;
bool reloading = IsReloading;
float reload = ReloadProgress;
Vector3 leftHand, rightHand;
bool reloading = IsReloading;
float reload = ReloadProgress;
Vector3 leftHand, rightHand;
rightHand = mat * Vector3(0.f, -8.f, 2.f);
rightHand = mat * Vector3(0.f, -8.f, 2.f);
Vector3 leftHand2 = mat * Vector3(5.f, -10.f, 4.f);
Vector3 leftHand3 = mat * Vector3(1.f, 1.f, 2.f);
Vector3 leftHand2 = mat * Vector3(5.f, -10.f, 4.f);
Vector3 leftHand3 = mat * Vector3(1.f, 1.f, 2.f);
if(AimDownSightStateSmooth > 0.8f){
mat = AdjustToAlignSight(mat, Vector3(0.f, 8.5f, -4.4f),
(AimDownSightStateSmooth - 0.8f) / 0.2f);
}
if (AimDownSightStateSmooth > 0.8f) {
mat = AdjustToAlignSight(mat, Vector3(0.f, 8.5f, -4.4f),
(AimDownSightStateSmooth - 0.8f) / 0.2f);
}
ModelRenderParam param;
Matrix4 weapMatrix = eyeMatrix * mat;
param.matrix = weapMatrix;
param.depthHack = true;
renderer.AddModel(gunModel, param);
ModelRenderParam param;
Matrix4 weapMatrix = eyeMatrix * mat;
param.matrix = weapMatrix;
param.depthHack = true;
renderer.AddModel(gunModel, param);
// draw sights
Matrix4 sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.025f, -9.f, -4.4f);
sightMat *= CreateScaleMatrix(0.05f);
param.matrix = sightMat;
renderer.AddModel(sightModel2, param); // rear
// draw sights
Matrix4 sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.025f, -9.f, -4.4f);
sightMat *= CreateScaleMatrix(0.05f);
param.matrix = sightMat;
renderer.AddModel(sightModel2, param); // rear
sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.025f, 8.5f, -4.4f);
sightMat *= CreateScaleMatrix(0.05f);
param.matrix = sightMat;
renderer.AddModel(sightModel1, param); // front pin
sightMat = weapMatrix;
sightMat *= CreateTranslateMatrix(0.025f, 8.5f, -4.4f);
sightMat *= CreateScaleMatrix(0.05f);
param.matrix = sightMat;
renderer.AddModel(sightModel1, param); // front pin
// reload action
reload *= 0.5f;
leftHand = mat * Vector3(0.f, 4.f, 2.f);
// reload action
reload *= 0.5f;
leftHand = mat * Vector3(0.f, 4.f, 2.f);
if(reloading) {
if(reload < 0.2f) {
float per = reload / 0.2f;
leftHand = Mix(leftHand, leftHand2,
SmoothStep(per));
}else if(reload < 0.35f){
float per = (reload - 0.2f) / 0.15f;
leftHand = Mix(leftHand2, leftHand3,
SmoothStep(per));
}else if(reload < 0.5f){
float per = (reload - 0.35f) / 0.15f;
leftHand = Mix(leftHand3, leftHand,
SmoothStep(per));
}
}
if (reloading) {
if (reload < 0.2f) {
float per = reload / 0.2f;
leftHand = Mix(leftHand, leftHand2, SmoothStep(per));
} else if (reload < 0.35f) {
float per = (reload - 0.2f) / 0.15f;
leftHand = Mix(leftHand2, leftHand3, SmoothStep(per));
} else if (reload < 0.5f) {
float per = (reload - 0.35f) / 0.15f;
leftHand = Mix(leftHand3, leftHand, SmoothStep(per));
}
}
// motion blending parameter
float cockFade = 1.f;
if(reloading){
if(reload < 0.25f ||
ammo < (clipSize - 1)) {
cockFade = 0.f;
}else{
cockFade = (reload - 0.25f) * 10.f;
cockFade = Min(cockFade, 1.f);
}
}
// motion blending parameter
float cockFade = 1.f;
if (reloading) {
if (reload < 0.25f || ammo < (clipSize - 1)) {
cockFade = 0.f;
} else {
cockFade = (reload - 0.25f) * 10.f;
cockFade = Min(cockFade, 1.f);
}
}
if(cockFade > 0.f){
float cock = 0.f;
float tim = 1.f - readyState;
if(tim < 0.f){
// might be right after reloading
if(ammo >= clipSize && reload > 0.5f && reload < 1.f){
tim = reload - 0.5f;
if(tim < 0.05f){
cock = 0.f;
}else if(tim < 0.12f){
cock = (tim - 0.05f) / 0.07f;
}else if(tim < 0.26f){
cock = 1.f;
}else if(tim < 0.36f){
cock = 1.f - (tim - 0.26f) / 0.1f;
}
}
}else if(tim < 0.2f){
cock = 0.f;
}else if(tim < 0.3f){
cock = (tim - 0.2f) / 0.1f;
}else if(tim < 0.42f){
cock = 1.f;
}else if(tim < 0.52f){
cock = 1.f - (tim - 0.42f) / 0.1f;
}else{
cock = 0.f;
}
if (cockFade > 0.f) {
float cock = 0.f;
float tim = 1.f - readyState;
if (tim < 0.f) {
// might be right after reloading
if (ammo >= clipSize && reload > 0.5f && reload < 1.f) {
tim = reload - 0.5f;
if (tim < 0.05f) {
cock = 0.f;
} else if (tim < 0.12f) {
cock = (tim - 0.05f) / 0.07f;
} else if (tim < 0.26f) {
cock = 1.f;
} else if (tim < 0.36f) {
cock = 1.f - (tim - 0.26f) / 0.1f;
}
}
} else if (tim < 0.2f) {
cock = 0.f;
} else if (tim < 0.3f) {
cock = (tim - 0.2f) / 0.1f;
} else if (tim < 0.42f) {
cock = 1.f;
} else if (tim < 0.52f) {
cock = 1.f - (tim - 0.42f) / 0.1f;
} else {
cock = 0.f;
}
cock *= cockFade;
mat = mat * CreateTranslateMatrix(0.f, cock * -1.5f, 0.f);
cock *= cockFade;
mat = mat * CreateTranslateMatrix(0.f, cock * -1.5f, 0.f);
leftHand = Mix(leftHand,
mat * Vector3(0.f, 4.f, 2.f), cockFade);
}
leftHand = Mix(leftHand, mat * Vector3(0.f, 4.f, 2.f), cockFade);
}
param.matrix = eyeMatrix * mat;
renderer.AddModel(pumpModel, param);
param.matrix = eyeMatrix * mat;
renderer.AddModel(pumpModel, param);
LeftHandPosition = leftHand;
RightHandPosition = rightHand;
}
}
LeftHandPosition = leftHand;
RightHandPosition = rightHand;
}
}
IWeaponSkin@ CreateViewShotgunSkin(Renderer@ r, AudioDevice@ dev) {
return ViewShotgunSkin(r, dev);
}
IWeaponSkin @CreateViewShotgunSkin(Renderer @r, AudioDevice @dev) {
return ViewShotgunSkin(r, dev);
}
}

View File

@ -1,23 +1,23 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BasicViewWeapon.as"
#include "Spade/ThirdPerson.as"
#include "Spade/View.as"

View File

@ -1,103 +1,98 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
namespace spades {
class ThirdPersonSpadeSkin:
IToolSkin, IThirdPersonToolSkin, ISpadeSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 originMatrix;
private SpadeActionType actionType;
private float actionProgress;
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
bool IsMuted {
set {
// nothing to do
}
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
float PitchBias {
get {
float pitch = 0.f;
if(actionType == spades::SpadeActionType::Bash) {
float per = 1.f - actionProgress;
pitch -= per * 0.7f;
}
return pitch;
}
}
SpadeActionType ActionType {
set { actionType = value; }
}
float ActionProgress {
set { actionProgress = value; }
}
private Renderer@ renderer;
private AudioDevice@ audioDevice;
private Model@ model;
ThirdPersonSpadeSkin(Renderer@ r, AudioDevice@ dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel
("Models/Weapons/Spade/Spade.kv6");
}
void Update(float dt) {
}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = CreateRotateMatrix(Vector3(0.f,0.f,1.f), Pi) * mat;
mat = CreateTranslateMatrix(0.35f, -1.f, 0.f) * mat;
ModelRenderParam param;
param.matrix = originMatrix * mat;
renderer.AddModel(model, param);
}
}
ISpadeSkin@ CreateThirdPersonSpadeSkin(Renderer@ r, AudioDevice@ dev) {
return ThirdPersonSpadeSkin(r, dev);
}
namespace spades {
class ThirdPersonSpadeSkin : IToolSkin, IThirdPersonToolSkin, ISpadeSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 originMatrix;
private SpadeActionType actionType;
private float actionProgress;
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
bool IsMuted {
set {
// nothing to do
}
}
Matrix4 OriginMatrix {
set { originMatrix = value; }
}
float PitchBias {
get {
float pitch = 0.f;
if (actionType == spades::SpadeActionType::Bash) {
float per = 1.f - actionProgress;
pitch -= per * 0.7f;
}
return pitch;
}
}
SpadeActionType ActionType {
set { actionType = value; }
}
float ActionProgress {
set { actionProgress = value; }
}
private Renderer @renderer;
private AudioDevice @audioDevice;
private Model @model;
ThirdPersonSpadeSkin(Renderer @r, AudioDevice @dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel("Models/Weapons/Spade/Spade.kv6");
}
void Update(float dt) {}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.05f);
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), Pi) * mat;
mat = CreateTranslateMatrix(0.35f, -1.f, 0.f) * mat;
ModelRenderParam param;
param.matrix = originMatrix * mat;
renderer.AddModel(model, param);
}
}
ISpadeSkin @CreateThirdPersonSpadeSkin(Renderer @r, AudioDevice @dev) {
return ThirdPersonSpadeSkin(r, dev);
}
}

View File

@ -18,177 +18,162 @@
*/
namespace spades {
class ViewSpadeSkin:
IToolSkin, IViewToolSkin, ISpadeSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 eyeMatrix;
private Vector3 swing;
private Vector3 leftHand;
private Vector3 rightHand;
private SpadeActionType actionType;
private float actionProgress;
namespace spades {
class ViewSpadeSkin : IToolSkin, IViewToolSkin, ISpadeSkin {
private float sprintState;
private float raiseState;
private Vector3 teamColor;
private Matrix4 eyeMatrix;
private Vector3 swing;
private Vector3 leftHand;
private Vector3 rightHand;
private SpadeActionType actionType;
private float actionProgress;
private float sprintStateSmooth;
private float sprintStateSmooth;
float SprintState {
set { sprintState = value; }
}
float SprintState {
set { sprintState = value; }
}
float RaiseState {
set { raiseState = value; }
}
float RaiseState {
set { raiseState = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
Vector3 TeamColor {
set { teamColor = value; }
}
bool IsMuted {
set {
// nothing to do
}
}
bool IsMuted {
set {
// nothing to do
}
}
Matrix4 EyeMatrix {
set { eyeMatrix = value; }
}
Matrix4 EyeMatrix {
set { eyeMatrix = value; }
}
Vector3 Swing {
set { swing = value; }
}
Vector3 Swing {
set { swing = value; }
}
Vector3 LeftHandPosition {
get {
return leftHand;
}
}
Vector3 RightHandPosition {
get {
return rightHand;
}
}
Vector3 LeftHandPosition {
get { return leftHand; }
}
Vector3 RightHandPosition {
get { return rightHand; }
}
SpadeActionType ActionType {
set { actionType = value; }
}
SpadeActionType ActionType {
set { actionType = value; }
}
float ActionProgress {
set { actionProgress = value; }
}
float ActionProgress {
set { actionProgress = value; }
}
private Renderer@ renderer;
private AudioDevice@ audioDevice;
private Model@ model;
private Image@ sightImage;
private Renderer @renderer;
private AudioDevice @audioDevice;
private Model @model;
private Image @sightImage;
ViewSpadeSkin(Renderer@ r, AudioDevice@ dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel
("Models/Weapons/Spade/Spade.kv6");
@sightImage = renderer.RegisterImage
("Gfx/Sight.tga");
}
ViewSpadeSkin(Renderer @r, AudioDevice @dev) {
@renderer = r;
@audioDevice = dev;
@model = renderer.RegisterModel("Models/Weapons/Spade/Spade.kv6");
@sightImage = renderer.RegisterImage("Gfx/Sight.tga");
}
void Update(float dt) {
float sprintStateSS = sprintState * sprintState;
if (sprintStateSS > sprintStateSmooth) {
sprintStateSmooth += (sprintStateSS - sprintStateSmooth) * (1.f - pow(0.001, dt));
} else {
sprintStateSmooth = sprintStateSS;
}
}
void Update(float dt) {
float sprintStateSS = sprintState * sprintState;
if (sprintStateSS > sprintStateSmooth) {
sprintStateSmooth += (sprintStateSS - sprintStateSmooth) * (1.f - pow(0.001, dt));
} else {
sprintStateSmooth = sprintStateSS;
}
}
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.033f);
void AddToScene() {
Matrix4 mat = CreateScaleMatrix(0.033f);
if(actionType == spades::SpadeActionType::Bash) {
float per = 1.f - actionProgress;
mat = CreateRotateMatrix(Vector3(1.f, 0.f, 0.f),
per * 1.7f) * mat;
mat = CreateTranslateMatrix(0.f, per * 0.3f, 0.f)
* mat;
}else if(actionType == spades::SpadeActionType::DigStart ||
actionType == spades::SpadeActionType::Dig) {
bool first = actionType == spades::SpadeActionType::DigStart;
float per = actionProgress;
if (actionType == spades::SpadeActionType::Bash) {
float per = 1.f - actionProgress;
mat = CreateRotateMatrix(Vector3(1.f, 0.f, 0.f), per * 1.7f) * mat;
mat = CreateTranslateMatrix(0.f, per * 0.3f, 0.f) * mat;
} else if (actionType == spades::SpadeActionType::DigStart ||
actionType == spades::SpadeActionType::Dig) {
bool first = actionType == spades::SpadeActionType::DigStart;
float per = actionProgress;
// some tunes
const float readyFront = -0.8f;
const float digAngle = 0.6f;
const float readyAngle = 0.6f;
// some tunes
const float readyFront = -0.8f;
const float digAngle = 0.6f;
const float readyAngle = 0.6f;
float angle;
float front = readyFront;
float side = 1.f;
float angle;
float front = readyFront;
float side = 1.f;
if(per < 0.5f) {
if(first) {
// bringing to the dig position
per = 4.f * per * per;
angle = per * readyAngle;
side = per;
front = per * readyFront;
}else{
// soon after digging
angle = readyAngle;
per = (0.5f - per) / 0.5f;
per *= per; per *= per;
angle += per * digAngle;
front += per * 2.0f;
}
}else{
per = (per - 0.5f) / 0.5f;
per = 1.f - (1.f-per) * (1.f-per);
angle = readyAngle + per * digAngle;
front += per * 2.f;
}
if (per < 0.5f) {
if (first) {
// bringing to the dig position
per = 4.f * per * per;
angle = per * readyAngle;
side = per;
front = per * readyFront;
} else {
// soon after digging
angle = readyAngle;
per = (0.5f - per) / 0.5f;
per *= per;
per *= per;
angle += per * digAngle;
front += per * 2.0f;
}
} else {
per = (per - 0.5f) / 0.5f;
per = 1.f - (1.f - per) * (1.f - per);
angle = readyAngle + per * digAngle;
front += per * 2.f;
}
mat = CreateRotateMatrix(Vector3(1.f, 0.f, 0.f),
angle) * mat;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f),
front * 0.15f) * mat;
mat = CreateRotateMatrix(Vector3(1.f, 0.f, 0.f), angle) * mat;
mat = CreateRotateMatrix(Vector3(0.f, 0.f, 1.f), front * 0.15f) * mat;
side *= 0.3f;
front *= 0.1f;
side *= 0.3f;
front *= 0.1f;
mat = CreateTranslateMatrix(side, front, front * 0.2f)
* mat;
}
mat = CreateTranslateMatrix(side, front, front * 0.2f) * mat;
}
if(sprintStateSmooth > 0.f || raiseState < 1.f){
float per = Max(sprintStateSmooth, 1.f - raiseState);
mat = CreateRotateMatrix(Vector3(0.f, 1.f, 0.f),
per * 1.3f) * mat;
mat = CreateTranslateMatrix(Vector3(0.3f, -0.4f, -0.1f) * per)
* mat;
}
if (sprintStateSmooth > 0.f || raiseState < 1.f) {
float per = Max(sprintStateSmooth, 1.f - raiseState);
mat = CreateRotateMatrix(Vector3(0.f, 1.f, 0.f), per * 1.3f) * mat;
mat = CreateTranslateMatrix(Vector3(0.3f, -0.4f, -0.1f) * per) * mat;
}
mat = CreateTranslateMatrix(0.f, (1.f - raiseState) * -0.3f, 0.f) * mat;
mat = CreateTranslateMatrix(0.f, (1.f - raiseState) * -0.3f, 0.f) * mat;
mat = CreateTranslateMatrix(-0.3f, 0.7f, 0.3f) * mat;
mat = CreateTranslateMatrix(swing) * mat;
mat = CreateTranslateMatrix(-0.3f, 0.7f, 0.3f) * mat;
mat = CreateTranslateMatrix(swing) * mat;
leftHand = mat * Vector3(0.f, 0.f, 7.f);
rightHand = mat * Vector3(0.f, 0.f, -2.f);
leftHand = mat * Vector3(0.f, 0.f, 7.f);
rightHand = mat * Vector3(0.f, 0.f, -2.f);
ModelRenderParam param;
param.matrix = eyeMatrix * mat;
param.depthHack = true;
renderer.AddModel(model, param);
}
ModelRenderParam param;
param.matrix = eyeMatrix * mat;
param.depthHack = true;
renderer.AddModel(model, param);
}
void Draw2D() {
renderer.ColorNP = (Vector4(1.f, 1.f, 1.f, 1.f));
renderer.DrawImage(sightImage,
Vector2((renderer.ScreenWidth - sightImage.Width) * 0.5f,
(renderer.ScreenHeight - sightImage.Height) * 0.5f));
}
}
void Draw2D() {
renderer.ColorNP = (Vector4(1.f, 1.f, 1.f, 1.f));
renderer.DrawImage(sightImage,
Vector2((renderer.ScreenWidth - sightImage.Width) * 0.5f,
(renderer.ScreenHeight - sightImage.Height) * 0.5f));
}
}
ISpadeSkin@ CreateViewSpadeSkin(Renderer@ r, AudioDevice@ dev) {
return ViewSpadeSkin(r, dev);
}
ISpadeSkin @CreateViewSpadeSkin(Renderer @r, AudioDevice @dev) { return ViewSpadeSkin(r, dev); }
}

37
run-clang-format.ps1 Executable file
View File

@ -0,0 +1,37 @@
#!/usr/bin/env pwsh
param(
[string]$SourceDirectory = ".",
[string]$ClangFormat = "clang-format"
)
# TODO: Run clang-format on C++ source files
# Run clang-format on AngelScript source files
$ScriptDirectory = Join-Path $SourceDirectory "Resources" "Scripts"
$Scripts = Get-ChildItem -Recurse -Include "*.as" $ScriptDirectory
$I = 0
foreach ($Item in $Scripts) {
$Path = $Item.FullName
$TmpPath = $Path.Substring(0, $Path.Length - 3) + ".java"
# Make it pretend to be a Java source file (which clang-format understands)
# I didn't choose C++ mainly due to the difference in how accessibility is
# specified.
Copy-Item $Path $TmpPath
# Run clang-format
&$ClangFormat -i -style=file $TmpPath
# Rename it back
Move-Item -Force $TmpPath $Path
# Fix `@ this.`
$Text = Get-Content $Path
$Text = $Text.Replace("@ this.", "@this.")
Set-Content $Path $Text
$I += 1
Write-Progress -Activity "Running clang-format on AngelScript source files" `
-PercentComplete ($I / $Scripts.Count * 100)
}