diff --git a/.github/workflows/PR-builds.yml b/.github/workflows/PR-builds.yml
index cae9970eb..fb7dbcf0a 100644
--- a/.github/workflows/PR-builds.yml
+++ b/.github/workflows/PR-builds.yml
@@ -3,7 +3,7 @@ on: [push, pull_request, workflow_dispatch]
jobs:
Build-Windows-32bit-VS2019:
name: 32-bit Windows On VS2019
- runs-on: windows-latest
+ runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- uses: microsoft/setup-msbuild@v1.1
@@ -20,7 +20,7 @@ jobs:
! engine/
Build-Windows-64bit-VS2019:
name: 64-bit Windows On VS2019
- runs-on: windows-latest
+ runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- uses: microsoft/setup-msbuild@v1.1
diff --git a/editor/AssetAdmin/AssetInspector.cs b/editor/AssetAdmin/AssetInspector.cs
index a306f53d2..15b1c0232 100644
--- a/editor/AssetAdmin/AssetInspector.cs
+++ b/editor/AssetAdmin/AssetInspector.cs
@@ -113,7 +113,10 @@
%this.emitterGraphPage = %this.createTabPage("Emitter Graph", "AssetParticleGraphEmitterTool", "AssetParticleGraphTool");
//Image Frame Edit Tool
- %this.imageFrameEditPage = %this.createTabPage("Frame Edit", "AssetImageFrameEditTool", "");
+ %this.imageFrameEditPage = %this.createTabPage("Explicit Frames", "AssetImageFrameEditTool", "");
+
+ //Image Layer Edit Tool
+ %this.imageLayersEditPage = %this.createTabPage("Image Layers", "AssetImageLayersEditTool", "");
}
function AssetInspector::createTabPage(%this, %name, %class, %superClass)
@@ -205,6 +208,8 @@
%this.tabBook.selectPage(0);
%this.tabBook.removeIfMember(%this.scaleGraphPage);
%this.tabBook.removeIfMember(%this.emitterGraphPage);
+ %this.tabBook.removeIfMember(%this.imageFrameEditPage);
+ %this.tabBook.removeIfMember(%this.imageLayersEditPage);
%this.emitterButtonBar.visible = false;
%this.deleteAssetButton.visible = true;
@@ -214,6 +219,7 @@
{
%this.resetInspector();
%this.tabBook.add(%this.imageFrameEditPage);
+ %this.tabBook.add(%this.imageLayersEditPage);
%this.tabBook.selectPage(0);
%this.titlebar.setText("Image Asset:" SPC %imageAsset.AssetName);
@@ -227,6 +233,7 @@
%this.inspector.openGroupByIndex(0);
%this.imageFrameEditPage.inspect(%imageAsset);
+ %this.imageLayersEditPage.inspect(%imageAsset);
}
function AssetInspector::loadAnimationAsset(%this, %animationAsset, %assetID)
diff --git a/editor/AssetAdmin/ImageEditor/AssetImageLayersEditRow.cs b/editor/AssetAdmin/ImageEditor/AssetImageLayersEditRow.cs
new file mode 100644
index 000000000..f4fa80740
--- /dev/null
+++ b/editor/AssetAdmin/ImageEditor/AssetImageLayersEditRow.cs
@@ -0,0 +1,254 @@
+
+function AssetImageLayersEditRow::onAdd(%this)
+{
+ %this.errorColor = "255 0 0 255";
+ %this.indexBox = new GuiControl()
+ {
+ HorizSizing="width";
+ VertSizing="height";
+ Position="0 0";
+ Extent="20 40";
+ Align = center;
+ vAlign = middle;
+ Text = %this.LayerIndex;
+ FontSizeAdjust = 1.4;
+ FontColor = %this.errorColor;
+ };
+ ThemeManager.setProfile(%this.indexBox, "codeProfile");
+ %this.add(%this.indexBox);
+
+ %this.imageBox = new GuiTextEditCtrl()
+ {
+ HorizSizing="width";
+ VertSizing="height";
+ Position="20 3";
+ Extent="200 32";
+ Text = %this.LayerImage;
+ AltCommand = %this.getID() @ ".LayerImageChange();";
+ FontColor = %this.errorColor;
+ InputMode = "AllText";
+ };
+ ThemeManager.setProfile(%this.imageBox, "textEditProfile");
+ %this.add(%this.imageBox);
+
+ %this.offsetXBox = new GuiTextEditCtrl()
+ {
+ HorizSizing="width";
+ VertSizing="height";
+ Position="224 3";
+ Extent="80 32";
+ Align = right;
+ Text = getWord(%this.LayerPosition, 0);
+ AltCommand = %this.getID() @ ".LayerPositionXChange();";
+ FontColor = %this.errorColor;
+ InputMode = "Number";
+ };
+ ThemeManager.setProfile(%this.offsetXBox, "textEditProfile");
+ %this.add(%this.offsetXBox);
+
+ %this.offsetYBox = new GuiTextEditCtrl()
+ {
+ HorizSizing="width";
+ VertSizing="height";
+ Position="308 3";
+ Extent="80 32";
+ Align = right;
+ Text = getWord(%this.LayerPosition, 1);
+ AltCommand = %this.getID() @ ".LayerPositionYChange();";
+ FontColor = %this.errorColor;
+ InputMode = "Number";
+ };
+ ThemeManager.setProfile(%this.offsetYBox, "textEditProfile");
+ %this.add(%this.offsetYBox);
+
+ %this.LayerColor = %this.scrubColor(%this.LayerColor);
+ %this.colorBox = new GuiTextEditCtrl()
+ {
+ HorizSizing="width";
+ VertSizing="height";
+ Position="392 3";
+ Extent="164 32";
+ Align = right;
+ Text = %this.LayerColor;
+ AltCommand = %this.getID() @ ".LayerColorChange();";
+ FontColor = %this.errorColor;
+ InputMode = "AllText";
+ };
+ ThemeManager.setProfile(%this.colorBox, "textEditProfile");
+ %this.add(%this.colorBox);
+
+ %this.buttonBar = new GuiChainCtrl()
+ {
+ Class = "EditorButtonBar";
+ Position = "564 5";
+ Extent = "0 24";
+ ChildSpacing = 4;
+ IsVertical = false;
+ Tool = %this;
+ };
+ ThemeManager.setProfile(%this.buttonBar, "emptyProfile");
+ %this.add(%this.buttonBar);
+
+ if(%this.LayerIndex > 0)
+ {
+ %this.buttonBar.addButton("MoveLayerUp", 2, "Move Layer Up", "getMoveLayerUpEnabled");
+ %this.buttonBar.addButton("MoveLayerDown", 6, "Move Layer Down", "getMoveLayerDownEnabled");
+ %this.buttonBar.addButton("RemoveLayer", 23, "Remove Layer", "");
+ }
+ else
+ {
+ %this.imageBox.active = false;
+ %this.offsetXBox.active = false;
+ %this.offsetYBox.active = false;
+ }
+}
+
+function AssetImageLayersEditRow::LayerImageChange(%this)
+{
+ %name = %this.imageBox.getText();
+ %name = stripChars(%name, " ");
+ %this.imageBox.setText(%name);
+ if(%name !$= %this.LayerImage)
+ {
+ if(%name $= "")
+ {
+ %this.setNameError(true);
+ }
+ else
+ {
+ %this.setNameError(false);
+ %this.postEvent("LayerImageChange", %this SPC %name);
+ }
+ }
+}
+
+function AssetImageLayersEditRow::LayerPositionXChange(%this)
+{
+ %x = %this.offsetXBox.getText();
+ %x = stripChars(%x, " ");
+ if(%x $= "")
+ {
+ %x = 0;
+ }
+ %this.offsetXBox.setText(%x);
+
+ if(%x !$= getWord(%this.LayerPosition, 0))
+ {
+ %this.postEvent("LayerPositionChange", %this SPC %x SPC getWord(%this.LayerPosition, 1));
+ }
+}
+
+function AssetImageLayersEditRow::LayerPositionYChange(%this)
+{
+ %y = %this.offsetYBox.getText();
+ %y = stripChars(%y, " ");
+ if(%y $= "")
+ {
+ %y = 0;
+ }
+ %this.offsetYBox.setText(%y);
+
+ if(%y !$= getWord(%this.CellOffset, 1))
+ {
+ %this.postEvent("LayerPositionChange", %this SPC getWord(%this.LayerPosition, 0) SPC %y);
+ }
+}
+
+function AssetImageLayersEditRow::LayerColorChange(%this)
+{
+ %color = %this.scrubColor(%this.colorBox.getText());
+ %this.colorBox.setText(%color);
+
+ if(%color !$= %this.LayerColor)
+ {
+ %this.postEvent("LayerColorChange", %this SPC %color);
+ }
+}
+
+function AssetImageLayersEditRow::setNameError(%this, %hasError)
+{
+ %this.imageBox.overrideFontColor = %hasError;
+ %this.indexBox.overrideFontColor = %hasError;
+}
+
+function AssetImageLayersEditRow::getMoveLayerUpEnabled(%this)
+{
+ return %this.LayerIndex != 1;
+}
+
+function AssetImageLayersEditRow::getMoveLayerDownEnabled(%this)
+{
+ return %this.LayerIndex != %this.LayerCount;
+}
+
+function AssetImageLayersEditRow::getRemoveCellEnabled(%this)
+{
+ return true;
+}
+
+function AssetImageLayersEditRow::updateLayerCount(%this, %newCount)
+{
+ %this.LayerCount = %newCount;
+ %this.buttonBar.refreshEnabled();
+}
+
+function AssetImageLayersEditRow::MoveLayerUp(%this)
+{
+ %this.postEvent("swapLayers", (%this.LayerIndex - 1) SPC %this.LayerIndex);
+}
+
+function AssetImageLayersEditRow::MoveLayerDown(%this)
+{
+ %this.postEvent("swapLayers", %this.LayerIndex SPC (%this.LayerIndex + 1));
+}
+
+function AssetImageLayersEditRow::RemoveLayer(%this)
+{
+ %this.postEvent("removeLayer", %this.LayerIndex);
+}
+
+function AssetImageLayersEditRow::refresh(%this)
+{
+ %this.indexBox.setText(%this.LayerIndex);
+ %this.imageBox.setText(%this.LayerImage);
+ %this.offsetXBox.setText(getWord(%this.LayerPosition, 0));
+ %this.offsetYBox.setText(getWord(%this.LayerPosition, 1));
+ %this.colorBox.setText(%this.LayerColor);
+}
+
+function AssetImageLayersEditRow::onRemove(%this)
+{
+ %this.deleteObjects();
+}
+
+function AssetImageLayersEditRow::scrubColor(%this, %color)
+{
+ %red = %this.scrubChannel(getWord(%color, 0));
+ %green = %this.scrubChannel(getWord(%color, 1));
+ %blue = %this.scrubChannel(getWord(%color, 2));
+ %alpha = %this.scrubChannel(getWord(%color, 3));
+
+ return %red SPC %green SPC %blue SPC %alpha;
+}
+
+function AssetImageLayersEditRow::scrubChannel(%this, %val)
+{
+ %val = mFloatLength(mClamp(%val, 0, 1), 3);
+ if(getSubStr(%val, 4, 1) !$= "0")
+ {
+ return %val;
+ }
+ %val = getSubStr(%val, 0, 4);
+
+ if(getSubStr(%val, 3, 1) !$= "0")
+ {
+ return %val;
+ }
+ %val = getSubStr(%val, 0, 3);
+
+ if(getSubStr(%val, 2, 1) !$= "0")
+ {
+ return %val;
+ }
+ return getSubStr(%val, 0, 1);
+}
diff --git a/editor/AssetAdmin/ImageEditor/AssetImageLayersEditTool.cs b/editor/AssetAdmin/ImageEditor/AssetImageLayersEditTool.cs
new file mode 100644
index 000000000..6a428fd76
--- /dev/null
+++ b/editor/AssetAdmin/ImageEditor/AssetImageLayersEditTool.cs
@@ -0,0 +1,203 @@
+
+function AssetImageLayersEditTool::onAdd(%this)
+{
+ %this.toolScroll = new GuiScrollCtrl()
+ {
+ HorizSizing="width";
+ VertSizing="height";
+ Position="0 40";
+ Extent= getWord(%this.extent, 0) SPC (getWord(%this.extent, 1) - 40);
+ hScrollBar="dynamic";
+ vScrollBar="dynamic";
+ constantThumbHeight="0";
+ showArrowButtons="1";
+ scrollBarThickness="14";
+ };
+ ThemeManager.setProfile(%this.toolScroll, "scrollingPanelProfile");
+ ThemeManager.setProfile(%this.toolScroll, "scrollingPanelThumbProfile", "ThumbProfile");
+ ThemeManager.setProfile(%this.toolScroll, "scrollingPanelTrackProfile", "TrackProfile");
+ ThemeManager.setProfile(%this.toolScroll, "scrollingPanelArrowProfile", "ArrowProfile");
+ %this.add(%this.toolScroll);
+
+ %this.rowChain = new GuiChainCtrl()
+ {
+ HorizSizing="right";
+ VertSizing="bottom";
+ Position="0 0";
+ Extent= "662" SPC getWord(%this.toolScroll.extent, 1);
+ IsVertical="1";
+ ChildSpacing="2";
+ };
+ ThemeManager.setProfile(%this.rowChain, "emptyProfile");
+ %this.toolScroll.add(%this.rowChain);
+
+ %this.addNewLayerButton = new GuiButtonCtrl()
+ {
+ HorizSizing="left";
+ VertSizing="bottom";
+ Position="580 5";
+ Extent= "110 26";
+ Text = "Add Layer";
+ command = %this.getID() @ ".addNewLayer();";
+ };
+ ThemeManager.setProfile(%this.addNewLayerButton, "buttonProfile");
+ %this.add(%this.addNewLayerButton);
+}
+
+function AssetImageLayersEditTool::inspect(%this, %asset)
+{
+ %this.asset = %asset;
+
+ %this.rowChain.deleteObjects();
+ %this.addHeaderRow();
+ %this.createRows();
+}
+
+function AssetImageLayersEditTool::createRows(%this)
+{
+ %this.addImageLayerRow(%this.asset.getRelativeImageFile(), "0 0", %this.asset.getBlendColor(), 0);
+
+ %count = %this.asset.getLayerCount();
+ for(%i = 1; %i <= %count; %i++)
+ {
+ %image = %this.asset.getLayerImage(%i);
+ %position = %this.asset.getLayerPosition(%i);
+ %color = %this.asset.getLayerBlendColor(%i);
+
+ %this.addImageLayerRow(%image, %position, %color, %i);
+ }
+}
+
+function AssetImageLayersEditTool::addHeaderRow(%this)
+{
+ %row = new GuiControl()
+ {
+ Class = "AssetImageLayersHeaderRow";
+ HorizSizing="right";
+ VertSizing="bottom";
+ Position="0 0";
+ Extent="560 22";
+ };
+ ThemeManager.setProfile(%row, "emptyProfile");
+ %this.rowChain.add(%row);
+}
+
+function AssetImageLayersEditTool::addImageLayerRow(%this, %image, %position, %color, %index)
+{
+ %row = new GuiControl()
+ {
+ Class = "AssetImageLayersEditRow";
+ HorizSizing="right";
+ VertSizing="bottom";
+ Position="0 0";
+ Extent="662 40";
+ LayerImage = %image;
+ LayerPosition = %position;
+ LayerColor = %color;
+ LayerIndex = %index;
+ LayerCount = %this.asset.getLayerCount();
+ };
+ ThemeManager.setProfile(%row, "emptyProfile");
+ %this.rowChain.add(%row);
+ %this.startListening(%row);
+}
+
+function AssetImageLayersEditTool::addNewLayer(%this)
+{
+ %index = %this.asset.getLayerCount();
+ %image = %this.asset.getRelativeImageFile();
+
+ %this.rowChain.callOnChildrenNoRecurse("updateLayerCount", %index + 1);
+
+ %this.asset.addLayer(%image, "0 0", "1 1 1 1");
+ %this.addImageLayerRow(%image, "0 0", "1 1 1 1", %index + 1);
+}
+
+function AssetImageLayersEditTool::onLayerImageChange(%this, %data)
+{
+ %row = getWord(%data, 0);
+ %image = getWord(%data, 1);
+
+ %this.asset.setLayerImage(%row.LayerIndex, %image);
+ %row.LayerImage = %image;
+}
+
+function AssetImageLayersEditTool::onLayerPositionChange(%this, %data)
+{
+ %row = getWord(%data, 0);
+ %x = getWord(%data, 1);
+ %y = getWord(%data, 2);
+
+ %this.asset.setLayerPosition(%row.LayerIndex, %x SPC %y);
+ %row.LayerPosition = %x SPC %y;
+}
+
+function AssetImageLayersEditTool::onLayerColorChange(%this, %data)
+{
+ %row = getWord(%data, 0);
+ %color = getWord(%data, 1) SPC getWord(%data, 2) SPC getWord(%data, 3) SPC getWord(%data, 4);
+
+ if(%row.LayerIndex == 0)
+ {
+ %this.asset.setBlendColor(%color);
+ }
+ else
+ {
+ %this.asset.setLayerBlendColor(%row.LayerIndex, %color);
+ }
+ %row.LayerColor = %color;
+}
+
+function AssetImageLayersEditTool::onSwapLayers(%this, %data)
+{
+ %index1 = getWord(%data, 0);
+ %index2 = getWord(%data, 1);
+
+ %image1 = %this.asset.getLayerImage(%index1);
+ %offset1 = %this.asset.getLayerPosition(%index1);
+ %color1 = %this.asset.getLayerBlendColor(%index1);
+
+ %image2 = %this.asset.getLayerImage(%index2);
+ %offset2 = %this.asset.getLayerPosition(%index2);
+ %color2 = %this.asset.getLayerBlendColor(%index2);
+
+ %this.asset.moveLayerForward(%index1);
+
+ %row1 = %this.rowChain.getObject(%index1 + 1);
+ %row2 = %this.rowChain.getObject(%index2 + 1);
+
+ %row1.LayerPosition = %offset2;
+ %row1.LayerColor = %color2;
+ %row1.LayerImage = %image2;
+
+ %row2.LayerPosition = %offset1;
+ %row2.LayerColor = %color1;
+ %row2.LayerImage = %image1;
+
+ %row1.refresh();
+ %row2.refresh();
+}
+
+function AssetImageLayersEditTool::onRemoveLayer(%this, %index)
+{
+ %this.schedule(50, "onRemoveLayer2", %index);
+}
+
+function AssetImageLayersEditTool::onRemoveLayer2(%this, %index)
+{
+ %this.asset.removeLayer(%index);
+ %row = %this.rowChain.getObject(%index + 1);
+ %row.delete();
+
+ %count = %this.asset.getLayerCount();
+ for(%i = 0; %i < %this.rowChain.getCount(); %i++)
+ {
+ %row = %this.rowChain.getObject(%i);
+ if(%row.isMethod("refresh"))
+ {
+ %row.LayerIndex = (%i - 1);
+ %row.updateLayerCount(%count);
+ %row.refresh();
+ }
+ }
+}
diff --git a/editor/AssetAdmin/ImageEditor/AssetImageLayersHeaderRow.cs b/editor/AssetAdmin/ImageEditor/AssetImageLayersHeaderRow.cs
new file mode 100644
index 000000000..a8afd38f7
--- /dev/null
+++ b/editor/AssetAdmin/ImageEditor/AssetImageLayersHeaderRow.cs
@@ -0,0 +1,54 @@
+
+function AssetImageLayersHeaderRow::onAdd(%this)
+{
+ %this.imageBox = new GuiControl()
+ {
+ HorizSizing="width";
+ VertSizing="height";
+ Position="20 0";
+ Extent="200 25";
+ Text = "Layer Image";
+ vAlign = "Bottom";
+ };
+ ThemeManager.setProfile(%this.imageBox, "LabelProfile");
+ %this.add(%this.imageBox);
+
+ %this.offsetXBox = new GuiControl()
+ {
+ HorizSizing="width";
+ VertSizing="height";
+ Position="224 0";
+ Extent="80 25";
+ Text = "X";
+ Align = "Center";
+ vAlign = "Bottom";
+ };
+ ThemeManager.setProfile(%this.offsetXBox, "LabelProfile");
+ %this.add(%this.offsetXBox);
+
+ %this.offsetYBox = new GuiControl()
+ {
+ HorizSizing="width";
+ VertSizing="height";
+ Position="308 0";
+ Extent="80 25";
+ Text = "Y";
+ Align = "Center";
+ vAlign = "Bottom";
+ };
+ ThemeManager.setProfile(%this.offsetYBox, "LabelProfile");
+ %this.add(%this.offsetYBox);
+
+ %this.colorBox = new GuiControl()
+ {
+ HorizSizing="width";
+ VertSizing="height";
+ Position="392 0";
+ Extent="164 25";
+ Text = "Color";
+ Align = "Center";
+ vAlign = "Bottom";
+ };
+ ThemeManager.setProfile(%this.colorBox, "LabelProfile");
+ %this.add(%this.colorBox);
+}
diff --git a/editor/AssetAdmin/ImageEditor/exec.cs b/editor/AssetAdmin/ImageEditor/exec.cs
index 8bf7ce834..6764f94ab 100644
--- a/editor/AssetAdmin/ImageEditor/exec.cs
+++ b/editor/AssetAdmin/ImageEditor/exec.cs
@@ -1,3 +1,7 @@
exec("./AssetImageFrameEditTool.cs");
exec("./AssetImageFrameEditRow.cs");
exec("./AssetImageFrameHeaderRow.cs");
+
+exec("./AssetImageLayersEditTool.cs");
+exec("./AssetImageLayersEditRow.cs");
+exec("./AssetImageLayersHeaderRow.cs");
diff --git a/editor/EditorCore/gui/guiProfiles.cs b/editor/EditorCore/gui/guiProfiles.cs
index 33b1c79e2..66138b721 100644
--- a/editor/EditorCore/gui/guiProfiles.cs
+++ b/editor/EditorCore/gui/guiProfiles.cs
@@ -81,7 +81,7 @@
if(isObject(%name))
{
%originalObject = nameToID(%name);
- if(%orginalObject.getClassName() !$= %object.getClassName())
+ if(%originalObject.getClassName() !$= %object.getClassName())
{
warn("Attempted to change the class of the named object " @ %name @ "!");
warn("Original Class: " @ %originalObject.getClassName());
diff --git a/engine/compilers/Make-32bit/Torque2D.mk b/engine/compilers/Make-32bit/Torque2D.mk
index 5cbed402a..f725ae61a 100644
--- a/engine/compilers/Make-32bit/Torque2D.mk
+++ b/engine/compilers/Make-32bit/Torque2D.mk
@@ -2,7 +2,8 @@ APPNAME := ../../../Torque2D
2D_SOURCES := $(shell find ../../source/2d/ -name "*.cc") + \
$(shell find ../../source/2d/ -name "*.cpp")
-ALGORITHM_SOURCES := $(shell find ../../source/algorithm/ -name "*.cc")
+ALGORITHM_SOURCES := $(shell find ../../source/algorithm/ -name "*.cc") + \
+ $(shell find ../../source/algorithm/ -name "*.c")
ASSETS_SOURCES := $(shell find ../../source/assets/ -name "*.cc")
AUDIO_SOURCES := $(shell find ../../source/audio/ -name "*.cc")
BITMAPFONT_SOURCES := $(shell find ../../source/bitmapFont/ -name "*.cc")
diff --git a/engine/compilers/Make-64bit/Torque2D.mk b/engine/compilers/Make-64bit/Torque2D.mk
index d5276427f..09309a1ee 100644
--- a/engine/compilers/Make-64bit/Torque2D.mk
+++ b/engine/compilers/Make-64bit/Torque2D.mk
@@ -2,7 +2,8 @@ APPNAME := ../../../Torque2D
2D_SOURCES := $(shell find ../../source/2d/ -name "*.cc") + \
$(shell find ../../source/2d/ -name "*.cpp")
-ALGORITHM_SOURCES := $(shell find ../../source/algorithm/ -name "*.cc")
+ALGORITHM_SOURCES := $(shell find ../../source/algorithm/ -name "*.cc") + \
+ $(shell find ../../source/algorithm/ -name "*.c")
ASSETS_SOURCES := $(shell find ../../source/assets/ -name "*.cc")
AUDIO_SOURCES := $(shell find ../../source/audio/ -name "*.cc")
BITMAPFONT_SOURCES := $(shell find ../../source/bitmapFont/ -name "*.cc")
@@ -63,7 +64,7 @@ SOURCES := $(2D_SOURCES) + \
LDFLAGS := -g -m64
LDLIBS := -lstdc++ -lm -ldl -lpthread -lrt -lX11 -lXft -lSDL -lopenal
-CFLAGS := -std=c++14 -MMD -I. -Wfatal-errors -Wunused -m64 -msse -march=x86-64 -pipe
+CFLAGS := -std=c++17 -MMD -I. -Wfatal-errors -Wunused -m64 -msse -march=x86-64 -pipe
CFLAGS += -I/usr/include
CFLAGS += -I/usr/include/freetype2
diff --git a/engine/compilers/VisualStudio 2017/GuiBlank.gui b/engine/compilers/VisualStudio 2017/GuiBlank.gui
deleted file mode 100644
index 1bb621045..000000000
--- a/engine/compilers/VisualStudio 2017/GuiBlank.gui
+++ /dev/null
@@ -1,51 +0,0 @@
-//--- Created With GUIEDITORTOY ---//
-%guiContent = new GuiControl(GuiBlank) {
- Name = "GuiBlank";
- canSaveDynamicFields = "0";
- hidden = "0";
- locked = "0";
- isContainer = "1";
- Profile = "GuiDefaultProfile";
- HorizSizing = "width";
- VertSizing = "height";
- Position = "0 0";
- Extent = "1920 1017";
- MinExtent = "8 2";
- canSave = "1";
- Visible = "1";
- Active = "0";
- tooltipWidth = "250";
- hovertime = "1000";
-
- new GuiWindowCtrl() {
- canSaveDynamicFields = "0";
- hidden = "0";
- locked = "0";
- isContainer = "1";
- Profile = "GuiWindowProfile";
- HorizSizing = "right";
- VertSizing = "bottom";
- Position = "256 456";
- Extent = "300 240";
- MinExtent = "8 2";
- canSave = "1";
- Visible = "1";
- Active = "1";
- tooltipWidth = "250";
- hovertime = "1000";
- resizeWidth = "1";
- resizeHeight = "1";
- canMove = "1";
- canClose = "1";
- canMinimize = "1";
- canMaximize = "1";
- titleHeight = "20";
- resizeRightWidth = "10";
- resizeBottomHeight = "10";
- contentProfile = "GuiWindowContentProfile";
- closeButtonProfile = "GuiWindowCloseButtonProfile";
- minButtonProfile = "GuiWindowMinButtonProfile";
- maxButtonProfile = "GuiWindowMaxButtonProfile";
- };
-};
-//--- GUIEDITORTOY END ---//
diff --git a/engine/compilers/VisualStudio 2019/Torque 2D.vcxproj b/engine/compilers/VisualStudio 2019/Torque 2D.vcxproj
index f13896cc8..8885ef9d5 100644
--- a/engine/compilers/VisualStudio 2019/Torque 2D.vcxproj
+++ b/engine/compilers/VisualStudio 2019/Torque 2D.vcxproj
@@ -516,6 +516,7 @@
+
@@ -677,6 +678,7 @@
+
@@ -940,6 +942,7 @@
+
@@ -1182,6 +1185,8 @@
+
+
diff --git a/engine/compilers/VisualStudio 2019/Torque 2D.vcxproj.filters b/engine/compilers/VisualStudio 2019/Torque 2D.vcxproj.filters
index 49560b268..1b53173f1 100644
--- a/engine/compilers/VisualStudio 2019/Torque 2D.vcxproj.filters
+++ b/engine/compilers/VisualStudio 2019/Torque 2D.vcxproj.filters
@@ -1336,6 +1336,12 @@
math\noise
+
+ algorithm
+
+
+ math\noise
+
@@ -3058,6 +3064,15 @@
math\noise
+
+ algorithm
+
+
+ math\noise
+
+
+ math\noise
+
diff --git a/engine/compilers/VisualStudio 2017/Torque 2D.aps b/engine/compilers/VisualStudio 2022/Torque 2D.aps
similarity index 67%
rename from engine/compilers/VisualStudio 2017/Torque 2D.aps
rename to engine/compilers/VisualStudio 2022/Torque 2D.aps
index 0cd1b2970..8b5584168 100644
Binary files a/engine/compilers/VisualStudio 2017/Torque 2D.aps and b/engine/compilers/VisualStudio 2022/Torque 2D.aps differ
diff --git a/engine/compilers/VisualStudio 2017/Torque 2D.ico b/engine/compilers/VisualStudio 2022/Torque 2D.ico
similarity index 100%
rename from engine/compilers/VisualStudio 2017/Torque 2D.ico
rename to engine/compilers/VisualStudio 2022/Torque 2D.ico
diff --git a/engine/compilers/VisualStudio 2017/Torque 2D.rc b/engine/compilers/VisualStudio 2022/Torque 2D.rc
similarity index 100%
rename from engine/compilers/VisualStudio 2017/Torque 2D.rc
rename to engine/compilers/VisualStudio 2022/Torque 2D.rc
diff --git a/engine/compilers/VisualStudio 2017/Torque 2D.sln b/engine/compilers/VisualStudio 2022/Torque 2D.sln
similarity index 99%
rename from engine/compilers/VisualStudio 2017/Torque 2D.sln
rename to engine/compilers/VisualStudio 2022/Torque 2D.sln
index da2ac364e..9ef72593f 100644
--- a/engine/compilers/VisualStudio 2017/Torque 2D.sln
+++ b/engine/compilers/VisualStudio 2022/Torque 2D.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28307.1300
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31729.503
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Torque2D", "Torque 2D.vcxproj", "{1564A07D-230E-4C90-AEE6-52AC9A58D6C9}"
ProjectSection(ProjectDependencies) = postProject
diff --git a/engine/compilers/VisualStudio 2017/Torque 2D.vcxproj b/engine/compilers/VisualStudio 2022/Torque 2D.vcxproj
similarity index 98%
rename from engine/compilers/VisualStudio 2017/Torque 2D.vcxproj
rename to engine/compilers/VisualStudio 2022/Torque 2D.vcxproj
index 77e1cf042..72e8d75bf 100644
--- a/engine/compilers/VisualStudio 2017/Torque 2D.vcxproj
+++ b/engine/compilers/VisualStudio 2022/Torque 2D.vcxproj
@@ -30,38 +30,38 @@
{1564A07D-230E-4C90-AEE6-52AC9A58D6C9}
TorqueGame
Torque2D
- 10.0.19041.0
+ 10.0
Application
false
- v141
+ v143
Application
false
- v141
+ v143
Application
false
- v141
+ v143
Application
false
- v141
+ v143
Application
false
- v141
+ v143
Application
false
- v141
+ v143
@@ -117,6 +117,10 @@
../../../
../../Link/VC2012.$(Configuration).$(PlatformName)/$(ProjectName)/
+
+ ../../../
+ ../../Link/VC2012.$(Configuration).$(PlatformName)/$(ProjectName)/
+
$(OutDir)Torque2D.tlb
@@ -143,7 +147,7 @@
Level3
4800;4100;4127;4512
false
- stdcpp14
+ true
_DEBUG;%(PreprocessorDefinitions)
@@ -193,7 +197,7 @@
4800;4100;4127;4512
false
true
- stdcpp14
+ true
_DEBUG;%(PreprocessorDefinitions)
@@ -243,7 +247,7 @@
CompileAsCpp
true
4800;4100;4127;4512
- stdcpp14
+ true
NDEBUG;%(PreprocessorDefinitions)
@@ -304,7 +308,7 @@
CompileAsCpp
true
4800;4100;4127;4512
- stdcpp14
+ true
NDEBUG;%(PreprocessorDefinitions)
@@ -364,7 +368,7 @@
CompileAsCpp
true
4800;4100;4127;4512
- stdcpp14
+ true
NDEBUG;%(PreprocessorDefinitions)
@@ -425,7 +429,7 @@
CompileAsCpp
true
4800;4100;4127;4512
- stdcpp14
+ true
NDEBUG;%(PreprocessorDefinitions)
@@ -512,6 +516,7 @@
+
@@ -673,6 +678,7 @@
+
@@ -936,6 +942,7 @@
+
@@ -1178,6 +1185,8 @@
+
+
diff --git a/engine/compilers/VisualStudio 2017/Torque 2D.vcxproj.filters b/engine/compilers/VisualStudio 2022/Torque 2D.vcxproj.filters
similarity index 99%
rename from engine/compilers/VisualStudio 2017/Torque 2D.vcxproj.filters
rename to engine/compilers/VisualStudio 2022/Torque 2D.vcxproj.filters
index 3282c3138..1b53173f1 100644
--- a/engine/compilers/VisualStudio 2017/Torque 2D.vcxproj.filters
+++ b/engine/compilers/VisualStudio 2022/Torque 2D.vcxproj.filters
@@ -203,7 +203,7 @@
{598766e4-7dc1-45b8-8acf-f133f4fced82}
- {1ca99a8e-9e94-4ab8-996e-b4835a603512}
+ {1a2a7ebc-eda6-4a67-b9ab-bc9f437b5d5c}
@@ -1336,6 +1336,12 @@
math\noise
+
+ algorithm
+
+
+ math\noise
+
@@ -3058,6 +3064,15 @@
math\noise
+
+ algorithm
+
+
+ math\noise
+
+
+ math\noise
+
diff --git a/engine/compilers/VisualStudio 2017/libogg.vcxproj b/engine/compilers/VisualStudio 2022/libogg.vcxproj
similarity index 92%
rename from engine/compilers/VisualStudio 2017/libogg.vcxproj
rename to engine/compilers/VisualStudio 2022/libogg.vcxproj
index 04e3b1cc2..f3996d531 100644
--- a/engine/compilers/VisualStudio 2017/libogg.vcxproj
+++ b/engine/compilers/VisualStudio 2022/libogg.vcxproj
@@ -30,30 +30,30 @@
{15CBFEFF-7965-41F5-B4E2-21E8795C9159}
libogg
Win32Proj
- 10.0.19041.0
+ 10.0
StaticLibrary
Unicode
false
- v141
+ v143
StaticLibrary
Unicode
- v141
+ v143
StaticLibrary
Unicode
- false
- v141
+ true
+ v143
StaticLibrary
Unicode
- v141
+ v143
@@ -79,8 +79,8 @@
.\../../Link/Debug/libogg\
.\../../Link/Release\
.\../../Link/Release/libogg\
- .\../../Link/Release\
- .\../../Link/Release/libogg\
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
$(ProjectName)_DEBUG
@@ -171,16 +171,12 @@
false
- Level3
+ Level4
CompileAsC
4244;%(DisableSpecificWarnings)
Cdecl
- .\../../Link/Release/libogg/
- .\../../Link/Release/libogg/
- .\../../Link/Release/libogg/
- false
diff --git a/engine/compilers/VisualStudio 2017/libvorbis.vcxproj b/engine/compilers/VisualStudio 2022/libvorbis.vcxproj
similarity index 97%
rename from engine/compilers/VisualStudio 2017/libvorbis.vcxproj
rename to engine/compilers/VisualStudio 2022/libvorbis.vcxproj
index 22797c189..c1b7d35a4 100644
--- a/engine/compilers/VisualStudio 2017/libvorbis.vcxproj
+++ b/engine/compilers/VisualStudio 2022/libvorbis.vcxproj
@@ -22,30 +22,30 @@
{3A214E06-B95E-4D61-A291-1F8DF2EC10FD}
libvorbis
Win32Proj
- 10.0.19041.0
+ 10.0
StaticLibrary
Unicode
false
- v141
+ v143
StaticLibrary
Unicode
- v141
+ v143
StaticLibrary
Unicode
true
- v141
+ v143
StaticLibrary
Unicode
- v141
+ v143
@@ -75,8 +75,8 @@
.\../../Link/Debug/libvorbis\
.\../../Link/Release\
.\../../Link/Release/libvorbis\
- $(SolutionDir)$(Platform)\$(Configuration)\
- $(Platform)\$(Configuration)\
+ .\../../Link/Release/
+ .\../../Link/Release/libvorbis
$(ProjectName)_DEBUG
diff --git a/engine/compilers/VisualStudio 2017/ljpeg.vcxproj b/engine/compilers/VisualStudio 2022/ljpeg.vcxproj
similarity index 99%
rename from engine/compilers/VisualStudio 2017/ljpeg.vcxproj
rename to engine/compilers/VisualStudio 2022/ljpeg.vcxproj
index 347cae1c1..c1b6c1fd1 100644
--- a/engine/compilers/VisualStudio 2017/ljpeg.vcxproj
+++ b/engine/compilers/VisualStudio 2022/ljpeg.vcxproj
@@ -28,38 +28,38 @@
{0B07BA94-AA53-4FD4-ADB4-79EC2DA53B36}
- 10.0.19041.0
+ 10.0
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
diff --git a/engine/compilers/VisualStudio 2017/ljpeg.vcxproj.filters b/engine/compilers/VisualStudio 2022/ljpeg.vcxproj.filters
similarity index 100%
rename from engine/compilers/VisualStudio 2017/ljpeg.vcxproj.filters
rename to engine/compilers/VisualStudio 2022/ljpeg.vcxproj.filters
diff --git a/engine/compilers/VisualStudio 2017/lpng.vcxproj b/engine/compilers/VisualStudio 2022/lpng.vcxproj
similarity index 98%
rename from engine/compilers/VisualStudio 2017/lpng.vcxproj
rename to engine/compilers/VisualStudio 2022/lpng.vcxproj
index 983f15328..319f241e1 100644
--- a/engine/compilers/VisualStudio 2017/lpng.vcxproj
+++ b/engine/compilers/VisualStudio 2022/lpng.vcxproj
@@ -28,38 +28,38 @@
{AF1179E3-A838-46A3-A427-1E62AA4C52F4}
- 10.0.19041.0
+ 10.0
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
diff --git a/engine/compilers/VisualStudio 2017/lpng.vcxproj.filters b/engine/compilers/VisualStudio 2022/lpng.vcxproj.filters
similarity index 100%
rename from engine/compilers/VisualStudio 2017/lpng.vcxproj.filters
rename to engine/compilers/VisualStudio 2022/lpng.vcxproj.filters
diff --git a/engine/compilers/VisualStudio 2017/main.cs b/engine/compilers/VisualStudio 2022/main.cs
similarity index 100%
rename from engine/compilers/VisualStudio 2017/main.cs
rename to engine/compilers/VisualStudio 2022/main.cs
diff --git a/engine/compilers/VisualStudio 2017/resource.h b/engine/compilers/VisualStudio 2022/resource.h
similarity index 100%
rename from engine/compilers/VisualStudio 2017/resource.h
rename to engine/compilers/VisualStudio 2022/resource.h
diff --git a/engine/compilers/VisualStudio 2017/zlib.vcxproj b/engine/compilers/VisualStudio 2022/zlib.vcxproj
similarity index 98%
rename from engine/compilers/VisualStudio 2017/zlib.vcxproj
rename to engine/compilers/VisualStudio 2022/zlib.vcxproj
index 273a3dd9a..f7531046e 100644
--- a/engine/compilers/VisualStudio 2017/zlib.vcxproj
+++ b/engine/compilers/VisualStudio 2022/zlib.vcxproj
@@ -58,38 +58,38 @@
{86CB2525-0CF3-40D3-BF42-A0A95035EE8C}
- 10.0.19041.0
+ 10.0
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
StaticLibrary
false
- v141
+ v143
diff --git a/engine/compilers/VisualStudio 2017/zlib.vcxproj.filters b/engine/compilers/VisualStudio 2022/zlib.vcxproj.filters
similarity index 100%
rename from engine/compilers/VisualStudio 2017/zlib.vcxproj.filters
rename to engine/compilers/VisualStudio 2022/zlib.vcxproj.filters
diff --git a/engine/source/2d/assets/ImageAsset.cc b/engine/source/2d/assets/ImageAsset.cc
index 3f8517270..fdcaec31e 100755
--- a/engine/source/2d/assets/ImageAsset.cc
+++ b/engine/source/2d/assets/ImageAsset.cc
@@ -117,6 +117,12 @@ static StringTableEntry cellWidthName = StringTable->insert( "Widt
static StringTableEntry cellHeightName = StringTable->insert( "Height" );
static StringTableEntry cellNameEntryName = StringTable->insert( "Name" );
+static StringTableEntry imageLayerCustomNodeName = StringTable->insert("ImageLayers");
+static StringTableEntry layerNodeName = StringTable->insert("ImageLayer");
+static StringTableEntry layerImageFile = StringTable->insert("ImageFile");
+static StringTableEntry layerPositionName = StringTable->insert("Position");
+static StringTableEntry layerBlendColorName = StringTable->insert("BlendColor");
+
//------------------------------------------------------------------------------
static EnumTable::Enums textureFilterLookup[] =
@@ -174,11 +180,14 @@ ImageAsset::ImageAsset() : mImageFile(StringTable->EmptyString),
mCellWidth(0),
mCellHeight(0),
+ mBlendColor(1.0f, 1.0f, 1.0f),
+
mImageTextureHandle(NULL)
{
// Set Vector Associations.
VECTOR_SET_ASSOCIATION( mFrames );
VECTOR_SET_ASSOCIATION( mExplicitFrames );
+ VECTOR_SET_ASSOCIATION(mImageLayers);
}
//------------------------------------------------------------------------------
@@ -201,6 +210,7 @@ void ImageAsset::initPersistFields()
addProtectedField("FilterMode", TypeEnum, Offset(mLocalFilterMode, ImageAsset), &setFilterMode, &defaultProtectedGetFn, &writeFilterMode, 1, &textureFilterTable);
addProtectedField("ExplicitMode", TypeBool, Offset(mExplicitMode, ImageAsset), &setExplicitMode, &defaultProtectedGetFn, &writeExplicitMode, "");
addProtectedField("CellRowOrder", TypeBool, Offset(mCellRowOrder, ImageAsset), &setCellRowOrder, &defaultProtectedGetFn, &writeCellRowOrder, "If true, cell number are applied left-to-right, top-to-bottom.");
+ addProtectedField("BlendColor", TypeColorF, Offset(mBlendColor, ImageAsset), &setBlendColor, &defaultProtectedGetFn, &writeBlendColor, "Changes the base color of the texture. You should only use this if you are using layers.");
endGroup("Image Fields");
addGroup("X Values");
@@ -1069,8 +1079,18 @@ void ImageAsset::initializeAsset( void )
// Ensure the image-file is expanded.
mImageFile = expandAssetFilePath( mImageFile );
+ // Time to load the layer files too.
+ for (auto& layer : mImageLayers)
+ {
+ const char* path = expandAssetFilePath(layer.mImageFile);
+ layer.LoadImage(path);
+ }
+
// Calculate the image.
calculateImage();
+
+ // Redraw the image.
+ redrawImage();
}
//------------------------------------------------------------------------------
@@ -1086,6 +1106,9 @@ void ImageAsset::onAssetRefresh( void )
// Compile image.
calculateImage();
+
+ // Redraw the image.
+ redrawImage();
}
//-----------------------------------------------------------------------------
@@ -1126,7 +1149,7 @@ void ImageAsset::calculateImage( void )
TextureManager::refresh( mImageFile );
// Get image texture.
- mImageTextureHandle.set( mImageFile, TextureHandle::BitmapTexture, true, getForce16Bit() );
+ mImageTextureHandle.set( mImageFile, mImageLayers.size() > 0 ? TextureHandle::BitmapKeepTexture : TextureHandle::BitmapTexture, true, getForce16Bit() );
// Is the texture valid?
if ( mImageTextureHandle.IsNull() )
@@ -1377,6 +1400,47 @@ void ImageAsset::calculateExplicitMode( void )
}
}
+void ImageAsset::completeLayerChange(const bool doRedraw)
+{
+ if (doRedraw)
+ {
+ redrawImage();
+
+ if (getOwned())
+ {
+ refreshAsset();
+ }
+ }
+}
+
+void ImageAsset::redrawImage()
+{
+ if (mImageLayers.size() > 0)
+ {
+ GBitmap* map = mImageTextureHandle.getBitmap();
+ if (map == nullptr)
+ {
+ // This should reload the texture and keep it in memory
+ mImageTextureHandle.set(mImageFile, TextureHandle::BitmapKeepTexture, true, getForce16Bit());
+ map = mImageTextureHandle.getBitmap();
+ if (map == nullptr)
+ {
+ // We still can't come up with a bitmap, so warn and return
+ Con::warnf("ImageAsset::redrawImage() - Unable to load bitmap for image '%s'.", mImageFile);
+ return;
+ }
+ mImageLayers[0].LoadImage(mImageLayers[0].mImageFile);
+ }
+ map->clearImage(mBlendColor);
+ for (auto &layer : mImageLayers)
+ {
+ map->mergeLayer(layer.mPosition, layer.mBitmap, layer.mBlendColor);
+ }
+
+ mImageTextureHandle.refresh();
+ }
+}
+
//------------------------------------------------------------------------------
bool ImageAsset::setFilterMode( void* obj, const char* data )
@@ -1385,6 +1449,233 @@ bool ImageAsset::setFilterMode( void* obj, const char* data )
return false;
}
+void ImageAsset::addLayer(const char* imagePath, const Point2I position, const ColorF blendColor, const bool doRedraw)
+{
+ insertLayer(mImageLayers.size(), imagePath, position, blendColor, doRedraw);
+}
+
+void ImageAsset::insertLayer(const U32 index, const char* imagePath, const Point2I position, const ColorF blendColor, const bool doRedraw)
+{
+ if (mImageLayers.size() == 0)
+ {
+ Point2I p(0, 0);
+ ImageLayer baseLayer(mImageFile, p, mBlendColor);
+ mImageLayers.push_back(baseLayer);
+
+ if (getOwned())
+ {
+ baseLayer.LoadImage(mImageFile);
+ }
+ }
+ ImageLayer layer(imagePath, position, blendColor);
+
+ if (getOwned())
+ {
+ const char* path = expandAssetFilePath(layer.mImageFile);
+ layer.LoadImage(path);
+ }
+
+ if (index == 0 || index >= mImageLayers.size())
+ {
+ mImageLayers.push_back(layer);
+ }
+ else
+ {
+ typeImageLayerVector::iterator iter = mImageLayers.begin() + index;
+ mImageLayers.insert(iter, layer);
+ }
+
+ completeLayerChange(doRedraw);
+}
+
+void ImageAsset::removeLayer(const U32 index, const bool doRedraw)
+{
+ if (index < 1 || index >= mImageLayers.size())
+ {
+ Con::warnf("ImageAsset::removeLayer() - Invalid Index of %d.", index);
+ return;
+ }
+
+ mImageLayers.erase(index);
+
+ if (mImageLayers.size() == 1)
+ {
+ mImageLayers.clear();
+ }
+
+ completeLayerChange(doRedraw);
+}
+
+void ImageAsset::moveLayerForward(const U32 index, const bool doRedraw)
+{
+ if (index < 1 || index >= mImageLayers.size())
+ {
+ Con::warnf("ImageAsset::moveLayerForward() - Invalid Index of %d.", index);
+ return;
+ }
+
+ if (index == mImageLayers.size() - 1)
+ {
+ return;
+ }
+
+ ImageLayer layer = mImageLayers[index];
+ mImageLayers.erase(index);
+ mImageLayers.insert(mImageLayers.begin() + index + 1, layer);
+
+ completeLayerChange(doRedraw);
+}
+
+void ImageAsset::moveLayerBackward(const U32 index, const bool doRedraw)
+{
+ if (index < 1 || index >= mImageLayers.size())
+ {
+ Con::warnf("ImageAsset::moveLayerBackward() - Invalid Index of %d.", index);
+ return;
+ }
+
+ if (index == 1)
+ {
+ return;
+ }
+
+ moveLayerForward(index - 1, doRedraw);
+}
+
+void ImageAsset::moveLayerToFront(const U32 index, const bool doRedraw)
+{
+ if (index < 1 || index >= mImageLayers.size())
+ {
+ Con::warnf("ImageAsset::moveLayerToFront() - Invalid Index of %d.", index);
+ return;
+ }
+
+ if (index == mImageLayers.size() - 1)
+ {
+ return;
+ }
+
+ ImageLayer layer = mImageLayers[index];
+ mImageLayers.erase(index);
+ mImageLayers.push_back(layer);//The back of the array is the front of the image
+
+ completeLayerChange(doRedraw);
+}
+
+void ImageAsset::moveLayerToBack(const U32 index, const bool doRedraw)
+{
+ if (index < 1 || index >= mImageLayers.size())
+ {
+ Con::warnf("ImageAsset::moveLayerToBack() - Invalid Index of %d.", index);
+ return;
+ }
+
+ if (index == 1)
+ {
+ return;
+ }
+
+ ImageLayer layer = mImageLayers[index];
+ mImageLayers.erase(index);
+ mImageLayers.insert(mImageLayers.begin() + 1, layer);//The front of the array is the back of the image
+
+ completeLayerChange(doRedraw);
+}
+
+void ImageAsset::setLayerImage(const U32 index, const char* imagePath, const bool doRedraw)
+{
+ if (index < 1 || index >= mImageLayers.size())
+ {
+ Con::warnf("ImageAsset::setLayerImage() - Invalid Index of %d.", index);
+ return;
+ }
+
+ if (getOwned())
+ {
+ const char* path = expandAssetFilePath(imagePath);
+ mImageLayers[index].mImageFile = StringTable->insert(imagePath);
+ mImageLayers[index].LoadImage(path);
+ }
+ else
+ {
+ mImageLayers[index].mImageFile = StringTable->insert(imagePath);
+ }
+
+ completeLayerChange(doRedraw);
+}
+
+void ImageAsset::setLayerPosition(const U32 index, const Point2I position, const bool doRedraw)
+{
+ if (index < 1 || index >= mImageLayers.size())
+ {
+ Con::warnf("ImageAsset::setLayerPosition() - Invalid Index of %d.", index);
+ return;
+ }
+ mImageLayers[index].mPosition.set(position.x, position.y);
+ completeLayerChange(doRedraw);
+}
+
+void ImageAsset::setLayerBlendColor(const U32 index, const ColorF blendColor, const bool doRedraw)
+{
+ if (index < 1 || index >= mImageLayers.size())
+ {
+ Con::warnf("ImageAsset::setLayerBlendColor() - Invalid Index of %d.", index);
+ return;
+ }
+ mImageLayers[index].mBlendColor.set(blendColor.red, blendColor.green, blendColor.blue, blendColor.alpha);
+ completeLayerChange(doRedraw);
+}
+
+const char* ImageAsset::getLayerImage(const U32 index)
+{
+ if (index < 1 || index >= mImageLayers.size())
+ {
+ Con::warnf("ImageAsset::getLayerImage() - Invalid Index of %d.", index);
+ return StringTable->EmptyString;
+ }
+ return mImageLayers[index].mImageFile;
+}
+
+const Point2I ImageAsset::getLayerPosition(const U32 index)
+{
+ if (index < 1 || index >= mImageLayers.size())
+ {
+ Con::warnf("ImageAsset::getLayerPosition() - Invalid Index of %d.", index);
+ return Point2I();
+ }
+ return mImageLayers[index].mPosition;
+}
+
+const ColorF ImageAsset::getLayerBlendColor(const U32 index)
+{
+ if (index < 1 || index >= mImageLayers.size())
+ {
+ Con::warnf("ImageAsset::getLayerBlendColor() - Invalid Index of %d.", index);
+ return ColorF();
+ }
+ return mImageLayers[index].mBlendColor;
+}
+
+void ImageAsset::setBlendColor(const ColorF color, const bool doRedraw)
+{
+ mBlendColor.set(color.red, color.green, color.blue, color.alpha);
+
+ if (mImageLayers.size() == 0)
+ {
+ Con::warnf("ImageAsset::setBlendColor() - The ImageAsset blend color will not be applied if layers are not being used.");
+ return;
+ }
+
+ mImageLayers[0].mBlendColor.set(color.red, color.green, color.blue, color.alpha);
+
+ completeLayerChange(doRedraw);
+}
+
+const ColorF ImageAsset::getBlendColor()
+{
+ return mBlendColor;
+}
+
//------------------------------------------------------------------------------
void ImageAsset::onTamlCustomWrite( TamlCustomNodes& customNodes )
@@ -1395,11 +1686,7 @@ void ImageAsset::onTamlCustomWrite( TamlCustomNodes& customNodes )
// Call parent.
Parent::onTamlCustomWrite( customNodes );
- // Finish if not in explicit mode.
- if ( !mExplicitMode )
- return;
-
- if (mExplicitFrames.size() > 0)
+ if (mExplicitMode && mExplicitFrames.size() > 0)
{
// Add cell custom node.
TamlCustomNode* pCustomCellNodes = customNodes.addNode( cellCustomNodeCellsName );
@@ -1420,18 +1707,42 @@ void ImageAsset::onTamlCustomWrite( TamlCustomNodes& customNodes )
pCellNode->addField( cellHeightName, pixelArea.mPixelHeight );
}
}
+
+ if (mImageLayers.size() > 0)
+ {
+ TamlCustomNode* pCustomLayerNodes = customNodes.addNode(imageLayerCustomNodeName);
+
+ for (typeImageLayerVector::iterator frameItr = mImageLayers.begin() + 1; frameItr != mImageLayers.end(); ++frameItr)
+ {
+ const ImageLayer& layer = *frameItr;
+ TamlCustomNode* pLayerNode = pCustomLayerNodes->addNode(layerNodeName);
+
+ pLayerNode->addField(layerImageFile, layer.mImageFile);
+ pLayerNode->addField(layerPositionName, layer.mPosition);
+ pLayerNode->addField(layerBlendColorName, layer.mBlendColor);
+ }
+ }
}
//-----------------------------------------------------------------------------
-void ImageAsset::onTamlCustomRead( const TamlCustomNodes& customNodes )
+void ImageAsset::onTamlCustomRead(const TamlCustomNodes& customNodes)
{
// Debug Profiling.
PROFILE_SCOPE(ImageAsset_OnTamlCustomRead);
-
+
// Call parent.
- Parent::onTamlCustomRead( customNodes );
-
+ Parent::onTamlCustomRead(customNodes);
+
+ // Load the explicit cells
+ loadTamlExplicitCells(customNodes);
+
+ // Load image layers
+ loadTamlImageLayers(customNodes);
+}
+
+void ImageAsset::loadTamlExplicitCells(const TamlCustomNodes& customNodes)
+{
// Find cell custom node.
const TamlCustomNode* pCustomCellNodes = customNodes.findNode( cellCustomNodeCellsName );
@@ -1554,6 +1865,84 @@ void ImageAsset::onTamlCustomRead( const TamlCustomNodes& customNodes )
}
}
+void ImageAsset::loadTamlImageLayers(const TamlCustomNodes& customNodes)
+{
+ // Find layer custom node.
+ const TamlCustomNode* pCustomLayerNodes = customNodes.findNode(imageLayerCustomNodeName);
+
+ // Continue if we have explicit layers.
+ if (pCustomLayerNodes != NULL)
+ {
+ // Fetch children layer nodes.
+ const TamlCustomNodeVector& layerNodes = pCustomLayerNodes->getChildren();
+
+ // Iterate layers.
+ for (TamlCustomNodeVector::const_iterator layerNodeItr = layerNodes.begin(); layerNodeItr != layerNodes.end(); ++layerNodeItr)
+ {
+ // Fetch layer node.
+ TamlCustomNode* pLayerNode = *layerNodeItr;
+
+ // Fetch node name.
+ StringTableEntry nodeName = pLayerNode->getNodeName();
+
+ // Is this a valid alias?
+ if (nodeName != layerNodeName)
+ {
+ // No, so warn.
+ Con::warnf("ImageAsset::onTamlCustomRead() - Encountered an unknown custom name of '%s'. Only '%s' is valid.", nodeName, layerNodeName);
+ continue;
+ }
+
+ Point2I layerPosition(0, 0);
+ const char* imagePath = StringTable->EmptyString;
+ ColorF blendColor = ColorF(1, 1, 1, 1);
+
+ // Fetch fields.
+ const TamlCustomFieldVector& fields = pLayerNode->getFields();
+
+ // Iterate property fields.
+ for (TamlCustomFieldVector::const_iterator fieldItr = fields.begin(); fieldItr != fields.end(); ++fieldItr)
+ {
+ // Fetch field.
+ const TamlCustomField* pField = *fieldItr;
+
+ // Fetch field name.
+ StringTableEntry fieldName = pField->getFieldName();
+
+ // Check common fields.
+ if (fieldName == layerImageFile)
+ {
+ imagePath = pField->getFieldValue();
+ }
+ else if (fieldName == layerPositionName)
+ {
+ pField->getFieldValue(layerPosition);
+ }
+ else if (fieldName == layerBlendColorName)
+ {
+ pField->getFieldValue(blendColor);
+ }
+ else
+ {
+ // Unknown name so warn.
+ Con::warnf("ImageAsset::onTamlCustomRead() - Encountered an unknown custom field name of '%s'.", fieldName);
+ continue;
+ }
+ }
+
+ // Is the image name valid?
+ if (imagePath == StringTable->EmptyString)
+ {
+ // No, so warn
+ Con::warnf("ImageAsset::onTamlCustomRead() - Image File of '%s' is invalid or was not set.", imagePath);
+ }
+
+ // Add image layer.
+ addLayer(imagePath, layerPosition, blendColor, false);
+ }
+ }
+}
+
//-----------------------------------------------------------------------------
static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement )
@@ -1564,6 +1953,8 @@ static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlEleme
char buffer[1024];
+ //---Cells---
+
// Create ImageAsset node element.
TiXmlElement* pImageAssetNodeElement = new TiXmlElement( "xs:element" );
dSprintf( buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), cellCustomNodeCellsName );
@@ -1616,6 +2007,57 @@ static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlEleme
pImageAssetHeight->SetAttribute( "name", cellHeightName );
pImageAssetHeight->SetAttribute( "type", "xs:unsignedInt" );
pImageAssetComplexTypeElement->LinkEndChild( pImageAssetHeight );
+
+ //---Layers---
+
+ char buffer2[1024];
+
+ // Create ImageAsset node element.
+ TiXmlElement* pImageAssetNodeElementL = new TiXmlElement("xs:element");
+ dSprintf(buffer, sizeof(buffer2), "%s.%s", pClassRep->getClassName(), imageLayerCustomNodeName);
+ pImageAssetNodeElementL->SetAttribute("name", buffer2);
+ pImageAssetNodeElementL->SetAttribute("minOccurs", 0);
+ pImageAssetNodeElementL->SetAttribute("maxOccurs", 1);
+ pParentElement->LinkEndChild(pImageAssetNodeElementL);
+
+ // Create complex type.
+ TiXmlElement* pImageAssetNodeComplexTypeElementL = new TiXmlElement("xs:complexType");
+ pImageAssetNodeElementL->LinkEndChild(pImageAssetNodeComplexTypeElementL);
+
+ // Create choice element.
+ TiXmlElement* pImageAssetNodeChoiceElementL = new TiXmlElement("xs:choice");
+ pImageAssetNodeChoiceElementL->SetAttribute("minOccurs", 0);
+ pImageAssetNodeChoiceElementL->SetAttribute("maxOccurs", "unbounded");
+ pImageAssetNodeComplexTypeElementL->LinkEndChild(pImageAssetNodeChoiceElementL);
+
+ // Create ImageAsset element.
+ TiXmlElement* pImageAssetElementL = new TiXmlElement("xs:element");
+ pImageAssetElementL->SetAttribute("name", layerNodeName);
+ pImageAssetElementL->SetAttribute("minOccurs", 0);
+ pImageAssetElementL->SetAttribute("maxOccurs", 1);
+ pImageAssetNodeChoiceElementL->LinkEndChild(pImageAssetElementL);
+
+ // Create complex type Element.
+ TiXmlElement* pImageAssetComplexTypeElementL = new TiXmlElement("xs:complexType");
+ pImageAssetElementL->LinkEndChild(pImageAssetComplexTypeElementL);
+
+ // Create "ImageFile" attribute.
+ TiXmlElement* pLayerImageFile = new TiXmlElement("xs:attribute");
+ pLayerImageFile->SetAttribute("name", layerImageFile);
+ pLayerImageFile->SetAttribute("type", "xs:string");
+ pImageAssetComplexTypeElementL->LinkEndChild(pLayerImageFile);
+
+ // Create "Position" attribute.
+ TiXmlElement* pLayerPosition = new TiXmlElement("xs:attribute");
+ pLayerPosition->SetAttribute("name", layerPositionName);
+ pLayerPosition->SetAttribute("type", "Point2I_ConsoleType");
+ pImageAssetComplexTypeElementL->LinkEndChild(pLayerPosition);
+
+ // Create "BlendColor" attribute.
+ TiXmlElement* pLayerBlendColor = new TiXmlElement("xs:attribute");
+ pLayerBlendColor->SetAttribute("name", layerBlendColorName);
+ pLayerBlendColor->SetAttribute("type", "ColorF_ConsoleType");
+ pImageAssetComplexTypeElementL->LinkEndChild(pLayerBlendColor);
}
//------------------------------------------------------------------------------
diff --git a/engine/source/2d/assets/ImageAsset.h b/engine/source/2d/assets/ImageAsset.h
index 5021d6625..3b55ea61b 100755
--- a/engine/source/2d/assets/ImageAsset.h
+++ b/engine/source/2d/assets/ImageAsset.h
@@ -158,9 +158,32 @@ class ImageAsset : public AssetBase
TexelArea mTexelArea;
};
+ class ImageLayer
+ {
+ public:
+ ImageLayer() {}
+
+ ImageLayer(const char* imageFile, const Point2I position, const ColorF blendColor) :
+ mPosition(position), mBlendColor(blendColor), mBitmap(nullptr)
+ {
+ mImageFile = StringTable->insert(imageFile);
+ }
+
+ void LoadImage(const char* path)
+ {
+ mBitmap = GBitmap::load(path);
+ }
+
+ StringTableEntry mImageFile;
+ Point2I mPosition;
+ ColorF mBlendColor;
+ GBitmap* mBitmap;
+ };
+
private:
typedef Vector typeFrameAreaVector;
typedef Vector typeExplicitFrameAreaVector;
+ typedef Vector typeImageLayerVector;
/// Configuration.
StringTableEntry mImageFile;
@@ -181,6 +204,8 @@ class ImageAsset : public AssetBase
typeFrameAreaVector mFrames;
typeExplicitFrameAreaVector mExplicitFrames;
TextureHandle mImageTextureHandle;
+ typeImageLayerVector mImageLayers;
+ ColorF mBlendColor;
public:
ImageAsset();
@@ -194,6 +219,7 @@ class ImageAsset : public AssetBase
void setImageFile( const char* pImageFile );
inline StringTableEntry getImageFile( void ) const { return mImageFile; };
+ inline StringTableEntry getRelativeImageFile(void) const { return collapseAssetFilePath(mImageFile); };
void setForce16Bit( const bool force16Bit );
inline bool getForce16Bit( void ) const { return mForce16Bit; }
@@ -267,6 +293,26 @@ class ImageAsset : public AssetBase
inline void forceCalculation( void ) { calculateImage(); }
+ /// Layers
+ void addLayer(const char* imagePath, const Point2I position, const ColorF blendColor, const bool doRedraw = true);
+ void insertLayer(const U32 index, const char* imagePath, const Point2I position, const ColorF blendColor, const bool doRedraw = true);
+ void removeLayer(const U32 index, const bool doRedraw = true);
+ void moveLayerForward(const U32 index, const bool doRedraw = true);
+ void moveLayerBackward(const U32 index, const bool doRedraw = true);
+ void moveLayerToFront(const U32 index, const bool doRedraw = true);
+ void moveLayerToBack(const U32 index, const bool doRedraw = true);
+ void setLayerImage(const U32 index, const char* imagePath, const bool doRedraw = true);
+ void setLayerPosition(const U32 index, const Point2I position, const bool doRedraw = true);
+ void setLayerBlendColor(const U32 index, const ColorF color, const bool doRedraw = true);
+ const U32 getLayerCount() { return getMax(mImageLayers.size() - 1, 0); } //We pretend layer 0 doesn't exist as it is internally created
+ const char* getLayerImage(const U32 index);
+ const Point2I getLayerPosition(const U32 index);
+ const ColorF getLayerBlendColor(const U32 index);
+ void forceRedrawImage() { redrawImage(); }
+ void setBlendColor(const ColorF color, const bool doRedraw = true);
+ const ColorF getBlendColor();
+
+
/// Declare Console Object.
DECLARE_CONOBJECT(ImageAsset);
@@ -277,6 +323,9 @@ class ImageAsset : public AssetBase
void calculateExplicitMode( void );
void setTextureFilter( const TextureFilterMode filterMode );
+ void completeLayerChange(const bool doRedraw);
+ void redrawImage();
+
protected:
virtual void initializeAsset( void );
virtual void onAssetRefresh( void );
@@ -287,6 +336,9 @@ class ImageAsset : public AssetBase
virtual void onTamlCustomWrite( TamlCustomNodes& customNodes );
virtual void onTamlCustomRead( const TamlCustomNodes& customNodes );
+ virtual void loadTamlExplicitCells(const TamlCustomNodes& customNodes);
+ virtual void loadTamlImageLayers(const TamlCustomNodes& customNodes);
+
protected:
static void textureEventCallback( const U32 eventCode, void *userData );
@@ -330,6 +382,22 @@ class ImageAsset : public AssetBase
static bool setCellHeight( void* obj, const char* data ) { static_cast(obj)->setCellHeight(dAtoi(data)); return false; }
static bool writeCellHeight( void* obj, StringTableEntry pFieldName ) { ImageAsset* pImageAsset = static_cast(obj); return !pImageAsset->getExplicitMode() && pImageAsset->getCellHeight() != 0; }
+
+ static bool setBlendColor(void* obj, const char* data)
+ {
+ if (Utility::mGetStringElementCount(data) < 4)
+ {
+ Con::warnf("ImageAsset::BlendColor - Blend colors require four values (red/green/blue/alpha).");
+ return false;
+ }
+ static_cast(obj)->setBlendColor(
+ ColorF(dAtof(Utility::mGetStringElement(data, 0)),
+ dAtof(Utility::mGetStringElement(data, 1)),
+ dAtof(Utility::mGetStringElement(data, 2)),
+ dAtof(Utility::mGetStringElement(data, 3))), true);
+ return false;
+ }
+ static bool writeBlendColor(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getBlendColor() != ColorF(1.0f, 1.0f, 1.0f, 1.0f); }
};
//-----------------------------------------------------------------------------
diff --git a/engine/source/2d/assets/ImageAsset_ScriptBinding.h b/engine/source/2d/assets/ImageAsset_ScriptBinding.h
index 792d2b035..c3e69e70c 100755
--- a/engine/source/2d/assets/ImageAsset_ScriptBinding.h
+++ b/engine/source/2d/assets/ImageAsset_ScriptBinding.h
@@ -33,13 +33,23 @@ ConsoleMethodWithDocs(ImageAsset, setImageFile, ConsoleVoid, 3, 3, (ImageFile))
//-----------------------------------------------------------------------------
/*! Gets the image file.
- @return Returns the bitmap image file.
+ @return Returns the bitmap image file, typically as an absolute path.
*/
ConsoleMethodWithDocs(ImageAsset, getImageFile, ConsoleString, 2, 2, ())
{
return object->getImageFile();
}
+//-----------------------------------------------------------------------------
+
+/*! Gets the image file.
+ @return Returns the bitmap image file as a path relative to the asset file.
+*/
+ConsoleMethodWithDocs(ImageAsset, getRelativeImageFile, ConsoleString, 2, 2, ())
+{
+ return object->getRelativeImageFile();
+}
+
//------------------------------------------------------------------------------
/*! Sets the filter mode.
@@ -602,4 +612,427 @@ ConsoleMethodWithDocs(ImageAsset, setExplicitMode, ConsoleVoid, 3, 3, (explicitM
object->setExplicitMode(dAtob(argv[2]));
}
+/*! Adds a layer to the ImageAsset
+@param imageFile The file for the image to layer over the texture.
+@param position The position for the layer to be at with (0, 0) in the top left corner.
+@param blendColor The blending color to be applied to this new layer.
+@param doRedraw Optional value that prevents a redraw of the texture when false. Defaults to true.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, addLayer, ConsoleVoid, 5, 6, (imageFile, position, blendColor, [doRedraw]))
+{
+ if (argc < 5)
+ {
+ Con::warnf("ImageAsset::addLayer() - Invalid number of parameters!");
+ return;
+ }
+
+ F32 x, y;
+ x = 0.0f;
+ y = 0.0f;
+ if (Utility::mGetStringElementCount(argv[3]) >= 2)
+ {
+ x = dAtof(Utility::mGetStringElement(argv[3], 0));
+ y = dAtof(Utility::mGetStringElement(argv[3], 1));
+ }
+ Point2I pos(x, y);
+
+ const U32 colorCount = Utility::mGetStringElementCount(argv[4]);
+ if (colorCount != 4)
+ {
+ Con::warnf("Scene::addLayer() - Invalid color! Colors require four values (red / green / blue / alpha)!");
+ return;
+ }
+ ColorF blendColor = ColorF(dAtof(Utility::mGetStringElement(argv[4], 0)),
+ dAtof(Utility::mGetStringElement(argv[4], 1)),
+ dAtof(Utility::mGetStringElement(argv[4], 2)),
+ dAtof(Utility::mGetStringElement(argv[4], 3)));
+
+ bool redraw = true;
+ if (argc == 6)
+ {
+ redraw = dAtob(argv[5]);
+ }
+
+ object->addLayer(argv[2], pos, blendColor, redraw);
+}
+
+/*! Inserts a layer into the stack of layers on a texture at a given index.
+@param index The one-based index to insert the new layer at. Must be less or equal to the number of layers.
+@param imageFile The file for the image to layer over the texture.
+@param position The position for the layer to be at with (0, 0) in the top left corner.
+@param blendColor The blending color to be applied to this new layer.
+@param doRedraw Optional value that prevents a redraw of the texture when false. Defaults to true.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, insertLayer, ConsoleVoid, 6, 7, (index, imageFile, position, blendColor, [doRedraw]))
+{
+ if (argc < 6)
+ {
+ Con::warnf("ImageAsset::insertLayer() - Invalid number of parameters!");
+ return;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ F32 x, y;
+ x = 0.0f;
+ y = 0.0f;
+ if (Utility::mGetStringElementCount(argv[4]) >= 2)
+ {
+ x = dAtof(Utility::mGetStringElement(argv[4], 0));
+ y = dAtof(Utility::mGetStringElement(argv[4], 1));
+ }
+ Point2I pos(x, y);
+
+ const U32 colorCount = Utility::mGetStringElementCount(argv[5]);
+ if (colorCount != 4)
+ {
+ Con::warnf("Scene::insertLayer() - Invalid color! Colors require four values (red / green / blue / alpha)!");
+ return;
+ }
+ ColorF blendColor = ColorF(dAtof(Utility::mGetStringElement(argv[5], 0)),
+ dAtof(Utility::mGetStringElement(argv[5], 1)),
+ dAtof(Utility::mGetStringElement(argv[5], 2)),
+ dAtof(Utility::mGetStringElement(argv[5], 3)));
+
+ bool redraw = true;
+ if (argc == 7)
+ {
+ redraw = dAtob(argv[6]);
+ }
+
+ object->insertLayer(index, argv[3], pos, blendColor, redraw);
+}
+
+/*! Removes a layer from a texture at a given index.
+@param index The one-based index to remove the new layer from. Must be less or equal to the number of layers.
+@param doRedraw Optional value that prevents a redraw of the texture when false. Defaults to true.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, removeLayer, ConsoleVoid, 3, 4, (index, [doRedraw]))
+{
+ if (argc < 3)
+ {
+ Con::warnf("ImageAsset::removeLayer() - Invalid number of parameters!");
+ return;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ bool redraw = true;
+ if (argc == 4)
+ {
+ redraw = dAtob(argv[3]);
+ }
+
+ object->removeLayer(index, redraw);
+}
+
+/*! Moves the layer at the index forward.
+@param index The one-based index to move forward. Must be less or equal to the number of layers.
+@param doRedraw Optional value that prevents a redraw of the texture when false. Defaults to true.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, moveLayerForward, ConsoleVoid, 3, 4, (index, [doRedraw]))
+{
+ if (argc < 3)
+ {
+ Con::warnf("ImageAsset::moveLayerForward() - Invalid number of parameters!");
+ return;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ bool redraw = true;
+ if (argc == 4)
+ {
+ redraw = dAtob(argv[3]);
+ }
+
+ object->moveLayerForward(index, redraw);
+}
+
+/*! Moves the layer at the index backward.
+@param index The one-based index to move backward. Must be less or equal to the number of layers.
+@param doRedraw Optional value that prevents a redraw of the texture when false. Defaults to true.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, moveLayerBackward, ConsoleVoid, 3, 4, (index, [doRedraw]))
+{
+ if (argc < 3)
+ {
+ Con::warnf("ImageAsset::moveLayerBackward() - Invalid number of parameters!");
+ return;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ bool redraw = true;
+ if (argc == 4)
+ {
+ redraw = dAtob(argv[3]);
+ }
+
+ object->moveLayerBackward(index, redraw);
+}
+
+/*! Moves the layer at the index to the front.
+@param index The one-based index to move to the front. Must be less or equal to the number of layers.
+@param doRedraw Optional value that prevents a redraw of the texture when false. Defaults to true.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, moveLayerToFront, ConsoleVoid, 3, 4, (index, [doRedraw]))
+{
+ if (argc < 3)
+ {
+ Con::warnf("ImageAsset::moveLayerToFront() - Invalid number of parameters!");
+ return;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ bool redraw = true;
+ if (argc == 4)
+ {
+ redraw = dAtob(argv[3]);
+ }
+
+ object->moveLayerToFront(index, redraw);
+}
+
+/*! Moves the layer at the index to the back.
+@param index The one-based index to move to the back. Must be less or equal to the number of layers.
+@param doRedraw Optional value that prevents a redraw of the texture when false. Defaults to true.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, moveLayerToBack, ConsoleVoid, 3, 4, (index, [doRedraw]))
+{
+ if (argc < 3)
+ {
+ Con::warnf("ImageAsset::moveLayerToBack() - Invalid number of parameters!");
+ return;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ bool redraw = true;
+ if (argc == 4)
+ {
+ redraw = dAtob(argv[3]);
+ }
+
+ object->moveLayerToBack(index, redraw);
+}
+
+/*! Sets the image for a layer at the given index.
+@param index The one-based index to move to the back. Must be less or equal to the number of layers.
+@param image The path to an image to be used by the layer.
+@param doRedraw Optional value that prevents a redraw of the texture when false. Defaults to true.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, setLayerImage, ConsoleVoid, 4, 5, (index, image, [doRedraw]))
+{
+ if (argc < 4)
+ {
+ Con::warnf("ImageAsset::setLayerImage() - Invalid number of parameters!");
+ return;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ bool redraw = true;
+ if (argc == 5)
+ {
+ redraw = dAtob(argv[4]);
+ }
+
+ object->setLayerImage(index, argv[3], redraw);
+}
+
+/*! Sets the position for a layer at the given index.
+@param index The one-based index to move to the back. Must be less or equal to the number of layers.
+@param position The space-deliminated (x, y) position to place the image with the top left corner as (0, 0). The layer can safely overflow the bounds of the original image.
+@param doRedraw Optional value that prevents a redraw of the texture when false. Defaults to true.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, setLayerPosition, ConsoleVoid, 4, 5, (index, position, [doRedraw]))
+{
+ if (argc < 4)
+ {
+ Con::warnf("ImageAsset::setLayerPosition() - Invalid number of parameters!");
+ return;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ F32 x, y;
+ x = 0.0f;
+ y = 0.0f;
+ if (Utility::mGetStringElementCount(argv[3]) >= 2)
+ {
+ x = dAtof(Utility::mGetStringElement(argv[3], 0));
+ y = dAtof(Utility::mGetStringElement(argv[3], 1));
+ }
+ Point2I pos(x, y);
+
+ bool redraw = true;
+ if (argc == 5)
+ {
+ redraw = dAtob(argv[4]);
+ }
+
+ object->setLayerPosition(index, pos, redraw);
+}
+
+/*! Sets the blend color for a layer at the given index.
+@param index The one-based index to move to the back. Must be less or equal to the number of layers.
+@param blendColor The space-deliminated color used to blend the layer. Requires four decimal values between 0 and 1 that represent red, green, blue, and alpha.
+@param doRedraw Optional value that prevents a redraw of the texture when false. Defaults to true.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, setLayerBlendColor, ConsoleVoid, 4, 5, (index, blendColor, [doRedraw]))
+{
+ if (argc < 4)
+ {
+ Con::warnf("ImageAsset::setLayerBlendColor() - Invalid number of parameters!");
+ return;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ const U32 colorCount = Utility::mGetStringElementCount(argv[3]);
+ if (colorCount != 4)
+ {
+ Con::warnf("Scene::setLayerBlendColor() - Invalid color! Colors require four values (red / green / blue / alpha)!");
+ return;
+ }
+ ColorF blendColor = ColorF(dAtof(Utility::mGetStringElement(argv[3], 0)),
+ dAtof(Utility::mGetStringElement(argv[3], 1)),
+ dAtof(Utility::mGetStringElement(argv[3], 2)),
+ dAtof(Utility::mGetStringElement(argv[3], 3)));
+
+ bool redraw = true;
+ if (argc == 5)
+ {
+ redraw = dAtob(argv[4]);
+ }
+
+ object->setLayerBlendColor(index, blendColor, redraw);
+}
+
+/*! Returns the number of layers.
+@return The number of layers used by the texture. Zero if only the base texture is used.
+*/
+ConsoleMethodWithDocs(ImageAsset, getLayerCount, ConsoleInt, 2, 2, ())
+{
+ return object->getLayerCount();
+}
+
+/*! Returns image used for a given layer.
+@param index The one-based index to move to the back. Must be less or equal to the number of layers.
+@return The path to the image file.
+*/
+ConsoleMethodWithDocs(ImageAsset, getLayerImage, ConsoleString, 3, 3, (index))
+{
+ if (argc < 3)
+ {
+ Con::warnf("ImageAsset::getLayerImage() - Invalid number of parameters!");
+ return StringTable->EmptyString;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ return object->getLayerImage(index);
+}
+
+/*! Returns position for a given layer.
+@param index The one-based index to move to the back. Must be less or equal to the number of layers.
+@return (int y, int x) The layer position.
+*/
+ConsoleMethodWithDocs(ImageAsset, getLayerPosition, ConsoleString, 3, 3, (index))
+{
+ if (argc < 3)
+ {
+ Con::warnf("ImageAsset::getLayerPosition() - Invalid number of parameters!");
+ return StringTable->EmptyString;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ char* retBuffer = Con::getReturnBuffer(64);
+ const Point2I& pos = object->getLayerPosition(index);
+ dSprintf(retBuffer, 64, "%d %d", pos.x, pos.y);
+ return retBuffer;
+}
+
+/*! Returns the blend color for a given layer.
+@param index The one-based index to move to the back. Must be less or equal to the number of layers.
+@return (float red / float green / float blue / float alpha) The layer blend color.
+*/
+ConsoleMethodWithDocs(ImageAsset, getLayerBlendColor, ConsoleString, 3, 3, (index))
+{
+ if (argc < 3)
+ {
+ Con::warnf("ImageAsset::getLayerBlendColor() - Invalid number of parameters!");
+ return StringTable->EmptyString;
+ }
+
+ U32 index = dAtoi(argv[2]);
+
+ return object->getLayerBlendColor(index).scriptThis();
+}
+
+/*! Forces the texture to redraw its layers. Redrawing can be expensive and is automatically done on every change to a layer unless prevented.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, forceRedraw, ConsoleVoid, 2, 2, ())
+{
+ if (object->getLayerCount() > 0)
+ {
+ object->forceRedrawImage();
+ }
+}
+
+/*! Sets the blend color for the base image when using layers.
+@param blendColor The space-deliminated color used to blend the layer. Requires four decimal values between 0 and 1 that represent red, green, blue, and alpha.
+@param doRedraw Optional value that prevents a redraw of the texture when false. Defaults to true.
+@return No return value.
+*/
+ConsoleMethodWithDocs(ImageAsset, setBlendColor, ConsoleVoid, 3, 4, (blendColor, [doRedraw]))
+{
+ if (argc < 3)
+ {
+ Con::warnf("ImageAsset::setBlendColor() - Invalid number of parameters!");
+ return;
+ }
+
+ const U32 colorCount = Utility::mGetStringElementCount(argv[2]);
+ if (colorCount != 4)
+ {
+ Con::warnf("Scene::setBlendColor() - Invalid color! Colors require four values (red / green / blue / alpha)!");
+ return;
+ }
+ ColorF blendColor = ColorF(dAtof(Utility::mGetStringElement(argv[2], 0)),
+ dAtof(Utility::mGetStringElement(argv[2], 1)),
+ dAtof(Utility::mGetStringElement(argv[2], 2)),
+ dAtof(Utility::mGetStringElement(argv[2], 3)));
+
+ bool redraw = true;
+ if (argc == 4)
+ {
+ redraw = dAtob(argv[3]);
+ }
+
+ object->setBlendColor(blendColor, redraw);
+}
+
+/*! Returns the blend color for the base texture when using layers.
+@return (float red / float green / float blue / float alpha) The base blend color.
+*/
+ConsoleMethodWithDocs(ImageAsset, getBlendColor, ConsoleString, 2, 2, ())
+{
+ return object->getBlendColor().scriptThis();
+}
+
ConsoleMethodGroupEndWithDocs(ImageAsset)
diff --git a/engine/source/2d/assets/ParticleAssetFieldCollection.h b/engine/source/2d/assets/ParticleAssetFieldCollection.h
index 954d872e8..26579ec1c 100644
--- a/engine/source/2d/assets/ParticleAssetFieldCollection.h
+++ b/engine/source/2d/assets/ParticleAssetFieldCollection.h
@@ -27,7 +27,7 @@
#include "2d/assets/ParticleAssetField.h"
#endif
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/2d/core/BatchRender.h b/engine/source/2d/core/BatchRender.h
index a138a1f95..64d49a231 100755
--- a/engine/source/2d/core/BatchRender.h
+++ b/engine/source/2d/core/BatchRender.h
@@ -39,7 +39,7 @@
#include "graphics/TextureManager.h"
#endif
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/2d/editorToy/EditorToySceneWindow.cc b/engine/source/2d/editorToy/EditorToySceneWindow.cc
index 2d0348223..85ca9e3fd 100644
--- a/engine/source/2d/editorToy/EditorToySceneWindow.cc
+++ b/engine/source/2d/editorToy/EditorToySceneWindow.cc
@@ -382,10 +382,8 @@ bool EditorToySceneWindow::initCursors()
mLeftRightCursor = dynamic_cast(obj);
obj = Sim::findObject("DefaultCursor");
mDefaultCursor = dynamic_cast(obj);
- obj = Sim::findObject("MoveCursor");
- mMoveCursor = dynamic_cast(obj);
- return(mMoveCursor != NULL && mUpDownCursor != NULL && mLeftRightCursor != NULL && mDefaultCursor != NULL && mMoveCursor != NULL);
+ return(mMoveCursor != NULL && mUpDownCursor != NULL && mLeftRightCursor != NULL && mDefaultCursor != NULL);
}
else
return(true);
diff --git a/engine/source/2d/gui/guiSpriteCtrl.cc b/engine/source/2d/gui/guiSpriteCtrl.cc
index 0267022c5..789eddcf8 100755
--- a/engine/source/2d/gui/guiSpriteCtrl.cc
+++ b/engine/source/2d/gui/guiSpriteCtrl.cc
@@ -67,6 +67,7 @@ GuiSpriteCtrl::GuiSpriteCtrl( void ) :
mImageSize.set(10, 10);
mFullSize = true;
mConstrainProportions = true;
+ mClampImage = true;
mSingleFrameBitmap = true;
}
@@ -95,6 +96,7 @@ void GuiSpriteCtrl::initPersistFields()
addField("imageColor", TypeFluidColorI, Offset(mImageColor, GuiSpriteCtrl));
addField("imageSize", TypePoint2I, Offset(mImageSize, GuiSpriteCtrl));
addField("fullSize", TypeBool, Offset(mFullSize, GuiSpriteCtrl));
+ addField("clampImage", TypeBool, Offset(mClampImage, GuiSpriteCtrl));
addField("constrainProportions", TypeBool, Offset(mConstrainProportions, GuiSpriteCtrl));
endGroup("GuiSpriteCtrl");
}
@@ -348,10 +350,18 @@ Point2I GuiSpriteCtrl::applyAlignment(RectI &bounds, Point2I &size)
}
//Apply the image offset
- S32 maxX = bounds.extent.x - size.x;
- S32 maxY = bounds.extent.y - size.y;
- offset.x = mClamp(offset.x + mPositionOffset.x, 0, maxX);
- offset.y = mClamp(offset.y + mPositionOffset.y, 0, maxY);
+ if (mClampImage)
+ {
+ S32 maxX = bounds.extent.x - size.x;
+ S32 maxY = bounds.extent.y - size.y;
+ offset.x = mClamp(offset.x + mPositionOffset.x, 0, maxX);
+ offset.y = mClamp(offset.y + mPositionOffset.y, 0, maxY);
+ }
+ else
+ {
+ offset.x = offset.x + mPositionOffset.x;
+ offset.y = offset.y + mPositionOffset.y;
+ }
return offset;
}
@@ -546,50 +556,52 @@ void GuiSpriteCtrl::onRender(Point2I offset, const RectI &updateRect)
dglSetClipRect(clipRect);
dglSetBitmapModulation(ColorF(mImageColor));
- Point2I offset = Point2I(0, 0);
+ Point2I imageOffset = Point2I(0, 0);
Point2I size = constrain(mImageSize);
if (mTileImage) //Tile the image
{
- offset = mPositionOffset;
- offset.x = (mPositionOffset.x % size.x);
- if (offset.x > 0)
+ imageOffset = mPositionOffset;
+ imageOffset.x = (mPositionOffset.x % size.x);
+ if (imageOffset.x > 0)
{
- offset.x -= size.x;
+ imageOffset.x -= size.x;
}
- offset.y = (mPositionOffset.y % size.y);
- if (offset.y > 0)
+ imageOffset.y = (mPositionOffset.y % size.y);
+ if (imageOffset.y > 0)
{
- offset.y -= size.y;
+ imageOffset.y -= size.y;
}
- RenderTiledImage(contentRect, offset, size);
+ RenderTiledImage(contentRect, imageOffset, size);
}
else if (mFullSize) //Fill with the image
{
size = constrain(contentRect.extent, false);
if (mConstrainProportions)
{
- offset = applyAlignment(contentRect, size);
+ imageOffset = applyAlignment(contentRect, size);
}
- RenderImage(contentRect, offset, size);
+ RenderImage(contentRect, imageOffset, size);
}
else //Position the image by profile alignment
{
- size = constrain(mImageSize);
- if (size.x > contentRect.extent.x)
- {
- size.x = contentRect.extent.x;
- size = constrainLockX(size);
- }
- if (size.y > contentRect.extent.y)
+ if (mClampImage)
{
- size.y = contentRect.extent.y;
- size = constrainLockY(size);
+ if (size.x > contentRect.extent.x)
+ {
+ size.x = contentRect.extent.x;
+ size = constrainLockX(size);
+ }
+ if (size.y > contentRect.extent.y)
+ {
+ size.y = contentRect.extent.y;
+ size = constrainLockY(size);
+ }
}
- offset = applyAlignment(contentRect, size);
+ imageOffset = applyAlignment(contentRect, size);
- RenderImage(contentRect, offset, size);
+ RenderImage(contentRect, imageOffset, size);
}
dglClearBitmapModulation();
dglSetClipRect(oldClip);
diff --git a/engine/source/2d/gui/guiSpriteCtrl.h b/engine/source/2d/gui/guiSpriteCtrl.h
index 9d0aaa9c9..7421fe6c1 100755
--- a/engine/source/2d/gui/guiSpriteCtrl.h
+++ b/engine/source/2d/gui/guiSpriteCtrl.h
@@ -49,6 +49,7 @@ class GuiSpriteCtrl : public GuiControl, public ImageFrameProvider
Point2I mImageSize; //The size of the image, reduced, if needed, to fit the content area
bool mFullSize; //If true, the image will take all available space
bool mConstrainProportions; //If true, the image will maintain its aspect ratio
+ bool mClampImage; //If true, the image will be forced into the control's content area.
bool mSingleFrameBitmap; //If true and bitmaps are used, this will assume there's only one frame when scanning the bitmap
Fluid mFluidMoveTo;
@@ -110,6 +111,8 @@ class GuiSpriteCtrl : public GuiControl, public ImageFrameProvider
inline void setImageSize(Point2I size) { mImageSize = size; }
inline bool getFullSize() { return mFullSize; }
inline void setFullSize(bool isFull) { mFullSize = isFull; }
+ inline bool getClampImage() { return mClampImage; }
+ inline void setClampImage(bool clamp) { mClampImage = clamp; }
inline bool getConstrainProportions() { return mConstrainProportions; }
inline void setConstrainProportions(bool setting) { mConstrainProportions = setting; }
inline bool getSingleFrameBitmap() { return mSingleFrameBitmap; }
diff --git a/engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h b/engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h
index 70b6e5f42..8eb1b2288 100755
--- a/engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h
+++ b/engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h
@@ -761,6 +761,29 @@ ConsoleMethodWithDocs(GuiSpriteCtrl, getConstrainProportions, ConsoleBool, 2, 2,
return object->getConstrainProportions();
}
+/*! Sets if the image should be able to overflow the content area.
+ @param clamp If true, the image will be forced into the content area. False will allow the image to overflow the content area, although it will still be cut off.
+ @return No return value.
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, setClampImage, ConsoleVoid, 3, 3, "(bool clamp)")
+{
+ if (argc != 3)
+ {
+ Con::warnf("GuiSpriteCtrl::setClampImage() - Invalid number of parameters!");
+ return;
+ }
+
+ object->setClampImage(dAtob(argv[2]));
+}
+
+/*! Gets if the image is able to overflow the content area.
+ @return True if overflow is possible and false otherwise.
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, getClampImage, ConsoleBool, 2, 2, "()")
+{
+ return object->getClampImage();
+}
+
/*! Animates the position offset from its current value to a target value over time.
@param x/y The space-delimited x and y values to change the image offset to.
@param time The time in miliseconds it should take to complete the transformation.
diff --git a/engine/source/2d/scene/Scene.cc b/engine/source/2d/scene/Scene.cc
index 93d67dff9..1c33f5e20 100755
--- a/engine/source/2d/scene/Scene.cc
+++ b/engine/source/2d/scene/Scene.cc
@@ -3578,7 +3578,7 @@ void Scene::setDebugSceneObject( SceneObject* pSceneObject )
void Scene::setLayerSortMode( const U32 layer, const SceneRenderQueue::RenderSort sortMode )
{
// Is the layer valid?
- if ( layer > MAX_LAYERS_SUPPORTED )
+ if ( layer >= MAX_LAYERS_SUPPORTED )
{
// No, so warn.
Con::warnf( "Scene::setLayerSortMode() - Layer '%d' is out of range.", layer );
@@ -3603,7 +3603,7 @@ void Scene::setLayerSortMode( const U32 layer, const SceneRenderQueue::RenderSor
SceneRenderQueue::RenderSort Scene::getLayerSortMode( const U32 layer )
{
// Is the layer valid?
- if ( layer > MAX_LAYERS_SUPPORTED )
+ if ( layer >= MAX_LAYERS_SUPPORTED )
{
// No, so warn.
Con::warnf( "Scene::getLayerSortMode() - Layer '%d' is out of range.", layer );
diff --git a/engine/source/2d/scene/Scene.h b/engine/source/2d/scene/Scene.h
index 3b1338c02..9a2e8b3d8 100755
--- a/engine/source/2d/scene/Scene.h
+++ b/engine/source/2d/scene/Scene.h
@@ -51,7 +51,7 @@
#include "2d/scene/DebugDraw.h"
#endif
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/2d/sceneobject/Path.h b/engine/source/2d/sceneobject/Path.h
index 6800def08..420525368 100644
--- a/engine/source/2d/sceneobject/Path.h
+++ b/engine/source/2d/sceneobject/Path.h
@@ -77,6 +77,7 @@ class Path : public SceneObject
{
if (mNodes.empty()) return false;
if((index >= 0) && (index < mNodes.size())) return true;
+ return false;
}
void attachObject(SceneObject* object, F32 speed, F32 force, bool orientToPath, F32 angleOff, bool snapToNode, S32 startNode, bool loop, S32 maxLoop);
@@ -95,6 +96,8 @@ class Path : public SceneObject
Vector::iterator i;
for (i = mObjs.begin(); i != mObjs.end(); i++)
if ((*i)->mObj == obj) return *i;
+
+ return NULL;
}
DECLARE_CONOBJECT(Path);
@@ -110,4 +113,4 @@ class Path : public SceneObject
};
-#endif
\ No newline at end of file
+#endif
diff --git a/engine/source/2d/sceneobject/SceneObject.cc b/engine/source/2d/sceneobject/SceneObject.cc
index 1f2291d2c..5cc33cf8a 100755
--- a/engine/source/2d/sceneobject/SceneObject.cc
+++ b/engine/source/2d/sceneobject/SceneObject.cc
@@ -4029,7 +4029,7 @@ void SceneObject::onTamlCustomRead( const TamlCustomNodes& customNodes )
}
// Is point count valid?
- if ( pointCount == 0 || pointCount != 2 )
+ if ( pointCount != 2 )
{
// No, so warn.
Con::warnf( "SceneObject::onTamlCustomRead() - No points (or not two points) on edge collision shape." );
diff --git a/engine/source/2d/sceneobject/Trigger.h b/engine/source/2d/sceneobject/Trigger.h
index 82a0f6897..e9fef6739 100755
--- a/engine/source/2d/sceneobject/Trigger.h
+++ b/engine/source/2d/sceneobject/Trigger.h
@@ -27,7 +27,7 @@
#include "2d/sceneobject/SceneObject.h"
#endif
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/algorithm/pcg_basic.c b/engine/source/algorithm/pcg_basic.c
new file mode 100644
index 000000000..8c2fd0d22
--- /dev/null
+++ b/engine/source/algorithm/pcg_basic.c
@@ -0,0 +1,116 @@
+/*
+ * PCG Random Number Generation for C.
+ *
+ * Copyright 2014 Melissa O'Neill
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For additional information about the PCG random number generation scheme,
+ * including its license and other licensing options, visit
+ *
+ * http://www.pcg-random.org
+ */
+
+/*
+ * This code is derived from the full C implementation, which is in turn
+ * derived from the canonical C++ PCG implementation. The C++ version
+ * has many additional features and is preferable if you can use C++ in
+ * your project.
+ */
+
+#include "pcg_basic.h"
+
+// state for global RNGs
+
+static pcg32_random_t pcg32_global = PCG32_INITIALIZER;
+
+// pcg32_srandom(initstate, initseq)
+// pcg32_srandom_r(rng, initstate, initseq):
+// Seed the rng. Specified in two parts, state initializer and a
+// sequence selection constant (a.k.a. stream id)
+
+void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate, uint64_t initseq)
+{
+ rng->state = 0U;
+ rng->inc = (initseq << 1u) | 1u;
+ pcg32_random_r(rng);
+ rng->state += initstate;
+ pcg32_random_r(rng);
+}
+
+void pcg32_srandom(uint64_t seed, uint64_t seq)
+{
+ pcg32_srandom_r(&pcg32_global, seed, seq);
+}
+
+// pcg32_random()
+// pcg32_random_r(rng)
+// Generate a uniformly distributed 32-bit random number
+
+uint32_t pcg32_random_r(pcg32_random_t* rng)
+{
+ uint64_t oldstate = rng->state;
+ rng->state = oldstate * 6364136223846793005ULL + rng->inc;
+ uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
+ uint32_t rot = oldstate >> 59u;
+ return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
+}
+
+uint32_t pcg32_random()
+{
+ return pcg32_random_r(&pcg32_global);
+}
+
+
+// pcg32_boundedrand(bound):
+// pcg32_boundedrand_r(rng, bound):
+// Generate a uniformly distributed number, r, where 0 <= r < bound
+
+uint32_t pcg32_boundedrand_r(pcg32_random_t* rng, uint32_t bound)
+{
+ // To avoid bias, we need to make the range of the RNG a multiple of
+ // bound, which we do by dropping output less than a threshold.
+ // A naive scheme to calculate the threshold would be to do
+ //
+ // uint32_t threshold = 0x100000000ull % bound;
+ //
+ // but 64-bit div/mod is slower than 32-bit div/mod (especially on
+ // 32-bit platforms). In essence, we do
+ //
+ // uint32_t threshold = (0x100000000ull-bound) % bound;
+ //
+ // because this version will calculate the same modulus, but the LHS
+ // value is less than 2^32.
+
+ uint32_t threshold = -bound % bound;
+
+ // Uniformity guarantees that this loop will terminate. In practice, it
+ // should usually terminate quickly; on average (assuming all bounds are
+ // equally likely), 82.25% of the time, we can expect it to require just
+ // one iteration. In the worst case, someone passes a bound of 2^31 + 1
+ // (i.e., 2147483649), which invalidates almost 50% of the range. In
+ // practice, bounds are typically small and only a tiny amount of the range
+ // is eliminated.
+ for (;;) {
+ uint32_t r = pcg32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+
+uint32_t pcg32_boundedrand(uint32_t bound)
+{
+ return pcg32_boundedrand_r(&pcg32_global, bound);
+}
+
diff --git a/engine/source/algorithm/pcg_basic.h b/engine/source/algorithm/pcg_basic.h
new file mode 100644
index 000000000..e2b526aa8
--- /dev/null
+++ b/engine/source/algorithm/pcg_basic.h
@@ -0,0 +1,78 @@
+/*
+ * PCG Random Number Generation for C.
+ *
+ * Copyright 2014 Melissa O'Neill
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For additional information about the PCG random number generation scheme,
+ * including its license and other licensing options, visit
+ *
+ * http://www.pcg-random.org
+ */
+
+/*
+ * This code is derived from the full C implementation, which is in turn
+ * derived from the canonical C++ PCG implementation. The C++ version
+ * has many additional features and is preferable if you can use C++ in
+ * your project.
+ */
+
+#ifndef PCG_BASIC_H_INCLUDED
+#define PCG_BASIC_H_INCLUDED 1
+
+#include
+
+#if __cplusplus
+extern "C" {
+#endif
+
+struct pcg_state_setseq_64 { // Internals are *Private*.
+ uint64_t state; // RNG state. All values are possible.
+ uint64_t inc; // Controls which RNG sequence (stream) is
+ // selected. Must *always* be odd.
+};
+typedef struct pcg_state_setseq_64 pcg32_random_t;
+
+// If you *must* statically initialize it, here's one.
+
+#define PCG32_INITIALIZER { 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL }
+
+// pcg32_srandom(initstate, initseq)
+// pcg32_srandom_r(rng, initstate, initseq):
+// Seed the rng. Specified in two parts, state initializer and a
+// sequence selection constant (a.k.a. stream id)
+
+void pcg32_srandom(uint64_t initstate, uint64_t initseq);
+void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate,
+ uint64_t initseq);
+
+// pcg32_random()
+// pcg32_random_r(rng)
+// Generate a uniformly distributed 32-bit random number
+
+uint32_t pcg32_random(void);
+uint32_t pcg32_random_r(pcg32_random_t* rng);
+
+// pcg32_boundedrand(bound):
+// pcg32_boundedrand_r(rng, bound):
+// Generate a uniformly distributed number, r, where 0 <= r < bound
+
+uint32_t pcg32_boundedrand(uint32_t bound);
+uint32_t pcg32_boundedrand_r(pcg32_random_t* rng, uint32_t bound);
+
+#if __cplusplus
+}
+#endif
+
+#endif // PCG_BASIC_H_INCLUDED
diff --git a/engine/source/assets/assetTagsManifest.h b/engine/source/assets/assetTagsManifest.h
index bb744026c..6d49c74bb 100755
--- a/engine/source/assets/assetTagsManifest.h
+++ b/engine/source/assets/assetTagsManifest.h
@@ -27,7 +27,7 @@
#include "sim/simBase.h"
#endif
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/collection/hashTable.h b/engine/source/collection/hashTable.h
index 9b58be9ec..b5e2a5b42 100755
--- a/engine/source/collection/hashTable.h
+++ b/engine/source/collection/hashTable.h
@@ -20,8 +20,8 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
-#ifndef _HASHTABLE_H
-#define _HASHTABLE_H
+#ifndef _HASHTABLE_H_
+#define _HASHTABLE_H_
#include "vector.h"
#include "platform/platform.h"
@@ -697,4 +697,4 @@ inline Value& HashMap::operator[](const Key& key)
-#endif// _HASHTABLE_H
+#endif// _HASHTABLE_H_
diff --git a/engine/source/collection/nameTags.h b/engine/source/collection/nameTags.h
index c743d0216..619b37105 100755
--- a/engine/source/collection/nameTags.h
+++ b/engine/source/collection/nameTags.h
@@ -27,7 +27,7 @@
#include "sim/simBase.h"
#endif
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/component/behaviors/behaviorInstance.h b/engine/source/component/behaviors/behaviorInstance.h
index 757f9dea9..6db795ccf 100755
--- a/engine/source/component/behaviors/behaviorInstance.h
+++ b/engine/source/component/behaviors/behaviorInstance.h
@@ -26,7 +26,7 @@
#include "sim/simBase.h"
#endif
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/console/console.cc b/engine/source/console/console.cc
index 3f1a62984..b37285c5e 100755
--- a/engine/source/console/console.cc
+++ b/engine/source/console/console.cc
@@ -42,7 +42,7 @@
#include "output_ScriptBinding.h"
#include "expando_ScriptBinding.h"
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/console/consoleDictionary.h b/engine/source/console/consoleDictionary.h
index f15c25b49..33b98d8d9 100755
--- a/engine/source/console/consoleDictionary.h
+++ b/engine/source/console/consoleDictionary.h
@@ -116,7 +116,7 @@ class Dictionary
if(type <= TypeInternalString)
{
fval = val;
- ival = static_cast(val);
+ ival = static_cast(static_cast(val));
if(sval != typeValueEmpty)
{
dFree(sval);
diff --git a/engine/source/game/defaultGame.cc b/engine/source/game/defaultGame.cc
index 39ba9e79d..e295c0807 100755
--- a/engine/source/game/defaultGame.cc
+++ b/engine/source/game/defaultGame.cc
@@ -592,9 +592,6 @@ void DefaultGame::processTimeEvent(TimeEvent *event)
{
elapsedTime = (U32) (elapsedTime * gTimeScale);
}
- {
- elapsedTime = elapsedTime;
- }
Platform::advanceTime(elapsedTime);
bool tickPass;
diff --git a/engine/source/game/version.h b/engine/source/game/version.h
index 4b623c088..20f894731 100755
--- a/engine/source/game/version.h
+++ b/engine/source/game/version.h
@@ -24,8 +24,8 @@
#define _ENGINE_VERSION_H_
// Engine Version.
-#define T2D_ENGINE_VERSION "v4.0.0 ea2" ///< Engine Version String.
-#define T2D_IPHONETOOLS_VERSION "v4.0.0 ea2" ///< Engine Version String for iPhone tools. Changing this will allow a fresh AppData folder to avoid conflicts with other builds existing on the system.
+#define T2D_ENGINE_VERSION "v4.0.0 ea2.1" ///< Engine Version String.
+#define T2D_IPHONETOOLS_VERSION "v4.0.0 ea2.1" ///< Engine Version String for iPhone tools. Changing this will allow a fresh AppData folder to avoid conflicts with other builds existing on the system.
/// Gets the specified version number. The version number is specified as a global in version.cc
U32 getVersionNumber();
diff --git a/engine/source/graphics/PNGImage.h b/engine/source/graphics/PNGImage.h
index bf3e126ce..895d3f5d6 100755
--- a/engine/source/graphics/PNGImage.h
+++ b/engine/source/graphics/PNGImage.h
@@ -71,7 +71,7 @@ class PNGImage : public SimObject
// Will "merge" the incoming image onto the current image on to an x, y position.
bool MergeOn(U32 x, U32 y, const PNGImage* inc);
- // Will clean up any allocated memory from the PNGImage. This must be called or their may be a memory leak.
+ // Will clean up any allocated memory from the PNGImage. This must be called or there may be a memory leak.
bool CleanMemoryUsage();
bool ClearImageData();
diff --git a/engine/source/graphics/gBitmap.cc b/engine/source/graphics/gBitmap.cc
index 59d4548c4..7e18ee870 100755
--- a/engine/source/graphics/gBitmap.cc
+++ b/engine/source/graphics/gBitmap.cc
@@ -121,6 +121,65 @@ void GBitmap::deleteImage()
SAFE_DELETE(pPalette);
}
+void GBitmap::clearImage(const ColorF blendColor)
+{
+ ColorI clearColor(blendColor.red, blendColor.green, blendColor.blue, 0);
+ for (U32 h = 0; h < getHeight(); h++)
+ {
+ for (U32 w = 0; w < getWidth(); w++)
+ {
+ setColor(w, h, clearColor);
+ }
+ }
+}
+
+bool GBitmap::mergeLayer(const Point2I pos, const GBitmap* layer, const ColorF blendColor)
+{
+ if (layer != nullptr && (getFormat() == BitmapFormat::RGBA || getFormat() == BitmapFormat::RGB) && (layer->getFormat() == BitmapFormat::RGBA || layer->getFormat() == BitmapFormat::RGB))
+ {
+ for (U32 h = getMax(0, pos.y); h < getHeight() && (h - pos.y) < layer->getHeight(); h++)
+ {
+ for (U32 w = getMax(0, pos.x); w < getWidth() && (w - pos.x) < layer->getWidth(); w++)
+ {
+ const U8* layerByte = layer->getAddress(w - pos.x, h - pos.y);
+ U8* baseByte = getAddress(w, h);
+
+ float layerAlpha = blendColor.alpha;
+ if (layer->getFormat() == BitmapFormat::RGBA)
+ {
+ layerAlpha = (layerByte[3] / 255.0f) * blendColor.alpha;
+ }
+ if (layerAlpha <= 0.005f)
+ {
+ continue;
+ }
+
+ float baseAlpha = 1.0f;
+ if (getFormat() == BitmapFormat::RGBA)
+ {
+ baseAlpha = (baseByte[3] / 255.0f);
+ }
+ float alpha = layerAlpha + baseAlpha * (1 - layerAlpha);
+
+ float red = ((float)layerByte[0]/255.0f * layerAlpha * blendColor.red) + ((float)baseByte[0]/255.0f * baseAlpha * (1 - layerAlpha)) / alpha;
+ float green = ((float)layerByte[1]/255.0f * layerAlpha * blendColor.green) + ((float)baseByte[1]/255.0f * baseAlpha * (1 - layerAlpha)) / alpha;
+ float blue = ((float)layerByte[2]/255.0f * layerAlpha * blendColor.blue) + ((float)baseByte[2]/255.0f * baseAlpha * (1 - layerAlpha)) / alpha;
+
+ baseByte[0] = (U8)mClamp(red * 255.0f, 0.0f, 255.0f);
+ baseByte[1] = (U8)mClamp(green * 255.0f, 0.0f, 255.0f);
+ baseByte[2] = (U8)mClamp(blue * 255.0f, 0.0f, 255.0f);
+
+ if (getFormat() == BitmapFormat::RGBA)
+ {
+ baseByte[3] = (U8)mClamp(alpha * 255.0f, 0.0f, 255.0f);
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
//--------------------------------------------------------------------------
void GBitmap::setPalette(GPalette* in_pPalette)
diff --git a/engine/source/graphics/gBitmap.h b/engine/source/graphics/gBitmap.h
index bc95cd82e..0c7934f2b 100755
--- a/engine/source/graphics/gBitmap.h
+++ b/engine/source/graphics/gBitmap.h
@@ -130,6 +130,7 @@ class GBitmap: public ResourceInstance
static U32 sBitmapIdSource;
void deleteImage();
+ void clearImage(const ColorF blendColor);
BitmapFormat internalFormat;
public:
@@ -149,6 +150,8 @@ class GBitmap: public ResourceInstance
/// deleted on exit, or written out on a
/// write.
+ bool mergeLayer(const Point2I pos, const GBitmap* layer, const ColorF blendColor);
+
//-------------------------------------- Input/Output interface
public:
bool readJPEG(Stream& io_rStream); // located in bitmapJpeg.cc
diff --git a/engine/source/graphics/gColor.cc b/engine/source/graphics/gColor.cc
index 993fb2d6b..fab84ad12 100644
--- a/engine/source/graphics/gColor.cc
+++ b/engine/source/graphics/gColor.cc
@@ -30,7 +30,7 @@
#include "string/stringUnit.h"
#endif
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/gui/buttons/guiDropDownCtrl.cc b/engine/source/gui/buttons/guiDropDownCtrl.cc
index eea6b7cf3..e760ddb92 100644
--- a/engine/source/gui/buttons/guiDropDownCtrl.cc
+++ b/engine/source/gui/buttons/guiDropDownCtrl.cc
@@ -180,13 +180,10 @@ void GuiDropDownCtrl::onRender(Point2I offset, const RectI& updateRect)
RectI contentRect = applyPadding(fillRect.point, fillRect.extent, currentState, mProfile);
//Render the triangle
- if(mProfile->usesDefaultRendering(currentState))
- {
- RectI drawArea = RectI(contentRect.point.x + contentRect.extent.x - contentRect.extent.y, contentRect.point.y, contentRect.extent.y, contentRect.extent.y);
- ColorI color = ColorI(getFontColor(mProfile, currentState));
- renderTriangleIcon(drawArea, color, GuiDirection::Down, 8);
- contentRect.extent.x -= contentRect.extent.y;
- }
+ RectI drawArea = RectI(contentRect.point.x + contentRect.extent.x - contentRect.extent.y, contentRect.point.y, contentRect.extent.y, contentRect.extent.y);
+ ColorI color = ColorI(getFontColor(mProfile, currentState));
+ renderTriangleIcon(drawArea, color, GuiDirection::Down, 8);
+ contentRect.extent.x -= contentRect.extent.y;
//Render the text
S32 index = mListBox->getSelectedItem();
diff --git a/engine/source/gui/containers/guiChainCtrl.cc b/engine/source/gui/containers/guiChainCtrl.cc
index a8ce6a8bf..4ee301a64 100644
--- a/engine/source/gui/containers/guiChainCtrl.cc
+++ b/engine/source/gui/containers/guiChainCtrl.cc
@@ -81,6 +81,15 @@ void GuiChainCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
void GuiChainCtrl::onChildAdded(GuiControl *child)
{
+ //Ensure the child isn't positioned to the center
+ if (child->getHorizSizing() == horizResizeCenter && !mIsVertical)
+ {
+ child->setHorizSizing(horizResizeLeft);
+ }
+ if (child->getVertSizing() == vertResizeCenter && mIsVertical)
+ {
+ child->setVertSizing(vertResizeTop);
+ }
Parent::onChildAdded(child);
calculateExtent();
}
diff --git a/engine/source/gui/containers/guiExpandCtrl.cc b/engine/source/gui/containers/guiExpandCtrl.cc
index 8ea7b7292..8512ac9c3 100644
--- a/engine/source/gui/containers/guiExpandCtrl.cc
+++ b/engine/source/gui/containers/guiExpandCtrl.cc
@@ -116,6 +116,12 @@ void GuiExpandCtrl::parentResized(const Point2I &oldParentExtent, const Point2I
setUpdate();
}
+void GuiExpandCtrl::childResized(GuiControl* child)
+{
+ calcExpandedExtent();
+ Parent::childResized(child);
+}
+
void GuiExpandCtrl::setCollapsedExtent(const Point2I &extent)
{
mCollapsedExtent = extent;
@@ -170,12 +176,27 @@ bool GuiExpandCtrl::processExpansion()
mBounds.extent.x = processValue(progress, mExpandedExtent.x, mCollapsedExtent.x);
mBounds.extent.y = processValue(progress, mExpandedExtent.y, mCollapsedExtent.y);
}
- setUpdate();
- GuiControl *parent = getParent();
+ GuiControl* parent = getParent();
if (parent)
+ {
+ if (mHorizSizing == horizResizeCenter)
+ {
+ mBounds.point.x = (parent->mBounds.extent.x - mBounds.extent.x) / 2;
+ }
+ if (mVertSizing == vertResizeCenter)
+ {
+ mBounds.point.y = (parent->mBounds.extent.y - mBounds.extent.y) / 2;
+ }
+
parent->childResized(this);
+ }
+ setUpdate();
+ if (isMethod("onResize"))
+ {
+ Con::executef(this, 2, "onResize");
+ }
if (mAnimationProgress >= 1.0f)
{
diff --git a/engine/source/gui/containers/guiExpandCtrl.h b/engine/source/gui/containers/guiExpandCtrl.h
index f926c2540..5c5d3efd4 100644
--- a/engine/source/gui/containers/guiExpandCtrl.h
+++ b/engine/source/gui/containers/guiExpandCtrl.h
@@ -60,6 +60,7 @@ class GuiExpandCtrl : public GuiControl, public Fluid
GuiExpandCtrl();
virtual void parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
+ virtual void childResized(GuiControl* child);
inline bool getExpanded() { return mExpanded; };
void setExpanded(bool isExpanded);
diff --git a/engine/source/gui/containers/guiGridCtrl.cc b/engine/source/gui/containers/guiGridCtrl.cc
index af1f215c0..3c278ee85 100644
--- a/engine/source/gui/containers/guiGridCtrl.cc
+++ b/engine/source/gui/containers/guiGridCtrl.cc
@@ -321,6 +321,15 @@ Point2F GuiGridCtrl::GetGridItemHeight(const S32 totalArea, const S32 maxChainLe
void GuiGridCtrl::onChildAdded(GuiControl *child)
{
+ //Ensure the child isn't positioned to the center
+ if (child->getHorizSizing() == horizResizeCenter)
+ {
+ child->setHorizSizing(horizResizeLeft);
+ }
+ if (child->getVertSizing() == vertResizeCenter)
+ {
+ child->setVertSizing(vertResizeTop);
+ }
resize(getPosition(), getExtent());
}
diff --git a/engine/source/gui/containers/guiScrollCtrl.cc b/engine/source/gui/containers/guiScrollCtrl.cc
index 9b2624efb..28dec1d04 100755
--- a/engine/source/gui/containers/guiScrollCtrl.cc
+++ b/engine/source/gui/containers/guiScrollCtrl.cc
@@ -95,8 +95,27 @@ void GuiScrollCtrl::initPersistFields()
void GuiScrollCtrl::resize(const Point2I &newPos, const Point2I &newExt)
{
- Parent::resize(newPos, newExt);
- computeSizes();
+ bool hasH = mHasHScrollBar;
+ bool hasV = mHasVScrollBar;
+ Parent::resize(newPos, newExt);
+ computeSizes();
+
+ if (hasH != mHasHScrollBar || hasV != mHasVScrollBar)
+ {
+ S32 deltaY = hasH != mHasHScrollBar ? (mHasHScrollBar ? mScrollBarThickness : -mScrollBarThickness) : 0;
+ S32 deltaX = hasV != mHasVScrollBar ? (mHasVScrollBar ? mScrollBarThickness : -mScrollBarThickness) : 0;
+
+ iterator i;
+ for (i = begin(); i != end(); i++)
+ {
+ GuiControl* ctrl = static_cast(*i);
+ ctrl->mRenderInsetRB = Point2I(ctrl->mRenderInsetRB.x + deltaX, ctrl->mRenderInsetRB.y + deltaY);
+ ctrl->parentResized(mBounds.extent - (ctrl->mRenderInsetLT + ctrl->mRenderInsetRB), mBounds.extent - (ctrl->mRenderInsetLT + ctrl->mRenderInsetRB));
+ }
+
+ Parent::resize(newPos, newExt);
+ computeSizes();
+ }
}
void GuiScrollCtrl::childResized(GuiControl *child)
diff --git a/engine/source/gui/containers/guiWindowCtrl.cc b/engine/source/gui/containers/guiWindowCtrl.cc
index a866768e8..c2173fb25 100755
--- a/engine/source/gui/containers/guiWindowCtrl.cc
+++ b/engine/source/gui/containers/guiWindowCtrl.cc
@@ -865,6 +865,11 @@ void GuiWindowCtrl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEve
{
Point2I mousePos = lastGuiEvent.mousePoint;
RectI winRect = mBounds;
+ GuiControl* parent = getParent();
+ if (!parent)
+ {
+ return;
+ }
Point2I offset = getParent()->localToGlobalCoord(Point2I(0,0));
RectI rightRect = RectI( ( ( winRect.extent.x + winRect.point.x ) - mResizeRightWidth + offset.x), winRect.point.y + mTitleHeight + offset.y, mResizeRightWidth, winRect.extent.y );
RectI bottomRect = RectI( winRect.point.x + offset.x, ( ( winRect.point.y + winRect.extent.y ) - mResizeBottomHeight) + offset.y, winRect.extent.x , mResizeBottomHeight );
diff --git a/engine/source/gui/guiControl.cc b/engine/source/gui/guiControl.cc
index bedf782c2..2b5faf924 100755
--- a/engine/source/gui/guiControl.cc
+++ b/engine/source/gui/guiControl.cc
@@ -305,10 +305,7 @@ void GuiControl::addObject(SimObject *object)
if(mAwake)
ctrl->awaken();
- // If we are a child, notify our parent that we've been added
- GuiControl *parent = ctrl->getParent();
- if( parent )
- parent->onChildAdded( ctrl );
+ onChildAdded( ctrl );
}
void GuiControl::removeObject(SimObject *object)
@@ -319,16 +316,14 @@ void GuiControl::removeObject(SimObject *object)
AssertWarn(0, "GuiControl::removeObject: attempted to remove NON GuiControl from set");
return;
}
- GuiControl *parent = ctrl->getParent();
- AssertFatal(mAwake == static_cast(object)->isAwake(), "GuiControl::removeObject: child control wake state is bad");
+ AssertFatal(mAwake == ctrl->isAwake(), "GuiControl::removeObject: child control wake state is bad");
if (mAwake)
- static_cast(object)->sleep();
+ ctrl->sleep();
Parent::removeObject(object);
// If we are a child, notify our parent that we've been removed
- if (parent)
- parent->onChildRemoved(ctrl);
+ onChildRemoved(ctrl);
}
GuiControl *GuiControl::getParent()
@@ -416,13 +411,28 @@ void GuiControl::resize(const Point2I &newPosition, const Point2I &newExtent)
Point2I oldExtent = mBounds.extent;
+ //force center if using center positioning
+ Point2I actualNewPosition = Point2I(newPosition);
+ GuiControl* parent = getParent();
+ if (parent)
+ {
+ if (mHorizSizing == horizResizeCenter)
+ {
+ actualNewPosition.x = (parent->mBounds.extent.x - actualNewExtent.x) / 2;
+ }
+ if (mVertSizing == vertResizeCenter)
+ {
+ actualNewPosition.y = (parent->mBounds.extent.y - actualNewExtent.y) / 2;
+ }
+ }
+
// only do the child control resizing stuff if you really need to.
bool extentChanged = (actualNewExtent != oldExtent);
if (extentChanged) {
//call set update both before and after
setUpdate();
- mBounds.set(newPosition, actualNewExtent);
+ mBounds.set(actualNewPosition, actualNewExtent);
iterator i;
for(i = begin(); i != end(); i++)
{
@@ -430,7 +440,6 @@ void GuiControl::resize(const Point2I &newPosition, const Point2I &newExtent)
ctrl->parentResized(oldExtent - (ctrl->mRenderInsetLT + ctrl->mRenderInsetRB), actualNewExtent - (ctrl->mRenderInsetLT + ctrl->mRenderInsetRB));
}
- GuiControl *parent = getParent();
if (parent)
parent->childResized(this);
setUpdate();
@@ -441,7 +450,7 @@ void GuiControl::resize(const Point2I &newPosition, const Point2I &newExtent)
}
}
else {
- mBounds.point = newPosition;
+ mBounds.point = actualNewPosition;
}
}
void GuiControl::setPosition( const Point2I &newPosition )
@@ -552,29 +561,35 @@ Point2I GuiControl::extentBattery(Point2I &newExtent)
}
Point2I result = Point2I(newExtent);
- if (newExtent.x < mBounds.extent.x && newExtent.x < mMinExtent.x)
- {
- mStoredExtent.x += mBounds.extent.x > mMinExtent.x ? (mMinExtent.x - newExtent.x) : (mBounds.extent.x - newExtent.x);
- result.x = mMinExtent.x;
- }
- else if (newExtent.x > mBounds.extent.x && mStoredExtent.x > 0)
- {
- S32 charge = getMin(newExtent.x - mBounds.extent.x, mStoredExtent.x);
- mStoredExtent.x -= charge;
- result.x = newExtent.x - charge;
- }
+ if (mHorizSizing != horizResizeRelative)
+ {
+ if (newExtent.x < mBounds.extent.x && newExtent.x < mMinExtent.x)
+ {
+ mStoredExtent.x += mBounds.extent.x > mMinExtent.x ? (mMinExtent.x - newExtent.x) : (mBounds.extent.x - newExtent.x);
+ result.x = mMinExtent.x;
+ }
+ else if (newExtent.x > mBounds.extent.x && mStoredExtent.x > 0)
+ {
+ S32 charge = getMin(newExtent.x - mBounds.extent.x, mStoredExtent.x);
+ mStoredExtent.x -= charge;
+ result.x = newExtent.x - charge;
+ }
+ }
- if (newExtent.y < mBounds.extent.y && newExtent.y < mMinExtent.y)
- {
- mStoredExtent.y += mBounds.extent.y > mMinExtent.y ? (mMinExtent.y - newExtent.y) : (mBounds.extent.y - newExtent.y);
- result.y = mMinExtent.y;
- }
- else if (newExtent.y > mBounds.extent.y && mStoredExtent.y > 0)
- {
- S32 charge = getMin(newExtent.y - mBounds.extent.y, mStoredExtent.y);
- mStoredExtent.y -= charge;
- result.y = newExtent.y - charge;
- }
+ if (mVertSizing != vertResizeRelative)
+ {
+ if (newExtent.y < mBounds.extent.y && newExtent.y < mMinExtent.y)
+ {
+ mStoredExtent.y += mBounds.extent.y > mMinExtent.y ? (mMinExtent.y - newExtent.y) : (mBounds.extent.y - newExtent.y);
+ result.y = mMinExtent.y;
+ }
+ else if (newExtent.y > mBounds.extent.y && mStoredExtent.y > 0)
+ {
+ S32 charge = getMin(newExtent.y - mBounds.extent.y, mStoredExtent.y);
+ mStoredExtent.y -= charge;
+ result.y = newExtent.y - charge;
+ }
+ }
return result;
}
diff --git a/engine/source/gui/guiControl.h b/engine/source/gui/guiControl.h
index 963dfaa90..e1ff26a8c 100755
--- a/engine/source/gui/guiControl.h
+++ b/engine/source/gui/guiControl.h
@@ -327,6 +327,12 @@ class GuiControl : public SimGroup, public virtual Tickable
inline void setTextExtend(const bool extend) { mTextExtend = extend; }
inline bool getTextExtend() { return mTextExtend; }
+ const horizSizingOptions getHorizSizing() { return static_cast(mHorizSizing); }
+ const vertSizingOptions getVertSizing() { return static_cast(mVertSizing); }
+
+ void setHorizSizing(const horizSizingOptions sizing) { mHorizSizing = sizing; }
+ void setVertSizing(const vertSizingOptions sizing) { mVertSizing = sizing; }
+
// Text Property Accessors
static bool setTextProperty(void* obj, const char* data) { static_cast(obj)->setText(data); return false; }
static const char* getTextProperty(void* obj, const char* data) { return static_cast(obj)->getText(); }
diff --git a/engine/source/gui/guiTypes.h b/engine/source/gui/guiTypes.h
index ed8ce4ba9..1f0d521e7 100755
--- a/engine/source/gui/guiTypes.h
+++ b/engine/source/gui/guiTypes.h
@@ -61,7 +61,7 @@
#include "graphics/gFont.h"
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/math/mRandom.cc b/engine/source/math/mRandom.cc
index 1c779da52..f584ae1b3 100755
--- a/engine/source/math/mRandom.cc
+++ b/engine/source/math/mRandom.cc
@@ -181,4 +181,27 @@ U32 RandomR250::randI( void )
return new_rand >> 1;
}
+RandomPCG::RandomPCG()
+{
+ pcg32_srandom_r(&rng, generateSeed(), generateSeed());
+}
+
+RandomPCG::RandomPCG(const S32 seed)
+{
+ pcg32_srandom_r(&rng, seed, generateSeed());
+}
+
+RandomPCG::RandomPCG(const S32 seed, const S32 stream)
+{
+ pcg32_srandom_r(&rng, seed, stream);
+}
+
+void RandomPCG::setSeed(const S32 seed)
+{
+ pcg32_srandom_r(&rng, seed, generateSeed());
+}
+void RandomPCG::setSeed(const S32 seed, const S32 stream)
+{
+ pcg32_srandom_r(&rng, seed, stream);
+}
\ No newline at end of file
diff --git a/engine/source/math/mRandom.h b/engine/source/math/mRandom.h
index 8704cf9ca..090eb4cd0 100755
--- a/engine/source/math/mRandom.h
+++ b/engine/source/math/mRandom.h
@@ -27,6 +27,8 @@
#include "platform/platform.h"
#endif
+#include "algorithm/pcg_basic.h"
+
//-----------------------------------------------------------------------------
class RandomGeneratorBase
@@ -99,6 +101,36 @@ class RandomR250 : public RandomGeneratorBase
//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// PCG Random Number Generator
+///
+/// Fast and statistically excellent random numbers
+///
+/// Period = 2^64
+///
+/// Copyright 2014 Melissa O'Neill
+///
+/// Licensed under the Apache License, Version 2.0
+//-----------------------------------------------------------------------------
+class RandomPCG : public RandomGeneratorBase
+{
+private:
+ pcg32_random_t rng;
+
+public:
+ RandomPCG();
+ RandomPCG(const S32 seed);
+ RandomPCG(const S32 seed, const S32 stream);
+
+ void setSeed(const S32 seed);
+ void setSeed(const S32 seed, const S32 stream);
+ U32 randI(void) { return static_cast(pcg32_random_r(&rng)); }
+ U32 randI(U32 bound) { return static_cast(pcg32_boundedrand_r(&rng, static_cast(bound))); }
+};
+
+//-----------------------------------------------------------------------------
+
extern RandomLCG gRandGen;
#endif //_MRANDOM_H_
diff --git a/engine/source/math/noise/NoiseGenerator_ScriptBinding.h b/engine/source/math/noise/NoiseGenerator_ScriptBinding.h
index 97fecc96b..a8099ec6f 100644
--- a/engine/source/math/noise/NoiseGenerator_ScriptBinding.h
+++ b/engine/source/math/noise/NoiseGenerator_ScriptBinding.h
@@ -23,7 +23,7 @@
ConsoleMethodGroupBeginWithDocs(NoiseGenerator, ScriptObject)
/*! Sets the seed for the noise generater.
-@param seed An interger seed value.
+@param seed An integer seed value.
@return No return value.
*/
ConsoleMethodWithDocs(NoiseGenerator, setSeed, ConsoleVoid, 3, 3, (int seed))
diff --git a/engine/source/math/noise/RandomNumberGenerator.cc b/engine/source/math/noise/RandomNumberGenerator.cc
new file mode 100644
index 000000000..da3ac1217
--- /dev/null
+++ b/engine/source/math/noise/RandomNumberGenerator.cc
@@ -0,0 +1,72 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _RANDOM_NUMBER_GENERATOR_H_
+#include "RandomNumberGenerator.h"
+#endif
+
+// Script bindings.
+#include "RandomNumberGenerator_ScriptBinding.h"
+
+//------------------------------------------------------------------------------
+
+IMPLEMENT_CONOBJECT(RandomNumberGenerator);
+
+//------------------------------------------------------------------------------
+
+RandomNumberGenerator::RandomNumberGenerator()
+{
+ mRNG = RandomPCG();
+}
+
+//------------------------------------------------------------------------------
+
+RandomNumberGenerator::~RandomNumberGenerator()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void RandomNumberGenerator::setSeed(const U32 seed)
+{
+ mRNG.setSeed(seed);
+}
+
+void RandomNumberGenerator::setSeed(const U32 seed, const U32 stream)
+{
+ mRNG.setSeed(seed, stream);
+}
+
+U32 RandomNumberGenerator::getSeed()
+{
+ return mRNG.getSeed();
+}
+
+U32 RandomNumberGenerator::getRandom()
+{
+ return mRNG.randI();
+}
+
+U32 RandomNumberGenerator::getRandom(const U32 bound)
+{
+ return mRNG.randI(bound);
+}
\ No newline at end of file
diff --git a/engine/source/math/noise/RandomNumberGenerator.h b/engine/source/math/noise/RandomNumberGenerator.h
new file mode 100644
index 000000000..372c689ca
--- /dev/null
+++ b/engine/source/math/noise/RandomNumberGenerator.h
@@ -0,0 +1,65 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _RANDOM_NUMBER_GENERATOR_H_
+#define _RANDOM_NUMBER_GENERATOR_H_
+
+#ifndef _MRANDOM_H_
+#include "math/mRandom.h"
+#endif
+
+#ifndef _SCRIPT_OBJECT_H_
+#include "sim/scriptObject.h"
+#endif
+
+#ifndef _UTILITY_H_
+#include "2d/core/Utility.h"
+#endif
+
+//-----------------------------------------------------------------------------
+
+class RandomNumberGenerator : public ScriptObject
+{
+ typedef ScriptObject Parent;
+
+private:
+ RandomPCG mRNG;
+
+public:
+ RandomNumberGenerator();
+ virtual ~RandomNumberGenerator();
+
+ void setSeed(const U32 seed);
+ void setSeed(const U32 seed, const U32 stream);
+ U32 getSeed();
+ U32 getRandom();
+ U32 getRandom(const U32 bound);
+
+ /// Declare Console Object.
+ DECLARE_CONOBJECT(RandomNumberGenerator);
+
+private:
+
+protected:
+};
+
+#endif // _NOISE_GENERATOR_H_
diff --git a/engine/source/math/noise/RandomNumberGenerator_ScriptBinding.h b/engine/source/math/noise/RandomNumberGenerator_ScriptBinding.h
new file mode 100644
index 000000000..ebc056885
--- /dev/null
+++ b/engine/source/math/noise/RandomNumberGenerator_ScriptBinding.h
@@ -0,0 +1,60 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+ConsoleMethodGroupBeginWithDocs(RandomNumberGenerator, ScriptObject)
+
+/*! Sets the seed and stream for the random number generater. Random values will always be the same for a seed/stream combination.
+@param seed An integer seed value.
+@param stream An optional integer value for the stream. If no stream is set a random stream value will be picked.
+@return No return value.
+*/
+ConsoleMethodWithDocs(RandomNumberGenerator, setSeed, ConsoleVoid, 3, 4, (int seed, [int stream]))
+{
+ if (argc == 3)
+ {
+ object->setSeed(dAtoi(argv[2]));
+ }
+ else if (argc == 4)
+ {
+ object->setSeed(dAtoi(argv[2]), dAtoi(argv[3]));
+ }
+}
+
+//------------------------------------------------------------------------------
+
+/*! Returns a random number integer value between 0 and an optional upper bound.
+* @param bound The optional value that the random number will be less than.
+@return A 32 bit number or a value where 0 <= number < bound.
+*/
+ConsoleMethodWithDocs(RandomNumberGenerator, getRandom, ConsoleFloat, 2, 3, ([int bound]))
+{
+ if (argc == 3)
+ {
+ return object->getRandom(dAtoi(argv[2]));
+ }
+ else
+ {
+ return object->getRandom();
+ }
+}
+
+ConsoleMethodGroupEndWithDocs(RandomNumberGenerator)
\ No newline at end of file
diff --git a/engine/source/module/moduleManager.cc b/engine/source/module/moduleManager.cc
index be0266579..4f91daa97 100755
--- a/engine/source/module/moduleManager.cc
+++ b/engine/source/module/moduleManager.cc
@@ -565,7 +565,7 @@ bool ModuleManager::unloadModuleGroup( const char* pModuleGroup )
if ( mEchoInfo )
{
Con::printf( "Module Manager: Unloading group '%s' but could not unload module Id '%s' at version Id '%d'.",
- moduleGroup, pLoadedEntry->mpModuleDefinition->getModuleId(), pLoadedEntry->mpModuleDefinition->getVersionId() );
+ moduleGroup, pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId() );
}
// Skip.
continue;
diff --git a/engine/source/module/moduleManager.h b/engine/source/module/moduleManager.h
index c54d39a0e..7e5f49f4c 100755
--- a/engine/source/module/moduleManager.h
+++ b/engine/source/module/moduleManager.h
@@ -31,7 +31,7 @@
#include "collection/vector.h"
#endif
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/persistence/taml/binary/tamlBinaryReader.h b/engine/source/persistence/taml/binary/tamlBinaryReader.h
index 25aae0967..efcc4f303 100644
--- a/engine/source/persistence/taml/binary/tamlBinaryReader.h
+++ b/engine/source/persistence/taml/binary/tamlBinaryReader.h
@@ -23,7 +23,7 @@
#ifndef _TAML_BINARYREADER_H_
#define _TAML_BINARYREADER_H_
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
@@ -33,7 +33,7 @@
//-----------------------------------------------------------------------------
-/// @ingroup tamlGroup
+/// @ingroup tamlGroup
/// @see tamlGroup
class TamlBinaryReader
{
diff --git a/engine/source/persistence/taml/json/tamlJSONReader.h b/engine/source/persistence/taml/json/tamlJSONReader.h
index bf201a0d0..3a6e2f5c1 100644
--- a/engine/source/persistence/taml/json/tamlJSONReader.h
+++ b/engine/source/persistence/taml/json/tamlJSONReader.h
@@ -23,7 +23,7 @@
#ifndef _TAML_JSONREADER_H_
#define _TAML_JSONREADER_H_
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
@@ -37,7 +37,7 @@
//-----------------------------------------------------------------------------
-/// @ingroup tamlGroup
+/// @ingroup tamlGroup
/// @see tamlGroup
class TamlJSONReader
{
diff --git a/engine/source/persistence/taml/taml.h b/engine/source/persistence/taml/taml.h
index fc958689e..080fce75a 100755
--- a/engine/source/persistence/taml/taml.h
+++ b/engine/source/persistence/taml/taml.h
@@ -47,7 +47,7 @@
#include "sim/simBase.h"
#endif
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
diff --git a/engine/source/persistence/taml/xml/tamlXmlReader.h b/engine/source/persistence/taml/xml/tamlXmlReader.h
index 168997d31..5412babdc 100644
--- a/engine/source/persistence/taml/xml/tamlXmlReader.h
+++ b/engine/source/persistence/taml/xml/tamlXmlReader.h
@@ -23,7 +23,7 @@
#ifndef _TAML_XMLREADER_H_
#define _TAML_XMLREADER_H_
-#ifndef _HASHTABLE_H
+#ifndef _HASHTABLE_H_
#include "collection/hashTable.h"
#endif
@@ -37,7 +37,7 @@
//-----------------------------------------------------------------------------
-/// @ingroup tamlGroup
+/// @ingroup tamlGroup
/// @see tamlGroup
class TamlXmlReader
{
diff --git a/engine/source/platform/platformFileIO.cc b/engine/source/platform/platformFileIO.cc
index 070dd5336..f56742390 100755
--- a/engine/source/platform/platformFileIO.cc
+++ b/engine/source/platform/platformFileIO.cc
@@ -345,7 +345,7 @@ StringTableEntry Platform::makeRelativePathName(const char *path, const char *to
return StringTable->insert(buffer);
}
- if((*pathPtr == 0 && *toPtr == '/') || (*toPtr == '/' && *pathPtr == 0))
+ if(*toPtr == '/' && *pathPtr == 0)
branch = pathPtr;
// Figure out parent dirs
diff --git a/engine/source/platform/platformString_ScriptBinding.h b/engine/source/platform/platformString_ScriptBinding.h
index 6b73e3d8a..b056811bd 100644
--- a/engine/source/platform/platformString_ScriptBinding.h
+++ b/engine/source/platform/platformString_ScriptBinding.h
@@ -347,7 +347,7 @@ ConsoleFunctionWithDocs( stripTrailingSpaces, ConsoleString, 2, 2, ( string ))
S32 temp = S32(dStrlen( argv[1] ));
if ( temp )
{
- while ( ( argv[1][temp - 1] == ' ' || argv[1][temp - 1] == '_' ) && temp >= 1 )
+ while ( temp >= 1 && ( argv[1][temp - 1] == ' ' || argv[1][temp - 1] == '_' ) )
temp--;
if ( temp )
@@ -362,4 +362,4 @@ ConsoleFunctionWithDocs( stripTrailingSpaces, ConsoleString, 2, 2, ( string ))
return( "" );
}
-/*! @} */ // group StringFunctions
\ No newline at end of file
+/*! @} */ // group StringFunctions
diff --git a/engine/source/platformWin32/winConsole_ScriptBinding.h b/engine/source/platformWin32/winConsole_ScriptBinding.h
index f32c2a024..b3bb7610e 100644
--- a/engine/source/platformWin32/winConsole_ScriptBinding.h
+++ b/engine/source/platformWin32/winConsole_ScriptBinding.h
@@ -42,7 +42,7 @@ ConsoleFunctionWithDocs(enableWinConsole, ConsoleVoid, 2, 2, ( enable ))
ConsoleFunctionWithDocs(getWinNTVersion, ConsoleVoid, 1, 1, ())
{
std::string ver = getWinNTVersion();
- Con::printf("%s", ver);
+ Con::printf("%s", ver.c_str());
}
/*! @} */ // end group WindowsPlatform
diff --git a/engine/source/platformWin32/winDInputDevice.cc b/engine/source/platformWin32/winDInputDevice.cc
index 2e50008a2..dbf46c5f5 100755
--- a/engine/source/platformWin32/winDInputDevice.cc
+++ b/engine/source/platformWin32/winDInputDevice.cc
@@ -991,7 +991,7 @@ bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData )
}
if( clearkeys & POV_down)
{
- newEvent.objInst = ( objInst == 0 ) ? SI_DPOV : SI_DPOV;
+ newEvent.objInst = ( objInst == 0 ) ? SI_DPOV : SI_DPOV2;
Game->postEvent(newEvent);
}
@@ -1022,7 +1022,7 @@ bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData )
}
if( setkeys & POV_down)
{
- newEvent.objInst = ( objInst == 0 ) ? SI_DPOV : SI_DPOV;
+ newEvent.objInst = ( objInst == 0 ) ? SI_DPOV : SI_DPOV2;
Game->postEvent(newEvent);
}
diff --git a/engine/source/platformWin32/winFileio.cc b/engine/source/platformWin32/winFileio.cc
index a1085b139..06243c1f6 100755
--- a/engine/source/platformWin32/winFileio.cc
+++ b/engine/source/platformWin32/winFileio.cc
@@ -981,7 +981,8 @@ bool Platform::hasSubDirectory(const char *pPath)
continue;
Platform::clearExcludedDirectories();
-
+ FindClose(handle);
+
return true;
}
}
@@ -1003,10 +1004,10 @@ static bool recurseDumpDirectories(const char *basePath, const char *subPath, Ve
// Compose our search string - Format : ([path]/[subpath]/*)
//-----------------------------------------------------------------------------
- dsize_t trLen = basePath ? dStrlen(basePath) : 0;
- dsize_t subtrLen = subPath ? dStrlen(subPath) : 0;
- char trail = trLen > 0 ? basePath[trLen - 1] : '\0';
- char subTrail = subtrLen > 0 ? subPath[subtrLen - 1] : '\0';
+ dsize_t trLen = basePath ? dStrlen(basePath) : 0;
+ dsize_t subtrLen = subPath ? dStrlen(subPath) : 0;
+ char trail = trLen > 0 ? basePath[trLen - 1] : '\0';
+ char subTrail = subtrLen > 0 ? subPath[subtrLen - 1] : '\0';
char subLead = subtrLen > 0 ? subPath[0] : '\0';
if (trail == '/')
diff --git a/engine/source/platformWin32/winGLSpecial.cc b/engine/source/platformWin32/winGLSpecial.cc
index a960270ff..ac7cb8ad2 100755
--- a/engine/source/platformWin32/winGLSpecial.cc
+++ b/engine/source/platformWin32/winGLSpecial.cc
@@ -190,28 +190,28 @@ static const char * TypeToString( GLenum t )
// GLU Log Functions
static void APIENTRY loggluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
{
- fprintf(winState.log_fp, "gluOrtho2D( %d, %d, %d, %d )\n", left, right, bottom, top);
+ fprintf(winState.log_fp, "gluOrtho2D( %f, %f, %f, %f )\n", left, right, bottom, top);
fflush(winState.log_fp);
dllgluOrtho2D(left, right, bottom, top);
}
static void APIENTRY loggluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
- fprintf(winState.log_fp, "gluPerspective( %d, %d, %d, %d )\n", fovy, aspect, zNear, zFar);
+ fprintf(winState.log_fp, "gluPerspective( %f, %f, %f, %f )\n", fovy, aspect, zNear, zFar);
fflush(winState.log_fp);
dllgluPerspective(fovy, aspect, zNear, zFar);
}
static void APIENTRY loggluPickMatrix(GLdouble x, GLdouble y, GLdouble width, GLdouble height, GLint viewport[4])
{
- fprintf(winState.log_fp, "gluPickMatrix(%d, %d, %d, %d, VIEW)\n", x, y, width, height);
+ fprintf(winState.log_fp, "gluPickMatrix(%f, %f, %f, %f, VIEW)\n", x, y, width, height);
fflush(winState.log_fp);
dllgluPickMatrix(x, y, width, height, viewport);
}
static void APIENTRY loggluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz)
{
- fprintf(winState.log_fp, "gluLookAt(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n",eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz);
+ fprintf(winState.log_fp, "gluLookAt(%f, %f, %f, %f, %f, %f, %f, %f, %f)\n",eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz);
fflush(winState.log_fp);
dllgluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz);
}
diff --git a/engine/source/platformWin32/winGLSpecial_ScriptBinding.h b/engine/source/platformWin32/winGLSpecial_ScriptBinding.h
index afdd71e90..df9eef11c 100644
--- a/engine/source/platformWin32/winGLSpecial_ScriptBinding.h
+++ b/engine/source/platformWin32/winGLSpecial_ScriptBinding.h
@@ -56,8 +56,6 @@ ConsoleFunctionWithDocs(GLEnableLogging, ConsoleVoid, 2, 2, ( enable ))
time( &aclock );
newtime = localtime( &aclock );
- asctime( newtime );
-
winState.log_fp = fopen( "gl_log.txt", "wt" );
fprintf( winState.log_fp, "%s\n", asctime( newtime ) );
diff --git a/library/AppCore/appCore.cs b/library/AppCore/appCore.cs
index 8d51773bd..10ba9a2a5 100644
--- a/library/AppCore/appCore.cs
+++ b/library/AppCore/appCore.cs
@@ -26,10 +26,12 @@
exec("./scripts/constants.cs");
exec("./scripts/defaultPreferences.cs");
exec("./gui/guiProfiles.cs");
+ %this.createGuiProfiles();
exec("./scripts/canvas.cs");
// Initialize the canvas
- %this.initializeCanvas(%this.Project);
+ %module = ModuleDatabase.findModule("AppCore", 1);
+ %this.initializeCanvas(%module.Project);
// Load other modules
ModuleDatabase.loadGroup("launch");
diff --git a/library/AppCore/gui/guiProfiles.cs b/library/AppCore/gui/guiProfiles.cs
index a78a2a6d5..f7734070a 100644
--- a/library/AppCore/gui/guiProfiles.cs
+++ b/library/AppCore/gui/guiProfiles.cs
@@ -81,7 +81,7 @@
if(isObject(%name))
{
%originalObject = nameToID(%name);
- if(%orginalObject.getClassName() !$= %object.getClassName())
+ if(%originalObject.getClassName() !$= %object.getClassName())
{
warn("Attempted to change the class of the named object " @ %name @ "!");
warn("Original Class: " @ %originalObject.getClassName());
diff --git a/library/BlankGame/gui/images/torqueBG.asset.taml b/library/BlankGame/gui/images/torqueBG.image.taml
similarity index 100%
rename from library/BlankGame/gui/images/torqueBG.asset.taml
rename to library/BlankGame/gui/images/torqueBG.image.taml
diff --git a/library/ScreenFade/gui/background.image.taml b/library/ScreenFade/gui/background.image.taml
new file mode 100644
index 000000000..a48a5858f
--- /dev/null
+++ b/library/ScreenFade/gui/background.image.taml
@@ -0,0 +1,3 @@
+
diff --git a/library/ScreenFade/gui/background.png b/library/ScreenFade/gui/background.png
new file mode 100644
index 000000000..169e6f7c5
Binary files /dev/null and b/library/ScreenFade/gui/background.png differ
diff --git a/library/ScreenFade/module.taml b/library/ScreenFade/module.taml
new file mode 100644
index 000000000..e6a0887e3
--- /dev/null
+++ b/library/ScreenFade/module.taml
@@ -0,0 +1,15 @@
+
+
+
diff --git a/library/ScreenFade/screenFade.cs b/library/ScreenFade/screenFade.cs
new file mode 100644
index 000000000..dbe25d621
--- /dev/null
+++ b/library/ScreenFade/screenFade.cs
@@ -0,0 +1,71 @@
+function ScreenFade::create(%this)
+{
+ exec("./scripts/ScreenFadeBackground.cs");
+
+ %this.background = new GuiSpriteCtrl() {
+ class = "ScreenFadeBackground";
+ profile = "GuiDefaultProfile";
+ HorizSizing = "relative";
+ VertSizing = "relative";
+ Position = "0 0";
+ Image = "ScreenFade:background";
+ FullSize = 1;
+ ConstrainProportions = 0;
+ ImageColor = "255 255 255 0";
+ Owner = %this;
+ };
+}
+
+function ScreenFade::destroy(%this)
+{
+ if(isObject(%this.background))
+ {
+ %this.background.delete();
+ }
+}
+
+//Switches the canvas by fading in to color and back out to the new content. The process takes the given time in milliseconds.
+//Color and time are optional.
+//ScreenFade will post event: onSwapComplete().
+function ScreenFade::swapCanvas(%this, %content, %color, %time)
+{
+ if(%color $= "")
+ {
+ %color = "0 0 0 0";
+ }
+
+ if(%time $= "")
+ {
+ %time = 1400;
+ }
+
+ %base = getWord(%color, 0) SPC getWord(%color, 1) SPC getWord(%color, 2);
+ %this.background.solidColor = %base SPC "255";
+ %this.background.transparentColor = %base SPC "0";
+ %this.background.swapContent = %content;
+ %this.background.swapTime = mRound((%time / 5) * 2);
+ %this.background.startSwap();
+}
+
+//Fades the screen to color and then puts the dialog on top of it.
+//Color and time are optional.
+//When your dialog closes, call %this.post("dialogClose"); to inform ScreenFade where %this is the same object passed to openDialog().
+//ScreenFade will post events: onOpenComplete() and onCloseComplete().
+function ScreenFade::openDialog(%this, %dialog, %color, %time)
+{
+ if(%color $= "")
+ {
+ %color = "0 0 0 230";
+ }
+
+ if(%time $= "")
+ {
+ %time = 300;
+ }
+
+ %this.background.solidColor = %color;
+ %this.background.transparentColor = getWord(%color, 0) SPC getWord(%color, 1) SPC getWord(%color, 2) SPC "0";
+ %this.background.dialog = %dialog;
+ %this.background.dialogTime = %time;
+ %this.background.openDialog();
+}
diff --git a/library/ScreenFade/scripts/ScreenFadeBackground.cs b/library/ScreenFade/scripts/ScreenFadeBackground.cs
new file mode 100644
index 000000000..cd9182168
--- /dev/null
+++ b/library/ScreenFade/scripts/ScreenFadeBackground.cs
@@ -0,0 +1,75 @@
+function ScreenFadeBackground::resetColor(%this)
+{
+ if(getWord(%this.getImageColor(), 3) == 0)
+ {
+ %this.setImageColor(%this.transparentColor);
+ %extent = Canvas.getExtent();
+ %this.setExtent(getWord(%extent, 0), getWord(%extent, 1));
+ }
+}
+
+function ScreenFadeBackground::startSwap(%this)
+{
+ %this.resetColor();
+ Canvas.pushDialog(%this);
+ %this.fadeTo(%this.solidColor, %this.swapTime, "EaseInOut");
+ %this.schedule(%this.swapTime, "doSwap");
+}
+
+function ScreenFadeBackground::doSwap(%this)
+{
+ Canvas.setContent(%this.swapContent);
+ Canvas.pushDialog(%this);
+ %this.schedule(%this.swapTime/2, "fadeSwap");
+}
+
+function ScreenFadeBackground::fadeSwap(%this)
+{
+ %this.fadeTo(%this.transparentColor, %this.swapTime, "EaseInOut");
+ %this.schedule(%this.swapTime, "finishSwap");
+}
+
+function ScreenFadeBackground::finishSwap(%this)
+{
+ Canvas.popDialog(%this);
+ %this.Owner.postEvent("SwapComplete");
+}
+
+function ScreenFadeBackground::openDialog(%this)
+{
+ %this.resetColor();
+ %this.add(%this.dialog);
+ Canvas.pushDialog(%this);
+ %this.fadeTo(%this.solidColor, %this.dialogTime, "EaseInOut");
+ %this.schedule(%this.dialogTime, "openDialogComplete");
+}
+
+function ScreenFadeBackground::openDialogComplete(%this)
+{
+ %this.Owner.postEvent("OpenComplete");
+ %this.startListening(%this.dialog);
+}
+
+function ScreenFadeBackground::onDialogClose(%this)
+{
+ if(%this.isAwake())
+ {
+ if(isEventPending(%this.hideSchedule))
+ {
+ cancel(%this.hideSchedule);
+ }
+ %this.fadeTo(%this.transparentColor, %this.dialogTime, "EaseIn");
+ %this.hideSchedule = %this.schedule(%this.dialogTime, "onCloseComplete");
+ }
+}
+
+function ScreenFadeBackground::onCloseComplete(%this)
+{
+ if(isObject(%this.dialog))
+ {
+ %this.stopListening(%this.dialog);
+ %this.removeIfMember(%this.dialog);
+ }
+ Canvas.popDialog(%this);
+ %this.Owner.postEvent("CloseComplete");
+}