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"); +}